mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-09 23:19:11 +02:00
[proxy] Anchor the Anthropic date strip to Claude ids
The release-date normalizer matched a bare "-YYYYMMDD" suffix on any id. Pricing looks every model up through it regardless of surface, and an operator can register a custom model under any id at all, so a custom "internal-llm-20250101" would silently inherit the rate registered for "internal-llm". Anchor the pattern on "claude" so it still covers the vendor-prefixed Bedrock forms while leaving every other vendor's id untouched.
This commit is contained in:
+16
-11
@@ -46,20 +46,25 @@ func NormalizeBedrockModel(modelID string) string {
|
|||||||
return bedrockVersionSuffix.ReplaceAllString(m, "")
|
return bedrockVersionSuffix.ReplaceAllString(m, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// anthropicDateSuffix matches the trailing "-YYYYMMDD" release-date suffix
|
// anthropicDatedModel matches a Claude model id carrying the trailing
|
||||||
// Anthropic appends to a pinned model id. No other vendor in the catalog
|
// "-YYYYMMDD" release-date suffix Anthropic appends to a pinned release,
|
||||||
// ends an id in eight consecutive digits, so the pattern is safe to apply
|
// capturing the id without it. The "claude" anchor is load-bearing: pricing
|
||||||
// before a lookup regardless of surface.
|
// looks every model up through this helper regardless of surface, and an
|
||||||
var anthropicDateSuffix = regexp.MustCompile(`-\d{8}$`)
|
// operator may register a custom id with any shape at all, so an unanchored
|
||||||
|
// "-\d{8}$" would let "internal-llm-20250101" silently inherit the rate
|
||||||
|
// registered for "internal-llm". The anchor also covers the vendor-prefixed
|
||||||
|
// forms ("anthropic.claude-...", "us.anthropic.claude-...").
|
||||||
|
var anthropicDatedModel = regexp.MustCompile(`(?i)^(.*claude.*)-\d{8}$`)
|
||||||
|
|
||||||
// NormalizeAnthropicModel strips the trailing release-date suffix from a
|
// NormalizeAnthropicModel strips the trailing release-date suffix from a
|
||||||
// first-party Anthropic model id, e.g. "claude-sonnet-4-5-20250929" ->
|
// Claude model id, e.g. "claude-sonnet-4-5-20250929" -> "claude-sonnet-4-5",
|
||||||
// "claude-sonnet-4-5", so a dated id a client pins matches the undated one
|
// so a dated id a client pins matches the undated one the operator
|
||||||
// the operator registered. Callers try the verbatim id first and fall back
|
// registered. Ids that are not Claude-family are returned untouched.
|
||||||
// to this, so two dated releases of the same family stay distinct wherever
|
// Callers try the verbatim id first and fall back to this, so two dated
|
||||||
// both are registered explicitly.
|
// releases of the same family stay distinct wherever both are registered
|
||||||
|
// explicitly.
|
||||||
func NormalizeAnthropicModel(modelID string) string {
|
func NormalizeAnthropicModel(modelID string) string {
|
||||||
return anthropicDateSuffix.ReplaceAllString(modelID, "")
|
return anthropicDatedModel.ReplaceAllString(modelID, "$1")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NormalizeVertexModel strips the "@version" suffix from a Vertex AI model id
|
// NormalizeVertexModel strips the "@version" suffix from a Vertex AI model id
|
||||||
|
|||||||
+18
-10
@@ -37,16 +37,24 @@ func TestNormalizeVertexModel(t *testing.T) {
|
|||||||
|
|
||||||
func TestNormalizeAnthropicModel(t *testing.T) {
|
func TestNormalizeAnthropicModel(t *testing.T) {
|
||||||
cases := map[string]string{
|
cases := map[string]string{
|
||||||
"claude-sonnet-4-5-20250929": "claude-sonnet-4-5",
|
"claude-sonnet-4-5-20250929": "claude-sonnet-4-5",
|
||||||
"claude-3-5-haiku-20241022": "claude-3-5-haiku",
|
"claude-3-5-haiku-20241022": "claude-3-5-haiku",
|
||||||
"claude-sonnet-5": "claude-sonnet-5",
|
"claude-sonnet-5": "claude-sonnet-5",
|
||||||
"claude-opus-4-8": "claude-opus-4-8",
|
"claude-opus-4-8": "claude-opus-4-8",
|
||||||
// Other vendors' ids must survive untouched: none of them end in
|
"anthropic.claude-haiku-4-5": "anthropic.claude-haiku-4-5",
|
||||||
// eight consecutive digits.
|
"anthropic.claude-sonnet-4-5-20250929": "anthropic.claude-sonnet-4-5",
|
||||||
"gpt-4o": "gpt-4o",
|
"us.anthropic.claude-opus-4-8-20250101": "us.anthropic.claude-opus-4-8",
|
||||||
"gpt-4o-2024-08-06": "gpt-4o-2024-08-06",
|
// Non-Claude ids must survive untouched even when they end in eight
|
||||||
"anthropic.claude-haiku-4-5": "anthropic.claude-haiku-4-5",
|
// consecutive digits: an operator can register a custom model under
|
||||||
"": "",
|
// any id, and pricing looks every one of them up through this helper.
|
||||||
|
"gpt-4o": "gpt-4o",
|
||||||
|
"gpt-4o-2024-08-06": "gpt-4o-2024-08-06",
|
||||||
|
"gpt-4o-20240806": "gpt-4o-20240806",
|
||||||
|
"internal-llm-20250101": "internal-llm-20250101",
|
||||||
|
"deepseek-r1-20250120": "deepseek-r1-20250120",
|
||||||
|
"Qwen/Qwen2.5-20250101": "Qwen/Qwen2.5-20250101",
|
||||||
|
"gemini-2-5-pro-20250101": "gemini-2-5-pro-20250101",
|
||||||
|
"": "",
|
||||||
}
|
}
|
||||||
for in, want := range cases {
|
for in, want := range cases {
|
||||||
require.Equal(t, want, NormalizeAnthropicModel(in), "normalize %q", in)
|
require.Equal(t, want, NormalizeAnthropicModel(in), "normalize %q", in)
|
||||||
|
|||||||
Reference in New Issue
Block a user