dashscope 1.23.8__py3-none-any.whl → 1.24.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.

@@ -0,0 +1,314 @@
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+
3
+ import json
4
+ import platform
5
+ import threading
6
+ import time
7
+ import uuid
8
+ from enum import Enum, unique
9
+
10
+ import dashscope
11
+ import websocket
12
+ from dashscope.common.error import InputRequired, ModelRequired
13
+ from dashscope.common.logging import logger
14
+
15
+
16
+ class QwenTtsRealtimeCallback:
17
+ """
18
+ An interface that defines callback methods for getting omni-realtime results. # noqa E501
19
+ Derive from this class and implement its function to provide your own data.
20
+ """
21
+ def on_open(self) -> None:
22
+ pass
23
+
24
+ def on_close(self, close_status_code, close_msg) -> None:
25
+ pass
26
+
27
+ def on_event(self, message: str) -> None:
28
+ pass
29
+
30
+
31
+ @unique
32
+ class AudioFormat(Enum):
33
+ # format, sample_rate, channels, bit_rate, name
34
+ PCM_24000HZ_MONO_16BIT = ('pcm', 24000, 'mono', '16bit', 'pcm16')
35
+
36
+ def __init__(self, format, sample_rate, channels, bit_rate, format_str):
37
+ self.format = format
38
+ self.sample_rate = sample_rate
39
+ self.channels = channels
40
+ self.bit_rate = bit_rate
41
+ self.format_str = format_str
42
+
43
+ def __repr__(self):
44
+ return self.format_str
45
+
46
+ def __str__(self):
47
+ return f'{self.format.upper()} with {self.sample_rate}Hz sample rate, {self.channels} channel, {self.bit_rate} bit rate: {self.format_str}'
48
+
49
+
50
+ class QwenTtsRealtime:
51
+ def __init__(
52
+ self,
53
+ model,
54
+ headers=None,
55
+ callback: QwenTtsRealtimeCallback = None,
56
+ workspace=None,
57
+ url=None,
58
+ additional_params=None,
59
+ ):
60
+ """
61
+ Qwen Tts Realtime SDK
62
+ Parameters:
63
+ -----------
64
+ model: str
65
+ Model name.
66
+ headers: Dict
67
+ User-defined headers.
68
+ callback: OmniRealtimeCallback
69
+ Callback to receive real-time omni results.
70
+ workspace: str
71
+ Dashscope workspace ID.
72
+ url: str
73
+ Dashscope WebSocket URL.
74
+ additional_params: Dict
75
+ Additional parameters for the Dashscope API.
76
+ """
77
+
78
+ if model is None:
79
+ raise ModelRequired('Model is required!')
80
+ if url is None:
81
+ url = f'wss://dashscope.aliyuncs.com/api-ws/v1/realtime?model={model}'
82
+ else:
83
+ url = f'{url}?model={model}'
84
+ self.url = url
85
+ self.apikey = dashscope.api_key
86
+ self.user_headers = headers
87
+ self.user_workspace = workspace
88
+ self.model = model
89
+ self.config = {}
90
+ self.callback = callback
91
+ self.ws = None
92
+ self.session_id = None
93
+ self.last_message = None
94
+ self.last_response_id = None
95
+ self.last_first_text_time = None
96
+ self.last_first_audio_delay = None
97
+ self.metrics = []
98
+
99
+ def _generate_event_id(self):
100
+ '''
101
+ generate random event id: event_xxxx
102
+ '''
103
+ return 'event_' + uuid.uuid4().hex
104
+
105
+ def _get_websocket_header(self, ):
106
+ ua = 'dashscope/%s; python/%s; platform/%s; processor/%s' % (
107
+ '1.18.0', # dashscope version
108
+ platform.python_version(),
109
+ platform.platform(),
110
+ platform.processor(),
111
+ )
112
+ headers = {
113
+ 'user-agent': ua,
114
+ 'Authorization': 'bearer ' + self.apikey,
115
+ }
116
+ if self.user_headers:
117
+ headers = {**self.user_headers, **headers}
118
+ if self.user_workspace:
119
+ headers = {
120
+ **headers,
121
+ 'X-DashScope-WorkSpace': self.user_workspace,
122
+ }
123
+ return headers
124
+
125
+ def connect(self) -> None:
126
+ '''
127
+ connect to server, create session and return default session configuration
128
+ '''
129
+ self.ws = websocket.WebSocketApp(
130
+ self.url,
131
+ header=self._get_websocket_header(),
132
+ on_message=self.on_message,
133
+ on_error=self.on_error,
134
+ on_close=self.on_close,
135
+ )
136
+ self.thread = threading.Thread(target=self.ws.run_forever)
137
+ self.thread.daemon = True
138
+ self.thread.start()
139
+ timeout = 5 # 最长等待时间(秒)
140
+ start_time = time.time()
141
+ while (not (self.ws.sock and self.ws.sock.connected)
142
+ and (time.time() - start_time) < timeout):
143
+ time.sleep(0.1) # 短暂休眠,避免密集轮询
144
+ if not (self.ws.sock and self.ws.sock.connected):
145
+ raise TimeoutError(
146
+ 'websocket connection could not established within 5s. '
147
+ 'Please check your network connection, firewall settings, or server status.'
148
+ )
149
+ self.callback.on_open()
150
+
151
+ def __send_str(self, data: str, enable_log: bool = True):
152
+ if enable_log:
153
+ logger.debug('[qwen tts realtime] send string: {}'.format(data))
154
+ self.ws.send(data)
155
+
156
+ def update_session(self,
157
+ voice: str,
158
+ response_format: AudioFormat = AudioFormat.
159
+ PCM_24000HZ_MONO_16BIT,
160
+ mode: str = 'server_commit',
161
+ **kwargs) -> None:
162
+ '''
163
+ update session configuration, should be used before create response
164
+
165
+ Parameters
166
+ ----------
167
+ voice: str
168
+ voice to be used in session
169
+ response_format: AudioFormat
170
+ output audio format
171
+ mode: str
172
+ response mode, server_commit or commit
173
+ '''
174
+ self.config = {
175
+ 'voice': voice,
176
+ 'mode': mode,
177
+ 'response_format': response_format.format,
178
+ 'sample_rate': response_format.sample_rate,
179
+ }
180
+ self.config.update(kwargs)
181
+ self.__send_str(
182
+ json.dumps({
183
+ 'event_id': self._generate_event_id(),
184
+ 'type': 'session.update',
185
+ 'session': self.config
186
+ }))
187
+
188
+ def append_text(self, text: str) -> None:
189
+ '''
190
+ send text
191
+
192
+ Parameters
193
+ ----------
194
+ text: str
195
+ text to send
196
+ '''
197
+ self.__send_str(
198
+ json.dumps({
199
+ 'event_id': self._generate_event_id(),
200
+ 'type': 'input_text_buffer.append',
201
+ 'text': text
202
+ }))
203
+ if self.last_first_text_time is None:
204
+ self.last_first_text_time = time.time() * 1000
205
+
206
+ def commit(self, ) -> None:
207
+ '''
208
+ commit the text sent before, create response and start synthesis audio.
209
+ '''
210
+ self.__send_str(
211
+ json.dumps({
212
+ 'event_id': self._generate_event_id(),
213
+ 'type': 'input_text_buffer.commit'
214
+ }))
215
+
216
+ def clear_appended_text(self, ) -> None:
217
+ '''
218
+ clear the text sent to server before.
219
+ '''
220
+ self.__send_str(
221
+ json.dumps({
222
+ 'event_id': self._generate_event_id(),
223
+ 'type': 'input_text_buffer.clear'
224
+ }))
225
+
226
+ def cancel_response(self, ) -> None:
227
+ '''
228
+ cancel the current response
229
+ '''
230
+ self.__send_str(
231
+ json.dumps({
232
+ 'event_id': self._generate_event_id(),
233
+ 'type': 'response.cancel'
234
+ }))
235
+
236
+ def send_raw(self, raw_data: str) -> None:
237
+ '''
238
+ send raw data to server
239
+ '''
240
+ self.__send_str(raw_data)
241
+
242
+ def finish(self, ) -> None:
243
+ '''
244
+ finish input text stream, server will synthesis all text in buffer and close the connection
245
+ '''
246
+ self.__send_str(
247
+ json.dumps({
248
+ 'event_id': self._generate_event_id(),
249
+ 'type': 'session.finish'
250
+ }))
251
+
252
+ def close(self, ) -> None:
253
+ '''
254
+ close the connection to server
255
+ '''
256
+ self.ws.close()
257
+
258
+ # 监听消息的回调函数
259
+ def on_message(self, ws, message):
260
+ if isinstance(message, str):
261
+ logger.debug('[omni realtime] receive string {}'.format(
262
+ message[:1024]))
263
+ try:
264
+ # 尝试将消息解析为JSON
265
+ json_data = json.loads(message)
266
+ self.last_message = json_data
267
+ self.callback.on_event(json_data)
268
+ if 'type' in message:
269
+ if 'session.created' == json_data['type']:
270
+ self.session_id = json_data['session']['id']
271
+ if 'response.created' == json_data['type']:
272
+ self.last_response_id = json_data['response']['id']
273
+ elif 'response.audio.delta' == json_data['type']:
274
+ if self.last_first_text_time and self.last_first_audio_delay is None:
275
+ self.last_first_audio_delay = time.time(
276
+ ) * 1000 - self.last_first_text_time
277
+ elif 'response.done' == json_data['type']:
278
+ logger.debug(
279
+ '[Metric] response: {}, first audio delay: {}'
280
+ .format(self.last_response_id,
281
+ self.last_first_audio_delay))
282
+ except json.JSONDecodeError:
283
+ logger.error('Failed to parse message as JSON.')
284
+ raise Exception('Failed to parse message as JSON.')
285
+ elif isinstance(message, (bytes, bytearray)):
286
+ # 如果失败,认为是二进制消息
287
+ logger.error(
288
+ 'should not receive binary message in omni realtime api')
289
+ logger.debug('[omni realtime] receive binary {} bytes'.format(
290
+ len(message)))
291
+
292
+ def on_close(self, ws, close_status_code, close_msg):
293
+ logger.debug(
294
+ '[omni realtime] connection closed with code {} and message {}'.format(
295
+ close_status_code, close_msg))
296
+ self.callback.on_close(close_status_code, close_msg)
297
+
298
+ # WebSocket发生错误的回调函数
299
+ def on_error(self, ws, error):
300
+ print(f'websocket closed due to {error}')
301
+ raise Exception(f'websocket closed due to {error}')
302
+
303
+ # 获取上一个任务的taskId
304
+ def get_session_id(self):
305
+ return self.session_id
306
+
307
+ def get_last_message(self):
308
+ return self.last_message
309
+
310
+ def get_last_response_id(self):
311
+ return self.last_response_id
312
+
313
+ def get_first_audio_delay(self):
314
+ return self.last_first_audio_delay
@@ -43,28 +43,39 @@ class ResultCallback:
43
43
 
44
44
  @unique
45
45
  class AudioFormat(Enum):
46
- DEFAULT = ('Default', 0, '0', '0')
47
- WAV_8000HZ_MONO_16BIT = ('wav', 8000, 'mono', '16bit')
48
- WAV_16000HZ_MONO_16BIT = ('wav', 16000, 'mono', '16bit')
49
- WAV_22050HZ_MONO_16BIT = ('wav', 22050, 'mono', '16bit')
50
- WAV_24000HZ_MONO_16BIT = ('wav', 24000, 'mono', '16bit')
51
- WAV_44100HZ_MONO_16BIT = ('wav', 44100, 'mono', '16bit')
52
- WAV_48000HZ_MONO_16BIT = ('wav', 48000, 'mono', '16bit')
53
-
54
- MP3_8000HZ_MONO_128KBPS = ('mp3', 8000, 'mono', '128kbps')
55
- MP3_16000HZ_MONO_128KBPS = ('mp3', 16000, 'mono', '128kbps')
56
- MP3_22050HZ_MONO_256KBPS = ('mp3', 22050, 'mono', '256kbps')
57
- MP3_24000HZ_MONO_256KBPS = ('mp3', 24000, 'mono', '256kbps')
58
- MP3_44100HZ_MONO_256KBPS = ('mp3', 44100, 'mono', '256kbps')
59
- MP3_48000HZ_MONO_256KBPS = ('mp3', 48000, 'mono', '256kbps')
60
-
61
- PCM_8000HZ_MONO_16BIT = ('pcm', 8000, 'mono', '16bit')
62
- PCM_16000HZ_MONO_16BIT = ('pcm', 16000, 'mono', '16bit')
63
- PCM_22050HZ_MONO_16BIT = ('pcm', 22050, 'mono', '16bit')
64
- PCM_24000HZ_MONO_16BIT = ('pcm', 24000, 'mono', '16bit')
65
- PCM_44100HZ_MONO_16BIT = ('pcm', 44100, 'mono', '16bit')
66
- PCM_48000HZ_MONO_16BIT = ('pcm', 48000, 'mono', '16bit')
67
-
46
+ DEFAULT = ('Default', 0, '0', 0)
47
+ WAV_8000HZ_MONO_16BIT = ('wav', 8000, 'mono', 0)
48
+ WAV_16000HZ_MONO_16BIT = ('wav', 16000, 'mono', 16)
49
+ WAV_22050HZ_MONO_16BIT = ('wav', 22050, 'mono', 16)
50
+ WAV_24000HZ_MONO_16BIT = ('wav', 24000, 'mono', 16)
51
+ WAV_44100HZ_MONO_16BIT = ('wav', 44100, 'mono', 16)
52
+ WAV_48000HZ_MONO_16BIT = ('wav', 48000, 'mono', 16)
53
+
54
+ MP3_8000HZ_MONO_128KBPS = ('mp3', 8000, 'mono', 128)
55
+ MP3_16000HZ_MONO_128KBPS = ('mp3', 16000, 'mono', 128)
56
+ MP3_22050HZ_MONO_256KBPS = ('mp3', 22050, 'mono', 256)
57
+ MP3_24000HZ_MONO_256KBPS = ('mp3', 24000, 'mono', 256)
58
+ MP3_44100HZ_MONO_256KBPS = ('mp3', 44100, 'mono', 256)
59
+ MP3_48000HZ_MONO_256KBPS = ('mp3', 48000, 'mono', 256)
60
+
61
+ PCM_8000HZ_MONO_16BIT = ('pcm', 8000, 'mono', 16)
62
+ PCM_16000HZ_MONO_16BIT = ('pcm', 16000, 'mono', 16)
63
+ PCM_22050HZ_MONO_16BIT = ('pcm', 22050, 'mono', 16)
64
+ PCM_24000HZ_MONO_16BIT = ('pcm', 24000, 'mono', 16)
65
+ PCM_44100HZ_MONO_16BIT = ('pcm', 44100, 'mono', 16)
66
+ PCM_48000HZ_MONO_16BIT = ('pcm', 48000, 'mono', 16)
67
+
68
+ OGG_OPUS_8KHZ_MONO_32KBPS = ("opus", 8000, "mono", 32)
69
+ OGG_OPUS_8KHZ_MONO_16KBPS = ("opus", 8000, "mono", 16)
70
+ OGG_OPUS_16KHZ_MONO_16KBPS = ("opus", 16000, "mono", 16)
71
+ OGG_OPUS_16KHZ_MONO_32KBPS = ("opus", 16000, "mono", 32)
72
+ OGG_OPUS_16KHZ_MONO_64KBPS = ("opus", 16000, "mono", 64)
73
+ OGG_OPUS_24KHZ_MONO_16KBPS = ("opus", 24000, "mono", 16)
74
+ OGG_OPUS_24KHZ_MONO_32KBPS = ("opus", 24000, "mono", 32)
75
+ OGG_OPUS_24KHZ_MONO_64KBPS = ("opus", 24000, "mono", 64)
76
+ OGG_OPUS_48KHZ_MONO_16KBPS = ("opus", 48000, "mono", 16)
77
+ OGG_OPUS_48KHZ_MONO_32KBPS = ("opus", 48000, "mono", 32)
78
+ OGG_OPUS_48KHZ_MONO_64KBPS = ("opus", 48000, "mono", 64)
68
79
  def __init__(self, format, sample_rate, channels, bit_rate):
69
80
  self.format = format
70
81
  self.sample_rate = sample_rate
@@ -83,6 +94,7 @@ class Request:
83
94
  voice,
84
95
  format='wav',
85
96
  sample_rate=16000,
97
+ bit_rate=64000,
86
98
  volume=50,
87
99
  speech_rate=1.0,
88
100
  pitch_rate=1.0,
@@ -93,6 +105,7 @@ class Request:
93
105
  self.model = model
94
106
  self.format = format
95
107
  self.sample_rate = sample_rate
108
+ self.bit_rate = bit_rate
96
109
  self.volume = volume
97
110
  self.speech_rate = speech_rate
98
111
  self.pitch_rate = pitch_rate
@@ -146,6 +159,8 @@ class Request:
146
159
  },
147
160
  },
148
161
  }
162
+ if self.format == 'opus':
163
+ cmd['payload']['parameters']['bit_rate'] = self.bit_rate
149
164
  if additional_params:
150
165
  cmd['payload']['parameters'].update(additional_params)
151
166
  return json.dumps(cmd)
@@ -252,6 +267,7 @@ class SpeechSynthesizer:
252
267
  voice=voice,
253
268
  format=format.format,
254
269
  sample_rate=format.sample_rate,
270
+ bit_rate = format.bit_rate,
255
271
  volume=volume,
256
272
  speech_rate=speech_rate,
257
273
  pitch_rate=pitch_rate,
dashscope/cli.py CHANGED
@@ -2,12 +2,14 @@
2
2
  import argparse
3
3
  import sys
4
4
  import time
5
+ import os
5
6
  from http import HTTPStatus
6
7
 
7
8
  import dashscope
8
9
  from dashscope.aigc import Generation
9
10
  from dashscope.common.constants import (DeploymentStatus, FilePurpose,
10
11
  TaskStatus)
12
+ from dashscope.utils.oss_utils import OssUtils
11
13
 
12
14
 
13
15
  def print_failed_message(rsp):
@@ -193,6 +195,34 @@ class FineTunes:
193
195
  else:
194
196
  print_failed_message(rsp)
195
197
 
198
+ class Oss:
199
+ @classmethod
200
+ def upload(cls, args):
201
+ print('Start oss.upload: model=%s, file=%s, api_key=%s' % (args.model, args.file, args.api_key))
202
+ if not args.file or not args.model:
203
+ print('Please specify the model and file path')
204
+ return
205
+
206
+ file_path = os.path.expanduser(args.file)
207
+ if not os.path.exists(file_path):
208
+ print('File %s does not exist' % file_path)
209
+ return
210
+
211
+ api_key = os.environ.get('DASHSCOPE_API_KEY', args.api_key)
212
+ if not api_key:
213
+ print('Please set your DashScope API key as environment variable '
214
+ 'DASHSCOPE_API_KEY or pass it as argument by -k/--api_key')
215
+ return
216
+
217
+ oss_url = OssUtils.upload(model=args.model,
218
+ file_path=file_path,
219
+ api_key=api_key)
220
+
221
+ if not oss_url:
222
+ print('Failed to upload file: %s' % file_path)
223
+ return
224
+
225
+ print('Uploaded oss url: %s' % oss_url)
196
226
 
197
227
  class Files:
198
228
  @classmethod
@@ -477,6 +507,30 @@ def main():
477
507
  help='The fine-tune job id.')
478
508
  fine_tune_cancel.set_defaults(func=FineTunes.cancel)
479
509
 
510
+ oss_upload = sub_parsers.add_parser('oss.upload')
511
+ oss_upload.add_argument(
512
+ '-f',
513
+ '--file',
514
+ type=str,
515
+ required=True,
516
+ help='The file path to upload',
517
+ )
518
+ oss_upload.add_argument(
519
+ '-m',
520
+ '--model',
521
+ type=str,
522
+ required=True,
523
+ help='The model name',
524
+ )
525
+ oss_upload.add_argument(
526
+ '-k',
527
+ '--api_key',
528
+ type=str,
529
+ required=False,
530
+ help='The dashscope api key',
531
+ )
532
+ oss_upload.set_defaults(func=Oss.upload)
533
+
480
534
  file_upload = sub_parsers.add_parser('files.upload')
481
535
  file_upload.add_argument(
482
536
  '-f',
@@ -15,6 +15,7 @@ class TextEmbedding(BaseApi):
15
15
  text_embedding_v1 = 'text-embedding-v1'
16
16
  text_embedding_v2 = 'text-embedding-v2'
17
17
  text_embedding_v3 = 'text-embedding-v3'
18
+ text_embedding_v4 = 'text-embedding-v4'
18
19
 
19
20
  @classmethod
20
21
  def call(cls,
@@ -83,12 +83,15 @@ class Upstream:
83
83
  # sample_rate: int # 合成音频采样率
84
84
 
85
85
  def to_dict(self):
86
- return {
86
+ upstream: dict = {
87
87
  "type": self.type,
88
88
  "mode": self.mode,
89
89
  "audio_format": self.audio_format,
90
90
  # "sample_rate": self.sample_rate
91
91
  }
92
+ if self.pass_through_params is not None:
93
+ upstream.update(self.pass_through_params)
94
+ return upstream
92
95
 
93
96
 
94
97
  @dataclass
@@ -105,6 +108,7 @@ class Downstream:
105
108
  volume: int = field(default=50) # 语音音量 0-100
106
109
  pitch_rate: int = field(default=100) # 语音语调 50-200
107
110
  speech_rate: int = field(default=100) # 语音语速 50-200
111
+ pass_through_params: dict = field(default=None)
108
112
 
109
113
  def to_dict(self):
110
114
  stream: dict = {
@@ -120,6 +124,8 @@ class Downstream:
120
124
  stream["voice"] = self.voice
121
125
  if self.sample_rate != 0:
122
126
  stream["sample_rate"] = self.sample_rate
127
+ if self.pass_through_params is not None:
128
+ stream.update(self.pass_through_params)
123
129
  return stream
124
130
 
125
131
 
@@ -199,6 +205,7 @@ class BizParams:
199
205
  user_prompt_params: dict = field(default=None)
200
206
  user_query_params: dict = field(default=None)
201
207
  videos: list = field(default=None)
208
+ pass_through_params: dict = field(default=None)
202
209
 
203
210
  def to_dict(self):
204
211
  params = {}
@@ -214,6 +221,8 @@ class BizParams:
214
221
  params["user_query_params"] = self.user_query_params
215
222
  if self.videos is not None:
216
223
  params["videos"] = self.videos
224
+ if self.pass_through_params is not None:
225
+ params.update(self.pass_through_params)
217
226
  return params
218
227
 
219
228
 
@@ -82,6 +82,10 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
82
82
  workspace: str = None,
83
83
  extra_body: Optional[Dict] = None,
84
84
  api_key: str = None,
85
+ top_p: Optional[float] = None,
86
+ top_k: Optional[int] = None,
87
+ temperature: Optional[float] = None,
88
+ max_tokens: Optional[int] = None,
85
89
  **kwargs) -> Run:
86
90
  """Create a run.
87
91
 
@@ -122,6 +126,15 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
122
126
  if extra_body is not None and extra_body:
123
127
  data = {**data, **extra_body}
124
128
 
129
+ if top_p is not None:
130
+ data['top_p'] = top_p
131
+ if top_k is not None:
132
+ data['top_k'] = top_k
133
+ if temperature is not None:
134
+ data['temperature'] = temperature
135
+ if max_tokens is not None:
136
+ data['max_tokens'] = max_tokens
137
+
125
138
  response = super().call(data=data,
126
139
  path=f'threads/{thread_id}/runs',
127
140
  api_key=api_key,
@@ -180,6 +193,10 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
180
193
  workspace: str = None,
181
194
  extra_body: Optional[Dict] = None,
182
195
  api_key: str = None,
196
+ top_p: Optional[float] = None,
197
+ top_k: Optional[int] = None,
198
+ temperature: Optional[float] = None,
199
+ max_tokens: Optional[int] = None,
183
200
  **kwargs) -> Run:
184
201
  """Create a run.
185
202
 
@@ -214,6 +231,10 @@ class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
214
231
  workspace=workspace,
215
232
  extra_body=extra_body,
216
233
  api_key=api_key,
234
+ top_p=top_p,
235
+ top_k=top_k,
236
+ temperature=temperature,
237
+ max_tokens=max_tokens,
217
238
  **kwargs)
218
239
 
219
240
  @classmethod
@@ -51,6 +51,13 @@ class Usage(BaseObjectMixin):
51
51
 
52
52
  total_tokens: int
53
53
  """Total number of tokens used (prompt + completion)."""
54
+
55
+ input_tokens: int
56
+ """Input tokens used (prompt)."""
57
+
58
+ output_tokens: int
59
+ """Output tokens used (completion)."""
60
+
54
61
  def __init__(self, **kwargs):
55
62
  super().__init__(**kwargs)
56
63
 
@@ -302,6 +309,11 @@ class Run(BaseObjectMixin):
302
309
 
303
310
  tools: List[Tool]
304
311
 
312
+ top_p: Optional[float] = None
313
+ top_k: Optional[int] = None
314
+ temperature: Optional[float] = None
315
+ max_tokens: Optional[int] = None
316
+
305
317
  usage: Optional[Usage] = None
306
318
 
307
319
  def __init__(self, **kwargs):
@@ -154,7 +154,10 @@ def check_and_upload_local(model: str, content: str, api_key: str):
154
154
  return True, file_url
155
155
  else:
156
156
  raise InvalidInput('The file: %s is not exists!' % file_path)
157
+ elif content.startswith('oss://'):
158
+ return True, content
157
159
  elif not content.startswith('http'):
160
+ content = os.path.expanduser(content)
158
161
  if os.path.isfile(content):
159
162
  file_url = OssUtils.upload(model=model,
160
163
  file_path=content,
dashscope/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # Copyright (c) Alibaba, Inc. and its affiliates.
2
2
 
3
- __version__ = '1.23.8'
3
+ __version__ = '1.24.0'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dashscope
3
- Version: 1.23.8
3
+ Version: 1.24.0
4
4
  Summary: dashscope client sdk library
5
5
  Home-page: https://dashscope.aliyun.com/
6
6
  Author: Alibaba Cloud