Skip to content

pydantic_ai.models

Logic related to making requests to an LLM.

The aim here is to make a common interface for different LLMs, so that the rest of the code can be agnostic to the specific LLM being used.

KnownModelName module-attribute

KnownModelName = TypeAliasType( "KnownModelName", Literal[ "anthropic:claude-3-5-haiku-20241022", "anthropic:claude-3-5-haiku-latest", "anthropic:claude-3-7-sonnet-20250219", "anthropic:claude-3-7-sonnet-latest", "anthropic:claude-3-haiku-20240307", "anthropic:claude-3-opus-20240229", "anthropic:claude-3-opus-latest", "anthropic:claude-4-opus-20250514", "anthropic:claude-4-sonnet-20250514", "anthropic:claude-haiku-4-5-20251001", "anthropic:claude-haiku-4-5", "anthropic:claude-opus-4-0", "anthropic:claude-opus-4-1-20250805", "anthropic:claude-opus-4-20250514", "anthropic:claude-opus-4-5-20251101", "anthropic:claude-opus-4-5", "anthropic:claude-sonnet-4-0", "anthropic:claude-sonnet-4-20250514", "anthropic:claude-sonnet-4-5-20250929", "anthropic:claude-sonnet-4-5", "bedrock:amazon.titan-text-express-v1", "bedrock:amazon.titan-text-lite-v1", "bedrock:amazon.titan-tg1-large", "bedrock:anthropic.claude-3-5-haiku-20241022-v1:0", "bedrock:anthropic.claude-3-5-sonnet-20240620-v1:0", "bedrock:anthropic.claude-3-5-sonnet-20241022-v2:0", "bedrock:anthropic.claude-3-7-sonnet-20250219-v1:0", "bedrock:anthropic.claude-3-haiku-20240307-v1:0", "bedrock:anthropic.claude-3-opus-20240229-v1:0", "bedrock:anthropic.claude-3-sonnet-20240229-v1:0", "bedrock:anthropic.claude-haiku-4-5-20251001-v1:0", "bedrock:anthropic.claude-instant-v1", "bedrock:anthropic.claude-opus-4-20250514-v1:0", "bedrock:anthropic.claude-sonnet-4-20250514-v1:0", "bedrock:anthropic.claude-sonnet-4-5-20250929-v1:0", "bedrock:anthropic.claude-v2:1", "bedrock:anthropic.claude-v2", "bedrock:cohere.command-light-text-v14", "bedrock:cohere.command-r-plus-v1:0", "bedrock:cohere.command-r-v1:0", "bedrock:cohere.command-text-v14", "bedrock:eu.anthropic.claude-haiku-4-5-20251001-v1:0", "bedrock:eu.anthropic.claude-sonnet-4-20250514-v1:0", "bedrock:eu.anthropic.claude-sonnet-4-5-20250929-v1:0", "bedrock:global.anthropic.claude-opus-4-5-20251101-v1:0", "bedrock:meta.llama3-1-405b-instruct-v1:0", "bedrock:meta.llama3-1-70b-instruct-v1:0", "bedrock:meta.llama3-1-8b-instruct-v1:0", "bedrock:meta.llama3-70b-instruct-v1:0", "bedrock:meta.llama3-8b-instruct-v1:0", "bedrock:mistral.mistral-7b-instruct-v0:2", "bedrock:mistral.mistral-large-2402-v1:0", "bedrock:mistral.mistral-large-2407-v1:0", "bedrock:mistral.mixtral-8x7b-instruct-v0:1", "bedrock:us.amazon.nova-lite-v1:0", "bedrock:us.amazon.nova-micro-v1:0", "bedrock:us.amazon.nova-pro-v1:0", "bedrock:us.anthropic.claude-3-5-haiku-20241022-v1:0", "bedrock:us.anthropic.claude-3-5-sonnet-20240620-v1:0", "bedrock:us.anthropic.claude-3-5-sonnet-20241022-v2:0", "bedrock:us.anthropic.claude-3-7-sonnet-20250219-v1:0", "bedrock:us.anthropic.claude-3-haiku-20240307-v1:0", "bedrock:us.anthropic.claude-3-opus-20240229-v1:0", "bedrock:us.anthropic.claude-3-sonnet-20240229-v1:0", "bedrock:us.anthropic.claude-haiku-4-5-20251001-v1:0", "bedrock:us.anthropic.claude-opus-4-20250514-v1:0", "bedrock:us.anthropic.claude-sonnet-4-20250514-v1:0", "bedrock:us.anthropic.claude-sonnet-4-5-20250929-v1:0", "bedrock:us.meta.llama3-1-70b-instruct-v1:0", "bedrock:us.meta.llama3-1-8b-instruct-v1:0", "bedrock:us.meta.llama3-2-11b-instruct-v1:0", "bedrock:us.meta.llama3-2-1b-instruct-v1:0", "bedrock:us.meta.llama3-2-3b-instruct-v1:0", "bedrock:us.meta.llama3-2-90b-instruct-v1:0", "bedrock:us.meta.llama3-3-70b-instruct-v1:0", "cerebras:gpt-oss-120b", "cerebras:llama-3.3-70b", "cerebras:llama3.1-8b", "cerebras:qwen-3-235b-a22b-instruct-2507", "cerebras:qwen-3-32b", "cerebras:zai-glm-4.6", "cohere:c4ai-aya-expanse-32b", "cohere:c4ai-aya-expanse-8b", "cohere:command-nightly", "cohere:command-r-08-2024", "cohere:command-r-plus-08-2024", "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-20251001", "gateway/anthropic:claude-haiku-4-5", "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-20251101", "gateway/anthropic:claude-opus-4-5", "gateway/anthropic:claude-sonnet-4-0", "gateway/anthropic:claude-sonnet-4-20250514", "gateway/anthropic:claude-sonnet-4-5-20250929", "gateway/anthropic:claude-sonnet-4-5", "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:1", "gateway/bedrock:anthropic.claude-v2", "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-lite", "gateway/google-vertex:gemini-2.0-flash", "gateway/google-vertex:gemini-2.5-flash-image", "gateway/google-vertex:gemini-2.5-flash-lite-preview-09-2025", "gateway/google-vertex:gemini-2.5-flash-lite", "gateway/google-vertex:gemini-2.5-flash-preview-09-2025", "gateway/google-vertex:gemini-2.5-flash", "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-arabic", "gateway/groq:playai-tts", "gateway/groq:qwen-2.5-32b", "gateway/groq:qwen-2.5-coder-32b", "gateway/groq:qwen-qwq-32b", "gateway/groq:whisper-large-v3-turbo", "gateway/groq:whisper-large-v3", "gateway/openai:chatgpt-4o-latest", "gateway/openai:codex-mini-latest", "gateway/openai:computer-use-preview-2025-03-11", "gateway/openai:computer-use-preview", "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-0613", "gateway/openai:gpt-3.5-turbo-16k", "gateway/openai:gpt-3.5-turbo", "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-0314", "gateway/openai:gpt-4-32k-0613", "gateway/openai:gpt-4-32k", "gateway/openai:gpt-4-turbo-2024-04-09", "gateway/openai:gpt-4-turbo-preview", "gateway/openai:gpt-4-turbo", "gateway/openai:gpt-4-vision-preview", "gateway/openai:gpt-4.1-2025-04-14", "gateway/openai:gpt-4.1-mini-2025-04-14", "gateway/openai:gpt-4.1-mini", "gateway/openai:gpt-4.1-nano-2025-04-14", "gateway/openai:gpt-4.1-nano", "gateway/openai:gpt-4.1", "gateway/openai:gpt-4", "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-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-audio-preview", "gateway/openai:gpt-4o-mini-2024-07-18", "gateway/openai:gpt-4o-mini-audio-preview-2024-12-17", "gateway/openai:gpt-4o-mini-audio-preview", "gateway/openai:gpt-4o-mini-search-preview-2025-03-11", "gateway/openai:gpt-4o-mini-search-preview", "gateway/openai:gpt-4o-mini", "gateway/openai:gpt-4o-search-preview-2025-03-11", "gateway/openai:gpt-4o-search-preview", "gateway/openai:gpt-4o", "gateway/openai:gpt-5-2025-08-07", "gateway/openai:gpt-5-chat-latest", "gateway/openai:gpt-5-codex", "gateway/openai:gpt-5-mini-2025-08-07", "gateway/openai:gpt-5-mini", "gateway/openai:gpt-5-nano-2025-08-07", "gateway/openai:gpt-5-nano", "gateway/openai:gpt-5-pro-2025-10-06", "gateway/openai:gpt-5-pro", "gateway/openai:gpt-5.1-2025-11-13", "gateway/openai:gpt-5.1-chat-latest", "gateway/openai:gpt-5.1-codex-max", "gateway/openai:gpt-5.1-codex", "gateway/openai:gpt-5.1-mini", "gateway/openai:gpt-5.1", "gateway/openai:gpt-5.2-2025-12-11", "gateway/openai:gpt-5.2-chat-latest", "gateway/openai:gpt-5.2-pro-2025-12-11", "gateway/openai:gpt-5.2-pro", "gateway/openai:gpt-5.2", "gateway/openai:gpt-5", "gateway/openai:o1-2024-12-17", "gateway/openai:o1-mini-2024-09-12", "gateway/openai:o1-mini", "gateway/openai:o1-preview-2024-09-12", "gateway/openai:o1-preview", "gateway/openai:o1-pro-2025-03-19", "gateway/openai:o1-pro", "gateway/openai:o1", "gateway/openai:o3-2025-04-16", "gateway/openai:o3-deep-research-2025-06-26", "gateway/openai:o3-deep-research", "gateway/openai:o3-mini-2025-01-31", "gateway/openai:o3-mini", "gateway/openai:o3-pro-2025-06-10", "gateway/openai:o3-pro", "gateway/openai:o3", "gateway/openai:o4-mini-2025-04-16", "gateway/openai:o4-mini-deep-research-2025-06-26", "gateway/openai:o4-mini-deep-research", "gateway/openai:o4-mini", "google-gla:gemini-2.0-flash-lite", "google-gla:gemini-2.0-flash", "google-gla:gemini-2.5-flash-image", "google-gla:gemini-2.5-flash-lite-preview-09-2025", "google-gla:gemini-2.5-flash-lite", "google-gla:gemini-2.5-flash-preview-09-2025", "google-gla:gemini-2.5-flash", "google-gla:gemini-2.5-pro", "google-gla:gemini-3-pro-image-preview", "google-gla:gemini-3-pro-preview", "google-gla:gemini-flash-latest", "google-gla:gemini-flash-lite-latest", "google-vertex:gemini-2.0-flash-lite", "google-vertex:gemini-2.0-flash", "google-vertex:gemini-2.5-flash-image", "google-vertex:gemini-2.5-flash-lite-preview-09-2025", "google-vertex:gemini-2.5-flash-lite", "google-vertex:gemini-2.5-flash-preview-09-2025", "google-vertex:gemini-2.5-flash", "google-vertex:gemini-2.5-pro", "google-vertex:gemini-3-pro-image-preview", "google-vertex:gemini-3-pro-preview", "google-vertex:gemini-flash-latest", "google-vertex:gemini-flash-lite-latest", "grok:grok-2-image-1212", "grok:grok-2-vision-1212", "grok:grok-3-fast", "grok:grok-3-mini-fast", "grok:grok-3-mini", "grok:grok-3", "grok:grok-4-0709", "grok:grok-4-1-fast-non-reasoning", "grok:grok-4-1-fast-reasoning", "grok:grok-4-1-fast", "grok:grok-4-fast-non-reasoning", "grok:grok-4-fast-reasoning", "grok:grok-4-fast", "grok:grok-4", "grok:grok-code-fast-1", "groq:deepseek-r1-distill-llama-70b", "groq:deepseek-r1-distill-qwen-32b", "groq:distil-whisper-large-v3-en", "groq:gemma2-9b-it", "groq:llama-3.1-8b-instant", "groq:llama-3.2-11b-vision-preview", "groq:llama-3.2-1b-preview", "groq:llama-3.2-3b-preview", "groq:llama-3.2-90b-vision-preview", "groq:llama-3.3-70b-specdec", "groq:llama-3.3-70b-versatile", "groq:llama-guard-3-8b", "groq:llama3-70b-8192", "groq:llama3-8b-8192", "groq:mistral-saba-24b", "groq:moonshotai/kimi-k2-instruct", "groq:playai-tts-arabic", "groq:playai-tts", "groq:qwen-2.5-32b", "groq:qwen-2.5-coder-32b", "groq:qwen-qwq-32b", "groq:whisper-large-v3-turbo", "groq:whisper-large-v3", "heroku:amazon-rerank-1-0", "heroku:claude-3-5-haiku", "heroku:claude-3-5-sonnet-latest", "heroku:claude-3-7-sonnet", "heroku:claude-3-haiku", "heroku:claude-4-5-haiku", "heroku:claude-4-5-sonnet", "heroku:claude-4-sonnet", "heroku:cohere-rerank-3-5", "heroku:gpt-oss-120b", "heroku:nova-lite", "heroku:nova-pro", "huggingface:deepseek-ai/DeepSeek-R1", "huggingface:meta-llama/Llama-3.3-70B-Instruct", "huggingface:meta-llama/Llama-4-Maverick-17B-128E-Instruct", "huggingface:meta-llama/Llama-4-Scout-17B-16E-Instruct", "huggingface:Qwen/Qwen2.5-72B-Instruct", "huggingface:Qwen/Qwen3-235B-A22B", "huggingface:Qwen/Qwen3-32B", "huggingface:Qwen/QwQ-32B", "mistral:codestral-latest", "mistral:mistral-large-latest", "mistral:mistral-moderation-latest", "mistral:mistral-small-latest", "moonshotai:kimi-k2-0711-preview", "moonshotai:kimi-latest", "moonshotai:kimi-thinking-preview", "moonshotai:moonshot-v1-128k-vision-preview", "moonshotai:moonshot-v1-128k", "moonshotai:moonshot-v1-32k-vision-preview", "moonshotai:moonshot-v1-32k", "moonshotai:moonshot-v1-8k-vision-preview", "moonshotai:moonshot-v1-8k", "openai:chatgpt-4o-latest", "openai:codex-mini-latest", "openai:computer-use-preview-2025-03-11", "openai:computer-use-preview", "openai:gpt-3.5-turbo-0125", "openai:gpt-3.5-turbo-0301", "openai:gpt-3.5-turbo-0613", "openai:gpt-3.5-turbo-1106", "openai:gpt-3.5-turbo-16k-0613", "openai:gpt-3.5-turbo-16k", "openai:gpt-3.5-turbo", "openai:gpt-4-0125-preview", "openai:gpt-4-0314", "openai:gpt-4-0613", "openai:gpt-4-1106-preview", "openai:gpt-4-32k-0314", "openai:gpt-4-32k-0613", "openai:gpt-4-32k", "openai:gpt-4-turbo-2024-04-09", "openai:gpt-4-turbo-preview", "openai:gpt-4-turbo", "openai:gpt-4-vision-preview", "openai:gpt-4.1-2025-04-14", "openai:gpt-4.1-mini-2025-04-14", "openai:gpt-4.1-mini", "openai:gpt-4.1-nano-2025-04-14", "openai:gpt-4.1-nano", "openai:gpt-4.1", "openai:gpt-4", "openai:gpt-4o-2024-05-13", "openai:gpt-4o-2024-08-06", "openai:gpt-4o-2024-11-20", "openai:gpt-4o-audio-preview-2024-10-01", "openai:gpt-4o-audio-preview-2024-12-17", "openai:gpt-4o-audio-preview-2025-06-03", "openai:gpt-4o-audio-preview", "openai:gpt-4o-mini-2024-07-18", "openai:gpt-4o-mini-audio-preview-2024-12-17", "openai:gpt-4o-mini-audio-preview", "openai:gpt-4o-mini-search-preview-2025-03-11", "openai:gpt-4o-mini-search-preview", "openai:gpt-4o-mini", "openai:gpt-4o-search-preview-2025-03-11", "openai:gpt-4o-search-preview", "openai:gpt-4o", "openai:gpt-5-2025-08-07", "openai:gpt-5-chat-latest", "openai:gpt-5-codex", "openai:gpt-5-mini-2025-08-07", "openai:gpt-5-mini", "openai:gpt-5-nano-2025-08-07", "openai:gpt-5-nano", "openai:gpt-5-pro-2025-10-06", "openai:gpt-5-pro", "openai:gpt-5.1-2025-11-13", "openai:gpt-5.1-chat-latest", "openai:gpt-5.1-codex-max", "openai:gpt-5.1-codex", "openai:gpt-5.1-mini", "openai:gpt-5.1", "openai:gpt-5.2-2025-12-11", "openai:gpt-5.2-chat-latest", "openai:gpt-5.2-pro-2025-12-11", "openai:gpt-5.2-pro", "openai:gpt-5.2", "openai:gpt-5", "openai:o1-2024-12-17", "openai:o1-mini-2024-09-12", "openai:o1-mini", "openai:o1-preview-2024-09-12", "openai:o1-preview", "openai:o1-pro-2025-03-19", "openai:o1-pro", "openai:o1", "openai:o3-2025-04-16", "openai:o3-deep-research-2025-06-26", "openai:o3-deep-research", "openai:o3-mini-2025-01-31", "openai:o3-mini", "openai:o3-pro-2025-06-10", "openai:o3-pro", "openai:o3", "openai:o4-mini-2025-04-16", "openai:o4-mini-deep-research-2025-06-26", "openai:o4-mini-deep-research", "openai:o4-mini", "test", ], ) 

Known model names that can be used with the model parameter of Agent.

KnownModelName is provided as a concise way to specify a model.

ModelRequestParameters dataclass

Configuration for an agent's request to a model, specifically related to tools and output handling.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
@dataclass(repr=False, kw_only=True) class ModelRequestParameters:  """Configuration for an agent's request to a model, specifically related to tools and output handling.""" function_tools: list[ToolDefinition] = field(default_factory=list) builtin_tools: list[AbstractBuiltinTool] = field(default_factory=list) output_mode: OutputMode = 'text' output_object: OutputObjectDefinition | None = None output_tools: list[ToolDefinition] = field(default_factory=list) prompted_output_template: str | None = None allow_text_output: bool = True allow_image_output: bool = False @cached_property def tool_defs(self) -> dict[str, ToolDefinition]: return {tool_def.name: tool_def for tool_def in [*self.function_tools, *self.output_tools]} @cached_property def prompted_output_instructions(self) -> str | None: if self.output_mode == 'prompted' and self.prompted_output_template and self.output_object: return PromptedOutputSchema.build_instructions(self.prompted_output_template, self.output_object) return None __repr__ = _utils.dataclasses_no_defaults_repr 

Model

Bases: ABC

Abstract class for a model.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
class Model(ABC):  """Abstract class for a model.""" _profile: ModelProfileSpec | None = None _settings: ModelSettings | None = None def __init__( self, *, settings: ModelSettings | None = None, profile: ModelProfileSpec | None = None, ) -> None:  """Initialize the model with optional settings and profile.  Args:  settings: Model-specific settings that will be used as defaults for this model.  profile: The model profile to use.  """ self._settings = settings self._profile = profile @property def settings(self) -> ModelSettings | None:  """Get the model settings.""" return self._settings @abstractmethod async def request( self, messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> ModelResponse:  """Make a request to the model.  This is ultimately called by `pydantic_ai._agent_graph.ModelRequestNode._make_request(...)`.  """ raise NotImplementedError() async def count_tokens( self, messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> RequestUsage:  """Make a request to the model for counting tokens.""" # This method is not required, but you need to implement it if you want to support `UsageLimits.count_tokens_before_request`. raise NotImplementedError(f'Token counting ahead of the request is not supported by {self.__class__.__name__}') @asynccontextmanager async def request_stream( self, messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, run_context: RunContext[Any] | None = None, ) -> AsyncIterator[StreamedResponse]:  """Make a request to the model and return a streaming response.""" # This method is not required, but you need to implement it if you want to support streamed responses raise NotImplementedError(f'Streamed requests not supported by this {self.__class__.__name__}') # yield is required to make this a generator for type checking # noinspection PyUnreachableCode yield # pragma: no cover def customize_request_parameters(self, model_request_parameters: ModelRequestParameters) -> ModelRequestParameters:  """Customize the request parameters for the model.  This method can be overridden by subclasses to modify the request parameters before sending them to the model.  In particular, this method can be used to make modifications to the generated tool JSON schemas if necessary  for vendor/model-specific reasons.  """ if transformer := self.profile.json_schema_transformer: model_request_parameters = replace( model_request_parameters, function_tools=[_customize_tool_def(transformer, t) for t in model_request_parameters.function_tools], output_tools=[_customize_tool_def(transformer, t) for t in model_request_parameters.output_tools], ) if output_object := model_request_parameters.output_object: model_request_parameters = replace( model_request_parameters, output_object=_customize_output_object(transformer, output_object), ) return model_request_parameters def prepare_request( self, model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> tuple[ModelSettings | None, ModelRequestParameters]:  """Prepare request inputs before they are passed to the provider.  This merges the given `model_settings` with the model's own `settings` attribute and ensures  `customize_request_parameters` is applied to the resolved  [`ModelRequestParameters`][pydantic_ai.models.ModelRequestParameters]. Subclasses can override this method if  they need to customize the preparation flow further, but most implementations should simply call  `self.prepare_request(...)` at the start of their `request` (and related) methods.  """ model_settings = merge_model_settings(self.settings, model_settings) params = self.customize_request_parameters(model_request_parameters) if builtin_tools := params.builtin_tools: # Deduplicate builtin tools params = replace( params, builtin_tools=list({tool.unique_id: tool for tool in builtin_tools}.values()), ) if params.output_mode == 'auto': output_mode = self.profile.default_structured_output_mode params = replace( params, output_mode=output_mode, allow_text_output=output_mode in ('native', 'prompted'), ) # Reset irrelevant fields if params.output_tools and params.output_mode != 'tool': params = replace(params, output_tools=[]) if params.output_object and params.output_mode not in ('native', 'prompted'): params = replace(params, output_object=None) if params.prompted_output_template and params.output_mode != 'prompted': params = replace(params, prompted_output_template=None) # pragma: no cover # Set default prompted output template if params.output_mode == 'prompted' and not params.prompted_output_template: params = replace(params, prompted_output_template=self.profile.prompted_output_template) # Check if output mode is supported if params.output_mode == 'native' and not self.profile.supports_json_schema_output: raise UserError('Native structured output is not supported by this model.') if params.output_mode == 'tool' and not self.profile.supports_tools: raise UserError('Tool output is not supported by this model.') if params.allow_image_output and not self.profile.supports_image_output: raise UserError('Image output is not supported by this model.') # Check if builtin tools are supported if params.builtin_tools: supported_types = self.profile.supported_builtin_tools unsupported = [tool for tool in params.builtin_tools if not isinstance(tool, tuple(supported_types))] if unsupported: unsupported_names = [type(tool).__name__ for tool in unsupported] supported_names = [t.__name__ for t in supported_types] raise UserError( f'Builtin tool(s) {unsupported_names} not supported by this model. Supported: {supported_names}' ) return model_settings, params @property @abstractmethod def model_name(self) -> str:  """The model name.""" raise NotImplementedError() @property def label(self) -> str:  """Human-friendly display label for the model.  Handles common patterns:  - gpt-5 -> GPT 5  - claude-sonnet-4-5 -> Claude Sonnet 4.5  - gemini-2.5-pro -> Gemini 2.5 Pro  - meta-llama/llama-3-70b -> Llama 3 70b (OpenRouter style)  """ label = self.model_name # Handle OpenRouter-style names with / (e.g., meta-llama/llama-3-70b) if '/' in label: label = label.split('/')[-1] parts = label.split('-') result: list[str] = [] for i, part in enumerate(parts): if i == 0 and part.lower() == 'gpt': result.append(part.upper()) elif part.replace('.', '').isdigit(): if result and result[-1].replace('.', '').isdigit(): result[-1] = f'{result[-1]}.{part}' else: result.append(part) else: result.append(part.capitalize()) return ' '.join(result) @classmethod def supported_builtin_tools(cls) -> frozenset[type[AbstractBuiltinTool]]:  """Return the set of builtin tool types this model class can handle.  Subclasses should override this to reflect their actual capabilities.  Default is empty set - subclasses must explicitly declare support.  """ return frozenset() @cached_property def profile(self) -> ModelProfile:  """The model profile.  We use this to compute the intersection of the profile's supported_builtin_tools  and the model's implemented tools, ensuring model.profile.supported_builtin_tools  is the single source of truth for what builtin tools are actually usable.  """ _profile = self._profile if callable(_profile): _profile = _profile(self.model_name) if _profile is None: _profile = DEFAULT_PROFILE # Compute intersection: profile's allowed tools & model's implemented tools model_supported = self.__class__.supported_builtin_tools() profile_supported = _profile.supported_builtin_tools effective_tools = profile_supported & model_supported if effective_tools != profile_supported: _profile = replace(_profile, supported_builtin_tools=effective_tools) return _profile @property @abstractmethod def system(self) -> str:  """The model provider, ex: openai.  Use to populate the `gen_ai.system` OpenTelemetry semantic convention attribute,  so should use well-known values listed in  https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/#gen-ai-system  when applicable.  """ raise NotImplementedError() @property def base_url(self) -> str | None:  """The base URL for the provider API, if available.""" return None @staticmethod def _get_instructions( messages: Sequence[ModelMessage], model_request_parameters: ModelRequestParameters | None = None ) -> str | None:  """Get instructions from the first ModelRequest found when iterating messages in reverse.  In the case that a "mock" request was generated to include a tool-return part for a result tool,  we want to use the instructions from the second-to-most-recent request (which should correspond to the  original request that generated the response that resulted in the tool-return part).  """ instructions = None last_two_requests: list[ModelRequest] = [] for message in reversed(messages): if isinstance(message, ModelRequest): last_two_requests.append(message) if len(last_two_requests) == 2: break if message.instructions is not None: instructions = message.instructions break # If we don't have two requests, and we didn't already return instructions, there are definitely not any: if instructions is None and len(last_two_requests) == 2: most_recent_request = last_two_requests[0] second_most_recent_request = last_two_requests[1] # If we've gotten this far and the most recent request consists of only tool-return parts or retry-prompt parts, # we use the instructions from the second-to-most-recent request. This is necessary because when handling # result tools, we generate a "mock" ModelRequest with a tool-return part for it, and that ModelRequest will not # have the relevant instructions from the agent. # While it's possible that you could have a message history where the most recent request has only tool returns, # I believe there is no way to achieve that would _change_ the instructions without manually crafting the most # recent message. That might make sense in principle for some usage pattern, but it's enough of an edge case # that I think it's not worth worrying about, since you can work around this by inserting another ModelRequest # with no parts at all immediately before the request that has the tool calls (that works because we only look # at the two most recent ModelRequests here). # If you have a use case where this causes pain, please open a GitHub issue and we can discuss alternatives. if all(p.part_kind == 'tool-return' or p.part_kind == 'retry-prompt' for p in most_recent_request.parts): instructions = second_most_recent_request.instructions if model_request_parameters and (output_instructions := model_request_parameters.prompted_output_instructions): if instructions: instructions = '\n\n'.join([instructions, output_instructions]) else: instructions = output_instructions return instructions 

__init__

__init__( *, settings: ModelSettings | None = None, profile: ModelProfileSpec | None = None ) -> None 

Initialize the model with optional settings and profile.

Parameters:

Name Type Description Default
settings ModelSettings | None

Model-specific settings that will be used as defaults for this model.

None
profile ModelProfileSpec | None

The model profile to use.

None
Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
566 567 568 569 570 571 572 573 574 575 576 577 578 579
def __init__( self, *, settings: ModelSettings | None = None, profile: ModelProfileSpec | None = None, ) -> None:  """Initialize the model with optional settings and profile.  Args:  settings: Model-specific settings that will be used as defaults for this model.  profile: The model profile to use.  """ self._settings = settings self._profile = profile 

settings property

settings: ModelSettings | None 

Get the model settings.

request abstractmethod async

request( messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> ModelResponse 

Make a request to the model.

This is ultimately called by pydantic_ai._agent_graph.ModelRequestNode._make_request(...).

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
586 587 588 589 590 591 592 593 594 595 596 597
@abstractmethod async def request( self, messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> ModelResponse:  """Make a request to the model.  This is ultimately called by `pydantic_ai._agent_graph.ModelRequestNode._make_request(...)`.  """ raise NotImplementedError() 

count_tokens async

count_tokens( messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> RequestUsage 

Make a request to the model for counting tokens.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
599 600 601 602 603 604 605 606 607
async def count_tokens( self, messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> RequestUsage:  """Make a request to the model for counting tokens.""" # This method is not required, but you need to implement it if you want to support `UsageLimits.count_tokens_before_request`. raise NotImplementedError(f'Token counting ahead of the request is not supported by {self.__class__.__name__}') 

request_stream async

request_stream( messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, run_context: RunContext[Any] | None = None, ) -> AsyncIterator[StreamedResponse] 

Make a request to the model and return a streaming response.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
609 610 611 612 613 614 615 616 617 618 619 620 621 622
@asynccontextmanager async def request_stream( self, messages: list[ModelMessage], model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, run_context: RunContext[Any] | None = None, ) -> AsyncIterator[StreamedResponse]:  """Make a request to the model and return a streaming response.""" # This method is not required, but you need to implement it if you want to support streamed responses raise NotImplementedError(f'Streamed requests not supported by this {self.__class__.__name__}') # yield is required to make this a generator for type checking # noinspection PyUnreachableCode yield # pragma: no cover 

customize_request_parameters

customize_request_parameters( model_request_parameters: ModelRequestParameters, ) -> ModelRequestParameters 

Customize the request parameters for the model.

This method can be overridden by subclasses to modify the request parameters before sending them to the model. In particular, this method can be used to make modifications to the generated tool JSON schemas if necessary for vendor/model-specific reasons.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
def customize_request_parameters(self, model_request_parameters: ModelRequestParameters) -> ModelRequestParameters:  """Customize the request parameters for the model.  This method can be overridden by subclasses to modify the request parameters before sending them to the model.  In particular, this method can be used to make modifications to the generated tool JSON schemas if necessary  for vendor/model-specific reasons.  """ if transformer := self.profile.json_schema_transformer: model_request_parameters = replace( model_request_parameters, function_tools=[_customize_tool_def(transformer, t) for t in model_request_parameters.function_tools], output_tools=[_customize_tool_def(transformer, t) for t in model_request_parameters.output_tools], ) if output_object := model_request_parameters.output_object: model_request_parameters = replace( model_request_parameters, output_object=_customize_output_object(transformer, output_object), ) return model_request_parameters 

prepare_request

prepare_request( model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> tuple[ModelSettings | None, ModelRequestParameters] 

Prepare request inputs before they are passed to the provider.

This merges the given model_settings with the model's own settings attribute and ensures customize_request_parameters is applied to the resolved ModelRequestParameters. Subclasses can override this method if they need to customize the preparation flow further, but most implementations should simply call self.prepare_request(...) at the start of their request (and related) methods.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
def prepare_request( self, model_settings: ModelSettings | None, model_request_parameters: ModelRequestParameters, ) -> tuple[ModelSettings | None, ModelRequestParameters]:  """Prepare request inputs before they are passed to the provider.  This merges the given `model_settings` with the model's own `settings` attribute and ensures  `customize_request_parameters` is applied to the resolved  [`ModelRequestParameters`][pydantic_ai.models.ModelRequestParameters]. Subclasses can override this method if  they need to customize the preparation flow further, but most implementations should simply call  `self.prepare_request(...)` at the start of their `request` (and related) methods.  """ model_settings = merge_model_settings(self.settings, model_settings) params = self.customize_request_parameters(model_request_parameters) if builtin_tools := params.builtin_tools: # Deduplicate builtin tools params = replace( params, builtin_tools=list({tool.unique_id: tool for tool in builtin_tools}.values()), ) if params.output_mode == 'auto': output_mode = self.profile.default_structured_output_mode params = replace( params, output_mode=output_mode, allow_text_output=output_mode in ('native', 'prompted'), ) # Reset irrelevant fields if params.output_tools and params.output_mode != 'tool': params = replace(params, output_tools=[]) if params.output_object and params.output_mode not in ('native', 'prompted'): params = replace(params, output_object=None) if params.prompted_output_template and params.output_mode != 'prompted': params = replace(params, prompted_output_template=None) # pragma: no cover # Set default prompted output template if params.output_mode == 'prompted' and not params.prompted_output_template: params = replace(params, prompted_output_template=self.profile.prompted_output_template) # Check if output mode is supported if params.output_mode == 'native' and not self.profile.supports_json_schema_output: raise UserError('Native structured output is not supported by this model.') if params.output_mode == 'tool' and not self.profile.supports_tools: raise UserError('Tool output is not supported by this model.') if params.allow_image_output and not self.profile.supports_image_output: raise UserError('Image output is not supported by this model.') # Check if builtin tools are supported if params.builtin_tools: supported_types = self.profile.supported_builtin_tools unsupported = [tool for tool in params.builtin_tools if not isinstance(tool, tuple(supported_types))] if unsupported: unsupported_names = [type(tool).__name__ for tool in unsupported] supported_names = [t.__name__ for t in supported_types] raise UserError( f'Builtin tool(s) {unsupported_names} not supported by this model. Supported: {supported_names}' ) return model_settings, params 

model_name abstractmethod property

model_name: str 

The model name.

label property

label: str 

Human-friendly display label for the model.

Handles common patterns: - gpt-5 -> GPT 5 - claude-sonnet-4-5 -> Claude Sonnet 4.5 - gemini-2.5-pro -> Gemini 2.5 Pro - meta-llama/llama-3-70b -> Llama 3 70b (OpenRouter style)

supported_builtin_tools classmethod

supported_builtin_tools() -> ( frozenset[type[AbstractBuiltinTool]] ) 

Return the set of builtin tool types this model class can handle.

Subclasses should override this to reflect their actual capabilities. Default is empty set - subclasses must explicitly declare support.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
747 748 749 750 751 752 753 754
@classmethod def supported_builtin_tools(cls) -> frozenset[type[AbstractBuiltinTool]]:  """Return the set of builtin tool types this model class can handle.  Subclasses should override this to reflect their actual capabilities.  Default is empty set - subclasses must explicitly declare support.  """ return frozenset() 

profile cached property

profile: ModelProfile 

The model profile.

We use this to compute the intersection of the profile's supported_builtin_tools and the model's implemented tools, ensuring model.profile.supported_builtin_tools is the single source of truth for what builtin tools are actually usable.

system abstractmethod property

system: str 

The model provider, ex: openai.

Use to populate the gen_ai.system OpenTelemetry semantic convention attribute, so should use well-known values listed in https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/#gen-ai-system when applicable.

base_url property

base_url: str | None 

The base URL for the provider API, if available.

StreamedResponse dataclass

Bases: ABC

Streamed response from an LLM when calling a tool.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987
@dataclass class StreamedResponse(ABC):  """Streamed response from an LLM when calling a tool.""" model_request_parameters: ModelRequestParameters final_result_event: FinalResultEvent | None = field(default=None, init=False) provider_response_id: str | None = field(default=None, init=False) provider_details: dict[str, Any] | None = field(default=None, init=False) finish_reason: FinishReason | None = field(default=None, init=False) _parts_manager: ModelResponsePartsManager = field(default_factory=ModelResponsePartsManager, init=False) _event_iterator: AsyncIterator[ModelResponseStreamEvent] | None = field(default=None, init=False) _usage: RequestUsage = field(default_factory=RequestUsage, init=False) def __aiter__(self) -> AsyncIterator[ModelResponseStreamEvent]:  """Stream the response as an async iterable of [`ModelResponseStreamEvent`][pydantic_ai.messages.ModelResponseStreamEvent]s.  This proxies the `_event_iterator()` and emits all events, while also checking for matches  on the result schema and emitting a [`FinalResultEvent`][pydantic_ai.messages.FinalResultEvent] if/when the  first match is found.  """ if self._event_iterator is None: async def iterator_with_final_event( iterator: AsyncIterator[ModelResponseStreamEvent], ) -> AsyncIterator[ModelResponseStreamEvent]: async for event in iterator: yield event if ( final_result_event := _get_final_result_event(event, self.model_request_parameters) ) is not None: self.final_result_event = final_result_event yield final_result_event break # If we broke out of the above loop, we need to yield the rest of the events # If we didn't, this will just be a no-op async for event in iterator: yield event async def iterator_with_part_end( iterator: AsyncIterator[ModelResponseStreamEvent], ) -> AsyncIterator[ModelResponseStreamEvent]: last_start_event: PartStartEvent | None = None def part_end_event(next_part: ModelResponsePart | None = None) -> PartEndEvent | None: if not last_start_event: return None index = last_start_event.index part = self._parts_manager.get_parts()[index] if not isinstance(part, TextPart | ThinkingPart | BaseToolCallPart): # Parts other than these 3 don't have deltas, so don't need an end part. return None return PartEndEvent( index=index, part=part, next_part_kind=next_part.part_kind if next_part else None, ) async for event in iterator: if isinstance(event, PartStartEvent): if last_start_event: end_event = part_end_event(event.part) if end_event: yield end_event event.previous_part_kind = last_start_event.part.part_kind last_start_event = event yield event end_event = part_end_event() if end_event: yield end_event self._event_iterator = iterator_with_part_end(iterator_with_final_event(self._get_event_iterator())) return self._event_iterator @abstractmethod async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]:  """Return an async iterator of [`ModelResponseStreamEvent`][pydantic_ai.messages.ModelResponseStreamEvent]s.  This method should be implemented by subclasses to translate the vendor-specific stream of events into  pydantic_ai-format events.  It should use the `_parts_manager` to handle deltas, and should update the `_usage` attributes as it goes.  """ raise NotImplementedError() # noinspection PyUnreachableCode yield def get(self) -> ModelResponse:  """Build a [`ModelResponse`][pydantic_ai.messages.ModelResponse] from the data received from the stream so far.""" return ModelResponse( parts=self._parts_manager.get_parts(), model_name=self.model_name, timestamp=self.timestamp, usage=self.usage(), provider_name=self.provider_name, provider_url=self.provider_url, provider_response_id=self.provider_response_id, provider_details=self.provider_details, finish_reason=self.finish_reason, ) # TODO (v2): Make this a property def usage(self) -> RequestUsage:  """Get the usage of the response so far. This will not be the final usage until the stream is exhausted.""" return self._usage @property @abstractmethod def model_name(self) -> str:  """Get the model name of the response.""" raise NotImplementedError() @property @abstractmethod def provider_name(self) -> str | None:  """Get the provider name.""" raise NotImplementedError() @property @abstractmethod def provider_url(self) -> str | None:  """Get the provider base URL.""" raise NotImplementedError() @property @abstractmethod def timestamp(self) -> datetime:  """Get the timestamp of the response.""" raise NotImplementedError() 

__aiter__

Stream the response as an async iterable of ModelResponseStreamEvents.

This proxies the _event_iterator() and emits all events, while also checking for matches on the result schema and emitting a FinalResultEvent if/when the first match is found.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
def __aiter__(self) -> AsyncIterator[ModelResponseStreamEvent]:  """Stream the response as an async iterable of [`ModelResponseStreamEvent`][pydantic_ai.messages.ModelResponseStreamEvent]s.  This proxies the `_event_iterator()` and emits all events, while also checking for matches  on the result schema and emitting a [`FinalResultEvent`][pydantic_ai.messages.FinalResultEvent] if/when the  first match is found.  """ if self._event_iterator is None: async def iterator_with_final_event( iterator: AsyncIterator[ModelResponseStreamEvent], ) -> AsyncIterator[ModelResponseStreamEvent]: async for event in iterator: yield event if ( final_result_event := _get_final_result_event(event, self.model_request_parameters) ) is not None: self.final_result_event = final_result_event yield final_result_event break # If we broke out of the above loop, we need to yield the rest of the events # If we didn't, this will just be a no-op async for event in iterator: yield event async def iterator_with_part_end( iterator: AsyncIterator[ModelResponseStreamEvent], ) -> AsyncIterator[ModelResponseStreamEvent]: last_start_event: PartStartEvent | None = None def part_end_event(next_part: ModelResponsePart | None = None) -> PartEndEvent | None: if not last_start_event: return None index = last_start_event.index part = self._parts_manager.get_parts()[index] if not isinstance(part, TextPart | ThinkingPart | BaseToolCallPart): # Parts other than these 3 don't have deltas, so don't need an end part. return None return PartEndEvent( index=index, part=part, next_part_kind=next_part.part_kind if next_part else None, ) async for event in iterator: if isinstance(event, PartStartEvent): if last_start_event: end_event = part_end_event(event.part) if end_event: yield end_event event.previous_part_kind = last_start_event.part.part_kind last_start_event = event yield event end_event = part_end_event() if end_event: yield end_event self._event_iterator = iterator_with_part_end(iterator_with_final_event(self._get_event_iterator())) return self._event_iterator 

get

get() -> ModelResponse 

Build a ModelResponse from the data received from the stream so far.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
946 947 948 949 950 951 952 953 954 955 956 957 958
def get(self) -> ModelResponse:  """Build a [`ModelResponse`][pydantic_ai.messages.ModelResponse] from the data received from the stream so far.""" return ModelResponse( parts=self._parts_manager.get_parts(), model_name=self.model_name, timestamp=self.timestamp, usage=self.usage(), provider_name=self.provider_name, provider_url=self.provider_url, provider_response_id=self.provider_response_id, provider_details=self.provider_details, finish_reason=self.finish_reason, ) 

usage

usage() -> RequestUsage 

Get the usage of the response so far. This will not be the final usage until the stream is exhausted.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
961 962 963
def usage(self) -> RequestUsage:  """Get the usage of the response so far. This will not be the final usage until the stream is exhausted.""" return self._usage 

model_name abstractmethod property

model_name: str 

Get the model name of the response.

provider_name abstractmethod property

provider_name: str | None 

Get the provider name.

provider_url abstractmethod property

provider_url: str | None 

Get the provider base URL.

timestamp abstractmethod property

timestamp: datetime 

Get the timestamp of the response.

ALLOW_MODEL_REQUESTS module-attribute

ALLOW_MODEL_REQUESTS = True 

Whether to allow requests to models.

This global setting allows you to disable request to most models, e.g. to make sure you don't accidentally make costly requests to a model during tests.

The testing models TestModel and FunctionModel are no affected by this setting.

check_allow_model_requests

check_allow_model_requests() -> None 

Check if model requests are allowed.

If you're defining your own models that have costs or latency associated with their use, you should call this in Model.request and Model.request_stream.

Raises:

Type Description
RuntimeError

If model requests are not allowed.

Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
def check_allow_model_requests() -> None:  """Check if model requests are allowed.  If you're defining your own models that have costs or latency associated with their use, you should call this in  [`Model.request`][pydantic_ai.models.Model.request] and [`Model.request_stream`][pydantic_ai.models.Model.request_stream].  Raises:  RuntimeError: If model requests are not allowed.  """ if not ALLOW_MODEL_REQUESTS: raise RuntimeError('Model requests are not allowed, since ALLOW_MODEL_REQUESTS is False') 

override_allow_model_requests

override_allow_model_requests( allow_model_requests: bool, ) -> Iterator[None] 

Context manager to temporarily override ALLOW_MODEL_REQUESTS.

Parameters:

Name Type Description Default
allow_model_requests bool

Whether to allow model requests within the context.

required
Source code in pydantic_ai_slim/pydantic_ai/models/__init__.py
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
@contextmanager def override_allow_model_requests(allow_model_requests: bool) -> Iterator[None]:  """Context manager to temporarily override [`ALLOW_MODEL_REQUESTS`][pydantic_ai.models.ALLOW_MODEL_REQUESTS].  Args:  allow_model_requests: Whether to allow model requests within the context.  """ global ALLOW_MODEL_REQUESTS old_value = ALLOW_MODEL_REQUESTS ALLOW_MODEL_REQUESTS = allow_model_requests # pyright: ignore[reportConstantRedefinition] try: yield finally: ALLOW_MODEL_REQUESTS = old_value # pyright: ignore[reportConstantRedefinition]