diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 868ba5c43e3..b4ae842c4e6 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -45059,16 +45059,16 @@ }, { "name": "anthropic-claude-ids", - "pattern": "^claude-[a-z]+-\\d+[-.]\\d+(?:-\\d{8})?$", - "description": "A bare Claude family-major-minor id, optionally with an 8-digit date suffix, anchored to the whole name. Routes an unmapped Claude id that carries no provider namespace to the Anthropic API.", + "pattern": "^claude-[a-z]+-\\d+(?:[-.]\\d+)?(?:-\\d{8})?$", + "description": "A bare Claude family-major id with an optional minor and an optional 8-digit date suffix, anchored to the whole name, so claude-newfamily-5 routes like claude-newfamily-5-1 does. Routes an unmapped Claude id that carries no provider namespace to the Anthropic API.", "model_info": { "litellm_provider": "anthropic" } }, { "name": "claude-family-baseline", - "pattern": "claude-[a-z]+-\\d+[-.]\\d+(?:-\\d{8})?", - "description": "Any Claude family-major-minor id, optionally with an 8-digit date suffix, under any provider namespace (bare, bedrock-dotted, vertex, databricks, ...). Carries the model-family facts every Claude shares; it carries no pricing, so cost stays on the standard unpriced behavior rather than a guessed number.", + "pattern": "claude-[a-z]+-\\d+(?:[-.]\\d+)?(?:-\\d{8})?", + "description": "Any Claude family-major id with an optional minor and an optional 8-digit date suffix, under any provider namespace (bare, bedrock-dotted, vertex, databricks, ...), so bare majors like claude-newfamily-5 get the same baseline as claude-newfamily-5-1. Carries the model-family facts every Claude shares; it carries no pricing, so cost stays on the standard unpriced behavior rather than a guessed number.", "model_info": { "mode": "chat", "max_input_tokens": 200000, @@ -45088,8 +45088,8 @@ }, { "name": "claude-adaptive-thinking", - "pattern": "(?:opus|sonnet|haiku)[-._](?:4[-._](?:[6-9]|[1-9]\\d)(?!\\d)|(?:[5-9]|[1-9]\\d{1,})[-._]\\d{1,2}(?!\\d))|claude-[a-z]+-(?:[5-9]|[1-9]\\d)(?!\\d)(?:[-._]\\d{1,2}(?!\\d))?", - "description": "Claude opus/sonnet/haiku at version 4.6 or higher (4.6 through 4.99, then any later major-minor), plus any claude-- id at major version 5 or higher, bare major or major-minor, so a new family shaped like claude-fable-5 is covered by the same gate as the core families. 4.x coverage stays limited to opus/sonnet/haiku. The minor is capped at two digits so an 8-digit date suffix such as claude-opus-4-20250514 is never read as a >= 4.6 minor. Turns on adaptive thinking for new versions and new families with no code change.", + "pattern": "claude-[a-z]+-(?:4[-._](?:[6-9]|[1-9]\\d)(?!\\d)|(?:[5-9]|[1-9]\\d)(?!\\d)(?:[-._]\\d{1,2}(?!\\d))?)", + "description": "Claude at version 4.6 or higher, in any id shape that contains claude--: minors 4.6 through 4.99, any later major-minor, and bare 5+ majors so a new family shaped like claude-fable-5 matches. Requiring the claude- prefix keeps non-Claude names such as team-sonnet-5-1 out. The minor is capped at two digits so an 8-digit date suffix such as claude-opus-4-20250514 is never read as a >= 4.6 minor. Turns on adaptive thinking for new versions and new families with no code change.", "model_info": { "supports_adaptive_thinking": true } diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 37ce3d270c8..94d9f6496bd 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -45292,16 +45292,16 @@ }, { "name": "anthropic-claude-ids", - "pattern": "^claude-[a-z]+-\\d+[-.]\\d+(?:-\\d{8})?$", - "description": "A bare Claude family-major-minor id, optionally with an 8-digit date suffix, anchored to the whole name. Routes an unmapped Claude id that carries no provider namespace to the Anthropic API.", + "pattern": "^claude-[a-z]+-\\d+(?:[-.]\\d+)?(?:-\\d{8})?$", + "description": "A bare Claude family-major id with an optional minor and an optional 8-digit date suffix, anchored to the whole name, so claude-newfamily-5 routes like claude-newfamily-5-1 does. Routes an unmapped Claude id that carries no provider namespace to the Anthropic API.", "model_info": { "litellm_provider": "anthropic" } }, { "name": "claude-family-baseline", - "pattern": "claude-[a-z]+-\\d+[-.]\\d+(?:-\\d{8})?", - "description": "Any Claude family-major-minor id, optionally with an 8-digit date suffix, under any provider namespace (bare, bedrock-dotted, vertex, databricks, ...). Carries the model-family facts every Claude shares; it carries no pricing, so cost stays on the standard unpriced behavior rather than a guessed number.", + "pattern": "claude-[a-z]+-\\d+(?:[-.]\\d+)?(?:-\\d{8})?", + "description": "Any Claude family-major id with an optional minor and an optional 8-digit date suffix, under any provider namespace (bare, bedrock-dotted, vertex, databricks, ...), so bare majors like claude-newfamily-5 get the same baseline as claude-newfamily-5-1. Carries the model-family facts every Claude shares; it carries no pricing, so cost stays on the standard unpriced behavior rather than a guessed number.", "model_info": { "mode": "chat", "max_input_tokens": 200000, @@ -45321,8 +45321,8 @@ }, { "name": "claude-adaptive-thinking", - "pattern": "(?:opus|sonnet|haiku)[-._](?:4[-._](?:[6-9]|[1-9]\\d)(?!\\d)|(?:[5-9]|[1-9]\\d{1,})[-._]\\d{1,2}(?!\\d))|claude-[a-z]+-(?:[5-9]|[1-9]\\d)(?!\\d)(?:[-._]\\d{1,2}(?!\\d))?", - "description": "Claude opus/sonnet/haiku at version 4.6 or higher (4.6 through 4.99, then any later major-minor), plus any claude-- id at major version 5 or higher, bare major or major-minor, so a new family shaped like claude-fable-5 is covered by the same gate as the core families. 4.x coverage stays limited to opus/sonnet/haiku. The minor is capped at two digits so an 8-digit date suffix such as claude-opus-4-20250514 is never read as a >= 4.6 minor. Turns on adaptive thinking for new versions and new families with no code change.", + "pattern": "claude-[a-z]+-(?:4[-._](?:[6-9]|[1-9]\\d)(?!\\d)|(?:[5-9]|[1-9]\\d)(?!\\d)(?:[-._]\\d{1,2}(?!\\d))?)", + "description": "Claude at version 4.6 or higher, in any id shape that contains claude--: minors 4.6 through 4.99, any later major-minor, and bare 5+ majors so a new family shaped like claude-fable-5 matches. Requiring the claude- prefix keeps non-Claude names such as team-sonnet-5-1 out. The minor is capped at two digits so an 8-digit date suffix such as claude-opus-4-20250514 is never read as a >= 4.6 minor. Turns on adaptive thinking for new versions and new families with no code change.", "model_info": { "supports_adaptive_thinking": true } diff --git a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py index 69020fceba1..0ea09463c16 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -427,15 +427,51 @@ def test_shipped_rules_flag_bare_5_plus_majors_of_any_family(shipped_cost_map): assert matched["supports_mid_conversation_system"] is True -def test_shipped_adaptive_rule_keeps_4x_coverage_to_core_families(shipped_cost_map): - """The family-agnostic adaptive branch starts at major 5; a non-core family at - 4.x gets the 4.8+ mid-conversation flag and baseline caps but never adaptive.""" - model = "claude-newfam-4-9" +def test_shipped_version_gates_are_family_agnostic_at_4x(shipped_cost_map): + """Both version gates apply to any claude-- id, 4.x included: a non-core + family at 4.9 gets adaptive and mid-conversation, while the same family at 4.5 + gets baseline only. Only opus/sonnet/haiku ever shipped 4.x ids, so the + family-agnostic 4.6+ gate changes nothing for real models.""" + high = litellm.get_model_info("claude-newfam-4-9", custom_llm_provider="anthropic") + assert high["supports_adaptive_thinking"] is True + assert high["supports_mid_conversation_system"] is True + assert high["supports_function_calling"] is True + + low = litellm.get_model_info("claude-newfam-4-5", custom_llm_provider="anthropic") + assert low.get("supports_adaptive_thinking") is None + assert low.get("supports_mid_conversation_system") is None + assert low["supports_function_calling"] is True + + +def test_shipped_rules_give_bare_majors_the_full_baseline_union(shipped_cost_map): + """A bare-major unmapped id (no minor) resolves the same baseline union as its + major-minor sibling: the baseline pattern's minor is optional, so claude-newt-5 + is not left with version flags but no mode, token limits, or capability facts.""" + model = "anthropic/claude-newt-5" assert model not in litellm.model_cost - info = litellm.get_model_info(model, custom_llm_provider="anthropic") - assert info["supports_mid_conversation_system"] is True - assert info.get("supports_adaptive_thinking") is None + info = litellm.get_model_info(model) + assert info["litellm_provider"] == "anthropic" + assert info["mode"] == "chat" + assert info["max_tokens"] == 64000 assert info["supports_function_calling"] is True + assert info["supports_adaptive_thinking"] is True + assert info["supports_mid_conversation_system"] is True + + +def test_shipped_routing_rule_covers_bare_majors(shipped_cost_map): + _, provider, _, _ = litellm.get_llm_provider(model="claude-newt-5") + assert provider == "anthropic" + + +def test_shipped_adaptive_rule_requires_claude_prefix(shipped_cost_map): + """A non-Claude name embedding a core-family 4.6+/5.x version substring must not + resolve from the rules; serving it a zero-priced rule entry would silently + swallow cost tracking for arbitrary custom deployment names.""" + model = "openai/team-sonnet-5-1-alias" + assert model not in litellm.model_cost + assert match_capability_generalizations("team-sonnet-5-1-alias") is None + with pytest.raises(Exception): + litellm.get_model_info(model) def test_shipped_exact_entry_beats_rules(shipped_cost_map): diff --git a/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py b/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py index 316f0d6ddf7..4bd270bb7fb 100644 --- a/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py +++ b/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py @@ -1685,8 +1685,8 @@ class TestClaudeOpus48AdaptiveThinking: self, local_model_cost_map, model ): """Provider-prefixed or suffixed Claude names that resolve to no mapped entry - still resolve to adaptive when their opus/sonnet/haiku family version is >= 4.6 - or any family's major version is >= 5. The version gate is the declarative + still resolve to adaptive when the id carries claude-- at version 4.6 + or higher, bare 5+ majors included. The version gate is the declarative ``claude-adaptive-thinking`` rule, so 5.x, 6.x and any later family are covered with no code change.""" import litellm