mirascope 1.18.0__py3-none-any.whl → 1.18.2__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.
@@ -10,7 +10,6 @@ from azure.ai.inference import ChatCompletionsClient
10
10
  from azure.ai.inference.aio import ChatCompletionsClient as AsyncChatCompletionsClient
11
11
  from azure.ai.inference.models import (
12
12
  ChatCompletions,
13
- ChatCompletionsResponseFormatJSON,
14
13
  ChatRequestMessage,
15
14
  StreamingChatCompletionsUpdate,
16
15
  UserMessage,
@@ -29,13 +28,27 @@ from ...base._utils import (
29
28
  from ...base.call_params import CommonCallParams
30
29
  from ...base.stream_config import StreamConfig
31
30
  from .._call_kwargs import AzureCallKwargs
32
- from ..call_params import AzureCallParams
31
+ from ..call_params import AzureCallParams, ResponseFormatJSON
33
32
  from ..dynamic_config import AsyncAzureDynamicConfig, AzureDynamicConfig
34
33
  from ..tool import AzureTool, GenerateAzureStrictToolJsonSchema
35
34
  from ._convert_common_call_params import convert_common_call_params
36
35
  from ._convert_message_params import convert_message_params
37
36
  from ._get_credential import get_credential
38
37
 
38
+ try:
39
+ from azure.ai.inference.models._models import (
40
+ ChatCompletionsResponseFormatJSON as FormatJSON,
41
+ )
42
+
43
+ json_object: ResponseFormatJSON | None = None
44
+ except ImportError: # pragma: no cover
45
+ # https://github.com/Azure/azure-sdk-for-python/commit/cf61ada8243d619ee6164bf1d32b3939b3c271e5#diff-0fb29d8cce6df3a014592ba8e9959409b8c471088381549807239324f5e8ddc4R15-R17
46
+ from azure.ai.inference.models._models import (
47
+ JsonSchemaFormat as FormatJSON, # pyright: ignore [reportAttributeAccessIssue]
48
+ )
49
+
50
+ json_object = "json_object" # pyright: ignore [reportAssignmentType]
51
+
39
52
 
40
53
  @overload
41
54
  def setup_call(
@@ -116,7 +129,7 @@ def setup_call(
116
129
  messages = convert_message_params(messages)
117
130
  if json_mode:
118
131
  if response_model and response_model.model_config.get("strict", False):
119
- call_kwargs["response_format"] = ChatCompletionsResponseFormatJSON(
132
+ call_kwargs["response_format"] = FormatJSON(
120
133
  {
121
134
  "name": response_model.__name__,
122
135
  "description": response_model.__doc__ or DEFAULT_TOOL_DOCSTRING,
@@ -127,7 +140,7 @@ def setup_call(
127
140
  }
128
141
  )
129
142
  else:
130
- call_kwargs["response_format"] = ChatCompletionsResponseFormatJSON()
143
+ call_kwargs["response_format"] = json_object or FormatJSON()
131
144
  json_mode_content = _utils.json_mode_content(response_model).strip()
132
145
  messages.append(UserMessage(content=json_mode_content))
133
146
  elif response_model:
@@ -2,13 +2,26 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any
5
+ from typing import Any, Literal, TypeAlias
6
6
 
7
7
  from azure.ai.inference.models import (
8
8
  ChatCompletionsNamedToolChoice,
9
- ChatCompletionsResponseFormat,
10
9
  ChatCompletionsToolChoicePreset,
11
10
  )
11
+
12
+ try:
13
+ from azure.ai.inference.models import (
14
+ ChatCompletionsResponseFormatJSON,
15
+ )
16
+
17
+ ResponseFormatJSON: TypeAlias = ChatCompletionsResponseFormatJSON # pyright: ignore [reportRedeclaration]
18
+ except ImportError: # pragma: no cover
19
+ from azure.ai.inference.models import (
20
+ JsonSchemaFormat, # pyright: ignore [reportAttributeAccessIssue]
21
+ )
22
+
23
+ ResponseFormatJSON: TypeAlias = JsonSchemaFormat | Literal["json_object"] # pyright: ignore [reportRedeclaration]
24
+
12
25
  from typing_extensions import NotRequired
13
26
 
14
27
  from ..base import BaseCallParams
@@ -36,7 +49,7 @@ class AzureCallParams(BaseCallParams):
36
49
  max_tokens: NotRequired[int | None]
37
50
  model_extras: NotRequired[dict[str, Any] | None]
38
51
  presence_penalty: NotRequired[float | None]
39
- response_format: NotRequired[ChatCompletionsResponseFormat | None]
52
+ response_format: NotRequired[ResponseFormatJSON | None]
40
53
  seed: NotRequired[int | None]
41
54
  stop: NotRequired[list[str] | None]
42
55
  temperature: NotRequired[float | None]
@@ -63,7 +63,10 @@ def convert_message_params(
63
63
  )
64
64
  )
65
65
  elif part.type == "image_url":
66
- if part.url.startswith(("https://", "http://")):
66
+ if (
67
+ part.url.startswith(("https://", "http://"))
68
+ and "generativelanguage.googleapis.com" not in part.url
69
+ ):
67
70
  downloaded_image = io.BytesIO(_load_media(part.url))
68
71
  image = PIL.Image.open(downloaded_image)
69
72
  media_type = (
@@ -92,24 +95,15 @@ def convert_message_params(
92
95
  )
93
96
  uri = file_ref.uri
94
97
  media_type = file_ref.mime_type
95
-
96
- converted_content.append(
97
- PartDict(
98
- file_data=FileDataDict(
99
- file_uri=uri, mime_type=media_type
100
- )
101
- )
102
- )
103
98
  else:
104
- media_type = "image/unknown"
105
99
  uri = part.url
106
- converted_content.append(
107
- PartDict(
108
- file_data=FileDataDict(
109
- file_uri=uri, mime_type=media_type
110
- )
111
- )
100
+ media_type = None
101
+
102
+ converted_content.append(
103
+ PartDict(
104
+ file_data=FileDataDict(file_uri=uri, mime_type=media_type)
112
105
  )
106
+ )
113
107
  elif part.type == "audio":
114
108
  if part.media_type not in [
115
109
  "audio/wav",
@@ -135,9 +129,12 @@ def convert_message_params(
135
129
  )
136
130
  )
137
131
  elif part.type == "audio_url":
138
- if part.url.startswith(("https://", "http://")):
139
- audio = _load_media(part.url)
140
- audio_type = get_audio_type(audio)
132
+ if (
133
+ part.url.startswith(("https://", "http://"))
134
+ and "generativelanguage.googleapis.com" not in part.url
135
+ ):
136
+ downloaded_audio = _load_media(part.url)
137
+ audio_type = get_audio_type(downloaded_audio)
141
138
  if audio_type not in [
142
139
  "audio/wav",
143
140
  "audio/mp3",
@@ -151,16 +148,23 @@ def convert_message_params(
151
148
  "Google currently only supports WAV, MP3, AIFF, AAC, OGG, "
152
149
  "and FLAC audio file types."
153
150
  )
154
- converted_content.append(
155
- {"mime_type": audio_type, "data": audio}
156
- )
151
+ if client.vertexai:
152
+ uri = part.url
153
+ else:
154
+ downloaded_audio = io.BytesIO(downloaded_audio)
155
+ downloaded_audio.seek(0)
156
+ file_ref = client.files.upload(
157
+ file=downloaded_audio, config={"mime_type": audio_type}
158
+ )
159
+ uri = file_ref.uri
160
+ media_type = file_ref.mime_type
157
161
  else:
158
- audio_type = "audio/unknown"
162
+ uri = part.url
163
+ audio_type = None
164
+
159
165
  converted_content.append(
160
166
  PartDict(
161
- file_data=FileDataDict(
162
- file_uri=part.url, mime_type=audio_type
163
- )
167
+ file_data=FileDataDict(file_uri=uri, mime_type=audio_type)
164
168
  )
165
169
  )
166
170
  else:
@@ -104,8 +104,14 @@ class GoogleMessageParamConverter(BaseMessageParamConverter):
104
104
  )
105
105
  )
106
106
  else:
107
- raise ValueError(
108
- f"Unsupported file_data mime type: {part.file_data.mime_type}. Cannot convert to BaseMessageParam."
107
+ # Since `FileDataDict` handles any file data, we use
108
+ # `ImageURLPart` for unknown mime types
109
+ content_list.append(
110
+ ImageURLPart(
111
+ type="image_url",
112
+ url=cast(str, part.file_data.file_uri),
113
+ detail=None,
114
+ )
109
115
  )
110
116
  elif part.function_call:
111
117
  converted.append(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mirascope
3
- Version: 1.18.0
3
+ Version: 1.18.2
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
@@ -65,7 +65,7 @@ mirascope/core/anthropic/_utils/_setup_call.py,sha256=tR-SFT_ZJd_Gk7RY4NOU3do536
65
65
  mirascope/core/azure/__init__.py,sha256=ozfFhyCC0bFLDUA7m2v1POywSFpLJi6E7xZ2bhBIdC0,852
66
66
  mirascope/core/azure/_call.py,sha256=SHqSJe6_4zgn4Y9PkpDl4vXvLuT4QmVnWUcws9e_RR8,2237
67
67
  mirascope/core/azure/_call_kwargs.py,sha256=q38xKSgCBWi8DLScepG-KnUfgi67AU6xr2uOHwCZ2mI,435
68
- mirascope/core/azure/call_params.py,sha256=o5xhlWlyUB8bTewp9fj3l0jvbCpoOsZFnaGwhkEWTD0,1366
68
+ mirascope/core/azure/call_params.py,sha256=NK_ggVJbactDip85DbfCaqSWRpO0CgwN1svY-KW4_Yg,1836
69
69
  mirascope/core/azure/call_response.py,sha256=eYH55I5awZ0Yhu3sK2N-4XLImjvRgDKOGF1pTs_QjIY,6834
70
70
  mirascope/core/azure/call_response_chunk.py,sha256=tcLgURISaGONGDvWjWDfDPs2c0hQJT_tVELiDqL33SQ,2884
71
71
  mirascope/core/azure/dynamic_config.py,sha256=6SBMGFce7tuXdwHrlKNISpZxVxUnnumbIQB9lGR6nbs,1066
@@ -81,7 +81,7 @@ mirascope/core/azure/_utils/_get_credential.py,sha256=hEWoKtB27PLZtC35qvPx36CPvQ
81
81
  mirascope/core/azure/_utils/_get_json_output.py,sha256=Qec7WJY5is1Q63Vp9uUNNfkRwgxhdoLMCI7AF_e2t90,1017
82
82
  mirascope/core/azure/_utils/_handle_stream.py,sha256=M_BGnjBGWTPefNyIMuJSHiDxIvqmENmqfVlDx_qzL1c,4638
83
83
  mirascope/core/azure/_utils/_message_param_converter.py,sha256=JAUeHObtd_V225YyZqEruuih3HRozq43pqjYJCbJj8A,4443
84
- mirascope/core/azure/_utils/_setup_call.py,sha256=07fVPaM56CC-nNgf9hjIAxiNTGC9XD3bvADEEOCKJ9E,5936
84
+ mirascope/core/azure/_utils/_setup_call.py,sha256=cdUof-RCxsPbKuJvevsEUYXU-ckoql3wTevNEQiEpz4,6496
85
85
  mirascope/core/base/__init__.py,sha256=iq8HMwrTt7MK-zgHg2JgBP4F7ruBTbDituFR2P4Jg2k,1904
86
86
  mirascope/core/base/_call_factory.py,sha256=YdFHAa9WtGfYeqVcM2xaDNh5gMg584rOe26_E51-1to,9663
87
87
  mirascope/core/base/_create.py,sha256=1UNRA6pwMguaiLyLiQkPzTk12ASaXT_hh7jlNw4UFX4,10016
@@ -212,10 +212,10 @@ mirascope/core/google/_utils/__init__.py,sha256=5MKOhK3NFseq2AlapU8TtWS82f8Z0ayJ
212
212
  mirascope/core/google/_utils/_calculate_cost.py,sha256=fUyi6QAEa_NpPhtoAgVdQ7PpUa0QykNghsODrDtAYvw,3069
213
213
  mirascope/core/google/_utils/_convert_common_call_params.py,sha256=KA-z6uvRtdD4WydC0eXd3dzQuSh4x4WKNR8PAqFNUVY,1065
214
214
  mirascope/core/google/_utils/_convert_finish_reason_to_common_finish_reasons.py,sha256=ig4tb7Zanz-tyZpvc9Ncd47a2FNTOS7-wl1PYBq-4cY,879
215
- mirascope/core/google/_utils/_convert_message_params.py,sha256=Da2690Pvb1eGbnz0iHdTcsdtBzYADC_RUlNIkxIJGyQ,7632
215
+ mirascope/core/google/_utils/_convert_message_params.py,sha256=h2RfIOw26QSjF5ybdo7W2Ah9u-7qI3rewLzma1sgKQ0,7852
216
216
  mirascope/core/google/_utils/_get_json_output.py,sha256=sxDgT0Ra6YJynL5_hhakf0dNJEhZm0DfAgfcvC_DAFU,1596
217
217
  mirascope/core/google/_utils/_handle_stream.py,sha256=BxFuheAu1LKPrPsDxxiLWd2KoajkwJyx2_QT1NXwtWE,1212
218
- mirascope/core/google/_utils/_message_param_converter.py,sha256=FcPWdMdMcz3Th4q7-vATkPoRPYdT-WdT-sDXsTJO8zQ,6240
218
+ mirascope/core/google/_utils/_message_param_converter.py,sha256=j-5fLlW2-3vI0kGQs-nVep_1kDr4kYYUBYYS9MV08Ks,6495
219
219
  mirascope/core/google/_utils/_setup_call.py,sha256=LAoIrNTTF5EOHNLZroBcN8sNKOjMYKJ07hM49yBaUgE,5791
220
220
  mirascope/core/groq/__init__.py,sha256=wo-_txqiLC3iswnXmPX4C6IgsU-_wv1DbBlNDY4rEvo,798
221
221
  mirascope/core/groq/_call.py,sha256=gR8VN5IaYWIFXc0csn995q59FM0nBs-xVFjkVycPjMM,2223
@@ -350,7 +350,7 @@ mirascope/v0/base/ops_utils.py,sha256=1Qq-VIwgHBaYutiZsS2MUQ4OgPC3APyywI5bTiTAmA
350
350
  mirascope/v0/base/prompts.py,sha256=FM2Yz98cSnDceYogiwPrp4BALf3_F3d4fIOCGAkd-SE,1298
351
351
  mirascope/v0/base/types.py,sha256=ZfatJoX0Yl0e3jhv0D_MhiSVHLYUeJsdN3um3iE10zY,352
352
352
  mirascope/v0/base/utils.py,sha256=XREPENRQTu8gpMhHU8RC8qH_am3FfGUvY-dJ6x8i-mw,681
353
- mirascope-1.18.0.dist-info/METADATA,sha256=P63GzWcu4PhSMPV6Wie3XbEgz_Jpu1xu-FNl2yJeftk,8678
354
- mirascope-1.18.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
355
- mirascope-1.18.0.dist-info/licenses/LICENSE,sha256=LAs5Q8mdawTsVdONpDGukwsoc4KEUBmmonDEL39b23Y,1072
356
- mirascope-1.18.0.dist-info/RECORD,,
353
+ mirascope-1.18.2.dist-info/METADATA,sha256=37QK3S0KrXlyR3HrMikdN36fE4cATMWLQfARj56jHoA,8678
354
+ mirascope-1.18.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
355
+ mirascope-1.18.2.dist-info/licenses/LICENSE,sha256=LAs5Q8mdawTsVdONpDGukwsoc4KEUBmmonDEL39b23Y,1072
356
+ mirascope-1.18.2.dist-info/RECORD,,