pydantic-ai-slim 0.2.8__tar.gz → 0.2.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/PKG-INFO +6 -6
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_cli.py +1 -1
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/mcp.py +49 -32
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/__init__.py +39 -15
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/anthropic.py +3 -8
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/gemini.py +35 -21
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/google.py +9 -5
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pyproject.toml +2 -2
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/.gitignore +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/LICENSE +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/README.md +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/__init__.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/__main__.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_a2a.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_agent_graph.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_griffe.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_output.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_parts_manager.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_pydantic.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_system_prompt.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/_utils.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/agent.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/common_tools/__init__.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/common_tools/duckduckgo.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/common_tools/tavily.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/direct.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/exceptions.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/format_as_xml.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/format_prompt.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/messages.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/_json_schema.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/bedrock.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/cohere.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/fallback.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/function.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/groq.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/instrumented.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/mistral.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/openai.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/test.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/models/wrapper.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/__init__.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/anthropic.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/azure.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/bedrock.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/cohere.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/deepseek.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/google.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/google_gla.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/google_vertex.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/groq.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/mistral.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/openai.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/providers/openrouter.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/py.typed +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/result.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/settings.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/tools.py +0 -0
- {pydantic_ai_slim-0.2.8 → pydantic_ai_slim-0.2.10}/pydantic_ai/usage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai-slim
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.10
|
|
4
4
|
Summary: Agent Framework / shim to use Pydantic with LLMs, slim package
|
|
5
5
|
Author-email: Samuel Colvin <samuel@pydantic.dev>, Marcelo Trylesinski <marcelotryle@gmail.com>, David Montague <david@pydantic.dev>, Alex Hall <alex@pydantic.dev>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -30,13 +30,13 @@ Requires-Dist: exceptiongroup; python_version < '3.11'
|
|
|
30
30
|
Requires-Dist: griffe>=1.3.2
|
|
31
31
|
Requires-Dist: httpx>=0.27
|
|
32
32
|
Requires-Dist: opentelemetry-api>=1.28.0
|
|
33
|
-
Requires-Dist: pydantic-graph==0.2.
|
|
33
|
+
Requires-Dist: pydantic-graph==0.2.10
|
|
34
34
|
Requires-Dist: pydantic>=2.10
|
|
35
35
|
Requires-Dist: typing-inspection>=0.4.0
|
|
36
36
|
Provides-Extra: a2a
|
|
37
|
-
Requires-Dist: fasta2a==0.2.
|
|
37
|
+
Requires-Dist: fasta2a==0.2.10; extra == 'a2a'
|
|
38
38
|
Provides-Extra: anthropic
|
|
39
|
-
Requires-Dist: anthropic>=0.
|
|
39
|
+
Requires-Dist: anthropic>=0.52.0; extra == 'anthropic'
|
|
40
40
|
Provides-Extra: bedrock
|
|
41
41
|
Requires-Dist: boto3>=1.35.74; extra == 'bedrock'
|
|
42
42
|
Provides-Extra: cli
|
|
@@ -48,7 +48,7 @@ Requires-Dist: cohere>=5.13.11; (platform_system != 'Emscripten') and extra == '
|
|
|
48
48
|
Provides-Extra: duckduckgo
|
|
49
49
|
Requires-Dist: duckduckgo-search>=7.0.0; extra == 'duckduckgo'
|
|
50
50
|
Provides-Extra: evals
|
|
51
|
-
Requires-Dist: pydantic-evals==0.2.
|
|
51
|
+
Requires-Dist: pydantic-evals==0.2.10; extra == 'evals'
|
|
52
52
|
Provides-Extra: google
|
|
53
53
|
Requires-Dist: google-genai>=1.15.0; extra == 'google'
|
|
54
54
|
Provides-Extra: groq
|
|
@@ -56,7 +56,7 @@ Requires-Dist: groq>=0.15.0; extra == 'groq'
|
|
|
56
56
|
Provides-Extra: logfire
|
|
57
57
|
Requires-Dist: logfire>=3.11.0; extra == 'logfire'
|
|
58
58
|
Provides-Extra: mcp
|
|
59
|
-
Requires-Dist: mcp>=1.
|
|
59
|
+
Requires-Dist: mcp>=1.8.0; (python_version >= '3.10') and extra == 'mcp'
|
|
60
60
|
Provides-Extra: mistral
|
|
61
61
|
Requires-Dist: mistralai>=1.2.5; extra == 'mistral'
|
|
62
62
|
Provides-Extra: openai
|
|
@@ -284,7 +284,7 @@ async def ask_agent(
|
|
|
284
284
|
stack.enter_context(live) # entering multiple times is idempotent
|
|
285
285
|
|
|
286
286
|
async for content in handle_stream.stream_output(debounce_by=None):
|
|
287
|
-
live.update(Markdown(content, code_theme=code_theme))
|
|
287
|
+
live.update(Markdown(str(content), code_theme=code_theme))
|
|
288
288
|
|
|
289
289
|
assert agent_run.result is not None
|
|
290
290
|
return agent_run.result.all_messages()
|
|
@@ -6,16 +6,18 @@ from abc import ABC, abstractmethod
|
|
|
6
6
|
from collections.abc import AsyncIterator, Sequence
|
|
7
7
|
from contextlib import AsyncExitStack, asynccontextmanager
|
|
8
8
|
from dataclasses import dataclass
|
|
9
|
+
from datetime import timedelta
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
from types import TracebackType
|
|
11
12
|
from typing import Any
|
|
12
13
|
|
|
14
|
+
import anyio
|
|
13
15
|
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
|
|
16
|
+
from mcp.shared.message import SessionMessage
|
|
14
17
|
from mcp.types import (
|
|
15
18
|
BlobResourceContents,
|
|
16
19
|
EmbeddedResource,
|
|
17
20
|
ImageContent,
|
|
18
|
-
JSONRPCMessage,
|
|
19
21
|
LoggingLevel,
|
|
20
22
|
TextContent,
|
|
21
23
|
TextResourceContents,
|
|
@@ -28,8 +30,8 @@ from pydantic_ai.tools import ToolDefinition
|
|
|
28
30
|
|
|
29
31
|
try:
|
|
30
32
|
from mcp.client.session import ClientSession
|
|
31
|
-
from mcp.client.sse import sse_client
|
|
32
33
|
from mcp.client.stdio import StdioServerParameters, stdio_client
|
|
34
|
+
from mcp.client.streamable_http import streamablehttp_client
|
|
33
35
|
except ImportError as _import_error:
|
|
34
36
|
raise ImportError(
|
|
35
37
|
'Please install the `mcp` package to use the MCP server, '
|
|
@@ -55,8 +57,8 @@ class MCPServer(ABC):
|
|
|
55
57
|
"""
|
|
56
58
|
|
|
57
59
|
_client: ClientSession
|
|
58
|
-
_read_stream: MemoryObjectReceiveStream[
|
|
59
|
-
_write_stream: MemoryObjectSendStream[
|
|
60
|
+
_read_stream: MemoryObjectReceiveStream[SessionMessage | Exception]
|
|
61
|
+
_write_stream: MemoryObjectSendStream[SessionMessage]
|
|
60
62
|
_exit_stack: AsyncExitStack
|
|
61
63
|
|
|
62
64
|
@abstractmethod
|
|
@@ -64,10 +66,7 @@ class MCPServer(ABC):
|
|
|
64
66
|
async def client_streams(
|
|
65
67
|
self,
|
|
66
68
|
) -> AsyncIterator[
|
|
67
|
-
tuple[
|
|
68
|
-
MemoryObjectReceiveStream[JSONRPCMessage | Exception],
|
|
69
|
-
MemoryObjectSendStream[JSONRPCMessage],
|
|
70
|
-
]
|
|
69
|
+
tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage]]
|
|
71
70
|
]:
|
|
72
71
|
"""Create the streams for the MCP server."""
|
|
73
72
|
raise NotImplementedError('MCP Server subclasses must implement this method.')
|
|
@@ -78,6 +77,9 @@ class MCPServer(ABC):
|
|
|
78
77
|
"""Get the log level for the MCP server."""
|
|
79
78
|
raise NotImplementedError('MCP Server subclasses must implement this method.')
|
|
80
79
|
|
|
80
|
+
def _get_client_initialize_timeout(self) -> float:
|
|
81
|
+
return 5 # pragma: no cover
|
|
82
|
+
|
|
81
83
|
def get_prefixed_tool_name(self, tool_name: str) -> str:
|
|
82
84
|
"""Get the tool name with prefix if `tool_prefix` is set."""
|
|
83
85
|
return f'{self.tool_prefix}_{tool_name}' if self.tool_prefix else tool_name
|
|
@@ -137,7 +139,9 @@ class MCPServer(ABC):
|
|
|
137
139
|
client = ClientSession(read_stream=self._read_stream, write_stream=self._write_stream)
|
|
138
140
|
self._client = await self._exit_stack.enter_async_context(client)
|
|
139
141
|
|
|
140
|
-
|
|
142
|
+
with anyio.fail_after(self._get_client_initialize_timeout()):
|
|
143
|
+
await self._client.initialize()
|
|
144
|
+
|
|
141
145
|
if log_level := self._get_log_level():
|
|
142
146
|
await self._client.set_logging_level(log_level)
|
|
143
147
|
self.is_running = True
|
|
@@ -252,14 +256,14 @@ class MCPServerStdio(MCPServer):
|
|
|
252
256
|
e.g. if `tool_prefix='foo'`, then a tool named `bar` will be registered as `foo_bar`
|
|
253
257
|
"""
|
|
254
258
|
|
|
259
|
+
timeout: float = 5
|
|
260
|
+
""" The timeout in seconds to wait for the client to initialize."""
|
|
261
|
+
|
|
255
262
|
@asynccontextmanager
|
|
256
263
|
async def client_streams(
|
|
257
264
|
self,
|
|
258
265
|
) -> AsyncIterator[
|
|
259
|
-
tuple[
|
|
260
|
-
MemoryObjectReceiveStream[JSONRPCMessage | Exception],
|
|
261
|
-
MemoryObjectSendStream[JSONRPCMessage],
|
|
262
|
-
]
|
|
266
|
+
tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage]]
|
|
263
267
|
]:
|
|
264
268
|
server = StdioServerParameters(command=self.command, args=list(self.args), env=self.env, cwd=self.cwd)
|
|
265
269
|
async with stdio_client(server=server) as (read_stream, write_stream):
|
|
@@ -271,16 +275,19 @@ class MCPServerStdio(MCPServer):
|
|
|
271
275
|
def __repr__(self) -> str:
|
|
272
276
|
return f'MCPServerStdio(command={self.command!r}, args={self.args!r}, tool_prefix={self.tool_prefix!r})'
|
|
273
277
|
|
|
278
|
+
def _get_client_initialize_timeout(self) -> float:
|
|
279
|
+
return self.timeout
|
|
280
|
+
|
|
274
281
|
|
|
275
282
|
@dataclass
|
|
276
283
|
class MCPServerHTTP(MCPServer):
|
|
277
284
|
"""An MCP server that connects over streamable HTTP connections.
|
|
278
285
|
|
|
279
|
-
This class implements the
|
|
280
|
-
See <https://
|
|
286
|
+
This class implements the Streamable HTTP transport from the MCP specification.
|
|
287
|
+
See <https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http> for more information.
|
|
281
288
|
|
|
282
|
-
The
|
|
283
|
-
|
|
289
|
+
The Streamable HTTP transport is intended to replace the SSE transport from the previous protocol, but it is fully
|
|
290
|
+
backwards compatible with SSE-based servers.
|
|
284
291
|
|
|
285
292
|
!!! note
|
|
286
293
|
Using this class as an async context manager will create a new pool of HTTP connections to connect
|
|
@@ -291,7 +298,7 @@ class MCPServerHTTP(MCPServer):
|
|
|
291
298
|
from pydantic_ai import Agent
|
|
292
299
|
from pydantic_ai.mcp import MCPServerHTTP
|
|
293
300
|
|
|
294
|
-
server = MCPServerHTTP('http://localhost:3001/
|
|
301
|
+
server = MCPServerHTTP('http://localhost:3001/mcp') # (1)!
|
|
295
302
|
agent = Agent('openai:gpt-4o', mcp_servers=[server])
|
|
296
303
|
|
|
297
304
|
async def main():
|
|
@@ -304,27 +311,27 @@ class MCPServerHTTP(MCPServer):
|
|
|
304
311
|
"""
|
|
305
312
|
|
|
306
313
|
url: str
|
|
307
|
-
"""The URL of the SSE endpoint on the MCP server.
|
|
314
|
+
"""The URL of the SSE or MCP endpoint on the MCP server.
|
|
308
315
|
|
|
309
|
-
For example for a server running locally, this might be `http://localhost:3001/
|
|
316
|
+
For example for a server running locally, this might be `http://localhost:3001/mcp`.
|
|
310
317
|
"""
|
|
311
318
|
|
|
312
319
|
headers: dict[str, Any] | None = None
|
|
313
|
-
"""Optional HTTP headers to be sent with each request to the
|
|
320
|
+
"""Optional HTTP headers to be sent with each request to the endpoint.
|
|
314
321
|
|
|
315
322
|
These headers will be passed directly to the underlying `httpx.AsyncClient`.
|
|
316
323
|
Useful for authentication, custom headers, or other HTTP-specific configurations.
|
|
317
324
|
"""
|
|
318
325
|
|
|
319
326
|
timeout: float = 5
|
|
320
|
-
"""Initial connection timeout in seconds for establishing the
|
|
327
|
+
"""Initial connection timeout in seconds for establishing the connection.
|
|
321
328
|
|
|
322
329
|
This timeout applies to the initial connection setup and handshake.
|
|
323
330
|
If the connection cannot be established within this time, the operation will fail.
|
|
324
331
|
"""
|
|
325
332
|
|
|
326
|
-
sse_read_timeout: float =
|
|
327
|
-
"""Maximum time in seconds to wait for new SSE messages before timing out.
|
|
333
|
+
sse_read_timeout: float = 300
|
|
334
|
+
"""Maximum time as in seconds to wait for new SSE messages before timing out.
|
|
328
335
|
|
|
329
336
|
This timeout applies to the long-lived SSE connection after it's established.
|
|
330
337
|
If no new messages are received within this time, the connection will be considered stale
|
|
@@ -346,21 +353,28 @@ class MCPServerHTTP(MCPServer):
|
|
|
346
353
|
For example, if `tool_prefix='foo'`, then a tool named `bar` will be registered as `foo_bar`
|
|
347
354
|
"""
|
|
348
355
|
|
|
356
|
+
def __post_init__(self):
|
|
357
|
+
# streamablehttp_client expects timedeltas, so we accept them too to match,
|
|
358
|
+
# but primarily work with floats for a simpler user API.
|
|
359
|
+
|
|
360
|
+
if isinstance(self.timeout, timedelta):
|
|
361
|
+
self.timeout = self.timeout.total_seconds()
|
|
362
|
+
|
|
363
|
+
if isinstance(self.sse_read_timeout, timedelta):
|
|
364
|
+
self.sse_read_timeout = self.sse_read_timeout.total_seconds()
|
|
365
|
+
|
|
349
366
|
@asynccontextmanager
|
|
350
367
|
async def client_streams(
|
|
351
368
|
self,
|
|
352
369
|
) -> AsyncIterator[
|
|
353
|
-
tuple[
|
|
354
|
-
MemoryObjectReceiveStream[JSONRPCMessage | Exception],
|
|
355
|
-
MemoryObjectSendStream[JSONRPCMessage],
|
|
356
|
-
]
|
|
370
|
+
tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage]]
|
|
357
371
|
]: # pragma: no cover
|
|
358
|
-
async with
|
|
372
|
+
async with streamablehttp_client(
|
|
359
373
|
url=self.url,
|
|
360
374
|
headers=self.headers,
|
|
361
|
-
timeout=self.timeout,
|
|
362
|
-
sse_read_timeout=self.sse_read_timeout,
|
|
363
|
-
) as (read_stream, write_stream):
|
|
375
|
+
timeout=timedelta(seconds=self.timeout),
|
|
376
|
+
sse_read_timeout=timedelta(self.sse_read_timeout),
|
|
377
|
+
) as (read_stream, write_stream, _):
|
|
364
378
|
yield read_stream, write_stream
|
|
365
379
|
|
|
366
380
|
def _get_log_level(self) -> LoggingLevel | None:
|
|
@@ -368,3 +382,6 @@ class MCPServerHTTP(MCPServer):
|
|
|
368
382
|
|
|
369
383
|
def __repr__(self) -> str: # pragma: no cover
|
|
370
384
|
return f'MCPServerHTTP(url={self.url!r}, tool_prefix={self.tool_prefix!r})'
|
|
385
|
+
|
|
386
|
+
def _get_client_initialize_timeout(self) -> float: # pragma: no cover
|
|
387
|
+
return self.timeout
|
|
@@ -26,12 +26,25 @@ from ..usage import Usage
|
|
|
26
26
|
KnownModelName = TypeAliasType(
|
|
27
27
|
'KnownModelName',
|
|
28
28
|
Literal[
|
|
29
|
-
'anthropic:claude-
|
|
29
|
+
'anthropic:claude-2.0',
|
|
30
|
+
'anthropic:claude-2.1',
|
|
31
|
+
'anthropic:claude-3-5-haiku-20241022',
|
|
30
32
|
'anthropic:claude-3-5-haiku-latest',
|
|
33
|
+
'anthropic:claude-3-5-sonnet-20240620',
|
|
34
|
+
'anthropic:claude-3-5-sonnet-20241022',
|
|
31
35
|
'anthropic:claude-3-5-sonnet-latest',
|
|
36
|
+
'anthropic:claude-3-7-sonnet-20250219',
|
|
37
|
+
'anthropic:claude-3-7-sonnet-latest',
|
|
38
|
+
'anthropic:claude-3-haiku-20240307',
|
|
39
|
+
'anthropic:claude-3-opus-20240229',
|
|
32
40
|
'anthropic:claude-3-opus-latest',
|
|
33
|
-
'claude-3-
|
|
34
|
-
'claude-
|
|
41
|
+
'anthropic:claude-3-sonnet-20240229',
|
|
42
|
+
'anthropic:claude-4-opus-20250514',
|
|
43
|
+
'anthropic:claude-4-sonnet-20250514',
|
|
44
|
+
'anthropic:claude-opus-4-0',
|
|
45
|
+
'anthropic:claude-opus-4-20250514',
|
|
46
|
+
'anthropic:claude-sonnet-4-0',
|
|
47
|
+
'anthropic:claude-sonnet-4-20250514',
|
|
35
48
|
'bedrock:amazon.titan-tg1-large',
|
|
36
49
|
'bedrock:amazon.titan-text-lite-v1',
|
|
37
50
|
'bedrock:amazon.titan-text-express-v1',
|
|
@@ -75,8 +88,25 @@ KnownModelName = TypeAliasType(
|
|
|
75
88
|
'bedrock:mistral.mixtral-8x7b-instruct-v0:1',
|
|
76
89
|
'bedrock:mistral.mistral-large-2402-v1:0',
|
|
77
90
|
'bedrock:mistral.mistral-large-2407-v1:0',
|
|
91
|
+
'claude-2.0',
|
|
92
|
+
'claude-2.1',
|
|
93
|
+
'claude-3-5-haiku-20241022',
|
|
94
|
+
'claude-3-5-haiku-latest',
|
|
95
|
+
'claude-3-5-sonnet-20240620',
|
|
96
|
+
'claude-3-5-sonnet-20241022',
|
|
78
97
|
'claude-3-5-sonnet-latest',
|
|
98
|
+
'claude-3-7-sonnet-20250219',
|
|
99
|
+
'claude-3-7-sonnet-latest',
|
|
100
|
+
'claude-3-haiku-20240307',
|
|
101
|
+
'claude-3-opus-20240229',
|
|
79
102
|
'claude-3-opus-latest',
|
|
103
|
+
'claude-3-sonnet-20240229',
|
|
104
|
+
'claude-4-opus-20250514',
|
|
105
|
+
'claude-4-sonnet-20250514',
|
|
106
|
+
'claude-opus-4-0',
|
|
107
|
+
'claude-opus-4-20250514',
|
|
108
|
+
'claude-sonnet-4-0',
|
|
109
|
+
'claude-sonnet-4-20250514',
|
|
80
110
|
'cohere:c4ai-aya-expanse-32b',
|
|
81
111
|
'cohere:c4ai-aya-expanse-8b',
|
|
82
112
|
'cohere:command',
|
|
@@ -92,32 +122,26 @@ KnownModelName = TypeAliasType(
|
|
|
92
122
|
'cohere:command-r7b-12-2024',
|
|
93
123
|
'deepseek:deepseek-chat',
|
|
94
124
|
'deepseek:deepseek-reasoner',
|
|
95
|
-
'google-gla:gemini-1.0-pro',
|
|
96
125
|
'google-gla:gemini-1.5-flash',
|
|
97
126
|
'google-gla:gemini-1.5-flash-8b',
|
|
98
127
|
'google-gla:gemini-1.5-pro',
|
|
99
|
-
'google-gla:gemini-
|
|
100
|
-
'google-gla:gemini-2.0-flash-thinking-exp-01-21',
|
|
101
|
-
'google-gla:gemini-exp-1206',
|
|
128
|
+
'google-gla:gemini-1.0-pro',
|
|
102
129
|
'google-gla:gemini-2.0-flash',
|
|
103
130
|
'google-gla:gemini-2.0-flash-lite-preview-02-05',
|
|
104
131
|
'google-gla:gemini-2.0-pro-exp-02-05',
|
|
105
|
-
'google-gla:gemini-2.5-flash-preview-
|
|
132
|
+
'google-gla:gemini-2.5-flash-preview-05-20',
|
|
106
133
|
'google-gla:gemini-2.5-pro-exp-03-25',
|
|
107
|
-
'google-gla:gemini-2.5-pro-preview-
|
|
108
|
-
'google-vertex:gemini-1.0-pro',
|
|
134
|
+
'google-gla:gemini-2.5-pro-preview-05-06',
|
|
109
135
|
'google-vertex:gemini-1.5-flash',
|
|
110
136
|
'google-vertex:gemini-1.5-flash-8b',
|
|
111
137
|
'google-vertex:gemini-1.5-pro',
|
|
112
|
-
'google-vertex:gemini-
|
|
113
|
-
'google-vertex:gemini-2.0-flash-thinking-exp-01-21',
|
|
114
|
-
'google-vertex:gemini-exp-1206',
|
|
138
|
+
'google-vertex:gemini-1.0-pro',
|
|
115
139
|
'google-vertex:gemini-2.0-flash',
|
|
116
140
|
'google-vertex:gemini-2.0-flash-lite-preview-02-05',
|
|
117
141
|
'google-vertex:gemini-2.0-pro-exp-02-05',
|
|
118
|
-
'google-vertex:gemini-2.5-flash-preview-
|
|
142
|
+
'google-vertex:gemini-2.5-flash-preview-05-20',
|
|
119
143
|
'google-vertex:gemini-2.5-pro-exp-03-25',
|
|
120
|
-
'google-vertex:gemini-2.5-pro-preview-
|
|
144
|
+
'google-vertex:gemini-2.5-pro-preview-05-06',
|
|
121
145
|
'gpt-3.5-turbo',
|
|
122
146
|
'gpt-3.5-turbo-0125',
|
|
123
147
|
'gpt-3.5-turbo-0301',
|
|
@@ -7,7 +7,6 @@ from dataclasses import dataclass, field
|
|
|
7
7
|
from datetime import datetime, timezone
|
|
8
8
|
from typing import Any, Literal, Union, cast, overload
|
|
9
9
|
|
|
10
|
-
from anthropic import AsyncAnthropic
|
|
11
10
|
from typing_extensions import assert_never
|
|
12
11
|
|
|
13
12
|
from .. import ModelHTTPError, UnexpectedModelBehavior, _utils, usage
|
|
@@ -41,7 +40,7 @@ from . import (
|
|
|
41
40
|
)
|
|
42
41
|
|
|
43
42
|
try:
|
|
44
|
-
from anthropic import NOT_GIVEN, APIStatusError, AsyncStream
|
|
43
|
+
from anthropic import NOT_GIVEN, APIStatusError, AsyncAnthropic, AsyncStream
|
|
45
44
|
from anthropic.types.beta import (
|
|
46
45
|
BetaBase64PDFBlockParam,
|
|
47
46
|
BetaBase64PDFSourceParam,
|
|
@@ -68,6 +67,7 @@ try:
|
|
|
68
67
|
BetaToolUseBlock,
|
|
69
68
|
BetaToolUseBlockParam,
|
|
70
69
|
)
|
|
70
|
+
from anthropic.types.model_param import ModelParam
|
|
71
71
|
|
|
72
72
|
except ImportError as _import_error:
|
|
73
73
|
raise ImportError(
|
|
@@ -75,12 +75,7 @@ except ImportError as _import_error:
|
|
|
75
75
|
'you can use the `anthropic` optional group — `pip install "pydantic-ai-slim[anthropic]"`'
|
|
76
76
|
) from _import_error
|
|
77
77
|
|
|
78
|
-
LatestAnthropicModelNames =
|
|
79
|
-
'claude-3-7-sonnet-latest',
|
|
80
|
-
'claude-3-5-haiku-latest',
|
|
81
|
-
'claude-3-5-sonnet-latest',
|
|
82
|
-
'claude-3-opus-latest',
|
|
83
|
-
]
|
|
78
|
+
LatestAnthropicModelNames = ModelParam
|
|
84
79
|
"""Latest Anthropic models."""
|
|
85
80
|
|
|
86
81
|
AnthropicModelName = Union[str, LatestAnthropicModelNames]
|
|
@@ -52,15 +52,12 @@ LatestGeminiModelNames = Literal[
|
|
|
52
52
|
'gemini-1.5-flash-8b',
|
|
53
53
|
'gemini-1.5-pro',
|
|
54
54
|
'gemini-1.0-pro',
|
|
55
|
-
'gemini-2.0-flash-exp',
|
|
56
|
-
'gemini-2.0-flash-thinking-exp-01-21',
|
|
57
|
-
'gemini-exp-1206',
|
|
58
55
|
'gemini-2.0-flash',
|
|
59
56
|
'gemini-2.0-flash-lite-preview-02-05',
|
|
60
57
|
'gemini-2.0-pro-exp-02-05',
|
|
61
|
-
'gemini-2.5-flash-preview-
|
|
58
|
+
'gemini-2.5-flash-preview-05-20',
|
|
62
59
|
'gemini-2.5-pro-exp-03-25',
|
|
63
|
-
'gemini-2.5-pro-preview-
|
|
60
|
+
'gemini-2.5-pro-preview-05-06',
|
|
64
61
|
]
|
|
65
62
|
"""Latest Gemini models."""
|
|
66
63
|
|
|
@@ -80,6 +77,7 @@ class GeminiModelSettings(ModelSettings, total=False):
|
|
|
80
77
|
"""
|
|
81
78
|
|
|
82
79
|
gemini_safety_settings: list[GeminiSafetySettings]
|
|
80
|
+
"""Safety settings options for Gemini model request."""
|
|
83
81
|
|
|
84
82
|
gemini_thinking_config: ThinkingConfig
|
|
85
83
|
"""Thinking is "on" by default in both the API and AI Studio.
|
|
@@ -93,6 +91,12 @@ class GeminiModelSettings(ModelSettings, total=False):
|
|
|
93
91
|
See more about it on <https://ai.google.dev/gemini-api/docs/thinking>.
|
|
94
92
|
"""
|
|
95
93
|
|
|
94
|
+
gemini_labels: dict[str, str]
|
|
95
|
+
"""User-defined metadata to break down billed charges. Only supported by the Vertex AI provider.
|
|
96
|
+
|
|
97
|
+
See the [Gemini API docs](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/add-labels-to-api-calls) for use cases and limitations.
|
|
98
|
+
"""
|
|
99
|
+
|
|
96
100
|
|
|
97
101
|
@dataclass(init=False)
|
|
98
102
|
class GeminiModel(Model):
|
|
@@ -223,25 +227,17 @@ class GeminiModel(Model):
|
|
|
223
227
|
if tool_config is not None:
|
|
224
228
|
request_data['toolConfig'] = tool_config
|
|
225
229
|
|
|
226
|
-
generation_config
|
|
227
|
-
if model_settings:
|
|
228
|
-
if (max_tokens := model_settings.get('max_tokens')) is not None:
|
|
229
|
-
generation_config['max_output_tokens'] = max_tokens
|
|
230
|
-
if (temperature := model_settings.get('temperature')) is not None:
|
|
231
|
-
generation_config['temperature'] = temperature
|
|
232
|
-
if (top_p := model_settings.get('top_p')) is not None:
|
|
233
|
-
generation_config['top_p'] = top_p
|
|
234
|
-
if (presence_penalty := model_settings.get('presence_penalty')) is not None:
|
|
235
|
-
generation_config['presence_penalty'] = presence_penalty
|
|
236
|
-
if (frequency_penalty := model_settings.get('frequency_penalty')) is not None:
|
|
237
|
-
generation_config['frequency_penalty'] = frequency_penalty
|
|
238
|
-
if (thinkingConfig := model_settings.get('gemini_thinking_config')) is not None:
|
|
239
|
-
generation_config['thinking_config'] = thinkingConfig # pragma: no cover
|
|
240
|
-
if (gemini_safety_settings := model_settings.get('gemini_safety_settings')) is not None:
|
|
241
|
-
request_data['safetySettings'] = gemini_safety_settings
|
|
230
|
+
generation_config = _settings_to_generation_config(model_settings)
|
|
242
231
|
if generation_config:
|
|
243
232
|
request_data['generationConfig'] = generation_config
|
|
244
233
|
|
|
234
|
+
if gemini_safety_settings := model_settings.get('gemini_safety_settings'):
|
|
235
|
+
request_data['safetySettings'] = gemini_safety_settings
|
|
236
|
+
|
|
237
|
+
if gemini_labels := model_settings.get('gemini_labels'):
|
|
238
|
+
if self._system == 'google-vertex':
|
|
239
|
+
request_data['labels'] = gemini_labels
|
|
240
|
+
|
|
245
241
|
headers = {'Content-Type': 'application/json', 'User-Agent': get_user_agent()}
|
|
246
242
|
url = f'/{self._model_name}:{"streamGenerateContent" if streamed else "generateContent"}'
|
|
247
243
|
|
|
@@ -362,6 +358,23 @@ class GeminiModel(Model):
|
|
|
362
358
|
return content
|
|
363
359
|
|
|
364
360
|
|
|
361
|
+
def _settings_to_generation_config(model_settings: GeminiModelSettings) -> _GeminiGenerationConfig:
|
|
362
|
+
config: _GeminiGenerationConfig = {}
|
|
363
|
+
if (max_tokens := model_settings.get('max_tokens')) is not None:
|
|
364
|
+
config['max_output_tokens'] = max_tokens
|
|
365
|
+
if (temperature := model_settings.get('temperature')) is not None:
|
|
366
|
+
config['temperature'] = temperature
|
|
367
|
+
if (top_p := model_settings.get('top_p')) is not None:
|
|
368
|
+
config['top_p'] = top_p
|
|
369
|
+
if (presence_penalty := model_settings.get('presence_penalty')) is not None:
|
|
370
|
+
config['presence_penalty'] = presence_penalty
|
|
371
|
+
if (frequency_penalty := model_settings.get('frequency_penalty')) is not None:
|
|
372
|
+
config['frequency_penalty'] = frequency_penalty
|
|
373
|
+
if (thinkingConfig := model_settings.get('gemini_thinking_config')) is not None:
|
|
374
|
+
config['thinking_config'] = thinkingConfig # pragma: no cover
|
|
375
|
+
return config
|
|
376
|
+
|
|
377
|
+
|
|
365
378
|
class AuthProtocol(Protocol):
|
|
366
379
|
"""Abstract definition for Gemini authentication."""
|
|
367
380
|
|
|
@@ -483,6 +496,7 @@ class _GeminiRequest(TypedDict):
|
|
|
483
496
|
<https://ai.google.dev/gemini-api/docs/system-instructions?lang=rest>
|
|
484
497
|
"""
|
|
485
498
|
generationConfig: NotRequired[_GeminiGenerationConfig]
|
|
499
|
+
labels: NotRequired[dict[str, str]]
|
|
486
500
|
|
|
487
501
|
|
|
488
502
|
class GeminiSafetySettings(TypedDict):
|
|
@@ -76,15 +76,12 @@ LatestGoogleModelNames = Literal[
|
|
|
76
76
|
'gemini-1.5-flash-8b',
|
|
77
77
|
'gemini-1.5-pro',
|
|
78
78
|
'gemini-1.0-pro',
|
|
79
|
-
'gemini-2.0-flash-exp',
|
|
80
|
-
'gemini-2.0-flash-thinking-exp-01-21',
|
|
81
|
-
'gemini-exp-1206',
|
|
82
79
|
'gemini-2.0-flash',
|
|
83
80
|
'gemini-2.0-flash-lite-preview-02-05',
|
|
84
81
|
'gemini-2.0-pro-exp-02-05',
|
|
85
|
-
'gemini-2.5-flash-preview-
|
|
82
|
+
'gemini-2.5-flash-preview-05-20',
|
|
86
83
|
'gemini-2.5-pro-exp-03-25',
|
|
87
|
-
'gemini-2.5-pro-preview-
|
|
84
|
+
'gemini-2.5-pro-preview-05-06',
|
|
88
85
|
]
|
|
89
86
|
"""Latest Gemini models."""
|
|
90
87
|
|
|
@@ -115,6 +112,12 @@ class GoogleModelSettings(ModelSettings, total=False):
|
|
|
115
112
|
See <https://ai.google.dev/gemini-api/docs/thinking> for more information.
|
|
116
113
|
"""
|
|
117
114
|
|
|
115
|
+
google_labels: dict[str, str]
|
|
116
|
+
"""User-defined metadata to break down billed charges. Only supported by the Vertex AI API.
|
|
117
|
+
|
|
118
|
+
See the [Gemini API docs](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/add-labels-to-api-calls) for use cases and limitations.
|
|
119
|
+
"""
|
|
120
|
+
|
|
118
121
|
|
|
119
122
|
@dataclass(init=False)
|
|
120
123
|
class GoogleModel(Model):
|
|
@@ -269,6 +272,7 @@ class GoogleModel(Model):
|
|
|
269
272
|
frequency_penalty=model_settings.get('frequency_penalty'),
|
|
270
273
|
safety_settings=model_settings.get('google_safety_settings'),
|
|
271
274
|
thinking_config=model_settings.get('google_thinking_config'),
|
|
275
|
+
labels=model_settings.get('google_labels'),
|
|
272
276
|
tools=cast(ToolListUnionDict, tools),
|
|
273
277
|
tool_config=tool_config,
|
|
274
278
|
)
|
|
@@ -65,7 +65,7 @@ openai = ["openai>=1.75.0"]
|
|
|
65
65
|
cohere = ["cohere>=5.13.11; platform_system != 'Emscripten'"]
|
|
66
66
|
vertexai = ["google-auth>=2.36.0", "requests>=2.32.2"]
|
|
67
67
|
google = ["google-genai>=1.15.0"]
|
|
68
|
-
anthropic = ["anthropic>=0.
|
|
68
|
+
anthropic = ["anthropic>=0.52.0"]
|
|
69
69
|
groq = ["groq>=0.15.0"]
|
|
70
70
|
mistral = ["mistralai>=1.2.5"]
|
|
71
71
|
bedrock = ["boto3>=1.35.74"]
|
|
@@ -75,7 +75,7 @@ tavily = ["tavily-python>=0.5.0"]
|
|
|
75
75
|
# CLI
|
|
76
76
|
cli = ["rich>=13", "prompt-toolkit>=3", "argcomplete>=3.5.0"]
|
|
77
77
|
# MCP
|
|
78
|
-
mcp = ["mcp>=1.
|
|
78
|
+
mcp = ["mcp>=1.8.0; python_version >= '3.10'"]
|
|
79
79
|
# Evals
|
|
80
80
|
evals = ["pydantic-evals=={{ version }}"]
|
|
81
81
|
# A2A
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|