mirascope 2.0.2__py3-none-any.whl → 2.1.0__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.
- mirascope/_stubs.py +39 -18
- mirascope/api/_generated/__init__.py +4 -0
- mirascope/api/_generated/project_memberships/__init__.py +4 -0
- mirascope/api/_generated/project_memberships/client.py +91 -0
- mirascope/api/_generated/project_memberships/raw_client.py +239 -0
- mirascope/api/_generated/project_memberships/types/__init__.py +4 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_get_response.py +33 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_get_response_role.py +7 -0
- mirascope/api/_generated/reference.md +72 -0
- mirascope/llm/__init__.py +19 -0
- mirascope/llm/calls/decorator.py +17 -24
- mirascope/llm/formatting/__init__.py +2 -2
- mirascope/llm/formatting/format.py +2 -4
- mirascope/llm/formatting/types.py +19 -2
- mirascope/llm/models/models.py +66 -146
- mirascope/llm/prompts/decorator.py +5 -16
- mirascope/llm/prompts/prompts.py +5 -13
- mirascope/llm/providers/anthropic/_utils/beta_decode.py +22 -7
- mirascope/llm/providers/anthropic/_utils/beta_encode.py +22 -16
- mirascope/llm/providers/anthropic/_utils/decode.py +45 -7
- mirascope/llm/providers/anthropic/_utils/encode.py +28 -15
- mirascope/llm/providers/anthropic/beta_provider.py +33 -69
- mirascope/llm/providers/anthropic/provider.py +52 -91
- mirascope/llm/providers/base/_utils.py +4 -9
- mirascope/llm/providers/base/base_provider.py +89 -205
- mirascope/llm/providers/google/_utils/decode.py +51 -1
- mirascope/llm/providers/google/_utils/encode.py +38 -21
- mirascope/llm/providers/google/provider.py +33 -69
- mirascope/llm/providers/mirascope/provider.py +25 -61
- mirascope/llm/providers/mlx/encoding/base.py +3 -6
- mirascope/llm/providers/mlx/encoding/transformers.py +4 -8
- mirascope/llm/providers/mlx/mlx.py +9 -21
- mirascope/llm/providers/mlx/provider.py +33 -69
- mirascope/llm/providers/openai/completions/_utils/encode.py +39 -20
- mirascope/llm/providers/openai/completions/base_provider.py +34 -75
- mirascope/llm/providers/openai/provider.py +25 -61
- mirascope/llm/providers/openai/responses/_utils/decode.py +31 -2
- mirascope/llm/providers/openai/responses/_utils/encode.py +32 -17
- mirascope/llm/providers/openai/responses/provider.py +34 -75
- mirascope/llm/responses/__init__.py +2 -1
- mirascope/llm/responses/base_stream_response.py +4 -0
- mirascope/llm/responses/response.py +8 -12
- mirascope/llm/responses/stream_response.py +8 -12
- mirascope/llm/responses/usage.py +44 -0
- mirascope/llm/tools/__init__.py +24 -0
- mirascope/llm/tools/provider_tools.py +18 -0
- mirascope/llm/tools/tool_schema.py +4 -2
- mirascope/llm/tools/toolkit.py +24 -6
- mirascope/llm/tools/types.py +112 -0
- mirascope/llm/tools/web_search_tool.py +32 -0
- mirascope/ops/__init__.py +19 -1
- mirascope/ops/_internal/instrumentation/__init__.py +20 -0
- mirascope/ops/_internal/instrumentation/llm/common.py +19 -49
- mirascope/ops/_internal/instrumentation/llm/model.py +61 -82
- mirascope/ops/_internal/instrumentation/llm/serialize.py +36 -12
- mirascope/ops/_internal/instrumentation/providers/__init__.py +29 -0
- mirascope/ops/_internal/instrumentation/providers/anthropic.py +78 -0
- mirascope/ops/_internal/instrumentation/providers/base.py +179 -0
- mirascope/ops/_internal/instrumentation/providers/google_genai.py +85 -0
- mirascope/ops/_internal/instrumentation/providers/openai.py +82 -0
- {mirascope-2.0.2.dist-info → mirascope-2.1.0.dist-info}/METADATA +96 -68
- {mirascope-2.0.2.dist-info → mirascope-2.1.0.dist-info}/RECORD +64 -54
- {mirascope-2.0.2.dist-info → mirascope-2.1.0.dist-info}/WHEEL +0 -0
- {mirascope-2.0.2.dist-info → mirascope-2.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -27,6 +27,7 @@ from .....responses import (
|
|
|
27
27
|
ChunkIterator,
|
|
28
28
|
FinishReason,
|
|
29
29
|
FinishReasonChunk,
|
|
30
|
+
ProviderToolUsage,
|
|
30
31
|
RawMessageChunk,
|
|
31
32
|
RawStreamEventChunk,
|
|
32
33
|
Usage,
|
|
@@ -40,8 +41,21 @@ INCOMPLETE_DETAILS_TO_FINISH_REASON = {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
|
|
44
|
+
def _extract_tool_usage(
|
|
45
|
+
output: list[openai_types.ResponseOutputItem],
|
|
46
|
+
) -> list[ProviderToolUsage] | None:
|
|
47
|
+
"""Extract provider tool usage from OpenAI Responses output."""
|
|
48
|
+
web_search_count = sum(1 for item in output if item.type == "web_search_call")
|
|
49
|
+
|
|
50
|
+
if web_search_count == 0:
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
return [ProviderToolUsage(name="web_search", call_count=web_search_count)]
|
|
54
|
+
|
|
55
|
+
|
|
43
56
|
def _decode_usage(
|
|
44
57
|
usage: openai_types.ResponseUsage | None,
|
|
58
|
+
output: list[openai_types.ResponseOutputItem] | None = None,
|
|
45
59
|
) -> Usage | None:
|
|
46
60
|
"""Convert OpenAI ResponseUsage to Mirascope Usage."""
|
|
47
61
|
if usage is None: # pragma: no cover
|
|
@@ -63,6 +77,7 @@ def _decode_usage(
|
|
|
63
77
|
else None
|
|
64
78
|
)
|
|
65
79
|
or 0,
|
|
80
|
+
provider_tool_usage=_extract_tool_usage(output) if output else None,
|
|
66
81
|
raw=usage,
|
|
67
82
|
)
|
|
68
83
|
|
|
@@ -112,7 +127,8 @@ def decode_response(
|
|
|
112
127
|
for reasoning_content in output_item.content:
|
|
113
128
|
if reasoning_content.type == "reasoning_text":
|
|
114
129
|
parts.append(Thought(thought=reasoning_content.text))
|
|
115
|
-
|
|
130
|
+
elif output_item.type == "web_search_call":
|
|
131
|
+
pass # Skip, preserved in raw_message
|
|
116
132
|
else:
|
|
117
133
|
raise NotImplementedError(f"Unsupported output item: {output_item.type}")
|
|
118
134
|
|
|
@@ -134,7 +150,7 @@ def decode_response(
|
|
|
134
150
|
],
|
|
135
151
|
)
|
|
136
152
|
|
|
137
|
-
usage = _decode_usage(response.usage)
|
|
153
|
+
usage = _decode_usage(response.usage, response.output)
|
|
138
154
|
return assistant_message, finish_reason, usage
|
|
139
155
|
|
|
140
156
|
|
|
@@ -145,6 +161,7 @@ class _OpenAIResponsesChunkProcessor:
|
|
|
145
161
|
self.current_content_type: Literal["text", "tool_call", "thought"] | None = None
|
|
146
162
|
self.refusal_encountered = False
|
|
147
163
|
self.include_thoughts = include_thoughts
|
|
164
|
+
self.web_search_count = 0
|
|
148
165
|
|
|
149
166
|
def process_chunk(self, event: ResponseStreamEvent) -> ChunkIterator:
|
|
150
167
|
"""Process a single OpenAI Responses stream event and yield the appropriate content chunks."""
|
|
@@ -178,6 +195,8 @@ class _OpenAIResponsesChunkProcessor:
|
|
|
178
195
|
name=item.name,
|
|
179
196
|
)
|
|
180
197
|
self.current_content_type = "tool_call"
|
|
198
|
+
elif item.type == "web_search_call":
|
|
199
|
+
self.web_search_count += 1
|
|
181
200
|
elif event.type == "response.function_call_arguments.delta":
|
|
182
201
|
yield ToolCallChunk(id=self.current_tool_call_id, delta=event.delta)
|
|
183
202
|
elif event.type == "response.function_call_arguments.done":
|
|
@@ -218,6 +237,15 @@ class _OpenAIResponsesChunkProcessor:
|
|
|
218
237
|
# Emit usage delta if present
|
|
219
238
|
if event.response.usage:
|
|
220
239
|
usage = event.response.usage
|
|
240
|
+
provider_tool_usage = (
|
|
241
|
+
[
|
|
242
|
+
ProviderToolUsage(
|
|
243
|
+
name="web_search", call_count=self.web_search_count
|
|
244
|
+
)
|
|
245
|
+
]
|
|
246
|
+
if self.web_search_count > 0
|
|
247
|
+
else None
|
|
248
|
+
)
|
|
221
249
|
yield UsageDeltaChunk(
|
|
222
250
|
input_tokens=usage.input_tokens,
|
|
223
251
|
output_tokens=usage.output_tokens,
|
|
@@ -234,6 +262,7 @@ class _OpenAIResponsesChunkProcessor:
|
|
|
234
262
|
else None
|
|
235
263
|
)
|
|
236
264
|
or 0,
|
|
265
|
+
provider_tool_usage=provider_tool_usage,
|
|
237
266
|
)
|
|
238
267
|
|
|
239
268
|
|
|
@@ -17,6 +17,8 @@ from openai.types.responses import (
|
|
|
17
17
|
ResponseTextConfigParam,
|
|
18
18
|
ToolChoiceAllowedParam,
|
|
19
19
|
ToolChoiceFunctionParam,
|
|
20
|
+
ToolParam,
|
|
21
|
+
WebSearchToolParam,
|
|
20
22
|
response_create_params,
|
|
21
23
|
)
|
|
22
24
|
from openai.types.responses.easy_input_message_param import EasyInputMessageParam
|
|
@@ -34,12 +36,18 @@ from openai.types.shared_params.responses_model import ResponsesModel
|
|
|
34
36
|
from .....exceptions import FeatureNotSupportedError
|
|
35
37
|
from .....formatting import (
|
|
36
38
|
Format,
|
|
39
|
+
FormatSpec,
|
|
37
40
|
FormattableT,
|
|
38
|
-
OutputParser,
|
|
39
41
|
resolve_format,
|
|
40
42
|
)
|
|
41
43
|
from .....messages import AssistantMessage, Message, UserMessage
|
|
42
|
-
from .....tools import
|
|
44
|
+
from .....tools import (
|
|
45
|
+
FORMAT_TOOL_NAME,
|
|
46
|
+
AnyToolSchema,
|
|
47
|
+
BaseToolkit,
|
|
48
|
+
ProviderTool,
|
|
49
|
+
WebSearchTool,
|
|
50
|
+
)
|
|
43
51
|
from ....base import _utils as _base_utils
|
|
44
52
|
from ...model_id import OpenAIModelId, model_name
|
|
45
53
|
from ...model_info import (
|
|
@@ -72,7 +80,7 @@ class ResponseCreateKwargs(TypedDict, total=False):
|
|
|
72
80
|
temperature: float
|
|
73
81
|
max_output_tokens: int
|
|
74
82
|
top_p: float
|
|
75
|
-
tools: list[
|
|
83
|
+
tools: list[ToolParam] | Omit
|
|
76
84
|
tool_choice: response_create_params.ToolChoice | Omit
|
|
77
85
|
text: ResponseTextConfigParam
|
|
78
86
|
reasoning: Reasoning | Omit
|
|
@@ -212,8 +220,16 @@ def _encode_message(
|
|
|
212
220
|
return _encode_user_message(message)
|
|
213
221
|
|
|
214
222
|
|
|
215
|
-
def
|
|
216
|
-
|
|
223
|
+
def _convert_tool_to_tool_param(
|
|
224
|
+
tool: AnyToolSchema | ProviderTool,
|
|
225
|
+
) -> ToolParam:
|
|
226
|
+
"""Convert a Mirascope ToolSchema to OpenAI Responses ToolParam."""
|
|
227
|
+
if isinstance(tool, WebSearchTool):
|
|
228
|
+
return WebSearchToolParam(type="web_search")
|
|
229
|
+
if isinstance(tool, ProviderTool):
|
|
230
|
+
raise FeatureNotSupportedError(
|
|
231
|
+
f"Provider tool {tool.name}", provider_id="openai:responses"
|
|
232
|
+
)
|
|
217
233
|
schema_dict = tool.parameters.model_dump(by_alias=True, exclude_none=True)
|
|
218
234
|
schema_dict["type"] = "object"
|
|
219
235
|
_base_utils.ensure_additional_properties_false(schema_dict)
|
|
@@ -281,11 +297,8 @@ def encode_request(
|
|
|
281
297
|
*,
|
|
282
298
|
model_id: OpenAIModelId,
|
|
283
299
|
messages: Sequence[Message],
|
|
284
|
-
tools:
|
|
285
|
-
format:
|
|
286
|
-
| Format[FormattableT]
|
|
287
|
-
| OutputParser[FormattableT]
|
|
288
|
-
| None,
|
|
300
|
+
tools: BaseToolkit[AnyToolSchema],
|
|
301
|
+
format: FormatSpec[FormattableT] | None,
|
|
289
302
|
params: Params,
|
|
290
303
|
) -> tuple[Sequence[Message], Format[FormattableT] | None, ResponseCreateKwargs]:
|
|
291
304
|
"""Prepares a request for the `OpenAI.responses.create` method."""
|
|
@@ -334,8 +347,7 @@ def encode_request(
|
|
|
334
347
|
if thinking_config.get("encode_thoughts_as_text"):
|
|
335
348
|
encode_thoughts = True
|
|
336
349
|
|
|
337
|
-
|
|
338
|
-
openai_tools = [_convert_tool_to_function_tool_param(tool) for tool in tools]
|
|
350
|
+
openai_tools = [_convert_tool_to_tool_param(tool) for tool in tools.tools]
|
|
339
351
|
|
|
340
352
|
model_supports_strict = model_id not in MODELS_WITHOUT_JSON_SCHEMA_SUPPORT
|
|
341
353
|
default_mode = "strict" if model_supports_strict else "tool"
|
|
@@ -346,16 +358,19 @@ def encode_request(
|
|
|
346
358
|
kwargs["text"] = {"format": _create_strict_response_format(format)}
|
|
347
359
|
elif format.mode == "tool":
|
|
348
360
|
format_tool_schema = format.create_tool_schema()
|
|
349
|
-
openai_tools.append(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
361
|
+
openai_tools.append(_convert_tool_to_tool_param(format_tool_schema))
|
|
362
|
+
if tools.tools:
|
|
363
|
+
# Only include function tools in tool_choice (filter out web search, etc.)
|
|
364
|
+
function_tools = cast(
|
|
365
|
+
list[FunctionToolParam],
|
|
366
|
+
[t for t in openai_tools if t.get("type") == "function"],
|
|
367
|
+
)
|
|
353
368
|
kwargs["tool_choice"] = ToolChoiceAllowedParam(
|
|
354
369
|
type="allowed_tools",
|
|
355
370
|
mode="required",
|
|
356
371
|
tools=[
|
|
357
372
|
{"type": "function", "name": tool["name"]}
|
|
358
|
-
for tool in
|
|
373
|
+
for tool in function_tools
|
|
359
374
|
],
|
|
360
375
|
)
|
|
361
376
|
else:
|
|
@@ -10,7 +10,7 @@ from openai import AsyncOpenAI, BadRequestError as OpenAIBadRequestError, OpenAI
|
|
|
10
10
|
|
|
11
11
|
from ....context import Context, DepsT
|
|
12
12
|
from ....exceptions import BadRequestError, NotFoundError
|
|
13
|
-
from ....formatting import
|
|
13
|
+
from ....formatting import FormatSpec, FormattableT
|
|
14
14
|
from ....messages import Message
|
|
15
15
|
from ....responses import (
|
|
16
16
|
AsyncContextResponse,
|
|
@@ -22,16 +22,7 @@ from ....responses import (
|
|
|
22
22
|
Response,
|
|
23
23
|
StreamResponse,
|
|
24
24
|
)
|
|
25
|
-
from ....tools import
|
|
26
|
-
AsyncContextTool,
|
|
27
|
-
AsyncContextToolkit,
|
|
28
|
-
AsyncTool,
|
|
29
|
-
AsyncToolkit,
|
|
30
|
-
ContextTool,
|
|
31
|
-
ContextToolkit,
|
|
32
|
-
Tool,
|
|
33
|
-
Toolkit,
|
|
34
|
-
)
|
|
25
|
+
from ....tools import AsyncContextToolkit, AsyncToolkit, ContextToolkit, Toolkit
|
|
35
26
|
from ...base import BaseProvider
|
|
36
27
|
from .. import _utils as _shared_utils
|
|
37
28
|
from ..model_id import OpenAIModelId, model_name
|
|
@@ -72,11 +63,8 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
72
63
|
*,
|
|
73
64
|
model_id: OpenAIModelId,
|
|
74
65
|
messages: Sequence[Message],
|
|
75
|
-
|
|
76
|
-
format:
|
|
77
|
-
| Format[FormattableT]
|
|
78
|
-
| OutputParser[FormattableT]
|
|
79
|
-
| None = None,
|
|
66
|
+
toolkit: Toolkit,
|
|
67
|
+
format: FormatSpec[FormattableT] | None = None,
|
|
80
68
|
**params: Unpack[Params],
|
|
81
69
|
) -> Response | Response[FormattableT]:
|
|
82
70
|
"""Generate an `llm.Response` by synchronously calling the OpenAI Responses API.
|
|
@@ -94,7 +82,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
94
82
|
messages, format, kwargs = _utils.encode_request(
|
|
95
83
|
model_id=model_id,
|
|
96
84
|
messages=messages,
|
|
97
|
-
tools=
|
|
85
|
+
tools=toolkit,
|
|
98
86
|
format=format,
|
|
99
87
|
params=params,
|
|
100
88
|
)
|
|
@@ -112,7 +100,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
112
100
|
model_id=model_id,
|
|
113
101
|
provider_model_name=provider_model_name,
|
|
114
102
|
params=params,
|
|
115
|
-
tools=
|
|
103
|
+
tools=toolkit,
|
|
116
104
|
input_messages=messages,
|
|
117
105
|
assistant_message=assistant_message,
|
|
118
106
|
finish_reason=finish_reason,
|
|
@@ -125,11 +113,8 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
125
113
|
*,
|
|
126
114
|
model_id: OpenAIModelId,
|
|
127
115
|
messages: Sequence[Message],
|
|
128
|
-
|
|
129
|
-
format:
|
|
130
|
-
| Format[FormattableT]
|
|
131
|
-
| OutputParser[FormattableT]
|
|
132
|
-
| None = None,
|
|
116
|
+
toolkit: AsyncToolkit,
|
|
117
|
+
format: FormatSpec[FormattableT] | None = None,
|
|
133
118
|
**params: Unpack[Params],
|
|
134
119
|
) -> AsyncResponse | AsyncResponse[FormattableT]:
|
|
135
120
|
"""Generate an `llm.AsyncResponse` by asynchronously calling the OpenAI Responses API.
|
|
@@ -147,7 +132,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
147
132
|
messages, format, kwargs = _utils.encode_request(
|
|
148
133
|
model_id=model_id,
|
|
149
134
|
messages=messages,
|
|
150
|
-
tools=
|
|
135
|
+
tools=toolkit,
|
|
151
136
|
format=format,
|
|
152
137
|
params=params,
|
|
153
138
|
)
|
|
@@ -165,7 +150,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
165
150
|
model_id=model_id,
|
|
166
151
|
provider_model_name=provider_model_name,
|
|
167
152
|
params=params,
|
|
168
|
-
tools=
|
|
153
|
+
tools=toolkit,
|
|
169
154
|
input_messages=messages,
|
|
170
155
|
assistant_message=assistant_message,
|
|
171
156
|
finish_reason=finish_reason,
|
|
@@ -178,11 +163,8 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
178
163
|
*,
|
|
179
164
|
model_id: OpenAIModelId,
|
|
180
165
|
messages: Sequence[Message],
|
|
181
|
-
|
|
182
|
-
format:
|
|
183
|
-
| Format[FormattableT]
|
|
184
|
-
| OutputParser[FormattableT]
|
|
185
|
-
| None = None,
|
|
166
|
+
toolkit: Toolkit,
|
|
167
|
+
format: FormatSpec[FormattableT] | None = None,
|
|
186
168
|
**params: Unpack[Params],
|
|
187
169
|
) -> StreamResponse | StreamResponse[FormattableT]:
|
|
188
170
|
"""Generate a `llm.StreamResponse` by synchronously streaming from the OpenAI Responses API.
|
|
@@ -200,7 +182,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
200
182
|
messages, format, kwargs = _utils.encode_request(
|
|
201
183
|
model_id=model_id,
|
|
202
184
|
messages=messages,
|
|
203
|
-
tools=
|
|
185
|
+
tools=toolkit,
|
|
204
186
|
format=format,
|
|
205
187
|
params=params,
|
|
206
188
|
)
|
|
@@ -220,7 +202,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
220
202
|
model_id=model_id,
|
|
221
203
|
provider_model_name=provider_model_name,
|
|
222
204
|
params=params,
|
|
223
|
-
tools=
|
|
205
|
+
tools=toolkit,
|
|
224
206
|
input_messages=messages,
|
|
225
207
|
chunk_iterator=chunk_iterator,
|
|
226
208
|
format=format,
|
|
@@ -231,11 +213,8 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
231
213
|
*,
|
|
232
214
|
model_id: OpenAIModelId,
|
|
233
215
|
messages: Sequence[Message],
|
|
234
|
-
|
|
235
|
-
format:
|
|
236
|
-
| Format[FormattableT]
|
|
237
|
-
| OutputParser[FormattableT]
|
|
238
|
-
| None = None,
|
|
216
|
+
toolkit: AsyncToolkit,
|
|
217
|
+
format: FormatSpec[FormattableT] | None = None,
|
|
239
218
|
**params: Unpack[Params],
|
|
240
219
|
) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]:
|
|
241
220
|
"""Generate a `llm.AsyncStreamResponse` by asynchronously streaming from the OpenAI Responses API.
|
|
@@ -253,7 +232,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
253
232
|
messages, format, kwargs = _utils.encode_request(
|
|
254
233
|
model_id=model_id,
|
|
255
234
|
messages=messages,
|
|
256
|
-
tools=
|
|
235
|
+
tools=toolkit,
|
|
257
236
|
format=format,
|
|
258
237
|
params=params,
|
|
259
238
|
)
|
|
@@ -273,7 +252,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
273
252
|
model_id=model_id,
|
|
274
253
|
provider_model_name=provider_model_name,
|
|
275
254
|
params=params,
|
|
276
|
-
tools=
|
|
255
|
+
tools=toolkit,
|
|
277
256
|
input_messages=messages,
|
|
278
257
|
chunk_iterator=chunk_iterator,
|
|
279
258
|
format=format,
|
|
@@ -285,13 +264,8 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
285
264
|
ctx: Context[DepsT],
|
|
286
265
|
model_id: OpenAIModelId,
|
|
287
266
|
messages: Sequence[Message],
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
| None = None,
|
|
291
|
-
format: type[FormattableT]
|
|
292
|
-
| Format[FormattableT]
|
|
293
|
-
| OutputParser[FormattableT]
|
|
294
|
-
| None = None,
|
|
267
|
+
toolkit: ContextToolkit[DepsT],
|
|
268
|
+
format: FormatSpec[FormattableT] | None = None,
|
|
295
269
|
**params: Unpack[Params],
|
|
296
270
|
) -> ContextResponse[DepsT] | ContextResponse[DepsT, FormattableT]:
|
|
297
271
|
"""Generate a `llm.ContextResponse` by synchronously calling the OpenAI Responses API with context.
|
|
@@ -310,7 +284,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
310
284
|
messages, format, kwargs = _utils.encode_request(
|
|
311
285
|
model_id=model_id,
|
|
312
286
|
messages=messages,
|
|
313
|
-
tools=
|
|
287
|
+
tools=toolkit,
|
|
314
288
|
format=format,
|
|
315
289
|
params=params,
|
|
316
290
|
)
|
|
@@ -328,7 +302,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
328
302
|
model_id=model_id,
|
|
329
303
|
provider_model_name=provider_model_name,
|
|
330
304
|
params=params,
|
|
331
|
-
tools=
|
|
305
|
+
tools=toolkit,
|
|
332
306
|
input_messages=messages,
|
|
333
307
|
assistant_message=assistant_message,
|
|
334
308
|
finish_reason=finish_reason,
|
|
@@ -342,13 +316,8 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
342
316
|
ctx: Context[DepsT],
|
|
343
317
|
model_id: OpenAIModelId,
|
|
344
318
|
messages: Sequence[Message],
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
| None = None,
|
|
348
|
-
format: type[FormattableT]
|
|
349
|
-
| Format[FormattableT]
|
|
350
|
-
| OutputParser[FormattableT]
|
|
351
|
-
| None = None,
|
|
319
|
+
toolkit: AsyncContextToolkit[DepsT],
|
|
320
|
+
format: FormatSpec[FormattableT] | None = None,
|
|
352
321
|
**params: Unpack[Params],
|
|
353
322
|
) -> AsyncContextResponse[DepsT] | AsyncContextResponse[DepsT, FormattableT]:
|
|
354
323
|
"""Generate a `llm.AsyncContextResponse` by asynchronously calling the OpenAI Responses API with context.
|
|
@@ -367,7 +336,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
367
336
|
messages, format, kwargs = _utils.encode_request(
|
|
368
337
|
model_id=model_id,
|
|
369
338
|
messages=messages,
|
|
370
|
-
tools=
|
|
339
|
+
tools=toolkit,
|
|
371
340
|
format=format,
|
|
372
341
|
params=params,
|
|
373
342
|
)
|
|
@@ -385,7 +354,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
385
354
|
model_id=model_id,
|
|
386
355
|
provider_model_name=provider_model_name,
|
|
387
356
|
params=params,
|
|
388
|
-
tools=
|
|
357
|
+
tools=toolkit,
|
|
389
358
|
input_messages=messages,
|
|
390
359
|
assistant_message=assistant_message,
|
|
391
360
|
finish_reason=finish_reason,
|
|
@@ -399,13 +368,8 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
399
368
|
ctx: Context[DepsT],
|
|
400
369
|
model_id: OpenAIModelId,
|
|
401
370
|
messages: Sequence[Message],
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
| None = None,
|
|
405
|
-
format: type[FormattableT]
|
|
406
|
-
| Format[FormattableT]
|
|
407
|
-
| OutputParser[FormattableT]
|
|
408
|
-
| None = None,
|
|
371
|
+
toolkit: ContextToolkit[DepsT],
|
|
372
|
+
format: FormatSpec[FormattableT] | None = None,
|
|
409
373
|
**params: Unpack[Params],
|
|
410
374
|
) -> ContextStreamResponse[DepsT] | ContextStreamResponse[DepsT, FormattableT]:
|
|
411
375
|
"""Generate a `llm.ContextStreamResponse` by synchronously streaming from the OpenAI Responses API with context.
|
|
@@ -424,7 +388,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
424
388
|
messages, format, kwargs = _utils.encode_request(
|
|
425
389
|
model_id=model_id,
|
|
426
390
|
messages=messages,
|
|
427
|
-
tools=
|
|
391
|
+
tools=toolkit,
|
|
428
392
|
format=format,
|
|
429
393
|
params=params,
|
|
430
394
|
)
|
|
@@ -445,7 +409,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
445
409
|
model_id=model_id,
|
|
446
410
|
provider_model_name=provider_model_name,
|
|
447
411
|
params=params,
|
|
448
|
-
tools=
|
|
412
|
+
tools=toolkit,
|
|
449
413
|
input_messages=messages,
|
|
450
414
|
chunk_iterator=chunk_iterator,
|
|
451
415
|
format=format,
|
|
@@ -457,13 +421,8 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
457
421
|
ctx: Context[DepsT],
|
|
458
422
|
model_id: OpenAIModelId,
|
|
459
423
|
messages: Sequence[Message],
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
| None = None,
|
|
463
|
-
format: type[FormattableT]
|
|
464
|
-
| Format[FormattableT]
|
|
465
|
-
| OutputParser[FormattableT]
|
|
466
|
-
| None = None,
|
|
424
|
+
toolkit: AsyncContextToolkit[DepsT],
|
|
425
|
+
format: FormatSpec[FormattableT] | None = None,
|
|
467
426
|
**params: Unpack[Params],
|
|
468
427
|
) -> (
|
|
469
428
|
AsyncContextStreamResponse[DepsT]
|
|
@@ -485,7 +444,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
485
444
|
messages, format, kwargs = _utils.encode_request(
|
|
486
445
|
model_id=model_id,
|
|
487
446
|
messages=messages,
|
|
488
|
-
tools=
|
|
447
|
+
tools=toolkit,
|
|
489
448
|
format=format,
|
|
490
449
|
params=params,
|
|
491
450
|
)
|
|
@@ -506,7 +465,7 @@ class OpenAIResponsesProvider(BaseProvider[OpenAI]):
|
|
|
506
465
|
model_id=model_id,
|
|
507
466
|
provider_model_name=provider_model_name,
|
|
508
467
|
params=params,
|
|
509
|
-
tools=
|
|
468
|
+
tools=toolkit,
|
|
510
469
|
input_messages=messages,
|
|
511
470
|
chunk_iterator=chunk_iterator,
|
|
512
471
|
format=format,
|
|
@@ -29,7 +29,7 @@ from .streams import (
|
|
|
29
29
|
ThoughtStream,
|
|
30
30
|
ToolCallStream,
|
|
31
31
|
)
|
|
32
|
-
from .usage import Usage, UsageDeltaChunk
|
|
32
|
+
from .usage import ProviderToolUsage, Usage, UsageDeltaChunk
|
|
33
33
|
|
|
34
34
|
__all__ = [
|
|
35
35
|
"AnyResponse",
|
|
@@ -47,6 +47,7 @@ __all__ = [
|
|
|
47
47
|
"ContextStreamResponse",
|
|
48
48
|
"FinishReason",
|
|
49
49
|
"FinishReasonChunk",
|
|
50
|
+
"ProviderToolUsage",
|
|
50
51
|
"RawMessageChunk",
|
|
51
52
|
"RawStreamEventChunk",
|
|
52
53
|
"Response",
|
|
@@ -504,6 +504,8 @@ class BaseSyncStreamResponse(BaseStreamResponse[ChunkIterator, ToolkitT, Formatt
|
|
|
504
504
|
self.usage.cache_read_tokens += chunk.cache_read_tokens
|
|
505
505
|
self.usage.cache_write_tokens += chunk.cache_write_tokens
|
|
506
506
|
self.usage.reasoning_tokens += chunk.reasoning_tokens
|
|
507
|
+
if chunk.provider_tool_usage:
|
|
508
|
+
self.usage.provider_tool_usage = chunk.provider_tool_usage
|
|
507
509
|
else:
|
|
508
510
|
yield self._handle_chunk(chunk)
|
|
509
511
|
|
|
@@ -725,6 +727,8 @@ class BaseAsyncStreamResponse(
|
|
|
725
727
|
self.usage.cache_read_tokens += chunk.cache_read_tokens
|
|
726
728
|
self.usage.cache_write_tokens += chunk.cache_write_tokens
|
|
727
729
|
self.usage.reasoning_tokens += chunk.reasoning_tokens
|
|
730
|
+
if chunk.provider_tool_usage:
|
|
731
|
+
self.usage.provider_tool_usage = chunk.provider_tool_usage
|
|
728
732
|
else:
|
|
729
733
|
yield self._handle_chunk(chunk)
|
|
730
734
|
|
|
@@ -9,14 +9,14 @@ from ..context import Context, DepsT
|
|
|
9
9
|
from ..formatting import Format, FormattableT
|
|
10
10
|
from ..messages import AssistantMessage, Message, UserContent
|
|
11
11
|
from ..tools import (
|
|
12
|
-
AsyncContextTool,
|
|
13
12
|
AsyncContextToolkit,
|
|
14
|
-
|
|
13
|
+
AsyncContextTools,
|
|
15
14
|
AsyncToolkit,
|
|
16
|
-
|
|
15
|
+
AsyncTools,
|
|
17
16
|
ContextToolkit,
|
|
18
|
-
|
|
17
|
+
ContextTools,
|
|
19
18
|
Toolkit,
|
|
19
|
+
Tools,
|
|
20
20
|
)
|
|
21
21
|
from ..types import Jsonable
|
|
22
22
|
from .base_response import BaseResponse
|
|
@@ -39,7 +39,7 @@ class Response(BaseResponse[Toolkit, FormattableT]):
|
|
|
39
39
|
model_id: "ModelId",
|
|
40
40
|
provider_model_name: str,
|
|
41
41
|
params: "Params",
|
|
42
|
-
tools:
|
|
42
|
+
tools: Tools | None = None,
|
|
43
43
|
format: Format[FormattableT] | None = None,
|
|
44
44
|
input_messages: Sequence[Message],
|
|
45
45
|
assistant_message: AssistantMessage,
|
|
@@ -112,7 +112,7 @@ class AsyncResponse(BaseResponse[AsyncToolkit, FormattableT]):
|
|
|
112
112
|
model_id: "ModelId",
|
|
113
113
|
provider_model_name: str,
|
|
114
114
|
params: "Params",
|
|
115
|
-
tools:
|
|
115
|
+
tools: AsyncTools | None = None,
|
|
116
116
|
format: Format[FormattableT] | None = None,
|
|
117
117
|
input_messages: Sequence[Message],
|
|
118
118
|
assistant_message: AssistantMessage,
|
|
@@ -194,9 +194,7 @@ class ContextResponse(
|
|
|
194
194
|
model_id: "ModelId",
|
|
195
195
|
provider_model_name: str,
|
|
196
196
|
params: "Params",
|
|
197
|
-
tools:
|
|
198
|
-
| ContextToolkit[DepsT]
|
|
199
|
-
| None = None,
|
|
197
|
+
tools: ContextTools[DepsT] | None = None,
|
|
200
198
|
format: Format[FormattableT] | None = None,
|
|
201
199
|
input_messages: Sequence[Message],
|
|
202
200
|
assistant_message: AssistantMessage,
|
|
@@ -284,9 +282,7 @@ class AsyncContextResponse(
|
|
|
284
282
|
model_id: "ModelId",
|
|
285
283
|
provider_model_name: str,
|
|
286
284
|
params: "Params",
|
|
287
|
-
tools:
|
|
288
|
-
| AsyncContextToolkit[DepsT]
|
|
289
|
-
| None = None,
|
|
285
|
+
tools: AsyncContextTools[DepsT] | None = None,
|
|
290
286
|
format: Format[FormattableT] | None = None,
|
|
291
287
|
input_messages: Sequence[Message],
|
|
292
288
|
assistant_message: AssistantMessage,
|
|
@@ -9,14 +9,14 @@ from ..context import Context, DepsT
|
|
|
9
9
|
from ..formatting import Format, FormattableT
|
|
10
10
|
from ..messages import Message, UserContent
|
|
11
11
|
from ..tools import (
|
|
12
|
-
AsyncContextTool,
|
|
13
12
|
AsyncContextToolkit,
|
|
14
|
-
|
|
13
|
+
AsyncContextTools,
|
|
15
14
|
AsyncToolkit,
|
|
16
|
-
|
|
15
|
+
AsyncTools,
|
|
17
16
|
ContextToolkit,
|
|
18
|
-
|
|
17
|
+
ContextTools,
|
|
19
18
|
Toolkit,
|
|
19
|
+
Tools,
|
|
20
20
|
)
|
|
21
21
|
from ..types import Jsonable
|
|
22
22
|
from .base_stream_response import (
|
|
@@ -98,7 +98,7 @@ class StreamResponse(BaseSyncStreamResponse[Toolkit, FormattableT]):
|
|
|
98
98
|
model_id: "ModelId",
|
|
99
99
|
provider_model_name: str,
|
|
100
100
|
params: "Params",
|
|
101
|
-
tools:
|
|
101
|
+
tools: Tools | None = None,
|
|
102
102
|
format: Format[FormattableT] | None = None,
|
|
103
103
|
input_messages: Sequence[Message],
|
|
104
104
|
chunk_iterator: ChunkIterator,
|
|
@@ -224,7 +224,7 @@ class AsyncStreamResponse(BaseAsyncStreamResponse[AsyncToolkit, FormattableT]):
|
|
|
224
224
|
model_id: "ModelId",
|
|
225
225
|
provider_model_name: str,
|
|
226
226
|
params: "Params",
|
|
227
|
-
tools:
|
|
227
|
+
tools: AsyncTools | None = None,
|
|
228
228
|
format: Format[FormattableT] | None = None,
|
|
229
229
|
input_messages: Sequence[Message],
|
|
230
230
|
chunk_iterator: AsyncChunkIterator,
|
|
@@ -359,9 +359,7 @@ class ContextStreamResponse(
|
|
|
359
359
|
model_id: "ModelId",
|
|
360
360
|
provider_model_name: str,
|
|
361
361
|
params: "Params",
|
|
362
|
-
tools:
|
|
363
|
-
| ContextToolkit[DepsT]
|
|
364
|
-
| None = None,
|
|
362
|
+
tools: ContextTools[DepsT] | None = None,
|
|
365
363
|
format: Format[FormattableT] | None = None,
|
|
366
364
|
input_messages: Sequence[Message],
|
|
367
365
|
chunk_iterator: ChunkIterator,
|
|
@@ -502,9 +500,7 @@ class AsyncContextStreamResponse(
|
|
|
502
500
|
model_id: "ModelId",
|
|
503
501
|
provider_model_name: str,
|
|
504
502
|
params: "Params",
|
|
505
|
-
tools:
|
|
506
|
-
| AsyncContextToolkit[DepsT]
|
|
507
|
-
| None = None,
|
|
503
|
+
tools: AsyncContextTools[DepsT] | None = None,
|
|
508
504
|
format: Format[FormattableT] | None = None,
|
|
509
505
|
input_messages: Sequence[Message],
|
|
510
506
|
chunk_iterator: AsyncChunkIterator,
|