From db6b8518846990bf72cb97d23bf0af541244abf6 Mon Sep 17 00:00:00 2001 From: kerry Date: Sat, 12 Sep 2026 21:14:24 +0000 Subject: [PATCH 1/4] feat(registry): add openai reasoning-family fallback generalization Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- ...odel_prices_and_context_window_backup.json | 8 +++++ model_prices_and_context_window.json | 8 +++++ .../test_fallback_generalizations.py | 31 +++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 7fa09951eae..f01a7a0414b 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -57470,6 +57470,14 @@ "model_info": { "supports_reasoning": true } + }, + { + "name": "openai-reasoning-family-baseline", + "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-(?:[5-9]|[1-9]\\d)(?:\\.\\d+)?(?![0-9.])|(?:[a-z0-9.-]+-)?(?:codex|deep-research|chat-latest))", + "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), any gpt-5 or later major including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", + "model_info": { + "supports_reasoning": true + } } ] }, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 7fa09951eae..f01a7a0414b 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -57470,6 +57470,14 @@ "model_info": { "supports_reasoning": true } + }, + { + "name": "openai-reasoning-family-baseline", + "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-(?:[5-9]|[1-9]\\d)(?:\\.\\d+)?(?![0-9.])|(?:[a-z0-9.-]+-)?(?:codex|deep-research|chat-latest))", + "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), any gpt-5 or later major including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", + "model_info": { + "supports_reasoning": 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 b0220a36054..e930d494b3e 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -677,3 +677,34 @@ def test_deployment_model_info_beats_the_seeded_rule_defaults(shipped_cost_map): assert litellm.model_cost[model]["supports_reasoning"] is False assert litellm.supports_reasoning(model="some-org/NoThink-1", custom_llm_provider="wandb") is False + + +def test_shipped_rules_flag_unmapped_openai_reasoning_families(shipped_cost_map): + """OpenAI ships reasoning families faster than this registry names them. Any id in + the o-series, gpt-5+ major, codex, deep-research or chat-latest shape resolves as + reasoning-capable through the rule, under any provider namespace and an optional + ft: prefix, so the Responses API keeps the caller's reasoning settings instead of + silently dropping them.""" + for model in ("gpt-5.7-nova", "openai/gpt-6", "ft:gpt-5.1-2025-11-13:org::abc", "o5-mini", "gpt-5.6-codex-max", "o4-mini-deep-research-2027-01-01", "gpt-5.7-chat-latest", "azure/gpt-5.7-cyber"): + assert model not in litellm.model_cost, model + assert match_capability_generalizations(model) == {"supports_reasoning": True}, model + info = litellm.get_model_info("gpt-5.7-nova", custom_llm_provider="openai") + assert info["litellm_provider"] == "openai" + assert info["supports_reasoning"] is True + assert info.get("mode") is None + assert not info.get("input_cost_per_token") + assert litellm.supports_reasoning(model="gpt-5.7-nova", custom_llm_provider="openai") is True + + +def test_shipped_openai_reasoning_rule_skips_non_reasoning_gpt_ids(shipped_cost_map): + """The rule is gated on the reasoning-family shapes, so gpt-4.x, gpt-oss, realtime, + image, moderation, embedding and search-api ids all stay unflagged.""" + for model in ("gpt-4o", "gpt-4.1-nano-new", "gpt-oss-120b", "gpt-realtime-2027", "gpt-image-2", "gpt-5-search-api-2027-01-01", "omni-moderation-new", "text-embedding-4"): + assert match_capability_generalizations(model) is None, model + + +def test_shipped_openai_reasoning_rule_loses_to_mapped_entries(shipped_cost_map): + """Rules lose to exact entries: gpt-5-search-api is mapped non-reasoning, and the + search-api negative lookahead keeps the rule from flagging it anyway.""" + assert "gpt-5-search-api" in litellm.model_cost + assert litellm.supports_reasoning(model="gpt-5-search-api", custom_llm_provider="openai") is False From 543ed2f6dae19d0d1f1a7201b352563f18d2a7d1 Mon Sep 17 00:00:00 2001 From: kerry Date: Sat, 12 Sep 2026 21:23:24 +0000 Subject: [PATCH 2/4] fix(registry): scope codex/deep-research/chat-latest markers to gpt bases Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/model_prices_and_context_window_backup.json | 4 ++-- model_prices_and_context_window.json | 4 ++-- .../test_fallback_generalizations.py | 13 ++----------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index f01a7a0414b..eae9faa3a91 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -57473,8 +57473,8 @@ }, { "name": "openai-reasoning-family-baseline", - "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-(?:[5-9]|[1-9]\\d)(?:\\.\\d+)?(?![0-9.])|(?:[a-z0-9.-]+-)?(?:codex|deep-research|chat-latest))", - "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), any gpt-5 or later major including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", + "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-(?:[5-9]|[1-9]\\d)(?:\\.\\d+)?(?![0-9.])|(?:gpt-\\d+(?:\\.\\d+)?(?:-[a-z0-9]+)*-)?(?:codex|deep-research|chat-latest)(?![a-z0-9]))", + "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), any gpt-5 or later major including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines when standalone or on a gpt base. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", "model_info": { "supports_reasoning": true } diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index f01a7a0414b..eae9faa3a91 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -57473,8 +57473,8 @@ }, { "name": "openai-reasoning-family-baseline", - "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-(?:[5-9]|[1-9]\\d)(?:\\.\\d+)?(?![0-9.])|(?:[a-z0-9.-]+-)?(?:codex|deep-research|chat-latest))", - "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), any gpt-5 or later major including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", + "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-(?:[5-9]|[1-9]\\d)(?:\\.\\d+)?(?![0-9.])|(?:gpt-\\d+(?:\\.\\d+)?(?:-[a-z0-9]+)*-)?(?:codex|deep-research|chat-latest)(?![a-z0-9]))", + "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), any gpt-5 or later major including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines when standalone or on a gpt base. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", "model_info": { "supports_reasoning": 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 e930d494b3e..2edda52032c 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -680,12 +680,7 @@ def test_deployment_model_info_beats_the_seeded_rule_defaults(shipped_cost_map): def test_shipped_rules_flag_unmapped_openai_reasoning_families(shipped_cost_map): - """OpenAI ships reasoning families faster than this registry names them. Any id in - the o-series, gpt-5+ major, codex, deep-research or chat-latest shape resolves as - reasoning-capable through the rule, under any provider namespace and an optional - ft: prefix, so the Responses API keeps the caller's reasoning settings instead of - silently dropping them.""" - for model in ("gpt-5.7-nova", "openai/gpt-6", "ft:gpt-5.1-2025-11-13:org::abc", "o5-mini", "gpt-5.6-codex-max", "o4-mini-deep-research-2027-01-01", "gpt-5.7-chat-latest", "azure/gpt-5.7-cyber"): + for model in ("gpt-5.7-nova", "openai/gpt-6", "ft:gpt-5.1-2025-11-13:org::abc", "o5-mini", "gpt-5.6-codex-max", "o4-mini-deep-research-2027-01-01", "gpt-5.7-chat-latest", "azure/gpt-5.7-cyber", "openai/codex-mini-latest-2027"): assert model not in litellm.model_cost, model assert match_capability_generalizations(model) == {"supports_reasoning": True}, model info = litellm.get_model_info("gpt-5.7-nova", custom_llm_provider="openai") @@ -697,14 +692,10 @@ def test_shipped_rules_flag_unmapped_openai_reasoning_families(shipped_cost_map) def test_shipped_openai_reasoning_rule_skips_non_reasoning_gpt_ids(shipped_cost_map): - """The rule is gated on the reasoning-family shapes, so gpt-4.x, gpt-oss, realtime, - image, moderation, embedding and search-api ids all stay unflagged.""" - for model in ("gpt-4o", "gpt-4.1-nano-new", "gpt-oss-120b", "gpt-realtime-2027", "gpt-image-2", "gpt-5-search-api-2027-01-01", "omni-moderation-new", "text-embedding-4"): + for model in ("gpt-4o", "gpt-4.1-nano-new", "gpt-oss-120b", "gpt-realtime-2027", "gpt-image-2", "gpt-5-search-api-2027-01-01", "omni-moderation-new", "text-embedding-4", "vendor/my-codex-embedding", "some-codex-model"): assert match_capability_generalizations(model) is None, model def test_shipped_openai_reasoning_rule_loses_to_mapped_entries(shipped_cost_map): - """Rules lose to exact entries: gpt-5-search-api is mapped non-reasoning, and the - search-api negative lookahead keeps the rule from flagging it anyway.""" assert "gpt-5-search-api" in litellm.model_cost assert litellm.supports_reasoning(model="gpt-5-search-api", custom_llm_provider="openai") is False From ca35119168cdef14a11c8a310a2a6ad94fc30a2a Mon Sep 17 00:00:00 2001 From: kerry Date: Sat, 12 Sep 2026 21:56:11 +0000 Subject: [PATCH 3/4] style(tests): wrap oversized model tuples Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../test_fallback_generalizations.py | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) 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 2edda52032c..2e5c6597753 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -680,7 +680,17 @@ def test_deployment_model_info_beats_the_seeded_rule_defaults(shipped_cost_map): def test_shipped_rules_flag_unmapped_openai_reasoning_families(shipped_cost_map): - for model in ("gpt-5.7-nova", "openai/gpt-6", "ft:gpt-5.1-2025-11-13:org::abc", "o5-mini", "gpt-5.6-codex-max", "o4-mini-deep-research-2027-01-01", "gpt-5.7-chat-latest", "azure/gpt-5.7-cyber", "openai/codex-mini-latest-2027"): + for model in ( + "gpt-5.7-nova", + "openai/gpt-6", + "ft:gpt-5.1-2025-11-13:org::abc", + "o5-mini", + "gpt-5.6-codex-max", + "o4-mini-deep-research-2027-01-01", + "gpt-5.7-chat-latest", + "azure/gpt-5.7-cyber", + "openai/codex-mini-latest-2027", + ): assert model not in litellm.model_cost, model assert match_capability_generalizations(model) == {"supports_reasoning": True}, model info = litellm.get_model_info("gpt-5.7-nova", custom_llm_provider="openai") @@ -692,7 +702,18 @@ def test_shipped_rules_flag_unmapped_openai_reasoning_families(shipped_cost_map) def test_shipped_openai_reasoning_rule_skips_non_reasoning_gpt_ids(shipped_cost_map): - for model in ("gpt-4o", "gpt-4.1-nano-new", "gpt-oss-120b", "gpt-realtime-2027", "gpt-image-2", "gpt-5-search-api-2027-01-01", "omni-moderation-new", "text-embedding-4", "vendor/my-codex-embedding", "some-codex-model"): + for model in ( + "gpt-4o", + "gpt-4.1-nano-new", + "gpt-oss-120b", + "gpt-realtime-2027", + "gpt-image-2", + "gpt-5-search-api-2027-01-01", + "omni-moderation-new", + "text-embedding-4", + "vendor/my-codex-embedding", + "some-codex-model", + ): assert match_capability_generalizations(model) is None, model From df272d7e2f586904f162d519d2111dd7ae0867ce Mon Sep 17 00:00:00 2001 From: kerry Date: Sat, 12 Sep 2026 22:01:58 +0000 Subject: [PATCH 4/4] fix(registry): limit reasoning fallback to single-digit gpt majors Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/model_prices_and_context_window_backup.json | 4 ++-- model_prices_and_context_window.json | 4 ++-- .../litellm_core_utils/test_fallback_generalizations.py | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index eae9faa3a91..64bb0325649 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -57473,8 +57473,8 @@ }, { "name": "openai-reasoning-family-baseline", - "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-(?:[5-9]|[1-9]\\d)(?:\\.\\d+)?(?![0-9.])|(?:gpt-\\d+(?:\\.\\d+)?(?:-[a-z0-9]+)*-)?(?:codex|deep-research|chat-latest)(?![a-z0-9]))", - "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), any gpt-5 or later major including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines when standalone or on a gpt base. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", + "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-[5-9](?:\\.\\d+)?(?![0-9.])|(?:gpt-\\d+(?:\\.\\d+)?(?:-[a-z0-9]+)*-)?(?:codex|deep-research|chat-latest)(?![a-z0-9]))", + "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), gpt-5 through gpt-9 majors including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines when standalone or on a gpt base. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", "model_info": { "supports_reasoning": true } diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index eae9faa3a91..64bb0325649 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -57473,8 +57473,8 @@ }, { "name": "openai-reasoning-family-baseline", - "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-(?:[5-9]|[1-9]\\d)(?:\\.\\d+)?(?![0-9.])|(?:gpt-\\d+(?:\\.\\d+)?(?:-[a-z0-9]+)*-)?(?:codex|deep-research|chat-latest)(?![a-z0-9]))", - "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), any gpt-5 or later major including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines when standalone or on a gpt base. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", + "pattern": "^(?!.*search-api)(?:[a-z0-9_.-]+/)*(?:ft:)?(?:o[1-9]\\d*(?![a-z0-9])|gpt-[5-9](?:\\.\\d+)?(?![0-9.])|(?:gpt-\\d+(?:\\.\\d+)?(?:-[a-z0-9]+)*-)?(?:codex|deep-research|chat-latest)(?![a-z0-9]))", + "description": "OpenAI reasoning families by id shape, under any provider namespace and with an optional ft: prefix: the o-series (o1, o3-pro, o4-mini), gpt-5 through gpt-9 majors including dotted minors and suffixed variants (gpt-5.5-cyber, gpt-6-astra), and the codex, deep-research and chat-latest lines when standalone or on a gpt base. gpt-5-search-api is excluded because it is a search-only surface. Every model here is a reasoning model, and the Responses API drops the caller's reasoning param for any mapped OpenAI model whose info lacks supports_reasoning, so an id the registry has not named yet keeps its reasoning settings instead of silently losing them. Rules lose to exact entries. Carries no mode and no pricing, so cost stays on the standard unpriced behavior.", "model_info": { "supports_reasoning": 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 2e5c6597753..b6e656f282a 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -713,6 +713,8 @@ def test_shipped_openai_reasoning_rule_skips_non_reasoning_gpt_ids(shipped_cost_ "text-embedding-4", "vendor/my-codex-embedding", "some-codex-model", + "azure/gpt-35-turbo-0125-custom", + "github_copilot/gpt-41-copilot-new", ): assert match_capability_generalizations(model) is None, model