pydantic-ai-slim 1.2.0__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pydantic-ai-slim might be problematic. Click here for more details.
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/PKG-INFO +5 -5
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/__init__.py +2 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_agent_graph.py +31 -6
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/agent/__init__.py +8 -8
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/builtin_tools.py +35 -4
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/exceptions.py +5 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/mcp.py +1 -22
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/__init__.py +34 -34
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/anthropic.py +2 -2
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/bedrock.py +4 -4
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/cohere.py +0 -7
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/gemini.py +9 -2
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/google.py +5 -7
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/groq.py +4 -4
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/huggingface.py +2 -2
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/openai.py +53 -36
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/__init__.py +21 -12
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/bedrock.py +60 -16
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/gateway.py +60 -72
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/google.py +61 -23
- pydantic_ai_slim-1.3.0/pydantic_ai/providers/ovhcloud.py +95 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/usage.py +13 -2
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pyproject.toml +2 -2
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/.gitignore +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/LICENSE +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/README.md +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/__main__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_a2a.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_cli.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_function_schema.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_griffe.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_instrumentation.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_json_schema.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_mcp.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_otel_messages.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_output.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_parts_manager.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_run_context.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_system_prompt.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_thinking_part.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_tool_manager.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/_utils.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/ag_ui.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/agent/abstract.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/agent/wrapper.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/common_tools/__init__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/common_tools/duckduckgo.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/common_tools/tavily.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/direct.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/__init__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/dbos/__init__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/dbos/_agent.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/dbos/_mcp_server.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/dbos/_model.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/dbos/_utils.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/prefect/__init__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/prefect/_agent.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/prefect/_cache_policies.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/prefect/_function_toolset.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/prefect/_mcp_server.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/prefect/_model.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/prefect/_toolset.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/prefect/_types.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/temporal/__init__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/temporal/_function_toolset.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/temporal/_model.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/ext/__init__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/ext/aci.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/ext/langchain.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/format_prompt.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/messages.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/fallback.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/function.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/instrumented.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/mcp_sampling.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/mistral.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/test.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/models/wrapper.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/output.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/__init__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/amazon.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/anthropic.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/cohere.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/deepseek.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/google.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/grok.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/groq.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/harmony.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/meta.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/mistral.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/moonshotai.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/openai.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/profiles/qwen.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/anthropic.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/azure.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/cerebras.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/cohere.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/deepseek.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/fireworks.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/github.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/google_gla.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/google_vertex.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/grok.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/groq.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/heroku.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/huggingface.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/litellm.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/mistral.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/moonshotai.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/nebius.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/ollama.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/openai.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/openrouter.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/together.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/providers/vercel.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/py.typed +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/result.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/retries.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/run.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/settings.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/tools.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/__init__.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/_dynamic.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/abstract.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/approval_required.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/combined.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/external.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/filtered.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/function.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/prefixed.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/prepared.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/renamed.py +0 -0
- {pydantic_ai_slim-1.2.0 → pydantic_ai_slim-1.3.0}/pydantic_ai/toolsets/wrapper.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai-slim
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Agent Framework / shim to use Pydantic with LLMs, slim package
|
|
5
5
|
Project-URL: Homepage, https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim
|
|
6
6
|
Project-URL: Source, https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim
|
|
@@ -29,11 +29,11 @@ Classifier: Topic :: Internet
|
|
|
29
29
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
30
30
|
Requires-Python: >=3.10
|
|
31
31
|
Requires-Dist: exceptiongroup; python_version < '3.11'
|
|
32
|
-
Requires-Dist: genai-prices>=0.0.
|
|
32
|
+
Requires-Dist: genai-prices>=0.0.35
|
|
33
33
|
Requires-Dist: griffe>=1.3.2
|
|
34
34
|
Requires-Dist: httpx>=0.27
|
|
35
35
|
Requires-Dist: opentelemetry-api>=1.28.0
|
|
36
|
-
Requires-Dist: pydantic-graph==1.
|
|
36
|
+
Requires-Dist: pydantic-graph==1.3.0
|
|
37
37
|
Requires-Dist: pydantic>=2.10
|
|
38
38
|
Requires-Dist: typing-inspection>=0.4.0
|
|
39
39
|
Provides-Extra: a2a
|
|
@@ -57,9 +57,9 @@ Requires-Dist: dbos>=1.14.0; extra == 'dbos'
|
|
|
57
57
|
Provides-Extra: duckduckgo
|
|
58
58
|
Requires-Dist: ddgs>=9.0.0; extra == 'duckduckgo'
|
|
59
59
|
Provides-Extra: evals
|
|
60
|
-
Requires-Dist: pydantic-evals==1.
|
|
60
|
+
Requires-Dist: pydantic-evals==1.3.0; extra == 'evals'
|
|
61
61
|
Provides-Extra: google
|
|
62
|
-
Requires-Dist: google-genai>=1.
|
|
62
|
+
Requires-Dist: google-genai>=1.46.0; extra == 'google'
|
|
63
63
|
Provides-Extra: groq
|
|
64
64
|
Requires-Dist: groq>=0.25.0; extra == 'groq'
|
|
65
65
|
Provides-Extra: huggingface
|
|
@@ -22,6 +22,7 @@ from .exceptions import (
|
|
|
22
22
|
ApprovalRequired,
|
|
23
23
|
CallDeferred,
|
|
24
24
|
FallbackExceptionGroup,
|
|
25
|
+
IncompleteToolCall,
|
|
25
26
|
ModelHTTPError,
|
|
26
27
|
ModelRetry,
|
|
27
28
|
UnexpectedModelBehavior,
|
|
@@ -124,6 +125,7 @@ __all__ = (
|
|
|
124
125
|
'ModelRetry',
|
|
125
126
|
'ModelHTTPError',
|
|
126
127
|
'FallbackExceptionGroup',
|
|
128
|
+
'IncompleteToolCall',
|
|
127
129
|
'UnexpectedModelBehavior',
|
|
128
130
|
'UsageLimitExceeded',
|
|
129
131
|
'UserError',
|
|
@@ -92,9 +92,28 @@ class GraphAgentState:
|
|
|
92
92
|
retries: int = 0
|
|
93
93
|
run_step: int = 0
|
|
94
94
|
|
|
95
|
-
def increment_retries(
|
|
95
|
+
def increment_retries(
|
|
96
|
+
self,
|
|
97
|
+
max_result_retries: int,
|
|
98
|
+
error: BaseException | None = None,
|
|
99
|
+
model_settings: ModelSettings | None = None,
|
|
100
|
+
) -> None:
|
|
96
101
|
self.retries += 1
|
|
97
102
|
if self.retries > max_result_retries:
|
|
103
|
+
if (
|
|
104
|
+
self.message_history
|
|
105
|
+
and isinstance(model_response := self.message_history[-1], _messages.ModelResponse)
|
|
106
|
+
and model_response.finish_reason == 'length'
|
|
107
|
+
and model_response.parts
|
|
108
|
+
and isinstance(tool_call := model_response.parts[-1], _messages.ToolCallPart)
|
|
109
|
+
):
|
|
110
|
+
try:
|
|
111
|
+
tool_call.args_as_dict()
|
|
112
|
+
except Exception:
|
|
113
|
+
max_tokens = (model_settings or {}).get('max_tokens') if model_settings else None
|
|
114
|
+
raise exceptions.IncompleteToolCall(
|
|
115
|
+
f'Model token limit ({max_tokens if max_tokens is not None else "provider default"}) exceeded while emitting a tool call, resulting in incomplete arguments. Increase max tokens or simplify tool call arguments to fit within limit.'
|
|
116
|
+
)
|
|
98
117
|
message = f'Exceeded maximum retries ({max_result_retries}) for output validation'
|
|
99
118
|
if error:
|
|
100
119
|
if isinstance(error, exceptions.UnexpectedModelBehavior) and error.__cause__ is not None:
|
|
@@ -568,7 +587,7 @@ class CallToolsNode(AgentNode[DepsT, NodeRunEndT]):
|
|
|
568
587
|
# resubmit the most recent request that resulted in an empty response,
|
|
569
588
|
# as the empty response and request will not create any items in the API payload,
|
|
570
589
|
# in the hope the model will return a non-empty response this time.
|
|
571
|
-
ctx.state.increment_retries(ctx.deps.max_result_retries)
|
|
590
|
+
ctx.state.increment_retries(ctx.deps.max_result_retries, model_settings=ctx.deps.model_settings)
|
|
572
591
|
self._next_node = ModelRequestNode[DepsT, NodeRunEndT](_messages.ModelRequest(parts=[]))
|
|
573
592
|
return
|
|
574
593
|
|
|
@@ -630,7 +649,9 @@ class CallToolsNode(AgentNode[DepsT, NodeRunEndT]):
|
|
|
630
649
|
)
|
|
631
650
|
raise ToolRetryError(m)
|
|
632
651
|
except ToolRetryError as e:
|
|
633
|
-
ctx.state.increment_retries(
|
|
652
|
+
ctx.state.increment_retries(
|
|
653
|
+
ctx.deps.max_result_retries, error=e, model_settings=ctx.deps.model_settings
|
|
654
|
+
)
|
|
634
655
|
self._next_node = ModelRequestNode[DepsT, NodeRunEndT](_messages.ModelRequest(parts=[e.tool_retry]))
|
|
635
656
|
|
|
636
657
|
self._events_iterator = _run_stream()
|
|
@@ -788,10 +809,14 @@ async def process_tool_calls( # noqa: C901
|
|
|
788
809
|
try:
|
|
789
810
|
result_data = await tool_manager.handle_call(call)
|
|
790
811
|
except exceptions.UnexpectedModelBehavior as e:
|
|
791
|
-
ctx.state.increment_retries(
|
|
812
|
+
ctx.state.increment_retries(
|
|
813
|
+
ctx.deps.max_result_retries, error=e, model_settings=ctx.deps.model_settings
|
|
814
|
+
)
|
|
792
815
|
raise e # pragma: lax no cover
|
|
793
816
|
except ToolRetryError as e:
|
|
794
|
-
ctx.state.increment_retries(
|
|
817
|
+
ctx.state.increment_retries(
|
|
818
|
+
ctx.deps.max_result_retries, error=e, model_settings=ctx.deps.model_settings
|
|
819
|
+
)
|
|
795
820
|
yield _messages.FunctionToolCallEvent(call)
|
|
796
821
|
output_parts.append(e.tool_retry)
|
|
797
822
|
yield _messages.FunctionToolResultEvent(e.tool_retry)
|
|
@@ -820,7 +845,7 @@ async def process_tool_calls( # noqa: C901
|
|
|
820
845
|
|
|
821
846
|
# Then, we handle unknown tool calls
|
|
822
847
|
if tool_calls_by_kind['unknown']:
|
|
823
|
-
ctx.state.increment_retries(ctx.deps.max_result_retries)
|
|
848
|
+
ctx.state.increment_retries(ctx.deps.max_result_retries, model_settings=ctx.deps.model_settings)
|
|
824
849
|
calls_to_run.extend(tool_calls_by_kind['unknown'])
|
|
825
850
|
|
|
826
851
|
calls_to_run_results: dict[str, DeferredToolResult] = {}
|
|
@@ -662,14 +662,14 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
662
662
|
)
|
|
663
663
|
|
|
664
664
|
try:
|
|
665
|
-
async with
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
665
|
+
async with graph.iter(
|
|
666
|
+
start_node,
|
|
667
|
+
state=state,
|
|
668
|
+
deps=graph_deps,
|
|
669
|
+
span=use_span(run_span) if run_span.is_recording() else None,
|
|
670
|
+
infer_name=False,
|
|
671
|
+
) as graph_run:
|
|
672
|
+
async with toolset:
|
|
673
673
|
agent_run = AgentRun(graph_run)
|
|
674
674
|
yield agent_run
|
|
675
675
|
if (final_result := agent_run.result) is not None and run_span.is_recording():
|
|
@@ -2,13 +2,12 @@ from __future__ import annotations as _annotations
|
|
|
2
2
|
|
|
3
3
|
from abc import ABC
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Annotated, Any, Literal, Union
|
|
6
6
|
|
|
7
|
+
import pydantic
|
|
8
|
+
from pydantic_core import core_schema
|
|
7
9
|
from typing_extensions import TypedDict
|
|
8
10
|
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from .builtin_tools import AbstractBuiltinTool
|
|
11
|
-
|
|
12
11
|
__all__ = (
|
|
13
12
|
'AbstractBuiltinTool',
|
|
14
13
|
'WebSearchTool',
|
|
@@ -19,6 +18,8 @@ __all__ = (
|
|
|
19
18
|
'MemoryTool',
|
|
20
19
|
)
|
|
21
20
|
|
|
21
|
+
_BUILTIN_TOOL_TYPES: dict[str, type[AbstractBuiltinTool]] = {}
|
|
22
|
+
|
|
22
23
|
|
|
23
24
|
@dataclass(kw_only=True)
|
|
24
25
|
class AbstractBuiltinTool(ABC):
|
|
@@ -32,6 +33,26 @@ class AbstractBuiltinTool(ABC):
|
|
|
32
33
|
kind: str = 'unknown_builtin_tool'
|
|
33
34
|
"""Built-in tool identifier, this should be available on all built-in tools as a discriminator."""
|
|
34
35
|
|
|
36
|
+
def __init_subclass__(cls, **kwargs: Any) -> None:
|
|
37
|
+
super().__init_subclass__(**kwargs)
|
|
38
|
+
_BUILTIN_TOOL_TYPES[cls.kind] = cls
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def __get_pydantic_core_schema__(
|
|
42
|
+
cls, _source_type: Any, handler: pydantic.GetCoreSchemaHandler
|
|
43
|
+
) -> core_schema.CoreSchema:
|
|
44
|
+
if cls is not AbstractBuiltinTool:
|
|
45
|
+
return handler(cls)
|
|
46
|
+
|
|
47
|
+
tools = _BUILTIN_TOOL_TYPES.values()
|
|
48
|
+
if len(tools) == 1: # pragma: no cover
|
|
49
|
+
tools_type = next(iter(tools))
|
|
50
|
+
else:
|
|
51
|
+
tools_annotated = [Annotated[tool, pydantic.Tag(tool.kind)] for tool in tools]
|
|
52
|
+
tools_type = Annotated[Union[tuple(tools_annotated)], pydantic.Discriminator(_tool_discriminator)] # noqa: UP007
|
|
53
|
+
|
|
54
|
+
return handler(tools_type)
|
|
55
|
+
|
|
35
56
|
|
|
36
57
|
@dataclass(kw_only=True)
|
|
37
58
|
class WebSearchTool(AbstractBuiltinTool):
|
|
@@ -120,6 +141,7 @@ class WebSearchUserLocation(TypedDict, total=False):
|
|
|
120
141
|
"""The timezone of the user's location."""
|
|
121
142
|
|
|
122
143
|
|
|
144
|
+
@dataclass(kw_only=True)
|
|
123
145
|
class CodeExecutionTool(AbstractBuiltinTool):
|
|
124
146
|
"""A builtin tool that allows your agent to execute code.
|
|
125
147
|
|
|
@@ -134,6 +156,7 @@ class CodeExecutionTool(AbstractBuiltinTool):
|
|
|
134
156
|
"""The kind of tool."""
|
|
135
157
|
|
|
136
158
|
|
|
159
|
+
@dataclass(kw_only=True)
|
|
137
160
|
class UrlContextTool(AbstractBuiltinTool):
|
|
138
161
|
"""Allows your agent to access contents from URLs.
|
|
139
162
|
|
|
@@ -227,6 +250,7 @@ class ImageGenerationTool(AbstractBuiltinTool):
|
|
|
227
250
|
"""The kind of tool."""
|
|
228
251
|
|
|
229
252
|
|
|
253
|
+
@dataclass(kw_only=True)
|
|
230
254
|
class MemoryTool(AbstractBuiltinTool):
|
|
231
255
|
"""A builtin tool that allows your agent to use memory.
|
|
232
256
|
|
|
@@ -237,3 +261,10 @@ class MemoryTool(AbstractBuiltinTool):
|
|
|
237
261
|
|
|
238
262
|
kind: str = 'memory'
|
|
239
263
|
"""The kind of tool."""
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _tool_discriminator(tool_data: dict[str, Any] | AbstractBuiltinTool) -> str:
|
|
267
|
+
if isinstance(tool_data, dict):
|
|
268
|
+
return tool_data.get('kind', AbstractBuiltinTool.kind)
|
|
269
|
+
else:
|
|
270
|
+
return tool_data.kind
|
|
@@ -23,6 +23,7 @@ __all__ = (
|
|
|
23
23
|
'UnexpectedModelBehavior',
|
|
24
24
|
'UsageLimitExceeded',
|
|
25
25
|
'ModelHTTPError',
|
|
26
|
+
'IncompleteToolCall',
|
|
26
27
|
'FallbackExceptionGroup',
|
|
27
28
|
)
|
|
28
29
|
|
|
@@ -168,3 +169,7 @@ class ToolRetryError(Exception):
|
|
|
168
169
|
def __init__(self, tool_retry: RetryPromptPart):
|
|
169
170
|
self.tool_retry = tool_retry
|
|
170
171
|
super().__init__()
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class IncompleteToolCall(UnexpectedModelBehavior):
|
|
175
|
+
"""Error raised when a model stops due to token limit while emitting a tool call."""
|
|
@@ -441,14 +441,9 @@ class MCPServerStdio(MCPServer):
|
|
|
441
441
|
'uv', args=['run', 'mcp-run-python', 'stdio'], timeout=10
|
|
442
442
|
)
|
|
443
443
|
agent = Agent('openai:gpt-4o', toolsets=[server])
|
|
444
|
-
|
|
445
|
-
async def main():
|
|
446
|
-
async with agent: # (2)!
|
|
447
|
-
...
|
|
448
444
|
```
|
|
449
445
|
|
|
450
446
|
1. See [MCP Run Python](https://github.com/pydantic/mcp-run-python) for more information.
|
|
451
|
-
2. This will start the server as a subprocess and connect to it.
|
|
452
447
|
"""
|
|
453
448
|
|
|
454
449
|
command: str
|
|
@@ -788,13 +783,7 @@ class MCPServerSSE(_MCPServerHTTP):
|
|
|
788
783
|
|
|
789
784
|
server = MCPServerSSE('http://localhost:3001/sse')
|
|
790
785
|
agent = Agent('openai:gpt-4o', toolsets=[server])
|
|
791
|
-
|
|
792
|
-
async def main():
|
|
793
|
-
async with agent: # (1)!
|
|
794
|
-
...
|
|
795
786
|
```
|
|
796
|
-
|
|
797
|
-
1. This will connect to a server running on `localhost:3001`.
|
|
798
787
|
"""
|
|
799
788
|
|
|
800
789
|
@classmethod
|
|
@@ -837,13 +826,7 @@ class MCPServerHTTP(MCPServerSSE):
|
|
|
837
826
|
|
|
838
827
|
server = MCPServerHTTP('http://localhost:3001/sse')
|
|
839
828
|
agent = Agent('openai:gpt-4o', toolsets=[server])
|
|
840
|
-
|
|
841
|
-
async def main():
|
|
842
|
-
async with agent: # (2)!
|
|
843
|
-
...
|
|
844
829
|
```
|
|
845
|
-
|
|
846
|
-
1. This will connect to a server running on `localhost:3001`.
|
|
847
830
|
"""
|
|
848
831
|
|
|
849
832
|
|
|
@@ -862,12 +845,8 @@ class MCPServerStreamableHTTP(_MCPServerHTTP):
|
|
|
862
845
|
from pydantic_ai import Agent
|
|
863
846
|
from pydantic_ai.mcp import MCPServerStreamableHTTP
|
|
864
847
|
|
|
865
|
-
server = MCPServerStreamableHTTP('http://localhost:8000/mcp')
|
|
848
|
+
server = MCPServerStreamableHTTP('http://localhost:8000/mcp')
|
|
866
849
|
agent = Agent('openai:gpt-4o', toolsets=[server])
|
|
867
|
-
|
|
868
|
-
async def main():
|
|
869
|
-
async with agent: # (2)!
|
|
870
|
-
...
|
|
871
850
|
```
|
|
872
851
|
"""
|
|
873
852
|
|
|
@@ -43,6 +43,7 @@ from ..messages import (
|
|
|
43
43
|
)
|
|
44
44
|
from ..output import OutputMode
|
|
45
45
|
from ..profiles import DEFAULT_PROFILE, ModelProfile, ModelProfileSpec
|
|
46
|
+
from ..providers import infer_provider
|
|
46
47
|
from ..settings import ModelSettings, merge_model_settings
|
|
47
48
|
from ..tools import ToolDefinition
|
|
48
49
|
from ..usage import RequestUsage
|
|
@@ -129,15 +130,8 @@ KnownModelName = TypeAliasType(
|
|
|
129
130
|
'cerebras:qwen-3-235b-a22b-thinking-2507',
|
|
130
131
|
'cohere:c4ai-aya-expanse-32b',
|
|
131
132
|
'cohere:c4ai-aya-expanse-8b',
|
|
132
|
-
'cohere:command',
|
|
133
|
-
'cohere:command-light',
|
|
134
|
-
'cohere:command-light-nightly',
|
|
135
133
|
'cohere:command-nightly',
|
|
136
|
-
'cohere:command-r',
|
|
137
|
-
'cohere:command-r-03-2024',
|
|
138
134
|
'cohere:command-r-08-2024',
|
|
139
|
-
'cohere:command-r-plus',
|
|
140
|
-
'cohere:command-r-plus-04-2024',
|
|
141
135
|
'cohere:command-r-plus-08-2024',
|
|
142
136
|
'cohere:command-r7b-12-2024',
|
|
143
137
|
'deepseek:deepseek-chat',
|
|
@@ -644,41 +638,39 @@ def infer_model(model: Model | KnownModelName | str) -> Model: # noqa: C901
|
|
|
644
638
|
return TestModel()
|
|
645
639
|
|
|
646
640
|
try:
|
|
647
|
-
|
|
641
|
+
provider_name, model_name = model.split(':', maxsplit=1)
|
|
648
642
|
except ValueError:
|
|
649
|
-
|
|
643
|
+
provider_name = None
|
|
650
644
|
model_name = model
|
|
651
645
|
if model_name.startswith(('gpt', 'o1', 'o3')):
|
|
652
|
-
|
|
646
|
+
provider_name = 'openai'
|
|
653
647
|
elif model_name.startswith('claude'):
|
|
654
|
-
|
|
648
|
+
provider_name = 'anthropic'
|
|
655
649
|
elif model_name.startswith('gemini'):
|
|
656
|
-
|
|
650
|
+
provider_name = 'google-gla'
|
|
657
651
|
|
|
658
|
-
if
|
|
652
|
+
if provider_name is not None:
|
|
659
653
|
warnings.warn(
|
|
660
|
-
f"Specifying a model name without a provider prefix is deprecated. Instead of {model_name!r}, use '{
|
|
654
|
+
f"Specifying a model name without a provider prefix is deprecated. Instead of {model_name!r}, use '{provider_name}:{model_name}'.",
|
|
661
655
|
DeprecationWarning,
|
|
662
656
|
)
|
|
663
657
|
else:
|
|
664
658
|
raise UserError(f'Unknown model: {model}')
|
|
665
659
|
|
|
666
|
-
if
|
|
660
|
+
if provider_name == 'vertexai': # pragma: no cover
|
|
667
661
|
warnings.warn(
|
|
668
662
|
"The 'vertexai' provider name is deprecated. Use 'google-vertex' instead.",
|
|
669
663
|
DeprecationWarning,
|
|
670
664
|
)
|
|
671
|
-
|
|
665
|
+
provider_name = 'google-vertex'
|
|
672
666
|
|
|
673
|
-
|
|
674
|
-
from ..providers.gateway import infer_model as infer_model_from_gateway
|
|
667
|
+
provider = infer_provider(provider_name)
|
|
675
668
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
elif provider in (
|
|
669
|
+
model_kind = provider_name
|
|
670
|
+
if model_kind.startswith('gateway/'):
|
|
671
|
+
model_kind = provider_name.removeprefix('gateway/')
|
|
672
|
+
if model_kind in (
|
|
673
|
+
'openai',
|
|
682
674
|
'azure',
|
|
683
675
|
'deepseek',
|
|
684
676
|
'cerebras',
|
|
@@ -688,42 +680,50 @@ def infer_model(model: Model | KnownModelName | str) -> Model: # noqa: C901
|
|
|
688
680
|
'heroku',
|
|
689
681
|
'moonshotai',
|
|
690
682
|
'ollama',
|
|
691
|
-
'openai',
|
|
692
|
-
'openai-chat',
|
|
693
683
|
'openrouter',
|
|
694
684
|
'together',
|
|
695
685
|
'vercel',
|
|
696
686
|
'litellm',
|
|
697
687
|
'nebius',
|
|
688
|
+
'ovhcloud',
|
|
698
689
|
):
|
|
690
|
+
model_kind = 'openai-chat'
|
|
691
|
+
elif model_kind in ('google-gla', 'google-vertex'):
|
|
692
|
+
model_kind = 'google'
|
|
693
|
+
|
|
694
|
+
if model_kind == 'openai-chat':
|
|
699
695
|
from .openai import OpenAIChatModel
|
|
700
696
|
|
|
701
697
|
return OpenAIChatModel(model_name, provider=provider)
|
|
702
|
-
elif
|
|
698
|
+
elif model_kind == 'openai-responses':
|
|
703
699
|
from .openai import OpenAIResponsesModel
|
|
704
700
|
|
|
705
|
-
return OpenAIResponsesModel(model_name, provider=
|
|
706
|
-
elif
|
|
701
|
+
return OpenAIResponsesModel(model_name, provider=provider)
|
|
702
|
+
elif model_kind == 'google':
|
|
707
703
|
from .google import GoogleModel
|
|
708
704
|
|
|
709
705
|
return GoogleModel(model_name, provider=provider)
|
|
710
|
-
elif
|
|
706
|
+
elif model_kind == 'groq':
|
|
711
707
|
from .groq import GroqModel
|
|
712
708
|
|
|
713
709
|
return GroqModel(model_name, provider=provider)
|
|
714
|
-
elif
|
|
710
|
+
elif model_kind == 'cohere':
|
|
711
|
+
from .cohere import CohereModel
|
|
712
|
+
|
|
713
|
+
return CohereModel(model_name, provider=provider)
|
|
714
|
+
elif model_kind == 'mistral':
|
|
715
715
|
from .mistral import MistralModel
|
|
716
716
|
|
|
717
717
|
return MistralModel(model_name, provider=provider)
|
|
718
|
-
elif
|
|
718
|
+
elif model_kind == 'anthropic':
|
|
719
719
|
from .anthropic import AnthropicModel
|
|
720
720
|
|
|
721
721
|
return AnthropicModel(model_name, provider=provider)
|
|
722
|
-
elif
|
|
722
|
+
elif model_kind == 'bedrock':
|
|
723
723
|
from .bedrock import BedrockConverseModel
|
|
724
724
|
|
|
725
725
|
return BedrockConverseModel(model_name, provider=provider)
|
|
726
|
-
elif
|
|
726
|
+
elif model_kind == 'huggingface':
|
|
727
727
|
from .huggingface import HuggingFaceModel
|
|
728
728
|
|
|
729
729
|
return HuggingFaceModel(model_name, provider=provider)
|
|
@@ -162,7 +162,7 @@ class AnthropicModel(Model):
|
|
|
162
162
|
self,
|
|
163
163
|
model_name: AnthropicModelName,
|
|
164
164
|
*,
|
|
165
|
-
provider: Literal['anthropic'] | Provider[AsyncAnthropicClient] = 'anthropic',
|
|
165
|
+
provider: Literal['anthropic', 'gateway'] | Provider[AsyncAnthropicClient] = 'anthropic',
|
|
166
166
|
profile: ModelProfileSpec | None = None,
|
|
167
167
|
settings: ModelSettings | None = None,
|
|
168
168
|
):
|
|
@@ -179,7 +179,7 @@ class AnthropicModel(Model):
|
|
|
179
179
|
self._model_name = model_name
|
|
180
180
|
|
|
181
181
|
if isinstance(provider, str):
|
|
182
|
-
provider = infer_provider(provider)
|
|
182
|
+
provider = infer_provider('gateway/anthropic' if provider == 'gateway' else provider)
|
|
183
183
|
self._provider = provider
|
|
184
184
|
self.client = provider.client
|
|
185
185
|
|
|
@@ -207,7 +207,7 @@ class BedrockConverseModel(Model):
|
|
|
207
207
|
self,
|
|
208
208
|
model_name: BedrockModelName,
|
|
209
209
|
*,
|
|
210
|
-
provider: Literal['bedrock'] | Provider[BaseClient] = 'bedrock',
|
|
210
|
+
provider: Literal['bedrock', 'gateway'] | Provider[BaseClient] = 'bedrock',
|
|
211
211
|
profile: ModelProfileSpec | None = None,
|
|
212
212
|
settings: ModelSettings | None = None,
|
|
213
213
|
):
|
|
@@ -226,7 +226,7 @@ class BedrockConverseModel(Model):
|
|
|
226
226
|
self._model_name = model_name
|
|
227
227
|
|
|
228
228
|
if isinstance(provider, str):
|
|
229
|
-
provider = infer_provider(provider)
|
|
229
|
+
provider = infer_provider('gateway/bedrock' if provider == 'gateway' else provider)
|
|
230
230
|
self._provider = provider
|
|
231
231
|
self.client = cast('BedrockRuntimeClient', provider.client)
|
|
232
232
|
|
|
@@ -701,8 +701,8 @@ class BedrockStreamedResponse(StreamedResponse):
|
|
|
701
701
|
signature=signature,
|
|
702
702
|
provider_name=self.provider_name if signature else None,
|
|
703
703
|
)
|
|
704
|
-
if
|
|
705
|
-
maybe_event = self._parts_manager.handle_text_delta(vendor_part_id=index, content=
|
|
704
|
+
if text := delta.get('text'):
|
|
705
|
+
maybe_event = self._parts_manager.handle_text_delta(vendor_part_id=index, content=text)
|
|
706
706
|
if maybe_event is not None: # pragma: no branch
|
|
707
707
|
yield maybe_event
|
|
708
708
|
if 'toolUse' in delta:
|
|
@@ -62,15 +62,8 @@ except ImportError as _import_error:
|
|
|
62
62
|
LatestCohereModelNames = Literal[
|
|
63
63
|
'c4ai-aya-expanse-32b',
|
|
64
64
|
'c4ai-aya-expanse-8b',
|
|
65
|
-
'command',
|
|
66
|
-
'command-light',
|
|
67
|
-
'command-light-nightly',
|
|
68
65
|
'command-nightly',
|
|
69
|
-
'command-r',
|
|
70
|
-
'command-r-03-2024',
|
|
71
66
|
'command-r-08-2024',
|
|
72
|
-
'command-r-plus',
|
|
73
|
-
'command-r-plus-04-2024',
|
|
74
67
|
'command-r-plus-08-2024',
|
|
75
68
|
'command-r7b-12-2024',
|
|
76
69
|
]
|
|
@@ -38,7 +38,7 @@ from ..messages import (
|
|
|
38
38
|
VideoUrl,
|
|
39
39
|
)
|
|
40
40
|
from ..profiles import ModelProfileSpec
|
|
41
|
-
from ..providers import Provider
|
|
41
|
+
from ..providers import Provider
|
|
42
42
|
from ..settings import ModelSettings
|
|
43
43
|
from ..tools import ToolDefinition
|
|
44
44
|
from . import Model, ModelRequestParameters, StreamedResponse, check_allow_model_requests, download_item, get_user_agent
|
|
@@ -131,7 +131,14 @@ class GeminiModel(Model):
|
|
|
131
131
|
self._model_name = model_name
|
|
132
132
|
|
|
133
133
|
if isinstance(provider, str):
|
|
134
|
-
provider
|
|
134
|
+
if provider == 'google-gla':
|
|
135
|
+
from pydantic_ai.providers.google_gla import GoogleGLAProvider # type: ignore[reportDeprecated]
|
|
136
|
+
|
|
137
|
+
provider = GoogleGLAProvider() # type: ignore[reportDeprecated]
|
|
138
|
+
else:
|
|
139
|
+
from pydantic_ai.providers.google_vertex import GoogleVertexProvider # type: ignore[reportDeprecated]
|
|
140
|
+
|
|
141
|
+
provider = GoogleVertexProvider() # type: ignore[reportDeprecated]
|
|
135
142
|
self._provider = provider
|
|
136
143
|
self.client = provider.client
|
|
137
144
|
self._url = str(self.client.base_url)
|
|
@@ -37,7 +37,7 @@ from ..messages import (
|
|
|
37
37
|
VideoUrl,
|
|
38
38
|
)
|
|
39
39
|
from ..profiles import ModelProfileSpec
|
|
40
|
-
from ..providers import Provider
|
|
40
|
+
from ..providers import Provider, infer_provider
|
|
41
41
|
from ..settings import ModelSettings
|
|
42
42
|
from ..tools import ToolDefinition
|
|
43
43
|
from . import (
|
|
@@ -85,8 +85,6 @@ try:
|
|
|
85
85
|
UrlContextDict,
|
|
86
86
|
VideoMetadataDict,
|
|
87
87
|
)
|
|
88
|
-
|
|
89
|
-
from ..providers.google import GoogleProvider
|
|
90
88
|
except ImportError as _import_error:
|
|
91
89
|
raise ImportError(
|
|
92
90
|
'Please install `google-genai` to use the Google model, '
|
|
@@ -187,7 +185,7 @@ class GoogleModel(Model):
|
|
|
187
185
|
self,
|
|
188
186
|
model_name: GoogleModelName,
|
|
189
187
|
*,
|
|
190
|
-
provider: Literal['google-gla', 'google-vertex'] | Provider[Client] = 'google-gla',
|
|
188
|
+
provider: Literal['google-gla', 'google-vertex', 'gateway'] | Provider[Client] = 'google-gla',
|
|
191
189
|
profile: ModelProfileSpec | None = None,
|
|
192
190
|
settings: ModelSettings | None = None,
|
|
193
191
|
):
|
|
@@ -196,15 +194,15 @@ class GoogleModel(Model):
|
|
|
196
194
|
Args:
|
|
197
195
|
model_name: The name of the model to use.
|
|
198
196
|
provider: The provider to use for authentication and API access. Can be either the string
|
|
199
|
-
'google-gla' or 'google-vertex' or an instance of `Provider[
|
|
200
|
-
|
|
197
|
+
'google-gla' or 'google-vertex' or an instance of `Provider[google.genai.AsyncClient]`.
|
|
198
|
+
Defaults to 'google-gla'.
|
|
201
199
|
profile: The model profile to use. Defaults to a profile picked by the provider based on the model name.
|
|
202
200
|
settings: The model settings to use. Defaults to None.
|
|
203
201
|
"""
|
|
204
202
|
self._model_name = model_name
|
|
205
203
|
|
|
206
204
|
if isinstance(provider, str):
|
|
207
|
-
provider =
|
|
205
|
+
provider = infer_provider('gateway/google-vertex' if provider == 'gateway' else provider)
|
|
208
206
|
self._provider = provider
|
|
209
207
|
self.client = provider.client
|
|
210
208
|
|
|
@@ -141,7 +141,7 @@ class GroqModel(Model):
|
|
|
141
141
|
self,
|
|
142
142
|
model_name: GroqModelName,
|
|
143
143
|
*,
|
|
144
|
-
provider: Literal['groq'] | Provider[AsyncGroq] = 'groq',
|
|
144
|
+
provider: Literal['groq', 'gateway'] | Provider[AsyncGroq] = 'groq',
|
|
145
145
|
profile: ModelProfileSpec | None = None,
|
|
146
146
|
settings: ModelSettings | None = None,
|
|
147
147
|
):
|
|
@@ -159,7 +159,7 @@ class GroqModel(Model):
|
|
|
159
159
|
self._model_name = model_name
|
|
160
160
|
|
|
161
161
|
if isinstance(provider, str):
|
|
162
|
-
provider = infer_provider(provider)
|
|
162
|
+
provider = infer_provider('gateway/groq' if provider == 'gateway' else provider)
|
|
163
163
|
self._provider = provider
|
|
164
164
|
self.client = provider.client
|
|
165
165
|
|
|
@@ -330,7 +330,7 @@ class GroqModel(Model):
|
|
|
330
330
|
if call_part and return_part: # pragma: no branch
|
|
331
331
|
items.append(call_part)
|
|
332
332
|
items.append(return_part)
|
|
333
|
-
if choice.message.content
|
|
333
|
+
if choice.message.content:
|
|
334
334
|
# NOTE: The `<think>` tag is only present if `groq_reasoning_format` is set to `raw`.
|
|
335
335
|
items.extend(split_content_into_text_and_thinking(choice.message.content, self.profile.thinking_tags))
|
|
336
336
|
if choice.message.tool_calls is not None:
|
|
@@ -563,7 +563,7 @@ class GroqStreamedResponse(StreamedResponse):
|
|
|
563
563
|
|
|
564
564
|
# Handle the text part of the response
|
|
565
565
|
content = choice.delta.content
|
|
566
|
-
if content
|
|
566
|
+
if content:
|
|
567
567
|
maybe_event = self._parts_manager.handle_text_delta(
|
|
568
568
|
vendor_part_id='content',
|
|
569
569
|
content=content,
|
|
@@ -277,7 +277,7 @@ class HuggingFaceModel(Model):
|
|
|
277
277
|
|
|
278
278
|
items: list[ModelResponsePart] = []
|
|
279
279
|
|
|
280
|
-
if content
|
|
280
|
+
if content:
|
|
281
281
|
items.extend(split_content_into_text_and_thinking(content, self.profile.thinking_tags))
|
|
282
282
|
if tool_calls is not None:
|
|
283
283
|
for c in tool_calls:
|
|
@@ -482,7 +482,7 @@ class HuggingFaceStreamedResponse(StreamedResponse):
|
|
|
482
482
|
|
|
483
483
|
# Handle the text part of the response
|
|
484
484
|
content = choice.delta.content
|
|
485
|
-
if content
|
|
485
|
+
if content:
|
|
486
486
|
maybe_event = self._parts_manager.handle_text_delta(
|
|
487
487
|
vendor_part_id='content',
|
|
488
488
|
content=content,
|