Skip to content
190 changes: 190 additions & 0 deletions pydantic_ai_slim/pydantic_ai/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,196 @@
'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-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-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',
'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: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',
'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-image-preview',
'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',
Expand Down
5 changes: 4 additions & 1 deletion pydantic_ai_slim/pydantic_ai/providers/deepseek.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations as _annotations

import os
from typing import overload
from typing import Literal, overload

import httpx
from openai import AsyncOpenAI
Expand All @@ -22,6 +22,9 @@
) from _import_error


DeepSeekModelName = Literal['deepseek-chat', 'deepseek-reasoner']


class DeepSeekProvider(Provider[AsyncOpenAI]):
"""Provider for DeepSeek API."""

Expand Down
10 changes: 8 additions & 2 deletions pydantic_ai_slim/pydantic_ai/providers/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,17 @@ def gateway_provider(
) -> Provider[Any]: ...


UpstreamProvider = Literal[
ModelProvider = Literal[
'openai',
'groq',
'anthropic',
'bedrock',
'google-vertex',
# Those are only API formats, but we still support them for convenience.
]


# These are only API flavors, we support them for convenience.
APIFlavor = Literal[
'openai-chat',
'openai-responses',
'chat',
Expand All @@ -108,6 +112,8 @@ def gateway_provider(
'gemini',
]

UpstreamProvider = ModelProvider | APIFlavor


def gateway_provider(
upstream_provider: UpstreamProvider | str,
Expand Down
60 changes: 31 additions & 29 deletions tests/models/test_model_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing_extensions import TypedDict

from pydantic_ai.models import KnownModelName
from pydantic_ai.providers.gateway import ModelProvider as GatewayModelProvider

from ..conftest import try_import

Expand All @@ -20,6 +21,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.deepseek import DeepSeekModelName
from pydantic_ai.providers.grok import GrokModelName
from pydantic_ai.providers.moonshotai import MoonshotAIModelName

Expand Down Expand Up @@ -49,6 +51,22 @@ def vcr_config(): # pragma: lax no cover
}


_PROVIDER_TO_MODEL_NAMES = {
'anthropic': AnthropicModelName,
'bedrock': BedrockModelName,
'cohere': CohereModelName,
'deepseek': DeepSeekModelName,
'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]:
Expand All @@ -58,39 +76,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']
huggingface_names = [f'huggingface:{n}' for n in get_model_names(HuggingFaceModelName)]
heroku_names = get_heroku_model_names()

cerebras_names = get_cerebras_model_names()
heroku_names = get_heroku_model_names()
gateway_names = [
f'gateway/{provider}:{model_name}'
for provider in GatewayModelProvider.__args__
for model_name in get_model_names(_PROVIDER_TO_MODEL_NAMES[provider])
]

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
+ 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
Expand Down
1 change: 1 addition & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ def test_list_models(capfd: CaptureFixture[str]):
'mistral',
'cohere',
'deepseek',
'gateway/',
'heroku',
'moonshotai',
'grok',
Expand Down