From 293b3f8a13933b61703b94c2d8b214c9da0e99dd Mon Sep 17 00:00:00 2001 From: David Sanchez <64162682+dsfaccini@users.noreply.github.com> Date: Fri, 28 Nov 2025 13:25:13 -0500 Subject: [PATCH 1/6] add gateway to known model names --- .../pydantic_ai/models/__init__.py | 23 ++++++++++++++++ tests/models/test_model_names.py | 26 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/pydantic_ai_slim/pydantic_ai/models/__init__.py b/pydantic_ai_slim/pydantic_ai/models/__init__.py index a9b3789855..3028b8cd11 100644 --- a/pydantic_ai_slim/pydantic_ai/models/__init__.py +++ b/pydantic_ai_slim/pydantic_ai/models/__init__.py @@ -145,6 +145,29 @@ 'cohere:command-r7b-12-2024', 'deepseek:deepseek-chat', 'deepseek:deepseek-reasoner', + 'gateway/anthropic:claude-haiku-4-5', + 'gateway/anthropic:claude-opus-4-0', + 'gateway/anthropic:claude-sonnet-4-5', + 'gateway/bedrock:anthropic.claude-haiku-4-5-20251001-v1:0', + 'gateway/bedrock:anthropic.claude-opus-4-20250514-v1:0', + 'gateway/bedrock:anthropic.claude-sonnet-4-5-20250929-v1:0', + 'gateway/bedrock:us.amazon.nova-lite-v1:0', + 'gateway/bedrock:us.amazon.nova-micro-v1:0', + 'gateway/bedrock:us.amazon.nova-pro-v1:0', + 'gateway/google-vertex:gemini-2.5-flash', + 'gateway/google-vertex:gemini-2.5-flash-lite', + 'gateway/google-vertex:gemini-2.5-pro', + 'gateway/google-vertex:gemini-3-pro-preview', + 'gateway/groq:deepseek-r1-distill-llama-70b', + 'gateway/groq:gemma2-9b-it', + 'gateway/groq:llama-3.1-8b-instant', + 'gateway/groq:llama-3.3-70b-versatile', + 'gateway/groq:qwen-qwq-32b', + 'gateway/openai:gpt-5', + 'gateway/openai:gpt-5-mini', + 'gateway/openai:gpt-5-pro', + 'gateway/openai:o3', + 'gateway/openai:o4-mini', 'google-gla:gemini-flash-latest', 'google-gla:gemini-flash-lite-latest', 'google-gla:gemini-2.0-flash', diff --git a/tests/models/test_model_names.py b/tests/models/test_model_names.py index 058ffe28c7..72f16e972c 100644 --- a/tests/models/test_model_names.py +++ b/tests/models/test_model_names.py @@ -70,6 +70,31 @@ def get_model_names(model_name_type: Any) -> Iterator[str]: openai_names = [f'openai:{n}' for n in get_model_names(OpenAIModelName)] bedrock_names = [f'bedrock:{n}' for n in get_model_names(BedrockModelName)] deepseek_names = ['deepseek:deepseek-chat', 'deepseek:deepseek-reasoner'] + gateway_names = [ + 'gateway/anthropic:claude-haiku-4-5', + 'gateway/anthropic:claude-opus-4-0', + 'gateway/anthropic:claude-sonnet-4-5', + 'gateway/bedrock:anthropic.claude-haiku-4-5-20251001-v1:0', + 'gateway/bedrock:anthropic.claude-opus-4-20250514-v1:0', + 'gateway/bedrock:anthropic.claude-sonnet-4-5-20250929-v1:0', + 'gateway/bedrock:us.amazon.nova-lite-v1:0', + 'gateway/bedrock:us.amazon.nova-micro-v1:0', + 'gateway/bedrock:us.amazon.nova-pro-v1:0', + 'gateway/google-vertex:gemini-2.5-flash', + 'gateway/google-vertex:gemini-2.5-flash-lite', + 'gateway/google-vertex:gemini-2.5-pro', + 'gateway/google-vertex:gemini-3-pro-preview', + 'gateway/groq:deepseek-r1-distill-llama-70b', + 'gateway/groq:gemma2-9b-it', + 'gateway/groq:llama-3.1-8b-instant', + 'gateway/groq:llama-3.3-70b-versatile', + 'gateway/groq:qwen-qwq-32b', + 'gateway/openai:gpt-5', + 'gateway/openai:gpt-5-mini', + 'gateway/openai:gpt-5-pro', + 'gateway/openai:o3', + 'gateway/openai:o4-mini', + ] huggingface_names = [f'huggingface:{n}' for n in get_model_names(HuggingFaceModelName)] heroku_names = get_heroku_model_names() cerebras_names = get_cerebras_model_names() @@ -86,6 +111,7 @@ def get_model_names(model_name_type: Any) -> Iterator[str]: + openai_names + bedrock_names + deepseek_names + + gateway_names + huggingface_names + heroku_names + cerebras_names From 00d05bb126f7a31371f2812bf618393e8b7146d4 Mon Sep 17 00:00:00 2001 From: David Sanchez <64162682+dsfaccini@users.noreply.github.com> Date: Fri, 28 Nov 2025 13:41:34 -0500 Subject: [PATCH 2/6] adjust cli test --- tests/test_cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index e95ff09141..3a76c71102 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -144,6 +144,7 @@ def test_list_models(capfd: CaptureFixture[str]): 'mistral', 'cohere', 'deepseek', + 'gateway/', 'heroku', 'moonshotai', 'grok', From e3b090a3677cb58e1988c1fd30318eb66bc77a4a Mon Sep 17 00:00:00 2001 From: David Sanchez <64162682+dsfaccini@users.noreply.github.com> Date: Fri, 28 Nov 2025 17:28:20 -0500 Subject: [PATCH 3/6] add all supported provider/models for gateway --- .../pydantic_ai/models/__init__.py | 166 ++++++++++++++++++ tests/models/test_model_names.py | 32 +--- 2 files changed, 173 insertions(+), 25 deletions(-) diff --git a/pydantic_ai_slim/pydantic_ai/models/__init__.py b/pydantic_ai_slim/pydantic_ai/models/__init__.py index 3028b8cd11..0f7a4b7125 100644 --- a/pydantic_ai_slim/pydantic_ai/models/__init__.py +++ b/pydantic_ai_slim/pydantic_ai/models/__init__.py @@ -145,29 +145,195 @@ 'cohere:command-r7b-12-2024', 'deepseek:deepseek-chat', 'deepseek:deepseek-reasoner', + 'gateway/anthropic:claude-3-5-haiku-20241022', + 'gateway/anthropic:claude-3-5-haiku-latest', + 'gateway/anthropic:claude-3-5-sonnet-20240620', + 'gateway/anthropic:claude-3-5-sonnet-20241022', + 'gateway/anthropic:claude-3-5-sonnet-latest', + 'gateway/anthropic:claude-3-7-sonnet-20250219', + 'gateway/anthropic:claude-3-7-sonnet-latest', + 'gateway/anthropic:claude-3-haiku-20240307', + 'gateway/anthropic:claude-3-opus-20240229', + 'gateway/anthropic:claude-3-opus-latest', + 'gateway/anthropic:claude-4-opus-20250514', + 'gateway/anthropic:claude-4-sonnet-20250514', 'gateway/anthropic:claude-haiku-4-5', + 'gateway/anthropic:claude-haiku-4-5-20251001', 'gateway/anthropic:claude-opus-4-0', + 'gateway/anthropic:claude-opus-4-1-20250805', + 'gateway/anthropic:claude-opus-4-20250514', + 'gateway/anthropic:claude-sonnet-4-0', + 'gateway/anthropic:claude-sonnet-4-20250514', 'gateway/anthropic:claude-sonnet-4-5', + 'gateway/anthropic:claude-sonnet-4-5-20250929', + 'gateway/bedrock:amazon.titan-text-express-v1', + 'gateway/bedrock:amazon.titan-text-lite-v1', + 'gateway/bedrock:amazon.titan-tg1-large', + 'gateway/bedrock:anthropic.claude-3-5-haiku-20241022-v1:0', + 'gateway/bedrock:anthropic.claude-3-5-sonnet-20240620-v1:0', + 'gateway/bedrock:anthropic.claude-3-5-sonnet-20241022-v2:0', + 'gateway/bedrock:anthropic.claude-3-7-sonnet-20250219-v1:0', + 'gateway/bedrock:anthropic.claude-3-haiku-20240307-v1:0', + 'gateway/bedrock:anthropic.claude-3-opus-20240229-v1:0', + 'gateway/bedrock:anthropic.claude-3-sonnet-20240229-v1:0', 'gateway/bedrock:anthropic.claude-haiku-4-5-20251001-v1:0', + 'gateway/bedrock:anthropic.claude-instant-v1', 'gateway/bedrock:anthropic.claude-opus-4-20250514-v1:0', + 'gateway/bedrock:anthropic.claude-sonnet-4-20250514-v1:0', 'gateway/bedrock:anthropic.claude-sonnet-4-5-20250929-v1:0', + 'gateway/bedrock:anthropic.claude-v2', + 'gateway/bedrock:anthropic.claude-v2:1', + 'gateway/bedrock:cohere.command-light-text-v14', + 'gateway/bedrock:cohere.command-r-plus-v1:0', + 'gateway/bedrock:cohere.command-r-v1:0', + 'gateway/bedrock:cohere.command-text-v14', + 'gateway/bedrock:eu.anthropic.claude-haiku-4-5-20251001-v1:0', + 'gateway/bedrock:eu.anthropic.claude-sonnet-4-20250514-v1:0', + 'gateway/bedrock:eu.anthropic.claude-sonnet-4-5-20250929-v1:0', + 'gateway/bedrock:meta.llama3-1-405b-instruct-v1:0', + 'gateway/bedrock:meta.llama3-1-70b-instruct-v1:0', + 'gateway/bedrock:meta.llama3-1-8b-instruct-v1:0', + 'gateway/bedrock:meta.llama3-70b-instruct-v1:0', + 'gateway/bedrock:meta.llama3-8b-instruct-v1:0', + 'gateway/bedrock:mistral.mistral-7b-instruct-v0:2', + 'gateway/bedrock:mistral.mistral-large-2402-v1:0', + 'gateway/bedrock:mistral.mistral-large-2407-v1:0', + 'gateway/bedrock:mistral.mixtral-8x7b-instruct-v0:1', 'gateway/bedrock:us.amazon.nova-lite-v1:0', 'gateway/bedrock:us.amazon.nova-micro-v1:0', 'gateway/bedrock:us.amazon.nova-pro-v1:0', + 'gateway/bedrock:us.anthropic.claude-3-5-haiku-20241022-v1:0', + 'gateway/bedrock:us.anthropic.claude-3-5-sonnet-20240620-v1:0', + 'gateway/bedrock:us.anthropic.claude-3-5-sonnet-20241022-v2:0', + 'gateway/bedrock:us.anthropic.claude-3-7-sonnet-20250219-v1:0', + 'gateway/bedrock:us.anthropic.claude-3-haiku-20240307-v1:0', + 'gateway/bedrock:us.anthropic.claude-3-opus-20240229-v1:0', + 'gateway/bedrock:us.anthropic.claude-3-sonnet-20240229-v1:0', + 'gateway/bedrock:us.anthropic.claude-haiku-4-5-20251001-v1:0', + 'gateway/bedrock:us.anthropic.claude-opus-4-20250514-v1:0', + 'gateway/bedrock:us.anthropic.claude-sonnet-4-20250514-v1:0', + 'gateway/bedrock:us.anthropic.claude-sonnet-4-5-20250929-v1:0', + 'gateway/bedrock:us.meta.llama3-1-70b-instruct-v1:0', + 'gateway/bedrock:us.meta.llama3-1-8b-instruct-v1:0', + 'gateway/bedrock:us.meta.llama3-2-11b-instruct-v1:0', + 'gateway/bedrock:us.meta.llama3-2-1b-instruct-v1:0', + 'gateway/bedrock:us.meta.llama3-2-3b-instruct-v1:0', + 'gateway/bedrock:us.meta.llama3-2-90b-instruct-v1:0', + 'gateway/bedrock:us.meta.llama3-3-70b-instruct-v1:0', + 'gateway/google-vertex:gemini-2.0-flash', + 'gateway/google-vertex:gemini-2.0-flash-lite', 'gateway/google-vertex:gemini-2.5-flash', + 'gateway/google-vertex:gemini-2.5-flash-image', 'gateway/google-vertex:gemini-2.5-flash-lite', + 'gateway/google-vertex:gemini-2.5-flash-lite-preview-09-2025', + 'gateway/google-vertex:gemini-2.5-flash-preview-09-2025', 'gateway/google-vertex:gemini-2.5-pro', 'gateway/google-vertex:gemini-3-pro-preview', + 'gateway/google-vertex:gemini-flash-latest', + 'gateway/google-vertex:gemini-flash-lite-latest', 'gateway/groq:deepseek-r1-distill-llama-70b', + 'gateway/groq:deepseek-r1-distill-qwen-32b', + 'gateway/groq:distil-whisper-large-v3-en', 'gateway/groq:gemma2-9b-it', 'gateway/groq:llama-3.1-8b-instant', + 'gateway/groq:llama-3.2-11b-vision-preview', + 'gateway/groq:llama-3.2-1b-preview', + 'gateway/groq:llama-3.2-3b-preview', + 'gateway/groq:llama-3.2-90b-vision-preview', + 'gateway/groq:llama-3.3-70b-specdec', 'gateway/groq:llama-3.3-70b-versatile', + 'gateway/groq:llama-guard-3-8b', + 'gateway/groq:llama3-70b-8192', + 'gateway/groq:llama3-8b-8192', + 'gateway/groq:mistral-saba-24b', + 'gateway/groq:moonshotai/kimi-k2-instruct', + 'gateway/groq:playai-tts', + 'gateway/groq:playai-tts-arabic', + 'gateway/groq:qwen-2.5-32b', + 'gateway/groq:qwen-2.5-coder-32b', 'gateway/groq:qwen-qwq-32b', + 'gateway/groq:whisper-large-v3', + 'gateway/groq:whisper-large-v3-turbo', + 'gateway/openai:chatgpt-4o-latest', + 'gateway/openai:codex-mini-latest', + 'gateway/openai:computer-use-preview', + 'gateway/openai:computer-use-preview-2025-03-11', + 'gateway/openai:gpt-3.5-turbo', + 'gateway/openai:gpt-3.5-turbo-0125', + 'gateway/openai:gpt-3.5-turbo-0301', + 'gateway/openai:gpt-3.5-turbo-0613', + 'gateway/openai:gpt-3.5-turbo-1106', + 'gateway/openai:gpt-3.5-turbo-16k', + 'gateway/openai:gpt-3.5-turbo-16k-0613', + 'gateway/openai:gpt-4', + 'gateway/openai:gpt-4-0125-preview', + 'gateway/openai:gpt-4-0314', + 'gateway/openai:gpt-4-0613', + 'gateway/openai:gpt-4-1106-preview', + 'gateway/openai:gpt-4-32k', + 'gateway/openai:gpt-4-32k-0314', + 'gateway/openai:gpt-4-32k-0613', + 'gateway/openai:gpt-4-turbo', + 'gateway/openai:gpt-4-turbo-2024-04-09', + 'gateway/openai:gpt-4-turbo-preview', + 'gateway/openai:gpt-4-vision-preview', + 'gateway/openai:gpt-4.1', + 'gateway/openai:gpt-4.1-2025-04-14', + 'gateway/openai:gpt-4.1-mini', + 'gateway/openai:gpt-4.1-mini-2025-04-14', + 'gateway/openai:gpt-4.1-nano', + 'gateway/openai:gpt-4.1-nano-2025-04-14', + 'gateway/openai:gpt-4o', + 'gateway/openai:gpt-4o-2024-05-13', + 'gateway/openai:gpt-4o-2024-08-06', + 'gateway/openai:gpt-4o-2024-11-20', + 'gateway/openai:gpt-4o-audio-preview', + 'gateway/openai:gpt-4o-audio-preview-2024-10-01', + 'gateway/openai:gpt-4o-audio-preview-2024-12-17', + 'gateway/openai:gpt-4o-audio-preview-2025-06-03', + 'gateway/openai:gpt-4o-mini', + 'gateway/openai:gpt-4o-mini-2024-07-18', + 'gateway/openai:gpt-4o-mini-audio-preview', + 'gateway/openai:gpt-4o-mini-audio-preview-2024-12-17', + 'gateway/openai:gpt-4o-mini-search-preview', + 'gateway/openai:gpt-4o-mini-search-preview-2025-03-11', + 'gateway/openai:gpt-4o-search-preview', + 'gateway/openai:gpt-4o-search-preview-2025-03-11', 'gateway/openai:gpt-5', + 'gateway/openai:gpt-5-2025-08-07', + 'gateway/openai:gpt-5-chat-latest', + 'gateway/openai:gpt-5-codex', 'gateway/openai:gpt-5-mini', + 'gateway/openai:gpt-5-mini-2025-08-07', + 'gateway/openai:gpt-5-nano', + 'gateway/openai:gpt-5-nano-2025-08-07', 'gateway/openai:gpt-5-pro', + 'gateway/openai:gpt-5-pro-2025-10-06', + 'gateway/openai:gpt-5.1', + 'gateway/openai:gpt-5.1-2025-11-13', + 'gateway/openai:gpt-5.1-chat-latest', + 'gateway/openai:gpt-5.1-codex', + 'gateway/openai:gpt-5.1-mini', + 'gateway/openai:o1', + 'gateway/openai:o1-2024-12-17', + 'gateway/openai:o1-mini', + 'gateway/openai:o1-mini-2024-09-12', + 'gateway/openai:o1-preview', + 'gateway/openai:o1-preview-2024-09-12', + 'gateway/openai:o1-pro', + 'gateway/openai:o1-pro-2025-03-19', 'gateway/openai:o3', + 'gateway/openai:o3-2025-04-16', + 'gateway/openai:o3-deep-research', + 'gateway/openai:o3-deep-research-2025-06-26', + 'gateway/openai:o3-mini', + 'gateway/openai:o3-mini-2025-01-31', + 'gateway/openai:o3-pro', + 'gateway/openai:o3-pro-2025-06-10', 'gateway/openai:o4-mini', + 'gateway/openai:o4-mini-2025-04-16', + 'gateway/openai:o4-mini-deep-research', + 'gateway/openai:o4-mini-deep-research-2025-06-26', 'google-gla:gemini-flash-latest', 'google-gla:gemini-flash-lite-latest', 'google-gla:gemini-2.0-flash', diff --git a/tests/models/test_model_names.py b/tests/models/test_model_names.py index 72f16e972c..968d7f22f8 100644 --- a/tests/models/test_model_names.py +++ b/tests/models/test_model_names.py @@ -70,31 +70,13 @@ def get_model_names(model_name_type: Any) -> Iterator[str]: openai_names = [f'openai:{n}' for n in get_model_names(OpenAIModelName)] bedrock_names = [f'bedrock:{n}' for n in get_model_names(BedrockModelName)] deepseek_names = ['deepseek:deepseek-chat', 'deepseek:deepseek-reasoner'] - gateway_names = [ - 'gateway/anthropic:claude-haiku-4-5', - 'gateway/anthropic:claude-opus-4-0', - 'gateway/anthropic:claude-sonnet-4-5', - 'gateway/bedrock:anthropic.claude-haiku-4-5-20251001-v1:0', - 'gateway/bedrock:anthropic.claude-opus-4-20250514-v1:0', - 'gateway/bedrock:anthropic.claude-sonnet-4-5-20250929-v1:0', - 'gateway/bedrock:us.amazon.nova-lite-v1:0', - 'gateway/bedrock:us.amazon.nova-micro-v1:0', - 'gateway/bedrock:us.amazon.nova-pro-v1:0', - 'gateway/google-vertex:gemini-2.5-flash', - 'gateway/google-vertex:gemini-2.5-flash-lite', - 'gateway/google-vertex:gemini-2.5-pro', - 'gateway/google-vertex:gemini-3-pro-preview', - 'gateway/groq:deepseek-r1-distill-llama-70b', - 'gateway/groq:gemma2-9b-it', - 'gateway/groq:llama-3.1-8b-instant', - 'gateway/groq:llama-3.3-70b-versatile', - 'gateway/groq:qwen-qwq-32b', - 'gateway/openai:gpt-5', - 'gateway/openai:gpt-5-mini', - 'gateway/openai:gpt-5-pro', - 'gateway/openai:o3', - 'gateway/openai:o4-mini', - ] + gateway_names = ( + [f'gateway/anthropic:{n}' for n in get_model_names(AnthropicModelName)] + + [f'gateway/bedrock:{n}' for n in get_model_names(BedrockModelName)] + + [f'gateway/google-vertex:{n}' for n in get_model_names(GoogleModelName)] + + [f'gateway/groq:{n}' for n in get_model_names(GroqModelName)] + + [f'gateway/openai:{n}' for n in get_model_names(OpenAIModelName)] + ) huggingface_names = [f'huggingface:{n}' for n in get_model_names(HuggingFaceModelName)] heroku_names = get_heroku_model_names() cerebras_names = get_cerebras_model_names() From 9d213cead85b8e645a7b2b7e1f669c7a0fe77e36 Mon Sep 17 00:00:00 2001 From: David Sanchez <64162682+dsfaccini@users.noreply.github.com> Date: Fri, 28 Nov 2025 19:07:16 -0500 Subject: [PATCH 4/6] test model names dynamically based on supported providers --- .../pydantic_ai/providers/gateway.py | 33 +++++++++++++++++-- tests/models/test_model_names.py | 13 ++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/pydantic_ai_slim/pydantic_ai/providers/gateway.py b/pydantic_ai_slim/pydantic_ai/providers/gateway.py index bc29606799..6eab55bcaa 100644 --- a/pydantic_ai_slim/pydantic_ai/providers/gateway.py +++ b/pydantic_ai_slim/pydantic_ai/providers/gateway.py @@ -3,7 +3,7 @@ from __future__ import annotations as _annotations import os -from collections.abc import Awaitable, Callable +from collections.abc import Awaitable, Callable, Mapping from typing import TYPE_CHECKING, Any, Literal, overload import httpx @@ -93,13 +93,38 @@ def gateway_provider( ) -> Provider[Any]: ... -UpstreamProvider = Literal[ +ModelProviders = Literal[ 'openai', 'groq', 'anthropic', 'bedrock', 'google-vertex', - # Those are only API formats, but we still support them for convenience. +] + + +def gateway_provider_to_model_names() -> Mapping[ModelProviders, object]: + """Get the gateway model name for a given provider. + + Args: + provider: The provider to get the model name for. + """ + from pydantic_ai.models.anthropic import AnthropicModelName + from pydantic_ai.models.bedrock import BedrockModelName + from pydantic_ai.models.google import GoogleModelName + from pydantic_ai.models.groq import GroqModelName + from pydantic_ai.models.openai import OpenAIModelName + + return { + 'openai': OpenAIModelName, + 'groq': GroqModelName, + 'anthropic': AnthropicModelName, + 'bedrock': BedrockModelName, + 'google-vertex': GoogleModelName, + } + + +# These are only API formats, but we still support them for convenience. +ApiFormatProviders = Literal[ 'openai-chat', 'openai-responses', 'chat', @@ -108,6 +133,8 @@ def gateway_provider( 'gemini', ] +UpstreamProvider = ModelProviders | ApiFormatProviders + def gateway_provider( upstream_provider: UpstreamProvider | str, diff --git a/tests/models/test_model_names.py b/tests/models/test_model_names.py index 968d7f22f8..72cf99c50f 100644 --- a/tests/models/test_model_names.py +++ b/tests/models/test_model_names.py @@ -20,6 +20,7 @@ from pydantic_ai.models.huggingface import HuggingFaceModelName from pydantic_ai.models.mistral import MistralModelName from pydantic_ai.models.openai import OpenAIModelName + from pydantic_ai.providers.gateway import gateway_provider_to_model_names from pydantic_ai.providers.grok import GrokModelName from pydantic_ai.providers.moonshotai import MoonshotAIModelName @@ -70,13 +71,11 @@ def get_model_names(model_name_type: Any) -> Iterator[str]: openai_names = [f'openai:{n}' for n in get_model_names(OpenAIModelName)] bedrock_names = [f'bedrock:{n}' for n in get_model_names(BedrockModelName)] deepseek_names = ['deepseek:deepseek-chat', 'deepseek:deepseek-reasoner'] - gateway_names = ( - [f'gateway/anthropic:{n}' for n in get_model_names(AnthropicModelName)] - + [f'gateway/bedrock:{n}' for n in get_model_names(BedrockModelName)] - + [f'gateway/google-vertex:{n}' for n in get_model_names(GoogleModelName)] - + [f'gateway/groq:{n}' for n in get_model_names(GroqModelName)] - + [f'gateway/openai:{n}' for n in get_model_names(OpenAIModelName)] - ) + gateway_names = [ + f'gateway/{provider}:{model_name}' + for provider, model_names in gateway_provider_to_model_names().items() + for model_name in get_model_names(model_names) + ] huggingface_names = [f'huggingface:{n}' for n in get_model_names(HuggingFaceModelName)] heroku_names = get_heroku_model_names() cerebras_names = get_cerebras_model_names() From 6e05859ec7b04fe69813a7cf383fe3a1a5c813a5 Mon Sep 17 00:00:00 2001 From: David Sanchez <64162682+dsfaccini@users.noreply.github.com> Date: Fri, 28 Nov 2025 19:44:34 -0500 Subject: [PATCH 5/6] fix ci --- pydantic_ai_slim/pydantic_ai/models/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pydantic_ai_slim/pydantic_ai/models/__init__.py b/pydantic_ai_slim/pydantic_ai/models/__init__.py index b57047dd64..0c32083143 100644 --- a/pydantic_ai_slim/pydantic_ai/models/__init__.py +++ b/pydantic_ai_slim/pydantic_ai/models/__init__.py @@ -147,9 +147,6 @@ 'deepseek:deepseek-reasoner', 'gateway/anthropic:claude-3-5-haiku-20241022', 'gateway/anthropic:claude-3-5-haiku-latest', - 'gateway/anthropic:claude-3-5-sonnet-20240620', - 'gateway/anthropic:claude-3-5-sonnet-20241022', - 'gateway/anthropic:claude-3-5-sonnet-latest', 'gateway/anthropic:claude-3-7-sonnet-20250219', 'gateway/anthropic:claude-3-7-sonnet-latest', 'gateway/anthropic:claude-3-haiku-20240307', @@ -162,6 +159,8 @@ 'gateway/anthropic:claude-opus-4-0', 'gateway/anthropic:claude-opus-4-1-20250805', 'gateway/anthropic:claude-opus-4-20250514', + 'gateway/anthropic:claude-opus-4-5', + 'gateway/anthropic:claude-opus-4-5-20251101', 'gateway/anthropic:claude-sonnet-4-0', 'gateway/anthropic:claude-sonnet-4-20250514', 'gateway/anthropic:claude-sonnet-4-5', @@ -190,6 +189,7 @@ 'gateway/bedrock:eu.anthropic.claude-haiku-4-5-20251001-v1:0', 'gateway/bedrock:eu.anthropic.claude-sonnet-4-20250514-v1:0', 'gateway/bedrock:eu.anthropic.claude-sonnet-4-5-20250929-v1:0', + 'gateway/bedrock:global.anthropic.claude-opus-4-5-20251101-v1:0', 'gateway/bedrock:meta.llama3-1-405b-instruct-v1:0', 'gateway/bedrock:meta.llama3-1-70b-instruct-v1:0', 'gateway/bedrock:meta.llama3-1-8b-instruct-v1:0', @@ -228,6 +228,7 @@ 'gateway/google-vertex:gemini-2.5-flash-lite-preview-09-2025', 'gateway/google-vertex:gemini-2.5-flash-preview-09-2025', 'gateway/google-vertex:gemini-2.5-pro', + 'gateway/google-vertex:gemini-3-pro-image-preview', 'gateway/google-vertex:gemini-3-pro-preview', 'gateway/google-vertex:gemini-flash-latest', 'gateway/google-vertex:gemini-flash-lite-latest', From dc3fd1c245ee41aa4c505a16649546573f5f0bc3 Mon Sep 17 00:00:00 2001 From: David Sanchez <64162682+dsfaccini@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:23:05 -0500 Subject: [PATCH 6/6] cleaner model name generation in test model names --- .../pydantic_ai/providers/gateway.py | 29 ++------- tests/models/test_model_names.py | 62 +++++++++---------- 2 files changed, 32 insertions(+), 59 deletions(-) diff --git a/pydantic_ai_slim/pydantic_ai/providers/gateway.py b/pydantic_ai_slim/pydantic_ai/providers/gateway.py index 6eab55bcaa..4f7e5b529f 100644 --- a/pydantic_ai_slim/pydantic_ai/providers/gateway.py +++ b/pydantic_ai_slim/pydantic_ai/providers/gateway.py @@ -3,7 +3,7 @@ from __future__ import annotations as _annotations import os -from collections.abc import Awaitable, Callable, Mapping +from collections.abc import Awaitable, Callable from typing import TYPE_CHECKING, Any, Literal, overload import httpx @@ -102,29 +102,8 @@ def gateway_provider( ] -def gateway_provider_to_model_names() -> Mapping[ModelProviders, object]: - """Get the gateway model name for a given provider. - - Args: - provider: The provider to get the model name for. - """ - from pydantic_ai.models.anthropic import AnthropicModelName - from pydantic_ai.models.bedrock import BedrockModelName - from pydantic_ai.models.google import GoogleModelName - from pydantic_ai.models.groq import GroqModelName - from pydantic_ai.models.openai import OpenAIModelName - - return { - 'openai': OpenAIModelName, - 'groq': GroqModelName, - 'anthropic': AnthropicModelName, - 'bedrock': BedrockModelName, - 'google-vertex': GoogleModelName, - } - - -# These are only API formats, but we still support them for convenience. -ApiFormatProviders = Literal[ +# These are only API flavors, we support them for convenience. +APIFlavor = Literal[ 'openai-chat', 'openai-responses', 'chat', @@ -133,7 +112,7 @@ def gateway_provider_to_model_names() -> Mapping[ModelProviders, object]: 'gemini', ] -UpstreamProvider = ModelProviders | ApiFormatProviders +UpstreamProvider = ModelProviders | APIFlavor def gateway_provider( diff --git a/tests/models/test_model_names.py b/tests/models/test_model_names.py index 72cf99c50f..244966f256 100644 --- a/tests/models/test_model_names.py +++ b/tests/models/test_model_names.py @@ -8,6 +8,7 @@ from typing_extensions import TypedDict from pydantic_ai.models import KnownModelName +from pydantic_ai.providers.gateway import ModelProviders from ..conftest import try_import @@ -20,7 +21,6 @@ from pydantic_ai.models.huggingface import HuggingFaceModelName from pydantic_ai.models.mistral import MistralModelName from pydantic_ai.models.openai import OpenAIModelName - from pydantic_ai.providers.gateway import gateway_provider_to_model_names from pydantic_ai.providers.grok import GrokModelName from pydantic_ai.providers.moonshotai import MoonshotAIModelName @@ -50,6 +50,22 @@ def vcr_config(): # pragma: lax no cover } +_PROVIDER_TO_MODEL_NAMES = { + 'anthropic': AnthropicModelName, + 'bedrock': BedrockModelName, + 'cohere': CohereModelName, + 'deepseek': Literal['deepseek-chat', 'deepseek-reasoner'], + 'google-gla': GoogleModelName, + 'google-vertex': GoogleModelName, + 'grok': GrokModelName, + 'groq': GroqModelName, + 'huggingface': HuggingFaceModelName, + 'mistral': MistralModelName, + 'moonshotai': MoonshotAIModelName, + 'openai': OpenAIModelName, +} + + def test_known_model_names(): # pragma: lax no cover # Coverage seems to be misbehaving..? def get_model_names(model_name_type: Any) -> Iterator[str]: @@ -59,45 +75,23 @@ def get_model_names(model_name_type: Any) -> Iterator[str]: else: yield from get_model_names(arg) - anthropic_names = [f'anthropic:{n}' for n in get_model_names(AnthropicModelName)] - cohere_names = [f'cohere:{n}' for n in get_model_names(CohereModelName)] - google_names = [f'google-gla:{n}' for n in get_model_names(GoogleModelName)] + [ - f'google-vertex:{n}' for n in get_model_names(GoogleModelName) + all_generated_names = [ + f'{provider}:{n}' + for provider, model_names in _PROVIDER_TO_MODEL_NAMES.items() + for n in get_model_names(model_names) ] - grok_names = [f'grok:{n}' for n in get_model_names(GrokModelName)] - groq_names = [f'groq:{n}' for n in get_model_names(GroqModelName)] - moonshotai_names = [f'moonshotai:{n}' for n in get_model_names(MoonshotAIModelName)] - mistral_names = [f'mistral:{n}' for n in get_model_names(MistralModelName)] - openai_names = [f'openai:{n}' for n in get_model_names(OpenAIModelName)] - bedrock_names = [f'bedrock:{n}' for n in get_model_names(BedrockModelName)] - deepseek_names = ['deepseek:deepseek-chat', 'deepseek:deepseek-reasoner'] + + cerebras_names = get_cerebras_model_names() + heroku_names = get_heroku_model_names() gateway_names = [ f'gateway/{provider}:{model_name}' - for provider, model_names in gateway_provider_to_model_names().items() - for model_name in get_model_names(model_names) + for provider in ModelProviders.__args__ + for model_name in get_model_names(_PROVIDER_TO_MODEL_NAMES[provider]) ] - huggingface_names = [f'huggingface:{n}' for n in get_model_names(HuggingFaceModelName)] - heroku_names = get_heroku_model_names() - cerebras_names = get_cerebras_model_names() + extra_names = ['test'] - generated_names = sorted( - anthropic_names - + cohere_names - + google_names - + grok_names - + groq_names - + mistral_names - + moonshotai_names - + openai_names - + bedrock_names - + deepseek_names - + gateway_names - + huggingface_names - + heroku_names - + cerebras_names - + extra_names - ) + generated_names = sorted(all_generated_names + gateway_names + heroku_names + cerebras_names + extra_names) known_model_names = sorted(get_args(KnownModelName.__value__)) assert generated_names == known_model_names