pydantic-ai-slim 0.0.35__py3-none-any.whl → 0.0.37__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 +2 -2
- pydantic_ai/agent.py +18 -4
- pydantic_ai/common_tools/duckduckgo.py +1 -1
- pydantic_ai/common_tools/tavily.py +2 -1
- pydantic_ai/messages.py +3 -1
- pydantic_ai/models/__init__.py +53 -1
- pydantic_ai/models/anthropic.py +4 -0
- pydantic_ai/models/bedrock.py +455 -0
- pydantic_ai/models/cohere.py +5 -0
- pydantic_ai/models/fallback.py +4 -0
- pydantic_ai/models/gemini.py +3 -2
- pydantic_ai/models/groq.py +4 -0
- pydantic_ai/models/instrumented.py +10 -2
- pydantic_ai/models/mistral.py +4 -0
- pydantic_ai/models/openai.py +4 -0
- pydantic_ai/models/vertexai.py +15 -24
- pydantic_ai/providers/__init__.py +5 -0
- pydantic_ai/providers/bedrock.py +76 -0
- pydantic_ai/providers/google_vertex.py +64 -28
- pydantic_ai/settings.py +3 -0
- {pydantic_ai_slim-0.0.35.dist-info → pydantic_ai_slim-0.0.37.dist-info}/METADATA +4 -2
- pydantic_ai_slim-0.0.37.dist-info/RECORD +45 -0
- pydantic_ai_slim-0.0.35.dist-info/RECORD +0 -43
- {pydantic_ai_slim-0.0.35.dist-info → pydantic_ai_slim-0.0.37.dist-info}/WHEEL +0 -0
- {pydantic_ai_slim-0.0.35.dist-info → pydantic_ai_slim-0.0.37.dist-info}/entry_points.txt +0 -0
pydantic_ai/_pydantic.py
CHANGED
|
@@ -6,7 +6,7 @@ This module has to use numerous internal Pydantic APIs and is therefore brittle
|
|
|
6
6
|
from __future__ import annotations as _annotations
|
|
7
7
|
|
|
8
8
|
from inspect import Parameter, signature
|
|
9
|
-
from typing import TYPE_CHECKING, Any, Callable,
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable, cast
|
|
10
10
|
|
|
11
11
|
from pydantic import ConfigDict
|
|
12
12
|
from pydantic._internal import _decorators, _generate_schema, _typing_extra
|
|
@@ -15,7 +15,7 @@ from pydantic.fields import FieldInfo
|
|
|
15
15
|
from pydantic.json_schema import GenerateJsonSchema
|
|
16
16
|
from pydantic.plugin._schema_validator import create_schema_validator
|
|
17
17
|
from pydantic_core import SchemaValidator, core_schema
|
|
18
|
-
from typing_extensions import get_origin
|
|
18
|
+
from typing_extensions import TypedDict, get_origin
|
|
19
19
|
|
|
20
20
|
from ._griffe import doc_descriptions
|
|
21
21
|
from ._utils import check_object_json_schema, is_model_like
|
pydantic_ai/agent.py
CHANGED
|
@@ -922,6 +922,7 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
922
922
|
self,
|
|
923
923
|
/,
|
|
924
924
|
*,
|
|
925
|
+
name: str | None = None,
|
|
925
926
|
retries: int | None = None,
|
|
926
927
|
prepare: ToolPrepareFunc[AgentDepsT] | None = None,
|
|
927
928
|
docstring_format: DocstringFormat = 'auto',
|
|
@@ -933,6 +934,7 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
933
934
|
func: ToolFuncContext[AgentDepsT, ToolParams] | None = None,
|
|
934
935
|
/,
|
|
935
936
|
*,
|
|
937
|
+
name: str | None = None,
|
|
936
938
|
retries: int | None = None,
|
|
937
939
|
prepare: ToolPrepareFunc[AgentDepsT] | None = None,
|
|
938
940
|
docstring_format: DocstringFormat = 'auto',
|
|
@@ -969,6 +971,7 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
969
971
|
|
|
970
972
|
Args:
|
|
971
973
|
func: The tool function to register.
|
|
974
|
+
name: The name of the tool, defaults to the function name.
|
|
972
975
|
retries: The number of retries to allow for this tool, defaults to the agent's default retries,
|
|
973
976
|
which defaults to 1.
|
|
974
977
|
prepare: custom method to prepare the tool definition for each step, return `None` to omit this
|
|
@@ -984,13 +987,17 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
984
987
|
func_: ToolFuncContext[AgentDepsT, ToolParams],
|
|
985
988
|
) -> ToolFuncContext[AgentDepsT, ToolParams]:
|
|
986
989
|
# noinspection PyTypeChecker
|
|
987
|
-
self._register_function(
|
|
990
|
+
self._register_function(
|
|
991
|
+
func_, True, name, retries, prepare, docstring_format, require_parameter_descriptions
|
|
992
|
+
)
|
|
988
993
|
return func_
|
|
989
994
|
|
|
990
995
|
return tool_decorator
|
|
991
996
|
else:
|
|
992
997
|
# noinspection PyTypeChecker
|
|
993
|
-
self._register_function(
|
|
998
|
+
self._register_function(
|
|
999
|
+
func, True, name, retries, prepare, docstring_format, require_parameter_descriptions
|
|
1000
|
+
)
|
|
994
1001
|
return func
|
|
995
1002
|
|
|
996
1003
|
@overload
|
|
@@ -1001,6 +1008,7 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
1001
1008
|
self,
|
|
1002
1009
|
/,
|
|
1003
1010
|
*,
|
|
1011
|
+
name: str | None = None,
|
|
1004
1012
|
retries: int | None = None,
|
|
1005
1013
|
prepare: ToolPrepareFunc[AgentDepsT] | None = None,
|
|
1006
1014
|
docstring_format: DocstringFormat = 'auto',
|
|
@@ -1012,6 +1020,7 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
1012
1020
|
func: ToolFuncPlain[ToolParams] | None = None,
|
|
1013
1021
|
/,
|
|
1014
1022
|
*,
|
|
1023
|
+
name: str | None = None,
|
|
1015
1024
|
retries: int | None = None,
|
|
1016
1025
|
prepare: ToolPrepareFunc[AgentDepsT] | None = None,
|
|
1017
1026
|
docstring_format: DocstringFormat = 'auto',
|
|
@@ -1048,6 +1057,7 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
1048
1057
|
|
|
1049
1058
|
Args:
|
|
1050
1059
|
func: The tool function to register.
|
|
1060
|
+
name: The name of the tool, defaults to the function name.
|
|
1051
1061
|
retries: The number of retries to allow for this tool, defaults to the agent's default retries,
|
|
1052
1062
|
which defaults to 1.
|
|
1053
1063
|
prepare: custom method to prepare the tool definition for each step, return `None` to omit this
|
|
@@ -1062,19 +1072,22 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
1062
1072
|
def tool_decorator(func_: ToolFuncPlain[ToolParams]) -> ToolFuncPlain[ToolParams]:
|
|
1063
1073
|
# noinspection PyTypeChecker
|
|
1064
1074
|
self._register_function(
|
|
1065
|
-
func_, False, retries, prepare, docstring_format, require_parameter_descriptions
|
|
1075
|
+
func_, False, name, retries, prepare, docstring_format, require_parameter_descriptions
|
|
1066
1076
|
)
|
|
1067
1077
|
return func_
|
|
1068
1078
|
|
|
1069
1079
|
return tool_decorator
|
|
1070
1080
|
else:
|
|
1071
|
-
self._register_function(
|
|
1081
|
+
self._register_function(
|
|
1082
|
+
func, False, name, retries, prepare, docstring_format, require_parameter_descriptions
|
|
1083
|
+
)
|
|
1072
1084
|
return func
|
|
1073
1085
|
|
|
1074
1086
|
def _register_function(
|
|
1075
1087
|
self,
|
|
1076
1088
|
func: ToolFuncEither[AgentDepsT, ToolParams],
|
|
1077
1089
|
takes_ctx: bool,
|
|
1090
|
+
name: str | None,
|
|
1078
1091
|
retries: int | None,
|
|
1079
1092
|
prepare: ToolPrepareFunc[AgentDepsT] | None,
|
|
1080
1093
|
docstring_format: DocstringFormat,
|
|
@@ -1085,6 +1098,7 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
|
|
|
1085
1098
|
tool = Tool[AgentDepsT](
|
|
1086
1099
|
func,
|
|
1087
1100
|
takes_ctx=takes_ctx,
|
|
1101
|
+
name=name,
|
|
1088
1102
|
max_retries=retries_,
|
|
1089
1103
|
prepare=prepare,
|
|
1090
1104
|
docstring_format=docstring_format,
|
pydantic_ai/messages.py
CHANGED
|
@@ -395,7 +395,9 @@ class ModelResponse:
|
|
|
395
395
|
ModelMessage = Annotated[Union[ModelRequest, ModelResponse], pydantic.Discriminator('kind')]
|
|
396
396
|
"""Any message sent to or returned by a model."""
|
|
397
397
|
|
|
398
|
-
ModelMessagesTypeAdapter = pydantic.TypeAdapter(
|
|
398
|
+
ModelMessagesTypeAdapter = pydantic.TypeAdapter(
|
|
399
|
+
list[ModelMessage], config=pydantic.ConfigDict(defer_build=True, ser_json_bytes='base64')
|
|
400
|
+
)
|
|
399
401
|
"""Pydantic [`TypeAdapter`][pydantic.type_adapter.TypeAdapter] for (de)serializing messages."""
|
|
400
402
|
|
|
401
403
|
|
pydantic_ai/models/__init__.py
CHANGED
|
@@ -34,6 +34,49 @@ KnownModelName = Literal[
|
|
|
34
34
|
'anthropic:claude-3-opus-latest',
|
|
35
35
|
'claude-3-7-sonnet-latest',
|
|
36
36
|
'claude-3-5-haiku-latest',
|
|
37
|
+
'bedrock:amazon.titan-tg1-large',
|
|
38
|
+
'bedrock:amazon.titan-text-lite-v1',
|
|
39
|
+
'bedrock:amazon.titan-text-express-v1',
|
|
40
|
+
'bedrock:us.amazon.nova-pro-v1:0',
|
|
41
|
+
'bedrock:us.amazon.nova-lite-v1:0',
|
|
42
|
+
'bedrock:us.amazon.nova-micro-v1:0',
|
|
43
|
+
'bedrock:anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
44
|
+
'bedrock:us.anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
45
|
+
'bedrock:anthropic.claude-3-5-haiku-20241022-v1:0',
|
|
46
|
+
'bedrock:us.anthropic.claude-3-5-haiku-20241022-v1:0',
|
|
47
|
+
'bedrock:anthropic.claude-instant-v1',
|
|
48
|
+
'bedrock:anthropic.claude-v2:1',
|
|
49
|
+
'bedrock:anthropic.claude-v2',
|
|
50
|
+
'bedrock:anthropic.claude-3-sonnet-20240229-v1:0',
|
|
51
|
+
'bedrock:us.anthropic.claude-3-sonnet-20240229-v1:0',
|
|
52
|
+
'bedrock:anthropic.claude-3-haiku-20240307-v1:0',
|
|
53
|
+
'bedrock:us.anthropic.claude-3-haiku-20240307-v1:0',
|
|
54
|
+
'bedrock:anthropic.claude-3-opus-20240229-v1:0',
|
|
55
|
+
'bedrock:us.anthropic.claude-3-opus-20240229-v1:0',
|
|
56
|
+
'bedrock:anthropic.claude-3-5-sonnet-20240620-v1:0',
|
|
57
|
+
'bedrock:us.anthropic.claude-3-5-sonnet-20240620-v1:0',
|
|
58
|
+
'bedrock:anthropic.claude-3-7-sonnet-20250219-v1:0',
|
|
59
|
+
'bedrock:us.anthropic.claude-3-7-sonnet-20250219-v1:0',
|
|
60
|
+
'bedrock:cohere.command-text-v14',
|
|
61
|
+
'bedrock:cohere.command-r-v1:0',
|
|
62
|
+
'bedrock:cohere.command-r-plus-v1:0',
|
|
63
|
+
'bedrock:cohere.command-light-text-v14',
|
|
64
|
+
'bedrock:meta.llama3-8b-instruct-v1:0',
|
|
65
|
+
'bedrock:meta.llama3-70b-instruct-v1:0',
|
|
66
|
+
'bedrock:meta.llama3-1-8b-instruct-v1:0',
|
|
67
|
+
'bedrock:us.meta.llama3-1-8b-instruct-v1:0',
|
|
68
|
+
'bedrock:meta.llama3-1-70b-instruct-v1:0',
|
|
69
|
+
'bedrock:us.meta.llama3-1-70b-instruct-v1:0',
|
|
70
|
+
'bedrock:meta.llama3-1-405b-instruct-v1:0',
|
|
71
|
+
'bedrock:us.meta.llama3-2-11b-instruct-v1:0',
|
|
72
|
+
'bedrock:us.meta.llama3-2-90b-instruct-v1:0',
|
|
73
|
+
'bedrock:us.meta.llama3-2-1b-instruct-v1:0',
|
|
74
|
+
'bedrock:us.meta.llama3-2-3b-instruct-v1:0',
|
|
75
|
+
'bedrock:us.meta.llama3-3-70b-instruct-v1:0',
|
|
76
|
+
'bedrock:mistral.mistral-7b-instruct-v0:2',
|
|
77
|
+
'bedrock:mistral.mixtral-8x7b-instruct-v0:1',
|
|
78
|
+
'bedrock:mistral.mistral-large-2402-v1:0',
|
|
79
|
+
'bedrock:mistral.mistral-large-2407-v1:0',
|
|
37
80
|
'claude-3-5-sonnet-latest',
|
|
38
81
|
'claude-3-opus-latest',
|
|
39
82
|
'cohere:c4ai-aya-expanse-32b',
|
|
@@ -223,6 +266,11 @@ class Model(ABC):
|
|
|
223
266
|
"""The system / model provider, ex: openai."""
|
|
224
267
|
raise NotImplementedError()
|
|
225
268
|
|
|
269
|
+
@property
|
|
270
|
+
def base_url(self) -> str | None:
|
|
271
|
+
"""The base URL for the provider API, if available."""
|
|
272
|
+
return None
|
|
273
|
+
|
|
226
274
|
|
|
227
275
|
@dataclass
|
|
228
276
|
class StreamedResponse(ABC):
|
|
@@ -324,7 +372,7 @@ def infer_model(model: Model | KnownModelName) -> Model:
|
|
|
324
372
|
return TestModel()
|
|
325
373
|
|
|
326
374
|
try:
|
|
327
|
-
provider, model_name = model.split(':')
|
|
375
|
+
provider, model_name = model.split(':', maxsplit=1)
|
|
328
376
|
except ValueError:
|
|
329
377
|
model_name = model
|
|
330
378
|
# TODO(Marcelo): We should deprecate this way.
|
|
@@ -368,6 +416,10 @@ def infer_model(model: Model | KnownModelName) -> Model:
|
|
|
368
416
|
|
|
369
417
|
# TODO(Marcelo): Missing provider API.
|
|
370
418
|
return AnthropicModel(model_name)
|
|
419
|
+
elif provider == 'bedrock':
|
|
420
|
+
from .bedrock import BedrockConverseModel
|
|
421
|
+
|
|
422
|
+
return BedrockConverseModel(model_name)
|
|
371
423
|
else:
|
|
372
424
|
raise UserError(f'Unknown model: {model}')
|
|
373
425
|
|
pydantic_ai/models/anthropic.py
CHANGED
|
@@ -143,6 +143,10 @@ class AnthropicModel(Model):
|
|
|
143
143
|
else:
|
|
144
144
|
self.client = AsyncAnthropic(api_key=api_key, http_client=cached_async_http_client())
|
|
145
145
|
|
|
146
|
+
@property
|
|
147
|
+
def base_url(self) -> str:
|
|
148
|
+
return str(self.client.base_url)
|
|
149
|
+
|
|
146
150
|
async def request(
|
|
147
151
|
self,
|
|
148
152
|
messages: list[ModelMessage],
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import functools
|
|
4
|
+
import typing
|
|
5
|
+
from collections.abc import AsyncIterator, Iterable
|
|
6
|
+
from contextlib import asynccontextmanager
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import TYPE_CHECKING, Generic, Literal, Union, cast, overload
|
|
10
|
+
|
|
11
|
+
import anyio
|
|
12
|
+
import anyio.to_thread
|
|
13
|
+
from typing_extensions import ParamSpec, assert_never
|
|
14
|
+
|
|
15
|
+
from pydantic_ai import _utils, result
|
|
16
|
+
from pydantic_ai.messages import (
|
|
17
|
+
ModelMessage,
|
|
18
|
+
ModelRequest,
|
|
19
|
+
ModelResponse,
|
|
20
|
+
ModelResponsePart,
|
|
21
|
+
ModelResponseStreamEvent,
|
|
22
|
+
RetryPromptPart,
|
|
23
|
+
SystemPromptPart,
|
|
24
|
+
TextPart,
|
|
25
|
+
ToolCallPart,
|
|
26
|
+
ToolReturnPart,
|
|
27
|
+
UserPromptPart,
|
|
28
|
+
)
|
|
29
|
+
from pydantic_ai.models import Model, ModelRequestParameters, StreamedResponse
|
|
30
|
+
from pydantic_ai.providers import Provider, infer_provider
|
|
31
|
+
from pydantic_ai.settings import ModelSettings
|
|
32
|
+
from pydantic_ai.tools import ToolDefinition
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from botocore.client import BaseClient
|
|
36
|
+
from botocore.eventstream import EventStream
|
|
37
|
+
from mypy_boto3_bedrock_runtime import BedrockRuntimeClient
|
|
38
|
+
from mypy_boto3_bedrock_runtime.type_defs import (
|
|
39
|
+
ContentBlockOutputTypeDef,
|
|
40
|
+
ConverseResponseTypeDef,
|
|
41
|
+
ConverseStreamMetadataEventTypeDef,
|
|
42
|
+
ConverseStreamOutputTypeDef,
|
|
43
|
+
InferenceConfigurationTypeDef,
|
|
44
|
+
MessageUnionTypeDef,
|
|
45
|
+
ToolChoiceTypeDef,
|
|
46
|
+
ToolTypeDef,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
LatestBedrockModelNames = Literal[
|
|
51
|
+
'amazon.titan-tg1-large',
|
|
52
|
+
'amazon.titan-text-lite-v1',
|
|
53
|
+
'amazon.titan-text-express-v1',
|
|
54
|
+
'us.amazon.nova-pro-v1:0',
|
|
55
|
+
'us.amazon.nova-lite-v1:0',
|
|
56
|
+
'us.amazon.nova-micro-v1:0',
|
|
57
|
+
'anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
58
|
+
'us.anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
59
|
+
'anthropic.claude-3-5-haiku-20241022-v1:0',
|
|
60
|
+
'us.anthropic.claude-3-5-haiku-20241022-v1:0',
|
|
61
|
+
'anthropic.claude-instant-v1',
|
|
62
|
+
'anthropic.claude-v2:1',
|
|
63
|
+
'anthropic.claude-v2',
|
|
64
|
+
'anthropic.claude-3-sonnet-20240229-v1:0',
|
|
65
|
+
'us.anthropic.claude-3-sonnet-20240229-v1:0',
|
|
66
|
+
'anthropic.claude-3-haiku-20240307-v1:0',
|
|
67
|
+
'us.anthropic.claude-3-haiku-20240307-v1:0',
|
|
68
|
+
'anthropic.claude-3-opus-20240229-v1:0',
|
|
69
|
+
'us.anthropic.claude-3-opus-20240229-v1:0',
|
|
70
|
+
'anthropic.claude-3-5-sonnet-20240620-v1:0',
|
|
71
|
+
'us.anthropic.claude-3-5-sonnet-20240620-v1:0',
|
|
72
|
+
'anthropic.claude-3-7-sonnet-20250219-v1:0',
|
|
73
|
+
'us.anthropic.claude-3-7-sonnet-20250219-v1:0',
|
|
74
|
+
'cohere.command-text-v14',
|
|
75
|
+
'cohere.command-r-v1:0',
|
|
76
|
+
'cohere.command-r-plus-v1:0',
|
|
77
|
+
'cohere.command-light-text-v14',
|
|
78
|
+
'meta.llama3-8b-instruct-v1:0',
|
|
79
|
+
'meta.llama3-70b-instruct-v1:0',
|
|
80
|
+
'meta.llama3-1-8b-instruct-v1:0',
|
|
81
|
+
'us.meta.llama3-1-8b-instruct-v1:0',
|
|
82
|
+
'meta.llama3-1-70b-instruct-v1:0',
|
|
83
|
+
'us.meta.llama3-1-70b-instruct-v1:0',
|
|
84
|
+
'meta.llama3-1-405b-instruct-v1:0',
|
|
85
|
+
'us.meta.llama3-2-11b-instruct-v1:0',
|
|
86
|
+
'us.meta.llama3-2-90b-instruct-v1:0',
|
|
87
|
+
'us.meta.llama3-2-1b-instruct-v1:0',
|
|
88
|
+
'us.meta.llama3-2-3b-instruct-v1:0',
|
|
89
|
+
'us.meta.llama3-3-70b-instruct-v1:0',
|
|
90
|
+
'mistral.mistral-7b-instruct-v0:2',
|
|
91
|
+
'mistral.mixtral-8x7b-instruct-v0:1',
|
|
92
|
+
'mistral.mistral-large-2402-v1:0',
|
|
93
|
+
'mistral.mistral-large-2407-v1:0',
|
|
94
|
+
]
|
|
95
|
+
"""Latest Bedrock models."""
|
|
96
|
+
|
|
97
|
+
BedrockModelName = Union[str, LatestBedrockModelNames]
|
|
98
|
+
"""Possible Bedrock model names.
|
|
99
|
+
|
|
100
|
+
Since Bedrock supports a variety of date-stamped models, we explicitly list the latest models but allow any name in the type hints.
|
|
101
|
+
See [the Bedrock docs](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) for a full list.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
P = ParamSpec('P')
|
|
106
|
+
T = typing.TypeVar('T')
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@dataclass(init=False)
|
|
110
|
+
class BedrockConverseModel(Model):
|
|
111
|
+
"""A model that uses the Bedrock Converse API."""
|
|
112
|
+
|
|
113
|
+
client: BedrockRuntimeClient
|
|
114
|
+
|
|
115
|
+
_model_name: BedrockModelName = field(repr=False)
|
|
116
|
+
_system: str | None = field(default='bedrock', repr=False)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def model_name(self) -> str:
|
|
120
|
+
"""The model name."""
|
|
121
|
+
return self._model_name
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def system(self) -> str | None:
|
|
125
|
+
"""The system / model provider, ex: openai."""
|
|
126
|
+
return self._system
|
|
127
|
+
|
|
128
|
+
def __init__(
|
|
129
|
+
self,
|
|
130
|
+
model_name: BedrockModelName,
|
|
131
|
+
*,
|
|
132
|
+
provider: Literal['bedrock'] | Provider[BaseClient] = 'bedrock',
|
|
133
|
+
):
|
|
134
|
+
"""Initialize a Bedrock model.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
model_name: The name of the model to use.
|
|
138
|
+
model_name: The name of the Bedrock model to use. List of model names available
|
|
139
|
+
[here](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html).
|
|
140
|
+
provider: The provider to use. Defaults to `'bedrock'`.
|
|
141
|
+
"""
|
|
142
|
+
self._model_name = model_name
|
|
143
|
+
|
|
144
|
+
if isinstance(provider, str):
|
|
145
|
+
self.client = infer_provider(provider).client
|
|
146
|
+
else:
|
|
147
|
+
self.client = cast('BedrockRuntimeClient', provider.client)
|
|
148
|
+
|
|
149
|
+
def _get_tools(self, model_request_parameters: ModelRequestParameters) -> list[ToolTypeDef]:
|
|
150
|
+
tools = [self._map_tool_definition(r) for r in model_request_parameters.function_tools]
|
|
151
|
+
if model_request_parameters.result_tools:
|
|
152
|
+
tools += [self._map_tool_definition(r) for r in model_request_parameters.result_tools]
|
|
153
|
+
return tools
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def _map_tool_definition(f: ToolDefinition) -> ToolTypeDef:
|
|
157
|
+
return {
|
|
158
|
+
'toolSpec': {
|
|
159
|
+
'name': f.name,
|
|
160
|
+
'description': f.description,
|
|
161
|
+
'inputSchema': {'json': f.parameters_json_schema},
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def base_url(self) -> str:
|
|
167
|
+
return str(self.client.meta.endpoint_url)
|
|
168
|
+
|
|
169
|
+
async def request(
|
|
170
|
+
self,
|
|
171
|
+
messages: list[ModelMessage],
|
|
172
|
+
model_settings: ModelSettings | None,
|
|
173
|
+
model_request_parameters: ModelRequestParameters,
|
|
174
|
+
) -> tuple[ModelResponse, result.Usage]:
|
|
175
|
+
response = await self._messages_create(messages, False, model_settings, model_request_parameters)
|
|
176
|
+
return await self._process_response(response)
|
|
177
|
+
|
|
178
|
+
@asynccontextmanager
|
|
179
|
+
async def request_stream(
|
|
180
|
+
self,
|
|
181
|
+
messages: list[ModelMessage],
|
|
182
|
+
model_settings: ModelSettings | None,
|
|
183
|
+
model_request_parameters: ModelRequestParameters,
|
|
184
|
+
) -> AsyncIterator[StreamedResponse]:
|
|
185
|
+
response = await self._messages_create(messages, True, model_settings, model_request_parameters)
|
|
186
|
+
yield BedrockStreamedResponse(_model_name=self.model_name, _event_stream=response)
|
|
187
|
+
|
|
188
|
+
async def _process_response(self, response: ConverseResponseTypeDef) -> tuple[ModelResponse, result.Usage]:
|
|
189
|
+
items: list[ModelResponsePart] = []
|
|
190
|
+
if message := response['output'].get('message'):
|
|
191
|
+
for item in message['content']:
|
|
192
|
+
if text := item.get('text'):
|
|
193
|
+
items.append(TextPart(content=text))
|
|
194
|
+
else:
|
|
195
|
+
tool_use = item.get('toolUse')
|
|
196
|
+
assert tool_use is not None, f'Found a content that is not a text or tool use: {item}'
|
|
197
|
+
items.append(
|
|
198
|
+
ToolCallPart(
|
|
199
|
+
tool_name=tool_use['name'],
|
|
200
|
+
args=tool_use['input'],
|
|
201
|
+
tool_call_id=tool_use['toolUseId'],
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
usage = result.Usage(
|
|
205
|
+
request_tokens=response['usage']['inputTokens'],
|
|
206
|
+
response_tokens=response['usage']['outputTokens'],
|
|
207
|
+
total_tokens=response['usage']['totalTokens'],
|
|
208
|
+
)
|
|
209
|
+
return ModelResponse(items, model_name=self.model_name), usage
|
|
210
|
+
|
|
211
|
+
@overload
|
|
212
|
+
async def _messages_create(
|
|
213
|
+
self,
|
|
214
|
+
messages: list[ModelMessage],
|
|
215
|
+
stream: Literal[True],
|
|
216
|
+
model_settings: ModelSettings | None,
|
|
217
|
+
model_request_parameters: ModelRequestParameters,
|
|
218
|
+
) -> EventStream[ConverseStreamOutputTypeDef]:
|
|
219
|
+
pass
|
|
220
|
+
|
|
221
|
+
@overload
|
|
222
|
+
async def _messages_create(
|
|
223
|
+
self,
|
|
224
|
+
messages: list[ModelMessage],
|
|
225
|
+
stream: Literal[False],
|
|
226
|
+
model_settings: ModelSettings | None,
|
|
227
|
+
model_request_parameters: ModelRequestParameters,
|
|
228
|
+
) -> ConverseResponseTypeDef:
|
|
229
|
+
pass
|
|
230
|
+
|
|
231
|
+
async def _messages_create(
|
|
232
|
+
self,
|
|
233
|
+
messages: list[ModelMessage],
|
|
234
|
+
stream: bool,
|
|
235
|
+
model_settings: ModelSettings | None,
|
|
236
|
+
model_request_parameters: ModelRequestParameters,
|
|
237
|
+
) -> ConverseResponseTypeDef | EventStream[ConverseStreamOutputTypeDef]:
|
|
238
|
+
tools = self._get_tools(model_request_parameters)
|
|
239
|
+
support_tools_choice = self.model_name.startswith(('anthropic', 'us.anthropic'))
|
|
240
|
+
if not tools or not support_tools_choice:
|
|
241
|
+
tool_choice: ToolChoiceTypeDef = {}
|
|
242
|
+
elif not model_request_parameters.allow_text_result:
|
|
243
|
+
tool_choice = {'any': {}}
|
|
244
|
+
else:
|
|
245
|
+
tool_choice = {'auto': {}}
|
|
246
|
+
|
|
247
|
+
system_prompt, bedrock_messages = self._map_message(messages)
|
|
248
|
+
inference_config = self._map_inference_config(model_settings)
|
|
249
|
+
|
|
250
|
+
params = {
|
|
251
|
+
'modelId': self.model_name,
|
|
252
|
+
'messages': bedrock_messages,
|
|
253
|
+
'system': [{'text': system_prompt}],
|
|
254
|
+
'inferenceConfig': inference_config,
|
|
255
|
+
**(
|
|
256
|
+
{'toolConfig': {'tools': tools, **({'toolChoice': tool_choice} if tool_choice else {})}}
|
|
257
|
+
if tools
|
|
258
|
+
else {}
|
|
259
|
+
),
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if stream:
|
|
263
|
+
model_response = await anyio.to_thread.run_sync(functools.partial(self.client.converse_stream, **params))
|
|
264
|
+
model_response = model_response['stream']
|
|
265
|
+
else:
|
|
266
|
+
model_response = await anyio.to_thread.run_sync(functools.partial(self.client.converse, **params))
|
|
267
|
+
return model_response
|
|
268
|
+
|
|
269
|
+
@staticmethod
|
|
270
|
+
def _map_inference_config(
|
|
271
|
+
model_settings: ModelSettings | None,
|
|
272
|
+
) -> InferenceConfigurationTypeDef:
|
|
273
|
+
model_settings = model_settings or {}
|
|
274
|
+
inference_config: InferenceConfigurationTypeDef = {}
|
|
275
|
+
|
|
276
|
+
if max_tokens := model_settings.get('max_tokens'):
|
|
277
|
+
inference_config['maxTokens'] = max_tokens
|
|
278
|
+
if temperature := model_settings.get('temperature'):
|
|
279
|
+
inference_config['temperature'] = temperature
|
|
280
|
+
if top_p := model_settings.get('top_p'):
|
|
281
|
+
inference_config['topP'] = top_p
|
|
282
|
+
# TODO(Marcelo): This is not included in model_settings yet.
|
|
283
|
+
# if stop_sequences := model_settings.get('stop_sequences'):
|
|
284
|
+
# inference_config['stopSequences'] = stop_sequences
|
|
285
|
+
|
|
286
|
+
return inference_config
|
|
287
|
+
|
|
288
|
+
def _map_message(self, messages: list[ModelMessage]) -> tuple[str, list[MessageUnionTypeDef]]:
|
|
289
|
+
"""Just maps a `pydantic_ai.Message` to the Bedrock `MessageUnionTypeDef`."""
|
|
290
|
+
system_prompt: str = ''
|
|
291
|
+
bedrock_messages: list[MessageUnionTypeDef] = []
|
|
292
|
+
for m in messages:
|
|
293
|
+
if isinstance(m, ModelRequest):
|
|
294
|
+
for part in m.parts:
|
|
295
|
+
if isinstance(part, SystemPromptPart):
|
|
296
|
+
system_prompt += part.content
|
|
297
|
+
elif isinstance(part, UserPromptPart):
|
|
298
|
+
if isinstance(part.content, str):
|
|
299
|
+
bedrock_messages.append({'role': 'user', 'content': [{'text': part.content}]})
|
|
300
|
+
else:
|
|
301
|
+
raise NotImplementedError('User prompt can only be a string for now.')
|
|
302
|
+
elif isinstance(part, ToolReturnPart):
|
|
303
|
+
assert part.tool_call_id is not None
|
|
304
|
+
bedrock_messages.append(
|
|
305
|
+
{
|
|
306
|
+
'role': 'user',
|
|
307
|
+
'content': [
|
|
308
|
+
{
|
|
309
|
+
'toolResult': {
|
|
310
|
+
'toolUseId': part.tool_call_id,
|
|
311
|
+
'content': [{'text': part.model_response_str()}],
|
|
312
|
+
'status': 'success',
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
],
|
|
316
|
+
}
|
|
317
|
+
)
|
|
318
|
+
elif isinstance(part, RetryPromptPart):
|
|
319
|
+
# TODO(Marcelo): We need to add a test here.
|
|
320
|
+
if part.tool_name is None: # pragma: no cover
|
|
321
|
+
bedrock_messages.append({'role': 'user', 'content': [{'text': part.model_response()}]})
|
|
322
|
+
else:
|
|
323
|
+
assert part.tool_call_id is not None
|
|
324
|
+
bedrock_messages.append(
|
|
325
|
+
{
|
|
326
|
+
'role': 'user',
|
|
327
|
+
'content': [
|
|
328
|
+
{
|
|
329
|
+
'toolResult': {
|
|
330
|
+
'toolUseId': part.tool_call_id,
|
|
331
|
+
'content': [{'text': part.model_response()}],
|
|
332
|
+
'status': 'error',
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
],
|
|
336
|
+
}
|
|
337
|
+
)
|
|
338
|
+
elif isinstance(m, ModelResponse):
|
|
339
|
+
content: list[ContentBlockOutputTypeDef] = []
|
|
340
|
+
for item in m.parts:
|
|
341
|
+
if isinstance(item, TextPart):
|
|
342
|
+
content.append({'text': item.content})
|
|
343
|
+
else:
|
|
344
|
+
assert isinstance(item, ToolCallPart)
|
|
345
|
+
content.append(self._map_tool_call(item)) # FIXME: MISSING key
|
|
346
|
+
bedrock_messages.append({'role': 'assistant', 'content': content})
|
|
347
|
+
else:
|
|
348
|
+
assert_never(m)
|
|
349
|
+
return system_prompt, bedrock_messages
|
|
350
|
+
|
|
351
|
+
@staticmethod
|
|
352
|
+
def _map_tool_call(t: ToolCallPart) -> ContentBlockOutputTypeDef:
|
|
353
|
+
assert t.tool_call_id is not None
|
|
354
|
+
return {
|
|
355
|
+
'toolUse': {
|
|
356
|
+
'toolUseId': t.tool_call_id,
|
|
357
|
+
'name': t.tool_name,
|
|
358
|
+
'input': t.args_as_dict(),
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@dataclass
|
|
364
|
+
class BedrockStreamedResponse(StreamedResponse):
|
|
365
|
+
"""Implementation of `StreamedResponse` for Bedrock models."""
|
|
366
|
+
|
|
367
|
+
_model_name: BedrockModelName
|
|
368
|
+
_event_stream: EventStream[ConverseStreamOutputTypeDef]
|
|
369
|
+
_timestamp: datetime = field(default_factory=_utils.now_utc)
|
|
370
|
+
|
|
371
|
+
async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]:
|
|
372
|
+
"""Return an async iterator of [`ModelResponseStreamEvent`][pydantic_ai.messages.ModelResponseStreamEvent]s.
|
|
373
|
+
|
|
374
|
+
This method should be implemented by subclasses to translate the vendor-specific stream of events into
|
|
375
|
+
pydantic_ai-format events.
|
|
376
|
+
"""
|
|
377
|
+
chunk: ConverseStreamOutputTypeDef
|
|
378
|
+
tool_id: str | None = None
|
|
379
|
+
async for chunk in _AsyncIteratorWrapper(self._event_stream):
|
|
380
|
+
# TODO(Marcelo): Switch this to `match` when we drop Python 3.9 support.
|
|
381
|
+
if 'messageStart' in chunk:
|
|
382
|
+
continue
|
|
383
|
+
if 'messageStop' in chunk:
|
|
384
|
+
continue
|
|
385
|
+
if 'metadata' in chunk:
|
|
386
|
+
if 'usage' in chunk['metadata']:
|
|
387
|
+
self._usage += self._map_usage(chunk['metadata'])
|
|
388
|
+
continue
|
|
389
|
+
if 'contentBlockStart' in chunk:
|
|
390
|
+
index = chunk['contentBlockStart']['contentBlockIndex']
|
|
391
|
+
start = chunk['contentBlockStart']['start']
|
|
392
|
+
if 'toolUse' in start:
|
|
393
|
+
tool_use_start = start['toolUse']
|
|
394
|
+
tool_id = tool_use_start['toolUseId']
|
|
395
|
+
tool_name = tool_use_start['name']
|
|
396
|
+
maybe_event = self._parts_manager.handle_tool_call_delta(
|
|
397
|
+
vendor_part_id=index,
|
|
398
|
+
tool_name=tool_name,
|
|
399
|
+
args=None,
|
|
400
|
+
tool_call_id=tool_id,
|
|
401
|
+
)
|
|
402
|
+
if maybe_event:
|
|
403
|
+
yield maybe_event
|
|
404
|
+
if 'contentBlockDelta' in chunk:
|
|
405
|
+
index = chunk['contentBlockDelta']['contentBlockIndex']
|
|
406
|
+
delta = chunk['contentBlockDelta']['delta']
|
|
407
|
+
if 'text' in delta:
|
|
408
|
+
yield self._parts_manager.handle_text_delta(vendor_part_id=index, content=delta['text'])
|
|
409
|
+
if 'toolUse' in delta:
|
|
410
|
+
tool_use = delta['toolUse']
|
|
411
|
+
maybe_event = self._parts_manager.handle_tool_call_delta(
|
|
412
|
+
vendor_part_id=index,
|
|
413
|
+
tool_name=tool_use.get('name'),
|
|
414
|
+
args=tool_use.get('input'),
|
|
415
|
+
tool_call_id=tool_id,
|
|
416
|
+
)
|
|
417
|
+
if maybe_event:
|
|
418
|
+
yield maybe_event
|
|
419
|
+
|
|
420
|
+
@property
|
|
421
|
+
def timestamp(self) -> datetime:
|
|
422
|
+
return self._timestamp
|
|
423
|
+
|
|
424
|
+
@property
|
|
425
|
+
def model_name(self) -> str:
|
|
426
|
+
"""Get the model name of the response."""
|
|
427
|
+
return self._model_name
|
|
428
|
+
|
|
429
|
+
def _map_usage(self, metadata: ConverseStreamMetadataEventTypeDef) -> result.Usage:
|
|
430
|
+
return result.Usage(
|
|
431
|
+
request_tokens=metadata['usage']['inputTokens'],
|
|
432
|
+
response_tokens=metadata['usage']['outputTokens'],
|
|
433
|
+
total_tokens=metadata['usage']['totalTokens'],
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class _AsyncIteratorWrapper(Generic[T]):
|
|
438
|
+
"""Wrap a synchronous iterator in an async iterator."""
|
|
439
|
+
|
|
440
|
+
def __init__(self, sync_iterator: Iterable[T]):
|
|
441
|
+
self.sync_iterator = iter(sync_iterator)
|
|
442
|
+
|
|
443
|
+
def __aiter__(self):
|
|
444
|
+
return self
|
|
445
|
+
|
|
446
|
+
async def __anext__(self) -> T:
|
|
447
|
+
try:
|
|
448
|
+
# Run the synchronous next() call in a thread pool
|
|
449
|
+
item = await anyio.to_thread.run_sync(next, self.sync_iterator)
|
|
450
|
+
return item
|
|
451
|
+
except RuntimeError as e:
|
|
452
|
+
if type(e.__cause__) is StopIteration:
|
|
453
|
+
raise StopAsyncIteration
|
|
454
|
+
else:
|
|
455
|
+
raise e
|
pydantic_ai/models/cohere.py
CHANGED
|
@@ -127,6 +127,11 @@ class CohereModel(Model):
|
|
|
127
127
|
else:
|
|
128
128
|
self.client = AsyncClientV2(api_key=api_key, httpx_client=http_client)
|
|
129
129
|
|
|
130
|
+
@property
|
|
131
|
+
def base_url(self) -> str:
|
|
132
|
+
client_wrapper = self.client._client_wrapper # type: ignore
|
|
133
|
+
return str(client_wrapper.get_base_url())
|
|
134
|
+
|
|
130
135
|
async def request(
|
|
131
136
|
self,
|
|
132
137
|
messages: list[ModelMessage],
|
pydantic_ai/models/fallback.py
CHANGED
|
@@ -106,6 +106,10 @@ class FallbackModel(Model):
|
|
|
106
106
|
"""The system / model provider, n/a for fallback models."""
|
|
107
107
|
return None
|
|
108
108
|
|
|
109
|
+
@property
|
|
110
|
+
def base_url(self) -> str | None:
|
|
111
|
+
return self.models[0].base_url
|
|
112
|
+
|
|
109
113
|
|
|
110
114
|
def _default_fallback_condition_factory(exceptions: tuple[type[Exception], ...]) -> Callable[[Exception], bool]:
|
|
111
115
|
"""Create a default fallback condition for the given exceptions."""
|
pydantic_ai/models/gemini.py
CHANGED
|
@@ -143,6 +143,7 @@ class GeminiModel(Model):
|
|
|
143
143
|
else:
|
|
144
144
|
self._system = provider.name
|
|
145
145
|
self.client = provider.client
|
|
146
|
+
self._url = str(self.client.base_url)
|
|
146
147
|
else:
|
|
147
148
|
if api_key is None:
|
|
148
149
|
if env_api_key := os.getenv('GEMINI_API_KEY'):
|
|
@@ -159,7 +160,7 @@ class GeminiModel(Model):
|
|
|
159
160
|
return self._auth
|
|
160
161
|
|
|
161
162
|
@property
|
|
162
|
-
def
|
|
163
|
+
def base_url(self) -> str:
|
|
163
164
|
assert self._url is not None, 'URL not initialized'
|
|
164
165
|
return self._url
|
|
165
166
|
|
|
@@ -257,7 +258,7 @@ class GeminiModel(Model):
|
|
|
257
258
|
'User-Agent': get_user_agent(),
|
|
258
259
|
}
|
|
259
260
|
if self._provider is None: # pragma: no cover
|
|
260
|
-
url = self.
|
|
261
|
+
url = self.base_url + ('streamGenerateContent' if streamed else 'generateContent')
|
|
261
262
|
headers.update(await self.auth.headers())
|
|
262
263
|
else:
|
|
263
264
|
url = f'/{self._model_name}:{"streamGenerateContent" if streamed else "generateContent"}'
|
pydantic_ai/models/groq.py
CHANGED
|
@@ -123,6 +123,10 @@ class GroqModel(Model):
|
|
|
123
123
|
else:
|
|
124
124
|
self.client = AsyncGroq(api_key=api_key, http_client=cached_async_http_client())
|
|
125
125
|
|
|
126
|
+
@property
|
|
127
|
+
def base_url(self) -> str:
|
|
128
|
+
return str(self.client.base_url)
|
|
129
|
+
|
|
126
130
|
async def request(
|
|
127
131
|
self,
|
|
128
132
|
messages: list[ModelMessage],
|
|
@@ -5,6 +5,7 @@ from collections.abc import AsyncIterator, Iterator, Mapping
|
|
|
5
5
|
from contextlib import asynccontextmanager, contextmanager
|
|
6
6
|
from dataclasses import dataclass, field
|
|
7
7
|
from typing import Any, Callable, Literal
|
|
8
|
+
from urllib.parse import urlparse
|
|
8
9
|
|
|
9
10
|
from opentelemetry._events import Event, EventLogger, EventLoggerProvider, get_event_logger_provider
|
|
10
11
|
from opentelemetry.trace import Span, Tracer, TracerProvider, get_tracer_provider
|
|
@@ -142,8 +143,6 @@ class InstrumentedModel(WrapperModel):
|
|
|
142
143
|
system = getattr(self.wrapped, 'system', '') or self.wrapped.__class__.__name__.removesuffix('Model').lower()
|
|
143
144
|
system = {'google-gla': 'gemini', 'google-vertex': 'vertex_ai', 'mistral': 'mistral_ai'}.get(system, system)
|
|
144
145
|
# TODO Missing attributes:
|
|
145
|
-
# - server.address: requires a Model.base_url abstract method or similar
|
|
146
|
-
# - server.port: to parse from the base_url
|
|
147
146
|
# - error.type: unclear if we should do something here or just always rely on span exceptions
|
|
148
147
|
# - gen_ai.request.stop_sequences/top_k: model_settings doesn't include these
|
|
149
148
|
attributes: dict[str, AttributeValue] = {
|
|
@@ -151,6 +150,15 @@ class InstrumentedModel(WrapperModel):
|
|
|
151
150
|
'gen_ai.system': system,
|
|
152
151
|
'gen_ai.request.model': model_name,
|
|
153
152
|
}
|
|
153
|
+
if base_url := self.wrapped.base_url:
|
|
154
|
+
try:
|
|
155
|
+
parsed = urlparse(base_url)
|
|
156
|
+
if parsed.hostname:
|
|
157
|
+
attributes['server.address'] = parsed.hostname
|
|
158
|
+
if parsed.port:
|
|
159
|
+
attributes['server.port'] = parsed.port
|
|
160
|
+
except Exception: # pragma: no cover
|
|
161
|
+
pass
|
|
154
162
|
|
|
155
163
|
if model_settings:
|
|
156
164
|
for key in MODEL_SETTING_ATTRIBUTES:
|
pydantic_ai/models/mistral.py
CHANGED
|
@@ -140,6 +140,10 @@ class MistralModel(Model):
|
|
|
140
140
|
api_key = os.getenv('MISTRAL_API_KEY') if api_key is None else api_key
|
|
141
141
|
self.client = Mistral(api_key=api_key, async_client=http_client or cached_async_http_client())
|
|
142
142
|
|
|
143
|
+
@property
|
|
144
|
+
def base_url(self) -> str:
|
|
145
|
+
return str(self.client.sdk_configuration.get_server_details()[0])
|
|
146
|
+
|
|
143
147
|
async def request(
|
|
144
148
|
self,
|
|
145
149
|
messages: list[ModelMessage],
|
pydantic_ai/models/openai.py
CHANGED
|
@@ -187,6 +187,10 @@ class OpenAIModel(Model):
|
|
|
187
187
|
self.system_prompt_role = system_prompt_role
|
|
188
188
|
self._system = system
|
|
189
189
|
|
|
190
|
+
@property
|
|
191
|
+
def base_url(self) -> str:
|
|
192
|
+
return str(self.client.base_url)
|
|
193
|
+
|
|
190
194
|
async def request(
|
|
191
195
|
self,
|
|
192
196
|
messages: list[ModelMessage],
|
pydantic_ai/models/vertexai.py
CHANGED
|
@@ -224,15 +224,13 @@ class BearerTokenAuth:
|
|
|
224
224
|
|
|
225
225
|
|
|
226
226
|
VertexAiRegion = Literal[
|
|
227
|
-
'
|
|
228
|
-
'
|
|
229
|
-
'
|
|
230
|
-
'
|
|
231
|
-
'
|
|
232
|
-
'
|
|
233
|
-
'
|
|
234
|
-
'us-west4',
|
|
235
|
-
'us-east5',
|
|
227
|
+
'asia-east1',
|
|
228
|
+
'asia-east2',
|
|
229
|
+
'asia-northeast1',
|
|
230
|
+
'asia-northeast3',
|
|
231
|
+
'asia-south1',
|
|
232
|
+
'asia-southeast1',
|
|
233
|
+
'australia-southeast1',
|
|
236
234
|
'europe-central2',
|
|
237
235
|
'europe-north1',
|
|
238
236
|
'europe-southwest1',
|
|
@@ -243,27 +241,20 @@ VertexAiRegion = Literal[
|
|
|
243
241
|
'europe-west6',
|
|
244
242
|
'europe-west8',
|
|
245
243
|
'europe-west9',
|
|
246
|
-
'europe-west12',
|
|
247
|
-
'africa-south1',
|
|
248
|
-
'asia-east1',
|
|
249
|
-
'asia-east2',
|
|
250
|
-
'asia-northeast1',
|
|
251
|
-
'asia-northeast2',
|
|
252
|
-
'asia-northeast3',
|
|
253
|
-
'asia-south1',
|
|
254
|
-
'asia-southeast1',
|
|
255
|
-
'asia-southeast2',
|
|
256
|
-
'australia-southeast1',
|
|
257
|
-
'australia-southeast2',
|
|
258
244
|
'me-central1',
|
|
259
245
|
'me-central2',
|
|
260
246
|
'me-west1',
|
|
261
247
|
'northamerica-northeast1',
|
|
262
|
-
'northamerica-northeast2',
|
|
263
248
|
'southamerica-east1',
|
|
264
|
-
'
|
|
249
|
+
'us-central1',
|
|
250
|
+
'us-east1',
|
|
251
|
+
'us-east4',
|
|
252
|
+
'us-east5',
|
|
253
|
+
'us-south1',
|
|
254
|
+
'us-west1',
|
|
255
|
+
'us-west4',
|
|
265
256
|
]
|
|
266
257
|
"""Regions available for Vertex AI.
|
|
267
258
|
|
|
268
|
-
More details [here](https://cloud.google.com/vertex-ai/docs/
|
|
259
|
+
More details [here](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations#genai-locations).
|
|
269
260
|
"""
|
|
@@ -60,5 +60,10 @@ def infer_provider(provider: str) -> Provider[Any]:
|
|
|
60
60
|
from .google_gla import GoogleGLAProvider
|
|
61
61
|
|
|
62
62
|
return GoogleGLAProvider()
|
|
63
|
+
# NOTE: We don't test because there are many ways the `boto3.client` can retrieve the credentials.
|
|
64
|
+
elif provider == 'bedrock': # pragma: no cover
|
|
65
|
+
from .bedrock import BedrockProvider
|
|
66
|
+
|
|
67
|
+
return BedrockProvider()
|
|
63
68
|
else: # pragma: no cover
|
|
64
69
|
raise ValueError(f'Unknown provider: {provider}')
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations as _annotations
|
|
2
|
+
|
|
3
|
+
from typing import overload
|
|
4
|
+
|
|
5
|
+
from pydantic_ai.providers import Provider
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
import boto3
|
|
9
|
+
from botocore.client import BaseClient
|
|
10
|
+
from botocore.exceptions import NoRegionError
|
|
11
|
+
except ImportError as _import_error:
|
|
12
|
+
raise ImportError(
|
|
13
|
+
'Please install `boto3` to use the Bedrock provider, '
|
|
14
|
+
"you can use the `bedrock` optional group — `pip install 'pydantic-ai-slim[bedrock]'`"
|
|
15
|
+
) from _import_error
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BedrockProvider(Provider[BaseClient]):
|
|
19
|
+
"""Provider for AWS Bedrock."""
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def name(self) -> str:
|
|
23
|
+
return 'bedrock'
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def base_url(self) -> str:
|
|
27
|
+
return self._client.meta.endpoint_url
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def client(self) -> BaseClient:
|
|
31
|
+
return self._client
|
|
32
|
+
|
|
33
|
+
@overload
|
|
34
|
+
def __init__(self, *, bedrock_client: BaseClient) -> None: ...
|
|
35
|
+
|
|
36
|
+
@overload
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
*,
|
|
40
|
+
region_name: str | None = None,
|
|
41
|
+
aws_access_key_id: str | None = None,
|
|
42
|
+
aws_secret_access_key: str | None = None,
|
|
43
|
+
aws_session_token: str | None = None,
|
|
44
|
+
) -> None: ...
|
|
45
|
+
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
*,
|
|
49
|
+
bedrock_client: BaseClient | None = None,
|
|
50
|
+
region_name: str | None = None,
|
|
51
|
+
aws_access_key_id: str | None = None,
|
|
52
|
+
aws_secret_access_key: str | None = None,
|
|
53
|
+
aws_session_token: str | None = None,
|
|
54
|
+
) -> None:
|
|
55
|
+
"""Initialize the Bedrock provider.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
bedrock_client: A boto3 client for Bedrock Runtime. If provided, other arguments are ignored.
|
|
59
|
+
region_name: The AWS region name.
|
|
60
|
+
aws_access_key_id: The AWS access key ID.
|
|
61
|
+
aws_secret_access_key: The AWS secret access key.
|
|
62
|
+
aws_session_token: The AWS session token.
|
|
63
|
+
"""
|
|
64
|
+
if bedrock_client is not None:
|
|
65
|
+
self._client = bedrock_client
|
|
66
|
+
else:
|
|
67
|
+
try:
|
|
68
|
+
self._client = boto3.client( # type: ignore[reportUnknownMemberType]
|
|
69
|
+
'bedrock-runtime',
|
|
70
|
+
aws_access_key_id=aws_access_key_id,
|
|
71
|
+
aws_secret_access_key=aws_secret_access_key,
|
|
72
|
+
aws_session_token=aws_session_token,
|
|
73
|
+
region_name=region_name,
|
|
74
|
+
)
|
|
75
|
+
except NoRegionError as exc: # pragma: no cover
|
|
76
|
+
raise ValueError('You must provide a `region_name` or a boto3 client for Bedrock Runtime.') from exc
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations as _annotations
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
|
-
from collections.abc import AsyncGenerator
|
|
4
|
+
from collections.abc import AsyncGenerator, Mapping
|
|
5
5
|
from datetime import datetime, timedelta
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Literal
|
|
7
|
+
from typing import Literal, overload
|
|
8
8
|
|
|
9
9
|
import anyio.to_thread
|
|
10
10
|
import httpx
|
|
@@ -52,19 +52,45 @@ class GoogleVertexProvider(Provider[httpx.AsyncClient]):
|
|
|
52
52
|
def client(self) -> httpx.AsyncClient:
|
|
53
53
|
return self._client
|
|
54
54
|
|
|
55
|
+
@overload
|
|
55
56
|
def __init__(
|
|
56
57
|
self,
|
|
58
|
+
*,
|
|
57
59
|
service_account_file: Path | str | None = None,
|
|
58
60
|
project_id: str | None = None,
|
|
59
61
|
region: VertexAiRegion = 'us-central1',
|
|
60
62
|
model_publisher: str = 'google',
|
|
61
63
|
http_client: httpx.AsyncClient | None = None,
|
|
64
|
+
) -> None: ...
|
|
65
|
+
|
|
66
|
+
@overload
|
|
67
|
+
def __init__(
|
|
68
|
+
self,
|
|
69
|
+
*,
|
|
70
|
+
service_account_info: Mapping[str, str] | None = None,
|
|
71
|
+
project_id: str | None = None,
|
|
72
|
+
region: VertexAiRegion = 'us-central1',
|
|
73
|
+
model_publisher: str = 'google',
|
|
74
|
+
http_client: httpx.AsyncClient | None = None,
|
|
75
|
+
) -> None: ...
|
|
76
|
+
|
|
77
|
+
def __init__(
|
|
78
|
+
self,
|
|
79
|
+
*,
|
|
80
|
+
service_account_file: Path | str | None = None,
|
|
81
|
+
service_account_info: Mapping[str, str] | None = None,
|
|
82
|
+
project_id: str | None = None,
|
|
83
|
+
region: VertexAiRegion = 'us-central1',
|
|
84
|
+
model_publisher: str = 'google',
|
|
85
|
+
http_client: httpx.AsyncClient | None = None,
|
|
62
86
|
) -> None:
|
|
63
87
|
"""Create a new Vertex AI provider.
|
|
64
88
|
|
|
65
89
|
Args:
|
|
66
90
|
service_account_file: Path to a service account file.
|
|
67
|
-
If not provided, the default environment credentials will be used.
|
|
91
|
+
If not provided, the service_account_info or default environment credentials will be used.
|
|
92
|
+
service_account_info: The loaded service_account_file contents.
|
|
93
|
+
If not provided, the service_account_file or default environment credentials will be used.
|
|
68
94
|
project_id: The project ID to use, if not provided it will be taken from the credentials.
|
|
69
95
|
region: The region to make requests to.
|
|
70
96
|
model_publisher: The model publisher to use, I couldn't find a good list of available publishers,
|
|
@@ -73,13 +99,17 @@ class GoogleVertexProvider(Provider[httpx.AsyncClient]):
|
|
|
73
99
|
Please create an issue or PR if you know how to use other publishers.
|
|
74
100
|
http_client: An existing `httpx.AsyncClient` to use for making HTTP requests.
|
|
75
101
|
"""
|
|
102
|
+
if service_account_file and service_account_info:
|
|
103
|
+
raise ValueError('Only one of `service_account_file` or `service_account_info` can be provided.')
|
|
104
|
+
|
|
76
105
|
self._client = http_client or cached_async_http_client()
|
|
77
106
|
self.service_account_file = service_account_file
|
|
107
|
+
self.service_account_info = service_account_info
|
|
78
108
|
self.project_id = project_id
|
|
79
109
|
self.region = region
|
|
80
110
|
self.model_publisher = model_publisher
|
|
81
111
|
|
|
82
|
-
self._client.auth = _VertexAIAuth(service_account_file, project_id, region)
|
|
112
|
+
self._client.auth = _VertexAIAuth(service_account_file, service_account_info, project_id, region)
|
|
83
113
|
self._client.base_url = self.base_url
|
|
84
114
|
|
|
85
115
|
|
|
@@ -91,10 +121,12 @@ class _VertexAIAuth(httpx.Auth):
|
|
|
91
121
|
def __init__(
|
|
92
122
|
self,
|
|
93
123
|
service_account_file: Path | str | None = None,
|
|
124
|
+
service_account_info: Mapping[str, str] | None = None,
|
|
94
125
|
project_id: str | None = None,
|
|
95
126
|
region: VertexAiRegion = 'us-central1',
|
|
96
127
|
) -> None:
|
|
97
128
|
self.service_account_file = service_account_file
|
|
129
|
+
self.service_account_info = service_account_info
|
|
98
130
|
self.project_id = project_id
|
|
99
131
|
self.region = region
|
|
100
132
|
|
|
@@ -119,6 +151,11 @@ class _VertexAIAuth(httpx.Auth):
|
|
|
119
151
|
assert creds.project_id is None or isinstance(creds.project_id, str) # type: ignore[reportUnknownMemberType]
|
|
120
152
|
creds_project_id: str | None = creds.project_id
|
|
121
153
|
creds_source = 'service account file'
|
|
154
|
+
elif self.service_account_info is not None:
|
|
155
|
+
creds = await _creds_from_info(self.service_account_info)
|
|
156
|
+
assert creds.project_id is None or isinstance(creds.project_id, str) # type: ignore[reportUnknownMemberType]
|
|
157
|
+
creds_project_id: str | None = creds.project_id
|
|
158
|
+
creds_source = 'service account info'
|
|
122
159
|
else:
|
|
123
160
|
creds, creds_project_id = await _async_google_auth()
|
|
124
161
|
creds_source = '`google.auth.default()`'
|
|
@@ -154,16 +191,22 @@ async def _creds_from_file(service_account_file: str | Path) -> ServiceAccountCr
|
|
|
154
191
|
return await anyio.to_thread.run_sync(service_account_credentials_from_file, str(service_account_file))
|
|
155
192
|
|
|
156
193
|
|
|
194
|
+
async def _creds_from_info(service_account_info: Mapping[str, str]) -> ServiceAccountCredentials:
|
|
195
|
+
service_account_credentials_from_string = functools.partial(
|
|
196
|
+
ServiceAccountCredentials.from_service_account_info, # type: ignore[reportUnknownMemberType]
|
|
197
|
+
scopes=['https://www.googleapis.com/auth/cloud-platform'],
|
|
198
|
+
)
|
|
199
|
+
return await anyio.to_thread.run_sync(service_account_credentials_from_string, service_account_info)
|
|
200
|
+
|
|
201
|
+
|
|
157
202
|
VertexAiRegion = Literal[
|
|
158
|
-
'
|
|
159
|
-
'
|
|
160
|
-
'
|
|
161
|
-
'
|
|
162
|
-
'
|
|
163
|
-
'
|
|
164
|
-
'
|
|
165
|
-
'us-west4',
|
|
166
|
-
'us-east5',
|
|
203
|
+
'asia-east1',
|
|
204
|
+
'asia-east2',
|
|
205
|
+
'asia-northeast1',
|
|
206
|
+
'asia-northeast3',
|
|
207
|
+
'asia-south1',
|
|
208
|
+
'asia-southeast1',
|
|
209
|
+
'australia-southeast1',
|
|
167
210
|
'europe-central2',
|
|
168
211
|
'europe-north1',
|
|
169
212
|
'europe-southwest1',
|
|
@@ -174,27 +217,20 @@ VertexAiRegion = Literal[
|
|
|
174
217
|
'europe-west6',
|
|
175
218
|
'europe-west8',
|
|
176
219
|
'europe-west9',
|
|
177
|
-
'europe-west12',
|
|
178
|
-
'africa-south1',
|
|
179
|
-
'asia-east1',
|
|
180
|
-
'asia-east2',
|
|
181
|
-
'asia-northeast1',
|
|
182
|
-
'asia-northeast2',
|
|
183
|
-
'asia-northeast3',
|
|
184
|
-
'asia-south1',
|
|
185
|
-
'asia-southeast1',
|
|
186
|
-
'asia-southeast2',
|
|
187
|
-
'australia-southeast1',
|
|
188
|
-
'australia-southeast2',
|
|
189
220
|
'me-central1',
|
|
190
221
|
'me-central2',
|
|
191
222
|
'me-west1',
|
|
192
223
|
'northamerica-northeast1',
|
|
193
|
-
'northamerica-northeast2',
|
|
194
224
|
'southamerica-east1',
|
|
195
|
-
'
|
|
225
|
+
'us-central1',
|
|
226
|
+
'us-east1',
|
|
227
|
+
'us-east4',
|
|
228
|
+
'us-east5',
|
|
229
|
+
'us-south1',
|
|
230
|
+
'us-west1',
|
|
231
|
+
'us-west4',
|
|
196
232
|
]
|
|
197
233
|
"""Regions available for Vertex AI.
|
|
198
234
|
|
|
199
|
-
More details [here](https://cloud.google.com/vertex-ai/docs/
|
|
235
|
+
More details [here](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations#genai-locations).
|
|
200
236
|
"""
|
pydantic_ai/settings.py
CHANGED
|
@@ -27,6 +27,7 @@ class ModelSettings(TypedDict, total=False):
|
|
|
27
27
|
* Groq
|
|
28
28
|
* Cohere
|
|
29
29
|
* Mistral
|
|
30
|
+
* Bedrock
|
|
30
31
|
"""
|
|
31
32
|
|
|
32
33
|
temperature: float
|
|
@@ -45,6 +46,7 @@ class ModelSettings(TypedDict, total=False):
|
|
|
45
46
|
* Groq
|
|
46
47
|
* Cohere
|
|
47
48
|
* Mistral
|
|
49
|
+
* Bedrock
|
|
48
50
|
"""
|
|
49
51
|
|
|
50
52
|
top_p: float
|
|
@@ -62,6 +64,7 @@ class ModelSettings(TypedDict, total=False):
|
|
|
62
64
|
* Groq
|
|
63
65
|
* Cohere
|
|
64
66
|
* Mistral
|
|
67
|
+
* Bedrock
|
|
65
68
|
"""
|
|
66
69
|
|
|
67
70
|
timeout: float | Timeout
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai-slim
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.37
|
|
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
|
|
@@ -29,11 +29,13 @@ Requires-Dist: exceptiongroup; python_version < '3.11'
|
|
|
29
29
|
Requires-Dist: griffe>=1.3.2
|
|
30
30
|
Requires-Dist: httpx>=0.27
|
|
31
31
|
Requires-Dist: opentelemetry-api>=1.28.0
|
|
32
|
-
Requires-Dist: pydantic-graph==0.0.
|
|
32
|
+
Requires-Dist: pydantic-graph==0.0.37
|
|
33
33
|
Requires-Dist: pydantic>=2.10
|
|
34
34
|
Requires-Dist: typing-inspection>=0.4.0
|
|
35
35
|
Provides-Extra: anthropic
|
|
36
36
|
Requires-Dist: anthropic>=0.49.0; extra == 'anthropic'
|
|
37
|
+
Provides-Extra: bedrock
|
|
38
|
+
Requires-Dist: boto3>=1.34.116; extra == 'bedrock'
|
|
37
39
|
Provides-Extra: cli
|
|
38
40
|
Requires-Dist: argcomplete>=3.5.0; extra == 'cli'
|
|
39
41
|
Requires-Dist: prompt-toolkit>=3; extra == 'cli'
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
pydantic_ai/__init__.py,sha256=xrSDxkBwpUVInbPtTVhReEecStk-mWZMttAPUAQR0Ic,927
|
|
2
|
+
pydantic_ai/_agent_graph.py,sha256=wbhm3_5VNpx_Oy1_sQ_6b2hkaFjd9vd1v9g3Rw_8sJY,30127
|
|
3
|
+
pydantic_ai/_cli.py,sha256=vvbRmOO1lj8AgEjJi0-I-05ofKFsj87fibW2EZLt1hU,8605
|
|
4
|
+
pydantic_ai/_griffe.py,sha256=RYRKiLbgG97QxnazbAwlnc74XxevGHLQet-FGfq9qls,3960
|
|
5
|
+
pydantic_ai/_parts_manager.py,sha256=ARfDQY1_5AIY5rNl_M2fAYHEFCe03ZxdhgjHf9qeIKw,11872
|
|
6
|
+
pydantic_ai/_pydantic.py,sha256=v8bqZvfpALiGzjAwhsAz4Pzyqxjr4N1296dsqjDoPGg,8808
|
|
7
|
+
pydantic_ai/_result.py,sha256=SlxqR-AKWzDoc7cRRN2jmIZ7pCv3DKzaP-dnZW-e7us,10117
|
|
8
|
+
pydantic_ai/_system_prompt.py,sha256=602c2jyle2R_SesOrITBDETZqsLk4BZ8Cbo8yEhmx04,1120
|
|
9
|
+
pydantic_ai/_utils.py,sha256=nx4Suswk2qjLvzphx8uQntKzFi-IzvhX_H1L7t_kJlQ,9579
|
|
10
|
+
pydantic_ai/agent.py,sha256=dy8oTMEjc_2EUu8v3dUvhNb5GgbnlQYVm4XK2DKbTZc,67318
|
|
11
|
+
pydantic_ai/exceptions.py,sha256=1ujJeB3jDDQ-pH5ydBYrgStvR35-GlEW0bYGTGEr4ME,3127
|
|
12
|
+
pydantic_ai/format_as_xml.py,sha256=QE7eMlg5-YUMw1_2kcI3h0uKYPZZyGkgXFDtfZTMeeI,4480
|
|
13
|
+
pydantic_ai/messages.py,sha256=oXFWWPllACi6C4K2wMHkHnCP7DVLMWfGkL48SD40oWI,23981
|
|
14
|
+
pydantic_ai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
pydantic_ai/result.py,sha256=LXKxRzy_rGMkdZ8xJ7yknPP3wGZtGNeZl-gh5opXbaQ,22542
|
|
16
|
+
pydantic_ai/settings.py,sha256=q__Hordc4dypesNxpy_cBT5rFdSiEY-rQt9G6zfyFaM,3101
|
|
17
|
+
pydantic_ai/tools.py,sha256=IPZuZJCSQUppz1uyLVwpfFLGoMirB8YtKWXIDQGR444,13414
|
|
18
|
+
pydantic_ai/usage.py,sha256=VmpU_o_RjFI65J81G1wfCwDIAYBclMjeWfLtslntFOw,5406
|
|
19
|
+
pydantic_ai/common_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
pydantic_ai/common_tools/duckduckgo.py,sha256=02Ud34xJBwZV0xqYHfPJL7PUfN3odfm9N00j-9p2t0Q,2241
|
|
21
|
+
pydantic_ai/common_tools/tavily.py,sha256=rz3nMIK1aD1kAFP1ZhFSYr4Uy0_uMDJY-JgZxQ1MxsM,2589
|
|
22
|
+
pydantic_ai/models/__init__.py,sha256=kMwX5bLTUXZuA6SUgs2uI7Xlxn3SfkziLq_hUy_8vwI,16262
|
|
23
|
+
pydantic_ai/models/anthropic.py,sha256=4SsM3K4YLk8S4o846jC5_sPpAUNLLBPmojCkmV3m-Wo,20766
|
|
24
|
+
pydantic_ai/models/bedrock.py,sha256=4M_LcIWT9t0p5IzKWG59HXH-8BOM4UigXvpr0tKyVek,18154
|
|
25
|
+
pydantic_ai/models/cohere.py,sha256=re_4dIvAzEbXms1Omvz4SOiBqgXoNBxCfqaFWeHhMZ8,11679
|
|
26
|
+
pydantic_ai/models/fallback.py,sha256=WC-6CFfn5WZY1bxdhkV5zZenW9VftEvBPtWQHyAYtjQ,4299
|
|
27
|
+
pydantic_ai/models/function.py,sha256=THIwVJ8qI3efYLNlYXlYze_J8hc7MHB-NMb3kpknq0g,11373
|
|
28
|
+
pydantic_ai/models/gemini.py,sha256=L6RwBGuVXr9RK6JITdxpe5P0xl58egfiRYW2d1yehFk,35864
|
|
29
|
+
pydantic_ai/models/groq.py,sha256=vDY3fdrY-Uj0e8zQZmee2VGMr1qr1jKBgAupgSKNNLo,16493
|
|
30
|
+
pydantic_ai/models/instrumented.py,sha256=sH5-RiXZ-lVhYgYXXH3F3ui42F4Tc55DP3AErypz32I,9839
|
|
31
|
+
pydantic_ai/models/mistral.py,sha256=kWomL1iWlbH_-UKXCmPMMt7ZPqlZ91oi_8q9Noiwuzc,27568
|
|
32
|
+
pydantic_ai/models/openai.py,sha256=eyg0GUd5pKlXuLHWdoBqvgTvH_oaXpn9ayfAPwz0Rz0,21682
|
|
33
|
+
pydantic_ai/models/test.py,sha256=Ux20cmuJFkhvI9L1N7ItHNFcd-j284TBEsrM53eWRag,16873
|
|
34
|
+
pydantic_ai/models/vertexai.py,sha256=fdzVj7dnrjF4emqtl7bxzdumhljlUN7ZEr-YL7p2A70,9680
|
|
35
|
+
pydantic_ai/models/wrapper.py,sha256=Zr3fgiUBpt2N9gXds6iSwaMEtEsFKr9WwhpHjSoHa7o,1410
|
|
36
|
+
pydantic_ai/providers/__init__.py,sha256=RN2Mm0y-4ZB2U-Aei3oAGh3uALVY4DGB1jYScGoeLDo,2053
|
|
37
|
+
pydantic_ai/providers/bedrock.py,sha256=O2MCKM_zUg1umM633VM8iglraMo0P9tms0MdGqXCmtk,2488
|
|
38
|
+
pydantic_ai/providers/deepseek.py,sha256=KDNvVXjB8cuRTw_xEM1JYLKig9V5YdvGFPm-dcf0kdc,2065
|
|
39
|
+
pydantic_ai/providers/google_gla.py,sha256=sfJXkuGW17nI-P40glnO8DaL_mrpL4uafgoH8xPvcEY,1539
|
|
40
|
+
pydantic_ai/providers/google_vertex.py,sha256=ClXkXg0vrRy1KttAPMmzLPayHTEYTDLKLIY-3DeXdzE,9244
|
|
41
|
+
pydantic_ai/providers/openai.py,sha256=wa6_UXtpOCc_XWuyru3Bf1QH44JGXsM3sIOhUa5Y6qs,2893
|
|
42
|
+
pydantic_ai_slim-0.0.37.dist-info/METADATA,sha256=Hp_5-Dn11hnKTjhXLQdvB9p7MUM7jK8iOf3RzrvwyYg,3343
|
|
43
|
+
pydantic_ai_slim-0.0.37.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
44
|
+
pydantic_ai_slim-0.0.37.dist-info/entry_points.txt,sha256=KxQSmlMS8GMTkwTsl4_q9a5nJvBjj3HWeXx688wLrKg,45
|
|
45
|
+
pydantic_ai_slim-0.0.37.dist-info/RECORD,,
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
pydantic_ai/__init__.py,sha256=xrSDxkBwpUVInbPtTVhReEecStk-mWZMttAPUAQR0Ic,927
|
|
2
|
-
pydantic_ai/_agent_graph.py,sha256=wbhm3_5VNpx_Oy1_sQ_6b2hkaFjd9vd1v9g3Rw_8sJY,30127
|
|
3
|
-
pydantic_ai/_cli.py,sha256=vvbRmOO1lj8AgEjJi0-I-05ofKFsj87fibW2EZLt1hU,8605
|
|
4
|
-
pydantic_ai/_griffe.py,sha256=RYRKiLbgG97QxnazbAwlnc74XxevGHLQet-FGfq9qls,3960
|
|
5
|
-
pydantic_ai/_parts_manager.py,sha256=ARfDQY1_5AIY5rNl_M2fAYHEFCe03ZxdhgjHf9qeIKw,11872
|
|
6
|
-
pydantic_ai/_pydantic.py,sha256=SxI7HBLzAATlO-_UP4eEuKItkxrkYYToBQMIDdLvwI4,8808
|
|
7
|
-
pydantic_ai/_result.py,sha256=SlxqR-AKWzDoc7cRRN2jmIZ7pCv3DKzaP-dnZW-e7us,10117
|
|
8
|
-
pydantic_ai/_system_prompt.py,sha256=602c2jyle2R_SesOrITBDETZqsLk4BZ8Cbo8yEhmx04,1120
|
|
9
|
-
pydantic_ai/_utils.py,sha256=nx4Suswk2qjLvzphx8uQntKzFi-IzvhX_H1L7t_kJlQ,9579
|
|
10
|
-
pydantic_ai/agent.py,sha256=IMngkZhSuX2X-4HrXWTIm14IZL2R6s73RflwsKkGfOQ,66873
|
|
11
|
-
pydantic_ai/exceptions.py,sha256=1ujJeB3jDDQ-pH5ydBYrgStvR35-GlEW0bYGTGEr4ME,3127
|
|
12
|
-
pydantic_ai/format_as_xml.py,sha256=QE7eMlg5-YUMw1_2kcI3h0uKYPZZyGkgXFDtfZTMeeI,4480
|
|
13
|
-
pydantic_ai/messages.py,sha256=yEYLz27UaiQBgMfzBkHR1I2RtCk5ba9eulNRdUHQxrY,23950
|
|
14
|
-
pydantic_ai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
pydantic_ai/result.py,sha256=LXKxRzy_rGMkdZ8xJ7yknPP3wGZtGNeZl-gh5opXbaQ,22542
|
|
16
|
-
pydantic_ai/settings.py,sha256=ntuWnke9UA18aByDxk9OIhN0tAgOaPdqCEkRf-wlp8Y,3059
|
|
17
|
-
pydantic_ai/tools.py,sha256=IPZuZJCSQUppz1uyLVwpfFLGoMirB8YtKWXIDQGR444,13414
|
|
18
|
-
pydantic_ai/usage.py,sha256=VmpU_o_RjFI65J81G1wfCwDIAYBclMjeWfLtslntFOw,5406
|
|
19
|
-
pydantic_ai/common_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
pydantic_ai/common_tools/duckduckgo.py,sha256=-kSa1gGn5-NIYvtxFWrFcX2XdmfEmGxI3_wAqrb6jLI,2230
|
|
21
|
-
pydantic_ai/common_tools/tavily.py,sha256=Lz35037ggkdWKa_Stj0yXBkiN_hygDefEevoRDUclF0,2560
|
|
22
|
-
pydantic_ai/models/__init__.py,sha256=m1TWcmpTKn7hKDqlBNaIt2shUlhFqrVxtFOluhlp0B0,13894
|
|
23
|
-
pydantic_ai/models/anthropic.py,sha256=DxoaSSo-HZYJSqbOAR2p7gsW6kUXY-SV6aA1j-8gy6c,20679
|
|
24
|
-
pydantic_ai/models/cohere.py,sha256=6F6eWPGVT7mpMXlRugbVbR-a8Q1zmb1SKS_fWOoBL80,11514
|
|
25
|
-
pydantic_ai/models/fallback.py,sha256=smHwNIpxu19JsgYYjY0nmzl3yox7yQRJ0Ir08zdhnk0,4207
|
|
26
|
-
pydantic_ai/models/function.py,sha256=THIwVJ8qI3efYLNlYXlYze_J8hc7MHB-NMb3kpknq0g,11373
|
|
27
|
-
pydantic_ai/models/gemini.py,sha256=r7PG7dMruGNmqFRWVFYLmxhICw2oAYfdB9Q1qLoSf8U,35804
|
|
28
|
-
pydantic_ai/models/groq.py,sha256=Z4sZJDu5Yxa2tZiAPp9EjSVMz4uwLhS3fW7kFSc09gI,16406
|
|
29
|
-
pydantic_ai/models/instrumented.py,sha256=TFxY-JFpwH8hkr4pEC8InhI7VjdSTzUFGGi5vgh6Cuc,9567
|
|
30
|
-
pydantic_ai/models/mistral.py,sha256=ZJ4xPcL9wJIQ5io34yP2fPyXy8GZrSvsW4itZiKPYFw,27448
|
|
31
|
-
pydantic_ai/models/openai.py,sha256=NpRFXO-Wc0VVmTY9OHyfl8Qelc_ecxcmRIn6F00CH0Y,21595
|
|
32
|
-
pydantic_ai/models/test.py,sha256=Ux20cmuJFkhvI9L1N7ItHNFcd-j284TBEsrM53eWRag,16873
|
|
33
|
-
pydantic_ai/models/vertexai.py,sha256=KbbLC1wdMqlKTh4Ot07Q4ejy-nfl_ZFI8WAST5j1dBk,9869
|
|
34
|
-
pydantic_ai/models/wrapper.py,sha256=Zr3fgiUBpt2N9gXds6iSwaMEtEsFKr9WwhpHjSoHa7o,1410
|
|
35
|
-
pydantic_ai/providers/__init__.py,sha256=tiH0iwFUjOlYuFQqK2L1coAPgCRlFU_NuLlbJiy_kNg,1819
|
|
36
|
-
pydantic_ai/providers/deepseek.py,sha256=KDNvVXjB8cuRTw_xEM1JYLKig9V5YdvGFPm-dcf0kdc,2065
|
|
37
|
-
pydantic_ai/providers/google_gla.py,sha256=sfJXkuGW17nI-P40glnO8DaL_mrpL4uafgoH8xPvcEY,1539
|
|
38
|
-
pydantic_ai/providers/google_vertex.py,sha256=F2vVukvXeeujgDnbCQnnDQg_3pDFHsyufTGzjJkYvus,7329
|
|
39
|
-
pydantic_ai/providers/openai.py,sha256=wa6_UXtpOCc_XWuyru3Bf1QH44JGXsM3sIOhUa5Y6qs,2893
|
|
40
|
-
pydantic_ai_slim-0.0.35.dist-info/METADATA,sha256=5NOAgrhn6OLK48ch_mJBcARvwEK67ApFm0agVE0DHso,3268
|
|
41
|
-
pydantic_ai_slim-0.0.35.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
42
|
-
pydantic_ai_slim-0.0.35.dist-info/entry_points.txt,sha256=KxQSmlMS8GMTkwTsl4_q9a5nJvBjj3HWeXx688wLrKg,45
|
|
43
|
-
pydantic_ai_slim-0.0.35.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|