-
-
Notifications
You must be signed in to change notification settings - Fork 11
feat: backend/sglang #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds SGLang as a first-class backend/provider: new profile ( Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant C as Client
participant GW as Olla API Gateway
participant RH as Routes/Handlers
participant CV as Model Converter
participant SG as SGLang Server
Note over C,GW: List models via OpenAI-compatible endpoint
C->>GW: GET /v1/models (X-Olla-Backend-Type: sglang)
GW->>RH: genericProviderModelsHandler(sglang, openai)
RH->>SG: GET /v1/models (SGLang)
SG-->>RH: SGLang model list (JSON)
RH->>CV: Convert SGLang->OpenAI model list
CV-->>RH: OpenAI-compatible models
RH-->>C: 200 OK, models (X-Olla-Backend-Type: sglang)
rect rgba(230,245,255,0.6)
Note right of CV: New/changed: SGLang converter — owner/parent/vision/radix/spec-decoding fields
end
sequenceDiagram
autonumber
participant D as Discovery Job
participant SG as SGLang Server
participant PR as SGLang Parser
participant REG as Model Registry
Note over D,REG: Periodic backend discovery
D->>SG: GET /v1/models
SG-->>D: SGLangResponse
D->>PR: Parse SGLangResponse
PR-->>D: []*ModelInfo (type=sglang, details)
D->>REG: Upsert models
REG-->>D: Ack
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/mkdocs.yml (1)
153-178: MkDocs nav still misses the new SGLang docs.
mkdocs --strictis failing because the navigation entries point tointegrations/backend/sglang.mdandapi-reference/sglang.md, but those files aren’t present in the repo. Please add the missing documents (or fix the paths) so the nav links resolve.Based on the pipeline logs
🧹 Nitpick comments (6)
config/profiles/README.md (1)
22-23: Minor wording nit.If you update
openai.yaml’s blurb again later, consider mirroring the other descriptions (“OpenAI-compatible API (generic profile)”) to keep the list uniform.internal/adapter/converter/factory_test.go (1)
55-68: Tighten the assertions for SGLang supportSince the factory now emits a sixth converter, let’s assert on it directly to avoid silent regressions. Please extend the “GetConverter returns correct converters” table (and optionally the unsupported-format error assertions) to cover
"sglang"explicitly. That gives us deterministic coverage that this new backend stays wired in.internal/adapter/converter/sglang_converter.go (4)
52-69: Make "created" deterministic and source from model when possible.Using time.Now() at conversion time makes outputs non-deterministic and can drift from the model’s actual creation/ingest time. Prefer
LastSeenor a metadata-provided timestamp, falling back to now as a last resort.Apply this diff:
- now := time.Now().Unix() + created := model.LastSeen.Unix() + if created == 0 { + if v := c.extractMetadataInt64(model.Metadata, "created"); v > 0 { + created = v + } else { + created = time.Now().Unix() + } + } @@ sglangModel := &profile.SGLangModel{ ID: modelID, Object: "model", - Created: now, + Created: created, OwnedBy: c.determineOwner(modelID), Root: modelID, // SGLang typically sets root to the model ID }
71-74: Fallback max context length from metadata if domain field is empty.Some sources may only provide
max_model_lenin metadata; add a fallback.// Set max context length if available if model.MaxContextLength != nil && *model.MaxContextLength > 0 { sglangModel.MaxModelLen = model.MaxContextLength } + if sglangModel.MaxModelLen == nil { + if max := c.extractMetadataInt64(model.Metadata, "max_model_len"); max > 0 { + sglangModel.MaxModelLen = &max + } + }
106-114: Support common "parent" key as well as "parent_model".Improves compatibility with varied metadata sources.
func (c *SGLangConverter) getParentModel(model *domain.UnifiedModel) string { // Check metadata first if parentModel := c.ExtractMetadataString(model.Metadata, "parent_model"); parentModel != "" { return parentModel } + if parentModel := c.ExtractMetadataString(model.Metadata, "parent"); parentModel != "" { + return parentModel + } return "" }
140-152: Harden metadata int parsing (strings).Metadata often carries numbers as strings; parse them too.
func (c *SGLangConverter) extractMetadataInt64(metadata map[string]interface{}, key string) int64 { if val, ok := metadata[key].(int64); ok { return val } if val, ok := metadata[key].(int); ok { return int64(val) } if val, ok := metadata[key].(float64); ok { return int64(val) } + if val, ok := metadata[key].(string); ok { + if i, err := strconv.ParseInt(val, 10, 64); err == nil { + return i + } + if f, err := strconv.ParseFloat(val, 64); err == nil { + return int64(f) + } + } return 0 }Add the import:
import ( + "strconv" "strings" "time"
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
config/profiles/README.md(1 hunks)config/profiles/sglang.yaml(1 hunks)config/profiles/vllm.yaml(1 hunks)docs/content/api-reference/overview.md(2 hunks)docs/content/index.md(3 hunks)docs/content/integrations/backend/sglang.md(1 hunks)docs/content/integrations/overview.md(1 hunks)docs/mkdocs.yml(2 hunks)internal/adapter/converter/factory.go(1 hunks)internal/adapter/converter/factory_test.go(2 hunks)internal/adapter/converter/sglang_converter.go(1 hunks)internal/adapter/converter/sglang_converter_test.go(1 hunks)internal/adapter/registry/profile/parsers.go(1 hunks)internal/adapter/registry/profile/sglang.go(1 hunks)internal/adapter/registry/profile/sglang_parser.go(1 hunks)internal/app/handlers/handler_common.go(1 hunks)internal/app/handlers/server_routes.go(1 hunks)internal/core/constants/providers.go(1 hunks)internal/core/domain/profile.go(1 hunks)internal/version/version.go(1 hunks)readme.md(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
config/profiles/{ollama,lmstudio,litellm,openai,vllm}.yaml
📄 CodeRabbit inference engine (CLAUDE.md)
Provider-specific profiles must reside under
config/profiles/with the specified filenames
Files:
config/profiles/vllm.yaml
internal/app/handlers/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Set response headers on proxy responses:
X-Olla-Endpoint,X-Olla-Model,X-Olla-Backend-Type,X-Olla-Request-ID,X-Olla-Response-Time
Files:
internal/app/handlers/server_routes.gointernal/app/handlers/handler_common.go
{internal,pkg}/**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
Include Go benchmarks (Benchmark* functions) for critical paths, proxy engine comparisons, pooling efficiency, and circuit breaker behaviour
Files:
internal/adapter/converter/factory_test.gointernal/adapter/converter/sglang_converter_test.go
🧠 Learnings (3)
📚 Learning: 2025-09-23T08:30:20.348Z
Learnt from: CR
PR: thushan/olla#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-23T08:30:20.348Z
Learning: Applies to internal/app/handlers/*.go : Set response headers on proxy responses: `X-Olla-Endpoint`, `X-Olla-Model`, `X-Olla-Backend-Type`, `X-Olla-Request-ID`, `X-Olla-Response-Time`
Applied to files:
docs/content/api-reference/overview.mddocs/content/index.md
📚 Learning: 2025-09-23T08:30:20.348Z
Learnt from: CR
PR: thushan/olla#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-23T08:30:20.348Z
Learning: Applies to internal/adapter/proxy/**/service.go : Proxy services must include response headers: `X-Olla-Endpoint`, `X-Olla-Model`, `X-Olla-Backend-Type`, `X-Olla-Request-ID`, `X-Olla-Response-Time`
Applied to files:
docs/content/api-reference/overview.mddocs/content/index.md
📚 Learning: 2025-09-23T08:30:20.348Z
Learnt from: CR
PR: thushan/olla#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-23T08:30:20.348Z
Learning: Applies to config/profiles/{ollama,lmstudio,litellm,openai,vllm}.yaml : Provider-specific profiles must reside under `config/profiles/` with the specified filenames
Applied to files:
config/profiles/README.md
🧬 Code graph analysis (7)
internal/app/handlers/server_routes.go (1)
internal/core/constants/providers.go (2)
ProviderTypeSGLang(8-8)ProviderTypeOpenAI(6-6)
internal/adapter/registry/profile/sglang_parser.go (2)
internal/core/domain/model.go (2)
ModelInfo(26-33)ModelDetails(11-24)internal/adapter/registry/profile/sglang.go (1)
SGLangResponse(4-7)
internal/adapter/converter/sglang_converter_test.go (6)
internal/adapter/converter/sglang_converter.go (2)
NewSGLangConverter(23-27)SGLangConverter(18-20)internal/core/constants/providers.go (1)
ProviderTypeSGLang(8-8)internal/core/domain/unified_model.go (3)
UnifiedModel(15-31)AliasEntry(9-12)SourceEndpoint(34-44)internal/core/ports/model_converter.go (1)
ModelFilters(18-23)internal/adapter/registry/profile/sglang.go (1)
SGLangResponse(4-7)internal/adapter/converter/base_converter.go (2)
BaseConverter(8-10)NewBaseConverter(13-17)
internal/app/handlers/handler_common.go (1)
internal/core/constants/providers.go (1)
ProviderTypeSGLang(8-8)
internal/adapter/converter/factory.go (1)
internal/adapter/converter/sglang_converter.go (1)
NewSGLangConverter(23-27)
internal/adapter/converter/sglang_converter.go (5)
internal/adapter/registry/profile/sglang.go (2)
SGLangResponse(4-7)SGLangModel(10-26)internal/adapter/converter/base_converter.go (2)
BaseConverter(8-10)NewBaseConverter(13-17)internal/core/ports/model_converter.go (2)
ModelResponseConverter(10-15)ModelFilters(18-23)internal/core/constants/providers.go (1)
ProviderTypeSGLang(8-8)internal/core/domain/unified_model.go (1)
UnifiedModel(15-31)
internal/adapter/registry/profile/parsers.go (1)
internal/core/constants/providers.go (1)
ProviderTypeSGLang(8-8)
🪛 GitHub Actions: Deploy Documentation
docs/content/api-reference/overview.md
[error] 1-1: mkdocs build --clean --strict failed. Process exited with code 1 due to strict mode warnings.
[warning] 1-1: Doc file 'api-reference/overview.md' contains a link 'sglang.md', but the target 'api-reference/sglang.md' is not found among documentation files.
docs/content/integrations/overview.md
[error] 1-1: mkdocs build --clean --strict failed. Process exited with code 1 due to strict mode warnings.
docs/content/index.md
[error] 1-1: mkdocs build --clean --strict failed. Process exited with code 1 due to strict mode warnings.
docs/mkdocs.yml
[error] 1-1: mkdocs build --clean --strict failed. Process exited with code 1 due to strict mode warnings.
docs/content/integrations/backend/sglang.md
[error] 1-1: mkdocs build --clean --strict failed. Process exited with code 1 due to strict mode warnings.
🪛 markdownlint-cli2 (0.18.1)
docs/content/integrations/backend/sglang.md
754-754: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
🔇 Additional comments (16)
internal/adapter/registry/profile/parsers.go (1)
25-26: SGLang parser wiring looks solid.Nice work adding the SGLang case into the parser switch — this keeps provider selection consistent with the other backends.
config/profiles/README.md (1)
21-22: README aligns with the new profile.Listing
sglang.yamlalongside the other built-ins keeps the documentation accurate.readme.md (1)
11-81: Table update is clear and accurate.The badges and supported-backend table now reflect SGLang without breaking the existing layout. Nice refresh.
config/profiles/sglang.yaml (1)
1-244: Profile structure matches the existing schema.The routing, detection, resource, and metrics sections line up with the other provider profiles, so this should load cleanly through the factory.
config/profiles/vllm.yaml (1)
3-3: Home URL addition looks good.Adding the upstream link keeps the profile metadata consistent with SGLang.
internal/app/handlers/handler_common.go (1)
82-87: Static provider list updated correctly.Including
sglanghere keepsisProviderSupportedin sync with the newly registered routes.internal/adapter/converter/factory.go (1)
25-25: Factory registration looks goodNice work wiring the SGLang converter straight into the factory; this keeps the supported formats list authoritative without extra branching.
internal/core/domain/profile.go (1)
6-6: Profile constant alignedAdding
ProfileSGLangalongside the existing profiles keeps the domain layer consistent with the new backend. Nothing further needed here.internal/version/version.go (1)
33-36: Version info updated correctlyIncluding
sglanginSupportedBackendsmakes the version banner accurately advertise the new capability. All good.internal/app/handlers/server_routes.go (1)
214-218: Static routing is consistentThe static provider map now covers SGLang with the expected OpenAI-compatible models endpoint plus proxy path, mirroring the other backends. Looks sound.
internal/core/constants/providers.go (1)
8-16: Constants syncedProvider type/display additions for SGLang line up with the broader integration work. No concerns.
docs/content/index.md (2)
16-18: Docs badge & copy refreshedGood to see SGLang represented alongside the other native backends; the copy stays accurate and consistent.
98-99: Header table remains accurateAppending
sglangto the backend-type header keeps the docs truthful after the new integration. Looks great.internal/adapter/registry/profile/sglang.go (2)
3-7: LGTM: response envelope mirrors OpenAI /v1/models.
object+datashape looks right for downstream consumers.
9-26: Model shape looks solid; optional metadata via pointers is a good call.Fields and JSON tags align with OpenAI-style models while allowing SGLang extras to be omitted cleanly.
internal/adapter/converter/sglang_converter.go (1)
33-48: Response envelope looks correct.
object: "list"with a flatdataarray is consistent with OpenAI-style listings.
| * [Ollama](./backend/ollama.md) - native support for [Ollama](https://github.com/ollama/ollama), including model unification. | ||
| * [LM Studio](./backend/lmstudio.md) - native support for [LM Studio](https://lmstudio.ai/), including model unification. | ||
| * [vLLM](./backend/vllm.md) - native support for [vLLM](https://github.com/vllm-project/vllm), including model unification. | ||
| * [SGLang](./backend/sglang.md) - native support for [SGLang](https://github.com/sgl-project/sglang) with RadixAttention and Frontend Language, including model unification and vision support. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broken link to the new SGLang backend doc
MkDocs strict mode fails when a referenced page is missing. The freshly added [SGLang](./backend/sglang.md) link resolves to 404 because docs/content/integrations/backend/sglang.md isn’t present (or is misnamed), triggering the pipeline error you’re seeing. Please add the page—or fix the path/name—so the link builds cleanly.
🤖 Prompt for AI Agents
In docs/content/integrations/overview.md at line 18 the link
[SGLang](./backend/sglang.md) points to a missing or misnamed page causing
MkDocs strict mode to fail; either add the missing file at
docs/content/integrations/backend/sglang.md with the expected frontmatter and
content, or update the link to the correct existing path/filename (watch for
case sensitivity and the exact directory name), then verify with a local mkdocs
build to ensure the link resolves.
| // findSGLangNativeName looks for the native SGLang name from aliases | ||
| func (c *SGLangConverter) findSGLangNativeName(model *domain.UnifiedModel) string { | ||
| // Use base converter to find SGLang-specific alias | ||
| alias, found := c.BaseConverter.FindProviderAlias(model) | ||
| if found { | ||
| return alias | ||
| } | ||
| return "" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Confirm BaseConverter helpers exist and are wired.
FindProviderAlias must be implemented on BaseConverter for this to compile and to constrain to the SGLang provider. Likewise for ExtractMetadataString/Bool and HasCapability.
Run:
🏁 Script executed:
#!/bin/bash
# Verify BaseConverter helper methods used by SGLangConverter exist.
rg -nP -C2 'func\s+\(\s*\*?BaseConverter\s*\)\s+FindProviderAlias\s*\('
rg -nP -C2 'func\s+\(\s*\*?BaseConverter\s*\)\s+ExtractMetadata(String|Bool)\s*\('
rg -nP -C2 'func\s+\(\s*\*?BaseConverter\s*\)\s+HasCapability\s*\('
# Also ensure filterModels is defined in the converter package.
rg -nP -C2 'func\s+filterModels\s*\(' --type goLength of output: 541
Implement missing BaseConverter helper methods
BaseConverter currently lacks the methods used by SGLangConverter:
- FindProviderAlias(model *domain.UnifiedModel) (string, bool)
- ExtractMetadataString/Bool
- HasCapability
Define these in internal/adapter/converter/unified_converter.go so SGLangConverter compiles and behaves as expected.
🤖 Prompt for AI Agents
In internal/adapter/converter/unified_converter.go (add near the BaseConverter
type definition), implement the missing helper methods used by SGLangConverter:
define FindProviderAlias(model *domain.UnifiedModel) (string, bool) to search
the model for provider-specific aliases and return the matching alias plus a
found flag; add ExtractMetadataString(model *domain.UnifiedModel, key string)
(string, bool) and ExtractMetadataBool(model *domain.UnifiedModel, key string)
(bool, bool) to safely read typed values from the model.Metadata map (returning
value and present flag); and add HasCapability(model *domain.UnifiedModel,
capability string) bool to check the model’s capabilities list/set. Each method
should handle nil maps/slices safely and avoid panics so SGLangConverter
compiles and behaves as expected.
| import ( | ||
| "fmt" | ||
| "time" | ||
|
|
||
| "github.com/thushan/olla/internal/core/domain" | ||
| ) | ||
|
|
||
| type sglangParser struct{} | ||
|
|
||
| func (p *sglangParser) Parse(data []byte) ([]*domain.ModelInfo, error) { | ||
| if len(data) == 0 { | ||
| return make([]*domain.ModelInfo, 0), nil | ||
| } | ||
|
|
||
| var response SGLangResponse | ||
| if err := json.Unmarshal(data, &response); err != nil { | ||
| return nil, fmt.Errorf("failed to parse SGLang response: %w", err) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the missing encoding/json import.
Line 18 calls json.Unmarshal, but encoding/json isn’t imported, so this file will fail to compile. Please add the import.
import (
+ "encoding/json"
"fmt"
"time"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import ( | |
| "fmt" | |
| "time" | |
| "github.com/thushan/olla/internal/core/domain" | |
| ) | |
| type sglangParser struct{} | |
| func (p *sglangParser) Parse(data []byte) ([]*domain.ModelInfo, error) { | |
| if len(data) == 0 { | |
| return make([]*domain.ModelInfo, 0), nil | |
| } | |
| var response SGLangResponse | |
| if err := json.Unmarshal(data, &response); err != nil { | |
| return nil, fmt.Errorf("failed to parse SGLang response: %w", err) | |
| } | |
| import ( | |
| "encoding/json" | |
| "fmt" | |
| "time" | |
| "github.com/thushan/olla/internal/core/domain" | |
| ) | |
| type sglangParser struct{} | |
| func (p *sglangParser) Parse(data []byte) ([]*domain.ModelInfo, error) { | |
| if len(data) == 0 { | |
| return make([]*domain.ModelInfo, 0), nil | |
| } | |
| var response SGLangResponse | |
| if err := json.Unmarshal(data, &response); err != nil { | |
| return nil, fmt.Errorf("failed to parse SGLang response: %w", err) | |
| } |
🤖 Prompt for AI Agents
internal/adapter/registry/profile/sglang_parser.go lines 3-20: the code calls
json.Unmarshal but encoding/json is not imported; add the import "encoding/json"
to the import block (alongside fmt and time) so the json package is available
and the file compiles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
internal/adapter/converter/sglang_converter_test.go(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{internal,pkg}/**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
Include Go benchmarks (Benchmark* functions) for critical paths, proxy engine comparisons, pooling efficiency, and circuit breaker behaviour
Files:
internal/adapter/converter/sglang_converter_test.go
🧠 Learnings (1)
📚 Learning: 2025-09-23T08:30:20.348Z
Learnt from: CR
PR: thushan/olla#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-23T08:30:20.348Z
Learning: Applies to {internal,pkg}/**/*_test.go : Include Go benchmarks (Benchmark* functions) for critical paths, proxy engine comparisons, pooling efficiency, and circuit breaker behaviour
Applied to files:
internal/adapter/converter/sglang_converter_test.go
🧬 Code graph analysis (1)
internal/adapter/converter/sglang_converter_test.go (6)
internal/adapter/converter/sglang_converter.go (2)
NewSGLangConverter(23-27)SGLangConverter(18-20)internal/core/constants/providers.go (1)
ProviderTypeSGLang(8-8)internal/core/domain/unified_model.go (3)
UnifiedModel(15-31)AliasEntry(9-12)SourceEndpoint(34-44)internal/core/ports/model_converter.go (1)
ModelFilters(18-23)internal/adapter/registry/profile/sglang.go (1)
SGLangResponse(4-7)internal/adapter/converter/base_converter.go (2)
BaseConverter(8-10)NewBaseConverter(13-17)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Cross-Platform Build Validation (windows-latest)
| converter := NewSGLangConverter() | ||
|
|
||
| // Create a large number of models to test performance | ||
| models := make([]*domain.UnifiedModel, 1000) | ||
| for i := 0; i < 1000; i++ { | ||
| models[i] = &domain.UnifiedModel{ | ||
| ID: "performance-test-model-" + string(rune(i)), | ||
| MaxContextLength: func() *int64 { v := int64(8192); return &v }(), | ||
| Aliases: []domain.AliasEntry{ | ||
| {Name: "performance-test-model-" + string(rune(i)), Source: constants.ProviderTypeSGLang}, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| // Report memory allocations | ||
| b.ReportAllocs() | ||
| b.ResetTimer() | ||
|
|
||
| for i := 0; i < b.N; i++ { | ||
| result, err := converter.ConvertToFormat(models, ports.ModelFilters{}) | ||
| if err != nil { | ||
| b.Fatalf("ConvertToFormat failed: %v", err) | ||
| } | ||
|
|
||
| response, ok := result.(profile.SGLangResponse) | ||
| if !ok { | ||
| b.Fatal("Result is not SGLangResponse") | ||
| } | ||
|
|
||
| if len(response.Data) != 1000 { | ||
| b.Fatalf("Expected 1000 models, got %d", len(response.Data)) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace rune casting with decimal suffix in benchmark data
Using string(rune(i)) injects control characters for the first entries (e.g. \x00) and non-ASCII glyphs afterwards, so the benchmark feeds malformed/opaque IDs and aliases into the converter. That makes any downstream JSON expectations brittle and hides regressions. Let’s stringify the loop index properly before concatenation.
Apply this diff to fix the issue:
@@
-import (
- "testing"
+import (
+ "strconv"
+ "testing"
@@
- for i := 0; i < 1000; i++ {
- models[i] = &domain.UnifiedModel{
- ID: "performance-test-model-" + string(rune(i)),
+ for i := 0; i < 1000; i++ {
+ suffix := strconv.Itoa(i)
+ models[i] = &domain.UnifiedModel{
+ ID: "performance-test-model-" + suffix,
@@
- Aliases: []domain.AliasEntry{
- {Name: "performance-test-model-" + string(rune(i)), Source: constants.ProviderTypeSGLang},
- },
+ Aliases: []domain.AliasEntry{
+ {Name: "performance-test-model-" + suffix, Source: constants.ProviderTypeSGLang},
+ },🤖 Prompt for AI Agents
internal/adapter/converter/sglang_converter_test.go around lines 333 to 365: the
benchmark builds model IDs and alias names using string(rune(i)) which yields
control/non-ASCII characters; replace that with a decimal string conversion
(e.g., strconv.Itoa(i) or fmt.Sprintf("%d", i)) when concatenating the loop
index so IDs and aliases are valid ASCII decimal strings; update imports to
include strconv (or fmt) as needed and run tests to verify behavior.
This PR implements the SGLang backend.
Summary by CodeRabbit
New Features
Documentation