dashscope 1.21.0__py3-none-any.whl → 1.22.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.
- dashscope/api_entities/aiohttp_request.py +0 -1
- dashscope/api_entities/api_request_data.py +0 -1
- dashscope/api_entities/api_request_factory.py +3 -1
- dashscope/api_entities/http_request.py +0 -1
- dashscope/api_entities/websocket_request.py +24 -3
- dashscope/audio/asr/__init__.py +10 -1
- dashscope/audio/asr/recognition.py +61 -22
- dashscope/audio/asr/translation_recognizer.py +1004 -0
- dashscope/audio/tts_v2/enrollment.py +1 -1
- dashscope/audio/tts_v2/speech_synthesizer.py +16 -1
- dashscope/client/base_api.py +4 -5
- dashscope/common/utils.py +0 -1
- dashscope/embeddings/batch_text_embedding_response.py +0 -1
- dashscope/utils/oss_utils.py +0 -1
- dashscope/version.py +1 -1
- {dashscope-1.21.0.dist-info → dashscope-1.22.0.dist-info}/METADATA +1 -1
- {dashscope-1.21.0.dist-info → dashscope-1.22.0.dist-info}/RECORD +21 -20
- {dashscope-1.21.0.dist-info → dashscope-1.22.0.dist-info}/LICENSE +0 -0
- {dashscope-1.21.0.dist-info → dashscope-1.22.0.dist-info}/WHEEL +0 -0
- {dashscope-1.21.0.dist-info → dashscope-1.22.0.dist-info}/entry_points.txt +0 -0
- {dashscope-1.21.0.dist-info → dashscope-1.22.0.dist-info}/top_level.txt +0 -0
|
@@ -2,7 +2,6 @@ import json
|
|
|
2
2
|
from http import HTTPStatus
|
|
3
3
|
|
|
4
4
|
import aiohttp
|
|
5
|
-
|
|
6
5
|
from dashscope.api_entities.base_request import AioBaseRequest
|
|
7
6
|
from dashscope.api_entities.dashscope_response import DashScopeAPIResponse
|
|
8
7
|
from dashscope.common.constants import (DEFAULT_REQUEST_TIMEOUT_SECONDS,
|
|
@@ -81,13 +81,15 @@ def _build_api_request(model: str,
|
|
|
81
81
|
websocket_url = base_address
|
|
82
82
|
else:
|
|
83
83
|
websocket_url = dashscope.base_websocket_api_url
|
|
84
|
+
pre_task_id = kwargs.pop('pre_task_id', None)
|
|
84
85
|
request = WebSocketRequest(url=websocket_url,
|
|
85
86
|
api_key=api_key,
|
|
86
87
|
stream=stream,
|
|
87
88
|
ws_stream_mode=ws_stream_mode,
|
|
88
89
|
is_binary_input=is_binary_input,
|
|
89
90
|
timeout=request_timeout,
|
|
90
|
-
flattened_output=flattened_output
|
|
91
|
+
flattened_output=flattened_output,
|
|
92
|
+
pre_task_id=pre_task_id)
|
|
91
93
|
else:
|
|
92
94
|
raise UnsupportedApiProtocol(
|
|
93
95
|
'Unsupported protocol: %s, support [http, https, websocket]' %
|
|
@@ -3,7 +3,6 @@ from http import HTTPStatus
|
|
|
3
3
|
|
|
4
4
|
import aiohttp
|
|
5
5
|
import requests
|
|
6
|
-
|
|
7
6
|
from dashscope.api_entities.base_request import AioBaseRequest
|
|
8
7
|
from dashscope.api_entities.dashscope_response import DashScopeAPIResponse
|
|
9
8
|
from dashscope.common.constants import (DEFAULT_REQUEST_TIMEOUT_SECONDS,
|
|
@@ -5,7 +5,6 @@ from http import HTTPStatus
|
|
|
5
5
|
from typing import Tuple, Union
|
|
6
6
|
|
|
7
7
|
import aiohttp
|
|
8
|
-
|
|
9
8
|
from dashscope.api_entities.base_request import AioBaseRequest
|
|
10
9
|
from dashscope.api_entities.dashscope_response import DashScopeAPIResponse
|
|
11
10
|
from dashscope.common.constants import (DEFAULT_REQUEST_TIMEOUT_SECONDS,
|
|
@@ -31,6 +30,7 @@ class WebSocketRequest(AioBaseRequest):
|
|
|
31
30
|
is_binary_input: bool = False,
|
|
32
31
|
timeout: int = DEFAULT_REQUEST_TIMEOUT_SECONDS,
|
|
33
32
|
flattened_output: bool = False,
|
|
33
|
+
pre_task_id=None,
|
|
34
34
|
) -> None:
|
|
35
35
|
super().__init__()
|
|
36
36
|
"""HttpRequest.
|
|
@@ -61,6 +61,7 @@ class WebSocketRequest(AioBaseRequest):
|
|
|
61
61
|
self.task_headers = {
|
|
62
62
|
'streaming': self.ws_stream_mode,
|
|
63
63
|
}
|
|
64
|
+
self.pre_task_id = pre_task_id
|
|
64
65
|
|
|
65
66
|
def add_headers(self, headers):
|
|
66
67
|
self.headers = {**self.headers, **headers}
|
|
@@ -77,6 +78,10 @@ class WebSocketRequest(AioBaseRequest):
|
|
|
77
78
|
pass
|
|
78
79
|
return output
|
|
79
80
|
|
|
81
|
+
async def close(self):
|
|
82
|
+
if self.ws is not None and not self.ws.closed:
|
|
83
|
+
await self.ws.close()
|
|
84
|
+
|
|
80
85
|
async def aio_call(self):
|
|
81
86
|
response = self.connection_handler()
|
|
82
87
|
if self.stream:
|
|
@@ -140,7 +145,11 @@ class WebSocketRequest(AioBaseRequest):
|
|
|
140
145
|
code=e.name,
|
|
141
146
|
message=e.message)
|
|
142
147
|
except aiohttp.ClientConnectorError as e:
|
|
143
|
-
|
|
148
|
+
logger.exception(e)
|
|
149
|
+
yield DashScopeAPIResponse(request_id='',
|
|
150
|
+
status_code=-1,
|
|
151
|
+
code='ClientConnectorError',
|
|
152
|
+
message=str(e))
|
|
144
153
|
except aiohttp.WSServerHandshakeError as e:
|
|
145
154
|
code = e.status
|
|
146
155
|
msg = e.message
|
|
@@ -227,17 +236,22 @@ class WebSocketRequest(AioBaseRequest):
|
|
|
227
236
|
raise error
|
|
228
237
|
|
|
229
238
|
async def _start_task(self, ws):
|
|
230
|
-
self.
|
|
239
|
+
if self.pre_task_id is not None:
|
|
240
|
+
self.task_headers['task_id'] = self.pre_task_id
|
|
241
|
+
else:
|
|
242
|
+
self.task_headers['task_id'] = uuid.uuid4().hex # create task id.
|
|
231
243
|
task_header = {**self.task_headers, ACTION_KEY: ActionType.START}
|
|
232
244
|
# for binary data, the start action has no input, only parameters.
|
|
233
245
|
start_data = self.data.get_websocket_start_data()
|
|
234
246
|
message = self._build_up_message(task_header, start_data)
|
|
247
|
+
logger.debug('Send start task: {}'.format(message))
|
|
235
248
|
await ws.send_str(message)
|
|
236
249
|
|
|
237
250
|
async def _send_finished_task(self, ws):
|
|
238
251
|
task_header = {**self.task_headers, ACTION_KEY: ActionType.FINISHED}
|
|
239
252
|
payload = {'input': {}}
|
|
240
253
|
message = self._build_up_message(task_header, payload)
|
|
254
|
+
logger.debug('Send finish task: {}'.format(message))
|
|
241
255
|
await ws.send_str(message)
|
|
242
256
|
|
|
243
257
|
async def _send_continue_task_data(self, ws):
|
|
@@ -250,12 +264,19 @@ class WebSocketRequest(AioBaseRequest):
|
|
|
250
264
|
if len(input) > 0:
|
|
251
265
|
if isinstance(input, bytes):
|
|
252
266
|
await ws.send_bytes(input)
|
|
267
|
+
logger.debug(
|
|
268
|
+
'Send continue task with bytes: {}'.format(
|
|
269
|
+
len(input)))
|
|
253
270
|
else:
|
|
254
271
|
await ws.send_bytes(list(input.values())[0])
|
|
272
|
+
logger.debug(
|
|
273
|
+
'Send continue task with list[byte]: {}'.format(
|
|
274
|
+
len(input)))
|
|
255
275
|
else:
|
|
256
276
|
if len(input) > 0:
|
|
257
277
|
message = self._build_up_message(headers=headers,
|
|
258
278
|
payload=input)
|
|
279
|
+
logger.debug('Send continue task: {}'.format(message))
|
|
259
280
|
await ws.send_str(message)
|
|
260
281
|
await asyncio.sleep(0.000001)
|
|
261
282
|
|
dashscope/audio/asr/__init__.py
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
from .asr_phrase_manager import AsrPhraseManager
|
|
2
2
|
from .recognition import Recognition, RecognitionCallback, RecognitionResult
|
|
3
3
|
from .transcription import Transcription
|
|
4
|
+
from .translation_recognizer import (TranscriptionResult, Translation,
|
|
5
|
+
TranslationRecognizerCallback,
|
|
6
|
+
TranslationRecognizerChat,
|
|
7
|
+
TranslationRecognizerRealtime,
|
|
8
|
+
TranslationRecognizerResultPack,
|
|
9
|
+
TranslationResult)
|
|
4
10
|
from .vocabulary import VocabularyService, VocabularyServiceException
|
|
5
11
|
|
|
6
12
|
__all__ = [
|
|
7
13
|
'Transcription', 'Recognition', 'RecognitionCallback', 'RecognitionResult',
|
|
8
|
-
'AsrPhraseManager', 'VocabularyServiceException', 'VocabularyService'
|
|
14
|
+
'AsrPhraseManager', 'VocabularyServiceException', 'VocabularyService',
|
|
15
|
+
'TranslationRecognizerRealtime', 'TranslationRecognizerChat',
|
|
16
|
+
'TranslationRecognizerCallback', 'Translation', 'TranslationResult',
|
|
17
|
+
'TranscriptionResult', 'TranslationRecognizerResultPack'
|
|
9
18
|
]
|
|
@@ -2,7 +2,9 @@ import json
|
|
|
2
2
|
import os
|
|
3
3
|
import threading
|
|
4
4
|
import time
|
|
5
|
+
import uuid
|
|
5
6
|
from http import HTTPStatus
|
|
7
|
+
from queue import Queue
|
|
6
8
|
from threading import Timer
|
|
7
9
|
from typing import Any, Dict, List, Union
|
|
8
10
|
|
|
@@ -153,18 +155,22 @@ class Recognition(BaseApi):
|
|
|
153
155
|
self._recognition_once = False
|
|
154
156
|
self._callback = callback
|
|
155
157
|
self._running = False
|
|
156
|
-
self._stream_data =
|
|
158
|
+
self._stream_data = Queue()
|
|
157
159
|
self._worker = None
|
|
158
160
|
self._silence_timer = None
|
|
159
161
|
self._kwargs = kwargs
|
|
160
162
|
self._workspace = workspace
|
|
161
163
|
self._start_stream_timestamp = -1
|
|
162
164
|
self._first_package_timestamp = -1
|
|
165
|
+
self._stop_stream_timestamp = -1
|
|
166
|
+
self._on_complete_timestamp = -1
|
|
167
|
+
self.request_id_confirmed = False
|
|
168
|
+
self.last_request_id = uuid.uuid4().hex
|
|
163
169
|
|
|
164
170
|
def __del__(self):
|
|
165
171
|
if self._running:
|
|
166
172
|
self._running = False
|
|
167
|
-
self._stream_data
|
|
173
|
+
self._stream_data = Queue()
|
|
168
174
|
if self._worker is not None and self._worker.is_alive():
|
|
169
175
|
self._worker.join()
|
|
170
176
|
if self._silence_timer is not None and self._silence_timer.is_alive( # noqa E501
|
|
@@ -182,6 +188,9 @@ class Recognition(BaseApi):
|
|
|
182
188
|
for part in responses:
|
|
183
189
|
if part.status_code == HTTPStatus.OK:
|
|
184
190
|
if len(part.output) == 0:
|
|
191
|
+
self._on_complete_timestamp = time.time() * 1000
|
|
192
|
+
logger.debug('last package delay {}'.format(
|
|
193
|
+
self.get_last_package_delay()))
|
|
185
194
|
self._callback.on_complete()
|
|
186
195
|
else:
|
|
187
196
|
usage: Dict[str, Any] = None
|
|
@@ -190,12 +199,12 @@ class Recognition(BaseApi):
|
|
|
190
199
|
if (self._first_package_timestamp < 0):
|
|
191
200
|
self._first_package_timestamp = time.time() * 1000
|
|
192
201
|
logger.debug('first package delay {}'.format(
|
|
193
|
-
self.
|
|
194
|
-
self._start_stream_timestamp))
|
|
202
|
+
self.get_first_package_delay()))
|
|
195
203
|
sentence = part.output['sentence']
|
|
196
|
-
logger.debug(
|
|
197
|
-
|
|
198
|
-
|
|
204
|
+
logger.debug(
|
|
205
|
+
'Recv Result [rid:{}]:{}, isEnd: {}'.format(
|
|
206
|
+
part.request_id, sentence,
|
|
207
|
+
RecognitionResult.is_sentence_end(sentence)))
|
|
199
208
|
if part.usage is not None:
|
|
200
209
|
usage = {
|
|
201
210
|
'end_time':
|
|
@@ -203,6 +212,9 @@ class Recognition(BaseApi):
|
|
|
203
212
|
'usage': part.usage
|
|
204
213
|
}
|
|
205
214
|
usages = [usage]
|
|
215
|
+
if self.request_id_confirmed is False and part.request_id is not None:
|
|
216
|
+
self.last_request_id = part.request_id
|
|
217
|
+
self.request_id_confirmed = True
|
|
206
218
|
|
|
207
219
|
self._callback.on_event(
|
|
208
220
|
RecognitionResult(
|
|
@@ -210,7 +222,7 @@ class Recognition(BaseApi):
|
|
|
210
222
|
usages=usages))
|
|
211
223
|
else:
|
|
212
224
|
self._running = False
|
|
213
|
-
self._stream_data
|
|
225
|
+
self._stream_data = Queue()
|
|
214
226
|
self._callback.on_error(
|
|
215
227
|
RecognitionResult(
|
|
216
228
|
RecognitionResponse.from_api_response(part)))
|
|
@@ -242,6 +254,7 @@ class Recognition(BaseApi):
|
|
|
242
254
|
format=self.format,
|
|
243
255
|
stream=True,
|
|
244
256
|
workspace=self._workspace,
|
|
257
|
+
pre_task_id=self.last_request_id,
|
|
245
258
|
**self._kwargs)
|
|
246
259
|
return responses
|
|
247
260
|
|
|
@@ -276,6 +289,8 @@ class Recognition(BaseApi):
|
|
|
276
289
|
|
|
277
290
|
self._start_stream_timestamp = -1
|
|
278
291
|
self._first_package_timestamp = -1
|
|
292
|
+
self._stop_stream_timestamp = -1
|
|
293
|
+
self._on_complete_timestamp = -1
|
|
279
294
|
self._phrase = phrase_id
|
|
280
295
|
self._kwargs.update(**kwargs)
|
|
281
296
|
self._recognition_once = False
|
|
@@ -334,7 +349,7 @@ class Recognition(BaseApi):
|
|
|
334
349
|
raise FileNotFoundError('No such file or directory: ' + file)
|
|
335
350
|
|
|
336
351
|
self._recognition_once = True
|
|
337
|
-
self._stream_data
|
|
352
|
+
self._stream_data = Queue()
|
|
338
353
|
self._phrase = phrase_id
|
|
339
354
|
self._kwargs.update(**kwargs)
|
|
340
355
|
error_flag: bool = False
|
|
@@ -352,16 +367,17 @@ class Recognition(BaseApi):
|
|
|
352
367
|
if not audio_data:
|
|
353
368
|
break
|
|
354
369
|
else:
|
|
355
|
-
self._stream_data
|
|
370
|
+
self._stream_data.put(audio_data)
|
|
356
371
|
else:
|
|
357
372
|
raise InputDataRequired(
|
|
358
373
|
'The supplied file was empty (zero bytes long)')
|
|
359
374
|
f.close()
|
|
375
|
+
self._stop_stream_timestamp = time.time() * 1000
|
|
360
376
|
except Exception as e:
|
|
361
377
|
logger.error(e)
|
|
362
378
|
raise e
|
|
363
379
|
|
|
364
|
-
if
|
|
380
|
+
if not self._stream_data.empty():
|
|
365
381
|
self._running = True
|
|
366
382
|
responses = self.__launch_request()
|
|
367
383
|
for part in responses:
|
|
@@ -373,9 +389,10 @@ class Recognition(BaseApi):
|
|
|
373
389
|
self._first_package_timestamp -
|
|
374
390
|
self._start_stream_timestamp))
|
|
375
391
|
sentence = part.output['sentence']
|
|
376
|
-
logger.debug(
|
|
377
|
-
|
|
378
|
-
|
|
392
|
+
logger.debug(
|
|
393
|
+
'Recv Result [rid:{}]:{}, isEnd: {}'.format(
|
|
394
|
+
part.request_id, sentence,
|
|
395
|
+
RecognitionResult.is_sentence_end(sentence)))
|
|
379
396
|
if RecognitionResult.is_sentence_end(sentence):
|
|
380
397
|
sentences.append(sentence)
|
|
381
398
|
|
|
@@ -394,12 +411,16 @@ class Recognition(BaseApi):
|
|
|
394
411
|
error_flag = True
|
|
395
412
|
break
|
|
396
413
|
|
|
414
|
+
self._on_complete_timestamp = time.time() * 1000
|
|
415
|
+
logger.debug('last package delay {}'.format(
|
|
416
|
+
self.get_last_package_delay()))
|
|
417
|
+
|
|
397
418
|
if error_flag:
|
|
398
419
|
result = RecognitionResult(response)
|
|
399
420
|
else:
|
|
400
421
|
result = RecognitionResult(response, sentences, usages)
|
|
401
422
|
|
|
402
|
-
self._stream_data
|
|
423
|
+
self._stream_data = Queue()
|
|
403
424
|
self._recognition_once = False
|
|
404
425
|
self._running = False
|
|
405
426
|
|
|
@@ -414,10 +435,12 @@ class Recognition(BaseApi):
|
|
|
414
435
|
if self._running is False:
|
|
415
436
|
raise InvalidParameter('Speech recognition has stopped.')
|
|
416
437
|
|
|
438
|
+
self._stop_stream_timestamp = time.time() * 1000
|
|
439
|
+
|
|
417
440
|
self._running = False
|
|
418
441
|
if self._worker is not None and self._worker.is_alive():
|
|
419
442
|
self._worker.join()
|
|
420
|
-
self._stream_data
|
|
443
|
+
self._stream_data = Queue()
|
|
421
444
|
if self._silence_timer is not None and self._silence_timer.is_alive():
|
|
422
445
|
self._silence_timer.cancel()
|
|
423
446
|
self._silence_timer = None
|
|
@@ -436,7 +459,7 @@ class Recognition(BaseApi):
|
|
|
436
459
|
if (self._start_stream_timestamp < 0):
|
|
437
460
|
self._start_stream_timestamp = time.time() * 1000
|
|
438
461
|
logger.debug('send_audio_frame: {}'.format(len(buffer)))
|
|
439
|
-
self._stream_data
|
|
462
|
+
self._stream_data.put(buffer)
|
|
440
463
|
|
|
441
464
|
def _tidy_kwargs(self):
|
|
442
465
|
for k in self._kwargs.copy():
|
|
@@ -445,8 +468,9 @@ class Recognition(BaseApi):
|
|
|
445
468
|
|
|
446
469
|
def _input_stream_cycle(self):
|
|
447
470
|
while self._running:
|
|
448
|
-
while
|
|
471
|
+
while self._stream_data.empty():
|
|
449
472
|
if self._running:
|
|
473
|
+
time.sleep(0.01)
|
|
450
474
|
continue
|
|
451
475
|
else:
|
|
452
476
|
break
|
|
@@ -459,16 +483,17 @@ class Recognition(BaseApi):
|
|
|
459
483
|
self._silence_stop_timer)
|
|
460
484
|
self._silence_timer.start()
|
|
461
485
|
|
|
462
|
-
|
|
486
|
+
while not self._stream_data.empty():
|
|
487
|
+
frame = self._stream_data.get()
|
|
463
488
|
yield bytes(frame)
|
|
464
|
-
self._stream_data.clear()
|
|
465
489
|
|
|
466
490
|
if self._recognition_once:
|
|
467
491
|
self._running = False
|
|
468
492
|
|
|
469
493
|
# drain all audio data when invoking stop().
|
|
470
494
|
if self._recognition_once is False:
|
|
471
|
-
|
|
495
|
+
while not self._stream_data.empty():
|
|
496
|
+
frame = self._stream_data.get()
|
|
472
497
|
yield bytes(frame)
|
|
473
498
|
|
|
474
499
|
def _silence_stop_timer(self):
|
|
@@ -480,4 +505,18 @@ class Recognition(BaseApi):
|
|
|
480
505
|
self._silence_timer = None
|
|
481
506
|
if self._worker is not None and self._worker.is_alive():
|
|
482
507
|
self._worker.join()
|
|
483
|
-
self._stream_data
|
|
508
|
+
self._stream_data = Queue()
|
|
509
|
+
|
|
510
|
+
def get_first_package_delay(self):
|
|
511
|
+
"""First Package Delay is the time between start sending audio and receive first words package
|
|
512
|
+
"""
|
|
513
|
+
return self._first_package_timestamp - self._start_stream_timestamp
|
|
514
|
+
|
|
515
|
+
def get_last_package_delay(self):
|
|
516
|
+
"""Last Package Delay is the time between stop sending audio and receive last words package
|
|
517
|
+
"""
|
|
518
|
+
return self._on_complete_timestamp - self._stop_stream_timestamp
|
|
519
|
+
|
|
520
|
+
# 获取上一个任务的taskId
|
|
521
|
+
def get_last_request_id(self):
|
|
522
|
+
return self.last_request_id
|