pydantic-ai-slim 1.0.10__tar.gz → 1.0.11__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.0.10 → pydantic_ai_slim-1.0.11}/PKG-INFO +6 -6
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_function_schema.py +18 -10
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_output.py +1 -8
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/mcp.py +1 -1
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/messages.py +2 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/__init__.py +2 -81
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/anthropic.py +15 -9
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/instrumented.py +27 -11
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/openai.py +39 -7
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/output.py +12 -1
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/harmony.py +3 -1
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/ollama.py +2 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pyproject.toml +3 -3
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/.gitignore +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/LICENSE +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/README.md +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/__main__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_a2a.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_agent_graph.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_cli.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_griffe.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_mcp.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_otel_messages.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_parts_manager.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_run_context.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_system_prompt.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_thinking_part.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_tool_manager.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/_utils.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/ag_ui.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/agent/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/agent/abstract.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/agent/wrapper.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/builtin_tools.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/common_tools/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/common_tools/duckduckgo.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/common_tools/tavily.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/direct.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/dbos/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/dbos/_agent.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/dbos/_mcp_server.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/dbos/_model.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/dbos/_utils.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_function_toolset.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_model.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/exceptions.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/ext/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/ext/aci.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/ext/langchain.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/format_prompt.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/bedrock.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/cohere.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/fallback.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/function.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/gemini.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/google.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/groq.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/huggingface.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/mcp_sampling.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/mistral.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/test.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/models/wrapper.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/_json_schema.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/amazon.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/anthropic.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/cohere.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/deepseek.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/google.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/grok.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/groq.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/meta.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/mistral.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/moonshotai.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/openai.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/profiles/qwen.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/anthropic.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/azure.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/bedrock.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/cerebras.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/cohere.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/deepseek.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/fireworks.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/gateway.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/github.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/google.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/google_gla.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/google_vertex.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/grok.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/groq.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/heroku.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/huggingface.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/litellm.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/mistral.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/moonshotai.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/openai.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/openrouter.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/together.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/providers/vercel.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/py.typed +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/result.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/retries.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/run.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/settings.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/tools.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/__init__.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/_dynamic.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/abstract.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/approval_required.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/combined.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/external.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/filtered.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/function.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/prefixed.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/prepared.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/renamed.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/wrapper.py +0 -0
- {pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/usage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai-slim
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.11
|
|
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.28
|
|
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.0.
|
|
36
|
+
Requires-Dist: pydantic-graph==1.0.11
|
|
37
37
|
Requires-Dist: pydantic>=2.10
|
|
38
38
|
Requires-Dist: typing-inspection>=0.4.0
|
|
39
39
|
Provides-Extra: a2a
|
|
@@ -42,7 +42,7 @@ Provides-Extra: ag-ui
|
|
|
42
42
|
Requires-Dist: ag-ui-protocol>=0.1.8; extra == 'ag-ui'
|
|
43
43
|
Requires-Dist: starlette>=0.45.3; extra == 'ag-ui'
|
|
44
44
|
Provides-Extra: anthropic
|
|
45
|
-
Requires-Dist: anthropic>=0.
|
|
45
|
+
Requires-Dist: anthropic>=0.69.0; extra == 'anthropic'
|
|
46
46
|
Provides-Extra: bedrock
|
|
47
47
|
Requires-Dist: boto3>=1.39.0; extra == 'bedrock'
|
|
48
48
|
Provides-Extra: cli
|
|
@@ -57,7 +57,7 @@ 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.0.
|
|
60
|
+
Requires-Dist: pydantic-evals==1.0.11; extra == 'evals'
|
|
61
61
|
Provides-Extra: google
|
|
62
62
|
Requires-Dist: google-genai>=1.31.0; extra == 'google'
|
|
63
63
|
Provides-Extra: groq
|
|
@@ -77,7 +77,7 @@ Requires-Dist: tenacity>=8.2.3; extra == 'retries'
|
|
|
77
77
|
Provides-Extra: tavily
|
|
78
78
|
Requires-Dist: tavily-python>=0.5.0; extra == 'tavily'
|
|
79
79
|
Provides-Extra: temporal
|
|
80
|
-
Requires-Dist: temporalio==1.
|
|
80
|
+
Requires-Dist: temporalio==1.18.0; extra == 'temporal'
|
|
81
81
|
Provides-Extra: vertexai
|
|
82
82
|
Requires-Dist: google-auth>=2.36.0; extra == 'vertexai'
|
|
83
83
|
Requires-Dist: requests>=2.32.2; extra == 'vertexai'
|
|
@@ -231,31 +231,39 @@ R = TypeVar('R')
|
|
|
231
231
|
|
|
232
232
|
WithCtx = Callable[Concatenate[RunContext[Any], P], R]
|
|
233
233
|
WithoutCtx = Callable[P, R]
|
|
234
|
-
|
|
234
|
+
TargetCallable = WithCtx[P, R] | WithoutCtx[P, R]
|
|
235
235
|
|
|
236
236
|
|
|
237
|
-
def _takes_ctx(
|
|
238
|
-
"""Check if a
|
|
237
|
+
def _takes_ctx(callable_obj: TargetCallable[P, R]) -> TypeIs[WithCtx[P, R]]:
|
|
238
|
+
"""Check if a callable takes a `RunContext` first argument.
|
|
239
239
|
|
|
240
240
|
Args:
|
|
241
|
-
|
|
241
|
+
callable_obj: The callable to check.
|
|
242
242
|
|
|
243
243
|
Returns:
|
|
244
|
-
`True` if the
|
|
244
|
+
`True` if the callable takes a `RunContext` as first argument, `False` otherwise.
|
|
245
245
|
"""
|
|
246
246
|
try:
|
|
247
|
-
sig = signature(
|
|
248
|
-
except ValueError:
|
|
249
|
-
return False
|
|
247
|
+
sig = signature(callable_obj)
|
|
248
|
+
except ValueError:
|
|
249
|
+
return False
|
|
250
250
|
try:
|
|
251
251
|
first_param_name = next(iter(sig.parameters.keys()))
|
|
252
252
|
except StopIteration:
|
|
253
253
|
return False
|
|
254
254
|
else:
|
|
255
|
-
|
|
255
|
+
# See https://github.com/pydantic/pydantic/pull/11451 for a similar implementation in Pydantic
|
|
256
|
+
if not isinstance(callable_obj, _decorators._function_like): # pyright: ignore[reportPrivateUsage]
|
|
257
|
+
call_func = getattr(type(callable_obj), '__call__', None)
|
|
258
|
+
if call_func is not None:
|
|
259
|
+
callable_obj = call_func
|
|
260
|
+
else:
|
|
261
|
+
return False # pragma: no cover
|
|
262
|
+
|
|
263
|
+
type_hints = _typing_extra.get_function_type_hints(_decorators.unwrap_wrapped_function(callable_obj))
|
|
256
264
|
annotation = type_hints.get(first_param_name)
|
|
257
265
|
if annotation is None:
|
|
258
|
-
return False
|
|
266
|
+
return False
|
|
259
267
|
return True is not sig.empty and _is_call_ctx(annotation)
|
|
260
268
|
|
|
261
269
|
|
|
@@ -19,6 +19,7 @@ from .output import (
|
|
|
19
19
|
NativeOutput,
|
|
20
20
|
OutputDataT,
|
|
21
21
|
OutputMode,
|
|
22
|
+
OutputObjectDefinition,
|
|
22
23
|
OutputSpec,
|
|
23
24
|
OutputTypeOrFunction,
|
|
24
25
|
PromptedOutput,
|
|
@@ -581,14 +582,6 @@ class ToolOrTextOutputSchema(ToolOutputSchema[OutputDataT], PlainTextOutputSchem
|
|
|
581
582
|
return 'tool_or_text'
|
|
582
583
|
|
|
583
584
|
|
|
584
|
-
@dataclass
|
|
585
|
-
class OutputObjectDefinition:
|
|
586
|
-
json_schema: ObjectJsonSchema
|
|
587
|
-
name: str | None = None
|
|
588
|
-
description: str | None = None
|
|
589
|
-
strict: bool | None = None
|
|
590
|
-
|
|
591
|
-
|
|
592
585
|
@dataclass(init=False)
|
|
593
586
|
class BaseOutputProcessor(ABC, Generic[OutputDataT]):
|
|
594
587
|
@abstractmethod
|
|
@@ -540,7 +540,7 @@ class MCPServerStdio(MCPServer):
|
|
|
540
540
|
f'args={self.args!r}',
|
|
541
541
|
]
|
|
542
542
|
if self.id:
|
|
543
|
-
repr_args.append(f'id={self.id!r}')
|
|
543
|
+
repr_args.append(f'id={self.id!r}') # pragma: lax no cover
|
|
544
544
|
return f'{self.__class__.__name__}({", ".join(repr_args)})'
|
|
545
545
|
|
|
546
546
|
def __eq__(self, value: object, /) -> bool:
|
|
@@ -126,6 +126,7 @@ class FileUrl(ABC):
|
|
|
126
126
|
|
|
127
127
|
Supported by:
|
|
128
128
|
- `GoogleModel`: `VideoUrl.vendor_metadata` is used as `video_metadata`: https://ai.google.dev/gemini-api/docs/video-understanding#customize-video-processing
|
|
129
|
+
- `OpenAIChatModel`, `OpenAIResponsesModel`: `ImageUrl.vendor_metadata['detail']` is used as `detail` setting for images
|
|
129
130
|
"""
|
|
130
131
|
|
|
131
132
|
_media_type: Annotated[str | None, pydantic.Field(alias='media_type', default=None, exclude=True)] = field(
|
|
@@ -471,6 +472,7 @@ class BinaryContent:
|
|
|
471
472
|
|
|
472
473
|
Supported by:
|
|
473
474
|
- `GoogleModel`: `BinaryContent.vendor_metadata` is used as `video_metadata`: https://ai.google.dev/gemini-api/docs/video-understanding#customize-video-processing
|
|
475
|
+
- `OpenAIChatModel`, `OpenAIResponsesModel`: `BinaryContent.vendor_metadata['detail']` is used as `detail` setting for images
|
|
474
476
|
"""
|
|
475
477
|
|
|
476
478
|
kind: Literal['binary'] = 'binary'
|
|
@@ -65,6 +65,8 @@ KnownModelName = TypeAliasType(
|
|
|
65
65
|
'anthropic:claude-opus-4-20250514',
|
|
66
66
|
'anthropic:claude-sonnet-4-0',
|
|
67
67
|
'anthropic:claude-sonnet-4-20250514',
|
|
68
|
+
'anthropic:claude-sonnet-4-5',
|
|
69
|
+
'anthropic:claude-sonnet-4-5-20250929',
|
|
68
70
|
'bedrock:amazon.titan-tg1-large',
|
|
69
71
|
'bedrock:amazon.titan-text-lite-v1',
|
|
70
72
|
'bedrock:amazon.titan-text-express-v1',
|
|
@@ -121,23 +123,6 @@ KnownModelName = TypeAliasType(
|
|
|
121
123
|
'cerebras:qwen-3-32b',
|
|
122
124
|
'cerebras:qwen-3-coder-480b',
|
|
123
125
|
'cerebras:qwen-3-235b-a22b-thinking-2507',
|
|
124
|
-
'claude-3-5-haiku-20241022',
|
|
125
|
-
'claude-3-5-haiku-latest',
|
|
126
|
-
'claude-3-5-sonnet-20240620',
|
|
127
|
-
'claude-3-5-sonnet-20241022',
|
|
128
|
-
'claude-3-5-sonnet-latest',
|
|
129
|
-
'claude-3-7-sonnet-20250219',
|
|
130
|
-
'claude-3-7-sonnet-latest',
|
|
131
|
-
'claude-3-haiku-20240307',
|
|
132
|
-
'claude-3-opus-20240229',
|
|
133
|
-
'claude-3-opus-latest',
|
|
134
|
-
'claude-4-opus-20250514',
|
|
135
|
-
'claude-4-sonnet-20250514',
|
|
136
|
-
'claude-opus-4-0',
|
|
137
|
-
'claude-opus-4-1-20250805',
|
|
138
|
-
'claude-opus-4-20250514',
|
|
139
|
-
'claude-sonnet-4-0',
|
|
140
|
-
'claude-sonnet-4-20250514',
|
|
141
126
|
'cohere:c4ai-aya-expanse-32b',
|
|
142
127
|
'cohere:c4ai-aya-expanse-8b',
|
|
143
128
|
'cohere:command',
|
|
@@ -163,54 +148,6 @@ KnownModelName = TypeAliasType(
|
|
|
163
148
|
'google-vertex:gemini-2.5-flash',
|
|
164
149
|
'google-vertex:gemini-2.5-flash-lite',
|
|
165
150
|
'google-vertex:gemini-2.5-pro',
|
|
166
|
-
'gpt-3.5-turbo',
|
|
167
|
-
'gpt-3.5-turbo-0125',
|
|
168
|
-
'gpt-3.5-turbo-0301',
|
|
169
|
-
'gpt-3.5-turbo-0613',
|
|
170
|
-
'gpt-3.5-turbo-1106',
|
|
171
|
-
'gpt-3.5-turbo-16k',
|
|
172
|
-
'gpt-3.5-turbo-16k-0613',
|
|
173
|
-
'gpt-4',
|
|
174
|
-
'gpt-4-0125-preview',
|
|
175
|
-
'gpt-4-0314',
|
|
176
|
-
'gpt-4-0613',
|
|
177
|
-
'gpt-4-1106-preview',
|
|
178
|
-
'gpt-4-32k',
|
|
179
|
-
'gpt-4-32k-0314',
|
|
180
|
-
'gpt-4-32k-0613',
|
|
181
|
-
'gpt-4-turbo',
|
|
182
|
-
'gpt-4-turbo-2024-04-09',
|
|
183
|
-
'gpt-4-turbo-preview',
|
|
184
|
-
'gpt-4-vision-preview',
|
|
185
|
-
'gpt-4.1',
|
|
186
|
-
'gpt-4.1-2025-04-14',
|
|
187
|
-
'gpt-4.1-mini',
|
|
188
|
-
'gpt-4.1-mini-2025-04-14',
|
|
189
|
-
'gpt-4.1-nano',
|
|
190
|
-
'gpt-4.1-nano-2025-04-14',
|
|
191
|
-
'gpt-4o',
|
|
192
|
-
'gpt-4o-2024-05-13',
|
|
193
|
-
'gpt-4o-2024-08-06',
|
|
194
|
-
'gpt-4o-2024-11-20',
|
|
195
|
-
'gpt-4o-audio-preview',
|
|
196
|
-
'gpt-4o-audio-preview-2024-10-01',
|
|
197
|
-
'gpt-4o-audio-preview-2024-12-17',
|
|
198
|
-
'gpt-4o-audio-preview-2025-06-03',
|
|
199
|
-
'gpt-4o-mini',
|
|
200
|
-
'gpt-4o-mini-2024-07-18',
|
|
201
|
-
'gpt-4o-mini-audio-preview',
|
|
202
|
-
'gpt-4o-mini-audio-preview-2024-12-17',
|
|
203
|
-
'gpt-4o-mini-search-preview',
|
|
204
|
-
'gpt-4o-mini-search-preview-2025-03-11',
|
|
205
|
-
'gpt-4o-search-preview',
|
|
206
|
-
'gpt-4o-search-preview-2025-03-11',
|
|
207
|
-
'gpt-5',
|
|
208
|
-
'gpt-5-2025-08-07',
|
|
209
|
-
'gpt-5-chat-latest',
|
|
210
|
-
'gpt-5-mini',
|
|
211
|
-
'gpt-5-mini-2025-08-07',
|
|
212
|
-
'gpt-5-nano',
|
|
213
|
-
'gpt-5-nano-2025-08-07',
|
|
214
151
|
'grok:grok-4',
|
|
215
152
|
'grok:grok-4-0709',
|
|
216
153
|
'grok:grok-3',
|
|
@@ -271,22 +208,6 @@ KnownModelName = TypeAliasType(
|
|
|
271
208
|
'moonshotai:kimi-latest',
|
|
272
209
|
'moonshotai:kimi-thinking-preview',
|
|
273
210
|
'moonshotai:kimi-k2-0711-preview',
|
|
274
|
-
'o1',
|
|
275
|
-
'o1-2024-12-17',
|
|
276
|
-
'o1-mini',
|
|
277
|
-
'o1-mini-2024-09-12',
|
|
278
|
-
'o1-preview',
|
|
279
|
-
'o1-preview-2024-09-12',
|
|
280
|
-
'o1-pro',
|
|
281
|
-
'o1-pro-2025-03-19',
|
|
282
|
-
'o3',
|
|
283
|
-
'o3-2025-04-16',
|
|
284
|
-
'o3-deep-research',
|
|
285
|
-
'o3-deep-research-2025-06-26',
|
|
286
|
-
'o3-mini',
|
|
287
|
-
'o3-mini-2025-01-31',
|
|
288
|
-
'o3-pro',
|
|
289
|
-
'o3-pro-2025-06-10',
|
|
290
211
|
'openai:chatgpt-4o-latest',
|
|
291
212
|
'openai:codex-mini-latest',
|
|
292
213
|
'openai:gpt-3.5-turbo',
|
|
@@ -54,7 +54,7 @@ _FINISH_REASON_MAP: dict[BetaStopReason, FinishReason] = {
|
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
try:
|
|
57
|
-
from anthropic import NOT_GIVEN, APIStatusError, AsyncStream
|
|
57
|
+
from anthropic import NOT_GIVEN, APIStatusError, AsyncStream, omit as OMIT
|
|
58
58
|
from anthropic.types.beta import (
|
|
59
59
|
BetaBase64PDFBlockParam,
|
|
60
60
|
BetaBase64PDFSourceParam,
|
|
@@ -265,6 +265,10 @@ class AnthropicModel(Model):
|
|
|
265
265
|
else:
|
|
266
266
|
if not model_request_parameters.allow_text_output:
|
|
267
267
|
tool_choice = {'type': 'any'}
|
|
268
|
+
if (thinking := model_settings.get('anthropic_thinking')) and thinking.get('type') == 'enabled':
|
|
269
|
+
raise UserError(
|
|
270
|
+
'Anthropic does not support thinking and output tools at the same time. Use `output_type=PromptedOutput(...)` instead.'
|
|
271
|
+
)
|
|
268
272
|
else:
|
|
269
273
|
tool_choice = {'type': 'auto'}
|
|
270
274
|
|
|
@@ -281,18 +285,18 @@ class AnthropicModel(Model):
|
|
|
281
285
|
|
|
282
286
|
return await self.client.beta.messages.create(
|
|
283
287
|
max_tokens=model_settings.get('max_tokens', 4096),
|
|
284
|
-
system=system_prompt or
|
|
288
|
+
system=system_prompt or OMIT,
|
|
285
289
|
messages=anthropic_messages,
|
|
286
290
|
model=self._model_name,
|
|
287
|
-
tools=tools or
|
|
288
|
-
tool_choice=tool_choice or
|
|
291
|
+
tools=tools or OMIT,
|
|
292
|
+
tool_choice=tool_choice or OMIT,
|
|
289
293
|
stream=stream,
|
|
290
|
-
thinking=model_settings.get('anthropic_thinking',
|
|
291
|
-
stop_sequences=model_settings.get('stop_sequences',
|
|
292
|
-
temperature=model_settings.get('temperature',
|
|
293
|
-
top_p=model_settings.get('top_p',
|
|
294
|
+
thinking=model_settings.get('anthropic_thinking', OMIT),
|
|
295
|
+
stop_sequences=model_settings.get('stop_sequences', OMIT),
|
|
296
|
+
temperature=model_settings.get('temperature', OMIT),
|
|
297
|
+
top_p=model_settings.get('top_p', OMIT),
|
|
294
298
|
timeout=model_settings.get('timeout', NOT_GIVEN),
|
|
295
|
-
metadata=model_settings.get('anthropic_metadata',
|
|
299
|
+
metadata=model_settings.get('anthropic_metadata', OMIT),
|
|
296
300
|
extra_headers=extra_headers,
|
|
297
301
|
extra_body=model_settings.get('extra_body'),
|
|
298
302
|
)
|
|
@@ -759,6 +763,8 @@ def _map_server_tool_use_block(item: BetaServerToolUseBlock, provider_name: str)
|
|
|
759
763
|
args=cast(dict[str, Any], item.input) or None,
|
|
760
764
|
tool_call_id=item.id,
|
|
761
765
|
)
|
|
766
|
+
elif item.name in ('web_fetch', 'bash_code_execution', 'text_editor_code_execution'): # pragma: no cover
|
|
767
|
+
raise NotImplementedError(f'Anthropic built-in tool {item.name!r} is not currently supported.')
|
|
762
768
|
else:
|
|
763
769
|
assert_never(item.name)
|
|
764
770
|
|
|
@@ -9,6 +9,7 @@ from dataclasses import dataclass, field
|
|
|
9
9
|
from typing import Any, Literal, cast
|
|
10
10
|
from urllib.parse import urlparse
|
|
11
11
|
|
|
12
|
+
from genai_prices.types import PriceCalculation
|
|
12
13
|
from opentelemetry._events import (
|
|
13
14
|
Event, # pyright: ignore[reportPrivateImportUsage]
|
|
14
15
|
EventLogger, # pyright: ignore[reportPrivateImportUsage]
|
|
@@ -169,6 +170,11 @@ class InstrumentationSettings:
|
|
|
169
170
|
self.tokens_histogram = self.meter.create_histogram(
|
|
170
171
|
**tokens_histogram_kwargs, # pyright: ignore
|
|
171
172
|
)
|
|
173
|
+
self.cost_histogram = self.meter.create_histogram(
|
|
174
|
+
'operation.cost',
|
|
175
|
+
unit='{USD}',
|
|
176
|
+
description='Monetary cost',
|
|
177
|
+
)
|
|
172
178
|
|
|
173
179
|
def messages_to_otel_events(self, messages: list[ModelMessage]) -> list[Event]:
|
|
174
180
|
"""Convert a list of model messages to OpenTelemetry events.
|
|
@@ -302,6 +308,21 @@ class InstrumentationSettings:
|
|
|
302
308
|
}
|
|
303
309
|
)
|
|
304
310
|
|
|
311
|
+
def record_metrics(
|
|
312
|
+
self,
|
|
313
|
+
response: ModelResponse,
|
|
314
|
+
price_calculation: PriceCalculation | None,
|
|
315
|
+
attributes: dict[str, AttributeValue],
|
|
316
|
+
):
|
|
317
|
+
for typ in ['input', 'output']:
|
|
318
|
+
if not (tokens := getattr(response.usage, f'{typ}_tokens', 0)): # pragma: no cover
|
|
319
|
+
continue
|
|
320
|
+
token_attributes = {**attributes, 'gen_ai.token.type': typ}
|
|
321
|
+
self.tokens_histogram.record(tokens, token_attributes)
|
|
322
|
+
if price_calculation:
|
|
323
|
+
cost = float(getattr(price_calculation, f'{typ}_price'))
|
|
324
|
+
self.cost_histogram.record(cost, token_attributes)
|
|
325
|
+
|
|
305
326
|
|
|
306
327
|
GEN_AI_SYSTEM_ATTRIBUTE = 'gen_ai.system'
|
|
307
328
|
GEN_AI_REQUEST_MODEL_ATTRIBUTE = 'gen_ai.request.model'
|
|
@@ -395,6 +416,7 @@ class InstrumentedModel(WrapperModel):
|
|
|
395
416
|
system = cast(str, attributes[GEN_AI_SYSTEM_ATTRIBUTE])
|
|
396
417
|
|
|
397
418
|
response_model = response.model_name or request_model
|
|
419
|
+
price_calculation = None
|
|
398
420
|
|
|
399
421
|
def _record_metrics():
|
|
400
422
|
metric_attributes = {
|
|
@@ -403,16 +425,7 @@ class InstrumentedModel(WrapperModel):
|
|
|
403
425
|
'gen_ai.request.model': request_model,
|
|
404
426
|
'gen_ai.response.model': response_model,
|
|
405
427
|
}
|
|
406
|
-
|
|
407
|
-
self.instrumentation_settings.tokens_histogram.record(
|
|
408
|
-
response.usage.input_tokens,
|
|
409
|
-
{**metric_attributes, 'gen_ai.token.type': 'input'},
|
|
410
|
-
)
|
|
411
|
-
if response.usage.output_tokens: # pragma: no branch
|
|
412
|
-
self.instrumentation_settings.tokens_histogram.record(
|
|
413
|
-
response.usage.output_tokens,
|
|
414
|
-
{**metric_attributes, 'gen_ai.token.type': 'output'},
|
|
415
|
-
)
|
|
428
|
+
self.instrumentation_settings.record_metrics(response, price_calculation, metric_attributes)
|
|
416
429
|
|
|
417
430
|
nonlocal record_metrics
|
|
418
431
|
record_metrics = _record_metrics
|
|
@@ -427,7 +440,7 @@ class InstrumentedModel(WrapperModel):
|
|
|
427
440
|
'gen_ai.response.model': response_model,
|
|
428
441
|
}
|
|
429
442
|
try:
|
|
430
|
-
|
|
443
|
+
price_calculation = response.cost()
|
|
431
444
|
except LookupError:
|
|
432
445
|
# The cost of this provider/model is unknown, which is common.
|
|
433
446
|
pass
|
|
@@ -435,6 +448,9 @@ class InstrumentedModel(WrapperModel):
|
|
|
435
448
|
warnings.warn(
|
|
436
449
|
f'Failed to get cost from response: {type(e).__name__}: {e}', CostCalculationFailedWarning
|
|
437
450
|
)
|
|
451
|
+
else:
|
|
452
|
+
attributes_to_set['operation.cost'] = float(price_calculation.total_price)
|
|
453
|
+
|
|
438
454
|
if response.provider_response_id is not None:
|
|
439
455
|
attributes_to_set['gen_ai.response.id'] = response.provider_response_id
|
|
440
456
|
if response.finish_reason is not None:
|
|
@@ -526,16 +526,20 @@ class OpenAIChatModel(Model):
|
|
|
526
526
|
|
|
527
527
|
choice = response.choices[0]
|
|
528
528
|
items: list[ModelResponsePart] = []
|
|
529
|
+
|
|
529
530
|
# The `reasoning_content` field is only present in DeepSeek models.
|
|
530
531
|
# https://api-docs.deepseek.com/guides/reasoning_model
|
|
531
532
|
if reasoning_content := getattr(choice.message, 'reasoning_content', None):
|
|
532
533
|
items.append(ThinkingPart(id='reasoning_content', content=reasoning_content, provider_name=self.system))
|
|
533
534
|
|
|
534
|
-
#
|
|
535
|
-
# - https://openrouter.ai/docs/use-cases/reasoning-tokens#preserving-reasoning-blocks
|
|
536
|
-
# NOTE: We don't currently handle OpenRouter/gpt-oss `reasoning`:
|
|
535
|
+
# The `reasoning` field is only present in gpt-oss via Ollama and OpenRouter.
|
|
537
536
|
# - https://cookbook.openai.com/articles/gpt-oss/handle-raw-cot#chat-completions-api
|
|
538
537
|
# - https://openrouter.ai/docs/use-cases/reasoning-tokens#basic-usage-with-reasoning-tokens
|
|
538
|
+
if reasoning := getattr(choice.message, 'reasoning', None):
|
|
539
|
+
items.append(ThinkingPart(id='reasoning', content=reasoning, provider_name=self.system))
|
|
540
|
+
|
|
541
|
+
# NOTE: We don't currently handle OpenRouter `reasoning_details`:
|
|
542
|
+
# - https://openrouter.ai/docs/use-cases/reasoning-tokens#preserving-reasoning-blocks
|
|
539
543
|
# If you need this, please file an issue.
|
|
540
544
|
|
|
541
545
|
vendor_details: dict[str, Any] = {}
|
|
@@ -753,12 +757,16 @@ class OpenAIChatModel(Model):
|
|
|
753
757
|
if isinstance(item, str):
|
|
754
758
|
content.append(ChatCompletionContentPartTextParam(text=item, type='text'))
|
|
755
759
|
elif isinstance(item, ImageUrl):
|
|
756
|
-
image_url =
|
|
760
|
+
image_url: ImageURL = {'url': item.url}
|
|
761
|
+
if metadata := item.vendor_metadata:
|
|
762
|
+
image_url['detail'] = metadata.get('detail', 'auto')
|
|
757
763
|
content.append(ChatCompletionContentPartImageParam(image_url=image_url, type='image_url'))
|
|
758
764
|
elif isinstance(item, BinaryContent):
|
|
759
765
|
base64_encoded = base64.b64encode(item.data).decode('utf-8')
|
|
760
766
|
if item.is_image:
|
|
761
|
-
image_url =
|
|
767
|
+
image_url: ImageURL = {'url': f'data:{item.media_type};base64,{base64_encoded}'}
|
|
768
|
+
if metadata := item.vendor_metadata:
|
|
769
|
+
image_url['detail'] = metadata.get('detail', 'auto')
|
|
762
770
|
content.append(ChatCompletionContentPartImageParam(image_url=image_url, type='image_url'))
|
|
763
771
|
elif item.is_audio:
|
|
764
772
|
assert item.format in ('wav', 'mp3')
|
|
@@ -1383,11 +1391,17 @@ class OpenAIResponsesModel(Model):
|
|
|
1383
1391
|
elif isinstance(item, BinaryContent):
|
|
1384
1392
|
base64_encoded = base64.b64encode(item.data).decode('utf-8')
|
|
1385
1393
|
if item.is_image:
|
|
1394
|
+
detail: Literal['auto', 'low', 'high'] = 'auto'
|
|
1395
|
+
if metadata := item.vendor_metadata:
|
|
1396
|
+
detail = cast(
|
|
1397
|
+
Literal['auto', 'low', 'high'],
|
|
1398
|
+
metadata.get('detail', 'auto'),
|
|
1399
|
+
)
|
|
1386
1400
|
content.append(
|
|
1387
1401
|
responses.ResponseInputImageParam(
|
|
1388
1402
|
image_url=f'data:{item.media_type};base64,{base64_encoded}',
|
|
1389
1403
|
type='input_image',
|
|
1390
|
-
detail=
|
|
1404
|
+
detail=detail,
|
|
1391
1405
|
)
|
|
1392
1406
|
)
|
|
1393
1407
|
elif item.is_document:
|
|
@@ -1406,8 +1420,15 @@ class OpenAIResponsesModel(Model):
|
|
|
1406
1420
|
else: # pragma: no cover
|
|
1407
1421
|
raise RuntimeError(f'Unsupported binary content type: {item.media_type}')
|
|
1408
1422
|
elif isinstance(item, ImageUrl):
|
|
1423
|
+
detail: Literal['auto', 'low', 'high'] = 'auto'
|
|
1424
|
+
if metadata := item.vendor_metadata:
|
|
1425
|
+
detail = cast(Literal['auto', 'low', 'high'], metadata.get('detail', 'auto'))
|
|
1409
1426
|
content.append(
|
|
1410
|
-
responses.ResponseInputImageParam(
|
|
1427
|
+
responses.ResponseInputImageParam(
|
|
1428
|
+
image_url=item.url,
|
|
1429
|
+
type='input_image',
|
|
1430
|
+
detail=detail,
|
|
1431
|
+
)
|
|
1411
1432
|
)
|
|
1412
1433
|
elif isinstance(item, AudioUrl): # pragma: no cover
|
|
1413
1434
|
downloaded_item = await download_item(item, data_format='base64_uri', type_format='extension')
|
|
@@ -1492,6 +1513,17 @@ class OpenAIStreamedResponse(StreamedResponse):
|
|
|
1492
1513
|
provider_name=self.provider_name,
|
|
1493
1514
|
)
|
|
1494
1515
|
|
|
1516
|
+
# The `reasoning` field is only present in gpt-oss via Ollama and OpenRouter.
|
|
1517
|
+
# - https://cookbook.openai.com/articles/gpt-oss/handle-raw-cot#chat-completions-api
|
|
1518
|
+
# - https://openrouter.ai/docs/use-cases/reasoning-tokens#basic-usage-with-reasoning-tokens
|
|
1519
|
+
if reasoning := getattr(choice.delta, 'reasoning', None): # pragma: no cover
|
|
1520
|
+
yield self._parts_manager.handle_thinking_delta(
|
|
1521
|
+
vendor_part_id='reasoning',
|
|
1522
|
+
id='reasoning',
|
|
1523
|
+
content=reasoning,
|
|
1524
|
+
provider_name=self.provider_name,
|
|
1525
|
+
)
|
|
1526
|
+
|
|
1495
1527
|
for dtc in choice.delta.tool_calls or []:
|
|
1496
1528
|
maybe_event = self._parts_manager.handle_tool_call_delta(
|
|
1497
1529
|
vendor_part_id=dtc.index,
|
|
@@ -11,7 +11,7 @@ from typing_extensions import TypeAliasType, TypeVar, deprecated
|
|
|
11
11
|
|
|
12
12
|
from . import _utils
|
|
13
13
|
from .messages import ToolCallPart
|
|
14
|
-
from .tools import DeferredToolRequests, RunContext, ToolDefinition
|
|
14
|
+
from .tools import DeferredToolRequests, ObjectJsonSchema, RunContext, ToolDefinition
|
|
15
15
|
|
|
16
16
|
__all__ = (
|
|
17
17
|
# classes
|
|
@@ -20,6 +20,7 @@ __all__ = (
|
|
|
20
20
|
'PromptedOutput',
|
|
21
21
|
'TextOutput',
|
|
22
22
|
'StructuredDict',
|
|
23
|
+
'OutputObjectDefinition',
|
|
23
24
|
# types
|
|
24
25
|
'OutputDataT',
|
|
25
26
|
'OutputMode',
|
|
@@ -242,6 +243,16 @@ class PromptedOutput(Generic[OutputDataT]):
|
|
|
242
243
|
self.template = template
|
|
243
244
|
|
|
244
245
|
|
|
246
|
+
@dataclass
|
|
247
|
+
class OutputObjectDefinition:
|
|
248
|
+
"""Definition of an output object used for structured output generation."""
|
|
249
|
+
|
|
250
|
+
json_schema: ObjectJsonSchema
|
|
251
|
+
name: str | None = None
|
|
252
|
+
description: str | None = None
|
|
253
|
+
strict: bool | None = None
|
|
254
|
+
|
|
255
|
+
|
|
245
256
|
@dataclass
|
|
246
257
|
class TextOutput(Generic[OutputDataT]):
|
|
247
258
|
"""Marker class to use text output for an output function taking a string argument.
|
|
@@ -10,4 +10,6 @@ def harmony_model_profile(model_name: str) -> ModelProfile | None:
|
|
|
10
10
|
See <https://cookbook.openai.com/articles/openai-harmony> for more details.
|
|
11
11
|
"""
|
|
12
12
|
profile = openai_model_profile(model_name)
|
|
13
|
-
return OpenAIModelProfile(
|
|
13
|
+
return OpenAIModelProfile(
|
|
14
|
+
openai_supports_tool_choice_required=False, ignore_streamed_leading_whitespace=True
|
|
15
|
+
).update(profile)
|
|
@@ -11,6 +11,7 @@ from pydantic_ai.profiles import ModelProfile
|
|
|
11
11
|
from pydantic_ai.profiles.cohere import cohere_model_profile
|
|
12
12
|
from pydantic_ai.profiles.deepseek import deepseek_model_profile
|
|
13
13
|
from pydantic_ai.profiles.google import google_model_profile
|
|
14
|
+
from pydantic_ai.profiles.harmony import harmony_model_profile
|
|
14
15
|
from pydantic_ai.profiles.meta import meta_model_profile
|
|
15
16
|
from pydantic_ai.profiles.mistral import mistral_model_profile
|
|
16
17
|
from pydantic_ai.profiles.openai import OpenAIJsonSchemaTransformer, OpenAIModelProfile
|
|
@@ -50,6 +51,7 @@ class OllamaProvider(Provider[AsyncOpenAI]):
|
|
|
50
51
|
'deepseek': deepseek_model_profile,
|
|
51
52
|
'mistral': mistral_model_profile,
|
|
52
53
|
'command': cohere_model_profile,
|
|
54
|
+
'gpt-oss': harmony_model_profile,
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
profile = None
|
|
@@ -60,7 +60,7 @@ dependencies = [
|
|
|
60
60
|
"exceptiongroup; python_version < '3.11'",
|
|
61
61
|
"opentelemetry-api>=1.28.0",
|
|
62
62
|
"typing-inspection>=0.4.0",
|
|
63
|
-
"genai-prices>=0.0.
|
|
63
|
+
"genai-prices>=0.0.28",
|
|
64
64
|
]
|
|
65
65
|
|
|
66
66
|
[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies]
|
|
@@ -71,7 +71,7 @@ openai = ["openai>=1.107.2"]
|
|
|
71
71
|
cohere = ["cohere>=5.18.0; platform_system != 'Emscripten'"]
|
|
72
72
|
vertexai = ["google-auth>=2.36.0", "requests>=2.32.2"]
|
|
73
73
|
google = ["google-genai>=1.31.0"]
|
|
74
|
-
anthropic = ["anthropic>=0.
|
|
74
|
+
anthropic = ["anthropic>=0.69.0"]
|
|
75
75
|
groq = ["groq>=0.25.0"]
|
|
76
76
|
mistral = ["mistralai>=1.9.10"]
|
|
77
77
|
bedrock = ["boto3>=1.39.0"]
|
|
@@ -97,7 +97,7 @@ ag-ui = ["ag-ui-protocol>=0.1.8", "starlette>=0.45.3"]
|
|
|
97
97
|
# Retries
|
|
98
98
|
retries = ["tenacity>=8.2.3"]
|
|
99
99
|
# Temporal
|
|
100
|
-
temporal = ["temporalio==1.
|
|
100
|
+
temporal = ["temporalio==1.18.0"]
|
|
101
101
|
# DBOS
|
|
102
102
|
dbos = ["dbos>=1.14.0"]
|
|
103
103
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/dbos/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/dbos/_mcp_server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/__init__.py
RENAMED
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_logfire.py
RENAMED
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_mcp_server.py
RENAMED
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_model.py
RENAMED
|
File without changes
|
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/durable_exec/temporal/_toolset.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_ai_slim-1.0.10 → pydantic_ai_slim-1.0.11}/pydantic_ai/toolsets/approval_required.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|