mirascope 1.18.2__py3-none-any.whl → 1.18.4__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 (89) hide show
  1. mirascope/__init__.py +20 -1
  2. mirascope/beta/openai/__init__.py +1 -1
  3. mirascope/beta/openai/realtime/__init__.py +1 -1
  4. mirascope/beta/openai/realtime/tool.py +1 -1
  5. mirascope/beta/rag/__init__.py +2 -2
  6. mirascope/beta/rag/base/__init__.py +2 -2
  7. mirascope/beta/rag/weaviate/__init__.py +1 -1
  8. mirascope/core/__init__.py +29 -6
  9. mirascope/core/anthropic/__init__.py +3 -3
  10. mirascope/core/anthropic/_utils/_calculate_cost.py +114 -47
  11. mirascope/core/anthropic/call_response.py +9 -3
  12. mirascope/core/anthropic/call_response_chunk.py +7 -0
  13. mirascope/core/anthropic/stream.py +3 -1
  14. mirascope/core/azure/__init__.py +2 -2
  15. mirascope/core/azure/_utils/_calculate_cost.py +4 -1
  16. mirascope/core/azure/call_response.py +9 -3
  17. mirascope/core/azure/call_response_chunk.py +5 -0
  18. mirascope/core/azure/stream.py +3 -1
  19. mirascope/core/base/__init__.py +11 -9
  20. mirascope/core/base/_utils/__init__.py +10 -10
  21. mirascope/core/base/_utils/_get_common_usage.py +8 -4
  22. mirascope/core/base/_utils/_get_create_fn_or_async_create_fn.py +2 -2
  23. mirascope/core/base/_utils/_protocols.py +9 -8
  24. mirascope/core/base/call_response.py +22 -22
  25. mirascope/core/base/call_response_chunk.py +12 -1
  26. mirascope/core/base/stream.py +24 -21
  27. mirascope/core/base/tool.py +7 -5
  28. mirascope/core/base/types.py +22 -5
  29. mirascope/core/bedrock/__init__.py +3 -3
  30. mirascope/core/bedrock/_utils/_calculate_cost.py +4 -1
  31. mirascope/core/bedrock/call_response.py +8 -3
  32. mirascope/core/bedrock/call_response_chunk.py +5 -0
  33. mirascope/core/bedrock/stream.py +3 -1
  34. mirascope/core/cohere/__init__.py +2 -2
  35. mirascope/core/cohere/_utils/_calculate_cost.py +4 -3
  36. mirascope/core/cohere/call_response.py +9 -3
  37. mirascope/core/cohere/call_response_chunk.py +5 -0
  38. mirascope/core/cohere/stream.py +3 -1
  39. mirascope/core/gemini/__init__.py +2 -2
  40. mirascope/core/gemini/_utils/_calculate_cost.py +4 -1
  41. mirascope/core/gemini/_utils/_convert_message_params.py +1 -1
  42. mirascope/core/gemini/call_response.py +9 -3
  43. mirascope/core/gemini/call_response_chunk.py +5 -0
  44. mirascope/core/gemini/stream.py +3 -1
  45. mirascope/core/google/__init__.py +2 -2
  46. mirascope/core/google/_utils/_calculate_cost.py +141 -14
  47. mirascope/core/google/_utils/_convert_message_params.py +120 -115
  48. mirascope/core/google/_utils/_message_param_converter.py +34 -33
  49. mirascope/core/google/_utils/_validate_media_type.py +34 -0
  50. mirascope/core/google/call_response.py +38 -10
  51. mirascope/core/google/call_response_chunk.py +17 -9
  52. mirascope/core/google/stream.py +20 -2
  53. mirascope/core/groq/__init__.py +2 -2
  54. mirascope/core/groq/_utils/_calculate_cost.py +12 -11
  55. mirascope/core/groq/call_response.py +9 -3
  56. mirascope/core/groq/call_response_chunk.py +5 -0
  57. mirascope/core/groq/stream.py +3 -1
  58. mirascope/core/litellm/__init__.py +1 -1
  59. mirascope/core/litellm/_utils/_setup_call.py +7 -3
  60. mirascope/core/mistral/__init__.py +2 -2
  61. mirascope/core/mistral/_utils/_calculate_cost.py +10 -9
  62. mirascope/core/mistral/call_response.py +9 -3
  63. mirascope/core/mistral/call_response_chunk.py +5 -0
  64. mirascope/core/mistral/stream.py +3 -1
  65. mirascope/core/openai/__init__.py +2 -2
  66. mirascope/core/openai/_utils/_calculate_cost.py +78 -37
  67. mirascope/core/openai/call_params.py +13 -0
  68. mirascope/core/openai/call_response.py +14 -3
  69. mirascope/core/openai/call_response_chunk.py +12 -0
  70. mirascope/core/openai/stream.py +6 -4
  71. mirascope/core/vertex/__init__.py +1 -1
  72. mirascope/core/vertex/_utils/_calculate_cost.py +1 -0
  73. mirascope/core/vertex/_utils/_convert_message_params.py +1 -1
  74. mirascope/core/vertex/call_response.py +9 -3
  75. mirascope/core/vertex/call_response_chunk.py +5 -0
  76. mirascope/core/vertex/stream.py +3 -1
  77. mirascope/integrations/_middleware_factory.py +6 -6
  78. mirascope/integrations/logfire/_utils.py +1 -1
  79. mirascope/llm/__init__.py +3 -1
  80. mirascope/llm/_protocols.py +5 -5
  81. mirascope/llm/call_response.py +16 -9
  82. mirascope/llm/llm_call.py +53 -25
  83. mirascope/llm/stream.py +43 -31
  84. mirascope/retries/__init__.py +1 -1
  85. mirascope/tools/__init__.py +2 -2
  86. {mirascope-1.18.2.dist-info → mirascope-1.18.4.dist-info}/METADATA +2 -2
  87. {mirascope-1.18.2.dist-info → mirascope-1.18.4.dist-info}/RECORD +89 -88
  88. {mirascope-1.18.2.dist-info → mirascope-1.18.4.dist-info}/WHEEL +0 -0
  89. {mirascope-1.18.2.dist-info → mirascope-1.18.4.dist-info}/licenses/LICENSE +0 -0
@@ -13,6 +13,7 @@ from mirascope.core.base import (
13
13
  BaseCallResponse,
14
14
  BaseMessageParam,
15
15
  BaseTool,
16
+ Usage,
16
17
  transform_tool_outputs,
17
18
  )
18
19
  from mirascope.core.base.message_param import ToolResultPart
@@ -22,14 +23,11 @@ from mirascope.llm.tool import Tool
22
23
 
23
24
  _ResponseT = TypeVar("_ResponseT")
24
25
 
25
- _ToolMessageParamT = TypeVar("_ToolMessageParamT")
26
- _BaseToolT = TypeVar("_BaseToolT", bound=BaseTool)
27
-
28
26
 
29
27
  class CallResponse(
30
28
  BaseCallResponse[
31
29
  _ResponseT,
32
- _BaseToolT,
30
+ Tool,
33
31
  Any,
34
32
  BaseDynamicConfig[Any, Any, Any],
35
33
  BaseMessageParam,
@@ -44,11 +42,11 @@ class CallResponse(
44
42
  We rely on _response having `common_` methods or properties for normalization.
45
43
  """
46
44
 
47
- _response: BaseCallResponse[_ResponseT, _BaseToolT, Any, Any, Any, Any, Any]
45
+ _response: BaseCallResponse[_ResponseT, Tool, Any, Any, Any, Any, Any]
48
46
 
49
47
  def __init__(
50
48
  self,
51
- response: BaseCallResponse[_ResponseT, _BaseToolT, Any, Any, Any, Any, Any],
49
+ response: BaseCallResponse[_ResponseT, Tool, Any, Any, Any, Any, Any],
52
50
  ) -> None:
53
51
  super().__init__(
54
52
  **{
@@ -65,7 +63,13 @@ class CallResponse(
65
63
  def __getattribute__(self, name: str) -> Any: # noqa: ANN401
66
64
  special_names = {
67
65
  "_response",
66
+ "finish_reasons",
67
+ "usage",
68
+ "message_param",
68
69
  "user_message_param",
70
+ "tools",
71
+ "tool",
72
+ "tool_message_params",
69
73
  "__dict__",
70
74
  "__class__",
71
75
  "model_fields",
@@ -97,17 +101,20 @@ class CallResponse(
97
101
  def finish_reasons(self) -> list[FinishReason] | None: # pyright: ignore [reportIncompatibleMethodOverride]
98
102
  return self._response.common_finish_reasons
99
103
 
104
+ @property
105
+ def usage(self) -> Usage | None:
106
+ """Returns the usage of the chat completion."""
107
+ return self._response.common_usage
108
+
100
109
  @computed_field
101
110
  @cached_property
102
111
  def message_param(self) -> BaseMessageParam:
103
112
  return self._response.common_message_param # pyright: ignore [reportReturnType]
104
113
 
105
- @computed_field
106
114
  @cached_property
107
115
  def tools(self) -> list[Tool] | None: # pyright: ignore [reportIncompatibleVariableOverride]
108
116
  return self._response.common_tools
109
117
 
110
- @computed_field
111
118
  @cached_property
112
119
  def tool(self) -> Tool | None: # pyright: ignore [reportIncompatibleVariableOverride]
113
120
  tools = self._response.common_tools
@@ -118,7 +125,7 @@ class CallResponse(
118
125
  @classmethod
119
126
  @transform_tool_outputs
120
127
  def tool_message_params(
121
- cls, tools_and_outputs: list[tuple[BaseTool, str]]
128
+ cls, tools_and_outputs: list[tuple[Tool, str]]
122
129
  ) -> list[BaseMessageParam]:
123
130
  """Returns the tool message parameters for tool call results.
124
131
 
mirascope/llm/llm_call.py CHANGED
@@ -191,31 +191,59 @@ def _call(
191
191
  }
192
192
  decorated = provider_call(**_original_args)(fn)
193
193
 
194
- @wraps(decorated)
195
- def inner(
196
- *args: _P.args, **kwargs: _P.kwargs
197
- ) -> CallResponse | Stream | Awaitable[CallResponse | Stream]:
198
- result = decorated(*args, **kwargs)
199
- if fn_is_async(decorated):
200
-
201
- async def async_wrapper() -> CallResponse | Stream:
202
- final = await result
203
- return _wrap_result(final)
204
-
205
- return async_wrapper()
206
- else:
207
-
208
- def sync_wrapper() -> CallResponse | Stream:
209
- final = result
210
- return _wrap_result(final)
211
-
212
- return sync_wrapper()
213
-
214
- inner._original_args = _original_args # pyright: ignore [reportAttributeAccessIssue]
215
- inner._original_provider_call = provider_call # pyright: ignore [reportAttributeAccessIssue]
216
- inner._original_fn = fn # pyright: ignore [reportAttributeAccessIssue]
217
- inner._original_provider = provider # pyright: ignore [reportAttributeAccessIssue]
218
- return inner
194
+ if fn_is_async(decorated):
195
+
196
+ @wraps(decorated)
197
+ async def inner_async(
198
+ *args: _P.args, **kwargs: _P.kwargs
199
+ ) -> CallResponse | Stream:
200
+ result = await decorated(*args, **kwargs)
201
+ return _wrap_result(result)
202
+
203
+ inner_async._original_args = _original_args # pyright: ignore [reportAttributeAccessIssue]
204
+ inner_async._original_provider_call = provider_call # pyright: ignore [reportAttributeAccessIssue]
205
+ inner_async._original_fn = fn # pyright: ignore [reportAttributeAccessIssue]
206
+ inner_async._original_provider = provider # pyright: ignore [reportAttributeAccessIssue]
207
+
208
+ return inner_async
209
+ else:
210
+
211
+ @wraps(decorated)
212
+ def inner(*args: _P.args, **kwargs: _P.kwargs) -> CallResponse | Stream:
213
+ result = decorated(*args, **kwargs)
214
+ return _wrap_result(result)
215
+
216
+ inner._original_args = _original_args # pyright: ignore [reportAttributeAccessIssue]
217
+ inner._original_provider_call = provider_call # pyright: ignore [reportAttributeAccessIssue]
218
+ inner._original_fn = fn # pyright: ignore [reportAttributeAccessIssue]
219
+ inner._original_provider = provider # pyright: ignore [reportAttributeAccessIssue]
220
+ return inner
221
+
222
+ # @wraps(decorated)
223
+ # def inner(
224
+ # *args: _P.args, **kwargs: _P.kwargs
225
+ # ) -> CallResponse | Stream | Awaitable[CallResponse | Stream]:
226
+ # result = decorated(*args, **kwargs)
227
+ # if fn_is_async(decorated):
228
+
229
+ # async def async_wrapper() -> CallResponse | Stream:
230
+ # final = await result
231
+ # return _wrap_result(final)
232
+
233
+ # return async_wrapper()
234
+ # else:
235
+
236
+ # def sync_wrapper() -> CallResponse | Stream:
237
+ # final = result
238
+ # return _wrap_result(final)
239
+
240
+ # return sync_wrapper()
241
+
242
+ # inner._original_args = _original_args # pyright: ignore [reportAttributeAccessIssue]
243
+ # inner._original_provider_call = provider_call # pyright: ignore [reportAttributeAccessIssue]
244
+ # inner._original_fn = fn # pyright: ignore [reportAttributeAccessIssue]
245
+ # inner._original_provider = provider # pyright: ignore [reportAttributeAccessIssue]
246
+ # return inner
219
247
 
220
248
  return wrapper # pyright: ignore [reportReturnType]
221
249
 
mirascope/llm/stream.py CHANGED
@@ -62,10 +62,21 @@ class Stream(
62
62
  _BaseCallParamsT,
63
63
  ],
64
64
  ):
65
- """
66
- A non-pydantic class that inherits from BaseStream.
65
+ """A non-pydantic class that inherits from BaseStream."""
67
66
 
68
- """
67
+ _stream: BaseStream[
68
+ _BaseCallResponseT,
69
+ _BaseCallResponseChunkT,
70
+ _UserMessageParamT,
71
+ _AssistantMessageParamT,
72
+ _ToolMessageParamT,
73
+ _MessageParamT,
74
+ _BaseToolT,
75
+ _ToolSchemaT,
76
+ _BaseDynamicConfigT,
77
+ _BaseCallParamsT,
78
+ FinishReason,
79
+ ]
69
80
 
70
81
  def __init__(
71
82
  self,
@@ -85,20 +96,27 @@ class Stream(
85
96
  ],
86
97
  ) -> None:
87
98
  """Initialize the Stream class."""
88
- self._stream = stream
89
- super().__init__(
90
- stream=stream.stream,
91
- metadata=stream.metadata,
92
- tool_types=stream.tool_types,
93
- call_response_type=stream.call_response_type,
94
- model=stream.model,
95
- prompt_template=stream.prompt_template,
96
- fn_args=stream.fn_args or {},
97
- dynamic_config=stream.dynamic_config,
98
- messages=stream.messages,
99
- call_params=stream.call_params,
100
- call_kwargs=stream.call_kwargs,
101
- )
99
+ object.__setattr__(self, "_stream", stream)
100
+
101
+ def __getattribute__(self, name: str) -> Any: # noqa: ANN401
102
+ special_names = {
103
+ "_stream",
104
+ "cost",
105
+ "_construct_message_param",
106
+ "construct_call_response",
107
+ "tool_message_params",
108
+ "__dict__",
109
+ "__class__",
110
+ "__repr__",
111
+ "__str__",
112
+ "__iter__",
113
+ "__aiter__",
114
+ }
115
+
116
+ if name in special_names:
117
+ return object.__getattribute__(self, name)
118
+ response = object.__getattribute__(self, "_stream")
119
+ return getattr(response, name)
102
120
 
103
121
  def __iter__( # pyright: ignore [reportIncompatibleMethodOverride]
104
122
  self,
@@ -110,7 +128,7 @@ class Stream(
110
128
  None,
111
129
  ]:
112
130
  """Iterate over the stream."""
113
- for chunk, tool in super().__iter__():
131
+ for chunk, tool in self._stream:
114
132
  yield (
115
133
  CallResponseChunk(response=chunk), # pyright: ignore [reportAbstractUsage]
116
134
  Tool(tool=tool) if tool is not None else None, # pyright: ignore [reportAbstractUsage]
@@ -125,20 +143,12 @@ class Stream(
125
143
  None,
126
144
  ]:
127
145
  """Iterates over the stream and stores useful information."""
128
- async for chunk, tool in super().__aiter__():
146
+ async for chunk, tool in self._stream:
129
147
  yield (
130
148
  CallResponseChunk(response=chunk), # pyright: ignore [reportAbstractUsage]
131
149
  Tool(tool=tool) if tool is not None else None, # pyright: ignore [reportAbstractUsage]
132
150
  )
133
151
 
134
- def common_construct_call_response(
135
- self,
136
- ) -> CallResponse[_BaseCallResponseT, Tool[_ToolMessageParamT]]:
137
- """A common method that constructs a CallResponse instance."""
138
- return CallResponse[_BaseCallResponseT, Tool](
139
- response=self._stream.construct_call_response()
140
- ) # pyright: ignore [reportAbstractUsage]
141
-
142
152
  @property
143
153
  def cost(self) -> float | None:
144
154
  return self._stream.cost
@@ -152,12 +162,14 @@ class Stream(
152
162
 
153
163
  def construct_call_response( # pyright: ignore [reportIncompatibleMethodOverride]
154
164
  self,
155
- ) -> CallResponse[_BaseCallResponseT, Tool[_ToolMessageParamT]]:
156
- return self.common_construct_call_response()
165
+ ) -> CallResponse[_BaseCallResponseT]:
166
+ return CallResponse[_BaseCallResponseT](
167
+ response=self._stream.construct_call_response()
168
+ ) # pyright: ignore [reportAbstractUsage]
157
169
 
158
170
  @classmethod
159
- def common_tool_message_params(
160
- cls, tools_and_outputs: list[tuple[BaseTool, JsonableType]]
171
+ def tool_message_params( # pyright: ignore [reportIncompatibleMethodOverride]
172
+ cls, tools_and_outputs: list[tuple[Tool, JsonableType]]
161
173
  ) -> list[BaseMessageParam]:
162
174
  """Returns the tool message parameters for tool call results.
163
175
 
@@ -8,4 +8,4 @@ with suppress(ImportError):
8
8
  from . import tenacity as tenacity
9
9
 
10
10
 
11
- __all__ = ["fallback", "FallbackError", "tenacity"]
11
+ __all__ = ["FallbackError", "fallback", "tenacity"]
@@ -21,6 +21,7 @@ with suppress(ImportError):
21
21
  from .web._requests import Requests, RequestsConfig
22
22
 
23
23
  __all__ = [
24
+ "HTTPX",
24
25
  "AsyncHTTPX",
25
26
  "DockerOperationToolKit",
26
27
  "DockerOperationToolKitConfig",
@@ -28,10 +29,9 @@ __all__ = [
28
29
  "DuckDuckGoSearchConfig",
29
30
  "FileSystemToolKit",
30
31
  "FileSystemToolKitConfig",
31
- "HTTPX",
32
32
  "HTTPXConfig",
33
- "ParseURLContent",
34
33
  "ParseURLConfig",
34
+ "ParseURLContent",
35
35
  "Requests",
36
36
  "RequestsConfig",
37
37
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mirascope
3
- Version: 1.18.2
3
+ Version: 1.18.4
4
4
  Summary: LLM abstractions that aren't obstructions
5
5
  Project-URL: Homepage, https://mirascope.com
6
6
  Project-URL: Documentation, https://mirascope.com/WELCOME
@@ -116,7 +116,7 @@ Description-Content-Type: text/markdown
116
116
 
117
117
  ---
118
118
 
119
- Mirascope is a powerful, flexible, and user-friendly library that simplifies the process of working with LLMs through a unified interface that works across various supported providers, including [OpenAI](https://openai.com/), [Anthropic](https://www.anthropic.com/), [Mistral](https://mistral.ai/), [Gemini](https://gemini.google.com), [Groq](https://groq.com/), [Cohere](https://cohere.com/), [LiteLLM](https://www.litellm.ai/), [Azure AI](https://azure.microsoft.com/en-us/solutions/ai), [Vertex AI](https://cloud.google.com/vertex-ai), and [Bedrock](https://aws.amazon.com/bedrock/).
119
+ Mirascope is a powerful, flexible, and user-friendly library that simplifies the process of working with LLMs through a unified interface that works across various supported providers, including [OpenAI](https://openai.com/), [Anthropic](https://www.anthropic.com/), [Mistral](https://mistral.ai/), [Google (Gemini/Vertex)](https://googleapis.github.io/python-genai/), [Groq](https://groq.com/), [Cohere](https://cohere.com/), [LiteLLM](https://www.litellm.ai/), [Azure AI](https://azure.microsoft.com/en-us/solutions/ai), and [Bedrock](https://aws.amazon.com/bedrock/).
120
120
 
121
121
  Whether you're generating text, extracting structured information, or developing complex AI-driven agent systems, Mirascope provides the tools you need to streamline your development process and create powerful, robust applications.
122
122