dashscope 1.8.0__py3-none-any.whl → 1.25.6__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 (110) hide show
  1. dashscope/__init__.py +61 -14
  2. dashscope/aigc/__init__.py +10 -3
  3. dashscope/aigc/chat_completion.py +282 -0
  4. dashscope/aigc/code_generation.py +145 -0
  5. dashscope/aigc/conversation.py +71 -12
  6. dashscope/aigc/generation.py +288 -16
  7. dashscope/aigc/image_synthesis.py +473 -31
  8. dashscope/aigc/multimodal_conversation.py +299 -14
  9. dashscope/aigc/video_synthesis.py +610 -0
  10. dashscope/api_entities/aiohttp_request.py +8 -5
  11. dashscope/api_entities/api_request_data.py +4 -2
  12. dashscope/api_entities/api_request_factory.py +68 -20
  13. dashscope/api_entities/base_request.py +20 -3
  14. dashscope/api_entities/chat_completion_types.py +344 -0
  15. dashscope/api_entities/dashscope_response.py +243 -15
  16. dashscope/api_entities/encryption.py +179 -0
  17. dashscope/api_entities/http_request.py +216 -62
  18. dashscope/api_entities/websocket_request.py +43 -34
  19. dashscope/app/__init__.py +5 -0
  20. dashscope/app/application.py +203 -0
  21. dashscope/app/application_response.py +246 -0
  22. dashscope/assistants/__init__.py +16 -0
  23. dashscope/assistants/assistant_types.py +175 -0
  24. dashscope/assistants/assistants.py +311 -0
  25. dashscope/assistants/files.py +197 -0
  26. dashscope/audio/__init__.py +4 -2
  27. dashscope/audio/asr/__init__.py +17 -1
  28. dashscope/audio/asr/asr_phrase_manager.py +203 -0
  29. dashscope/audio/asr/recognition.py +167 -27
  30. dashscope/audio/asr/transcription.py +107 -14
  31. dashscope/audio/asr/translation_recognizer.py +1006 -0
  32. dashscope/audio/asr/vocabulary.py +177 -0
  33. dashscope/audio/qwen_asr/__init__.py +7 -0
  34. dashscope/audio/qwen_asr/qwen_transcription.py +189 -0
  35. dashscope/audio/qwen_omni/__init__.py +11 -0
  36. dashscope/audio/qwen_omni/omni_realtime.py +524 -0
  37. dashscope/audio/qwen_tts/__init__.py +5 -0
  38. dashscope/audio/qwen_tts/speech_synthesizer.py +77 -0
  39. dashscope/audio/qwen_tts_realtime/__init__.py +10 -0
  40. dashscope/audio/qwen_tts_realtime/qwen_tts_realtime.py +355 -0
  41. dashscope/audio/tts/__init__.py +2 -0
  42. dashscope/audio/tts/speech_synthesizer.py +5 -0
  43. dashscope/audio/tts_v2/__init__.py +12 -0
  44. dashscope/audio/tts_v2/enrollment.py +179 -0
  45. dashscope/audio/tts_v2/speech_synthesizer.py +886 -0
  46. dashscope/cli.py +157 -37
  47. dashscope/client/base_api.py +652 -87
  48. dashscope/common/api_key.py +2 -0
  49. dashscope/common/base_type.py +135 -0
  50. dashscope/common/constants.py +13 -16
  51. dashscope/common/env.py +2 -0
  52. dashscope/common/error.py +58 -22
  53. dashscope/common/logging.py +2 -0
  54. dashscope/common/message_manager.py +2 -0
  55. dashscope/common/utils.py +276 -46
  56. dashscope/customize/__init__.py +0 -0
  57. dashscope/customize/customize_types.py +192 -0
  58. dashscope/customize/deployments.py +146 -0
  59. dashscope/customize/finetunes.py +234 -0
  60. dashscope/embeddings/__init__.py +5 -1
  61. dashscope/embeddings/batch_text_embedding.py +208 -0
  62. dashscope/embeddings/batch_text_embedding_response.py +65 -0
  63. dashscope/embeddings/multimodal_embedding.py +118 -10
  64. dashscope/embeddings/text_embedding.py +13 -1
  65. dashscope/{file.py → files.py} +19 -4
  66. dashscope/io/input_output.py +2 -0
  67. dashscope/model.py +11 -2
  68. dashscope/models.py +43 -0
  69. dashscope/multimodal/__init__.py +20 -0
  70. dashscope/multimodal/dialog_state.py +56 -0
  71. dashscope/multimodal/multimodal_constants.py +28 -0
  72. dashscope/multimodal/multimodal_dialog.py +648 -0
  73. dashscope/multimodal/multimodal_request_params.py +313 -0
  74. dashscope/multimodal/tingwu/__init__.py +10 -0
  75. dashscope/multimodal/tingwu/tingwu.py +80 -0
  76. dashscope/multimodal/tingwu/tingwu_realtime.py +579 -0
  77. dashscope/nlp/__init__.py +0 -0
  78. dashscope/nlp/understanding.py +64 -0
  79. dashscope/protocol/websocket.py +3 -0
  80. dashscope/rerank/__init__.py +0 -0
  81. dashscope/rerank/text_rerank.py +69 -0
  82. dashscope/resources/qwen.tiktoken +151643 -0
  83. dashscope/threads/__init__.py +26 -0
  84. dashscope/threads/messages/__init__.py +0 -0
  85. dashscope/threads/messages/files.py +113 -0
  86. dashscope/threads/messages/messages.py +220 -0
  87. dashscope/threads/runs/__init__.py +0 -0
  88. dashscope/threads/runs/runs.py +501 -0
  89. dashscope/threads/runs/steps.py +112 -0
  90. dashscope/threads/thread_types.py +665 -0
  91. dashscope/threads/threads.py +212 -0
  92. dashscope/tokenizers/__init__.py +7 -0
  93. dashscope/tokenizers/qwen_tokenizer.py +111 -0
  94. dashscope/tokenizers/tokenization.py +125 -0
  95. dashscope/tokenizers/tokenizer.py +45 -0
  96. dashscope/tokenizers/tokenizer_base.py +32 -0
  97. dashscope/utils/__init__.py +0 -0
  98. dashscope/utils/message_utils.py +838 -0
  99. dashscope/utils/oss_utils.py +243 -0
  100. dashscope/utils/param_utils.py +29 -0
  101. dashscope/version.py +3 -1
  102. {dashscope-1.8.0.dist-info → dashscope-1.25.6.dist-info}/METADATA +53 -50
  103. dashscope-1.25.6.dist-info/RECORD +112 -0
  104. {dashscope-1.8.0.dist-info → dashscope-1.25.6.dist-info}/WHEEL +1 -1
  105. {dashscope-1.8.0.dist-info → dashscope-1.25.6.dist-info}/entry_points.txt +0 -1
  106. {dashscope-1.8.0.dist-info → dashscope-1.25.6.dist-info/licenses}/LICENSE +2 -4
  107. dashscope/deployment.py +0 -129
  108. dashscope/finetune.py +0 -149
  109. dashscope-1.8.0.dist-info/RECORD +0 -49
  110. {dashscope-1.8.0.dist-info → dashscope-1.25.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,665 @@
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+
3
+ # adapter from openai sdk
4
+ # yapf: disable
5
+ from dataclasses import dataclass
6
+ from typing import Dict, List, Literal, Optional, Union
7
+
8
+ from dashscope.assistants.assistant_types import (
9
+ Tool, convert_tools_dict_to_objects)
10
+ from dashscope.common.base_type import BaseList, BaseObjectMixin
11
+
12
+ __all__ = [
13
+ 'MessageFile', 'MessageFileList', 'Usage', 'ImageFile',
14
+ 'MessageContentImageFile', 'Text', 'MessageContentText', 'ThreadMessage',
15
+ 'ThreadMessageList', 'Thread', 'Function',
16
+ 'RequiredActionFunctionToolCall', 'RequiredActionSubmitToolOutputs',
17
+ 'RequiredAction', 'LastError', 'Run', 'RunList', 'MessageCreation',
18
+ 'MessageCreationStepDetails', 'CodeInterpreterOutputLogs',
19
+ 'CodeInterpreterOutputImageImage', 'CodeInterpreterOutputImage',
20
+ 'CodeInterpreter', 'CodeToolCall', 'RetrievalToolCall', 'FunctionToolCall',
21
+ 'ToolCallsStepDetails', 'RunStep', 'RunStepList'
22
+ ]
23
+
24
+
25
+ @dataclass(init=False)
26
+ class MessageFile(BaseObjectMixin):
27
+ id: str
28
+ message_id: str
29
+ created_at: int
30
+ object: str
31
+
32
+ def __init__(self, **kwargs):
33
+ super().__init__(**kwargs)
34
+
35
+
36
+ @dataclass(init=False)
37
+ class MessageFileList(BaseList):
38
+ data: List[MessageFile]
39
+
40
+ def __init__(self, **kwargs):
41
+ super().__init__(**kwargs)
42
+
43
+
44
+ @dataclass(init=False)
45
+ class Usage(BaseObjectMixin):
46
+ completion_tokens: int
47
+ """Number of completion tokens used over the course of the run."""
48
+
49
+ prompt_tokens: int
50
+ """Number of prompt tokens used over the course of the run."""
51
+
52
+ total_tokens: int
53
+ """Total number of tokens used (prompt + completion)."""
54
+
55
+ input_tokens: int
56
+ """Input tokens used (prompt)."""
57
+
58
+ output_tokens: int
59
+ """Output tokens used (completion)."""
60
+
61
+ def __init__(self, **kwargs):
62
+ super().__init__(**kwargs)
63
+
64
+
65
+ @dataclass(init=False)
66
+ class ImageFile(BaseObjectMixin):
67
+ file_id: str
68
+
69
+ def __init__(self, file_id, **kwargs):
70
+ super().__init__(**kwargs)
71
+
72
+
73
+ @dataclass(init=False)
74
+ class MessageContentImageFile(BaseObjectMixin):
75
+ type: str = 'image_file'
76
+ image_file: ImageFile
77
+
78
+ def __init__(self, **kwargs):
79
+ self.image_file = ImageFile(**kwargs.pop(self.type, {}))
80
+ super().__init__(**kwargs)
81
+
82
+
83
+ TextAnnotation = Union[Dict]
84
+
85
+
86
+ @dataclass(init=False)
87
+ class Text(BaseObjectMixin):
88
+ annotations: List[TextAnnotation]
89
+ value: str
90
+
91
+ def __init__(self, **kwargs):
92
+ annotations = kwargs.pop('annotations', None)
93
+ if annotations:
94
+ self.annotations = []
95
+ for annotation in annotations:
96
+ self.annotations.append(annotation)
97
+ else:
98
+ self.annotations = annotations
99
+ super().__init__(**kwargs)
100
+
101
+
102
+ @dataclass(init=False)
103
+ class MessageContentText(BaseObjectMixin):
104
+ text: Text
105
+ type: str = 'text'
106
+
107
+ def __init__(self, **kwargs):
108
+ input_text = kwargs.pop('text', {})
109
+ if input_text:
110
+ self.text = Text(**input_text)
111
+ super().__init__(**kwargs)
112
+
113
+
114
+ MESSAGE_SUPPORT_CONTENT = {
115
+ 'text': MessageContentText,
116
+ 'image_file': MessageContentImageFile,
117
+ }
118
+
119
+ Content = Union[MessageContentImageFile, MessageContentText]
120
+
121
+
122
+ @dataclass(init=False)
123
+ class ThreadMessageDeltaContent(BaseObjectMixin):
124
+ content: Content
125
+ role: str
126
+
127
+ def __init__(self, **kwargs):
128
+ contents = kwargs.pop('content', None)
129
+ if contents:
130
+ for item in contents:
131
+ if item['type'] == 'text':
132
+ self.content = MessageContentText(**item)
133
+ elif item['type'] == 'image_file':
134
+ self.content = MessageContentImageFile(**item)
135
+ else:
136
+ self.content = item
137
+ else:
138
+ self.content = contents
139
+ super().__init__(**kwargs)
140
+
141
+
142
+ @dataclass(init=False)
143
+ class ThreadMessageDelta(BaseObjectMixin):
144
+ status_code: int
145
+ id: str
146
+ object: str = 'thread.message.delta'
147
+ delta: ThreadMessageDeltaContent
148
+
149
+ def __init__(self, **kwargs):
150
+ content = kwargs.pop('delta', None)
151
+ if content:
152
+ self.delta = ThreadMessageDeltaContent(**content)
153
+ else:
154
+ self.delta = None
155
+ super().__init__(**kwargs)
156
+
157
+
158
+ @dataclass(init=False)
159
+ class ThreadMessage(BaseObjectMixin):
160
+ status_code: int
161
+ id: str
162
+ created_at: int
163
+ thread_id: str
164
+ role: str
165
+ content: List[Content]
166
+ metadata: Optional[object] = None
167
+ object: str = 'thread.message'
168
+ assistant_id: Optional[str] = None
169
+ file_ids: List[str] = None
170
+ run_id: Optional[str] = None
171
+
172
+ def __init__(self, **kwargs):
173
+ input_content = kwargs.pop('content', None)
174
+ if input_content:
175
+ content_list = []
176
+ for content in input_content:
177
+ if 'type' in content:
178
+ content_type = MESSAGE_SUPPORT_CONTENT.get(
179
+ content['type'], None)
180
+ if content_type:
181
+ content_list.append(content_type(**content))
182
+ else:
183
+ content_list.append(content)
184
+ else:
185
+ content_list.append(content)
186
+ self.content = content_list
187
+ else:
188
+ self.content = input_content
189
+
190
+ super().__init__(**kwargs)
191
+
192
+
193
+ @dataclass(init=False)
194
+ class ThreadMessageList(BaseList):
195
+ data: List[ThreadMessage]
196
+
197
+ def __init__(self,
198
+ has_more: bool = None,
199
+ last_id: Optional[str] = None,
200
+ first_id: Optional[str] = None,
201
+ data: List[ThreadMessage] = [],
202
+ **kwargs):
203
+ super().__init__(has_more=has_more,
204
+ last_id=last_id,
205
+ first_id=first_id,
206
+ data=data,
207
+ **kwargs)
208
+
209
+
210
+ @dataclass(init=False)
211
+ class Thread(BaseObjectMixin):
212
+ status_code: int
213
+ id: str
214
+ created_at: int
215
+ metadata: Optional[object] = None
216
+ object: str = 'thread'
217
+
218
+ def __init__(self, **kwargs):
219
+ super().__init__(**kwargs)
220
+
221
+
222
+ @dataclass(init=False)
223
+ class Function(BaseObjectMixin):
224
+ arguments: str
225
+ name: str
226
+ output: Optional[str] = None
227
+
228
+ def __init__(self, **kwargs):
229
+ super().__init__(**kwargs)
230
+
231
+
232
+ @dataclass(init=False)
233
+ class RequiredActionFunctionToolCall(BaseObjectMixin):
234
+ id: str
235
+
236
+ function: Function
237
+
238
+ type: str = 'function'
239
+
240
+ def __init__(self, **kwargs):
241
+ self.function = Function(**kwargs.pop('function', {}))
242
+ super().__init__(**kwargs)
243
+
244
+
245
+ @dataclass(init=False)
246
+ class RequiredActionSubmitToolOutputs(BaseObjectMixin):
247
+ tool_calls: List[RequiredActionFunctionToolCall]
248
+
249
+ def __init__(self, **kwargs):
250
+ tcs = kwargs.pop('tool_calls', [])
251
+ if tcs:
252
+ self.tool_calls = []
253
+ for tc in tcs:
254
+ self.tool_calls.append(RequiredActionFunctionToolCall(**tc))
255
+ else:
256
+ self.tool_calls = tcs
257
+ super().__init__(**kwargs)
258
+
259
+
260
+ @dataclass(init=False)
261
+ class RequiredAction(BaseObjectMixin):
262
+ submit_tool_outputs: RequiredActionSubmitToolOutputs
263
+
264
+ type: Literal['submit_tool_outputs']
265
+
266
+ def __init__(self, **kwargs):
267
+ self.submit_tool_outputs = RequiredActionSubmitToolOutputs(
268
+ **kwargs.pop('submit_tool_outputs', {}))
269
+ super().__init__(**kwargs)
270
+
271
+
272
+ @dataclass(init=False)
273
+ class LastError(BaseObjectMixin):
274
+ code: Literal['server_error', 'rate_limit_exceeded']
275
+ message: str
276
+
277
+ def __init__(self, **kwargs):
278
+ super().__init__(**kwargs)
279
+
280
+
281
+ @dataclass(init=False)
282
+ class Run(BaseObjectMixin):
283
+ status_code: int
284
+ id: str
285
+ assistant_id: str
286
+ cancelled_at: Optional[int] = None
287
+ completed_at: Optional[int] = None
288
+ created_at: int = None
289
+ expires_at: int = None
290
+ failed_at: Optional[int] = None
291
+ file_ids: List[str] = None
292
+
293
+ instructions: str = None
294
+
295
+ metadata: Optional[object] = None
296
+ last_error: Optional[LastError] = None
297
+ model: str = None
298
+
299
+ object: str = 'thread.run'
300
+
301
+ required_action: Optional[RequiredAction] = None
302
+
303
+ started_at: Optional[int] = None
304
+
305
+ status: Literal['queued', 'in_progress', 'requires_action', 'cancelling',
306
+ 'cancelled', 'failed', 'completed', 'expired']
307
+
308
+ thread_id: str
309
+
310
+ tools: List[Tool]
311
+
312
+ top_p: Optional[float] = None
313
+ top_k: Optional[int] = None
314
+ temperature: Optional[float] = None
315
+ max_tokens: Optional[int] = None
316
+
317
+ usage: Optional[Usage] = None
318
+
319
+ def __init__(self, **kwargs):
320
+ self.tools = convert_tools_dict_to_objects(kwargs.pop('tools', []))
321
+ actions = kwargs.pop('required_action', None)
322
+ if actions:
323
+ self.required_action = RequiredAction(**actions)
324
+ else:
325
+ self.required_action = actions
326
+
327
+ super().__init__(**kwargs)
328
+
329
+
330
+ @dataclass(init=False)
331
+ class RunList(BaseObjectMixin):
332
+ data: List[Run]
333
+
334
+ def __init__(self,
335
+ has_more: bool = None,
336
+ last_id: Optional[str] = None,
337
+ first_id: Optional[str] = None,
338
+ data: List[Run] = [],
339
+ **kwargs):
340
+ super().__init__(has_more=has_more,
341
+ last_id=last_id,
342
+ first_id=first_id,
343
+ data=data,
344
+ **kwargs)
345
+
346
+
347
+ @dataclass(init=False)
348
+ class MessageCreation(BaseObjectMixin):
349
+ message_id: str
350
+ """The ID of the message that was created by this run step."""
351
+ def __init__(self, **kwargs):
352
+ super().__init__(**kwargs)
353
+
354
+
355
+ @dataclass(init=False)
356
+ class MessageCreationStepDetails(BaseObjectMixin):
357
+ message_creation: MessageCreation
358
+
359
+ type: Literal['message_creation']
360
+ """Always `message_creation`."""
361
+ def __init__(self, **kwargs):
362
+ super().__init__(**kwargs)
363
+
364
+
365
+ @dataclass(init=False)
366
+ class CodeInterpreterOutputLogs(BaseObjectMixin):
367
+ logs: str
368
+ """The text output from the Code Interpreter tool call."""
369
+
370
+ type: Literal['logs']
371
+ """Always `logs`."""
372
+ def __init__(self, **kwargs):
373
+ super().__init__(**kwargs)
374
+
375
+
376
+ @dataclass(init=False)
377
+ class CodeInterpreterOutputImageImage(BaseObjectMixin):
378
+ file_id: str
379
+ """
380
+ The [file](https://platform.openai.com/docs/api-reference/files) ID of the
381
+ image.
382
+ """
383
+ def __init__(self, **kwargs):
384
+ super().__init__(**kwargs)
385
+
386
+
387
+ @dataclass(init=False)
388
+ class CodeInterpreterOutputImage(BaseObjectMixin):
389
+ image: CodeInterpreterOutputImageImage
390
+
391
+ type: Literal['image']
392
+ """Always `image`."""
393
+ def __init__(self, **kwargs):
394
+ self.image = CodeInterpreterOutputImageImage(**kwargs.pop('image', {}))
395
+ super().__init__(**kwargs)
396
+
397
+
398
+ CodeInterpreterOutput = Union[CodeInterpreterOutputLogs,
399
+ CodeInterpreterOutputImage]
400
+
401
+
402
+ @dataclass(init=False)
403
+ class CodeInterpreter(BaseObjectMixin):
404
+ input: str
405
+ """The input to the Code Interpreter tool call."""
406
+
407
+ outputs: List[CodeInterpreterOutput]
408
+ """The outputs from the Code Interpreter tool call.
409
+
410
+ Code Interpreter can output one or more items, including text (`logs`) or images
411
+ (`image`). Each of these are represented by a different object type.
412
+ """
413
+ def __init__(self, **kwargs):
414
+ self.outputs = []
415
+ for output in kwargs.pop('outputs', []):
416
+ self.outputs.append(CodeInterpreterOutput(**output))
417
+
418
+ super().__init__(**kwargs)
419
+
420
+
421
+ @dataclass(init=False)
422
+ class CodeToolCall(BaseObjectMixin):
423
+ id: str
424
+ """The ID of the tool call."""
425
+
426
+ code_interpreter: CodeInterpreter
427
+ """The Code Interpreter tool call definition."""
428
+
429
+ type: Literal['code_interpreter']
430
+ """The type of tool call.
431
+
432
+ This is always going to be `code_interpreter` for this type of tool call.
433
+ """
434
+ def __init__(self, **kwargs):
435
+ self.code_interpreter = CodeInterpreter(
436
+ **kwargs.pop('code_interpreter', {}))
437
+ super().__init__(**kwargs)
438
+
439
+
440
+ @dataclass(init=False)
441
+ class RetrievalToolCall(BaseObjectMixin):
442
+ id: str
443
+ """The ID of the tool call object."""
444
+
445
+ retrieval: object
446
+ """For now, this is always going to be an empty object."""
447
+
448
+ type: Literal['quark_search']
449
+ """The type of tool call.
450
+
451
+ This is always going to be `quark_search` for this type of tool call.
452
+ """
453
+ def __init__(self, **kwargs):
454
+ super().__init__(**kwargs)
455
+
456
+
457
+ @dataclass(init=False)
458
+ class FunctionToolCall(BaseObjectMixin):
459
+ id: str
460
+ """The ID of the tool call object."""
461
+
462
+ function: Function
463
+ """The definition of the function that was called."""
464
+
465
+ type: Literal['function']
466
+ """The type of tool call.
467
+
468
+ This is always going to be `function` for this type of tool call.
469
+ """
470
+ def __init__(self, **kwargs):
471
+ self.function = Function(**kwargs.pop('function', {}))
472
+ super().__init__(**kwargs)
473
+
474
+
475
+ ToolCall = Union[CodeToolCall, RetrievalToolCall, FunctionToolCall]
476
+
477
+ TOOL_CALL_TYPES = {
478
+ 'function': FunctionToolCall,
479
+ 'code_interpreter': CodeToolCall,
480
+ 'retrieval': RetrievalToolCall,
481
+ }
482
+
483
+
484
+ def convert_tool_calls_dict_to_object(tool_calls):
485
+ tool_calls_object = []
486
+ for tool_call in tool_calls:
487
+ if 'type' in tool_call:
488
+ tool_call_type = TOOL_CALL_TYPES.get(tool_call['type'], None)
489
+ if tool_call_type:
490
+ tool_calls_object.append(tool_call_type(**tool_call))
491
+ else:
492
+ tool_calls_object.append(tool_call)
493
+ else:
494
+ tool_calls_object.append(tool_call)
495
+ return tool_calls_object
496
+
497
+
498
+ @dataclass(init=False)
499
+ class ToolCallsStepDetails(BaseObjectMixin):
500
+ tool_calls: List[ToolCall]
501
+ """An array of tool calls the run step was involved in.
502
+
503
+ These can be associated with one of three types of tools: `code_interpreter`,
504
+ `retrieval`, or `function`.
505
+ """
506
+
507
+ type: Literal['tool_calls']
508
+ """Always `tool_calls`."""
509
+ def __init__(self, **kwargs):
510
+ self.tool_calls = convert_tool_calls_dict_to_object(
511
+ kwargs.pop('tool_calls', []))
512
+ super().__init__(**kwargs)
513
+
514
+
515
+ StepDetails = Union[MessageCreationStepDetails, ToolCallsStepDetails]
516
+ STEP_TYPES = {
517
+ 'tool_calls': ToolCallsStepDetails,
518
+ 'message_creation': MessageCreationStepDetails,
519
+ }
520
+
521
+
522
+ def convert_step_details_dict_to_objects(step_details):
523
+ if 'type' in step_details:
524
+ tool_type = STEP_TYPES.get(step_details['type'], None)
525
+ if tool_type:
526
+ return tool_type(**step_details)
527
+ return step_details
528
+
529
+
530
+ @dataclass(init=False)
531
+ class RunStepDeltaContent(BaseObjectMixin):
532
+ step_details: StepDetails
533
+
534
+ def __init__(self, **kwargs):
535
+ self.step_details = convert_step_details_dict_to_objects(
536
+ kwargs.pop('step_details', {}))
537
+ super().__init__(**kwargs)
538
+
539
+
540
+ @dataclass(init=False)
541
+ class RunStepDelta(BaseObjectMixin):
542
+ id: str
543
+ object: str = 'thread.run.step.delta'
544
+ delta: RunStepDeltaContent
545
+
546
+ def __init__(self, **kwargs):
547
+ delta = kwargs.pop('delta', None)
548
+ if delta:
549
+ self.delta = RunStepDeltaContent(**delta)
550
+ else:
551
+ self.delta = delta
552
+ super().__init__(**kwargs)
553
+
554
+
555
+ @dataclass(init=False)
556
+ class RunStep(BaseObjectMixin):
557
+ status_code: int = None
558
+ id: str
559
+ """The identifier of the run step, which can be referenced in API endpoints."""
560
+
561
+ assistant_id: str
562
+ """
563
+ The ID of the
564
+ [assistant](https://platform.openai.com/docs/api-reference/assistants)
565
+ associated with the run step.
566
+ """
567
+
568
+ cancelled_at: Optional[int] = None
569
+ """The Unix timestamp (in seconds) for when the run step was cancelled."""
570
+
571
+ completed_at: Optional[int] = None
572
+ """The Unix timestamp (in seconds) for when the run step completed."""
573
+
574
+ created_at: int
575
+ """The Unix timestamp (in seconds) for when the run step was created."""
576
+
577
+ expired_at: Optional[int] = None
578
+ """The Unix timestamp (in seconds) for when the run step expired.
579
+
580
+ A step is considered expired if the parent run is expired.
581
+ """
582
+
583
+ failed_at: Optional[int] = None
584
+ """The Unix timestamp (in seconds) for when the run step failed."""
585
+
586
+ last_error: Optional[LastError] = None
587
+ """The last error associated with this run step.
588
+
589
+ Will be `null` if there are no errors.
590
+ """
591
+
592
+ metadata: Optional[object] = None
593
+ """Set of 16 key-value pairs that can be attached to an object.
594
+
595
+ This can be useful for storing additional information about the object in a
596
+ structured format. Keys can be a maximum of 64 characters long and values can be
597
+ a maxium of 512 characters long.
598
+ """
599
+
600
+ object: Literal['thread.run.step']
601
+ """The object type, which is always `thread.run.step`."""
602
+
603
+ run_id: str
604
+ """
605
+ The ID of the [run](https://platform.openai.com/docs/api-reference/runs) that
606
+ this run step is a part of.
607
+ """
608
+
609
+ status: Literal['in_progress', 'cancelled', 'failed', 'completed',
610
+ 'expired']
611
+ """
612
+ The status of the run step, which can be either `in_progress`, `cancelled`,
613
+ `failed`, `completed`, or `expired`.
614
+ """
615
+
616
+ step_details: StepDetails
617
+ """The details of the run step."""
618
+
619
+ thread_id: str
620
+ """
621
+ The ID of the [thread](https://platform.openai.com/docs/api-reference/threads)
622
+ that was run.
623
+ """
624
+
625
+ type: Literal['message_creation', 'tool_calls']
626
+ """The type of run step, which can be either `message_creation` or `tool_calls`."""
627
+
628
+ usage: Optional[Usage] = None
629
+
630
+ def __init__(self, **kwargs):
631
+ self.step_details = convert_step_details_dict_to_objects(
632
+ kwargs.pop('step_details', {}))
633
+ if 'usage' in kwargs and kwargs['usage'] is not None and kwargs['usage']:
634
+ self.usage = Usage(**kwargs.pop('usage', {}))
635
+ else:
636
+ self.usage = None
637
+ last_error = kwargs.pop('last_error', None)
638
+ if last_error:
639
+ self.last_error = LastError(**last_error)
640
+ else:
641
+ last_error = last_error
642
+ super().__init__(**kwargs)
643
+
644
+
645
+ @dataclass(init=False)
646
+ class RunStepList(BaseList):
647
+ data: List[RunStep]
648
+
649
+ def __init__(self,
650
+ has_more: bool = None,
651
+ last_id: Optional[str] = None,
652
+ first_id: Optional[str] = None,
653
+ data: List[RunStep] = [],
654
+ **kwargs):
655
+ if data:
656
+ steps = []
657
+ for step in data:
658
+ steps.append(RunStep(**step))
659
+ self.data = steps
660
+ else:
661
+ self.data = []
662
+ super().__init__(has_more=has_more,
663
+ last_id=last_id,
664
+ first_id=first_id,
665
+ **kwargs)