pydantic-ai-slim 1.0.11__py3-none-any.whl → 1.0.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pydantic-ai-slim might be problematic. Click here for more details.

Files changed (61) hide show
  1. pydantic_ai/__init__.py +134 -4
  2. pydantic_ai/_a2a.py +1 -1
  3. pydantic_ai/{profiles/_json_schema.py → _json_schema.py} +5 -3
  4. pydantic_ai/_thinking_part.py +1 -1
  5. pydantic_ai/_utils.py +24 -7
  6. pydantic_ai/agent/__init__.py +1 -2
  7. pydantic_ai/builtin_tools.py +20 -1
  8. pydantic_ai/common_tools/duckduckgo.py +2 -2
  9. pydantic_ai/common_tools/tavily.py +2 -2
  10. pydantic_ai/direct.py +4 -4
  11. pydantic_ai/durable_exec/dbos/_agent.py +1 -1
  12. pydantic_ai/durable_exec/dbos/_mcp_server.py +1 -2
  13. pydantic_ai/durable_exec/dbos/_model.py +2 -2
  14. pydantic_ai/durable_exec/temporal/_agent.py +1 -1
  15. pydantic_ai/durable_exec/temporal/_function_toolset.py +1 -1
  16. pydantic_ai/durable_exec/temporal/_mcp_server.py +1 -1
  17. pydantic_ai/durable_exec/temporal/_model.py +3 -3
  18. pydantic_ai/durable_exec/temporal/_toolset.py +1 -3
  19. pydantic_ai/ext/aci.py +1 -1
  20. pydantic_ai/ext/langchain.py +1 -1
  21. pydantic_ai/mcp.py +20 -6
  22. pydantic_ai/messages.py +14 -11
  23. pydantic_ai/models/__init__.py +1 -1
  24. pydantic_ai/models/anthropic.py +21 -14
  25. pydantic_ai/models/bedrock.py +6 -5
  26. pydantic_ai/models/google.py +2 -2
  27. pydantic_ai/models/openai.py +79 -29
  28. pydantic_ai/output.py +11 -1
  29. pydantic_ai/profiles/__init__.py +1 -1
  30. pydantic_ai/profiles/google.py +1 -1
  31. pydantic_ai/profiles/openai.py +1 -1
  32. pydantic_ai/providers/__init__.py +1 -1
  33. pydantic_ai/providers/anthropic.py +1 -1
  34. pydantic_ai/providers/azure.py +1 -1
  35. pydantic_ai/providers/bedrock.py +1 -1
  36. pydantic_ai/providers/cerebras.py +1 -1
  37. pydantic_ai/providers/cohere.py +1 -1
  38. pydantic_ai/providers/deepseek.py +1 -1
  39. pydantic_ai/providers/fireworks.py +1 -1
  40. pydantic_ai/providers/github.py +1 -1
  41. pydantic_ai/providers/google.py +1 -1
  42. pydantic_ai/providers/google_gla.py +1 -1
  43. pydantic_ai/providers/google_vertex.py +1 -1
  44. pydantic_ai/providers/grok.py +1 -1
  45. pydantic_ai/providers/groq.py +1 -1
  46. pydantic_ai/providers/heroku.py +1 -1
  47. pydantic_ai/providers/huggingface.py +1 -1
  48. pydantic_ai/providers/litellm.py +1 -1
  49. pydantic_ai/providers/mistral.py +1 -1
  50. pydantic_ai/providers/moonshotai.py +1 -1
  51. pydantic_ai/providers/ollama.py +1 -1
  52. pydantic_ai/providers/openai.py +1 -1
  53. pydantic_ai/providers/openrouter.py +1 -1
  54. pydantic_ai/providers/together.py +1 -1
  55. pydantic_ai/providers/vercel.py +1 -1
  56. pydantic_ai/toolsets/function.py +1 -2
  57. {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.12.dist-info}/METADATA +3 -3
  58. {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.12.dist-info}/RECORD +61 -61
  59. {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.12.dist-info}/WHEEL +0 -0
  60. {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.12.dist-info}/entry_points.txt +0 -0
  61. {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.12.dist-info}/licenses/LICENSE +0 -0
@@ -10,11 +10,10 @@ from typing import Any, Literal, cast, overload
10
10
  from pydantic import TypeAdapter
11
11
  from typing_extensions import assert_never
12
12
 
13
- from pydantic_ai.builtin_tools import CodeExecutionTool, WebSearchTool
14
-
15
13
  from .. import ModelHTTPError, UnexpectedModelBehavior, _utils, usage
16
14
  from .._run_context import RunContext
17
15
  from .._utils import guard_tool_call_id as _guard_tool_call_id
16
+ from ..builtin_tools import CodeExecutionTool, MemoryTool, WebSearchTool
18
17
  from ..exceptions import UserError
19
18
  from ..messages import (
20
19
  BinaryContent,
@@ -68,6 +67,7 @@ try:
68
67
  BetaContentBlockParam,
69
68
  BetaImageBlockParam,
70
69
  BetaInputJSONDelta,
70
+ BetaMemoryTool20250818Param,
71
71
  BetaMessage,
72
72
  BetaMessageParam,
73
73
  BetaMetadataParam,
@@ -255,8 +255,7 @@ class AnthropicModel(Model):
255
255
  ) -> BetaMessage | AsyncStream[BetaRawMessageStreamEvent]:
256
256
  # standalone function to make it easier to override
257
257
  tools = self._get_tools(model_request_parameters)
258
- builtin_tools, tool_headers = self._get_builtin_tools(model_request_parameters)
259
- tools += builtin_tools
258
+ tools, beta_features = self._add_builtin_tools(tools, model_request_parameters)
260
259
 
261
260
  tool_choice: BetaToolChoiceParam | None
262
261
 
@@ -279,9 +278,11 @@ class AnthropicModel(Model):
279
278
 
280
279
  try:
281
280
  extra_headers = model_settings.get('extra_headers', {})
282
- for k, v in tool_headers.items():
283
- extra_headers.setdefault(k, v)
284
281
  extra_headers.setdefault('User-Agent', get_user_agent())
282
+ if beta_features:
283
+ if 'anthropic-beta' in extra_headers:
284
+ beta_features.insert(0, extra_headers['anthropic-beta'])
285
+ extra_headers['anthropic-beta'] = ','.join(beta_features)
285
286
 
286
287
  return await self.client.beta.messages.create(
287
288
  max_tokens=model_settings.get('max_tokens', 4096),
@@ -367,14 +368,13 @@ class AnthropicModel(Model):
367
368
  _provider_name=self._provider.name,
368
369
  )
369
370
 
370
- def _get_tools(self, model_request_parameters: ModelRequestParameters) -> list[BetaToolParam]:
371
+ def _get_tools(self, model_request_parameters: ModelRequestParameters) -> list[BetaToolUnionParam]:
371
372
  return [self._map_tool_definition(r) for r in model_request_parameters.tool_defs.values()]
372
373
 
373
- def _get_builtin_tools(
374
- self, model_request_parameters: ModelRequestParameters
375
- ) -> tuple[list[BetaToolUnionParam], dict[str, str]]:
376
- tools: list[BetaToolUnionParam] = []
377
- extra_headers: dict[str, str] = {}
374
+ def _add_builtin_tools(
375
+ self, tools: list[BetaToolUnionParam], model_request_parameters: ModelRequestParameters
376
+ ) -> tuple[list[BetaToolUnionParam], list[str]]:
377
+ beta_features: list[str] = []
378
378
  for tool in model_request_parameters.builtin_tools:
379
379
  if isinstance(tool, WebSearchTool):
380
380
  user_location = UserLocation(type='approximate', **tool.user_location) if tool.user_location else None
@@ -389,13 +389,20 @@ class AnthropicModel(Model):
389
389
  )
390
390
  )
391
391
  elif isinstance(tool, CodeExecutionTool): # pragma: no branch
392
- extra_headers['anthropic-beta'] = 'code-execution-2025-05-22'
393
392
  tools.append(BetaCodeExecutionTool20250522Param(name='code_execution', type='code_execution_20250522'))
393
+ beta_features.append('code-execution-2025-05-22')
394
+ elif isinstance(tool, MemoryTool): # pragma: no branch
395
+ if 'memory' not in model_request_parameters.tool_defs:
396
+ raise UserError("Built-in `MemoryTool` requires a 'memory' tool to be defined.")
397
+ # Replace the memory tool definition with the built-in memory tool
398
+ tools = [tool for tool in tools if tool['name'] != 'memory']
399
+ tools.append(BetaMemoryTool20250818Param(name='memory', type='memory_20250818'))
400
+ beta_features.append('context-management-2025-06-27')
394
401
  else: # pragma: no cover
395
402
  raise UserError(
396
403
  f'`{tool.__class__.__name__}` is not supported by `AnthropicModel`. If it should be, please file an issue.'
397
404
  )
398
- return tools, extra_headers
405
+ return tools, beta_features
399
406
 
400
407
  async def _map_message(self, messages: list[ModelMessage]) -> tuple[str, list[BetaMessageParam]]: # noqa: C901
401
408
  """Just maps a `pydantic_ai.Message` to a `anthropic.types.MessageParam`."""
@@ -13,10 +13,7 @@ import anyio
13
13
  import anyio.to_thread
14
14
  from typing_extensions import ParamSpec, assert_never
15
15
 
16
- from pydantic_ai import _utils, usage
17
- from pydantic_ai._run_context import RunContext
18
- from pydantic_ai.exceptions import UserError
19
- from pydantic_ai.messages import (
16
+ from pydantic_ai import (
20
17
  AudioUrl,
21
18
  BinaryContent,
22
19
  BuiltinToolCallPart,
@@ -25,6 +22,7 @@ from pydantic_ai.messages import (
25
22
  FinishReason,
26
23
  ImageUrl,
27
24
  ModelMessage,
25
+ ModelProfileSpec,
28
26
  ModelRequest,
29
27
  ModelResponse,
30
28
  ModelResponsePart,
@@ -37,9 +35,12 @@ from pydantic_ai.messages import (
37
35
  ToolReturnPart,
38
36
  UserPromptPart,
39
37
  VideoUrl,
38
+ _utils,
39
+ usage,
40
40
  )
41
+ from pydantic_ai._run_context import RunContext
42
+ from pydantic_ai.exceptions import UserError
41
43
  from pydantic_ai.models import Model, ModelRequestParameters, StreamedResponse, download_item
42
- from pydantic_ai.profiles import ModelProfileSpec
43
44
  from pydantic_ai.providers import Provider, infer_provider
44
45
  from pydantic_ai.providers.bedrock import BedrockModelProfile
45
46
  from pydantic_ai.settings import ModelSettings
@@ -419,8 +419,8 @@ class GoogleModel(Model):
419
419
  return contents, config
420
420
 
421
421
  def _process_response(self, response: GenerateContentResponse) -> ModelResponse:
422
- if not response.candidates or len(response.candidates) != 1:
423
- raise UnexpectedModelBehavior('Expected exactly one candidate in Gemini response') # pragma: no cover
422
+ if not response.candidates:
423
+ raise UnexpectedModelBehavior('Expected at least one candidate in Gemini response') # pragma: no cover
424
424
  candidate = response.candidates[0]
425
425
  if candidate.content is None or candidate.content.parts is None:
426
426
  if candidate.finish_reason == 'SAFETY':
@@ -519,6 +519,10 @@ class OpenAIChatModel(Model):
519
519
  timestamp = _now_utc()
520
520
  response.created = int(timestamp.timestamp())
521
521
 
522
+ # Workaround for local Ollama which sometimes returns a `None` finish reason.
523
+ if response.choices and (choice := response.choices[0]) and choice.finish_reason is None: # pyright: ignore[reportUnnecessaryComparison]
524
+ choice.finish_reason = 'stop'
525
+
522
526
  try:
523
527
  response = chat.ChatCompletion.model_validate(response.model_dump())
524
528
  except ValidationError as e:
@@ -746,8 +750,7 @@ class OpenAIChatModel(Model):
746
750
  else:
747
751
  assert_never(part)
748
752
 
749
- @staticmethod
750
- async def _map_user_prompt(part: UserPromptPart) -> chat.ChatCompletionUserMessageParam:
753
+ async def _map_user_prompt(self, part: UserPromptPart) -> chat.ChatCompletionUserMessageParam: # noqa: C901
751
754
  content: str | list[ChatCompletionContentPartParam]
752
755
  if isinstance(part.content, str):
753
756
  content = part.content
@@ -762,28 +765,40 @@ class OpenAIChatModel(Model):
762
765
  image_url['detail'] = metadata.get('detail', 'auto')
763
766
  content.append(ChatCompletionContentPartImageParam(image_url=image_url, type='image_url'))
764
767
  elif isinstance(item, BinaryContent):
765
- base64_encoded = base64.b64encode(item.data).decode('utf-8')
766
- if item.is_image:
767
- image_url: ImageURL = {'url': f'data:{item.media_type};base64,{base64_encoded}'}
768
- if metadata := item.vendor_metadata:
769
- image_url['detail'] = metadata.get('detail', 'auto')
770
- content.append(ChatCompletionContentPartImageParam(image_url=image_url, type='image_url'))
771
- elif item.is_audio:
772
- assert item.format in ('wav', 'mp3')
773
- audio = InputAudio(data=base64_encoded, format=item.format)
774
- content.append(ChatCompletionContentPartInputAudioParam(input_audio=audio, type='input_audio'))
775
- elif item.is_document:
768
+ if self._is_text_like_media_type(item.media_type):
769
+ # Inline text-like binary content as a text block
776
770
  content.append(
777
- File(
778
- file=FileFile(
779
- file_data=f'data:{item.media_type};base64,{base64_encoded}',
780
- filename=f'filename.{item.format}',
781
- ),
782
- type='file',
771
+ self._inline_text_file_part(
772
+ item.data.decode('utf-8'),
773
+ media_type=item.media_type,
774
+ identifier=item.identifier,
783
775
  )
784
776
  )
785
- else: # pragma: no cover
786
- raise RuntimeError(f'Unsupported binary content type: {item.media_type}')
777
+ else:
778
+ base64_encoded = base64.b64encode(item.data).decode('utf-8')
779
+ if item.is_image:
780
+ image_url: ImageURL = {'url': f'data:{item.media_type};base64,{base64_encoded}'}
781
+ if metadata := item.vendor_metadata:
782
+ image_url['detail'] = metadata.get('detail', 'auto')
783
+ content.append(ChatCompletionContentPartImageParam(image_url=image_url, type='image_url'))
784
+ elif item.is_audio:
785
+ assert item.format in ('wav', 'mp3')
786
+ audio = InputAudio(data=base64_encoded, format=item.format)
787
+ content.append(
788
+ ChatCompletionContentPartInputAudioParam(input_audio=audio, type='input_audio')
789
+ )
790
+ elif item.is_document:
791
+ content.append(
792
+ File(
793
+ file=FileFile(
794
+ file_data=f'data:{item.media_type};base64,{base64_encoded}',
795
+ filename=f'filename.{item.format}',
796
+ ),
797
+ type='file',
798
+ )
799
+ )
800
+ else: # pragma: no cover
801
+ raise RuntimeError(f'Unsupported binary content type: {item.media_type}')
787
802
  elif isinstance(item, AudioUrl):
788
803
  downloaded_item = await download_item(item, data_format='base64', type_format='extension')
789
804
  assert downloaded_item['data_type'] in (
@@ -793,20 +808,54 @@ class OpenAIChatModel(Model):
793
808
  audio = InputAudio(data=downloaded_item['data'], format=downloaded_item['data_type'])
794
809
  content.append(ChatCompletionContentPartInputAudioParam(input_audio=audio, type='input_audio'))
795
810
  elif isinstance(item, DocumentUrl):
796
- downloaded_item = await download_item(item, data_format='base64_uri', type_format='extension')
797
- file = File(
798
- file=FileFile(
799
- file_data=downloaded_item['data'], filename=f'filename.{downloaded_item["data_type"]}'
800
- ),
801
- type='file',
802
- )
803
- content.append(file)
811
+ if self._is_text_like_media_type(item.media_type):
812
+ downloaded_text = await download_item(item, data_format='text')
813
+ content.append(
814
+ self._inline_text_file_part(
815
+ downloaded_text['data'],
816
+ media_type=item.media_type,
817
+ identifier=item.identifier,
818
+ )
819
+ )
820
+ else:
821
+ downloaded_item = await download_item(item, data_format='base64_uri', type_format='extension')
822
+ content.append(
823
+ File(
824
+ file=FileFile(
825
+ file_data=downloaded_item['data'],
826
+ filename=f'filename.{downloaded_item["data_type"]}',
827
+ ),
828
+ type='file',
829
+ )
830
+ )
804
831
  elif isinstance(item, VideoUrl): # pragma: no cover
805
832
  raise NotImplementedError('VideoUrl is not supported for OpenAI')
806
833
  else:
807
834
  assert_never(item)
808
835
  return chat.ChatCompletionUserMessageParam(role='user', content=content)
809
836
 
837
+ @staticmethod
838
+ def _is_text_like_media_type(media_type: str) -> bool:
839
+ return (
840
+ media_type.startswith('text/')
841
+ or media_type == 'application/json'
842
+ or media_type.endswith('+json')
843
+ or media_type == 'application/xml'
844
+ or media_type.endswith('+xml')
845
+ or media_type in ('application/x-yaml', 'application/yaml')
846
+ )
847
+
848
+ @staticmethod
849
+ def _inline_text_file_part(text: str, *, media_type: str, identifier: str) -> ChatCompletionContentPartTextParam:
850
+ text = '\n'.join(
851
+ [
852
+ f'-----BEGIN FILE id="{identifier}" type="{media_type}"-----',
853
+ text,
854
+ f'-----END FILE id="{identifier}"-----',
855
+ ]
856
+ )
857
+ return ChatCompletionContentPartTextParam(text=text, type='text')
858
+
810
859
 
811
860
  @deprecated(
812
861
  '`OpenAIModel` was renamed to `OpenAIChatModel` to clearly distinguish it from `OpenAIResponsesModel` which '
@@ -1467,6 +1516,7 @@ class OpenAIStreamedResponse(StreamedResponse):
1467
1516
 
1468
1517
  async def _get_event_iterator(self) -> AsyncIterator[ModelResponseStreamEvent]:
1469
1518
  async for chunk in self._response:
1519
+ print(chunk)
1470
1520
  self._usage += _map_usage(chunk)
1471
1521
 
1472
1522
  if chunk.id: # pragma: no branch
pydantic_ai/output.py CHANGED
@@ -9,7 +9,8 @@ from pydantic.json_schema import JsonSchemaValue
9
9
  from pydantic_core import core_schema
10
10
  from typing_extensions import TypeAliasType, TypeVar, deprecated
11
11
 
12
- from . import _utils
12
+ from . import _utils, exceptions
13
+ from ._json_schema import InlineDefsJsonSchemaTransformer
13
14
  from .messages import ToolCallPart
14
15
  from .tools import DeferredToolRequests, ObjectJsonSchema, RunContext, ToolDefinition
15
16
 
@@ -311,6 +312,15 @@ def StructuredDict(
311
312
  """
312
313
  json_schema = _utils.check_object_json_schema(json_schema)
313
314
 
315
+ # Pydantic `TypeAdapter` fails when `object.__get_pydantic_json_schema__` has `$defs`, so we inline them
316
+ # See https://github.com/pydantic/pydantic/issues/12145
317
+ if '$defs' in json_schema:
318
+ json_schema = InlineDefsJsonSchemaTransformer(json_schema).walk()
319
+ if '$defs' in json_schema:
320
+ raise exceptions.UserError(
321
+ '`StructuredDict` does not currently support recursive `$ref`s and `$defs`. See https://github.com/pydantic/pydantic/issues/12145 for more information.'
322
+ )
323
+
314
324
  if name:
315
325
  json_schema['title'] = name
316
326
 
@@ -6,8 +6,8 @@ from textwrap import dedent
6
6
 
7
7
  from typing_extensions import Self
8
8
 
9
+ from .._json_schema import InlineDefsJsonSchemaTransformer, JsonSchemaTransformer
9
10
  from ..output import StructuredOutputMode
10
- from ._json_schema import InlineDefsJsonSchemaTransformer, JsonSchemaTransformer
11
11
 
12
12
  __all__ = [
13
13
  'ModelProfile',
@@ -4,8 +4,8 @@ import warnings
4
4
 
5
5
  from pydantic_ai.exceptions import UserError
6
6
 
7
+ from .._json_schema import JsonSchema, JsonSchemaTransformer
7
8
  from . import ModelProfile
8
- from ._json_schema import JsonSchema, JsonSchemaTransformer
9
9
 
10
10
 
11
11
  def google_model_profile(model_name: str) -> ModelProfile | None:
@@ -6,8 +6,8 @@ from collections.abc import Sequence
6
6
  from dataclasses import dataclass
7
7
  from typing import Any, Literal
8
8
 
9
+ from .._json_schema import JsonSchema, JsonSchemaTransformer
9
10
  from . import ModelProfile
10
- from ._json_schema import JsonSchema, JsonSchemaTransformer
11
11
 
12
12
  OpenAISystemPromptRole = Literal['system', 'developer', 'user']
13
13
 
@@ -8,7 +8,7 @@ from __future__ import annotations as _annotations
8
8
  from abc import ABC, abstractmethod
9
9
  from typing import Any, Generic, TypeVar
10
10
 
11
- from pydantic_ai.profiles import ModelProfile
11
+ from pydantic_ai import ModelProfile
12
12
 
13
13
  InterfaceClient = TypeVar('InterfaceClient')
14
14
 
@@ -5,9 +5,9 @@ from typing import TypeAlias, overload
5
5
 
6
6
  import httpx
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import cached_async_http_client
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.anthropic import anthropic_model_profile
12
12
  from pydantic_ai.providers import Provider
13
13
 
@@ -6,9 +6,9 @@ from typing import overload
6
6
  import httpx
7
7
  from openai import AsyncOpenAI
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
11
  from pydantic_ai.models import cached_async_http_client
11
- from pydantic_ai.profiles import ModelProfile
12
12
  from pydantic_ai.profiles.cohere import cohere_model_profile
13
13
  from pydantic_ai.profiles.deepseek import deepseek_model_profile
14
14
  from pydantic_ai.profiles.grok import grok_model_profile
@@ -6,8 +6,8 @@ from collections.abc import Callable
6
6
  from dataclasses import dataclass
7
7
  from typing import Literal, overload
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.amazon import amazon_model_profile
12
12
  from pydantic_ai.profiles.anthropic import anthropic_model_profile
13
13
  from pydantic_ai.profiles.cohere import cohere_model_profile
@@ -5,9 +5,9 @@ from typing import overload
5
5
 
6
6
  import httpx
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import cached_async_http_client
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.harmony import harmony_model_profile
12
12
  from pydantic_ai.profiles.meta import meta_model_profile
13
13
  from pydantic_ai.profiles.openai import OpenAIJsonSchemaTransformer, OpenAIModelProfile
@@ -4,9 +4,9 @@ import os
4
4
 
5
5
  import httpx
6
6
 
7
+ from pydantic_ai import ModelProfile
7
8
  from pydantic_ai.exceptions import UserError
8
9
  from pydantic_ai.models import cached_async_http_client
9
- from pydantic_ai.profiles import ModelProfile
10
10
  from pydantic_ai.profiles.cohere import cohere_model_profile
11
11
  from pydantic_ai.providers import Provider
12
12
 
@@ -6,9 +6,9 @@ from typing import overload
6
6
  import httpx
7
7
  from openai import AsyncOpenAI
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
11
  from pydantic_ai.models import cached_async_http_client
11
- from pydantic_ai.profiles import ModelProfile
12
12
  from pydantic_ai.profiles.deepseek import deepseek_model_profile
13
13
  from pydantic_ai.profiles.openai import OpenAIJsonSchemaTransformer, OpenAIModelProfile
14
14
  from pydantic_ai.providers import Provider
@@ -6,9 +6,9 @@ from typing import overload
6
6
  import httpx
7
7
  from openai import AsyncOpenAI
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
11
  from pydantic_ai.models import cached_async_http_client
11
- from pydantic_ai.profiles import ModelProfile
12
12
  from pydantic_ai.profiles.deepseek import deepseek_model_profile
13
13
  from pydantic_ai.profiles.google import google_model_profile
14
14
  from pydantic_ai.profiles.meta import meta_model_profile
@@ -5,9 +5,9 @@ from typing import overload
5
5
 
6
6
  import httpx
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import cached_async_http_client
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.cohere import cohere_model_profile
12
12
  from pydantic_ai.profiles.deepseek import deepseek_model_profile
13
13
  from pydantic_ai.profiles.grok import grok_model_profile
@@ -5,9 +5,9 @@ from typing import Literal, overload
5
5
 
6
6
  import httpx
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import get_user_agent
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.google import google_model_profile
12
12
  from pydantic_ai.providers import Provider
13
13
 
@@ -5,9 +5,9 @@ import os
5
5
  import httpx
6
6
  from typing_extensions import deprecated
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import cached_async_http_client
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.google import google_model_profile
12
12
  from pydantic_ai.providers import Provider
13
13
 
@@ -10,9 +10,9 @@ import anyio.to_thread
10
10
  import httpx
11
11
  from typing_extensions import deprecated
12
12
 
13
+ from pydantic_ai import ModelProfile
13
14
  from pydantic_ai.exceptions import UserError
14
15
  from pydantic_ai.models import cached_async_http_client
15
- from pydantic_ai.profiles import ModelProfile
16
16
  from pydantic_ai.profiles.google import google_model_profile
17
17
  from pydantic_ai.providers import Provider
18
18
 
@@ -6,9 +6,9 @@ from typing import Literal, overload
6
6
  import httpx
7
7
  from openai import AsyncOpenAI
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
11
  from pydantic_ai.models import cached_async_http_client
11
- from pydantic_ai.profiles import ModelProfile
12
12
  from pydantic_ai.profiles.grok import grok_model_profile
13
13
  from pydantic_ai.profiles.openai import OpenAIJsonSchemaTransformer, OpenAIModelProfile
14
14
  from pydantic_ai.providers import Provider
@@ -5,9 +5,9 @@ from typing import overload
5
5
 
6
6
  import httpx
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import cached_async_http_client
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.deepseek import deepseek_model_profile
12
12
  from pydantic_ai.profiles.google import google_model_profile
13
13
  from pydantic_ai.profiles.groq import groq_model_profile
@@ -6,9 +6,9 @@ from typing import overload
6
6
  import httpx
7
7
  from openai import AsyncOpenAI
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
11
  from pydantic_ai.models import cached_async_http_client
11
- from pydantic_ai.profiles import ModelProfile
12
12
  from pydantic_ai.profiles.openai import OpenAIJsonSchemaTransformer, OpenAIModelProfile
13
13
  from pydantic_ai.providers import Provider
14
14
 
@@ -5,8 +5,8 @@ from typing import overload
5
5
 
6
6
  from httpx import AsyncClient
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
- from pydantic_ai.profiles import ModelProfile
10
10
  from pydantic_ai.profiles.deepseek import deepseek_model_profile
11
11
  from pydantic_ai.profiles.google import google_model_profile
12
12
  from pydantic_ai.profiles.meta import meta_model_profile
@@ -5,8 +5,8 @@ from typing import overload
5
5
  from httpx import AsyncClient as AsyncHTTPClient
6
6
  from openai import AsyncOpenAI
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.models import cached_async_http_client
9
- from pydantic_ai.profiles import ModelProfile
10
10
  from pydantic_ai.profiles.amazon import amazon_model_profile
11
11
  from pydantic_ai.profiles.anthropic import anthropic_model_profile
12
12
  from pydantic_ai.profiles.cohere import cohere_model_profile
@@ -5,9 +5,9 @@ from typing import overload
5
5
 
6
6
  import httpx
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import cached_async_http_client
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.mistral import mistral_model_profile
12
12
  from pydantic_ai.providers import Provider
13
13
 
@@ -6,9 +6,9 @@ from typing import Literal, overload
6
6
  import httpx
7
7
  from openai import AsyncOpenAI
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
11
  from pydantic_ai.models import cached_async_http_client
11
- from pydantic_ai.profiles import ModelProfile
12
12
  from pydantic_ai.profiles.moonshotai import moonshotai_model_profile
13
13
  from pydantic_ai.profiles.openai import (
14
14
  OpenAIJsonSchemaTransformer,
@@ -5,9 +5,9 @@ import os
5
5
  import httpx
6
6
  from openai import AsyncOpenAI
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import cached_async_http_client
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.cohere import cohere_model_profile
12
12
  from pydantic_ai.profiles.deepseek import deepseek_model_profile
13
13
  from pydantic_ai.profiles.google import google_model_profile
@@ -5,8 +5,8 @@ from typing import overload
5
5
 
6
6
  import httpx
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.models import cached_async_http_client
9
- from pydantic_ai.profiles import ModelProfile
10
10
  from pydantic_ai.profiles.openai import openai_model_profile
11
11
  from pydantic_ai.providers import Provider
12
12
 
@@ -6,9 +6,9 @@ from typing import overload
6
6
  import httpx
7
7
  from openai import AsyncOpenAI
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
11
  from pydantic_ai.models import cached_async_http_client
11
- from pydantic_ai.profiles import ModelProfile
12
12
  from pydantic_ai.profiles.amazon import amazon_model_profile
13
13
  from pydantic_ai.profiles.anthropic import anthropic_model_profile
14
14
  from pydantic_ai.profiles.cohere import cohere_model_profile
@@ -6,9 +6,9 @@ from typing import overload
6
6
  import httpx
7
7
  from openai import AsyncOpenAI
8
8
 
9
+ from pydantic_ai import ModelProfile
9
10
  from pydantic_ai.exceptions import UserError
10
11
  from pydantic_ai.models import cached_async_http_client
11
- from pydantic_ai.profiles import ModelProfile
12
12
  from pydantic_ai.profiles.deepseek import deepseek_model_profile
13
13
  from pydantic_ai.profiles.google import google_model_profile
14
14
  from pydantic_ai.profiles.meta import meta_model_profile
@@ -5,9 +5,9 @@ from typing import overload
5
5
 
6
6
  import httpx
7
7
 
8
+ from pydantic_ai import ModelProfile
8
9
  from pydantic_ai.exceptions import UserError
9
10
  from pydantic_ai.models import cached_async_http_client
10
- from pydantic_ai.profiles import ModelProfile
11
11
  from pydantic_ai.profiles.amazon import amazon_model_profile
12
12
  from pydantic_ai.profiles.anthropic import anthropic_model_profile
13
13
  from pydantic_ai.profiles.cohere import cohere_model_profile
@@ -148,8 +148,7 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
148
148
 
149
149
  Example:
150
150
  ```python
151
- from pydantic_ai import Agent, RunContext
152
- from pydantic_ai.toolsets.function import FunctionToolset
151
+ from pydantic_ai import Agent, FunctionToolset, RunContext
153
152
 
154
153
  toolset = FunctionToolset()
155
154