mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-24 16:41:30 +02:00
[proxy] Keep slash-bearing model ids in the discovery filter
The filter treated a slash in a listing entry's id as a gateway provider prefix and matched only the tail. Self-hosted backends serve ids that carry a slash of their own, so every "Qwen/Qwen2.5-0.5B-Instruct" style model was dropped from the picker even when the policy named it exactly. Try the id as written first and fall back to the tail, so both a prefixed id and a self-hosted one resolve.
This commit is contained in:
@@ -109,7 +109,7 @@ func filterListingBody(body []byte, permitted map[string]struct{}) ([]byte, bool
|
||||
|
||||
kept := make([]map[string]json.RawMessage, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if _, ok := permitted[entryModelID(entry)]; ok {
|
||||
if entryPermitted(entry, permitted) {
|
||||
kept = append(kept, entry)
|
||||
}
|
||||
}
|
||||
@@ -126,23 +126,40 @@ func filterListingBody(body []byte, permitted map[string]struct{}) ([]byte, bool
|
||||
return out, true
|
||||
}
|
||||
|
||||
// entryModelID returns the entry's model id in the form the policy stores
|
||||
// it, or "" when the entry carries no usable id. A provider-prefixed id
|
||||
// ("bedrock/anthropic.claude-sonnet-5") keeps only its last segment, which
|
||||
// is what the operator registers.
|
||||
func entryModelID(entry map[string]json.RawMessage) string {
|
||||
// entryPermitted reports whether a listing entry names a model the policy
|
||||
// authorises, trying every form the same model is written in.
|
||||
func entryPermitted(entry map[string]json.RawMessage, permitted map[string]struct{}) bool {
|
||||
raw, ok := entry["id"]
|
||||
if !ok {
|
||||
return ""
|
||||
return false
|
||||
}
|
||||
var id string
|
||||
if err := json.Unmarshal(raw, &id); err != nil {
|
||||
return ""
|
||||
return false
|
||||
}
|
||||
for _, candidate := range modelIDForms(id) {
|
||||
if _, ok := permitted[candidate]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// modelIDForms returns the forms a single model id may be written in: the id
|
||||
// itself, its undated form, and the same two with a gateway's provider
|
||||
// prefix removed ("vertex_ai/claude-sonnet-5"). The bare id is tried first,
|
||||
// because a self-hosted id can legitimately contain a slash of its own
|
||||
// ("Qwen/Qwen2.5-0.5B-Instruct") and must not be cut down to its tail.
|
||||
func modelIDForms(id string) []string {
|
||||
if id == "" {
|
||||
return nil
|
||||
}
|
||||
forms := []string{id, sharedllm.NormalizeAnthropicModel(id)}
|
||||
if slash := strings.LastIndex(id, "/"); slash >= 0 {
|
||||
id = id[slash+1:]
|
||||
tail := id[slash+1:]
|
||||
forms = append(forms, tail, sharedllm.NormalizeAnthropicModel(tail))
|
||||
}
|
||||
return sharedllm.NormalizeAnthropicModel(id)
|
||||
return forms
|
||||
}
|
||||
|
||||
// restoreBody puts body back on the response and fixes the length headers
|
||||
|
||||
@@ -153,3 +153,20 @@ func TestModelDiscoveryFilter_RunsNextHook(t *testing.T) {
|
||||
require.NoError(t, modelDiscoveryFilter([]string{"claude-sonnet-5"}, next)(resp)) //nolint:bodyclose // in-memory body, replaced by the filter
|
||||
assert.True(t, called, "the chained hook must still run")
|
||||
}
|
||||
|
||||
// TestModelDiscoveryFilter_KeepsSlashBearingIDs covers self-hosted backends
|
||||
// whose model ids carry a slash of their own. Treating the slash as a
|
||||
// gateway prefix and keeping only the tail dropped every such model from
|
||||
// the picker even though the policy named it exactly.
|
||||
func TestModelDiscoveryFilter_KeepsSlashBearingIDs(t *testing.T) {
|
||||
ids := listedIDs(t, []string{"Qwen/Qwen2.5-0.5B-Instruct"}, `{
|
||||
"object": "list",
|
||||
"data": [
|
||||
{"id": "Qwen/Qwen2.5-0.5B-Instruct"},
|
||||
{"id": "Qwen/Qwen2.5-7B-Instruct"}
|
||||
]
|
||||
}`)
|
||||
|
||||
assert.Equal(t, []string{"Qwen/Qwen2.5-0.5B-Instruct"}, ids,
|
||||
"a slash inside the model id is part of the id, not a provider prefix")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user