dashscope 1.17.0__py3-none-any.whl → 1.18.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.

Potentially problematic release.


This version of dashscope might be problematic. Click here for more details.

@@ -24,6 +24,7 @@ class ImageSynthesis(BaseAsyncApi):
24
24
  images: List[str] = None,
25
25
  api_key: str = None,
26
26
  sketch_image_url: str = None,
27
+ ref_img: str = None,
27
28
  workspace: str = None,
28
29
  **kwargs) -> ImageSynthesisResponse:
29
30
  """Call image(s) synthesis service and get result.
@@ -61,6 +62,7 @@ class ImageSynthesis(BaseAsyncApi):
61
62
  images,
62
63
  api_key=api_key,
63
64
  sketch_image_url=sketch_image_url,
65
+ ref_img=ref_img,
64
66
  workspace=workspace,
65
67
  **kwargs)
66
68
 
@@ -72,6 +74,7 @@ class ImageSynthesis(BaseAsyncApi):
72
74
  images: List[str] = None,
73
75
  api_key: str = None,
74
76
  sketch_image_url: str = None,
77
+ ref_img: str = None,
75
78
  workspace: str = None,
76
79
  **kwargs) -> ImageSynthesisResponse:
77
80
  """Create a image(s) synthesis task, and return task information.
@@ -113,6 +116,8 @@ class ImageSynthesis(BaseAsyncApi):
113
116
  input[IMAGES] = images
114
117
  if sketch_image_url is not None and sketch_image_url:
115
118
  input['sketch_image_url'] = sketch_image_url
119
+ if ref_img is not None and ref_img:
120
+ input['ref_img'] == ref_img
116
121
  response = super().async_call(model=model,
117
122
  task_group=task_group,
118
123
  task=ImageSynthesis.task,
@@ -9,6 +9,7 @@ from dashscope.common.constants import (DEFAULT_REQUEST_TIMEOUT_SECONDS,
9
9
  SSE_CONTENT_TYPE, HTTPMethod)
10
10
  from dashscope.common.error import UnsupportedHTTPMethod
11
11
  from dashscope.common.logging import logger
12
+ from dashscope.common.utils import _handle_stream
12
13
 
13
14
 
14
15
  class HttpRequest(BaseRequest):
@@ -83,34 +84,14 @@ class HttpRequest(BaseRequest):
83
84
  pass
84
85
  return output
85
86
 
86
- def _handle_stream(self, response: requests.Response):
87
- # TODO define done message.
88
- is_error = False
89
- status_code = HTTPStatus.INTERNAL_SERVER_ERROR
90
- for line in response.iter_lines():
91
- if line:
92
- line = line.decode('utf8')
93
- line = line.rstrip('\n').rstrip('\r')
94
- if line.startswith('event:error'):
95
- is_error = True
96
- elif line.startswith('status:'):
97
- status_code = line[len('status:'):]
98
- status_code = int(status_code.strip())
99
- elif line.startswith('data:'):
100
- line = line[len('data:'):]
101
- yield (is_error, status_code, line)
102
- if is_error:
103
- break
104
- else:
105
- continue # ignore heartbeat...
106
-
107
87
  def _handle_response(self, response: requests.Response):
108
88
  request_id = ''
109
89
  if (response.status_code == HTTPStatus.OK and self.stream
110
90
  and SSE_CONTENT_TYPE in response.headers.get(
111
91
  'content-type', '')):
112
- for is_error, status_code, data in self._handle_stream(response):
92
+ for is_error, status_code, event in _handle_stream(response):
113
93
  try:
94
+ data = event.data
114
95
  output = None
115
96
  usage = None
116
97
  msg = json.loads(data)
@@ -112,6 +112,11 @@ class Application(BaseApi):
112
112
  if prompt is None or not prompt:
113
113
  raise InputRequired('prompt is required!')
114
114
 
115
+ if workspace is not None and workspace:
116
+ headers = kwargs.pop('headers', {})
117
+ headers['X-DashScope-WorkSpace'] = workspace
118
+ kwargs['headers'] = headers
119
+
115
120
  input, parameters = cls._build_input_parameters(
116
121
  prompt, history, **kwargs)
117
122
  request = _build_api_request(model='',
@@ -15,8 +15,9 @@ from dashscope.common.constants import (DEFAULT_REQUEST_TIMEOUT_SECONDS,
15
15
  from dashscope.common.error import InvalidParameter, InvalidTask, ModelRequired
16
16
  from dashscope.common.logging import logger
17
17
  from dashscope.common.utils import (_handle_http_failed_response,
18
- _handle_http_response, default_headers,
19
- join_url)
18
+ _handle_http_response,
19
+ _handle_http_stream_response,
20
+ default_headers, join_url)
20
21
 
21
22
 
22
23
  class BaseAioApi():
@@ -720,6 +721,7 @@ class CreateMixin():
720
721
  data: object,
721
722
  api_key: str = None,
722
723
  path: str = None,
724
+ stream: bool = False,
723
725
  workspace: str = None,
724
726
  **kwargs) -> Union[DashScopeAPIResponse, Dict]:
725
727
  """Create a object
@@ -741,6 +743,7 @@ class CreateMixin():
741
743
  logger.debug('Starting request: %s' % url)
742
744
  response = session.post(url,
743
745
  json=data,
746
+ stream=stream,
744
747
  headers={
745
748
  **_workspace_header(workspace),
746
749
  **default_headers(api_key),
@@ -748,7 +751,16 @@ class CreateMixin():
748
751
  },
749
752
  timeout=timeout)
750
753
  logger.debug('Starting processing response: %s' % url)
751
- return _handle_http_response(response, flattened_output)
754
+ response = _handle_http_stream_response(response, flattened_output)
755
+ if stream:
756
+ return (item for item in response)
757
+ else:
758
+ _, output = next(response)
759
+ try:
760
+ next(response)
761
+ except StopIteration:
762
+ pass
763
+ return output
752
764
 
753
765
 
754
766
  class UpdateMixin():
dashscope/common/utils.py CHANGED
@@ -2,6 +2,7 @@ import asyncio
2
2
  import json
3
3
  import os
4
4
  import platform
5
+ from dataclasses import dataclass
5
6
  from http import HTTPStatus
6
7
  from typing import Dict
7
8
  from urllib.parse import urlparse
@@ -11,6 +12,8 @@ import requests
11
12
 
12
13
  from dashscope.api_entities.dashscope_response import DashScopeAPIResponse
13
14
  from dashscope.common.api_key import get_default_api_key
15
+ from dashscope.common.constants import SSE_CONTENT_TYPE
16
+ from dashscope.common.logging import logger
14
17
  from dashscope.version import __version__
15
18
 
16
19
 
@@ -163,6 +166,52 @@ async def _handle_aiohttp_response(response: aiohttp.ClientResponse):
163
166
  message=msg)
164
167
 
165
168
 
169
+ @dataclass
170
+ class SSEEvent:
171
+ id: str
172
+ eventType: str
173
+ data: str
174
+
175
+ def __init__(self, id: str, type: str, data: str):
176
+ self.id = id
177
+ self.eventType = type
178
+ self.data = data
179
+
180
+
181
+ def _handle_stream(response: requests.Response):
182
+ # TODO define done message.
183
+ is_error = False
184
+ status_code = HTTPStatus.INTERNAL_SERVER_ERROR
185
+ event = SSEEvent(None, None, None)
186
+ eventType = None
187
+ for line in response.iter_lines():
188
+ if line:
189
+ line = line.decode('utf8')
190
+ line = line.rstrip('\n').rstrip('\r')
191
+ print(line)
192
+ if line.startswith('id:'):
193
+ id = line[len('id:'):]
194
+ event.id = id.strip()
195
+ elif line.startswith('event:'):
196
+ eventType = line[len('event:'):]
197
+ event.eventType = eventType.strip()
198
+ if eventType == 'error':
199
+ is_error = True
200
+ elif line.startswith('status:'):
201
+ status_code = line[len('status:'):]
202
+ status_code = int(status_code.strip())
203
+ elif line.startswith('data:'):
204
+ line = line[len('data:'):]
205
+ event.data = line.strip()
206
+ if eventType is not None and eventType == 'done':
207
+ continue
208
+ yield (is_error, status_code, event)
209
+ if is_error:
210
+ break
211
+ else:
212
+ continue # ignore heartbeat...
213
+
214
+
166
215
  def _handle_http_failed_response(
167
216
  response: requests.Response,
168
217
  flattened_output: bool = False) -> DashScopeAPIResponse:
@@ -198,38 +247,105 @@ def _handle_http_failed_response(
198
247
 
199
248
  def _handle_http_response(response: requests.Response,
200
249
  flattened_output: bool = False):
250
+ response = _handle_http_stream_response(response, flattened_output)
251
+ _, output = next(response)
252
+ try:
253
+ next(response)
254
+ except StopIteration:
255
+ pass
256
+ return output
257
+
258
+
259
+ def _handle_http_stream_response(response: requests.Response,
260
+ flattened_output: bool = False):
201
261
  request_id = ''
202
- if response.status_code == HTTPStatus.OK or response.status_code == HTTPStatus.CREATED:
262
+ if (response.status_code == HTTPStatus.OK
263
+ and SSE_CONTENT_TYPE in response.headers.get('content-type', '')):
264
+ for is_error, status_code, event in _handle_stream(response):
265
+ if not is_error:
266
+ try:
267
+ output = None
268
+ usage = None
269
+ msg = json.loads(event.data)
270
+ if flattened_output:
271
+ msg['status_code'] = response.status_code
272
+ yield event.eventType, msg
273
+ else:
274
+ logger.debug('Stream message: %s' % msg)
275
+ if not is_error:
276
+ if 'output' in msg:
277
+ output = msg['output']
278
+ if 'usage' in msg:
279
+ usage = msg['usage']
280
+ if 'request_id' in msg:
281
+ request_id = msg['request_id']
282
+ yield event.eventType, DashScopeAPIResponse(
283
+ request_id=request_id,
284
+ status_code=HTTPStatus.OK,
285
+ output=output,
286
+ usage=usage)
287
+ except json.JSONDecodeError as e:
288
+ if flattened_output:
289
+ yield event.eventType, {
290
+ 'status_code': response.status_code,
291
+ 'message': e.message
292
+ }
293
+ else:
294
+ yield event.eventType, DashScopeAPIResponse(
295
+ request_id=request_id,
296
+ status_code=HTTPStatus.BAD_REQUEST,
297
+ output=None,
298
+ code='Unknown',
299
+ message=event.data)
300
+ continue
301
+ else:
302
+ if flattened_output:
303
+ yield event.eventType, {
304
+ 'status_code': status_code,
305
+ 'message': event.data
306
+ }
307
+ else:
308
+ msg = json.loads(event.eventType)
309
+ yield event.eventType, DashScopeAPIResponse(
310
+ request_id=request_id,
311
+ status_code=status_code,
312
+ output=None,
313
+ code=msg['code']
314
+ if 'code' in msg else None, # noqa E501
315
+ message=msg['message']
316
+ if 'message' in msg else None) # noqa E501
317
+ elif response.status_code == HTTPStatus.OK or response.status_code == HTTPStatus.CREATED:
203
318
  json_content = response.json()
204
319
  if flattened_output:
205
320
  json_content['status_code'] = response.status_code
206
- return json_content
207
- output = None
208
- usage = None
209
- code = None
210
- msg = ''
211
- if 'data' in json_content:
212
- output = json_content['data']
213
- if 'code' in json_content:
214
- code = json_content['code']
215
- if 'message' in json_content:
216
- msg = json_content['message']
217
- if 'output' in json_content:
218
- output = json_content['output']
219
- if 'usage' in json_content:
220
- usage = json_content['usage']
221
- if 'request_id' in json_content:
222
- request_id = json_content['request_id']
223
- json_content.pop('request_id', None)
224
-
225
- if 'data' not in json_content and 'output' not in json_content:
226
- output = json_content
227
-
228
- return DashScopeAPIResponse(request_id=request_id,
229
- status_code=response.status_code,
230
- code=code,
231
- output=output,
232
- usage=usage,
233
- message=msg)
321
+ yield None, json_content
322
+ else:
323
+ output = None
324
+ usage = None
325
+ code = None
326
+ msg = ''
327
+ if 'data' in json_content:
328
+ output = json_content['data']
329
+ if 'code' in json_content:
330
+ code = json_content['code']
331
+ if 'message' in json_content:
332
+ msg = json_content['message']
333
+ if 'output' in json_content:
334
+ output = json_content['output']
335
+ if 'usage' in json_content:
336
+ usage = json_content['usage']
337
+ if 'request_id' in json_content:
338
+ request_id = json_content['request_id']
339
+ json_content.pop('request_id', None)
340
+
341
+ if 'data' not in json_content and 'output' not in json_content:
342
+ output = json_content
343
+
344
+ yield None, DashScopeAPIResponse(request_id=request_id,
345
+ status_code=response.status_code,
346
+ code=code,
347
+ output=output,
348
+ usage=usage,
349
+ message=msg)
234
350
  else:
235
- return _handle_http_failed_response(response, flattened_output)
351
+ yield None, _handle_http_failed_response(response, flattened_output)
@@ -7,7 +7,9 @@ from dashscope.client.base_api import (CancelMixin, CreateMixin,
7
7
  UpdateMixin)
8
8
  from dashscope.common.error import InputRequired, TimeoutException
9
9
  from dashscope.common.logging import logger
10
- from dashscope.threads.thread_types import Run, RunList
10
+ from dashscope.threads.thread_types import (Run, RunList, RunStep,
11
+ RunStepDelta, Thread,
12
+ ThreadMessage, ThreadMessageDelta)
11
13
 
12
14
  __all__ = ['Runs']
13
15
 
@@ -25,8 +27,10 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
25
27
  instructions: Optional[str] = None,
26
28
  additional_instructions: Optional[str] = None,
27
29
  tools: Optional[List[Dict]] = None,
30
+ stream: Optional[bool] = False,
28
31
  metadata: Optional[Dict] = None,
29
32
  workspace: str = None,
33
+ extra_body: Optional[Dict] = None,
30
34
  api_key: str = None,
31
35
  **kwargs) -> Run:
32
36
  if not assistant_id:
@@ -44,14 +48,22 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
44
48
  data['tools'] = tools
45
49
  if metadata:
46
50
  data['metadata'] = metadata
51
+ data['stream'] = stream
52
+ if extra_body is not None and extra_body:
53
+ data = {**data, **extra_body}
47
54
 
48
55
  response = super().call(data=data,
49
56
  path='threads/runs',
50
57
  api_key=api_key,
51
58
  flattened_output=True,
59
+ stream=stream,
52
60
  workspace=workspace,
53
61
  **kwargs)
54
- return Run(**response)
62
+ if stream:
63
+ return ((event_type, cls.convert_stream_object(event_type, item))
64
+ for event_type, item in response)
65
+ else:
66
+ return Run(**response)
55
67
 
56
68
  @classmethod
57
69
  def create(cls,
@@ -63,7 +75,9 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
63
75
  additional_instructions: Optional[str] = None,
64
76
  tools: Optional[List[Dict]] = None,
65
77
  metadata: Optional[Dict] = None,
78
+ stream: Optional[bool] = False,
66
79
  workspace: str = None,
80
+ extra_body: Optional[Dict] = None,
67
81
  api_key: str = None,
68
82
  **kwargs) -> Run:
69
83
  """Create a run.
@@ -101,14 +115,53 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
101
115
  data['tools'] = tools
102
116
  if metadata:
103
117
  data['metadata'] = metadata
118
+ data['stream'] = stream
119
+ if extra_body is not None and extra_body:
120
+ data = {**data, **extra_body}
104
121
 
105
122
  response = super().call(data=data,
106
123
  path=f'threads/{thread_id}/runs',
107
124
  api_key=api_key,
108
125
  flattened_output=True,
126
+ stream=stream,
109
127
  workspace=workspace,
110
128
  **kwargs)
111
- return Run(**response)
129
+ if stream:
130
+ return ((event_type, cls.convert_stream_object(event_type, item))
131
+ for event_type, item in response)
132
+ else:
133
+ return Run(**response)
134
+
135
+ @classmethod
136
+ def convert_stream_object(cls, event, item):
137
+ event_object_map = {
138
+ 'thread.created': Thread,
139
+ 'thread.run.created': Run,
140
+ 'thread.run.queued': Run,
141
+ 'thread.run.in_progress': Run,
142
+ 'thread.run.requires_action': Run,
143
+ 'thread.run.completed': Run,
144
+ 'thread.run.failed': Run,
145
+ 'thread.run.cancelled': Run,
146
+ 'thread.run.expired': Run,
147
+ 'thread.run.step.created': RunStep,
148
+ 'thread.run.step.in_progress': RunStep,
149
+ 'thread.run.step.delta': RunStepDelta,
150
+ 'thread.run.step.completed': RunStep,
151
+ 'thread.run.step.failed': RunStep,
152
+ 'thread.run.step.cancelled': RunStep,
153
+ 'thread.run.step.expired': RunStep,
154
+ 'thread.message.created': ThreadMessage,
155
+ 'thread.message.in_progress': ThreadMessage,
156
+ 'thread.message.delta': ThreadMessageDelta,
157
+ 'thread.message.completed': ThreadMessage,
158
+ 'thread.message.incomplete': ThreadMessage,
159
+ 'error': item,
160
+ }
161
+ if (event in event_object_map):
162
+ return event_object_map[event](**item)
163
+ else:
164
+ return item
112
165
 
113
166
  @classmethod
114
167
  def call(cls,
@@ -119,8 +172,10 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
119
172
  instructions: Optional[str] = None,
120
173
  additional_instructions: Optional[str] = None,
121
174
  tools: Optional[List[Dict]] = None,
175
+ stream: Optional[bool] = False,
122
176
  metadata: Optional[Dict] = None,
123
177
  workspace: str = None,
178
+ extra_body: Optional[Dict] = None,
124
179
  api_key: str = None,
125
180
  **kwargs) -> Run:
126
181
  """Create a run.
@@ -151,8 +206,10 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
151
206
  instructions=instructions,
152
207
  additional_instructions=additional_instructions,
153
208
  tools=tools,
209
+ stream=stream,
154
210
  metadata=metadata,
155
211
  workspace=workspace,
212
+ extra_body=extra_body,
156
213
  api_key=api_key,
157
214
  **kwargs)
158
215
 
@@ -254,7 +311,9 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
254
311
  *,
255
312
  thread_id: str,
256
313
  tool_outputs: List[Dict],
314
+ stream: Optional[bool] = False,
257
315
  workspace: str = None,
316
+ extra_body: Optional[Dict] = None,
258
317
  api_key: str = None,
259
318
  **kwargs) -> Run:
260
319
  """_summary_
@@ -278,14 +337,24 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
278
337
  if not thread_id or not run_id:
279
338
  raise InputRequired('thread_id and run_id are required!')
280
339
 
340
+ data = {'tool_outputs': tool_outputs}
341
+ data['stream'] = stream
342
+ if extra_body is not None and extra_body:
343
+ data = {**data, **extra_body}
344
+
281
345
  response = super().call(
282
- {'tool_outputs': tool_outputs},
346
+ data,
283
347
  path=f'threads/{thread_id}/runs/{run_id}/submit_tool_outputs',
284
348
  workspace=workspace,
285
349
  api_key=api_key,
350
+ stream=stream,
286
351
  flattened_output=True,
287
352
  **kwargs)
288
- return Run(**response)
353
+ if stream:
354
+ return ((event_type, cls.convert_stream_object(event_type, item))
355
+ for event_type, item in response)
356
+ else:
357
+ return Run(**response)
289
358
 
290
359
  @classmethod
291
360
  def wait(cls,
@@ -316,6 +385,12 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
316
385
  thread_id=thread_id,
317
386
  workspace=workspace,
318
387
  api_key=api_key)
388
+ import json
389
+ print(
390
+ json.dumps(run,
391
+ default=lambda o: o.__dict__,
392
+ sort_keys=True,
393
+ indent=4))
319
394
  if run.status_code == HTTPStatus.OK:
320
395
  if hasattr(run, 'status'):
321
396
  if run.status in [
@@ -85,6 +85,8 @@ class Text(BaseObjectMixin):
85
85
  self.annotations = []
86
86
  for annotation in annotations:
87
87
  self.annotations.append(annotation)
88
+ else:
89
+ self.annotations = annotations
88
90
  super().__init__(**kwargs)
89
91
 
90
92
 
@@ -108,6 +110,42 @@ MESSAGE_SUPPORT_CONTENT = {
108
110
  Content = Union[MessageContentImageFile, MessageContentText]
109
111
 
110
112
 
113
+ @dataclass(init=False)
114
+ class ThreadMessageDeltaContent(BaseObjectMixin):
115
+ content: Content
116
+ role: str
117
+
118
+ def __init__(self, **kwargs):
119
+ contents = kwargs.pop('content', None)
120
+ if contents:
121
+ for item in contents:
122
+ if item['type'] == 'text':
123
+ self.content = MessageContentText(**item)
124
+ elif item['type'] == 'image_file':
125
+ self.content = MessageContentImageFile(**item)
126
+ else:
127
+ self.content = item
128
+ else:
129
+ self.content = contents
130
+ super().__init__(**kwargs)
131
+
132
+
133
+ @dataclass(init=False)
134
+ class ThreadMessageDelta(BaseObjectMixin):
135
+ status_code: int
136
+ id: str
137
+ object: str = 'thread.message.delta'
138
+ delta: ThreadMessageDeltaContent
139
+
140
+ def __init__(self, **kwargs):
141
+ content = kwargs.pop('delta', None)
142
+ if content:
143
+ self.delta = ThreadMessageDeltaContent(**content)
144
+ else:
145
+ self.delta = None
146
+ super().__init__(**kwargs)
147
+
148
+
111
149
  @dataclass(init=False)
112
150
  class ThreadMessage(BaseObjectMixin):
113
151
  status_code: int
@@ -137,6 +175,8 @@ class ThreadMessage(BaseObjectMixin):
137
175
  else:
138
176
  content_list.append(content)
139
177
  self.content = content_list
178
+ else:
179
+ self.content = input_content
140
180
 
141
181
  super().__init__(**kwargs)
142
182
 
@@ -203,6 +243,8 @@ class RequiredActionSubmitToolOutputs(BaseObjectMixin):
203
243
  self.tool_calls = []
204
244
  for tc in tcs:
205
245
  self.tool_calls.append(RequiredActionFunctionToolCall(**tc))
246
+ else:
247
+ self.tool_calls = tcs
206
248
  super().__init__(**kwargs)
207
249
 
208
250
 
@@ -265,6 +307,8 @@ class Run(BaseObjectMixin):
265
307
  actions = kwargs.pop('required_action', None)
266
308
  if actions:
267
309
  self.required_action = RequiredAction(**actions)
310
+ else:
311
+ self.required_action = actions
268
312
 
269
313
  super().__init__(**kwargs)
270
314
 
@@ -387,10 +431,10 @@ class RetrievalToolCall(BaseObjectMixin):
387
431
  retrieval: object
388
432
  """For now, this is always going to be an empty object."""
389
433
 
390
- type: Literal['retrieval']
434
+ type: Literal['quark_search']
391
435
  """The type of tool call.
392
436
 
393
- This is always going to be `retrieval` for this type of tool call.
437
+ This is always going to be `quark_search` for this type of tool call.
394
438
  """
395
439
  def __init__(self, **kwargs):
396
440
  super().__init__(**kwargs)
@@ -469,9 +513,34 @@ def convert_step_details_dict_to_objects(step_details):
469
513
  return step_details
470
514
 
471
515
 
516
+ @dataclass(init=False)
517
+ class RunStepDeltaContent(BaseObjectMixin):
518
+ step_details: StepDetails
519
+
520
+ def __init__(self, **kwargs):
521
+ self.step_details = convert_step_details_dict_to_objects(
522
+ kwargs.pop('step_details', {}))
523
+ super().__init__(**kwargs)
524
+
525
+
526
+ @dataclass(init=False)
527
+ class RunStepDelta(BaseObjectMixin):
528
+ id: str
529
+ object: str = 'thread.run.step.delta'
530
+ delta: RunStepDeltaContent
531
+
532
+ def __init__(self, **kwargs):
533
+ delta = kwargs.pop('delta', None)
534
+ if delta:
535
+ self.delta = RunStepDeltaContent(**delta)
536
+ else:
537
+ self.delta = delta
538
+ super().__init__(**kwargs)
539
+
540
+
472
541
  @dataclass(init=False)
473
542
  class RunStep(BaseObjectMixin):
474
- status_code: int
543
+ status_code: int = None
475
544
  id: str
476
545
  """The identifier of the run step, which can be referenced in API endpoints."""
477
546
 
@@ -547,10 +616,15 @@ class RunStep(BaseObjectMixin):
547
616
  def __init__(self, **kwargs):
548
617
  self.step_details = convert_step_details_dict_to_objects(
549
618
  kwargs.pop('step_details', {}))
550
- self.usage = Usage(**kwargs.pop('usage', {}))
619
+ if 'usage' in kwargs and kwargs['usage'] is not None and kwargs['usage']:
620
+ self.usage = Usage(**kwargs.pop('usage', {}))
621
+ else:
622
+ self.usage = None
551
623
  last_error = kwargs.pop('last_error', None)
552
624
  if last_error:
553
625
  self.last_error = LastError(**last_error)
626
+ else:
627
+ last_error = last_error
554
628
  super().__init__(**kwargs)
555
629
 
556
630
 
@@ -564,8 +638,14 @@ class RunStepList(BaseList):
564
638
  first_id: Optional[str] = None,
565
639
  data: List[RunStep] = [],
566
640
  **kwargs):
641
+ if data:
642
+ steps = []
643
+ for step in data:
644
+ steps.append(RunStep(**step))
645
+ self.data = steps
646
+ else:
647
+ self.data = []
567
648
  super().__init__(has_more=has_more,
568
649
  last_id=last_id,
569
650
  first_id=first_id,
570
- data=data,
571
651
  **kwargs)
dashscope/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '1.17.0'
1
+ __version__ = '1.18.0'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dashscope
3
- Version: 1.17.0
3
+ Version: 1.18.0
4
4
  Summary: dashscope client sdk library
5
5
  Home-page: https://dashscope.aliyun.com/
6
6
  Author: Alibaba Cloud
@@ -6,12 +6,12 @@ dashscope/files.py,sha256=QgJjwhtn9F548nCA8jD8OvE6aQEj-20hZqJgYXsUdQU,3930
6
6
  dashscope/finetune.py,sha256=_tflDUvu0KagSoCzLaf0hofpG_P8NU6PylL8CPjVhrA,6243
7
7
  dashscope/model.py,sha256=UPOn1qMYFhX-ovXi3BMxZEBk8qOK7WLJOYHMbPZwYBo,1440
8
8
  dashscope/models.py,sha256=UPOn1qMYFhX-ovXi3BMxZEBk8qOK7WLJOYHMbPZwYBo,1440
9
- dashscope/version.py,sha256=U6ZR0tatDYFB2QLb4J_eI-DLS9Pd8RCafZF8BQcrTYE,23
9
+ dashscope/version.py,sha256=q8fI5ieuQmE0i1govJ0GSDS7ZYmdLjENalxa2NdG9VQ,23
10
10
  dashscope/aigc/__init__.py,sha256=s-MCA87KYiVumYtKtJi5IMN7xelSF6TqEU3s3_7RF-Y,327
11
11
  dashscope/aigc/code_generation.py,sha256=KAJVrGp6tiNFBBg64Ovs9RfcP5SrIhrbW3wdA89NKso,10885
12
12
  dashscope/aigc/conversation.py,sha256=xRoJlCR-IXHjSdkDrK74a9ut1FJg0FZhTNXZAJC18MA,14231
13
13
  dashscope/aigc/generation.py,sha256=9PMAhSy5Ht5eizUGXnDdk8Jl3yIDM4fR8eSxn1W4c-U,10051
14
- dashscope/aigc/image_synthesis.py,sha256=b7813Yz9Ivv2KijXfBSycRE1rer4uVRS2Ntx_lPts1A,9791
14
+ dashscope/aigc/image_synthesis.py,sha256=7A5txSkKBkg5pN5F7IP5C90277Yk8fkKAWu30YhskdM,9994
15
15
  dashscope/aigc/multimodal_conversation.py,sha256=SlNnnsUPV19gdx8fYJAtsMFWPNGY6vhk5IGHZ5ZczpI,5369
16
16
  dashscope/api_entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  dashscope/api_entities/aiohttp_request.py,sha256=aE3AeWba8Ig_xHMYjrAdkq0N61l_L2VFTG6HYh912X0,10229
@@ -19,10 +19,10 @@ dashscope/api_entities/api_request_data.py,sha256=JUMcfpJjKXEZLCBSFIDpgoaeQYk5uK
19
19
  dashscope/api_entities/api_request_factory.py,sha256=4p-qxMuvCA0CmUHdH19QaUCaHmlLHAM1X2Jd4YKt5c0,4661
20
20
  dashscope/api_entities/base_request.py,sha256=cXUL7xqSV8wBr5d-1kx65AO3IsRR9A_ps6Lok-v-MKM,926
21
21
  dashscope/api_entities/dashscope_response.py,sha256=Bp1T7HwVlkOvpMNg-AEjz-BScxhLUXMXlE8ApXTtfhQ,17872
22
- dashscope/api_entities/http_request.py,sha256=Y25LeW3Sq73AbjP-Zsvs1CYMsSBPEBTFXcthbFkV0dI,9834
22
+ dashscope/api_entities/http_request.py,sha256=Y9z4PcRAPlp6Ozfz9P3IVP3y9cufhhIFjXaJOF6xCtQ,9043
23
23
  dashscope/api_entities/websocket_request.py,sha256=IaydqRvOSr5IdSSpnX8Vc8rRoVldjfcrLvDxTnPep9g,14676
24
24
  dashscope/app/__init__.py,sha256=OOV2rFy0QlA9Gu3XVPtWJoBwK1J11BdGhkEdX_sdYGU,68
25
- dashscope/app/application.py,sha256=Lk6d00PEZvnzlfJkMI1xQaQr9PKZknrONw9aQQFR1zA,7755
25
+ dashscope/app/application.py,sha256=AegGVsk3dDzYACoYRNNjo3eG-2wrDd0dlOjYHpF0r2Y,7949
26
26
  dashscope/app/application_response.py,sha256=pIuDSu_SAcX1Y_gK6ZYaadaMXV52XBZoM1uN4tTZ3FA,6739
27
27
  dashscope/assistants/__init__.py,sha256=i9N5OxHgY7edlOhTdPyC0N5Uc0uMCkB2vbMPDCD1zX0,383
28
28
  dashscope/assistants/assistant_types.py,sha256=1jNL30TOlrkiYhvCaB3E8jkPLG8CnQ6I3tHpYXZCsD0,4211
@@ -36,7 +36,7 @@ dashscope/audio/asr/transcription.py,sha256=e5O1U51GT-OQPu-wWN2w_T7l6IopWuGMVkhe
36
36
  dashscope/audio/tts/__init__.py,sha256=fbnieZX9yNFNh5BsxLpLXb63jlxzxrdCJakV3ignjlQ,194
37
37
  dashscope/audio/tts/speech_synthesizer.py,sha256=dnKx9FDDdO_ETHAjhK8zaMVaH6SfoTtN5YxXXqgY1JA,7571
38
38
  dashscope/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- dashscope/client/base_api.py,sha256=k6DS7dtVGTeavAzKOl_DDruyRN8UzvjAtjhSRbXgiNQ,40587
39
+ dashscope/client/base_api.py,sha256=UDxvwlxiR0KZwj_AI0jACfkLErJ55voure82OmOiDMk,41034
40
40
  dashscope/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  dashscope/common/api_key.py,sha256=5Stp0odL5JSuIO3qJBp23QNppuGbqhhvKPS66qbMs0I,1986
42
42
  dashscope/common/base_type.py,sha256=wKqLGrr2o9bpI43ws1P0YCuJmoS17J9_Rw_uuYHjIFQ,4531
@@ -45,7 +45,7 @@ dashscope/common/env.py,sha256=oQOZW5JyEeTSde394un2lpDJ5RBh4fMU9hBfbtrKKkc,869
45
45
  dashscope/common/error.py,sha256=eFUSBNERfXYQ4g3bVka_IGuRG1A06Zf6njObBtR2z6E,1951
46
46
  dashscope/common/logging.py,sha256=ecGxylG3bWES_Xv5-BD6ep4_0Ciu7F6ZPBjiZtu9Jx4,984
47
47
  dashscope/common/message_manager.py,sha256=i5149WzDk6nWmdFaHzYx4USXMBeX18GKSI-F4fLwbN0,1097
48
- dashscope/common/utils.py,sha256=oGwoDgO31-Filg64GrhyR14lxORhE3esVPJvnOgtpvw,7365
48
+ dashscope/common/utils.py,sha256=AqpU4Lh6C64-Uy-BLybpRz01HqlmcAgVqlqN73tD1I0,12041
49
49
  dashscope/embeddings/__init__.py,sha256=-dxHaoxZZVuP-wAGUIa3sNNh8CQwaeWj2UlqsDy1sV4,240
50
50
  dashscope/embeddings/batch_text_embedding.py,sha256=P32LFO9v7ehdJsl0c32In94hUET6K6AaGJ_pDRtFqco,8791
51
51
  dashscope/embeddings/batch_text_embedding_response.py,sha256=WziXlQsFIkL1kPc_7lRG1HtqgkO5vVThtnNqExJggNU,2000
@@ -61,13 +61,13 @@ dashscope/rerank/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
61
61
  dashscope/rerank/text_rerank.py,sha256=1L-RLUxMCvNhbMud1FUG6YFWT7ZV979fzhMEuVjJ1oI,2398
62
62
  dashscope/resources/qwen.tiktoken,sha256=srG437XMXwJLr8NzEhxquj9m-aWgJp4kNHCh3hajMYY,2561218
63
63
  dashscope/threads/__init__.py,sha256=md5bsHekHHGOg3uQrBCk8f4BCNnA1AuI_-LDf92pNVU,621
64
- dashscope/threads/thread_types.py,sha256=h1fYspH_ppCv32ffjTXIiGKBSgzEVtOdwT57xlcEd_Q,16028
64
+ dashscope/threads/thread_types.py,sha256=SwAJNi-RbqFXlrztDUCt0q0MfgfJLHyYl9qWrQDmQQo,18280
65
65
  dashscope/threads/threads.py,sha256=dD72xklN71KFGBVoBVHEbCbZADwLbi9yGS9LbFpnlAI,7665
66
66
  dashscope/threads/messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
67
  dashscope/threads/messages/files.py,sha256=wi0nJ2zsPWOw2Jn-ZkxA3URZBIrkGxqM_uAPfXY1xv0,3820
68
68
  dashscope/threads/messages/messages.py,sha256=Zjmyf3rT1XSdn33hPrqOY6DSWUVL7pDEapG03FREPV8,8419
69
69
  dashscope/threads/runs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- dashscope/threads/runs/runs.py,sha256=Fyny9GyCgxL0CRBht84f7sFjYKBwyZBC-HMCW1tx_3k,15529
70
+ dashscope/threads/runs/runs.py,sha256=24zFdIldjKUMN2EFiHv9unm9fgnD5irkurYtRfm0gQ0,18698
71
71
  dashscope/threads/runs/steps.py,sha256=pLNR-5g7zvYkvC-p4sZGVgYHd1jqxBerM2WFyB358H8,3638
72
72
  dashscope/tokenizers/__init__.py,sha256=Oy5FMT37Non6e1YxdHQ89U93Dy3CG1Ez0gBa771KZo0,200
73
73
  dashscope/tokenizers/qwen_tokenizer.py,sha256=dCnT9-9NrqPS85bEhjlPULUfDADVRhlleYwM_ILgCeI,4111
@@ -76,9 +76,9 @@ dashscope/tokenizers/tokenizer.py,sha256=y6P91qTCYo__pEx_0VHAcj9YECfbUdRqZU1fdGT
76
76
  dashscope/tokenizers/tokenizer_base.py,sha256=REDhzRyDT13iequ61-a6_KcTy0GFKlihQve5HkyoyRs,656
77
77
  dashscope/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
78
  dashscope/utils/oss_utils.py,sha256=fi8-PPsN-iR-iv5k2NS5Z8nlWkpgUhr56FRWm4BDh4A,6984
79
- dashscope-1.17.0.dist-info/LICENSE,sha256=Izp5L1DF1Mbza6qojkqNNWlE_mYLnr4rmzx2EBF8YFw,11413
80
- dashscope-1.17.0.dist-info/METADATA,sha256=EbZoYp1sVHD7WzeWQL-P9JvJkd3gaPdzkE2G5--G2GA,6609
81
- dashscope-1.17.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
82
- dashscope-1.17.0.dist-info/entry_points.txt,sha256=raEp5dOuj8whJ7yqZlDM8WQ5p2RfnGrGNo0QLQEnatY,50
83
- dashscope-1.17.0.dist-info/top_level.txt,sha256=woqavFJK9zas5xTqynmALqOtlafghjsk63Xk86powTU,10
84
- dashscope-1.17.0.dist-info/RECORD,,
79
+ dashscope-1.18.0.dist-info/LICENSE,sha256=Izp5L1DF1Mbza6qojkqNNWlE_mYLnr4rmzx2EBF8YFw,11413
80
+ dashscope-1.18.0.dist-info/METADATA,sha256=O7GFznTd2fn-87dJSUvcIfZkhTcGv_KBxPf9s3Cvbiw,6609
81
+ dashscope-1.18.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
82
+ dashscope-1.18.0.dist-info/entry_points.txt,sha256=raEp5dOuj8whJ7yqZlDM8WQ5p2RfnGrGNo0QLQEnatY,50
83
+ dashscope-1.18.0.dist-info/top_level.txt,sha256=woqavFJK9zas5xTqynmALqOtlafghjsk63Xk86powTU,10
84
+ dashscope-1.18.0.dist-info/RECORD,,