pydantic-ai-slim 0.0.19__py3-none-any.whl → 0.0.21__py3-none-any.whl
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/_parts_manager.py +1 -1
- pydantic_ai/_pydantic.py +1 -0
- pydantic_ai/_result.py +29 -28
- pydantic_ai/_system_prompt.py +4 -4
- pydantic_ai/_utils.py +1 -56
- pydantic_ai/agent.py +137 -113
- pydantic_ai/messages.py +24 -56
- pydantic_ai/models/__init__.py +122 -51
- pydantic_ai/models/anthropic.py +109 -38
- pydantic_ai/models/cohere.py +290 -0
- pydantic_ai/models/function.py +12 -8
- pydantic_ai/models/gemini.py +29 -15
- pydantic_ai/models/groq.py +27 -23
- pydantic_ai/models/mistral.py +34 -29
- pydantic_ai/models/openai.py +45 -23
- pydantic_ai/models/test.py +47 -24
- pydantic_ai/models/vertexai.py +2 -1
- pydantic_ai/result.py +45 -26
- pydantic_ai/settings.py +58 -1
- pydantic_ai/tools.py +29 -26
- {pydantic_ai_slim-0.0.19.dist-info → pydantic_ai_slim-0.0.21.dist-info}/METADATA +6 -4
- pydantic_ai_slim-0.0.21.dist-info/RECORD +29 -0
- pydantic_ai/models/ollama.py +0 -120
- pydantic_ai_slim-0.0.19.dist-info/RECORD +0 -29
- {pydantic_ai_slim-0.0.19.dist-info → pydantic_ai_slim-0.0.21.dist-info}/WHEEL +0 -0
pydantic_ai/result.py
CHANGED
|
@@ -11,35 +11,49 @@ import logfire_api
|
|
|
11
11
|
from typing_extensions import TypeVar
|
|
12
12
|
|
|
13
13
|
from . import _result, _utils, exceptions, messages as _messages, models
|
|
14
|
-
from .tools import
|
|
14
|
+
from .tools import AgentDepsT, RunContext
|
|
15
15
|
from .usage import Usage, UsageLimits
|
|
16
16
|
|
|
17
|
-
__all__ = '
|
|
17
|
+
__all__ = 'ResultDataT', 'ResultDataT_inv', 'ResultValidatorFunc', 'RunResult', 'StreamedRunResult'
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
"""
|
|
20
|
+
T = TypeVar('T')
|
|
21
|
+
"""An invariant TypeVar."""
|
|
22
|
+
ResultDataT_inv = TypeVar('ResultDataT_inv', default=str)
|
|
23
|
+
"""
|
|
24
|
+
An invariant type variable for the result data of a model.
|
|
25
|
+
|
|
26
|
+
We need to use an invariant typevar for `ResultValidator` and `ResultValidatorFunc` because the result data type is used
|
|
27
|
+
in both the input and output of a `ResultValidatorFunc`. This can theoretically lead to some issues assuming that types
|
|
28
|
+
possessing ResultValidator's are covariant in the result data type, but in practice this is rarely an issue, and
|
|
29
|
+
changing it would have negative consequences for the ergonomics of the library.
|
|
30
|
+
|
|
31
|
+
At some point, it may make sense to change the input to ResultValidatorFunc to be `Any` or `object` as doing that would
|
|
32
|
+
resolve these potential variance issues.
|
|
33
|
+
"""
|
|
34
|
+
ResultDataT = TypeVar('ResultDataT', default=str, covariant=True)
|
|
35
|
+
"""Covariant type variable for the result data type of a run."""
|
|
22
36
|
|
|
23
37
|
ResultValidatorFunc = Union[
|
|
24
|
-
Callable[[RunContext[
|
|
25
|
-
Callable[[RunContext[
|
|
26
|
-
Callable[[
|
|
27
|
-
Callable[[
|
|
38
|
+
Callable[[RunContext[AgentDepsT], ResultDataT_inv], ResultDataT_inv],
|
|
39
|
+
Callable[[RunContext[AgentDepsT], ResultDataT_inv], Awaitable[ResultDataT_inv]],
|
|
40
|
+
Callable[[ResultDataT_inv], ResultDataT_inv],
|
|
41
|
+
Callable[[ResultDataT_inv], Awaitable[ResultDataT_inv]],
|
|
28
42
|
]
|
|
29
43
|
"""
|
|
30
|
-
A function that always takes
|
|
44
|
+
A function that always takes and returns the same type of data (which is the result type of an agent run), and:
|
|
31
45
|
|
|
32
46
|
* may or may not take [`RunContext`][pydantic_ai.tools.RunContext] as a first argument
|
|
33
47
|
* may or may not be async
|
|
34
48
|
|
|
35
|
-
Usage `ResultValidatorFunc[
|
|
49
|
+
Usage `ResultValidatorFunc[AgentDepsT, T]`.
|
|
36
50
|
"""
|
|
37
51
|
|
|
38
52
|
_logfire = logfire_api.Logfire(otel_scope='pydantic-ai')
|
|
39
53
|
|
|
40
54
|
|
|
41
55
|
@dataclass
|
|
42
|
-
class _BaseRunResult(ABC, Generic[
|
|
56
|
+
class _BaseRunResult(ABC, Generic[ResultDataT]):
|
|
43
57
|
"""Base type for results.
|
|
44
58
|
|
|
45
59
|
You should not import or use this type directly, instead use its subclasses `RunResult` and `StreamedRunResult`.
|
|
@@ -119,10 +133,10 @@ class _BaseRunResult(ABC, Generic[ResultData]):
|
|
|
119
133
|
|
|
120
134
|
|
|
121
135
|
@dataclass
|
|
122
|
-
class RunResult(_BaseRunResult[
|
|
136
|
+
class RunResult(_BaseRunResult[ResultDataT]):
|
|
123
137
|
"""Result of a non-streamed run."""
|
|
124
138
|
|
|
125
|
-
data:
|
|
139
|
+
data: ResultDataT
|
|
126
140
|
"""Data from the final response in the run."""
|
|
127
141
|
_result_tool_name: str | None
|
|
128
142
|
_usage: Usage
|
|
@@ -165,14 +179,14 @@ class RunResult(_BaseRunResult[ResultData]):
|
|
|
165
179
|
|
|
166
180
|
|
|
167
181
|
@dataclass
|
|
168
|
-
class StreamedRunResult(_BaseRunResult[
|
|
182
|
+
class StreamedRunResult(_BaseRunResult[ResultDataT], Generic[AgentDepsT, ResultDataT]):
|
|
169
183
|
"""Result of a streamed run that returns structured data via a tool call."""
|
|
170
184
|
|
|
171
185
|
_usage_limits: UsageLimits | None
|
|
172
186
|
_stream_response: models.StreamedResponse
|
|
173
|
-
_result_schema: _result.ResultSchema[
|
|
174
|
-
_run_ctx: RunContext[
|
|
175
|
-
_result_validators: list[_result.ResultValidator[
|
|
187
|
+
_result_schema: _result.ResultSchema[ResultDataT] | None
|
|
188
|
+
_run_ctx: RunContext[AgentDepsT]
|
|
189
|
+
_result_validators: list[_result.ResultValidator[AgentDepsT, ResultDataT]]
|
|
176
190
|
_result_tool_name: str | None
|
|
177
191
|
_on_complete: Callable[[], Awaitable[None]]
|
|
178
192
|
is_complete: bool = field(default=False, init=False)
|
|
@@ -185,7 +199,7 @@ class StreamedRunResult(_BaseRunResult[ResultData], Generic[AgentDeps, ResultDat
|
|
|
185
199
|
[`get_data`][pydantic_ai.result.StreamedRunResult.get_data] completes.
|
|
186
200
|
"""
|
|
187
201
|
|
|
188
|
-
async def stream(self, *, debounce_by: float | None = 0.1) -> AsyncIterator[
|
|
202
|
+
async def stream(self, *, debounce_by: float | None = 0.1) -> AsyncIterator[ResultDataT]:
|
|
189
203
|
"""Stream the response as an async iterable.
|
|
190
204
|
|
|
191
205
|
The pydantic validator for structured data will be called in
|
|
@@ -269,7 +283,12 @@ class StreamedRunResult(_BaseRunResult[ResultData], Generic[AgentDeps, ResultDat
|
|
|
269
283
|
yield combined_validated_text
|
|
270
284
|
|
|
271
285
|
lf_span.set_attribute('combined_text', combined_validated_text)
|
|
272
|
-
await self._marked_completed(
|
|
286
|
+
await self._marked_completed(
|
|
287
|
+
_messages.ModelResponse(
|
|
288
|
+
parts=[_messages.TextPart(combined_validated_text)],
|
|
289
|
+
model_name=self._stream_response.model_name(),
|
|
290
|
+
)
|
|
291
|
+
)
|
|
273
292
|
|
|
274
293
|
async def stream_structured(
|
|
275
294
|
self, *, debounce_by: float | None = 0.1
|
|
@@ -306,7 +325,7 @@ class StreamedRunResult(_BaseRunResult[ResultData], Generic[AgentDeps, ResultDat
|
|
|
306
325
|
lf_span.set_attribute('structured_response', msg)
|
|
307
326
|
await self._marked_completed(msg)
|
|
308
327
|
|
|
309
|
-
async def get_data(self) ->
|
|
328
|
+
async def get_data(self) -> ResultDataT:
|
|
310
329
|
"""Stream the whole response, validate and return it."""
|
|
311
330
|
usage_checking_stream = _get_usage_checking_stream_response(
|
|
312
331
|
self._stream_response, self._usage_limits, self.usage
|
|
@@ -332,7 +351,7 @@ class StreamedRunResult(_BaseRunResult[ResultData], Generic[AgentDeps, ResultDat
|
|
|
332
351
|
|
|
333
352
|
async def validate_structured_result(
|
|
334
353
|
self, message: _messages.ModelResponse, *, allow_partial: bool = False
|
|
335
|
-
) ->
|
|
354
|
+
) -> ResultDataT:
|
|
336
355
|
"""Validate a structured result message."""
|
|
337
356
|
if self._result_schema is not None and self._result_tool_name is not None:
|
|
338
357
|
match = self._result_schema.find_named_tool(message.parts, self._result_tool_name)
|
|
@@ -351,17 +370,17 @@ class StreamedRunResult(_BaseRunResult[ResultData], Generic[AgentDeps, ResultDat
|
|
|
351
370
|
text = '\n\n'.join(x.content for x in message.parts if isinstance(x, _messages.TextPart))
|
|
352
371
|
for validator in self._result_validators:
|
|
353
372
|
text = await validator.validate(
|
|
354
|
-
text,
|
|
373
|
+
text,
|
|
355
374
|
None,
|
|
356
375
|
self._run_ctx,
|
|
357
376
|
)
|
|
358
|
-
# Since there is no result tool, we can assume that str is compatible with
|
|
359
|
-
return cast(
|
|
377
|
+
# Since there is no result tool, we can assume that str is compatible with ResultDataT
|
|
378
|
+
return cast(ResultDataT, text)
|
|
360
379
|
|
|
361
380
|
async def _validate_text_result(self, text: str) -> str:
|
|
362
381
|
for validator in self._result_validators:
|
|
363
|
-
text = await validator.validate(
|
|
364
|
-
text,
|
|
382
|
+
text = await validator.validate(
|
|
383
|
+
text,
|
|
365
384
|
None,
|
|
366
385
|
self._run_ctx,
|
|
367
386
|
)
|
pydantic_ai/settings.py
CHANGED
|
@@ -12,7 +12,8 @@ if TYPE_CHECKING:
|
|
|
12
12
|
class ModelSettings(TypedDict, total=False):
|
|
13
13
|
"""Settings to configure an LLM.
|
|
14
14
|
|
|
15
|
-
Here we include only settings which apply to multiple models / model providers
|
|
15
|
+
Here we include only settings which apply to multiple models / model providers,
|
|
16
|
+
though not all of these settings are supported by all models.
|
|
16
17
|
"""
|
|
17
18
|
|
|
18
19
|
max_tokens: int
|
|
@@ -24,6 +25,8 @@ class ModelSettings(TypedDict, total=False):
|
|
|
24
25
|
* Anthropic
|
|
25
26
|
* OpenAI
|
|
26
27
|
* Groq
|
|
28
|
+
* Cohere
|
|
29
|
+
* Mistral
|
|
27
30
|
"""
|
|
28
31
|
|
|
29
32
|
temperature: float
|
|
@@ -40,6 +43,8 @@ class ModelSettings(TypedDict, total=False):
|
|
|
40
43
|
* Anthropic
|
|
41
44
|
* OpenAI
|
|
42
45
|
* Groq
|
|
46
|
+
* Cohere
|
|
47
|
+
* Mistral
|
|
43
48
|
"""
|
|
44
49
|
|
|
45
50
|
top_p: float
|
|
@@ -55,6 +60,8 @@ class ModelSettings(TypedDict, total=False):
|
|
|
55
60
|
* Anthropic
|
|
56
61
|
* OpenAI
|
|
57
62
|
* Groq
|
|
63
|
+
* Cohere
|
|
64
|
+
* Mistral
|
|
58
65
|
"""
|
|
59
66
|
|
|
60
67
|
timeout: float | Timeout
|
|
@@ -66,6 +73,56 @@ class ModelSettings(TypedDict, total=False):
|
|
|
66
73
|
* Anthropic
|
|
67
74
|
* OpenAI
|
|
68
75
|
* Groq
|
|
76
|
+
* Mistral
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
parallel_tool_calls: bool
|
|
80
|
+
"""Whether to allow parallel tool calls.
|
|
81
|
+
|
|
82
|
+
Supported by:
|
|
83
|
+
* OpenAI (some models, not o1)
|
|
84
|
+
* Groq
|
|
85
|
+
* Anthropic
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
seed: int
|
|
89
|
+
"""The random seed to use for the model, theoretically allowing for deterministic results.
|
|
90
|
+
|
|
91
|
+
Supported by:
|
|
92
|
+
* OpenAI
|
|
93
|
+
* Groq
|
|
94
|
+
* Cohere
|
|
95
|
+
* Mistral
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
presence_penalty: float
|
|
99
|
+
"""Penalize new tokens based on whether they have appeared in the text so far.
|
|
100
|
+
|
|
101
|
+
Supported by:
|
|
102
|
+
* OpenAI
|
|
103
|
+
* Groq
|
|
104
|
+
* Cohere
|
|
105
|
+
* Gemini
|
|
106
|
+
* Mistral
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
frequency_penalty: float
|
|
110
|
+
"""Penalize new tokens based on their existing frequency in the text so far.
|
|
111
|
+
|
|
112
|
+
Supported by:
|
|
113
|
+
* OpenAI
|
|
114
|
+
* Groq
|
|
115
|
+
* Cohere
|
|
116
|
+
* Gemini
|
|
117
|
+
* Mistral
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
logit_bias: dict[str, int]
|
|
121
|
+
"""Modify the likelihood of specified tokens appearing in the completion.
|
|
122
|
+
|
|
123
|
+
Supported by:
|
|
124
|
+
* OpenAI
|
|
125
|
+
* Groq
|
|
69
126
|
"""
|
|
70
127
|
|
|
71
128
|
|
pydantic_ai/tools.py
CHANGED
|
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|
|
17
17
|
from .result import Usage
|
|
18
18
|
|
|
19
19
|
__all__ = (
|
|
20
|
-
'
|
|
20
|
+
'AgentDepsT',
|
|
21
21
|
'DocstringFormat',
|
|
22
22
|
'RunContext',
|
|
23
23
|
'SystemPromptFunc',
|
|
@@ -31,15 +31,15 @@ __all__ = (
|
|
|
31
31
|
'ToolDefinition',
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
AgentDepsT = TypeVar('AgentDepsT', default=None, contravariant=True)
|
|
35
35
|
"""Type variable for agent dependencies."""
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
@dataclasses.dataclass
|
|
39
|
-
class RunContext(Generic[
|
|
39
|
+
class RunContext(Generic[AgentDepsT]):
|
|
40
40
|
"""Information about the current call."""
|
|
41
41
|
|
|
42
|
-
deps:
|
|
42
|
+
deps: AgentDepsT
|
|
43
43
|
"""Dependencies for the agent."""
|
|
44
44
|
model: models.Model
|
|
45
45
|
"""The model used in this run."""
|
|
@@ -58,7 +58,7 @@ class RunContext(Generic[AgentDeps]):
|
|
|
58
58
|
|
|
59
59
|
def replace_with(
|
|
60
60
|
self, retry: int | None = None, tool_name: str | None | _utils.Unset = _utils.UNSET
|
|
61
|
-
) -> RunContext[
|
|
61
|
+
) -> RunContext[AgentDepsT]:
|
|
62
62
|
# Create a new `RunContext` a new `retry` value and `tool_name`.
|
|
63
63
|
kwargs = {}
|
|
64
64
|
if retry is not None:
|
|
@@ -72,35 +72,35 @@ ToolParams = ParamSpec('ToolParams', default=...)
|
|
|
72
72
|
"""Retrieval function param spec."""
|
|
73
73
|
|
|
74
74
|
SystemPromptFunc = Union[
|
|
75
|
-
Callable[[RunContext[
|
|
76
|
-
Callable[[RunContext[
|
|
75
|
+
Callable[[RunContext[AgentDepsT]], str],
|
|
76
|
+
Callable[[RunContext[AgentDepsT]], Awaitable[str]],
|
|
77
77
|
Callable[[], str],
|
|
78
78
|
Callable[[], Awaitable[str]],
|
|
79
79
|
]
|
|
80
80
|
"""A function that may or maybe not take `RunContext` as an argument, and may or may not be async.
|
|
81
81
|
|
|
82
|
-
Usage `SystemPromptFunc[
|
|
82
|
+
Usage `SystemPromptFunc[AgentDepsT]`.
|
|
83
83
|
"""
|
|
84
84
|
|
|
85
|
-
ToolFuncContext = Callable[Concatenate[RunContext[
|
|
85
|
+
ToolFuncContext = Callable[Concatenate[RunContext[AgentDepsT], ToolParams], Any]
|
|
86
86
|
"""A tool function that takes `RunContext` as the first argument.
|
|
87
87
|
|
|
88
|
-
Usage `ToolContextFunc[
|
|
88
|
+
Usage `ToolContextFunc[AgentDepsT, ToolParams]`.
|
|
89
89
|
"""
|
|
90
90
|
ToolFuncPlain = Callable[ToolParams, Any]
|
|
91
91
|
"""A tool function that does not take `RunContext` as the first argument.
|
|
92
92
|
|
|
93
93
|
Usage `ToolPlainFunc[ToolParams]`.
|
|
94
94
|
"""
|
|
95
|
-
ToolFuncEither = Union[ToolFuncContext[
|
|
95
|
+
ToolFuncEither = Union[ToolFuncContext[AgentDepsT, ToolParams], ToolFuncPlain[ToolParams]]
|
|
96
96
|
"""Either kind of tool function.
|
|
97
97
|
|
|
98
98
|
This is just a union of [`ToolFuncContext`][pydantic_ai.tools.ToolFuncContext] and
|
|
99
99
|
[`ToolFuncPlain`][pydantic_ai.tools.ToolFuncPlain].
|
|
100
100
|
|
|
101
|
-
Usage `ToolFuncEither[
|
|
101
|
+
Usage `ToolFuncEither[AgentDepsT, ToolParams]`.
|
|
102
102
|
"""
|
|
103
|
-
ToolPrepareFunc: TypeAlias = 'Callable[[RunContext[
|
|
103
|
+
ToolPrepareFunc: TypeAlias = 'Callable[[RunContext[AgentDepsT], ToolDefinition], Awaitable[ToolDefinition | None]]'
|
|
104
104
|
"""Definition of a function that can prepare a tool definition at call time.
|
|
105
105
|
|
|
106
106
|
See [tool docs](../tools.md#tool-prepare) for more information.
|
|
@@ -125,7 +125,7 @@ def hitchhiker(ctx: RunContext[int], answer: str) -> str:
|
|
|
125
125
|
hitchhiker = Tool(hitchhiker, prepare=only_if_42)
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
Usage `ToolPrepareFunc[
|
|
128
|
+
Usage `ToolPrepareFunc[AgentDepsT]`.
|
|
129
129
|
"""
|
|
130
130
|
|
|
131
131
|
DocstringFormat = Literal['google', 'numpy', 'sphinx', 'auto']
|
|
@@ -141,15 +141,15 @@ A = TypeVar('A')
|
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
@dataclass(init=False)
|
|
144
|
-
class Tool(Generic[
|
|
144
|
+
class Tool(Generic[AgentDepsT]):
|
|
145
145
|
"""A tool function for an agent."""
|
|
146
146
|
|
|
147
|
-
function: ToolFuncEither[
|
|
147
|
+
function: ToolFuncEither[AgentDepsT]
|
|
148
148
|
takes_ctx: bool
|
|
149
149
|
max_retries: int | None
|
|
150
150
|
name: str
|
|
151
151
|
description: str
|
|
152
|
-
prepare: ToolPrepareFunc[
|
|
152
|
+
prepare: ToolPrepareFunc[AgentDepsT] | None
|
|
153
153
|
docstring_format: DocstringFormat
|
|
154
154
|
require_parameter_descriptions: bool
|
|
155
155
|
_is_async: bool = field(init=False)
|
|
@@ -158,17 +158,20 @@ class Tool(Generic[AgentDeps]):
|
|
|
158
158
|
_var_positional_field: str | None = field(init=False)
|
|
159
159
|
_validator: SchemaValidator = field(init=False, repr=False)
|
|
160
160
|
_parameters_json_schema: ObjectJsonSchema = field(init=False)
|
|
161
|
+
|
|
162
|
+
# TODO: Move this state off the Tool class, which is otherwise stateless.
|
|
163
|
+
# This should be tracked inside a specific agent run, not the tool.
|
|
161
164
|
current_retry: int = field(default=0, init=False)
|
|
162
165
|
|
|
163
166
|
def __init__(
|
|
164
167
|
self,
|
|
165
|
-
function: ToolFuncEither[
|
|
168
|
+
function: ToolFuncEither[AgentDepsT],
|
|
166
169
|
*,
|
|
167
170
|
takes_ctx: bool | None = None,
|
|
168
171
|
max_retries: int | None = None,
|
|
169
172
|
name: str | None = None,
|
|
170
173
|
description: str | None = None,
|
|
171
|
-
prepare: ToolPrepareFunc[
|
|
174
|
+
prepare: ToolPrepareFunc[AgentDepsT] | None = None,
|
|
172
175
|
docstring_format: DocstringFormat = 'auto',
|
|
173
176
|
require_parameter_descriptions: bool = False,
|
|
174
177
|
):
|
|
@@ -240,7 +243,7 @@ class Tool(Generic[AgentDeps]):
|
|
|
240
243
|
self._validator = f['validator']
|
|
241
244
|
self._parameters_json_schema = f['json_schema']
|
|
242
245
|
|
|
243
|
-
async def prepare_tool_def(self, ctx: RunContext[
|
|
246
|
+
async def prepare_tool_def(self, ctx: RunContext[AgentDepsT]) -> ToolDefinition | None:
|
|
244
247
|
"""Get the tool definition.
|
|
245
248
|
|
|
246
249
|
By default, this method creates a tool definition, then either returns it, or calls `self.prepare`
|
|
@@ -260,14 +263,14 @@ class Tool(Generic[AgentDeps]):
|
|
|
260
263
|
return tool_def
|
|
261
264
|
|
|
262
265
|
async def run(
|
|
263
|
-
self, message: _messages.ToolCallPart, run_context: RunContext[
|
|
264
|
-
) -> _messages.
|
|
266
|
+
self, message: _messages.ToolCallPart, run_context: RunContext[AgentDepsT]
|
|
267
|
+
) -> _messages.ToolReturnPart | _messages.RetryPromptPart:
|
|
265
268
|
"""Run the tool function asynchronously."""
|
|
266
269
|
try:
|
|
267
|
-
if isinstance(message.args,
|
|
268
|
-
args_dict = self._validator.validate_json(message.args
|
|
270
|
+
if isinstance(message.args, str):
|
|
271
|
+
args_dict = self._validator.validate_json(message.args)
|
|
269
272
|
else:
|
|
270
|
-
args_dict = self._validator.validate_python(message.args
|
|
273
|
+
args_dict = self._validator.validate_python(message.args)
|
|
271
274
|
except ValidationError as e:
|
|
272
275
|
return self._on_error(e, message)
|
|
273
276
|
|
|
@@ -293,7 +296,7 @@ class Tool(Generic[AgentDeps]):
|
|
|
293
296
|
self,
|
|
294
297
|
args_dict: dict[str, Any],
|
|
295
298
|
message: _messages.ToolCallPart,
|
|
296
|
-
run_context: RunContext[
|
|
299
|
+
run_context: RunContext[AgentDepsT],
|
|
297
300
|
) -> tuple[list[Any], dict[str, Any]]:
|
|
298
301
|
if self._single_arg_name:
|
|
299
302
|
args_dict = {self._single_arg_name: args_dict}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai-slim
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.21
|
|
4
4
|
Summary: Agent Framework / shim to use Pydantic with LLMs, slim package
|
|
5
5
|
Author-email: Samuel Colvin <samuel@pydantic.dev>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,13 +26,15 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
26
26
|
Requires-Python: >=3.9
|
|
27
27
|
Requires-Dist: eval-type-backport>=0.2.0
|
|
28
28
|
Requires-Dist: griffe>=1.3.2
|
|
29
|
-
Requires-Dist: httpx>=0.27
|
|
29
|
+
Requires-Dist: httpx>=0.27
|
|
30
30
|
Requires-Dist: logfire-api>=1.2.0
|
|
31
31
|
Requires-Dist: pydantic>=2.10
|
|
32
32
|
Provides-Extra: anthropic
|
|
33
33
|
Requires-Dist: anthropic>=0.40.0; extra == 'anthropic'
|
|
34
|
+
Provides-Extra: cohere
|
|
35
|
+
Requires-Dist: cohere>=5.13.11; extra == 'cohere'
|
|
34
36
|
Provides-Extra: graph
|
|
35
|
-
Requires-Dist: pydantic-graph==0.0.
|
|
37
|
+
Requires-Dist: pydantic-graph==0.0.21; extra == 'graph'
|
|
36
38
|
Provides-Extra: groq
|
|
37
39
|
Requires-Dist: groq>=0.12.0; extra == 'groq'
|
|
38
40
|
Provides-Extra: logfire
|
|
@@ -40,7 +42,7 @@ Requires-Dist: logfire>=2.3; extra == 'logfire'
|
|
|
40
42
|
Provides-Extra: mistral
|
|
41
43
|
Requires-Dist: mistralai>=1.2.5; extra == 'mistral'
|
|
42
44
|
Provides-Extra: openai
|
|
43
|
-
Requires-Dist: openai>=1.
|
|
45
|
+
Requires-Dist: openai>=1.59.0; extra == 'openai'
|
|
44
46
|
Provides-Extra: vertexai
|
|
45
47
|
Requires-Dist: google-auth>=2.36.0; extra == 'vertexai'
|
|
46
48
|
Requires-Dist: requests>=2.32.3; extra == 'vertexai'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
pydantic_ai/__init__.py,sha256=FbYetEgT6OO25u2KF5ZnFxKpz5DtnSpfckRXP4mjl8E,489
|
|
2
|
+
pydantic_ai/_griffe.py,sha256=RYRKiLbgG97QxnazbAwlnc74XxevGHLQet-FGfq9qls,3960
|
|
3
|
+
pydantic_ai/_parts_manager.py,sha256=ARfDQY1_5AIY5rNl_M2fAYHEFCe03ZxdhgjHf9qeIKw,11872
|
|
4
|
+
pydantic_ai/_pydantic.py,sha256=dROz3Hmfdi0C2exq88FhefDRVo_8S3rtkXnoUHzsz0c,8753
|
|
5
|
+
pydantic_ai/_result.py,sha256=tN1pVulf_EM4bkBvpNUWPnUXezLY-sBrJEVCFdy2nLU,10264
|
|
6
|
+
pydantic_ai/_system_prompt.py,sha256=602c2jyle2R_SesOrITBDETZqsLk4BZ8Cbo8yEhmx04,1120
|
|
7
|
+
pydantic_ai/_utils.py,sha256=zfuY3NiPPsSM5J1q2JElfbfIa8S1ONGOlC7M-iyBVso,9430
|
|
8
|
+
pydantic_ai/agent.py,sha256=7o7yfatFPBDkrpSi2t0A4xivX7lzlNbOhtIMEJQpLKc,63620
|
|
9
|
+
pydantic_ai/exceptions.py,sha256=eGDKX6bGhgVxXBzu81Sk3iiAkXr0GUtgT7bD5Rxlqpg,2028
|
|
10
|
+
pydantic_ai/format_as_xml.py,sha256=QE7eMlg5-YUMw1_2kcI3h0uKYPZZyGkgXFDtfZTMeeI,4480
|
|
11
|
+
pydantic_ai/messages.py,sha256=kzXn4ZjlX9Sy2KXgFHWYbbwPk7TzTPdztzOJLWEONwU,17101
|
|
12
|
+
pydantic_ai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
pydantic_ai/result.py,sha256=0beXiUfiSb2kVc68iqLeg2qFQW6-mnTC8TFtiQayPDQ,18394
|
|
14
|
+
pydantic_ai/settings.py,sha256=QSqs4_l_Gs2v4oixYNwKQhPiec_m9pn6XEAeUMFxt24,3054
|
|
15
|
+
pydantic_ai/tools.py,sha256=lhupwm815lPlFFS79B0P61AyhUYtepA62LbZOCJrPEY,13205
|
|
16
|
+
pydantic_ai/usage.py,sha256=60d9f6M7YEYuKMbqDGDogX4KsA73fhDtWyDXYXoIPaI,4948
|
|
17
|
+
pydantic_ai/models/__init__.py,sha256=XgZAhiSVVX0TbePHXSxVnDIbG38jQG9g3WRMlA_EHDY,13063
|
|
18
|
+
pydantic_ai/models/anthropic.py,sha256=v2m6zjaezLjtkHO2Rx67rmoN1iOqDeAp9fswJcqRMBA,16967
|
|
19
|
+
pydantic_ai/models/cohere.py,sha256=wyjtD2uwkYYbsXLKwr-flmXSng_Atd-0jqtVDxDie14,10611
|
|
20
|
+
pydantic_ai/models/function.py,sha256=jv2aw5K4KrMIRPFSTiGbBHcv16UZtGEe_1irjTudLg0,9826
|
|
21
|
+
pydantic_ai/models/gemini.py,sha256=espBJbEMZjdzT5fC_rKOHoo_5o5xH-Y1Ea-RZR4JaPs,28222
|
|
22
|
+
pydantic_ai/models/groq.py,sha256=W-uosi9PtvgXp8yoF6w8QZxPtrVjX1fmRQDjQQ10meE,13603
|
|
23
|
+
pydantic_ai/models/mistral.py,sha256=RuRlxTBPGXIpcwTdjX2596uN2tgHBvCDQCWieWa1A_Q,24793
|
|
24
|
+
pydantic_ai/models/openai.py,sha256=6ymsBzyu9WJVewbn3345jt_JoXpUpCLYOQERYJJlyRY,15228
|
|
25
|
+
pydantic_ai/models/test.py,sha256=D_wBpRtrPcikopd5LBYjdAp3q-1gvuB9WnuopBQiRME,16659
|
|
26
|
+
pydantic_ai/models/vertexai.py,sha256=bQZ5W8n4521AH3jTiyP1fOYxtNgCgkhjCbBeASv5Ap8,9388
|
|
27
|
+
pydantic_ai_slim-0.0.21.dist-info/METADATA,sha256=EeGz0ZJG_g_o7xKu-2XiXN2zZsBhGZLwL39QaQGZQdc,2879
|
|
28
|
+
pydantic_ai_slim-0.0.21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
29
|
+
pydantic_ai_slim-0.0.21.dist-info/RECORD,,
|
pydantic_ai/models/ollama.py
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations as _annotations
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from typing import Literal, Union
|
|
5
|
-
|
|
6
|
-
from httpx import AsyncClient as AsyncHTTPClient
|
|
7
|
-
|
|
8
|
-
from ..tools import ToolDefinition
|
|
9
|
-
from . import (
|
|
10
|
-
AgentModel,
|
|
11
|
-
Model,
|
|
12
|
-
cached_async_http_client,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
try:
|
|
16
|
-
from openai import AsyncOpenAI
|
|
17
|
-
except ImportError as e:
|
|
18
|
-
raise ImportError(
|
|
19
|
-
'Please install `openai` to use the OpenAI model, '
|
|
20
|
-
"you can use the `openai` optional group — `pip install 'pydantic-ai-slim[openai]'`"
|
|
21
|
-
) from e
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
from .openai import OpenAIModel
|
|
25
|
-
|
|
26
|
-
CommonOllamaModelNames = Literal[
|
|
27
|
-
'codellama',
|
|
28
|
-
'gemma',
|
|
29
|
-
'gemma2',
|
|
30
|
-
'llama3',
|
|
31
|
-
'llama3.1',
|
|
32
|
-
'llama3.2',
|
|
33
|
-
'llama3.2-vision',
|
|
34
|
-
'llama3.3',
|
|
35
|
-
'mistral',
|
|
36
|
-
'mistral-nemo',
|
|
37
|
-
'mixtral',
|
|
38
|
-
'phi3',
|
|
39
|
-
'phi4',
|
|
40
|
-
'qwq',
|
|
41
|
-
'qwen',
|
|
42
|
-
'qwen2',
|
|
43
|
-
'qwen2.5',
|
|
44
|
-
'starcoder2',
|
|
45
|
-
]
|
|
46
|
-
"""This contains just the most common ollama models.
|
|
47
|
-
|
|
48
|
-
For a full list see [ollama.com/library](https://ollama.com/library).
|
|
49
|
-
"""
|
|
50
|
-
OllamaModelName = Union[CommonOllamaModelNames, str]
|
|
51
|
-
"""Possible ollama models.
|
|
52
|
-
|
|
53
|
-
Since Ollama supports hundreds of models, we explicitly list the most models but
|
|
54
|
-
allow any name in the type hints.
|
|
55
|
-
"""
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@dataclass(init=False)
|
|
59
|
-
class OllamaModel(Model):
|
|
60
|
-
"""A model that implements Ollama using the OpenAI API.
|
|
61
|
-
|
|
62
|
-
Internally, this uses the [OpenAI Python client](https://github.com/openai/openai-python) to interact with the Ollama server.
|
|
63
|
-
|
|
64
|
-
Apart from `__init__`, all methods are private or match those of the base class.
|
|
65
|
-
"""
|
|
66
|
-
|
|
67
|
-
model_name: OllamaModelName
|
|
68
|
-
openai_model: OpenAIModel
|
|
69
|
-
|
|
70
|
-
def __init__(
|
|
71
|
-
self,
|
|
72
|
-
model_name: OllamaModelName,
|
|
73
|
-
*,
|
|
74
|
-
base_url: str | None = 'http://localhost:11434/v1/',
|
|
75
|
-
api_key: str = 'ollama',
|
|
76
|
-
openai_client: AsyncOpenAI | None = None,
|
|
77
|
-
http_client: AsyncHTTPClient | None = None,
|
|
78
|
-
):
|
|
79
|
-
"""Initialize an Ollama model.
|
|
80
|
-
|
|
81
|
-
Ollama has built-in compatability for the OpenAI chat completions API ([source](https://ollama.com/blog/openai-compatibility)), so we reuse the
|
|
82
|
-
[`OpenAIModel`][pydantic_ai.models.openai.OpenAIModel] here.
|
|
83
|
-
|
|
84
|
-
Args:
|
|
85
|
-
model_name: The name of the Ollama model to use. List of models available [here](https://ollama.com/library)
|
|
86
|
-
You must first download the model (`ollama pull <MODEL-NAME>`) in order to use the model
|
|
87
|
-
base_url: The base url for the ollama requests. The default value is the ollama default
|
|
88
|
-
api_key: The API key to use for authentication. Defaults to 'ollama' for local instances,
|
|
89
|
-
but can be customized for proxy setups that require authentication
|
|
90
|
-
openai_client: An existing
|
|
91
|
-
[`AsyncOpenAI`](https://github.com/openai/openai-python?tab=readme-ov-file#async-usage)
|
|
92
|
-
client to use, if provided, `base_url` and `http_client` must be `None`.
|
|
93
|
-
http_client: An existing `httpx.AsyncClient` to use for making HTTP requests.
|
|
94
|
-
"""
|
|
95
|
-
self.model_name = model_name
|
|
96
|
-
if openai_client is not None:
|
|
97
|
-
assert base_url is None, 'Cannot provide both `openai_client` and `base_url`'
|
|
98
|
-
assert http_client is None, 'Cannot provide both `openai_client` and `http_client`'
|
|
99
|
-
self.openai_model = OpenAIModel(model_name=model_name, openai_client=openai_client)
|
|
100
|
-
else:
|
|
101
|
-
# API key is not required for ollama but a value is required to create the client
|
|
102
|
-
http_client_ = http_client or cached_async_http_client()
|
|
103
|
-
oai_client = AsyncOpenAI(base_url=base_url, api_key=api_key, http_client=http_client_)
|
|
104
|
-
self.openai_model = OpenAIModel(model_name=model_name, openai_client=oai_client)
|
|
105
|
-
|
|
106
|
-
async def agent_model(
|
|
107
|
-
self,
|
|
108
|
-
*,
|
|
109
|
-
function_tools: list[ToolDefinition],
|
|
110
|
-
allow_text_result: bool,
|
|
111
|
-
result_tools: list[ToolDefinition],
|
|
112
|
-
) -> AgentModel:
|
|
113
|
-
return await self.openai_model.agent_model(
|
|
114
|
-
function_tools=function_tools,
|
|
115
|
-
allow_text_result=allow_text_result,
|
|
116
|
-
result_tools=result_tools,
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
def name(self) -> str:
|
|
120
|
-
return f'ollama:{self.model_name}'
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
pydantic_ai/__init__.py,sha256=FbYetEgT6OO25u2KF5ZnFxKpz5DtnSpfckRXP4mjl8E,489
|
|
2
|
-
pydantic_ai/_griffe.py,sha256=RYRKiLbgG97QxnazbAwlnc74XxevGHLQet-FGfq9qls,3960
|
|
3
|
-
pydantic_ai/_parts_manager.py,sha256=pMDZs6BGC8EmaNa-73QvuptmxdG2MhBrBLIydCOl-gM,11886
|
|
4
|
-
pydantic_ai/_pydantic.py,sha256=Zvjd2te6EzPrFnz--oDSdqwZuPw3vCiflTHriRhpNsY,8698
|
|
5
|
-
pydantic_ai/_result.py,sha256=cUSugZQV0n5Z4fFHiMqua-2xs_0S6m-rr-yd6QS3nFE,10317
|
|
6
|
-
pydantic_ai/_system_prompt.py,sha256=Fsl1K6GdQP0WhWBzvJxCc5uTqCD06lHjJlTADah-PI0,1116
|
|
7
|
-
pydantic_ai/_utils.py,sha256=EHW866W6ZpGJLCWtoEAcwIPeWo9OQFhnD5el2DwVcwc,10949
|
|
8
|
-
pydantic_ai/agent.py,sha256=Z_79gw4BIJooBIqJwPbnDHvmBcCXp2dbNd_832tc_do,62500
|
|
9
|
-
pydantic_ai/exceptions.py,sha256=eGDKX6bGhgVxXBzu81Sk3iiAkXr0GUtgT7bD5Rxlqpg,2028
|
|
10
|
-
pydantic_ai/format_as_xml.py,sha256=QE7eMlg5-YUMw1_2kcI3h0uKYPZZyGkgXFDtfZTMeeI,4480
|
|
11
|
-
pydantic_ai/messages.py,sha256=b4RpaXogREquE8WHlGPMm0UGTNx2QtePV5GYk-9EscY,18185
|
|
12
|
-
pydantic_ai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
pydantic_ai/result.py,sha256=93ZLxr2jPx0cZeslHgphJ6XJnQMEybktzQ_LUT47h3Q,17429
|
|
14
|
-
pydantic_ai/settings.py,sha256=oTk8ZfYuUsNxpJMWLvSrO1OH_0ur7VKgDNTMQG0tPyM,1974
|
|
15
|
-
pydantic_ai/tools.py,sha256=iwa2PyhnKmvh_njy4aMfRIh7AP5igDIZ1ZPvgvvn6bM,13018
|
|
16
|
-
pydantic_ai/usage.py,sha256=60d9f6M7YEYuKMbqDGDogX4KsA73fhDtWyDXYXoIPaI,4948
|
|
17
|
-
pydantic_ai/models/__init__.py,sha256=Q4_fHy48szaA_TrIW3LZhRXiDUlhPAYf8LkhinSP3s8,10883
|
|
18
|
-
pydantic_ai/models/anthropic.py,sha256=MkFqy2F7SPb_qAbgzc04iZWmVuoEBgn30v1HY1Wjadc,13543
|
|
19
|
-
pydantic_ai/models/function.py,sha256=iT4XT8VEaJbNwYJAWtrI_jbRAb2tZO6UL93ErR4RYhM,9629
|
|
20
|
-
pydantic_ai/models/gemini.py,sha256=3RTVQBAI1jWL3Xx_hi7qdy_6H-kTeuAOTPELnlVtPp4,27498
|
|
21
|
-
pydantic_ai/models/groq.py,sha256=kzQSFT-04WmQmdRaB6Wj0mxHeAXIgyrryZkptNiA4Ng,13211
|
|
22
|
-
pydantic_ai/models/mistral.py,sha256=qyYOLBpOdI5iPBmQxf5jp1d17sxqa1r8GJ7tb4yE45U,24549
|
|
23
|
-
pydantic_ai/models/ollama.py,sha256=aHI8pNw7fqOOgvlEWcTnTYTmhf0cGg41x-p5sUQr2_k,4200
|
|
24
|
-
pydantic_ai/models/openai.py,sha256=FzV6OCuK4Sr_J2GTuM-6Vu9NbDyZPxllwQPmssdOtbQ,13774
|
|
25
|
-
pydantic_ai/models/test.py,sha256=0m2Pdn0xJMjvAVekVIoADQL0aSkOnGZJct9k4WvImrQ,15880
|
|
26
|
-
pydantic_ai/models/vertexai.py,sha256=dHGrmLMgekWAEOZkLsO5rwDtQ6mjPixvn0umlvWAZok,9323
|
|
27
|
-
pydantic_ai_slim-0.0.19.dist-info/METADATA,sha256=lnGlda0-tCapsWI72DyzGV9Sppm5I7koWbb7-xEpWcU,2808
|
|
28
|
-
pydantic_ai_slim-0.0.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
29
|
-
pydantic_ai_slim-0.0.19.dist-info/RECORD,,
|
|
File without changes
|