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
@@ -1,6 +1,9 @@
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+ import asyncio
3
+ import collections
1
4
  import time
2
5
  from http import HTTPStatus
3
- from typing import List, Union
6
+ from typing import Any, Dict, Iterator, List, Union
4
7
 
5
8
  import requests
6
9
 
@@ -11,20 +14,307 @@ from dashscope.common.api_key import get_default_api_key
11
14
  from dashscope.common.constants import (DEFAULT_REQUEST_TIMEOUT_SECONDS,
12
15
  REPEATABLE_STATUS,
13
16
  REQUEST_TIMEOUT_KEYWORD,
14
- SSE_CONTENT_TYPE, TaskStatus)
17
+ SSE_CONTENT_TYPE, TaskStatus, HTTPMethod)
15
18
  from dashscope.common.error import InvalidParameter, InvalidTask, ModelRequired
16
19
  from dashscope.common.logging import logger
17
20
  from dashscope.common.utils import (_handle_http_failed_response,
18
- _handle_http_response, default_headers,
19
- join_url)
21
+ _handle_http_response,
22
+ _handle_http_stream_response,
23
+ default_headers, join_url)
20
24
 
25
+ class AsyncAioTaskGetMixin:
26
+ @classmethod
27
+ async def _get(cls,
28
+ task_id: str,
29
+ api_key: str = None,
30
+ workspace: str = None,
31
+ **kwargs) -> DashScopeAPIResponse:
32
+ base_url = kwargs.pop('base_address', None)
33
+ url = _normalization_url(base_url, 'tasks', task_id)
34
+ kwargs = cls._handle_kwargs(api_key, workspace, **kwargs)
35
+ kwargs["base_address"] = url
36
+ if not api_key:
37
+ api_key = get_default_api_key()
38
+ request = _build_api_request("", "", "",
39
+ "", "", api_key=api_key,
40
+ is_service=False, **kwargs)
41
+ return await cls._handle_request(request)
21
42
 
22
- def _normalization_url(*args):
23
- url = dashscope.base_http_api_url
24
- return join_url(url, *args)
43
+ @classmethod
44
+ def _handle_kwargs(cls, api_key: str = None ,workspace: str = None, **kwargs):
45
+ custom_headers = kwargs.pop('headers', None)
46
+ headers = {
47
+ **_workspace_header(workspace),
48
+ **default_headers(api_key),
49
+ }
50
+ if custom_headers:
51
+ headers = {
52
+ **custom_headers,
53
+ **headers,
54
+ }
55
+ if workspace is not None:
56
+ headers = {
57
+ 'X-DashScope-WorkSpace': workspace,
58
+ **kwargs.pop('headers', {})
59
+ }
60
+ kwargs['headers'] = headers
61
+ kwargs['http_method'] = HTTPMethod.GET
62
+ return kwargs
63
+
64
+ @classmethod
65
+ async def _handle_request(cls, request):
66
+ # 如果 aio_call 返回的是异步生成器,则需要从中获取响应
67
+ response = await request.aio_call()
68
+ # 处理异步生成器的情况
69
+ if isinstance(response, collections.abc.AsyncGenerator):
70
+ result = None
71
+ async for item in response:
72
+ result = item
73
+ return result
74
+ else:
75
+ return response
76
+
77
+ class BaseAsyncAioApi(AsyncAioTaskGetMixin):
78
+ """BaseApi, internal use only.
79
+
80
+ """
81
+ @classmethod
82
+ def _validate_params(cls, api_key, model):
83
+ if api_key is None:
84
+ api_key = get_default_api_key()
85
+ if model is None or not model:
86
+ raise ModelRequired('Model is required!')
87
+ return api_key, model
88
+
89
+ @classmethod
90
+ async def async_call(cls,
91
+ model: str,
92
+ input: object,
93
+ task_group: str,
94
+ task: str = None,
95
+ function: str = None,
96
+ api_key: str = None,
97
+ workspace: str = None,
98
+ **kwargs) -> DashScopeAPIResponse:
99
+ api_key, model = cls._validate_params(api_key, model)
100
+ if workspace is not None:
101
+ headers = {
102
+ 'X-DashScope-WorkSpace': workspace,
103
+ **kwargs.pop('headers', {})
104
+ }
105
+ kwargs['headers'] = headers
106
+ kwargs['async_request'] = True
107
+ request = _build_api_request(model=model,
108
+ input=input,
109
+ task_group=task_group,
110
+ task=task,
111
+ function=function,
112
+ api_key=api_key,
113
+ **kwargs)
114
+ # call request service.
115
+ return await request.aio_call()
116
+
117
+ @classmethod
118
+ async def call(cls,
119
+ model: str,
120
+ input: object,
121
+ task_group: str,
122
+ task: str = None,
123
+ function: str = None,
124
+ api_key: str = None,
125
+ workspace: str = None,
126
+ **kwargs) -> DashScopeAPIResponse:
127
+ # call request service.
128
+ response = await BaseAsyncAioApi.async_call(model, input, task_group, task,
129
+ function, api_key, workspace,
130
+ **kwargs)
131
+ response = await BaseAsyncAioApi.wait(response,
132
+ api_key=api_key,
133
+ workspace=workspace,
134
+ **kwargs)
135
+ return response
136
+
137
+
138
+ @classmethod
139
+ def _get_task_id(cls, task):
140
+ if isinstance(task, str):
141
+ task_id = task
142
+ elif isinstance(task, DashScopeAPIResponse):
143
+ if task.status_code == HTTPStatus.OK:
144
+ task_id = task.output['task_id']
145
+ else:
146
+ raise InvalidTask('Invalid task, task create failed: %s' %
147
+ task)
148
+ else:
149
+ raise InvalidParameter('Task invalid!')
150
+ if task_id is None or task_id == '':
151
+ raise InvalidParameter('Task id required!')
152
+ return task_id
153
+
154
+ @classmethod
155
+ async def wait(cls,
156
+ task: Union[str, DashScopeAPIResponse],
157
+ api_key: str = None,
158
+ workspace: str = None,
159
+ **kwargs) -> DashScopeAPIResponse:
160
+ """Wait for async task completion and return task result.
161
+
162
+ Args:
163
+ task (Union[str, DashScopeAPIResponse]): The task_id, or
164
+ async_call response.
165
+ api_key (str, optional): The api_key. Defaults to None.
166
+
167
+ Returns:
168
+ DashScopeAPIResponse: The async task information.
169
+ """
170
+ task_id = cls._get_task_id(task)
171
+ wait_seconds = 1
172
+ max_wait_seconds = 5
173
+ increment_steps = 3
174
+ step = 0
175
+ while True:
176
+ step += 1
177
+ # we start by querying once every second, and double
178
+ # the query interval after every 3(increment_steps)
179
+ # intervals, until we hit the max waiting interval
180
+ # of 5(seconds)
181
+ # (server side return immediately when ready)
182
+ if wait_seconds < max_wait_seconds and step % increment_steps == 0:
183
+ wait_seconds = min(wait_seconds * 2, max_wait_seconds)
184
+ rsp = await cls._get(task_id, api_key, workspace=workspace, **kwargs)
185
+ if rsp.status_code == HTTPStatus.OK:
186
+ if rsp.output is None:
187
+ return rsp
188
+
189
+ task_status = rsp.output['task_status']
190
+ if task_status in [
191
+ TaskStatus.FAILED, TaskStatus.CANCELED,
192
+ TaskStatus.SUCCEEDED, TaskStatus.UNKNOWN
193
+ ]:
194
+ return rsp
195
+ else:
196
+ logger.info('The task %s is %s' % (task_id, task_status))
197
+ await asyncio.sleep(wait_seconds) # 异步等待
198
+ elif rsp.status_code in REPEATABLE_STATUS:
199
+ logger.warn(
200
+ ('Get task: %s temporary failure, \
201
+ status_code: %s, code: %s message: %s, will try again.'
202
+ ) % (task_id, rsp.status_code, rsp.code, rsp.message))
203
+ await asyncio.sleep(wait_seconds) # 异步等待
204
+ else:
205
+ return rsp
206
+
207
+ @classmethod
208
+ async def cancel(
209
+ cls,
210
+ task: Union[str, DashScopeAPIResponse],
211
+ api_key: str = None,
212
+ workspace: str = None,
213
+ **kwargs,
214
+ ) -> DashScopeAPIResponse:
215
+ """Cancel PENDING task.
216
+
217
+ Args:
218
+ task (Union[str, DashScopeAPIResponse]): The task_id, or
219
+ async_call response.
220
+ api_key (str, optional): The api-key. Defaults to None.
221
+
222
+ Returns:
223
+ DashScopeAPIResponse: The cancel result.
224
+ """
225
+ task_id = cls._get_task_id(task)
226
+ base_url = kwargs.pop('base_address', None)
227
+ url = _normalization_url(base_url, 'tasks', task_id, 'cancel')
228
+ kwargs = cls._handle_kwargs(api_key, workspace, **kwargs)
229
+ kwargs["base_address"] = url
230
+ if not api_key:
231
+ api_key = get_default_api_key()
232
+ request = _build_api_request("", "", "",
233
+ "", "",api_key=api_key,
234
+ is_service=False, **kwargs)
235
+ return await cls._handle_request(request)
236
+
237
+ @classmethod
238
+ async def list(cls,
239
+ start_time: str = None,
240
+ end_time: str = None,
241
+ model_name: str = None,
242
+ api_key_id: str = None,
243
+ region: str = None,
244
+ status: str = None,
245
+ page_no: int = 1,
246
+ page_size: int = 10,
247
+ api_key: str = None,
248
+ workspace: str = None,
249
+ **kwargs) -> DashScopeAPIResponse:
250
+ """List async tasks.
251
+
252
+ Args:
253
+ start_time (str, optional): The tasks start time,
254
+ for example: 20230420000000. Defaults to None.
255
+ end_time (str, optional): The tasks end time,
256
+ for example: 20230420000000. Defaults to None.
257
+ model_name (str, optional): The tasks model name.
258
+ Defaults to None.
259
+ api_key_id (str, optional): The tasks api-key-id.
260
+ Defaults to None.
261
+ region (str, optional): The service region,
262
+ for example: cn-beijing. Defaults to None.
263
+ status (str, optional): The status of tasks[PENDING,
264
+ RUNNING, SUCCEEDED, FAILED, CANCELED]. Defaults to None.
265
+ page_no (int, optional): The page number. Defaults to 1.
266
+ page_size (int, optional): The page size. Defaults to 10.
267
+ api_key (str, optional): The user api-key. Defaults to None.
268
+
269
+ Returns:
270
+ DashScopeAPIResponse: The response data.
271
+ """
272
+ base_url = kwargs.pop('base_address', None)
273
+ url = _normalization_url(base_url, 'tasks')
274
+ params = {'page_no': page_no, 'page_size': page_size}
275
+ if start_time is not None:
276
+ params['start_time'] = start_time
277
+ if end_time is not None:
278
+ params['end_time'] = end_time
279
+ if model_name is not None:
280
+ params['model_name'] = model_name
281
+ if api_key_id is not None:
282
+ params['api_key_id'] = api_key_id
283
+ if region is not None:
284
+ params['region'] = region
285
+ if status is not None:
286
+ params['status'] = status
287
+ kwargs = cls._handle_kwargs(api_key, workspace, **kwargs)
288
+ kwargs["base_address"] = url
289
+ if not api_key:
290
+ api_key = get_default_api_key()
291
+ request = _build_api_request(model_name, "", "",
292
+ "", "", api_key=api_key,
293
+ is_service=False, extra_url_parameters=params,
294
+ **kwargs)
295
+ return await cls._handle_request(request)
25
296
 
297
+ @classmethod
298
+ async def fetch(cls,
299
+ task: Union[str, DashScopeAPIResponse],
300
+ api_key: str = None,
301
+ workspace: str = None,
302
+ **kwargs) -> DashScopeAPIResponse:
303
+ """Query async task status.
26
304
 
27
- class BaseAioApi():
305
+ Args:
306
+ task (Union[str, DashScopeAPIResponse]): The task_id, or
307
+ async_call response.
308
+ api_key (str, optional): The api_key. Defaults to None.
309
+
310
+ Returns:
311
+ DashScopeAPIResponse: The async task information.
312
+ """
313
+ task_id = cls._get_task_id(task)
314
+ return await cls._get(task_id, api_key, workspace, **kwargs)
315
+
316
+
317
+ class BaseAioApi:
28
318
  """BaseApi, internal use only.
29
319
 
30
320
  """
@@ -37,14 +327,15 @@ class BaseAioApi():
37
327
  return api_key, model
38
328
 
39
329
  @classmethod
40
- def aio_call(cls,
41
- model: str,
42
- input: object,
43
- task_group: str,
44
- task: str = None,
45
- function: str = None,
46
- api_key: str = None,
47
- **kwargs) -> DashScopeAPIResponse:
330
+ async def call(cls,
331
+ model: str,
332
+ input: object,
333
+ task_group: str,
334
+ task: str = None,
335
+ function: str = None,
336
+ api_key: str = None,
337
+ workspace: str = None,
338
+ **kwargs) -> DashScopeAPIResponse:
48
339
  """Call service and get result.
49
340
 
50
341
  Args:
@@ -69,6 +360,12 @@ class BaseAioApi():
69
360
  DashScopeAPIResponse: The service response.
70
361
  """
71
362
  api_key, model = BaseAioApi._validate_params(api_key, model)
363
+ if workspace is not None:
364
+ headers = {
365
+ 'X-DashScope-WorkSpace': workspace,
366
+ **kwargs.pop('headers', {})
367
+ }
368
+ kwargs['headers'] = headers
72
369
  request = _build_api_request(model=model,
73
370
  input=input,
74
371
  task_group=task_group,
@@ -77,7 +374,7 @@ class BaseAioApi():
77
374
  api_key=api_key,
78
375
  **kwargs)
79
376
  # call request service.
80
- return request.aio_call()
377
+ return await request.aio_call()
81
378
 
82
379
 
83
380
  class BaseApi():
@@ -100,6 +397,7 @@ class BaseApi():
100
397
  task: str = None,
101
398
  function: str = None,
102
399
  api_key: str = None,
400
+ workspace: str = None,
103
401
  **kwargs) -> DashScopeAPIResponse:
104
402
  """Call service and get result.
105
403
 
@@ -125,6 +423,12 @@ class BaseApi():
125
423
  DashScopeAPIResponse: The service response.
126
424
  """
127
425
  api_key, model = BaseApi._validate_params(api_key, model)
426
+ if workspace is not None:
427
+ headers = {
428
+ 'X-DashScope-WorkSpace': workspace,
429
+ **kwargs.pop('headers', {})
430
+ }
431
+ kwargs['headers'] = headers
128
432
  request = _build_api_request(model=model,
129
433
  input=input,
130
434
  task_group=task_group,
@@ -136,16 +440,45 @@ class BaseApi():
136
440
  return request.call()
137
441
 
138
442
 
443
+ def _workspace_header(workspace) -> Dict:
444
+ if workspace is not None:
445
+ headers = {'X-DashScope-WorkSpace': workspace}
446
+ else:
447
+ headers = {}
448
+ return headers
449
+
450
+
451
+ def _normalization_url(base_address, *args):
452
+ if base_address:
453
+ url = base_address
454
+ else:
455
+ url = dashscope.base_http_api_url
456
+ return join_url(url, *args)
457
+
458
+
139
459
  class AsyncTaskGetMixin():
140
460
  @classmethod
141
- def _get(cls, task_id: str, api_key: str = None) -> DashScopeAPIResponse:
142
- status_url = _normalization_url('tasks', task_id)
461
+ def _get(cls,
462
+ task_id: str,
463
+ api_key: str = None,
464
+ workspace: str = None,
465
+ **kwargs) -> DashScopeAPIResponse:
466
+ base_url = kwargs.pop('base_address', None)
467
+ status_url = _normalization_url(base_url, 'tasks', task_id)
468
+ custom_headers = kwargs.pop('headers', None)
469
+ headers = {
470
+ **_workspace_header(workspace),
471
+ **default_headers(api_key),
472
+ }
473
+ if custom_headers:
474
+ headers = {
475
+ **custom_headers,
476
+ **headers,
477
+ }
143
478
  with requests.Session() as session:
144
479
  logger.debug('Starting request: %s' % status_url)
145
480
  response = session.get(status_url,
146
- headers={
147
- **default_headers(api_key),
148
- },
481
+ headers=headers,
149
482
  timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
150
483
  logger.debug('Starting processing response: %s' % status_url)
151
484
  return _handle_http_response(response)
@@ -164,11 +497,20 @@ class BaseAsyncApi(AsyncTaskGetMixin):
164
497
  return api_key, model
165
498
 
166
499
  @classmethod
167
- def call(cls, *args, **kwargs) -> DashScopeAPIResponse:
500
+ def call(cls,
501
+ *args,
502
+ api_key: str = None,
503
+ workspace: str = None,
504
+ **kwargs) -> DashScopeAPIResponse:
168
505
  """Call service and get result.
169
506
  """
170
- task_response = cls.async_call(*args, **kwargs)
171
- response = cls.wait(task_response)
507
+ task_response = cls.async_call(*args,
508
+ api_key=api_key,
509
+ workspace=workspace,
510
+ **kwargs)
511
+ response = cls.wait(task_response,
512
+ api_key=api_key,
513
+ workspace=workspace)
172
514
  return response
173
515
 
174
516
  @classmethod
@@ -182,7 +524,9 @@ class BaseAsyncApi(AsyncTaskGetMixin):
182
524
  raise InvalidTask('Invalid task, task create failed: %s' %
183
525
  task)
184
526
  else:
185
- raise InvalidParameter('task invalid!')
527
+ raise InvalidParameter('Task invalid!')
528
+ if task_id is None or task_id == '':
529
+ raise InvalidParameter('Task id required!')
186
530
  return task_id
187
531
 
188
532
  @classmethod
@@ -190,6 +534,8 @@ class BaseAsyncApi(AsyncTaskGetMixin):
190
534
  cls,
191
535
  task: Union[str, DashScopeAPIResponse],
192
536
  api_key: str = None,
537
+ workspace: str = None,
538
+ **kwargs,
193
539
  ) -> DashScopeAPIResponse:
194
540
  """Cancel PENDING task.
195
541
 
@@ -202,10 +548,12 @@ class BaseAsyncApi(AsyncTaskGetMixin):
202
548
  DashScopeAPIResponse: The cancel result.
203
549
  """
204
550
  task_id = cls._get_task_id(task)
205
- url = _normalization_url('tasks', task_id, 'cancel')
551
+ base_url = kwargs.pop('base_address', None)
552
+ url = _normalization_url(base_url, 'tasks', task_id, 'cancel')
206
553
  with requests.Session() as session:
207
554
  response = session.post(url,
208
555
  headers={
556
+ **_workspace_header(workspace),
209
557
  **default_headers(api_key),
210
558
  })
211
559
  return _handle_http_response(response)
@@ -221,6 +569,7 @@ class BaseAsyncApi(AsyncTaskGetMixin):
221
569
  page_no: int = 1,
222
570
  page_size: int = 10,
223
571
  api_key: str = None,
572
+ workspace: str = None,
224
573
  **kwargs) -> DashScopeAPIResponse:
225
574
  """List async tasks.
226
575
 
@@ -229,8 +578,10 @@ class BaseAsyncApi(AsyncTaskGetMixin):
229
578
  for example: 20230420000000. Defaults to None.
230
579
  end_time (str, optional): The tasks end time,
231
580
  for example: 20230420000000. Defaults to None.
232
- model_name (str, optional): The tasks model name. Defaults to None.
233
- api_key_id (str, optional): The tasks api-key-id. Defaults to None.
581
+ model_name (str, optional): The tasks model name.
582
+ Defaults to None.
583
+ api_key_id (str, optional): The tasks api-key-id.
584
+ Defaults to None.
234
585
  region (str, optional): The service region,
235
586
  for example: cn-beijing. Defaults to None.
236
587
  status (str, optional): The status of tasks[PENDING,
@@ -242,7 +593,8 @@ class BaseAsyncApi(AsyncTaskGetMixin):
242
593
  Returns:
243
594
  DashScopeAPIResponse: The response data.
244
595
  """
245
- url = _normalization_url('tasks')
596
+ base_url = kwargs.pop('base_address', None)
597
+ url = _normalization_url(base_url, 'tasks')
246
598
  params = {'page_no': page_no, 'page_size': page_size}
247
599
  if start_time is not None:
248
600
  params['start_time'] = start_time
@@ -261,6 +613,7 @@ class BaseAsyncApi(AsyncTaskGetMixin):
261
613
  response = session.get(url,
262
614
  params=params,
263
615
  headers={
616
+ **_workspace_header(workspace),
264
617
  **default_headers(api_key),
265
618
  })
266
619
  if response.status_code == HTTPStatus.OK:
@@ -283,6 +636,8 @@ class BaseAsyncApi(AsyncTaskGetMixin):
283
636
  cls,
284
637
  task: Union[str, DashScopeAPIResponse],
285
638
  api_key: str = None,
639
+ workspace: str = None,
640
+ **kwargs,
286
641
  ) -> DashScopeAPIResponse:
287
642
  """Query async task status.
288
643
 
@@ -295,12 +650,13 @@ class BaseAsyncApi(AsyncTaskGetMixin):
295
650
  DashScopeAPIResponse: The async task information.
296
651
  """
297
652
  task_id = cls._get_task_id(task)
298
- return cls._get(task_id, api_key)
653
+ return cls._get(task_id, api_key, workspace, **kwargs)
299
654
 
300
655
  @classmethod
301
656
  def wait(cls,
302
657
  task: Union[str, DashScopeAPIResponse],
303
658
  api_key: str = None,
659
+ workspace: str = None,
304
660
  **kwargs) -> DashScopeAPIResponse:
305
661
  """Wait for async task completion and return task result.
306
662
 
@@ -313,8 +669,21 @@ class BaseAsyncApi(AsyncTaskGetMixin):
313
669
  DashScopeAPIResponse: The async task information.
314
670
  """
315
671
  task_id = cls._get_task_id(task)
672
+ wait_seconds = 1
673
+ max_wait_seconds = 5
674
+ increment_steps = 3
675
+ step = 0
316
676
  while True:
317
- rsp = cls._get(task_id, api_key)
677
+ step += 1
678
+ # we start by querying once every second, and double
679
+ # the query interval after every 3(increment_steps)
680
+ # intervals, until we hit the max waiting interval
681
+ # of 5(seconds)
682
+ # TODO: investigate if we can use long-poll
683
+ # (server side return immediately when ready)
684
+ if wait_seconds < max_wait_seconds and step % increment_steps == 0:
685
+ wait_seconds = min(wait_seconds * 2, max_wait_seconds)
686
+ rsp = cls._get(task_id, api_key, workspace=workspace, **kwargs)
318
687
  if rsp.status_code == HTTPStatus.OK:
319
688
  if rsp.output is None:
320
689
  return rsp
@@ -327,13 +696,13 @@ class BaseAsyncApi(AsyncTaskGetMixin):
327
696
  return rsp
328
697
  else:
329
698
  logger.info('The task %s is %s' % (task_id, task_status))
330
- time.sleep(5)
699
+ time.sleep(wait_seconds)
331
700
  elif rsp.status_code in REPEATABLE_STATUS:
332
701
  logger.warn(
333
702
  ('Get task: %s temporary failure, \
334
703
  status_code: %s, code: %s message: %s, will try again.'
335
704
  ) % (task_id, rsp.status_code, rsp.code, rsp.message))
336
- time.sleep(5)
705
+ time.sleep(wait_seconds)
337
706
  else:
338
707
  return rsp
339
708
 
@@ -345,6 +714,7 @@ class BaseAsyncApi(AsyncTaskGetMixin):
345
714
  task: str = None,
346
715
  function: str = None,
347
716
  api_key: str = None,
717
+ workspace: str = None,
348
718
  **kwargs) -> DashScopeAPIResponse:
349
719
  """Call async service return async task information.
350
720
 
@@ -367,6 +737,12 @@ class BaseAsyncApi(AsyncTaskGetMixin):
367
737
  if is_stream:
368
738
  logger.warn('async_call do not support stream argument')
369
739
  api_key, model = BaseApi._validate_params(api_key, model)
740
+ if workspace is not None:
741
+ headers = {
742
+ 'X-DashScope-WorkSpace': workspace,
743
+ **kwargs.pop('headers', {})
744
+ }
745
+ kwargs['headers'] = headers
370
746
  request = _build_api_request(model=model,
371
747
  input=input,
372
748
  task_group=task_group,
@@ -379,20 +755,83 @@ class BaseAsyncApi(AsyncTaskGetMixin):
379
755
  return request.call()
380
756
 
381
757
 
382
- def _get(url, params={}, api_key=None, **kwargs) -> DashScopeAPIResponse:
758
+ def _get(url,
759
+ params={},
760
+ api_key=None,
761
+ flattened_output=False,
762
+ workspace: str = None,
763
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
383
764
  timeout = kwargs.pop(REQUEST_TIMEOUT_KEYWORD,
384
765
  DEFAULT_REQUEST_TIMEOUT_SECONDS)
385
766
  with requests.Session() as session:
386
767
  logger.debug('Starting request: %s' % url)
387
768
  response = session.get(url,
388
769
  headers={
770
+ **_workspace_header(workspace),
389
771
  **default_headers(api_key),
390
772
  **kwargs.pop('headers', {})
391
773
  },
392
774
  params=params,
393
775
  timeout=timeout)
394
776
  logger.debug('Starting processing response: %s' % url)
395
- return _handle_http_response(response)
777
+ return _handle_http_response(response, flattened_output)
778
+
779
+
780
+ def _get_url(custom_base_url, default_path, path):
781
+ if not custom_base_url:
782
+ base_url = dashscope.base_http_api_url
783
+ else:
784
+ base_url = custom_base_url
785
+ if path is not None:
786
+ url = join_url(base_url, path)
787
+ else:
788
+ url = join_url(base_url, default_path)
789
+ return url
790
+
791
+
792
+ class ListObjectMixin():
793
+ @classmethod
794
+ def list(cls,
795
+ limit: int = None,
796
+ order: str = None,
797
+ after: str = None,
798
+ before: str = None,
799
+ path: str = None,
800
+ workspace: str = None,
801
+ api_key: str = None,
802
+ **kwargs) -> Any:
803
+ """List object
804
+
805
+ Args:
806
+ limit (int, optional): How many object to list. Defaults to None.
807
+ order (str, optional): The order of result. Defaults to None.
808
+ after (str, optional): The id of the object begin. Defaults to None.
809
+ before (str, optional): The if of the object end. Defaults to None.
810
+ path (str, optional): The request path. Defaults to None.
811
+ workspace (str, optional): The DashScope workspace id. Defaults to None.
812
+ api_key (str, optional): The DashScope api_key. Defaults to None.
813
+
814
+ Returns:
815
+ Any: The object list.
816
+ """
817
+ custom_base_url = kwargs.pop('base_address', None)
818
+ url = _get_url(custom_base_url, cls.SUB_PATH.lower(), path)
819
+ params = {}
820
+ if limit is not None:
821
+ if limit < 0:
822
+ raise InvalidParameter('limit should >= 0')
823
+ params['limit'] = limit
824
+ if order is not None:
825
+ params['order'] = order
826
+ if after is not None:
827
+ params['after'] = after
828
+ if before is not None:
829
+ params['before'] = before
830
+ return _get(url,
831
+ params=params,
832
+ api_key=api_key,
833
+ workspace=workspace,
834
+ **kwargs)
396
835
 
397
836
 
398
837
  class ListMixin():
@@ -401,21 +840,29 @@ class ListMixin():
401
840
  page_no=1,
402
841
  page_size=10,
403
842
  api_key: str = None,
404
- **kwargs) -> DashScopeAPIResponse:
843
+ path: str = None,
844
+ workspace: str = None,
845
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
405
846
  """list objects
406
847
 
407
848
  Args:
408
849
  api_key (str, optional): The api api_key, if not present,
409
850
  will get by default rule(TODO: api key doc). Defaults to None.
851
+ path (str, optional): The path of the api, if not default.
410
852
  page_no (int, optional): Page number. Defaults to 1.
411
853
  page_size (int, optional): Items per page. Defaults to 10.
412
854
 
413
855
  Returns:
414
856
  DashScopeAPIResponse: The object list in output.
415
857
  """
416
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower())
858
+ custom_base_url = kwargs.pop('base_address', None)
859
+ url = _get_url(custom_base_url, cls.SUB_PATH.lower(), path)
417
860
  params = {'page_no': page_no, 'page_size': page_size}
418
- return _get(url, params=params, api_key=api_key, **kwargs)
861
+ return _get(url,
862
+ params=params,
863
+ api_key=api_key,
864
+ workspace=workspace,
865
+ **kwargs)
419
866
 
420
867
 
421
868
  class LogMixin():
@@ -425,7 +872,9 @@ class LogMixin():
425
872
  offset=1,
426
873
  line=1000,
427
874
  api_key: str = None,
428
- **kwargs) -> DashScopeAPIResponse:
875
+ path: str = None,
876
+ workspace: str = None,
877
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
429
878
  """Get log of the job.
430
879
 
431
880
  Args:
@@ -437,10 +886,18 @@ class LogMixin():
437
886
  Returns:
438
887
  DashScopeAPIResponse: The response
439
888
  """
440
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
441
- job_id, 'logs')
889
+ custom_base_url = kwargs.pop('base_address', None)
890
+ if not custom_base_url:
891
+ url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
892
+ job_id, 'logs')
893
+ else:
894
+ url = custom_base_url
442
895
  params = {'offset': offset, 'line': line}
443
- return _get(url, params=params, api_key=api_key, **kwargs)
896
+ return _get(url,
897
+ params=params,
898
+ api_key=api_key,
899
+ workspace=workspace,
900
+ **kwargs)
444
901
 
445
902
 
446
903
  class GetMixin():
@@ -448,7 +905,10 @@ class GetMixin():
448
905
  def get(cls,
449
906
  target,
450
907
  api_key: str = None,
451
- **kwargs) -> DashScopeAPIResponse:
908
+ params: dict = {},
909
+ path: str = None,
910
+ workspace: str = None,
911
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
452
912
  """Get object information.
453
913
 
454
914
  Args:
@@ -459,9 +919,23 @@ class GetMixin():
459
919
  Returns:
460
920
  DashScopeAPIResponse: The object information in output.
461
921
  """
462
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
463
- target)
464
- return _get(url, api_key, **kwargs)
922
+ custom_base_url = kwargs.pop('base_address', None)
923
+ if custom_base_url:
924
+ base_url = custom_base_url
925
+ else:
926
+ base_url = dashscope.base_http_api_url
927
+
928
+ if path is not None:
929
+ url = join_url(base_url, path)
930
+ else:
931
+ url = join_url(base_url, cls.SUB_PATH.lower(), target)
932
+ flattened_output = kwargs.pop('flattened_output', False)
933
+ return _get(url,
934
+ api_key=api_key,
935
+ params=params,
936
+ flattened_output=flattened_output,
937
+ workspace=workspace,
938
+ **kwargs)
465
939
 
466
940
 
467
941
  class GetStatusMixin():
@@ -469,7 +943,9 @@ class GetStatusMixin():
469
943
  def get(cls,
470
944
  target,
471
945
  api_key: str = None,
472
- **kwargs) -> DashScopeAPIResponse:
946
+ path: str = None,
947
+ workspace: str = None,
948
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
473
949
  """Get object information.
474
950
 
475
951
  Args:
@@ -480,9 +956,21 @@ class GetStatusMixin():
480
956
  Returns:
481
957
  DashScopeAPIResponse: The object information in output.
482
958
  """
483
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
484
- target)
485
- return _get(url, api_key, **kwargs)
959
+ custom_base_url = kwargs.pop('base_address', None)
960
+ if custom_base_url:
961
+ base_url = custom_base_url
962
+ else:
963
+ base_url = dashscope.base_http_api_url
964
+ if path is not None:
965
+ url = join_url(base_url, path)
966
+ else:
967
+ url = join_url(base_url, cls.SUB_PATH.lower(), target)
968
+ flattened_output = kwargs.pop('flattened_output', False)
969
+ return _get(url,
970
+ api_key=api_key,
971
+ flattened_output=flattened_output,
972
+ workspace=workspace,
973
+ **kwargs)
486
974
 
487
975
 
488
976
  class DeleteMixin():
@@ -490,7 +978,10 @@ class DeleteMixin():
490
978
  def delete(cls,
491
979
  target: str,
492
980
  api_key: str = None,
493
- **kwargs) -> DashScopeAPIResponse:
981
+ path: str = None,
982
+ workspace: str = None,
983
+ flattened_output=False,
984
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
494
985
  """Delete object.
495
986
 
496
987
  Args:
@@ -501,20 +992,28 @@ class DeleteMixin():
501
992
  Returns:
502
993
  DashScopeAPIResponse: The delete result.
503
994
  """
504
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
505
- target)
995
+ custom_base_url = kwargs.pop('base_address', None)
996
+ if custom_base_url:
997
+ base_url = custom_base_url
998
+ else:
999
+ base_url = dashscope.base_http_api_url
1000
+ if path is not None:
1001
+ url = join_url(base_url, path)
1002
+ else:
1003
+ url = join_url(base_url, cls.SUB_PATH.lower(), target)
506
1004
  timeout = kwargs.pop(REQUEST_TIMEOUT_KEYWORD,
507
1005
  DEFAULT_REQUEST_TIMEOUT_SECONDS)
508
1006
  with requests.Session() as session:
509
1007
  logger.debug('Starting request: %s' % url)
510
1008
  response = session.delete(url,
511
1009
  headers={
1010
+ **_workspace_header(workspace),
512
1011
  **default_headers(api_key),
513
1012
  **kwargs.pop('headers', {})
514
1013
  },
515
1014
  timeout=timeout)
516
1015
  logger.debug('Starting processing response: %s' % url)
517
- return _handle_http_response(response)
1016
+ return _handle_http_response(response, flattened_output)
518
1017
 
519
1018
 
520
1019
  class CreateMixin():
@@ -522,7 +1021,10 @@ class CreateMixin():
522
1021
  def call(cls,
523
1022
  data: object,
524
1023
  api_key: str = None,
525
- **kwargs) -> DashScopeAPIResponse:
1024
+ path: str = None,
1025
+ stream: bool = False,
1026
+ workspace: str = None,
1027
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
526
1028
  """Create a object
527
1029
 
528
1030
  Args:
@@ -533,20 +1035,33 @@ class CreateMixin():
533
1035
  Returns:
534
1036
  DashScopeAPIResponse: The created object in output.
535
1037
  """
536
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower())
1038
+ url = _get_url(kwargs.pop('base_address', None), cls.SUB_PATH.lower(),
1039
+ path)
537
1040
  timeout = kwargs.pop(REQUEST_TIMEOUT_KEYWORD,
538
1041
  DEFAULT_REQUEST_TIMEOUT_SECONDS)
1042
+ flattened_output = kwargs.pop('flattened_output', False)
539
1043
  with requests.Session() as session:
540
1044
  logger.debug('Starting request: %s' % url)
541
1045
  response = session.post(url,
542
1046
  json=data,
1047
+ stream=stream,
543
1048
  headers={
1049
+ **_workspace_header(workspace),
544
1050
  **default_headers(api_key),
545
1051
  **kwargs.pop('headers', {})
546
1052
  },
547
1053
  timeout=timeout)
548
1054
  logger.debug('Starting processing response: %s' % url)
549
- return _handle_http_response(response)
1055
+ response = _handle_http_stream_response(response, flattened_output)
1056
+ if stream:
1057
+ return (item for item in response)
1058
+ else:
1059
+ _, output = next(response)
1060
+ try:
1061
+ next(response)
1062
+ except StopIteration:
1063
+ pass
1064
+ return output
550
1065
 
551
1066
 
552
1067
  class UpdateMixin():
@@ -555,7 +1070,10 @@ class UpdateMixin():
555
1070
  target: str,
556
1071
  json: object,
557
1072
  api_key: str = None,
558
- **kwargs) -> DashScopeAPIResponse:
1073
+ path: str = None,
1074
+ workspace: str = None,
1075
+ method: str = 'patch',
1076
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
559
1077
  """Async update a object
560
1078
 
561
1079
  Args:
@@ -567,21 +1085,40 @@ class UpdateMixin():
567
1085
  Returns:
568
1086
  DashScopeAPIResponse: The updated object information in output.
569
1087
  """
570
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
571
- target)
1088
+ custom_base_url = kwargs.pop('base_address', None)
1089
+ if custom_base_url:
1090
+ base_url = custom_base_url
1091
+ else:
1092
+ base_url = dashscope.base_http_api_url
1093
+ if path is not None:
1094
+ url = join_url(base_url, path)
1095
+ else:
1096
+ url = join_url(base_url, cls.SUB_PATH.lower(), target)
572
1097
  timeout = kwargs.pop(REQUEST_TIMEOUT_KEYWORD,
573
1098
  DEFAULT_REQUEST_TIMEOUT_SECONDS)
1099
+ flattened_output = kwargs.pop('flattened_output', False)
574
1100
  with requests.Session() as session:
575
1101
  logger.debug('Starting request: %s' % url)
576
- response = session.patch(url,
577
- json=json,
578
- headers={
579
- **default_headers(api_key),
580
- **kwargs.pop('headers', {})
581
- },
582
- timeout=timeout)
1102
+ if method == 'post':
1103
+ response = session.post(url,
1104
+ json=json,
1105
+ headers={
1106
+ **_workspace_header(workspace),
1107
+ **default_headers(api_key),
1108
+ **kwargs.pop('headers', {})
1109
+ },
1110
+ timeout=timeout)
1111
+ else:
1112
+ response = session.patch(url,
1113
+ json=json,
1114
+ headers={
1115
+ **_workspace_header(workspace),
1116
+ **default_headers(api_key),
1117
+ **kwargs.pop('headers', {})
1118
+ },
1119
+ timeout=timeout)
583
1120
  logger.debug('Starting processing response: %s' % url)
584
- return _handle_http_response(response)
1121
+ return _handle_http_response(response, flattened_output)
585
1122
 
586
1123
 
587
1124
  class PutMixin():
@@ -589,9 +1126,10 @@ class PutMixin():
589
1126
  def put(cls,
590
1127
  target: str,
591
1128
  json: object,
592
- extra_path: str = None,
1129
+ path: str = None,
593
1130
  api_key: str = None,
594
- **kwargs) -> DashScopeAPIResponse:
1131
+ workspace: str = None,
1132
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
595
1133
  """Async update a object
596
1134
 
597
1135
  Args:
@@ -603,13 +1141,15 @@ class PutMixin():
603
1141
  Returns:
604
1142
  DashScopeAPIResponse: The updated object information in output.
605
1143
  """
606
- if extra_path is None:
607
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
608
- target)
1144
+ custom_base_url = kwargs.pop('base_address', None)
1145
+ if custom_base_url:
1146
+ base_url = custom_base_url
609
1147
  else:
610
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
611
- target, extra_path)
612
- print(url)
1148
+ base_url = dashscope.base_http_api_url
1149
+ if path is None:
1150
+ url = join_url(base_url, cls.SUB_PATH.lower(), target)
1151
+ else:
1152
+ url = join_url(base_url, path)
613
1153
  timeout = kwargs.pop(REQUEST_TIMEOUT_KEYWORD,
614
1154
  DEFAULT_REQUEST_TIMEOUT_SECONDS)
615
1155
  with requests.Session() as session:
@@ -617,6 +1157,7 @@ class PutMixin():
617
1157
  response = session.put(url,
618
1158
  json=json,
619
1159
  headers={
1160
+ **_workspace_header(workspace),
620
1161
  **default_headers(api_key),
621
1162
  **kwargs.pop('headers', {})
622
1163
  },
@@ -632,7 +1173,8 @@ class FileUploadMixin():
632
1173
  descriptions: List[str] = None,
633
1174
  params: dict = None,
634
1175
  api_key: str = None,
635
- **kwargs) -> DashScopeAPIResponse:
1176
+ workspace: str = None,
1177
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
636
1178
  """Upload files
637
1179
 
638
1180
  Args:
@@ -645,7 +1187,12 @@ class FileUploadMixin():
645
1187
  Returns:
646
1188
  DashScopeAPIResponse: The uploaded file information in the output.
647
1189
  """
648
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower())
1190
+ custom_base_url = kwargs.pop('base_address', None)
1191
+ if custom_base_url:
1192
+ base_url = custom_base_url
1193
+ else:
1194
+ base_url = dashscope.base_http_api_url
1195
+ url = join_url(base_url, cls.SUB_PATH.lower())
649
1196
  js = None
650
1197
  if descriptions:
651
1198
  js = {'descriptions': descriptions}
@@ -656,6 +1203,7 @@ class FileUploadMixin():
656
1203
  response = session.post(url,
657
1204
  data=js,
658
1205
  headers={
1206
+ **_workspace_header(workspace),
659
1207
  **default_headers(api_key),
660
1208
  **kwargs.pop('headers', {})
661
1209
  },
@@ -669,8 +1217,10 @@ class CancelMixin():
669
1217
  @classmethod
670
1218
  def cancel(cls,
671
1219
  target: str,
1220
+ path: str = None,
672
1221
  api_key: str = None,
673
- **kwargs) -> DashScopeAPIResponse:
1222
+ workspace: str = None,
1223
+ **kwargs) -> Union[DashScopeAPIResponse, Dict]:
674
1224
  """Cancel a job.
675
1225
 
676
1226
  Args:
@@ -681,20 +1231,29 @@ class CancelMixin():
681
1231
  Returns:
682
1232
  DashScopeAPIResponse: The cancel result.
683
1233
  """
684
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
685
- target, 'cancel')
1234
+ custom_base_url = kwargs.pop('base_address', None)
1235
+ if custom_base_url:
1236
+ base_url = custom_base_url
1237
+ else:
1238
+ base_url = dashscope.base_http_api_url
1239
+ if not path:
1240
+ url = join_url(base_url, cls.SUB_PATH.lower(), target, 'cancel')
1241
+ else:
1242
+ url = join_url(base_url, path)
686
1243
  timeout = kwargs.pop(REQUEST_TIMEOUT_KEYWORD,
687
1244
  DEFAULT_REQUEST_TIMEOUT_SECONDS)
1245
+ flattened_output = kwargs.pop('flattened_output', False)
688
1246
  with requests.Session() as session:
689
1247
  logger.debug('Starting request: %s' % url)
690
1248
  response = session.post(url,
691
1249
  headers={
1250
+ **_workspace_header(workspace),
692
1251
  **default_headers(api_key),
693
1252
  **kwargs.pop('headers', {})
694
1253
  },
695
1254
  timeout=timeout)
696
1255
  logger.debug('Starting processing response: %s' % url)
697
- return _handle_http_response(response)
1256
+ return _handle_http_response(response, flattened_output)
698
1257
 
699
1258
 
700
1259
  class StreamEventMixin():
@@ -748,13 +1307,14 @@ class StreamEventMixin():
748
1307
  output=json_content,
749
1308
  usage=None)
750
1309
  else:
751
- _handle_http_failed_response(response)
1310
+ yield _handle_http_failed_response(response)
752
1311
 
753
1312
  @classmethod
754
1313
  def stream_events(cls,
755
1314
  target,
756
1315
  api_key: str = None,
757
- **kwargs) -> DashScopeAPIResponse:
1316
+ workspace: str = None,
1317
+ **kwargs) -> Iterator[DashScopeAPIResponse]:
758
1318
  """Get job log.
759
1319
 
760
1320
  Args:
@@ -765,14 +1325,19 @@ class StreamEventMixin():
765
1325
  Returns:
766
1326
  DashScopeAPIResponse: The target outputs.
767
1327
  """
768
- url = join_url(dashscope.base_http_api_url, cls.SUB_PATH.lower(),
769
- target, 'stream')
1328
+ custom_base_url = kwargs.pop('base_address', None)
1329
+ if custom_base_url:
1330
+ base_url = custom_base_url
1331
+ else:
1332
+ base_url = dashscope.base_http_api_url
1333
+ url = join_url(base_url, cls.SUB_PATH.lower(), target, 'stream')
770
1334
  timeout = kwargs.pop(REQUEST_TIMEOUT_KEYWORD,
771
1335
  DEFAULT_REQUEST_TIMEOUT_SECONDS)
772
1336
  with requests.Session() as session:
773
1337
  logger.debug('Starting request: %s' % url)
774
1338
  response = session.get(url,
775
1339
  headers={
1340
+ **_workspace_header(workspace),
776
1341
  **default_headers(api_key),
777
1342
  **kwargs.pop('headers', {})
778
1343
  },