-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
fix(cliproxy): keep original model ids routable with aliases #4125
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
base: dev
Are you sure you want to change the base?
Changes from 3 commits
8b42bc3
adc389d
28f8f0a
a2a2cb2
e9df43e
cc21639
5afc7ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2479,12 +2479,15 @@ func buildOpenAICompatibilityConfigModels(compat *config.OpenAICompatibility) [] | |
| return nil | ||
| } | ||
| now := time.Now().Unix() | ||
| models := make([]*ModelInfo, 0, len(compat.Models)) | ||
| models := make([]*ModelInfo, 0, len(compat.Models)*2) | ||
| seen := make(map[string]struct{}, len(compat.Models)*2) | ||
| for i := range compat.Models { | ||
| model := compat.Models[i] | ||
| modelID := strings.TrimSpace(model.Alias) | ||
| alias := strings.TrimSpace(model.Alias) | ||
| name := strings.TrimSpace(model.Name) | ||
| modelID := alias | ||
| if modelID == "" { | ||
| modelID = strings.TrimSpace(model.Name) | ||
| modelID = name | ||
| } | ||
| if modelID == "" { | ||
| continue | ||
|
|
@@ -2497,7 +2500,7 @@ func buildOpenAICompatibilityConfigModels(compat *config.OpenAICompatibility) [] | |
| if thinking == nil && !model.Image { | ||
| thinking = ®istry.ThinkingSupport{Levels: []string{"low", "medium", "high"}} | ||
| } | ||
| models = append(models, &ModelInfo{ | ||
| info := &ModelInfo{ | ||
| ID: modelID, | ||
| Object: "model", | ||
| Created: now, | ||
|
|
@@ -2506,18 +2509,48 @@ func buildOpenAICompatibilityConfigModels(compat *config.OpenAICompatibility) [] | |
| DisplayName: modelID, | ||
| UserDefined: false, | ||
| Thinking: thinking, | ||
| }) | ||
| } | ||
| models = appendModelInfoIfUnique(models, info, seen) | ||
| if alias != "" && name != "" && alias != name { | ||
| models = appendModelInfoIfUnique(models, &ModelInfo{ | ||
| ID: name, | ||
| Object: "model", | ||
| Created: now, | ||
| OwnedBy: compat.Name, | ||
| Type: modelType, | ||
| DisplayName: name, | ||
| UserDefined: false, | ||
| Thinking: thinking, | ||
| }, seen) | ||
| } | ||
| } | ||
| return models | ||
| } | ||
|
|
||
| func appendModelInfoIfUnique(models []*ModelInfo, info *ModelInfo, seen map[string]struct{}) []*ModelInfo { | ||
| if info == nil { | ||
| return models | ||
| } | ||
| modelID := strings.TrimSpace(info.ID) | ||
| if modelID == "" { | ||
| return models | ||
| } | ||
| key := modelID | ||
| if _, exists := seen[key]; exists { | ||
| return models | ||
| } | ||
| seen[key] = struct{}{} | ||
| info.ID = modelID | ||
| return append(models, info) | ||
| } | ||
|
|
||
| func buildConfigModels[T modelEntry](models []T, ownedBy, modelType string) []*ModelInfo { | ||
| if len(models) == 0 { | ||
| return nil | ||
| } | ||
| now := time.Now().Unix() | ||
| out := make([]*ModelInfo, 0, len(models)) | ||
| seen := make(map[string]struct{}, len(models)) | ||
| out := make([]*ModelInfo, 0, len(models)*2) | ||
| seen := make(map[string]struct{}, len(models)*2) | ||
| for i := range models { | ||
| model := models[i] | ||
| name := strings.TrimSpace(model.GetName()) | ||
|
|
@@ -2528,11 +2561,6 @@ func buildConfigModels[T modelEntry](models []T, ownedBy, modelType string) []*M | |
| if alias == "" { | ||
| continue | ||
| } | ||
| key := strings.ToLower(alias) | ||
| if _, exists := seen[key]; exists { | ||
| continue | ||
| } | ||
| seen[key] = struct{}{} | ||
| display := name | ||
| if display == "" { | ||
| display = alias | ||
|
|
@@ -2551,7 +2579,22 @@ func buildConfigModels[T modelEntry](models []T, ownedBy, modelType string) []*M | |
| info.Thinking = upstream.Thinking | ||
| } | ||
| } | ||
| out = append(out, info) | ||
| out = appendModelInfoIfUnique(out, info, seen) | ||
| if name != "" && alias != name { | ||
| nameInfo := &ModelInfo{ | ||
| ID: name, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an API-key config uses an alias and excludes that alias (the only registered ID before this change), Useful? React with 👍 / 👎. |
||
| Object: "model", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When one API-key config aliases a built-in model while another credential for the same provider registers the normal catalog, this new original-ID entry can be the last Useful? React with 👍 / 👎. |
||
| Created: now, | ||
| OwnedBy: ownedBy, | ||
| Type: modelType, | ||
| DisplayName: name, | ||
| UserDefined: true, | ||
| } | ||
| if upstream := registry.LookupStaticModelInfo(name); upstream != nil && upstream.Thinking != nil { | ||
| nameInfo.Thinking = upstream.Thinking | ||
| } | ||
| out = appendModelInfoIfUnique(out, nameInfo, seen) | ||
| } | ||
| } | ||
| return out | ||
| } | ||
|
|
||
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.
When a config contains two aliases that differ only by case, this helper now registers both spellings as separate model IDs because the de-dupe key is the exact ID. The execution path still resolves API-key aliases case-insensitively and keeps the first mapping in
compileAPIKeyModelAliasForModels(OpenAI-compatible pooling also matches aliases withEqualFold), so a request for the second advertised alias selects this credential but is sent to the first alias's upstream model. Please keep folded de-dupe for configured aliases and apply case-sensitive uniqueness only when adding the extra original upstream ID.Useful? React with 👍 / 👎.