pydantic-ai-slim 0.0.10__py3-none-any.whl → 0.0.12__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/_pydantic.py +6 -4
- pydantic_ai/_result.py +18 -22
- pydantic_ai/_system_prompt.py +1 -1
- pydantic_ai/_utils.py +11 -6
- pydantic_ai/agent.py +156 -69
- pydantic_ai/messages.py +5 -2
- pydantic_ai/models/__init__.py +30 -37
- pydantic_ai/models/function.py +8 -14
- pydantic_ai/models/gemini.py +11 -10
- pydantic_ai/models/groq.py +31 -34
- pydantic_ai/models/ollama.py +116 -0
- pydantic_ai/models/openai.py +43 -38
- pydantic_ai/models/test.py +70 -49
- pydantic_ai/models/vertexai.py +7 -6
- pydantic_ai/tools.py +119 -34
- {pydantic_ai_slim-0.0.10.dist-info → pydantic_ai_slim-0.0.12.dist-info}/METADATA +1 -1
- pydantic_ai_slim-0.0.12.dist-info/RECORD +23 -0
- pydantic_ai_slim-0.0.10.dist-info/RECORD +0 -22
- {pydantic_ai_slim-0.0.10.dist-info → pydantic_ai_slim-0.0.12.dist-info}/WHEEL +0 -0
pydantic_ai/_pydantic.py
CHANGED
|
@@ -17,10 +17,10 @@ from pydantic.plugin._schema_validator import create_schema_validator
|
|
|
17
17
|
from pydantic_core import SchemaValidator, core_schema
|
|
18
18
|
|
|
19
19
|
from ._griffe import doc_descriptions
|
|
20
|
-
from ._utils import
|
|
20
|
+
from ._utils import check_object_json_schema, is_model_like
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
|
-
|
|
23
|
+
from .tools import ObjectJsonSchema
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
__all__ = 'function_schema', 'LazyTypeAdapter'
|
|
@@ -168,11 +168,13 @@ def takes_ctx(function: Callable[..., Any]) -> bool:
|
|
|
168
168
|
"""
|
|
169
169
|
sig = signature(function)
|
|
170
170
|
try:
|
|
171
|
-
|
|
171
|
+
first_param_name = next(iter(sig.parameters.keys()))
|
|
172
172
|
except StopIteration:
|
|
173
173
|
return False
|
|
174
174
|
else:
|
|
175
|
-
|
|
175
|
+
type_hints = _typing_extra.get_function_type_hints(function)
|
|
176
|
+
annotation = type_hints[first_param_name]
|
|
177
|
+
return annotation is not sig.empty and _is_call_ctx(annotation)
|
|
176
178
|
|
|
177
179
|
|
|
178
180
|
def _build_schema(
|
pydantic_ai/_result.py
CHANGED
|
@@ -14,7 +14,7 @@ from . import _utils, messages
|
|
|
14
14
|
from .exceptions import ModelRetry
|
|
15
15
|
from .messages import ModelStructuredResponse, ToolCall
|
|
16
16
|
from .result import ResultData
|
|
17
|
-
from .tools import AgentDeps, ResultValidatorFunc, RunContext
|
|
17
|
+
from .tools import AgentDeps, ResultValidatorFunc, RunContext, ToolDefinition
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
@dataclass
|
|
@@ -94,10 +94,7 @@ class ResultSchema(Generic[ResultData]):
|
|
|
94
94
|
allow_text_result = False
|
|
95
95
|
|
|
96
96
|
def _build_tool(a: Any, tool_name_: str, multiple: bool) -> ResultTool[ResultData]:
|
|
97
|
-
return cast(
|
|
98
|
-
ResultTool[ResultData],
|
|
99
|
-
ResultTool.build(a, tool_name_, description, multiple), # pyright: ignore[reportUnknownMemberType]
|
|
100
|
-
)
|
|
97
|
+
return cast(ResultTool[ResultData], ResultTool(a, tool_name_, description, multiple))
|
|
101
98
|
|
|
102
99
|
tools: dict[str, ResultTool[ResultData]] = {}
|
|
103
100
|
if args := get_union_args(response_type):
|
|
@@ -121,38 +118,38 @@ class ResultSchema(Generic[ResultData]):
|
|
|
121
118
|
"""Return the names of the tools."""
|
|
122
119
|
return list(self.tools.keys())
|
|
123
120
|
|
|
121
|
+
def tool_defs(self) -> list[ToolDefinition]:
|
|
122
|
+
"""Get tool definitions to register with the model."""
|
|
123
|
+
return [t.tool_def for t in self.tools.values()]
|
|
124
|
+
|
|
124
125
|
|
|
125
126
|
DEFAULT_DESCRIPTION = 'The final response which ends this conversation'
|
|
126
127
|
|
|
127
128
|
|
|
128
|
-
@dataclass
|
|
129
|
+
@dataclass(init=False)
|
|
129
130
|
class ResultTool(Generic[ResultData]):
|
|
130
|
-
|
|
131
|
-
description: str
|
|
131
|
+
tool_def: ToolDefinition
|
|
132
132
|
type_adapter: TypeAdapter[Any]
|
|
133
|
-
json_schema: _utils.ObjectJsonSchema
|
|
134
|
-
outer_typed_dict_key: str | None
|
|
135
133
|
|
|
136
|
-
|
|
137
|
-
def build(cls, response_type: type[ResultData], name: str, description: str | None, multiple: bool) -> Self | None:
|
|
134
|
+
def __init__(self, response_type: type[ResultData], name: str, description: str | None, multiple: bool):
|
|
138
135
|
"""Build a ResultTool dataclass from a response type."""
|
|
139
136
|
assert response_type is not str, 'ResultTool does not support str as a response type'
|
|
140
137
|
|
|
141
138
|
if _utils.is_model_like(response_type):
|
|
142
|
-
type_adapter = TypeAdapter(response_type)
|
|
139
|
+
self.type_adapter = TypeAdapter(response_type)
|
|
143
140
|
outer_typed_dict_key: str | None = None
|
|
144
141
|
# noinspection PyArgumentList
|
|
145
|
-
|
|
142
|
+
parameters_json_schema = _utils.check_object_json_schema(self.type_adapter.json_schema())
|
|
146
143
|
else:
|
|
147
144
|
response_data_typed_dict = TypedDict('response_data_typed_dict', {'response': response_type}) # noqa
|
|
148
|
-
type_adapter = TypeAdapter(response_data_typed_dict)
|
|
145
|
+
self.type_adapter = TypeAdapter(response_data_typed_dict)
|
|
149
146
|
outer_typed_dict_key = 'response'
|
|
150
147
|
# noinspection PyArgumentList
|
|
151
|
-
|
|
148
|
+
parameters_json_schema = _utils.check_object_json_schema(self.type_adapter.json_schema())
|
|
152
149
|
# including `response_data_typed_dict` as a title here doesn't add anything and could confuse the LLM
|
|
153
|
-
|
|
150
|
+
parameters_json_schema.pop('title')
|
|
154
151
|
|
|
155
|
-
if json_schema_description :=
|
|
152
|
+
if json_schema_description := parameters_json_schema.pop('description', None):
|
|
156
153
|
if description is None:
|
|
157
154
|
tool_description = json_schema_description
|
|
158
155
|
else:
|
|
@@ -162,11 +159,10 @@ class ResultTool(Generic[ResultData]):
|
|
|
162
159
|
if multiple:
|
|
163
160
|
tool_description = f'{union_arg_name(response_type)}: {tool_description}'
|
|
164
161
|
|
|
165
|
-
|
|
162
|
+
self.tool_def = ToolDefinition(
|
|
166
163
|
name=name,
|
|
167
164
|
description=tool_description,
|
|
168
|
-
|
|
169
|
-
json_schema=json_schema,
|
|
165
|
+
parameters_json_schema=parameters_json_schema,
|
|
170
166
|
outer_typed_dict_key=outer_typed_dict_key,
|
|
171
167
|
)
|
|
172
168
|
|
|
@@ -204,7 +200,7 @@ class ResultTool(Generic[ResultData]):
|
|
|
204
200
|
else:
|
|
205
201
|
raise
|
|
206
202
|
else:
|
|
207
|
-
if k := self.outer_typed_dict_key:
|
|
203
|
+
if k := self.tool_def.outer_typed_dict_key:
|
|
208
204
|
result = result[k]
|
|
209
205
|
return result
|
|
210
206
|
|
pydantic_ai/_system_prompt.py
CHANGED
pydantic_ai/_utils.py
CHANGED
|
@@ -8,12 +8,15 @@ from dataclasses import dataclass, is_dataclass
|
|
|
8
8
|
from datetime import datetime, timezone
|
|
9
9
|
from functools import partial
|
|
10
10
|
from types import GenericAlias
|
|
11
|
-
from typing import Any, Callable, Generic, TypeVar, Union, cast, overload
|
|
11
|
+
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, Union, cast, overload
|
|
12
12
|
|
|
13
13
|
from pydantic import BaseModel
|
|
14
14
|
from pydantic.json_schema import JsonSchemaValue
|
|
15
15
|
from typing_extensions import ParamSpec, TypeAlias, TypeGuard, is_typeddict
|
|
16
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from .tools import ObjectJsonSchema
|
|
19
|
+
|
|
17
20
|
_P = ParamSpec('_P')
|
|
18
21
|
_R = TypeVar('_R')
|
|
19
22
|
|
|
@@ -39,10 +42,6 @@ def is_model_like(type_: Any) -> bool:
|
|
|
39
42
|
)
|
|
40
43
|
|
|
41
44
|
|
|
42
|
-
# With PEP-728 this should be a TypedDict with `type: Literal['object']`, and `extra_items=Any`
|
|
43
|
-
ObjectJsonSchema: TypeAlias = dict[str, Any]
|
|
44
|
-
|
|
45
|
-
|
|
46
45
|
def check_object_json_schema(schema: JsonSchemaValue) -> ObjectJsonSchema:
|
|
47
46
|
from .exceptions import UserError
|
|
48
47
|
|
|
@@ -127,6 +126,12 @@ class Either(Generic[Left, Right]):
|
|
|
127
126
|
def whichever(self) -> Left | Right:
|
|
128
127
|
return self._left.value if self._left is not None else self.right
|
|
129
128
|
|
|
129
|
+
def __repr__(self):
|
|
130
|
+
if left := self._left:
|
|
131
|
+
return f'Either(left={left.value!r})'
|
|
132
|
+
else:
|
|
133
|
+
return f'Either(right={self.right!r})'
|
|
134
|
+
|
|
130
135
|
|
|
131
136
|
@asynccontextmanager
|
|
132
137
|
async def group_by_temporal(
|
|
@@ -218,7 +223,7 @@ async def group_by_temporal(
|
|
|
218
223
|
|
|
219
224
|
try:
|
|
220
225
|
yield async_iter_groups()
|
|
221
|
-
finally:
|
|
226
|
+
finally: # pragma: no cover
|
|
222
227
|
# after iteration if a tasks still exists, cancel it, this will only happen if an error occurred
|
|
223
228
|
if task:
|
|
224
229
|
task.cancel('Cancelling due to error in iterator')
|