mirascope 2.0.0a3__py3-none-any.whl → 2.0.0a5__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.
Files changed (118) hide show
  1. mirascope/api/_generated/__init__.py +78 -6
  2. mirascope/api/_generated/api_keys/__init__.py +7 -0
  3. mirascope/api/_generated/api_keys/client.py +453 -0
  4. mirascope/api/_generated/api_keys/raw_client.py +853 -0
  5. mirascope/api/_generated/api_keys/types/__init__.py +9 -0
  6. mirascope/api/_generated/api_keys/types/api_keys_create_response.py +36 -0
  7. mirascope/api/_generated/api_keys/types/api_keys_get_response.py +35 -0
  8. mirascope/api/_generated/api_keys/types/api_keys_list_response_item.py +35 -0
  9. mirascope/api/_generated/client.py +14 -0
  10. mirascope/api/_generated/environments/__init__.py +17 -0
  11. mirascope/api/_generated/environments/client.py +532 -0
  12. mirascope/api/_generated/environments/raw_client.py +1088 -0
  13. mirascope/api/_generated/environments/types/__init__.py +15 -0
  14. mirascope/api/_generated/environments/types/environments_create_response.py +26 -0
  15. mirascope/api/_generated/environments/types/environments_get_response.py +26 -0
  16. mirascope/api/_generated/environments/types/environments_list_response_item.py +26 -0
  17. mirascope/api/_generated/environments/types/environments_update_response.py +26 -0
  18. mirascope/api/_generated/errors/__init__.py +11 -1
  19. mirascope/api/_generated/errors/conflict_error.py +15 -0
  20. mirascope/api/_generated/errors/forbidden_error.py +15 -0
  21. mirascope/api/_generated/errors/internal_server_error.py +15 -0
  22. mirascope/api/_generated/errors/not_found_error.py +15 -0
  23. mirascope/api/_generated/organizations/__init__.py +25 -0
  24. mirascope/api/_generated/organizations/client.py +404 -0
  25. mirascope/api/_generated/organizations/raw_client.py +902 -0
  26. mirascope/api/_generated/organizations/types/__init__.py +23 -0
  27. mirascope/api/_generated/organizations/types/organizations_create_response.py +25 -0
  28. mirascope/api/_generated/organizations/types/organizations_create_response_role.py +7 -0
  29. mirascope/api/_generated/organizations/types/organizations_get_response.py +25 -0
  30. mirascope/api/_generated/organizations/types/organizations_get_response_role.py +7 -0
  31. mirascope/api/_generated/organizations/types/organizations_list_response_item.py +25 -0
  32. mirascope/api/_generated/organizations/types/organizations_list_response_item_role.py +7 -0
  33. mirascope/api/_generated/organizations/types/organizations_update_response.py +25 -0
  34. mirascope/api/_generated/organizations/types/organizations_update_response_role.py +7 -0
  35. mirascope/api/_generated/projects/__init__.py +17 -0
  36. mirascope/api/_generated/projects/client.py +482 -0
  37. mirascope/api/_generated/projects/raw_client.py +1058 -0
  38. mirascope/api/_generated/projects/types/__init__.py +15 -0
  39. mirascope/api/_generated/projects/types/projects_create_response.py +31 -0
  40. mirascope/api/_generated/projects/types/projects_get_response.py +31 -0
  41. mirascope/api/_generated/projects/types/projects_list_response_item.py +31 -0
  42. mirascope/api/_generated/projects/types/projects_update_response.py +31 -0
  43. mirascope/api/_generated/reference.md +1311 -0
  44. mirascope/api/_generated/types/__init__.py +20 -4
  45. mirascope/api/_generated/types/already_exists_error.py +24 -0
  46. mirascope/api/_generated/types/already_exists_error_tag.py +5 -0
  47. mirascope/api/_generated/types/database_error.py +24 -0
  48. mirascope/api/_generated/types/database_error_tag.py +5 -0
  49. mirascope/api/_generated/types/http_api_decode_error.py +1 -3
  50. mirascope/api/_generated/types/issue.py +1 -5
  51. mirascope/api/_generated/types/not_found_error_body.py +24 -0
  52. mirascope/api/_generated/types/not_found_error_tag.py +5 -0
  53. mirascope/api/_generated/types/permission_denied_error.py +24 -0
  54. mirascope/api/_generated/types/permission_denied_error_tag.py +7 -0
  55. mirascope/api/_generated/types/property_key.py +2 -2
  56. mirascope/api/_generated/types/{property_key_tag.py → property_key_key.py} +3 -5
  57. mirascope/api/_generated/types/{property_key_tag_tag.py → property_key_key_tag.py} +1 -1
  58. mirascope/llm/__init__.py +6 -2
  59. mirascope/llm/exceptions.py +28 -0
  60. mirascope/llm/providers/__init__.py +12 -4
  61. mirascope/llm/providers/anthropic/__init__.py +6 -1
  62. mirascope/llm/providers/anthropic/_utils/__init__.py +17 -5
  63. mirascope/llm/providers/anthropic/_utils/beta_decode.py +271 -0
  64. mirascope/llm/providers/anthropic/_utils/beta_encode.py +216 -0
  65. mirascope/llm/providers/anthropic/_utils/decode.py +39 -7
  66. mirascope/llm/providers/anthropic/_utils/encode.py +156 -64
  67. mirascope/llm/providers/anthropic/_utils/errors.py +46 -0
  68. mirascope/llm/providers/anthropic/beta_provider.py +328 -0
  69. mirascope/llm/providers/anthropic/model_id.py +10 -27
  70. mirascope/llm/providers/anthropic/model_info.py +87 -0
  71. mirascope/llm/providers/anthropic/provider.py +132 -145
  72. mirascope/llm/providers/base/__init__.py +2 -1
  73. mirascope/llm/providers/base/_utils.py +15 -1
  74. mirascope/llm/providers/base/base_provider.py +173 -58
  75. mirascope/llm/providers/google/_utils/__init__.py +2 -0
  76. mirascope/llm/providers/google/_utils/decode.py +55 -3
  77. mirascope/llm/providers/google/_utils/encode.py +14 -6
  78. mirascope/llm/providers/google/_utils/errors.py +49 -0
  79. mirascope/llm/providers/google/model_id.py +7 -13
  80. mirascope/llm/providers/google/model_info.py +62 -0
  81. mirascope/llm/providers/google/provider.py +13 -8
  82. mirascope/llm/providers/mlx/_utils.py +31 -2
  83. mirascope/llm/providers/mlx/encoding/transformers.py +17 -1
  84. mirascope/llm/providers/mlx/provider.py +12 -0
  85. mirascope/llm/providers/ollama/__init__.py +19 -0
  86. mirascope/llm/providers/ollama/provider.py +71 -0
  87. mirascope/llm/providers/openai/__init__.py +10 -1
  88. mirascope/llm/providers/openai/_utils/__init__.py +5 -0
  89. mirascope/llm/providers/openai/_utils/errors.py +46 -0
  90. mirascope/llm/providers/openai/completions/__init__.py +6 -1
  91. mirascope/llm/providers/openai/completions/_utils/decode.py +57 -5
  92. mirascope/llm/providers/openai/completions/_utils/encode.py +9 -8
  93. mirascope/llm/providers/openai/completions/base_provider.py +513 -0
  94. mirascope/llm/providers/openai/completions/provider.py +13 -447
  95. mirascope/llm/providers/openai/model_info.py +57 -0
  96. mirascope/llm/providers/openai/provider.py +30 -5
  97. mirascope/llm/providers/openai/responses/_utils/decode.py +55 -4
  98. mirascope/llm/providers/openai/responses/_utils/encode.py +9 -9
  99. mirascope/llm/providers/openai/responses/provider.py +33 -28
  100. mirascope/llm/providers/provider_id.py +11 -1
  101. mirascope/llm/providers/provider_registry.py +59 -4
  102. mirascope/llm/providers/together/__init__.py +19 -0
  103. mirascope/llm/providers/together/provider.py +40 -0
  104. mirascope/llm/responses/__init__.py +3 -0
  105. mirascope/llm/responses/base_response.py +4 -0
  106. mirascope/llm/responses/base_stream_response.py +25 -1
  107. mirascope/llm/responses/finish_reason.py +1 -0
  108. mirascope/llm/responses/response.py +9 -0
  109. mirascope/llm/responses/root_response.py +5 -1
  110. mirascope/llm/responses/usage.py +95 -0
  111. mirascope/ops/_internal/closure.py +62 -11
  112. {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/METADATA +3 -3
  113. {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/RECORD +115 -56
  114. mirascope/llm/providers/load_provider.py +0 -48
  115. mirascope/llm/providers/openai/shared/__init__.py +0 -7
  116. mirascope/llm/providers/openai/shared/_utils.py +0 -59
  117. {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/WHEEL +0 -0
  118. {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,513 @@
1
+ """Base class for OpenAI Completions-compatible providers."""
2
+
3
+ import os
4
+ from collections.abc import Sequence
5
+ from typing import ClassVar
6
+ from typing_extensions import Unpack
7
+
8
+ from openai import AsyncOpenAI, OpenAI
9
+
10
+ from ....context import Context, DepsT
11
+ from ....formatting import Format, FormattableT
12
+ from ....messages import Message
13
+ from ....responses import (
14
+ AsyncContextResponse,
15
+ AsyncContextStreamResponse,
16
+ AsyncResponse,
17
+ AsyncStreamResponse,
18
+ ContextResponse,
19
+ ContextStreamResponse,
20
+ Response,
21
+ StreamResponse,
22
+ )
23
+ from ....tools import (
24
+ AsyncContextTool,
25
+ AsyncContextToolkit,
26
+ AsyncTool,
27
+ AsyncToolkit,
28
+ ContextTool,
29
+ ContextToolkit,
30
+ Tool,
31
+ Toolkit,
32
+ )
33
+ from ...base import BaseProvider, Params
34
+ from .. import _utils as _shared_utils
35
+ from ..model_id import model_name as openai_model_name
36
+ from . import _utils
37
+
38
+
39
+ class BaseOpenAICompletionsProvider(BaseProvider[OpenAI]):
40
+ """Base class for providers that use OpenAI Completions-compatible APIs."""
41
+
42
+ id: ClassVar[str]
43
+ default_scope: ClassVar[str | list[str]]
44
+ default_base_url: ClassVar[str | None] = None
45
+ api_key_env_var: ClassVar[str]
46
+ api_key_required: ClassVar[bool] = True
47
+ provider_name: ClassVar[str | None] = None
48
+ error_map = _shared_utils.OPENAI_ERROR_MAP
49
+
50
+ def __init__(
51
+ self,
52
+ *,
53
+ api_key: str | None = None,
54
+ base_url: str | None = None,
55
+ ) -> None:
56
+ """Initialize the OpenAI Completions-compatible provider client."""
57
+ resolved_api_key = api_key or os.environ.get(self.api_key_env_var)
58
+
59
+ if self.api_key_required and not resolved_api_key:
60
+ name = self.provider_name or self.id.split(":")[0].capitalize()
61
+ raise ValueError(
62
+ f"{name} API key is required. "
63
+ f"Set the {self.api_key_env_var} environment variable "
64
+ f"or pass the api_key parameter to register_provider()."
65
+ )
66
+
67
+ resolved_base_url = base_url or self.default_base_url
68
+
69
+ effective_api_key: str | None = resolved_api_key
70
+ if resolved_base_url is not None and not effective_api_key:
71
+ effective_api_key = "not-needed"
72
+
73
+ self.client = OpenAI(
74
+ api_key=effective_api_key,
75
+ base_url=resolved_base_url,
76
+ )
77
+ self.async_client = AsyncOpenAI(
78
+ api_key=effective_api_key,
79
+ base_url=resolved_base_url,
80
+ )
81
+
82
+ def get_error_status(self, e: Exception) -> int | None:
83
+ """Extract HTTP status code from OpenAI exception."""
84
+ return getattr(e, "status_code", None)
85
+
86
+ def _model_name(self, model_id: str) -> str:
87
+ """Extract the model name to send to the API."""
88
+ return openai_model_name(model_id, None)
89
+
90
+ def _provider_model_name(self, model_id: str) -> str:
91
+ """Get the model name for tracking in Response."""
92
+ return self._model_name(model_id)
93
+
94
+ def _call(
95
+ self,
96
+ *,
97
+ model_id: str,
98
+ messages: Sequence[Message],
99
+ tools: Sequence[Tool] | Toolkit | None = None,
100
+ format: type[FormattableT] | Format[FormattableT] | None = None,
101
+ **params: Unpack[Params],
102
+ ) -> Response | Response[FormattableT]:
103
+ """Generate an `llm.Response` by synchronously calling the API.
104
+
105
+ Args:
106
+ model_id: Model identifier to use.
107
+ messages: Messages to send to the LLM.
108
+ tools: Optional tools that the model may invoke.
109
+ format: Optional response format specifier.
110
+ **params: Additional parameters to configure output (e.g. temperature). See `llm.Params`.
111
+
112
+ Returns:
113
+ An `llm.Response` object containing the LLM-generated content.
114
+ """
115
+ input_messages, format, kwargs = _utils.encode_request(
116
+ model_id=model_id,
117
+ messages=messages,
118
+ tools=tools,
119
+ format=format,
120
+ params=params,
121
+ )
122
+ kwargs["model"] = self._model_name(model_id)
123
+ openai_response = self.client.chat.completions.create(**kwargs)
124
+
125
+ assistant_message, finish_reason, usage = _utils.decode_response(
126
+ openai_response,
127
+ model_id,
128
+ self.id,
129
+ self._provider_model_name(model_id),
130
+ )
131
+
132
+ return Response(
133
+ raw=openai_response,
134
+ provider_id=self.id,
135
+ model_id=model_id,
136
+ provider_model_name=self._provider_model_name(model_id),
137
+ params=params,
138
+ tools=tools,
139
+ input_messages=input_messages,
140
+ assistant_message=assistant_message,
141
+ finish_reason=finish_reason,
142
+ usage=usage,
143
+ format=format,
144
+ )
145
+
146
+ def _context_call(
147
+ self,
148
+ *,
149
+ ctx: Context[DepsT],
150
+ model_id: str,
151
+ messages: Sequence[Message],
152
+ tools: Sequence[Tool | ContextTool[DepsT]]
153
+ | ContextToolkit[DepsT]
154
+ | None = None,
155
+ format: type[FormattableT] | Format[FormattableT] | None = None,
156
+ **params: Unpack[Params],
157
+ ) -> ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT]:
158
+ """Generate an `llm.ContextResponse` by synchronously calling the API.
159
+
160
+ Args:
161
+ ctx: Context object with dependencies for tools.
162
+ model_id: Model identifier to use.
163
+ messages: Messages to send to the LLM.
164
+ tools: Optional tools that the model may invoke.
165
+ format: Optional response format specifier.
166
+ **params: Additional parameters to configure output (e.g. temperature). See `llm.Params`.
167
+
168
+ Returns:
169
+ An `llm.ContextResponse` object containing the LLM-generated content.
170
+ """
171
+ input_messages, format, kwargs = _utils.encode_request(
172
+ model_id=model_id,
173
+ messages=messages,
174
+ tools=tools,
175
+ format=format,
176
+ params=params,
177
+ )
178
+ kwargs["model"] = self._model_name(model_id)
179
+ openai_response = self.client.chat.completions.create(**kwargs)
180
+
181
+ assistant_message, finish_reason, usage = _utils.decode_response(
182
+ openai_response,
183
+ model_id,
184
+ self.id,
185
+ self._provider_model_name(model_id),
186
+ )
187
+
188
+ return ContextResponse(
189
+ raw=openai_response,
190
+ provider_id=self.id,
191
+ model_id=model_id,
192
+ provider_model_name=self._provider_model_name(model_id),
193
+ params=params,
194
+ tools=tools,
195
+ input_messages=input_messages,
196
+ assistant_message=assistant_message,
197
+ finish_reason=finish_reason,
198
+ usage=usage,
199
+ format=format,
200
+ )
201
+
202
+ async def _call_async(
203
+ self,
204
+ *,
205
+ model_id: str,
206
+ messages: Sequence[Message],
207
+ tools: Sequence[AsyncTool] | AsyncToolkit | None = None,
208
+ format: type[FormattableT] | Format[FormattableT] | None = None,
209
+ **params: Unpack[Params],
210
+ ) -> AsyncResponse | AsyncResponse[FormattableT]:
211
+ """Generate an `llm.AsyncResponse` by asynchronously calling the API.
212
+
213
+ Args:
214
+ model_id: Model identifier to use.
215
+ messages: Messages to send to the LLM.
216
+ tools: Optional tools that the model may invoke.
217
+ format: Optional response format specifier.
218
+ **params: Additional parameters to configure output (e.g. temperature). See `llm.Params`.
219
+
220
+ Returns:
221
+ An `llm.AsyncResponse` object containing the LLM-generated content.
222
+ """
223
+ input_messages, format, kwargs = _utils.encode_request(
224
+ model_id=model_id,
225
+ params=params,
226
+ messages=messages,
227
+ tools=tools,
228
+ format=format,
229
+ )
230
+ kwargs["model"] = self._model_name(model_id)
231
+ openai_response = await self.async_client.chat.completions.create(**kwargs)
232
+
233
+ assistant_message, finish_reason, usage = _utils.decode_response(
234
+ openai_response,
235
+ model_id,
236
+ self.id,
237
+ self._provider_model_name(model_id),
238
+ )
239
+
240
+ return AsyncResponse(
241
+ raw=openai_response,
242
+ provider_id=self.id,
243
+ model_id=model_id,
244
+ provider_model_name=self._provider_model_name(model_id),
245
+ params=params,
246
+ tools=tools,
247
+ input_messages=input_messages,
248
+ assistant_message=assistant_message,
249
+ finish_reason=finish_reason,
250
+ usage=usage,
251
+ format=format,
252
+ )
253
+
254
+ async def _context_call_async(
255
+ self,
256
+ *,
257
+ ctx: Context[DepsT],
258
+ model_id: str,
259
+ messages: Sequence[Message],
260
+ tools: Sequence[AsyncTool | AsyncContextTool[DepsT]]
261
+ | AsyncContextToolkit[DepsT]
262
+ | None = None,
263
+ format: type[FormattableT] | Format[FormattableT] | None = None,
264
+ **params: Unpack[Params],
265
+ ) -> AsyncContextResponse[DepsT, None] | AsyncContextResponse[DepsT, FormattableT]:
266
+ """Generate an `llm.AsyncContextResponse` by asynchronously calling the API.
267
+
268
+ Args:
269
+ ctx: Context object with dependencies for tools.
270
+ model_id: Model identifier to use.
271
+ messages: Messages to send to the LLM.
272
+ tools: Optional tools that the model may invoke.
273
+ format: Optional response format specifier.
274
+ **params: Additional parameters to configure output (e.g. temperature). See `llm.Params`.
275
+
276
+ Returns:
277
+ An `llm.AsyncContextResponse` object containing the LLM-generated content.
278
+ """
279
+ input_messages, format, kwargs = _utils.encode_request(
280
+ model_id=model_id,
281
+ params=params,
282
+ messages=messages,
283
+ tools=tools,
284
+ format=format,
285
+ )
286
+ kwargs["model"] = self._model_name(model_id)
287
+ openai_response = await self.async_client.chat.completions.create(**kwargs)
288
+
289
+ assistant_message, finish_reason, usage = _utils.decode_response(
290
+ openai_response,
291
+ model_id,
292
+ self.id,
293
+ self._provider_model_name(model_id),
294
+ )
295
+
296
+ return AsyncContextResponse(
297
+ raw=openai_response,
298
+ provider_id=self.id,
299
+ model_id=model_id,
300
+ provider_model_name=self._provider_model_name(model_id),
301
+ params=params,
302
+ tools=tools,
303
+ input_messages=input_messages,
304
+ assistant_message=assistant_message,
305
+ finish_reason=finish_reason,
306
+ usage=usage,
307
+ format=format,
308
+ )
309
+
310
+ def _stream(
311
+ self,
312
+ *,
313
+ model_id: str,
314
+ messages: Sequence[Message],
315
+ tools: Sequence[Tool] | Toolkit | None = None,
316
+ format: type[FormattableT] | Format[FormattableT] | None = None,
317
+ **params: Unpack[Params],
318
+ ) -> StreamResponse | StreamResponse[FormattableT]:
319
+ """Generate an `llm.StreamResponse` by synchronously streaming from the API.
320
+
321
+ Args:
322
+ model_id: Model identifier to use.
323
+ messages: Messages to send to the LLM.
324
+ tools: Optional tools that the model may invoke.
325
+ format: Optional response format specifier.
326
+ **params: Additional parameters to configure output (e.g. temperature). See `llm.Params`.
327
+
328
+ Returns:
329
+ An `llm.StreamResponse` object for iterating over the LLM-generated content.
330
+ """
331
+ input_messages, format, kwargs = _utils.encode_request(
332
+ model_id=model_id,
333
+ messages=messages,
334
+ tools=tools,
335
+ format=format,
336
+ params=params,
337
+ )
338
+ kwargs["model"] = self._model_name(model_id)
339
+ openai_stream = self.client.chat.completions.create(
340
+ **kwargs,
341
+ stream=True,
342
+ stream_options={"include_usage": True},
343
+ )
344
+
345
+ chunk_iterator = _utils.decode_stream(openai_stream)
346
+
347
+ return StreamResponse(
348
+ provider_id=self.id,
349
+ model_id=model_id,
350
+ provider_model_name=self._provider_model_name(model_id),
351
+ params=params,
352
+ tools=tools,
353
+ input_messages=input_messages,
354
+ chunk_iterator=chunk_iterator,
355
+ format=format,
356
+ )
357
+
358
+ def _context_stream(
359
+ self,
360
+ *,
361
+ ctx: Context[DepsT],
362
+ model_id: str,
363
+ messages: Sequence[Message],
364
+ tools: Sequence[Tool | ContextTool[DepsT]]
365
+ | ContextToolkit[DepsT]
366
+ | None = None,
367
+ format: type[FormattableT] | Format[FormattableT] | None = None,
368
+ **params: Unpack[Params],
369
+ ) -> ContextStreamResponse[DepsT] | ContextStreamResponse[DepsT, FormattableT]:
370
+ """Generate an `llm.ContextStreamResponse` by synchronously streaming from the API.
371
+
372
+ Args:
373
+ ctx: Context object with dependencies for tools.
374
+ model_id: Model identifier to use.
375
+ messages: Messages to send to the LLM.
376
+ tools: Optional tools that the model may invoke.
377
+ format: Optional response format specifier.
378
+ **params: Additional parameters to configure output (e.g. temperature). See `llm.Params`.
379
+
380
+ Returns:
381
+ An `llm.ContextStreamResponse` object for iterating over the LLM-generated content.
382
+ """
383
+ input_messages, format, kwargs = _utils.encode_request(
384
+ model_id=model_id,
385
+ messages=messages,
386
+ tools=tools,
387
+ format=format,
388
+ params=params,
389
+ )
390
+ kwargs["model"] = self._model_name(model_id)
391
+
392
+ openai_stream = self.client.chat.completions.create(
393
+ **kwargs,
394
+ stream=True,
395
+ stream_options={"include_usage": True},
396
+ )
397
+
398
+ chunk_iterator = _utils.decode_stream(openai_stream)
399
+
400
+ return ContextStreamResponse(
401
+ provider_id=self.id,
402
+ model_id=model_id,
403
+ provider_model_name=self._provider_model_name(model_id),
404
+ params=params,
405
+ tools=tools,
406
+ input_messages=input_messages,
407
+ chunk_iterator=chunk_iterator,
408
+ format=format,
409
+ )
410
+
411
+ async def _stream_async(
412
+ self,
413
+ *,
414
+ model_id: str,
415
+ messages: Sequence[Message],
416
+ tools: Sequence[AsyncTool] | AsyncToolkit | None = None,
417
+ format: type[FormattableT] | Format[FormattableT] | None = None,
418
+ **params: Unpack[Params],
419
+ ) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]:
420
+ """Generate an `llm.AsyncStreamResponse` by asynchronously streaming from the API.
421
+
422
+ Args:
423
+ model_id: Model identifier to use.
424
+ messages: Messages to send to the LLM.
425
+ tools: Optional tools that the model may invoke.
426
+ format: Optional response format specifier.
427
+ **params: Additional parameters to configure output (e.g. temperature). See `llm.Params`.
428
+
429
+ Returns:
430
+ An `llm.AsyncStreamResponse` object for iterating over the LLM-generated content.
431
+ """
432
+ input_messages, format, kwargs = _utils.encode_request(
433
+ model_id=model_id,
434
+ messages=messages,
435
+ tools=tools,
436
+ format=format,
437
+ params=params,
438
+ )
439
+ kwargs["model"] = self._model_name(model_id)
440
+ openai_stream = await self.async_client.chat.completions.create(
441
+ **kwargs,
442
+ stream=True,
443
+ stream_options={"include_usage": True},
444
+ )
445
+
446
+ chunk_iterator = _utils.decode_async_stream(openai_stream)
447
+
448
+ return AsyncStreamResponse(
449
+ provider_id=self.id,
450
+ model_id=model_id,
451
+ provider_model_name=self._provider_model_name(model_id),
452
+ params=params,
453
+ tools=tools,
454
+ input_messages=input_messages,
455
+ chunk_iterator=chunk_iterator,
456
+ format=format,
457
+ )
458
+
459
+ async def _context_stream_async(
460
+ self,
461
+ *,
462
+ ctx: Context[DepsT],
463
+ model_id: str,
464
+ messages: Sequence[Message],
465
+ tools: Sequence[AsyncTool | AsyncContextTool[DepsT]]
466
+ | AsyncContextToolkit[DepsT]
467
+ | None = None,
468
+ format: type[FormattableT] | Format[FormattableT] | None = None,
469
+ **params: Unpack[Params],
470
+ ) -> (
471
+ AsyncContextStreamResponse[DepsT]
472
+ | AsyncContextStreamResponse[DepsT, FormattableT]
473
+ ):
474
+ """Generate an `llm.AsyncContextStreamResponse` by asynchronously streaming from the API.
475
+
476
+ Args:
477
+ ctx: Context object with dependencies for tools.
478
+ model_id: Model identifier to use.
479
+ messages: Messages to send to the LLM.
480
+ tools: Optional tools that the model may invoke.
481
+ format: Optional response format specifier.
482
+ **params: Additional parameters to configure output (e.g. temperature). See `llm.Params`.
483
+
484
+ Returns:
485
+ An `llm.AsyncContextStreamResponse` object for iterating over the LLM-generated content.
486
+ """
487
+ input_messages, format, kwargs = _utils.encode_request(
488
+ model_id=model_id,
489
+ messages=messages,
490
+ tools=tools,
491
+ format=format,
492
+ params=params,
493
+ )
494
+ kwargs["model"] = self._model_name(model_id)
495
+
496
+ openai_stream = await self.async_client.chat.completions.create(
497
+ **kwargs,
498
+ stream=True,
499
+ stream_options={"include_usage": True},
500
+ )
501
+
502
+ chunk_iterator = _utils.decode_async_stream(openai_stream)
503
+
504
+ return AsyncContextStreamResponse(
505
+ provider_id=self.id,
506
+ model_id=model_id,
507
+ provider_model_name=self._provider_model_name(model_id),
508
+ params=params,
509
+ tools=tools,
510
+ input_messages=input_messages,
511
+ chunk_iterator=chunk_iterator,
512
+ format=format,
513
+ )