mistralai 1.10.1__py3-none-any.whl → 1.12.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.
Files changed (251) hide show
  1. mistralai/_version.py +3 -3
  2. mistralai/accesses.py +22 -12
  3. mistralai/agents.py +88 -44
  4. mistralai/audio.py +20 -0
  5. mistralai/basesdk.py +6 -0
  6. mistralai/chat.py +96 -40
  7. mistralai/classifiers.py +35 -22
  8. mistralai/conversations.py +234 -72
  9. mistralai/documents.py +72 -26
  10. mistralai/embeddings.py +17 -8
  11. mistralai/extra/__init__.py +48 -0
  12. mistralai/extra/exceptions.py +49 -4
  13. mistralai/extra/realtime/__init__.py +25 -0
  14. mistralai/extra/realtime/connection.py +207 -0
  15. mistralai/extra/realtime/transcription.py +271 -0
  16. mistralai/files.py +64 -24
  17. mistralai/fim.py +20 -12
  18. mistralai/httpclient.py +0 -1
  19. mistralai/jobs.py +65 -26
  20. mistralai/libraries.py +20 -10
  21. mistralai/mistral_agents.py +825 -34
  22. mistralai/mistral_jobs.py +33 -14
  23. mistralai/models/__init__.py +119 -0
  24. mistralai/models/agent.py +1 -1
  25. mistralai/models/agentaliasresponse.py +23 -0
  26. mistralai/models/agentconversation.py +15 -5
  27. mistralai/models/agenthandoffdoneevent.py +1 -1
  28. mistralai/models/agenthandoffentry.py +3 -2
  29. mistralai/models/agenthandoffstartedevent.py +1 -1
  30. mistralai/models/agents_api_v1_agents_create_or_update_aliasop.py +26 -0
  31. mistralai/models/agents_api_v1_agents_get_versionop.py +21 -0
  32. mistralai/models/agents_api_v1_agents_getop.py +12 -3
  33. mistralai/models/agents_api_v1_agents_list_version_aliasesop.py +16 -0
  34. mistralai/models/agents_api_v1_agents_list_versionsop.py +33 -0
  35. mistralai/models/agents_api_v1_agents_listop.py +4 -0
  36. mistralai/models/agentscompletionrequest.py +2 -5
  37. mistralai/models/agentscompletionstreamrequest.py +2 -5
  38. mistralai/models/archiveftmodelout.py +1 -1
  39. mistralai/models/assistantmessage.py +1 -1
  40. mistralai/models/audiochunk.py +1 -1
  41. mistralai/models/audioencoding.py +6 -1
  42. mistralai/models/audioformat.py +2 -4
  43. mistralai/models/audiotranscriptionrequest.py +8 -0
  44. mistralai/models/audiotranscriptionrequeststream.py +8 -0
  45. mistralai/models/basemodelcard.py +1 -1
  46. mistralai/models/batchjobin.py +2 -4
  47. mistralai/models/batchjobout.py +1 -1
  48. mistralai/models/batchjobsout.py +1 -1
  49. mistralai/models/chatcompletionchoice.py +10 -5
  50. mistralai/models/chatcompletionrequest.py +2 -5
  51. mistralai/models/chatcompletionstreamrequest.py +2 -5
  52. mistralai/models/classifierdetailedjobout.py +4 -2
  53. mistralai/models/classifierftmodelout.py +3 -2
  54. mistralai/models/classifierjobout.py +4 -2
  55. mistralai/models/codeinterpretertool.py +1 -1
  56. mistralai/models/completiondetailedjobout.py +5 -2
  57. mistralai/models/completionftmodelout.py +3 -2
  58. mistralai/models/completionjobout.py +5 -2
  59. mistralai/models/completionresponsestreamchoice.py +9 -8
  60. mistralai/models/conversationappendrequest.py +4 -1
  61. mistralai/models/conversationappendstreamrequest.py +4 -1
  62. mistralai/models/conversationhistory.py +2 -1
  63. mistralai/models/conversationmessages.py +1 -1
  64. mistralai/models/conversationrequest.py +13 -3
  65. mistralai/models/conversationresponse.py +2 -1
  66. mistralai/models/conversationrestartrequest.py +22 -5
  67. mistralai/models/conversationrestartstreamrequest.py +24 -5
  68. mistralai/models/conversationstreamrequest.py +17 -3
  69. mistralai/models/documentlibrarytool.py +1 -1
  70. mistralai/models/documenturlchunk.py +1 -1
  71. mistralai/models/embeddingdtype.py +7 -1
  72. mistralai/models/encodingformat.py +4 -1
  73. mistralai/models/entitytype.py +8 -1
  74. mistralai/models/filepurpose.py +8 -1
  75. mistralai/models/files_api_routes_list_filesop.py +12 -12
  76. mistralai/models/files_api_routes_upload_fileop.py +2 -6
  77. mistralai/models/fileschema.py +3 -5
  78. mistralai/models/finetuneablemodeltype.py +4 -1
  79. mistralai/models/ftclassifierlossfunction.py +4 -1
  80. mistralai/models/ftmodelcard.py +1 -1
  81. mistralai/models/functioncallentry.py +3 -2
  82. mistralai/models/functioncallevent.py +1 -1
  83. mistralai/models/functionresultentry.py +3 -2
  84. mistralai/models/functiontool.py +1 -1
  85. mistralai/models/githubrepositoryin.py +1 -1
  86. mistralai/models/githubrepositoryout.py +1 -1
  87. mistralai/models/httpvalidationerror.py +4 -2
  88. mistralai/models/imagegenerationtool.py +1 -1
  89. mistralai/models/imageurlchunk.py +1 -1
  90. mistralai/models/jobsout.py +1 -1
  91. mistralai/models/legacyjobmetadataout.py +1 -1
  92. mistralai/models/messageinputentry.py +9 -3
  93. mistralai/models/messageoutputentry.py +6 -3
  94. mistralai/models/messageoutputevent.py +4 -2
  95. mistralai/models/mistralerror.py +11 -7
  96. mistralai/models/mistralpromptmode.py +5 -1
  97. mistralai/models/modelcapabilities.py +3 -0
  98. mistralai/models/modelconversation.py +1 -1
  99. mistralai/models/no_response_error.py +5 -1
  100. mistralai/models/ocrrequest.py +11 -1
  101. mistralai/models/ocrtableobject.py +4 -1
  102. mistralai/models/realtimetranscriptionerror.py +27 -0
  103. mistralai/models/realtimetranscriptionerrordetail.py +29 -0
  104. mistralai/models/realtimetranscriptionsession.py +20 -0
  105. mistralai/models/realtimetranscriptionsessioncreated.py +30 -0
  106. mistralai/models/realtimetranscriptionsessionupdated.py +30 -0
  107. mistralai/models/referencechunk.py +1 -1
  108. mistralai/models/requestsource.py +5 -1
  109. mistralai/models/responsedoneevent.py +1 -1
  110. mistralai/models/responseerrorevent.py +1 -1
  111. mistralai/models/responseformats.py +5 -1
  112. mistralai/models/responsestartedevent.py +1 -1
  113. mistralai/models/responsevalidationerror.py +2 -0
  114. mistralai/models/retrievefileout.py +3 -5
  115. mistralai/models/sampletype.py +7 -1
  116. mistralai/models/sdkerror.py +2 -0
  117. mistralai/models/shareenum.py +7 -1
  118. mistralai/models/sharingdelete.py +2 -4
  119. mistralai/models/sharingin.py +3 -5
  120. mistralai/models/source.py +8 -1
  121. mistralai/models/systemmessage.py +1 -1
  122. mistralai/models/textchunk.py +1 -1
  123. mistralai/models/thinkchunk.py +1 -1
  124. mistralai/models/timestampgranularity.py +4 -1
  125. mistralai/models/tool.py +2 -6
  126. mistralai/models/toolcall.py +2 -6
  127. mistralai/models/toolchoice.py +2 -6
  128. mistralai/models/toolchoiceenum.py +6 -1
  129. mistralai/models/toolexecutiondeltaevent.py +2 -1
  130. mistralai/models/toolexecutiondoneevent.py +2 -1
  131. mistralai/models/toolexecutionentry.py +4 -2
  132. mistralai/models/toolexecutionstartedevent.py +2 -1
  133. mistralai/models/toolfilechunk.py +2 -1
  134. mistralai/models/toolmessage.py +1 -1
  135. mistralai/models/toolreferencechunk.py +2 -1
  136. mistralai/models/tooltypes.py +1 -1
  137. mistralai/models/transcriptionsegmentchunk.py +42 -3
  138. mistralai/models/transcriptionstreamdone.py +1 -1
  139. mistralai/models/transcriptionstreamlanguage.py +1 -1
  140. mistralai/models/transcriptionstreamsegmentdelta.py +39 -3
  141. mistralai/models/transcriptionstreamtextdelta.py +1 -1
  142. mistralai/models/unarchiveftmodelout.py +1 -1
  143. mistralai/models/uploadfileout.py +3 -5
  144. mistralai/models/usermessage.py +1 -1
  145. mistralai/models/wandbintegration.py +1 -1
  146. mistralai/models/wandbintegrationout.py +1 -1
  147. mistralai/models/websearchpremiumtool.py +1 -1
  148. mistralai/models/websearchtool.py +1 -1
  149. mistralai/models_.py +24 -12
  150. mistralai/ocr.py +38 -10
  151. mistralai/sdk.py +2 -2
  152. mistralai/transcriptions.py +52 -12
  153. mistralai/types/basemodel.py +41 -3
  154. mistralai/utils/__init__.py +0 -3
  155. mistralai/utils/annotations.py +32 -8
  156. mistralai/utils/enums.py +60 -0
  157. mistralai/utils/forms.py +21 -10
  158. mistralai/utils/queryparams.py +14 -2
  159. mistralai/utils/requestbodies.py +3 -3
  160. mistralai/utils/retries.py +69 -5
  161. mistralai/utils/serializers.py +0 -20
  162. mistralai/utils/unmarshal_json_response.py +15 -1
  163. {mistralai-1.10.1.dist-info → mistralai-1.12.0.dist-info}/METADATA +28 -31
  164. {mistralai-1.10.1.dist-info → mistralai-1.12.0.dist-info}/RECORD +251 -237
  165. mistralai_azure/_version.py +3 -3
  166. mistralai_azure/basesdk.py +6 -0
  167. mistralai_azure/chat.py +27 -15
  168. mistralai_azure/httpclient.py +0 -1
  169. mistralai_azure/models/__init__.py +16 -1
  170. mistralai_azure/models/assistantmessage.py +1 -1
  171. mistralai_azure/models/chatcompletionchoice.py +10 -7
  172. mistralai_azure/models/chatcompletionrequest.py +8 -6
  173. mistralai_azure/models/chatcompletionstreamrequest.py +8 -6
  174. mistralai_azure/models/completionresponsestreamchoice.py +11 -7
  175. mistralai_azure/models/documenturlchunk.py +1 -1
  176. mistralai_azure/models/httpvalidationerror.py +4 -2
  177. mistralai_azure/models/imageurlchunk.py +1 -1
  178. mistralai_azure/models/mistralazureerror.py +11 -7
  179. mistralai_azure/models/mistralpromptmode.py +1 -1
  180. mistralai_azure/models/no_response_error.py +5 -1
  181. mistralai_azure/models/ocrpageobject.py +32 -5
  182. mistralai_azure/models/ocrrequest.py +20 -1
  183. mistralai_azure/models/ocrtableobject.py +34 -0
  184. mistralai_azure/models/referencechunk.py +1 -1
  185. mistralai_azure/models/responseformats.py +5 -1
  186. mistralai_azure/models/responsevalidationerror.py +2 -0
  187. mistralai_azure/models/sdkerror.py +2 -0
  188. mistralai_azure/models/systemmessage.py +1 -1
  189. mistralai_azure/models/textchunk.py +1 -1
  190. mistralai_azure/models/thinkchunk.py +1 -1
  191. mistralai_azure/models/tool.py +2 -6
  192. mistralai_azure/models/toolcall.py +2 -6
  193. mistralai_azure/models/toolchoice.py +2 -6
  194. mistralai_azure/models/toolchoiceenum.py +6 -1
  195. mistralai_azure/models/toolmessage.py +1 -1
  196. mistralai_azure/models/tooltypes.py +1 -1
  197. mistralai_azure/models/usermessage.py +1 -1
  198. mistralai_azure/ocr.py +26 -6
  199. mistralai_azure/types/basemodel.py +41 -3
  200. mistralai_azure/utils/__init__.py +0 -3
  201. mistralai_azure/utils/annotations.py +32 -8
  202. mistralai_azure/utils/enums.py +60 -0
  203. mistralai_azure/utils/forms.py +21 -10
  204. mistralai_azure/utils/queryparams.py +14 -2
  205. mistralai_azure/utils/requestbodies.py +3 -3
  206. mistralai_azure/utils/retries.py +69 -5
  207. mistralai_azure/utils/serializers.py +0 -20
  208. mistralai_azure/utils/unmarshal_json_response.py +15 -1
  209. mistralai_gcp/_version.py +3 -3
  210. mistralai_gcp/basesdk.py +6 -0
  211. mistralai_gcp/chat.py +27 -15
  212. mistralai_gcp/fim.py +27 -15
  213. mistralai_gcp/httpclient.py +0 -1
  214. mistralai_gcp/models/assistantmessage.py +1 -1
  215. mistralai_gcp/models/chatcompletionchoice.py +10 -7
  216. mistralai_gcp/models/chatcompletionrequest.py +8 -6
  217. mistralai_gcp/models/chatcompletionstreamrequest.py +8 -6
  218. mistralai_gcp/models/completionresponsestreamchoice.py +11 -7
  219. mistralai_gcp/models/fimcompletionrequest.py +6 -1
  220. mistralai_gcp/models/fimcompletionstreamrequest.py +6 -1
  221. mistralai_gcp/models/httpvalidationerror.py +4 -2
  222. mistralai_gcp/models/imageurlchunk.py +1 -1
  223. mistralai_gcp/models/mistralgcperror.py +11 -7
  224. mistralai_gcp/models/mistralpromptmode.py +1 -1
  225. mistralai_gcp/models/no_response_error.py +5 -1
  226. mistralai_gcp/models/referencechunk.py +1 -1
  227. mistralai_gcp/models/responseformats.py +5 -1
  228. mistralai_gcp/models/responsevalidationerror.py +2 -0
  229. mistralai_gcp/models/sdkerror.py +2 -0
  230. mistralai_gcp/models/systemmessage.py +1 -1
  231. mistralai_gcp/models/textchunk.py +1 -1
  232. mistralai_gcp/models/thinkchunk.py +1 -1
  233. mistralai_gcp/models/tool.py +2 -6
  234. mistralai_gcp/models/toolcall.py +2 -6
  235. mistralai_gcp/models/toolchoice.py +2 -6
  236. mistralai_gcp/models/toolchoiceenum.py +6 -1
  237. mistralai_gcp/models/toolmessage.py +1 -1
  238. mistralai_gcp/models/tooltypes.py +1 -1
  239. mistralai_gcp/models/usermessage.py +1 -1
  240. mistralai_gcp/types/basemodel.py +41 -3
  241. mistralai_gcp/utils/__init__.py +0 -3
  242. mistralai_gcp/utils/annotations.py +32 -8
  243. mistralai_gcp/utils/enums.py +60 -0
  244. mistralai_gcp/utils/forms.py +21 -10
  245. mistralai_gcp/utils/queryparams.py +14 -2
  246. mistralai_gcp/utils/requestbodies.py +3 -3
  247. mistralai_gcp/utils/retries.py +69 -5
  248. mistralai_gcp/utils/serializers.py +0 -20
  249. mistralai_gcp/utils/unmarshal_json_response.py +15 -1
  250. {mistralai-1.10.1.dist-info → mistralai-1.12.0.dist-info}/WHEEL +0 -0
  251. {mistralai-1.10.1.dist-info → mistralai-1.12.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,6 +2,10 @@
2
2
 
3
3
  import enum
4
4
  import sys
5
+ from typing import Any
6
+
7
+ from pydantic_core import core_schema
8
+
5
9
 
6
10
  class OpenEnumMeta(enum.EnumMeta):
7
11
  # The __call__ method `boundary` kwarg was added in 3.11 and must be present
@@ -72,3 +76,59 @@ class OpenEnumMeta(enum.EnumMeta):
72
76
  )
73
77
  except ValueError:
74
78
  return value
79
+
80
+ def __new__(mcs, name, bases, namespace, **kwargs):
81
+ cls = super().__new__(mcs, name, bases, namespace, **kwargs)
82
+
83
+ # Add __get_pydantic_core_schema__ to make open enums work correctly
84
+ # in union discrimination. In strict mode (used by Pydantic for unions),
85
+ # only known enum values match. In lax mode, unknown values are accepted.
86
+ def __get_pydantic_core_schema__(
87
+ cls_inner: Any, _source_type: Any, _handler: Any
88
+ ) -> core_schema.CoreSchema:
89
+ # Create a validator that only accepts known enum values (for strict mode)
90
+ def validate_strict(v: Any) -> Any:
91
+ if isinstance(v, cls_inner):
92
+ return v
93
+ # Use the parent EnumMeta's __call__ which raises ValueError for unknown values
94
+ return enum.EnumMeta.__call__(cls_inner, v)
95
+
96
+ # Create a lax validator that accepts unknown values
97
+ def validate_lax(v: Any) -> Any:
98
+ if isinstance(v, cls_inner):
99
+ return v
100
+ try:
101
+ return enum.EnumMeta.__call__(cls_inner, v)
102
+ except ValueError:
103
+ # Return the raw value for unknown enum values
104
+ return v
105
+
106
+ # Determine the base type schema (str or int)
107
+ is_int_enum = False
108
+ for base in cls_inner.__mro__:
109
+ if base is int:
110
+ is_int_enum = True
111
+ break
112
+ if base is str:
113
+ break
114
+
115
+ base_schema = (
116
+ core_schema.int_schema()
117
+ if is_int_enum
118
+ else core_schema.str_schema()
119
+ )
120
+
121
+ # Use lax_or_strict_schema:
122
+ # - strict mode: only known enum values match (raises ValueError for unknown)
123
+ # - lax mode: accept any value, return enum member or raw value
124
+ return core_schema.lax_or_strict_schema(
125
+ lax_schema=core_schema.chain_schema(
126
+ [base_schema, core_schema.no_info_plain_validator_function(validate_lax)]
127
+ ),
128
+ strict_schema=core_schema.chain_schema(
129
+ [base_schema, core_schema.no_info_plain_validator_function(validate_strict)]
130
+ ),
131
+ )
132
+
133
+ setattr(cls, "__get_pydantic_core_schema__", classmethod(__get_pydantic_core_schema__))
134
+ return cls
@@ -142,16 +142,21 @@ def serialize_multipart_form(
142
142
  if field_metadata.file:
143
143
  if isinstance(val, List):
144
144
  # Handle array of files
145
+ array_field_name = f_name + "[]"
145
146
  for file_obj in val:
146
147
  if not _is_set(file_obj):
147
148
  continue
148
-
149
- file_name, content, content_type = _extract_file_properties(file_obj)
149
+
150
+ file_name, content, content_type = _extract_file_properties(
151
+ file_obj
152
+ )
150
153
 
151
154
  if content_type is not None:
152
- files.append((f_name + "[]", (file_name, content, content_type)))
155
+ files.append(
156
+ (array_field_name, (file_name, content, content_type))
157
+ )
153
158
  else:
154
- files.append((f_name + "[]", (file_name, content)))
159
+ files.append((array_field_name, (file_name, content)))
155
160
  else:
156
161
  # Handle single file
157
162
  file_name, content, content_type = _extract_file_properties(val)
@@ -161,11 +166,16 @@ def serialize_multipart_form(
161
166
  else:
162
167
  files.append((f_name, (file_name, content)))
163
168
  elif field_metadata.json:
164
- files.append((f_name, (
165
- None,
166
- marshal_json(val, request_field_types[name]),
167
- "application/json",
168
- )))
169
+ files.append(
170
+ (
171
+ f_name,
172
+ (
173
+ None,
174
+ marshal_json(val, request_field_types[name]),
175
+ "application/json",
176
+ ),
177
+ )
178
+ )
169
179
  else:
170
180
  if isinstance(val, List):
171
181
  values = []
@@ -175,7 +185,8 @@ def serialize_multipart_form(
175
185
  continue
176
186
  values.append(_val_to_string(value))
177
187
 
178
- form[f_name + "[]"] = values
188
+ array_field_name = f_name + "[]"
189
+ form[array_field_name] = values
179
190
  else:
180
191
  form[f_name] = _val_to_string(val)
181
192
  return media_type, form, files
@@ -27,12 +27,13 @@ from .forms import _populate_form
27
27
  def get_query_params(
28
28
  query_params: Any,
29
29
  gbls: Optional[Any] = None,
30
+ allow_empty_value: Optional[List[str]] = None,
30
31
  ) -> Dict[str, List[str]]:
31
32
  params: Dict[str, List[str]] = {}
32
33
 
33
- globals_already_populated = _populate_query_params(query_params, gbls, params, [])
34
+ globals_already_populated = _populate_query_params(query_params, gbls, params, [], allow_empty_value)
34
35
  if _is_set(gbls):
35
- _populate_query_params(gbls, None, params, globals_already_populated)
36
+ _populate_query_params(gbls, None, params, globals_already_populated, allow_empty_value)
36
37
 
37
38
  return params
38
39
 
@@ -42,6 +43,7 @@ def _populate_query_params(
42
43
  gbls: Any,
43
44
  query_param_values: Dict[str, List[str]],
44
45
  skip_fields: List[str],
46
+ allow_empty_value: Optional[List[str]] = None,
45
47
  ) -> List[str]:
46
48
  globals_already_populated: List[str] = []
47
49
 
@@ -69,6 +71,16 @@ def _populate_query_params(
69
71
  globals_already_populated.append(name)
70
72
 
71
73
  f_name = field.alias if field.alias is not None else name
74
+
75
+ allow_empty_set = set(allow_empty_value or [])
76
+ should_include_empty = f_name in allow_empty_set and (
77
+ value is None or value == [] or value == ""
78
+ )
79
+
80
+ if should_include_empty:
81
+ query_param_values[f_name] = [""]
82
+ continue
83
+
72
84
  serialization = metadata.serialization
73
85
  if serialization is not None:
74
86
  serialized_parms = _get_serialized_params(
@@ -44,15 +44,15 @@ def serialize_request_body(
44
44
 
45
45
  serialized_request_body = SerializedRequestBody(media_type)
46
46
 
47
- if re.match(r"(application|text)\/.*?\+*json.*", media_type) is not None:
47
+ if re.match(r"^(application|text)\/([^+]+\+)*json.*", media_type) is not None:
48
48
  serialized_request_body.content = marshal_json(request_body, request_body_type)
49
- elif re.match(r"multipart\/.*", media_type) is not None:
49
+ elif re.match(r"^multipart\/.*", media_type) is not None:
50
50
  (
51
51
  serialized_request_body.media_type,
52
52
  serialized_request_body.data,
53
53
  serialized_request_body.files,
54
54
  ) = serialize_multipart_form(media_type, request_body)
55
- elif re.match(r"application\/x-www-form-urlencoded.*", media_type) is not None:
55
+ elif re.match(r"^application\/x-www-form-urlencoded.*", media_type) is not None:
56
56
  serialized_request_body.data = serialize_form_data(request_body)
57
57
  elif isinstance(request_body, (bytes, bytearray, io.BytesIO, io.BufferedReader)):
58
58
  serialized_request_body.content = request_body
@@ -3,7 +3,9 @@
3
3
  import asyncio
4
4
  import random
5
5
  import time
6
- from typing import List
6
+ from datetime import datetime
7
+ from email.utils import parsedate_to_datetime
8
+ from typing import List, Optional
7
9
 
8
10
  import httpx
9
11
 
@@ -51,9 +53,11 @@ class Retries:
51
53
 
52
54
  class TemporaryError(Exception):
53
55
  response: httpx.Response
56
+ retry_after: Optional[int]
54
57
 
55
58
  def __init__(self, response: httpx.Response):
56
59
  self.response = response
60
+ self.retry_after = _parse_retry_after_header(response)
57
61
 
58
62
 
59
63
  class PermanentError(Exception):
@@ -63,6 +67,62 @@ class PermanentError(Exception):
63
67
  self.inner = inner
64
68
 
65
69
 
70
+ def _parse_retry_after_header(response: httpx.Response) -> Optional[int]:
71
+ """Parse Retry-After header from response.
72
+
73
+ Returns:
74
+ Retry interval in milliseconds, or None if header is missing or invalid.
75
+ """
76
+ retry_after_header = response.headers.get("retry-after")
77
+ if not retry_after_header:
78
+ return None
79
+
80
+ try:
81
+ seconds = float(retry_after_header)
82
+ return round(seconds * 1000)
83
+ except ValueError:
84
+ pass
85
+
86
+ try:
87
+ retry_date = parsedate_to_datetime(retry_after_header)
88
+ delta = (retry_date - datetime.now(retry_date.tzinfo)).total_seconds()
89
+ return round(max(0, delta) * 1000)
90
+ except (ValueError, TypeError):
91
+ pass
92
+
93
+ return None
94
+
95
+
96
+ def _get_sleep_interval(
97
+ exception: Exception,
98
+ initial_interval: int,
99
+ max_interval: int,
100
+ exponent: float,
101
+ retries: int,
102
+ ) -> float:
103
+ """Get sleep interval for retry with exponential backoff.
104
+
105
+ Args:
106
+ exception: The exception that triggered the retry.
107
+ initial_interval: Initial retry interval in milliseconds.
108
+ max_interval: Maximum retry interval in milliseconds.
109
+ exponent: Base for exponential backoff calculation.
110
+ retries: Current retry attempt count.
111
+
112
+ Returns:
113
+ Sleep interval in seconds.
114
+ """
115
+ if (
116
+ isinstance(exception, TemporaryError)
117
+ and exception.retry_after is not None
118
+ and exception.retry_after > 0
119
+ ):
120
+ return exception.retry_after / 1000
121
+
122
+ sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1)
123
+ return min(sleep, max_interval / 1000)
124
+
125
+
66
126
  def retry(func, retries: Retries):
67
127
  if retries.config.strategy == "backoff":
68
128
 
@@ -183,8 +243,10 @@ def retry_with_backoff(
183
243
  return exception.response
184
244
 
185
245
  raise
186
- sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1)
187
- sleep = min(sleep, max_interval / 1000)
246
+
247
+ sleep = _get_sleep_interval(
248
+ exception, initial_interval, max_interval, exponent, retries
249
+ )
188
250
  time.sleep(sleep)
189
251
  retries += 1
190
252
 
@@ -211,7 +273,9 @@ async def retry_with_backoff_async(
211
273
  return exception.response
212
274
 
213
275
  raise
214
- sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1)
215
- sleep = min(sleep, max_interval / 1000)
276
+
277
+ sleep = _get_sleep_interval(
278
+ exception, initial_interval, max_interval, exponent, retries
279
+ )
216
280
  await asyncio.sleep(sleep)
217
281
  retries += 1
@@ -102,26 +102,6 @@ def validate_int(b):
102
102
  return int(b)
103
103
 
104
104
 
105
- def validate_open_enum(is_int: bool):
106
- def validate(e):
107
- if e is None:
108
- return None
109
-
110
- if isinstance(e, Unset):
111
- return e
112
-
113
- if is_int:
114
- if not isinstance(e, int):
115
- raise ValueError("Expected int")
116
- else:
117
- if not isinstance(e, str):
118
- raise ValueError("Expected string")
119
-
120
- return e
121
-
122
- return validate
123
-
124
-
125
105
  def validate_const(v):
126
106
  def validate(c):
127
107
  # Optional[T] is a Union[T, None]
@@ -1,12 +1,26 @@
1
1
  """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
2
 
3
- from typing import Any, Optional
3
+ from typing import Any, Optional, Type, TypeVar, overload
4
4
 
5
5
  import httpx
6
6
 
7
7
  from .serializers import unmarshal_json
8
8
  from mistralai_azure import models
9
9
 
10
+ T = TypeVar("T")
11
+
12
+
13
+ @overload
14
+ def unmarshal_json_response(
15
+ typ: Type[T], http_res: httpx.Response, body: Optional[str] = None
16
+ ) -> T: ...
17
+
18
+
19
+ @overload
20
+ def unmarshal_json_response(
21
+ typ: Any, http_res: httpx.Response, body: Optional[str] = None
22
+ ) -> Any: ...
23
+
10
24
 
11
25
  def unmarshal_json_response(
12
26
  typ: Any, http_res: httpx.Response, body: Optional[str] = None
mistralai_gcp/_version.py CHANGED
@@ -3,10 +3,10 @@
3
3
  import importlib.metadata
4
4
 
5
5
  __title__: str = "mistralai-gcp"
6
- __version__: str = "1.7.0"
6
+ __version__: str = "1.8.0"
7
7
  __openapi_doc_version__: str = "1.0.0"
8
- __gen_version__: str = "2.687.13"
9
- __user_agent__: str = "speakeasy-sdk/python 1.7.0 2.687.13 1.0.0 mistralai-gcp"
8
+ __gen_version__: str = "2.794.1"
9
+ __user_agent__: str = "speakeasy-sdk/python 1.8.0 2.794.1 1.0.0 mistralai-gcp"
10
10
 
11
11
  try:
12
12
  if __package__ is not None:
mistralai_gcp/basesdk.py CHANGED
@@ -60,6 +60,7 @@ class BaseSDK:
60
60
  ] = None,
61
61
  url_override: Optional[str] = None,
62
62
  http_headers: Optional[Mapping[str, str]] = None,
63
+ allow_empty_value: Optional[List[str]] = None,
63
64
  ) -> httpx.Request:
64
65
  client = self.sdk_configuration.async_client
65
66
  return self._build_request_with_client(
@@ -80,6 +81,7 @@ class BaseSDK:
80
81
  get_serialized_body,
81
82
  url_override,
82
83
  http_headers,
84
+ allow_empty_value,
83
85
  )
84
86
 
85
87
  def _build_request(
@@ -102,6 +104,7 @@ class BaseSDK:
102
104
  ] = None,
103
105
  url_override: Optional[str] = None,
104
106
  http_headers: Optional[Mapping[str, str]] = None,
107
+ allow_empty_value: Optional[List[str]] = None,
105
108
  ) -> httpx.Request:
106
109
  client = self.sdk_configuration.client
107
110
  return self._build_request_with_client(
@@ -122,6 +125,7 @@ class BaseSDK:
122
125
  get_serialized_body,
123
126
  url_override,
124
127
  http_headers,
128
+ allow_empty_value,
125
129
  )
126
130
 
127
131
  def _build_request_with_client(
@@ -145,6 +149,7 @@ class BaseSDK:
145
149
  ] = None,
146
150
  url_override: Optional[str] = None,
147
151
  http_headers: Optional[Mapping[str, str]] = None,
152
+ allow_empty_value: Optional[List[str]] = None,
148
153
  ) -> httpx.Request:
149
154
  query_params = {}
150
155
 
@@ -160,6 +165,7 @@ class BaseSDK:
160
165
  query_params = utils.get_query_params(
161
166
  request if request_has_query_params else None,
162
167
  _globals if request_has_query_params else None,
168
+ allow_empty_value,
163
169
  )
164
170
  else:
165
171
  # Pick up the query parameter from the override so they can be
mistralai_gcp/chat.py CHANGED
@@ -6,7 +6,7 @@ from mistralai_gcp._hooks import HookContext
6
6
  from mistralai_gcp.types import OptionalNullable, UNSET
7
7
  from mistralai_gcp.utils import eventstreaming
8
8
  from mistralai_gcp.utils.unmarshal_json_response import unmarshal_json_response
9
- from typing import Any, List, Mapping, Optional, Union
9
+ from typing import Any, Dict, List, Mapping, Optional, Union
10
10
 
11
11
 
12
12
  class Chat(BaseSDK):
@@ -23,6 +23,7 @@ class Chat(BaseSDK):
23
23
  stream: Optional[bool] = True,
24
24
  stop: Optional[Union[models.Stop, models.StopTypedDict]] = None,
25
25
  random_seed: OptionalNullable[int] = UNSET,
26
+ metadata: OptionalNullable[Dict[str, Any]] = UNSET,
26
27
  response_format: Optional[
27
28
  Union[models.ResponseFormat, models.ResponseFormatTypedDict]
28
29
  ] = None,
@@ -47,7 +48,7 @@ class Chat(BaseSDK):
47
48
  server_url: Optional[str] = None,
48
49
  timeout_ms: Optional[int] = None,
49
50
  http_headers: Optional[Mapping[str, str]] = None,
50
- ) -> Optional[eventstreaming.EventStream[models.CompletionEvent]]:
51
+ ) -> eventstreaming.EventStream[models.CompletionEvent]:
51
52
  r"""Stream chat completion
52
53
 
53
54
  Mistral AI provides the ability to stream responses back to a client in order to allow partial results for certain requests. Tokens will be sent as data-only server-sent events as they become available, with the stream terminated by a data: [DONE] message. Otherwise, the server will hold the request open until the timeout or until completion, with the response containing the full result as JSON.
@@ -60,6 +61,7 @@ class Chat(BaseSDK):
60
61
  :param stream:
61
62
  :param stop: Stop generation if this token is detected. Or if one of these tokens is detected when providing an array
62
63
  :param random_seed: The seed to use for random sampling. If set, different calls will generate deterministic results.
64
+ :param metadata:
63
65
  :param response_format: Specify the format that the model must output. By default it will use `{ \"type\": \"text\" }`. Setting to `{ \"type\": \"json_object\" }` enables JSON mode, which guarantees the message the model generates is in JSON. When using JSON mode you MUST also instruct the model to produce JSON yourself with a system or a user message. Setting to `{ \"type\": \"json_schema\" }` enables JSON schema mode, which guarantees the message the model generates is in JSON and follows the schema you provide.
64
66
  :param tools: A list of tools the model may call. Use this to provide a list of functions the model may generate JSON inputs for.
65
67
  :param tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `any` or `required` means the model must call one or more tools. Specifying a particular tool via `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.
@@ -92,6 +94,7 @@ class Chat(BaseSDK):
92
94
  stream=stream,
93
95
  stop=stop,
94
96
  random_seed=random_seed,
97
+ metadata=metadata,
95
98
  messages=utils.get_pydantic_model(messages, List[models.Messages]),
96
99
  response_format=utils.get_pydantic_model(
97
100
  response_format, Optional[models.ResponseFormat]
@@ -126,6 +129,7 @@ class Chat(BaseSDK):
126
129
  get_serialized_body=lambda: utils.serialize_request_body(
127
130
  request, False, False, "json", models.ChatCompletionStreamRequest
128
131
  ),
132
+ allow_empty_value=None,
129
133
  timeout_ms=timeout_ms,
130
134
  )
131
135
 
@@ -142,7 +146,7 @@ class Chat(BaseSDK):
142
146
  config=self.sdk_configuration,
143
147
  base_url=base_url or "",
144
148
  operation_id="stream_chat",
145
- oauth2_scopes=[],
149
+ oauth2_scopes=None,
146
150
  security_source=self.sdk_configuration.security,
147
151
  ),
148
152
  request=req,
@@ -186,6 +190,7 @@ class Chat(BaseSDK):
186
190
  stream: Optional[bool] = True,
187
191
  stop: Optional[Union[models.Stop, models.StopTypedDict]] = None,
188
192
  random_seed: OptionalNullable[int] = UNSET,
193
+ metadata: OptionalNullable[Dict[str, Any]] = UNSET,
189
194
  response_format: Optional[
190
195
  Union[models.ResponseFormat, models.ResponseFormatTypedDict]
191
196
  ] = None,
@@ -210,7 +215,7 @@ class Chat(BaseSDK):
210
215
  server_url: Optional[str] = None,
211
216
  timeout_ms: Optional[int] = None,
212
217
  http_headers: Optional[Mapping[str, str]] = None,
213
- ) -> Optional[eventstreaming.EventStreamAsync[models.CompletionEvent]]:
218
+ ) -> eventstreaming.EventStreamAsync[models.CompletionEvent]:
214
219
  r"""Stream chat completion
215
220
 
216
221
  Mistral AI provides the ability to stream responses back to a client in order to allow partial results for certain requests. Tokens will be sent as data-only server-sent events as they become available, with the stream terminated by a data: [DONE] message. Otherwise, the server will hold the request open until the timeout or until completion, with the response containing the full result as JSON.
@@ -223,6 +228,7 @@ class Chat(BaseSDK):
223
228
  :param stream:
224
229
  :param stop: Stop generation if this token is detected. Or if one of these tokens is detected when providing an array
225
230
  :param random_seed: The seed to use for random sampling. If set, different calls will generate deterministic results.
231
+ :param metadata:
226
232
  :param response_format: Specify the format that the model must output. By default it will use `{ \"type\": \"text\" }`. Setting to `{ \"type\": \"json_object\" }` enables JSON mode, which guarantees the message the model generates is in JSON. When using JSON mode you MUST also instruct the model to produce JSON yourself with a system or a user message. Setting to `{ \"type\": \"json_schema\" }` enables JSON schema mode, which guarantees the message the model generates is in JSON and follows the schema you provide.
227
233
  :param tools: A list of tools the model may call. Use this to provide a list of functions the model may generate JSON inputs for.
228
234
  :param tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `any` or `required` means the model must call one or more tools. Specifying a particular tool via `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.
@@ -255,6 +261,7 @@ class Chat(BaseSDK):
255
261
  stream=stream,
256
262
  stop=stop,
257
263
  random_seed=random_seed,
264
+ metadata=metadata,
258
265
  messages=utils.get_pydantic_model(messages, List[models.Messages]),
259
266
  response_format=utils.get_pydantic_model(
260
267
  response_format, Optional[models.ResponseFormat]
@@ -289,6 +296,7 @@ class Chat(BaseSDK):
289
296
  get_serialized_body=lambda: utils.serialize_request_body(
290
297
  request, False, False, "json", models.ChatCompletionStreamRequest
291
298
  ),
299
+ allow_empty_value=None,
292
300
  timeout_ms=timeout_ms,
293
301
  )
294
302
 
@@ -305,7 +313,7 @@ class Chat(BaseSDK):
305
313
  config=self.sdk_configuration,
306
314
  base_url=base_url or "",
307
315
  operation_id="stream_chat",
308
- oauth2_scopes=[],
316
+ oauth2_scopes=None,
309
317
  security_source=self.sdk_configuration.security,
310
318
  ),
311
319
  request=req,
@@ -357,6 +365,7 @@ class Chat(BaseSDK):
357
365
  ]
358
366
  ] = None,
359
367
  random_seed: OptionalNullable[int] = UNSET,
368
+ metadata: OptionalNullable[Dict[str, Any]] = UNSET,
360
369
  response_format: Optional[
361
370
  Union[models.ResponseFormat, models.ResponseFormatTypedDict]
362
371
  ] = None,
@@ -381,7 +390,7 @@ class Chat(BaseSDK):
381
390
  server_url: Optional[str] = None,
382
391
  timeout_ms: Optional[int] = None,
383
392
  http_headers: Optional[Mapping[str, str]] = None,
384
- ) -> Optional[models.ChatCompletionResponse]:
393
+ ) -> models.ChatCompletionResponse:
385
394
  r"""Chat Completion
386
395
 
387
396
  :param model: ID of the model to use. You can use the [List Available Models](/api/#tag/models/operation/list_models_v1_models_get) API to see all of your available models, or see our [Model overview](/models) for model descriptions.
@@ -392,6 +401,7 @@ class Chat(BaseSDK):
392
401
  :param stream: Whether to stream back partial progress. If set, tokens will be sent as data-only server-side events as they become available, with the stream terminated by a data: [DONE] message. Otherwise, the server will hold the request open until the timeout or until completion, with the response containing the full result as JSON.
393
402
  :param stop: Stop generation if this token is detected. Or if one of these tokens is detected when providing an array
394
403
  :param random_seed: The seed to use for random sampling. If set, different calls will generate deterministic results.
404
+ :param metadata:
395
405
  :param response_format: Specify the format that the model must output. By default it will use `{ \"type\": \"text\" }`. Setting to `{ \"type\": \"json_object\" }` enables JSON mode, which guarantees the message the model generates is in JSON. When using JSON mode you MUST also instruct the model to produce JSON yourself with a system or a user message. Setting to `{ \"type\": \"json_schema\" }` enables JSON schema mode, which guarantees the message the model generates is in JSON and follows the schema you provide.
396
406
  :param tools: A list of tools the model may call. Use this to provide a list of functions the model may generate JSON inputs for.
397
407
  :param tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `any` or `required` means the model must call one or more tools. Specifying a particular tool via `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.
@@ -424,6 +434,7 @@ class Chat(BaseSDK):
424
434
  stream=stream,
425
435
  stop=stop,
426
436
  random_seed=random_seed,
437
+ metadata=metadata,
427
438
  messages=utils.get_pydantic_model(
428
439
  messages, List[models.ChatCompletionRequestMessages]
429
440
  ),
@@ -460,6 +471,7 @@ class Chat(BaseSDK):
460
471
  get_serialized_body=lambda: utils.serialize_request_body(
461
472
  request, False, False, "json", models.ChatCompletionRequest
462
473
  ),
474
+ allow_empty_value=None,
463
475
  timeout_ms=timeout_ms,
464
476
  )
465
477
 
@@ -476,7 +488,7 @@ class Chat(BaseSDK):
476
488
  config=self.sdk_configuration,
477
489
  base_url=base_url or "",
478
490
  operation_id="chat_completion_v1_chat_completions_post",
479
- oauth2_scopes=[],
491
+ oauth2_scopes=None,
480
492
  security_source=self.sdk_configuration.security,
481
493
  ),
482
494
  request=req,
@@ -486,9 +498,7 @@ class Chat(BaseSDK):
486
498
 
487
499
  response_data: Any = None
488
500
  if utils.match_response(http_res, "200", "application/json"):
489
- return unmarshal_json_response(
490
- Optional[models.ChatCompletionResponse], http_res
491
- )
501
+ return unmarshal_json_response(models.ChatCompletionResponse, http_res)
492
502
  if utils.match_response(http_res, "422", "application/json"):
493
503
  response_data = unmarshal_json_response(
494
504
  models.HTTPValidationErrorData, http_res
@@ -522,6 +532,7 @@ class Chat(BaseSDK):
522
532
  ]
523
533
  ] = None,
524
534
  random_seed: OptionalNullable[int] = UNSET,
535
+ metadata: OptionalNullable[Dict[str, Any]] = UNSET,
525
536
  response_format: Optional[
526
537
  Union[models.ResponseFormat, models.ResponseFormatTypedDict]
527
538
  ] = None,
@@ -546,7 +557,7 @@ class Chat(BaseSDK):
546
557
  server_url: Optional[str] = None,
547
558
  timeout_ms: Optional[int] = None,
548
559
  http_headers: Optional[Mapping[str, str]] = None,
549
- ) -> Optional[models.ChatCompletionResponse]:
560
+ ) -> models.ChatCompletionResponse:
550
561
  r"""Chat Completion
551
562
 
552
563
  :param model: ID of the model to use. You can use the [List Available Models](/api/#tag/models/operation/list_models_v1_models_get) API to see all of your available models, or see our [Model overview](/models) for model descriptions.
@@ -557,6 +568,7 @@ class Chat(BaseSDK):
557
568
  :param stream: Whether to stream back partial progress. If set, tokens will be sent as data-only server-side events as they become available, with the stream terminated by a data: [DONE] message. Otherwise, the server will hold the request open until the timeout or until completion, with the response containing the full result as JSON.
558
569
  :param stop: Stop generation if this token is detected. Or if one of these tokens is detected when providing an array
559
570
  :param random_seed: The seed to use for random sampling. If set, different calls will generate deterministic results.
571
+ :param metadata:
560
572
  :param response_format: Specify the format that the model must output. By default it will use `{ \"type\": \"text\" }`. Setting to `{ \"type\": \"json_object\" }` enables JSON mode, which guarantees the message the model generates is in JSON. When using JSON mode you MUST also instruct the model to produce JSON yourself with a system or a user message. Setting to `{ \"type\": \"json_schema\" }` enables JSON schema mode, which guarantees the message the model generates is in JSON and follows the schema you provide.
561
573
  :param tools: A list of tools the model may call. Use this to provide a list of functions the model may generate JSON inputs for.
562
574
  :param tool_choice: Controls which (if any) tool is called by the model. `none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `any` or `required` means the model must call one or more tools. Specifying a particular tool via `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.
@@ -589,6 +601,7 @@ class Chat(BaseSDK):
589
601
  stream=stream,
590
602
  stop=stop,
591
603
  random_seed=random_seed,
604
+ metadata=metadata,
592
605
  messages=utils.get_pydantic_model(
593
606
  messages, List[models.ChatCompletionRequestMessages]
594
607
  ),
@@ -625,6 +638,7 @@ class Chat(BaseSDK):
625
638
  get_serialized_body=lambda: utils.serialize_request_body(
626
639
  request, False, False, "json", models.ChatCompletionRequest
627
640
  ),
641
+ allow_empty_value=None,
628
642
  timeout_ms=timeout_ms,
629
643
  )
630
644
 
@@ -641,7 +655,7 @@ class Chat(BaseSDK):
641
655
  config=self.sdk_configuration,
642
656
  base_url=base_url or "",
643
657
  operation_id="chat_completion_v1_chat_completions_post",
644
- oauth2_scopes=[],
658
+ oauth2_scopes=None,
645
659
  security_source=self.sdk_configuration.security,
646
660
  ),
647
661
  request=req,
@@ -651,9 +665,7 @@ class Chat(BaseSDK):
651
665
 
652
666
  response_data: Any = None
653
667
  if utils.match_response(http_res, "200", "application/json"):
654
- return unmarshal_json_response(
655
- Optional[models.ChatCompletionResponse], http_res
656
- )
668
+ return unmarshal_json_response(models.ChatCompletionResponse, http_res)
657
669
  if utils.match_response(http_res, "422", "application/json"):
658
670
  response_data = unmarshal_json_response(
659
671
  models.HTTPValidationErrorData, http_res