pydantic-ai-slim 0.7.5__tar.gz → 0.7.6__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.
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/PKG-INFO +3 -3
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/agent/__init__.py +11 -4
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/__init__.py +20 -9
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/anthropic.py +2 -2
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/bedrock.py +1 -1
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/openai.py +62 -36
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/__init__.py +1 -1
- pydantic_ai_slim-0.7.6/pydantic_ai/profiles/harmony.py +13 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/openai.py +6 -1
- pydantic_ai_slim-0.7.6/pydantic_ai/profiles/qwen.py +19 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/__init__.py +5 -1
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/azure.py +1 -1
- pydantic_ai_slim-0.7.6/pydantic_ai/providers/cerebras.py +96 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/cohere.py +2 -2
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/deepseek.py +4 -4
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/fireworks.py +3 -3
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/github.py +4 -4
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/grok.py +3 -3
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/groq.py +3 -3
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/heroku.py +3 -3
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/mistral.py +3 -3
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/moonshotai.py +3 -6
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/ollama.py +1 -1
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/openrouter.py +4 -4
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/together.py +3 -3
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/vercel.py +4 -4
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/retries.py +154 -42
- pydantic_ai_slim-0.7.5/pydantic_ai/profiles/qwen.py +0 -11
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/.gitignore +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/LICENSE +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/README.md +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/__init__.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/__main__.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_a2a.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_agent_graph.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_cli.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_function_schema.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_griffe.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_mcp.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_otel_messages.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_output.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_parts_manager.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_run_context.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_system_prompt.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_thinking_part.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_tool_manager.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/_utils.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/ag_ui.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/agent/abstract.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/agent/wrapper.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/builtin_tools.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/common_tools/__init__.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/common_tools/duckduckgo.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/common_tools/tavily.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/direct.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/__init__.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/temporal/__init__.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/temporal/_function_toolset.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/temporal/_model.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/exceptions.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/ext/__init__.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/ext/aci.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/ext/langchain.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/format_prompt.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/mcp.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/messages.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/cohere.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/fallback.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/function.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/gemini.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/google.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/groq.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/huggingface.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/instrumented.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/mcp_sampling.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/mistral.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/test.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/models/wrapper.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/output.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/_json_schema.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/amazon.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/anthropic.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/cohere.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/deepseek.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/google.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/grok.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/groq.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/meta.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/mistral.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/profiles/moonshotai.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/anthropic.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/bedrock.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/google.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/google_gla.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/google_vertex.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/huggingface.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/providers/openai.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/py.typed +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/result.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/run.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/settings.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/tools.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/__init__.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/_dynamic.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/abstract.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/combined.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/deferred.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/filtered.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/function.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/prefixed.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/prepared.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/renamed.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/toolsets/wrapper.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pydantic_ai/usage.py +0 -0
- {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.7.6}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai-slim
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.6
|
|
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
|
|
@@ -35,7 +35,7 @@ Requires-Dist: genai-prices>=0.0.22
|
|
|
35
35
|
Requires-Dist: griffe>=1.3.2
|
|
36
36
|
Requires-Dist: httpx>=0.27
|
|
37
37
|
Requires-Dist: opentelemetry-api>=1.28.0
|
|
38
|
-
Requires-Dist: pydantic-graph==0.7.
|
|
38
|
+
Requires-Dist: pydantic-graph==0.7.6
|
|
39
39
|
Requires-Dist: pydantic>=2.10
|
|
40
40
|
Requires-Dist: typing-inspection>=0.4.0
|
|
41
41
|
Provides-Extra: a2a
|
|
@@ -57,7 +57,7 @@ Requires-Dist: cohere>=5.16.0; (platform_system != 'Emscripten') and extra == 'c
|
|
|
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==0.7.
|
|
60
|
+
Requires-Dist: pydantic-evals==0.7.6; extra == 'evals'
|
|
61
61
|
Provides-Extra: google
|
|
62
62
|
Requires-Dist: google-genai>=1.31.0; extra == 'google'
|
|
63
63
|
Provides-Extra: groq
|
|
@@ -677,16 +677,23 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
677
677
|
def _run_span_end_attributes(
|
|
678
678
|
self, state: _agent_graph.GraphAgentState, usage: _usage.RunUsage, settings: InstrumentationSettings
|
|
679
679
|
):
|
|
680
|
+
if settings.version == 1:
|
|
681
|
+
attr_name = 'all_messages_events'
|
|
682
|
+
value = [
|
|
683
|
+
InstrumentedModel.event_to_dict(e) for e in settings.messages_to_otel_events(state.message_history)
|
|
684
|
+
]
|
|
685
|
+
else:
|
|
686
|
+
attr_name = 'pydantic_ai.all_messages'
|
|
687
|
+
value = settings.messages_to_otel_messages(state.message_history)
|
|
688
|
+
|
|
680
689
|
return {
|
|
681
690
|
**usage.opentelemetry_attributes(),
|
|
682
|
-
|
|
683
|
-
[InstrumentedModel.event_to_dict(e) for e in settings.messages_to_otel_events(state.message_history)]
|
|
684
|
-
),
|
|
691
|
+
attr_name: json.dumps(value),
|
|
685
692
|
'logfire.json_schema': json.dumps(
|
|
686
693
|
{
|
|
687
694
|
'type': 'object',
|
|
688
695
|
'properties': {
|
|
689
|
-
|
|
696
|
+
attr_name: {'type': 'array'},
|
|
690
697
|
'final_result': {'type': 'object'},
|
|
691
698
|
},
|
|
692
699
|
}
|
|
@@ -111,6 +111,15 @@ KnownModelName = TypeAliasType(
|
|
|
111
111
|
'bedrock:mistral.mixtral-8x7b-instruct-v0:1',
|
|
112
112
|
'bedrock:mistral.mistral-large-2402-v1:0',
|
|
113
113
|
'bedrock:mistral.mistral-large-2407-v1:0',
|
|
114
|
+
'cerebras:gpt-oss-120b',
|
|
115
|
+
'cerebras:llama3.1-8b',
|
|
116
|
+
'cerebras:llama-3.3-70b',
|
|
117
|
+
'cerebras:llama-4-scout-17b-16e-instruct',
|
|
118
|
+
'cerebras:llama-4-maverick-17b-128e-instruct',
|
|
119
|
+
'cerebras:qwen-3-235b-a22b-instruct-2507',
|
|
120
|
+
'cerebras:qwen-3-32b',
|
|
121
|
+
'cerebras:qwen-3-coder-480b',
|
|
122
|
+
'cerebras:qwen-3-235b-a22b-thinking-2507',
|
|
114
123
|
'claude-3-5-haiku-20241022',
|
|
115
124
|
'claude-3-5-haiku-latest',
|
|
116
125
|
'claude-3-5-sonnet-20240620',
|
|
@@ -695,21 +704,23 @@ def infer_model(model: Model | KnownModelName | str) -> Model: # noqa: C901
|
|
|
695
704
|
|
|
696
705
|
return CohereModel(model_name, provider=provider)
|
|
697
706
|
elif provider in (
|
|
698
|
-
'openai',
|
|
699
|
-
'deepseek',
|
|
700
707
|
'azure',
|
|
701
|
-
'
|
|
702
|
-
'
|
|
708
|
+
'deepseek',
|
|
709
|
+
'cerebras',
|
|
710
|
+
'fireworks',
|
|
711
|
+
'github',
|
|
703
712
|
'grok',
|
|
713
|
+
'heroku',
|
|
704
714
|
'moonshotai',
|
|
705
|
-
'
|
|
715
|
+
'openai',
|
|
716
|
+
'openai-chat',
|
|
717
|
+
'openrouter',
|
|
706
718
|
'together',
|
|
707
|
-
'
|
|
708
|
-
'github',
|
|
719
|
+
'vercel',
|
|
709
720
|
):
|
|
710
|
-
from .openai import
|
|
721
|
+
from .openai import OpenAIChatModel
|
|
711
722
|
|
|
712
|
-
return
|
|
723
|
+
return OpenAIChatModel(model_name, provider=provider)
|
|
713
724
|
elif provider == 'openai-responses':
|
|
714
725
|
from .openai import OpenAIResponsesModel
|
|
715
726
|
|
|
@@ -475,9 +475,9 @@ class AnthropicModel(Model):
|
|
|
475
475
|
anthropic_messages.append(BetaMessageParam(role='assistant', content=assistant_content_params))
|
|
476
476
|
else:
|
|
477
477
|
assert_never(m)
|
|
478
|
-
system_prompt = '\n\n'.join(system_prompt_parts)
|
|
479
478
|
if instructions := self._get_instructions(messages):
|
|
480
|
-
|
|
479
|
+
system_prompt_parts.insert(0, instructions)
|
|
480
|
+
system_prompt = '\n\n'.join(system_prompt_parts)
|
|
481
481
|
return system_prompt, anthropic_messages
|
|
482
482
|
|
|
483
483
|
@staticmethod
|
|
@@ -423,7 +423,7 @@ class BedrockConverseModel(Model):
|
|
|
423
423
|
for message in messages:
|
|
424
424
|
if isinstance(message, ModelRequest):
|
|
425
425
|
for part in message.parts:
|
|
426
|
-
if isinstance(part, SystemPromptPart):
|
|
426
|
+
if isinstance(part, SystemPromptPart) and part.content:
|
|
427
427
|
system_prompt.append({'text': part.content})
|
|
428
428
|
elif isinstance(part, UserPromptPart):
|
|
429
429
|
bedrock_messages.extend(await self._map_user_prompt(part, document_count))
|
|
@@ -82,8 +82,10 @@ except ImportError as _import_error:
|
|
|
82
82
|
|
|
83
83
|
__all__ = (
|
|
84
84
|
'OpenAIModel',
|
|
85
|
+
'OpenAIChatModel',
|
|
85
86
|
'OpenAIResponsesModel',
|
|
86
87
|
'OpenAIModelSettings',
|
|
88
|
+
'OpenAIChatModelSettings',
|
|
87
89
|
'OpenAIResponsesModelSettings',
|
|
88
90
|
'OpenAIModelName',
|
|
89
91
|
)
|
|
@@ -101,7 +103,7 @@ allows this model to be used more easily with other model types (ie, Ollama, Dee
|
|
|
101
103
|
"""
|
|
102
104
|
|
|
103
105
|
|
|
104
|
-
class
|
|
106
|
+
class OpenAIChatModelSettings(ModelSettings, total=False):
|
|
105
107
|
"""Settings used for an OpenAI model request."""
|
|
106
108
|
|
|
107
109
|
# ALL FIELDS MUST BE `openai_` PREFIXED SO YOU CAN MERGE THEM WITH OTHER MODELS.
|
|
@@ -139,7 +141,12 @@ class OpenAIModelSettings(ModelSettings, total=False):
|
|
|
139
141
|
"""
|
|
140
142
|
|
|
141
143
|
|
|
142
|
-
|
|
144
|
+
@deprecated('Use `OpenAIChatModelSettings` instead.')
|
|
145
|
+
class OpenAIModelSettings(OpenAIChatModelSettings, total=False):
|
|
146
|
+
"""Deprecated alias for `OpenAIChatModelSettings`."""
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class OpenAIResponsesModelSettings(OpenAIChatModelSettings, total=False):
|
|
143
150
|
"""Settings used for an OpenAI Responses model request.
|
|
144
151
|
|
|
145
152
|
ALL FIELDS MUST BE `openai_` PREFIXED SO YOU CAN MERGE THEM WITH OTHER MODELS.
|
|
@@ -185,7 +192,7 @@ class OpenAIResponsesModelSettings(OpenAIModelSettings, total=False):
|
|
|
185
192
|
|
|
186
193
|
|
|
187
194
|
@dataclass(init=False)
|
|
188
|
-
class
|
|
195
|
+
class OpenAIChatModel(Model):
|
|
189
196
|
"""A model that uses the OpenAI API.
|
|
190
197
|
|
|
191
198
|
Internally, this uses the [OpenAI Python client](https://github.com/openai/openai-python) to interact with the API.
|
|
@@ -204,18 +211,20 @@ class OpenAIModel(Model):
|
|
|
204
211
|
model_name: OpenAIModelName,
|
|
205
212
|
*,
|
|
206
213
|
provider: Literal[
|
|
207
|
-
'openai',
|
|
208
|
-
'deepseek',
|
|
209
214
|
'azure',
|
|
210
|
-
'
|
|
211
|
-
'
|
|
212
|
-
'vercel',
|
|
213
|
-
'grok',
|
|
215
|
+
'deepseek',
|
|
216
|
+
'cerebras',
|
|
214
217
|
'fireworks',
|
|
215
|
-
'together',
|
|
216
|
-
'heroku',
|
|
217
218
|
'github',
|
|
219
|
+
'grok',
|
|
220
|
+
'heroku',
|
|
221
|
+
'moonshotai',
|
|
218
222
|
'ollama',
|
|
223
|
+
'openai',
|
|
224
|
+
'openai-chat',
|
|
225
|
+
'openrouter',
|
|
226
|
+
'together',
|
|
227
|
+
'vercel',
|
|
219
228
|
]
|
|
220
229
|
| Provider[AsyncOpenAI] = 'openai',
|
|
221
230
|
profile: ModelProfileSpec | None = None,
|
|
@@ -229,18 +238,20 @@ class OpenAIModel(Model):
|
|
|
229
238
|
model_name: OpenAIModelName,
|
|
230
239
|
*,
|
|
231
240
|
provider: Literal[
|
|
232
|
-
'openai',
|
|
233
|
-
'deepseek',
|
|
234
241
|
'azure',
|
|
235
|
-
'
|
|
236
|
-
'
|
|
237
|
-
'vercel',
|
|
238
|
-
'grok',
|
|
242
|
+
'deepseek',
|
|
243
|
+
'cerebras',
|
|
239
244
|
'fireworks',
|
|
240
|
-
'together',
|
|
241
|
-
'heroku',
|
|
242
245
|
'github',
|
|
246
|
+
'grok',
|
|
247
|
+
'heroku',
|
|
248
|
+
'moonshotai',
|
|
243
249
|
'ollama',
|
|
250
|
+
'openai',
|
|
251
|
+
'openai-chat',
|
|
252
|
+
'openrouter',
|
|
253
|
+
'together',
|
|
254
|
+
'vercel',
|
|
244
255
|
]
|
|
245
256
|
| Provider[AsyncOpenAI] = 'openai',
|
|
246
257
|
profile: ModelProfileSpec | None = None,
|
|
@@ -253,18 +264,20 @@ class OpenAIModel(Model):
|
|
|
253
264
|
model_name: OpenAIModelName,
|
|
254
265
|
*,
|
|
255
266
|
provider: Literal[
|
|
256
|
-
'openai',
|
|
257
|
-
'deepseek',
|
|
258
267
|
'azure',
|
|
259
|
-
'
|
|
260
|
-
'
|
|
261
|
-
'vercel',
|
|
262
|
-
'grok',
|
|
268
|
+
'deepseek',
|
|
269
|
+
'cerebras',
|
|
263
270
|
'fireworks',
|
|
264
|
-
'together',
|
|
265
|
-
'heroku',
|
|
266
271
|
'github',
|
|
272
|
+
'grok',
|
|
273
|
+
'heroku',
|
|
274
|
+
'moonshotai',
|
|
267
275
|
'ollama',
|
|
276
|
+
'openai',
|
|
277
|
+
'openai-chat',
|
|
278
|
+
'openrouter',
|
|
279
|
+
'together',
|
|
280
|
+
'vercel',
|
|
268
281
|
]
|
|
269
282
|
| Provider[AsyncOpenAI] = 'openai',
|
|
270
283
|
profile: ModelProfileSpec | None = None,
|
|
@@ -322,7 +335,7 @@ class OpenAIModel(Model):
|
|
|
322
335
|
) -> ModelResponse:
|
|
323
336
|
check_allow_model_requests()
|
|
324
337
|
response = await self._completions_create(
|
|
325
|
-
messages, False, cast(
|
|
338
|
+
messages, False, cast(OpenAIChatModelSettings, model_settings or {}), model_request_parameters
|
|
326
339
|
)
|
|
327
340
|
model_response = self._process_response(response)
|
|
328
341
|
return model_response
|
|
@@ -337,7 +350,7 @@ class OpenAIModel(Model):
|
|
|
337
350
|
) -> AsyncIterator[StreamedResponse]:
|
|
338
351
|
check_allow_model_requests()
|
|
339
352
|
response = await self._completions_create(
|
|
340
|
-
messages, True, cast(
|
|
353
|
+
messages, True, cast(OpenAIChatModelSettings, model_settings or {}), model_request_parameters
|
|
341
354
|
)
|
|
342
355
|
async with response:
|
|
343
356
|
yield await self._process_streamed_response(response, model_request_parameters)
|
|
@@ -347,7 +360,7 @@ class OpenAIModel(Model):
|
|
|
347
360
|
self,
|
|
348
361
|
messages: list[ModelMessage],
|
|
349
362
|
stream: Literal[True],
|
|
350
|
-
model_settings:
|
|
363
|
+
model_settings: OpenAIChatModelSettings,
|
|
351
364
|
model_request_parameters: ModelRequestParameters,
|
|
352
365
|
) -> AsyncStream[ChatCompletionChunk]: ...
|
|
353
366
|
|
|
@@ -356,7 +369,7 @@ class OpenAIModel(Model):
|
|
|
356
369
|
self,
|
|
357
370
|
messages: list[ModelMessage],
|
|
358
371
|
stream: Literal[False],
|
|
359
|
-
model_settings:
|
|
372
|
+
model_settings: OpenAIChatModelSettings,
|
|
360
373
|
model_request_parameters: ModelRequestParameters,
|
|
361
374
|
) -> chat.ChatCompletion: ...
|
|
362
375
|
|
|
@@ -364,7 +377,7 @@ class OpenAIModel(Model):
|
|
|
364
377
|
self,
|
|
365
378
|
messages: list[ModelMessage],
|
|
366
379
|
stream: bool,
|
|
367
|
-
model_settings:
|
|
380
|
+
model_settings: OpenAIChatModelSettings,
|
|
368
381
|
model_request_parameters: ModelRequestParameters,
|
|
369
382
|
) -> chat.ChatCompletion | AsyncStream[ChatCompletionChunk]:
|
|
370
383
|
tools = self._get_tools(model_request_parameters)
|
|
@@ -392,10 +405,15 @@ class OpenAIModel(Model):
|
|
|
392
405
|
): # pragma: no branch
|
|
393
406
|
response_format = {'type': 'json_object'}
|
|
394
407
|
|
|
408
|
+
unsupported_model_settings = OpenAIModelProfile.from_profile(self.profile).openai_unsupported_model_settings
|
|
409
|
+
for setting in unsupported_model_settings:
|
|
410
|
+
model_settings.pop(setting, None)
|
|
411
|
+
|
|
412
|
+
# TODO(Marcelo): Deprecate this in favor of `openai_unsupported_model_settings`.
|
|
395
413
|
sampling_settings = (
|
|
396
414
|
model_settings
|
|
397
415
|
if OpenAIModelProfile.from_profile(self.profile).openai_supports_sampling_settings
|
|
398
|
-
else
|
|
416
|
+
else OpenAIChatModelSettings()
|
|
399
417
|
)
|
|
400
418
|
|
|
401
419
|
try:
|
|
@@ -636,9 +654,7 @@ class OpenAIModel(Model):
|
|
|
636
654
|
)
|
|
637
655
|
elif isinstance(part, RetryPromptPart):
|
|
638
656
|
if part.tool_name is None:
|
|
639
|
-
yield chat.ChatCompletionUserMessageParam(
|
|
640
|
-
role='user', content=part.model_response()
|
|
641
|
-
)
|
|
657
|
+
yield chat.ChatCompletionUserMessageParam(role='user', content=part.model_response())
|
|
642
658
|
else:
|
|
643
659
|
yield chat.ChatCompletionToolMessageParam(
|
|
644
660
|
role='tool',
|
|
@@ -706,6 +722,16 @@ class OpenAIModel(Model):
|
|
|
706
722
|
return chat.ChatCompletionUserMessageParam(role='user', content=content)
|
|
707
723
|
|
|
708
724
|
|
|
725
|
+
@deprecated(
|
|
726
|
+
'`OpenAIModel` was renamed to `OpenAIChatModel` to clearly distinguish it from `OpenAIResponsesModel` which '
|
|
727
|
+
"uses OpenAI's newer Responses API. Use that unless you're using an OpenAI Chat Completions-compatible API, or "
|
|
728
|
+
"require a feature that the Responses API doesn't support yet like audio."
|
|
729
|
+
)
|
|
730
|
+
@dataclass(init=False)
|
|
731
|
+
class OpenAIModel(OpenAIChatModel):
|
|
732
|
+
"""Deprecated alias for `OpenAIChatModel`."""
|
|
733
|
+
|
|
734
|
+
|
|
709
735
|
@dataclass(init=False)
|
|
710
736
|
class OpenAIResponsesModel(Model):
|
|
711
737
|
"""A model that uses the OpenAI Responses API.
|
|
@@ -52,7 +52,7 @@ class ModelProfile:
|
|
|
52
52
|
This is a workaround for models that emit `<think>\n</think>\n\n` or an empty text part ahead of tool calls (e.g. Ollama + Qwen3),
|
|
53
53
|
which we don't want to end up treating as a final result when using `run_stream` with `str` a valid `output_type`.
|
|
54
54
|
|
|
55
|
-
This is currently only used by `
|
|
55
|
+
This is currently only used by `OpenAIChatModel`, `HuggingFaceModel`, and `GroqModel`.
|
|
56
56
|
"""
|
|
57
57
|
|
|
58
58
|
@classmethod
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations as _annotations
|
|
2
|
+
|
|
3
|
+
from . import ModelProfile
|
|
4
|
+
from .openai import OpenAIModelProfile, openai_model_profile
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def harmony_model_profile(model_name: str) -> ModelProfile | None:
|
|
8
|
+
"""The model profile for the OpenAI Harmony Response format.
|
|
9
|
+
|
|
10
|
+
See <https://cookbook.openai.com/articles/openai-harmony> for more details.
|
|
11
|
+
"""
|
|
12
|
+
profile = openai_model_profile(model_name)
|
|
13
|
+
return OpenAIModelProfile(openai_supports_tool_choice_required=False).update(profile)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations as _annotations
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
+
from collections.abc import Sequence
|
|
4
5
|
from dataclasses import dataclass
|
|
5
6
|
from typing import Any, Literal
|
|
6
7
|
|
|
@@ -12,7 +13,7 @@ OpenAISystemPromptRole = Literal['system', 'developer', 'user']
|
|
|
12
13
|
|
|
13
14
|
@dataclass
|
|
14
15
|
class OpenAIModelProfile(ModelProfile):
|
|
15
|
-
"""Profile for models used with
|
|
16
|
+
"""Profile for models used with `OpenAIChatModel`.
|
|
16
17
|
|
|
17
18
|
ALL FIELDS MUST BE `openai_` PREFIXED SO YOU CAN MERGE THEM WITH OTHER MODELS.
|
|
18
19
|
"""
|
|
@@ -20,9 +21,13 @@ class OpenAIModelProfile(ModelProfile):
|
|
|
20
21
|
openai_supports_strict_tool_definition: bool = True
|
|
21
22
|
"""This can be set by a provider or user if the OpenAI-"compatible" API doesn't support strict tool definitions."""
|
|
22
23
|
|
|
24
|
+
# TODO(Marcelo): Deprecate this in favor of `openai_unsupported_model_settings`.
|
|
23
25
|
openai_supports_sampling_settings: bool = True
|
|
24
26
|
"""Turn off to don't send sampling settings like `temperature` and `top_p` to models that don't support them, like OpenAI's o-series reasoning models."""
|
|
25
27
|
|
|
28
|
+
openai_unsupported_model_settings: Sequence[str] = ()
|
|
29
|
+
"""A list of model settings that are not supported by the model."""
|
|
30
|
+
|
|
26
31
|
# Some OpenAI-compatible providers (e.g. MoonshotAI) currently do **not** accept
|
|
27
32
|
# `tool_choice="required"`. This flag lets the calling model know whether it's
|
|
28
33
|
# safe to pass that value along. Default is `True` to preserve existing
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations as _annotations
|
|
2
|
+
|
|
3
|
+
from ..profiles.openai import OpenAIModelProfile
|
|
4
|
+
from . import InlineDefsJsonSchemaTransformer, ModelProfile
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def qwen_model_profile(model_name: str) -> ModelProfile | None:
|
|
8
|
+
"""Get the model profile for a Qwen model."""
|
|
9
|
+
if model_name.startswith('qwen-3-coder'):
|
|
10
|
+
return OpenAIModelProfile(
|
|
11
|
+
json_schema_transformer=InlineDefsJsonSchemaTransformer,
|
|
12
|
+
openai_supports_tool_choice_required=False,
|
|
13
|
+
openai_supports_strict_tool_definition=False,
|
|
14
|
+
ignore_streamed_leading_whitespace=True,
|
|
15
|
+
)
|
|
16
|
+
return ModelProfile(
|
|
17
|
+
json_schema_transformer=InlineDefsJsonSchemaTransformer,
|
|
18
|
+
ignore_streamed_leading_whitespace=True,
|
|
19
|
+
)
|
|
@@ -20,7 +20,7 @@ class Provider(ABC, Generic[InterfaceClient]):
|
|
|
20
20
|
|
|
21
21
|
Each provider only supports a specific interface. A interface can be supported by multiple providers.
|
|
22
22
|
|
|
23
|
-
For example, the
|
|
23
|
+
For example, the `OpenAIChatModel` interface can be supported by the `OpenAIProvider` and the `DeepSeekProvider`.
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
26
|
_client: InterfaceClient
|
|
@@ -95,6 +95,10 @@ def infer_provider_class(provider: str) -> type[Provider[Any]]: # noqa: C901
|
|
|
95
95
|
from .mistral import MistralProvider
|
|
96
96
|
|
|
97
97
|
return MistralProvider
|
|
98
|
+
elif provider == 'cerebras':
|
|
99
|
+
from .cerebras import CerebrasProvider
|
|
100
|
+
|
|
101
|
+
return CerebrasProvider
|
|
98
102
|
elif provider == 'cohere':
|
|
99
103
|
from .cohere import CohereProvider
|
|
100
104
|
|
|
@@ -65,7 +65,7 @@ class AzureProvider(Provider[AsyncOpenAI]):
|
|
|
65
65
|
|
|
66
66
|
profile = profile_func(model_name)
|
|
67
67
|
|
|
68
|
-
# As AzureProvider is always used with
|
|
68
|
+
# As AzureProvider is always used with OpenAIChatModel, which used to unconditionally use OpenAIJsonSchemaTransformer,
|
|
69
69
|
# we need to maintain that behavior unless json_schema_transformer is set explicitly
|
|
70
70
|
return OpenAIModelProfile(json_schema_transformer=OpenAIJsonSchemaTransformer).update(profile)
|
|
71
71
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from __future__ import annotations as _annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import overload
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
from pydantic_ai.exceptions import UserError
|
|
9
|
+
from pydantic_ai.models import cached_async_http_client
|
|
10
|
+
from pydantic_ai.profiles import ModelProfile
|
|
11
|
+
from pydantic_ai.profiles.harmony import harmony_model_profile
|
|
12
|
+
from pydantic_ai.profiles.meta import meta_model_profile
|
|
13
|
+
from pydantic_ai.profiles.openai import OpenAIJsonSchemaTransformer, OpenAIModelProfile
|
|
14
|
+
from pydantic_ai.profiles.qwen import qwen_model_profile
|
|
15
|
+
from pydantic_ai.providers import Provider
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from openai import AsyncOpenAI
|
|
19
|
+
except ImportError as _import_error: # pragma: no cover
|
|
20
|
+
raise ImportError(
|
|
21
|
+
'Please install the `openai` package to use the Cerebras provider, '
|
|
22
|
+
'you can use the `openai` optional group — `pip install "pydantic-ai-slim[openai]"`'
|
|
23
|
+
) from _import_error
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class CerebrasProvider(Provider[AsyncOpenAI]):
|
|
27
|
+
"""Provider for Cerebras API."""
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def name(self) -> str:
|
|
31
|
+
return 'cerebras'
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def base_url(self) -> str:
|
|
35
|
+
return 'https://api.cerebras.ai/v1'
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def client(self) -> AsyncOpenAI:
|
|
39
|
+
return self._client
|
|
40
|
+
|
|
41
|
+
def model_profile(self, model_name: str) -> ModelProfile | None:
|
|
42
|
+
prefix_to_profile = {'llama': meta_model_profile, 'qwen': qwen_model_profile, 'gpt-oss': harmony_model_profile}
|
|
43
|
+
|
|
44
|
+
profile = None
|
|
45
|
+
for prefix, profile_func in prefix_to_profile.items():
|
|
46
|
+
model_name = model_name.lower()
|
|
47
|
+
if model_name.startswith(prefix):
|
|
48
|
+
profile = profile_func(model_name)
|
|
49
|
+
|
|
50
|
+
# According to https://inference-docs.cerebras.ai/resources/openai#currently-unsupported-openai-features,
|
|
51
|
+
# Cerebras doesn't support some model settings.
|
|
52
|
+
unsupported_model_settings = (
|
|
53
|
+
'frequency_penalty',
|
|
54
|
+
'logit_bias',
|
|
55
|
+
'presence_penalty',
|
|
56
|
+
'parallel_tool_calls',
|
|
57
|
+
'service_tier',
|
|
58
|
+
)
|
|
59
|
+
return OpenAIModelProfile(
|
|
60
|
+
json_schema_transformer=OpenAIJsonSchemaTransformer,
|
|
61
|
+
openai_unsupported_model_settings=unsupported_model_settings,
|
|
62
|
+
).update(profile)
|
|
63
|
+
|
|
64
|
+
@overload
|
|
65
|
+
def __init__(self) -> None: ...
|
|
66
|
+
|
|
67
|
+
@overload
|
|
68
|
+
def __init__(self, *, api_key: str) -> None: ...
|
|
69
|
+
|
|
70
|
+
@overload
|
|
71
|
+
def __init__(self, *, api_key: str, http_client: httpx.AsyncClient) -> None: ...
|
|
72
|
+
|
|
73
|
+
@overload
|
|
74
|
+
def __init__(self, *, openai_client: AsyncOpenAI | None = None) -> None: ...
|
|
75
|
+
|
|
76
|
+
def __init__(
|
|
77
|
+
self,
|
|
78
|
+
*,
|
|
79
|
+
api_key: str | None = None,
|
|
80
|
+
openai_client: AsyncOpenAI | None = None,
|
|
81
|
+
http_client: httpx.AsyncClient | None = None,
|
|
82
|
+
) -> None:
|
|
83
|
+
api_key = api_key or os.getenv('CEREBRAS_API_KEY')
|
|
84
|
+
if not api_key and openai_client is None:
|
|
85
|
+
raise UserError(
|
|
86
|
+
'Set the `CEREBRAS_API_KEY` environment variable or pass it via `CerebrasProvider(api_key=...)` '
|
|
87
|
+
'to use the Cerebras provider.'
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if openai_client is not None:
|
|
91
|
+
self._client = openai_client
|
|
92
|
+
elif http_client is not None:
|
|
93
|
+
self._client = AsyncOpenAI(base_url=self.base_url, api_key=api_key, http_client=http_client)
|
|
94
|
+
else:
|
|
95
|
+
http_client = cached_async_http_client(provider='cerebras')
|
|
96
|
+
self._client = AsyncOpenAI(base_url=self.base_url, api_key=api_key, http_client=http_client)
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations as _annotations
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import httpx
|
|
6
6
|
|
|
7
7
|
from pydantic_ai.exceptions import UserError
|
|
8
8
|
from pydantic_ai.models import cached_async_http_client
|
|
@@ -43,7 +43,7 @@ class CohereProvider(Provider[AsyncClientV2]):
|
|
|
43
43
|
*,
|
|
44
44
|
api_key: str | None = None,
|
|
45
45
|
cohere_client: AsyncClientV2 | None = None,
|
|
46
|
-
http_client:
|
|
46
|
+
http_client: httpx.AsyncClient | None = None,
|
|
47
47
|
) -> None:
|
|
48
48
|
"""Create a new Cohere provider.
|
|
49
49
|
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations as _annotations
|
|
|
3
3
|
import os
|
|
4
4
|
from typing import overload
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import httpx
|
|
7
7
|
from openai import AsyncOpenAI
|
|
8
8
|
|
|
9
9
|
from pydantic_ai.exceptions import UserError
|
|
@@ -40,7 +40,7 @@ class DeepSeekProvider(Provider[AsyncOpenAI]):
|
|
|
40
40
|
def model_profile(self, model_name: str) -> ModelProfile | None:
|
|
41
41
|
profile = deepseek_model_profile(model_name)
|
|
42
42
|
|
|
43
|
-
# As DeepSeekProvider is always used with
|
|
43
|
+
# As DeepSeekProvider is always used with OpenAIChatModel, which used to unconditionally use OpenAIJsonSchemaTransformer,
|
|
44
44
|
# we need to maintain that behavior unless json_schema_transformer is set explicitly.
|
|
45
45
|
# This was not the case when using a DeepSeek model with another model class (e.g. BedrockConverseModel or GroqModel),
|
|
46
46
|
# so we won't do this in `deepseek_model_profile` unless we learn it's always needed.
|
|
@@ -53,7 +53,7 @@ class DeepSeekProvider(Provider[AsyncOpenAI]):
|
|
|
53
53
|
def __init__(self, *, api_key: str) -> None: ...
|
|
54
54
|
|
|
55
55
|
@overload
|
|
56
|
-
def __init__(self, *, api_key: str, http_client:
|
|
56
|
+
def __init__(self, *, api_key: str, http_client: httpx.AsyncClient) -> None: ...
|
|
57
57
|
|
|
58
58
|
@overload
|
|
59
59
|
def __init__(self, *, openai_client: AsyncOpenAI | None = None) -> None: ...
|
|
@@ -63,7 +63,7 @@ class DeepSeekProvider(Provider[AsyncOpenAI]):
|
|
|
63
63
|
*,
|
|
64
64
|
api_key: str | None = None,
|
|
65
65
|
openai_client: AsyncOpenAI | None = None,
|
|
66
|
-
http_client:
|
|
66
|
+
http_client: httpx.AsyncClient | None = None,
|
|
67
67
|
) -> None:
|
|
68
68
|
api_key = api_key or os.getenv('DEEPSEEK_API_KEY')
|
|
69
69
|
if not api_key and openai_client is None:
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations as _annotations
|
|
|
3
3
|
import os
|
|
4
4
|
from typing import overload
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import httpx
|
|
7
7
|
from openai import AsyncOpenAI
|
|
8
8
|
|
|
9
9
|
from pydantic_ai.exceptions import UserError
|
|
@@ -71,7 +71,7 @@ class FireworksProvider(Provider[AsyncOpenAI]):
|
|
|
71
71
|
def __init__(self, *, api_key: str) -> None: ...
|
|
72
72
|
|
|
73
73
|
@overload
|
|
74
|
-
def __init__(self, *, api_key: str, http_client:
|
|
74
|
+
def __init__(self, *, api_key: str, http_client: httpx.AsyncClient) -> None: ...
|
|
75
75
|
|
|
76
76
|
@overload
|
|
77
77
|
def __init__(self, *, openai_client: AsyncOpenAI | None = None) -> None: ...
|
|
@@ -81,7 +81,7 @@ class FireworksProvider(Provider[AsyncOpenAI]):
|
|
|
81
81
|
*,
|
|
82
82
|
api_key: str | None = None,
|
|
83
83
|
openai_client: AsyncOpenAI | None = None,
|
|
84
|
-
http_client:
|
|
84
|
+
http_client: httpx.AsyncClient | None = None,
|
|
85
85
|
) -> None:
|
|
86
86
|
api_key = api_key or os.getenv('FIREWORKS_API_KEY')
|
|
87
87
|
if not api_key and openai_client is None:
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations as _annotations
|
|
|
3
3
|
import os
|
|
4
4
|
from typing import overload
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import httpx
|
|
7
7
|
|
|
8
8
|
from pydantic_ai.exceptions import UserError
|
|
9
9
|
from pydantic_ai.models import cached_async_http_client
|
|
@@ -65,7 +65,7 @@ class GitHubProvider(Provider[AsyncOpenAI]):
|
|
|
65
65
|
model_name, *_ = model_name.split(':', 1) # drop tags
|
|
66
66
|
profile = provider_to_profile[provider](model_name)
|
|
67
67
|
|
|
68
|
-
# As GitHubProvider is always used with
|
|
68
|
+
# As GitHubProvider is always used with OpenAIChatModel, which used to unconditionally use OpenAIJsonSchemaTransformer,
|
|
69
69
|
# we need to maintain that behavior unless json_schema_transformer is set explicitly
|
|
70
70
|
return OpenAIModelProfile(json_schema_transformer=OpenAIJsonSchemaTransformer).update(profile)
|
|
71
71
|
|
|
@@ -76,7 +76,7 @@ class GitHubProvider(Provider[AsyncOpenAI]):
|
|
|
76
76
|
def __init__(self, *, api_key: str) -> None: ...
|
|
77
77
|
|
|
78
78
|
@overload
|
|
79
|
-
def __init__(self, *, api_key: str, http_client:
|
|
79
|
+
def __init__(self, *, api_key: str, http_client: httpx.AsyncClient) -> None: ...
|
|
80
80
|
|
|
81
81
|
@overload
|
|
82
82
|
def __init__(self, *, openai_client: AsyncOpenAI | None = None) -> None: ...
|
|
@@ -86,7 +86,7 @@ class GitHubProvider(Provider[AsyncOpenAI]):
|
|
|
86
86
|
*,
|
|
87
87
|
api_key: str | None = None,
|
|
88
88
|
openai_client: AsyncOpenAI | None = None,
|
|
89
|
-
http_client:
|
|
89
|
+
http_client: httpx.AsyncClient | None = None,
|
|
90
90
|
) -> None:
|
|
91
91
|
"""Create a new GitHub Models provider.
|
|
92
92
|
|