volcengine-python-sdk-aicc 0.0.41__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 (60) hide show
  1. bytedance/__init__.py +4 -0
  2. bytedance/jeddak_secure_channel/__init__.py +28 -0
  3. bytedance/jeddak_secure_channel/client.py +305 -0
  4. bytedance/jeddak_secure_channel/config.py +171 -0
  5. bytedance/jeddak_secure_channel/consts.py +5 -0
  6. bytedance/jeddak_secure_channel/crypto/__init__.py +14 -0
  7. bytedance/jeddak_secure_channel/crypto/aes.py +174 -0
  8. bytedance/jeddak_secure_channel/crypto/envelope.py +395 -0
  9. bytedance/jeddak_secure_channel/crypto/rsa.py +164 -0
  10. bytedance/jeddak_secure_channel/error.py +131 -0
  11. bytedance/jeddak_secure_channel/log/__init__.py +23 -0
  12. bytedance/jeddak_secure_channel/log/config.py +31 -0
  13. bytedance/jeddak_secure_channel/log/logger.py +88 -0
  14. bytedance/jeddak_secure_channel/logger_factory.py +134 -0
  15. bytedance/jeddak_secure_channel/ra.py +772 -0
  16. bytedance/jeddak_secure_channel/server.py +745 -0
  17. bytedance/jeddak_secure_channel/service/__init__.py +16 -0
  18. bytedance/jeddak_secure_channel/service/eps.py +133 -0
  19. bytedance/jeddak_secure_channel/service/eps_models.py +47 -0
  20. bytedance/jeddak_secure_channel/service/ras.py +88 -0
  21. bytedance/jeddak_secure_channel/service/tks.py +51 -0
  22. bytedance/jeddak_secure_channel/service/tks_models.py +334 -0
  23. bytedance/jeddak_secure_channel/utils.py +469 -0
  24. bytedance/jeddak_secure_model/model_automation_tool.py +181 -0
  25. bytedance/jeddak_secure_model/model_encryption.py +416 -0
  26. bytedance/jeddak_secure_model/model_hub_admin.py +116 -0
  27. bytedance/jeddak_secure_model/pcc_utils.py +279 -0
  28. bytedance/jeddak_secure_model/rds_utils.py +63 -0
  29. bytedance/tks/attester.py +41 -0
  30. bytedance/tks/client.py +629 -0
  31. bytedance/tks/consts.py +122 -0
  32. bytedance/tks/crypto/aes.py +47 -0
  33. bytedance/tks/crypto/ec.py +39 -0
  34. bytedance/tks/exceptions.py +22 -0
  35. bytedance/volcengine_aicc_sdk/__init__.py +14 -0
  36. bytedance/volcengine_aicc_sdk/aicc_client.py +277 -0
  37. bytedance/volcengine_aicc_sdk/aicc_inference.py +64 -0
  38. bytedance/volcengine_aicc_sdk/ark_inference_client.py +343 -0
  39. bytedance/volcengine_aicc_sdk/asr_inference_client.py +158 -0
  40. bytedance/volcengine_aicc_sdk/asr_websocket_client.py +705 -0
  41. bytedance/volcengine_aicc_sdk/auc_inference_client.py +305 -0
  42. bytedance/volcengine_aicc_sdk/common/__init__.py +0 -0
  43. bytedance/volcengine_aicc_sdk/common/aes.py +136 -0
  44. bytedance/volcengine_aicc_sdk/common/constant.py +4 -0
  45. bytedance/volcengine_aicc_sdk/common/error.py +21 -0
  46. bytedance/volcengine_aicc_sdk/common/log/__init__.py +24 -0
  47. bytedance/volcengine_aicc_sdk/common/log/config.py +31 -0
  48. bytedance/volcengine_aicc_sdk/common/log/logger.py +88 -0
  49. bytedance/volcengine_aicc_sdk/common/tos_utils.py +341 -0
  50. bytedance/volcengine_aicc_sdk/common/utils.py +45 -0
  51. bytedance/volcengine_aicc_sdk/cu_inference_client.py +292 -0
  52. bytedance/volcengine_aicc_sdk/deepseek_inference_client.py +501 -0
  53. bytedance/volcengine_aicc_sdk/secure_http_client.py +406 -0
  54. bytedance/volcengine_aicc_sdk/seedance_inference_client.py +500 -0
  55. bytedance/volcengine_aicc_sdk/seedream_inference_client.py +213 -0
  56. volcengine_python_sdk_aicc-0.0.41.dist-info/METADATA +79 -0
  57. volcengine_python_sdk_aicc-0.0.41.dist-info/RECORD +60 -0
  58. volcengine_python_sdk_aicc-0.0.41.dist-info/WHEEL +5 -0
  59. volcengine_python_sdk_aicc-0.0.41.dist-info/licenses/LICENSE +202 -0
  60. volcengine_python_sdk_aicc-0.0.41.dist-info/top_level.txt +1 -0
@@ -0,0 +1,343 @@
1
+ """
2
+ 机密豆包客户端
3
+ """
4
+ __all__ = ["ARKClient"]
5
+
6
+ import copy
7
+ import json
8
+ import os
9
+ from typing import IO, Union
10
+
11
+ from volcenginesdkarkruntime import Ark
12
+ from volcenginesdkarkruntime._utils._key_agreement import (
13
+ aes_gcm_encrypt_base64_string,
14
+ aes_gcm_decrypt_base64_string,
15
+ key_agreement_client
16
+ )
17
+ from openai import OpenAI
18
+ from volcenginesdkarkruntime.types.chat import ChatCompletion, ChatCompletionChunk
19
+
20
+ from .aicc_inference import AICCInference
21
+ from .common.error import AICCException
22
+ from .common.log import logger
23
+
24
+
25
+ class ARKClient(AICCInference):
26
+ """
27
+ 机密豆包客户端.
28
+ """
29
+
30
+ def __init__(self,
31
+ base_url: str = None,
32
+ api_key: str = None,
33
+ ep: str = None,
34
+ is_openai: bool = False,
35
+ is_secure: bool = True,
36
+ thinking_type: str = "disabled",
37
+ ak: str = None,
38
+ sk: str = None,
39
+ region: str = "cn-beijing",
40
+ **kwargs):
41
+ if not base_url or not api_key or not ep:
42
+ raise AICCException(f"New ARK client failed, base_url={base_url}, api_key={api_key}, ep={ep}")
43
+
44
+ super().__init__(base_url, is_openai, is_secure, ak, sk, region)
45
+
46
+ os.environ["VOLC_ARK_ENCRYPTION"] = "AICC"
47
+
48
+ self.base_url = base_url
49
+ self.api_key = api_key
50
+ self.ep = ep
51
+ self.is_openai = is_openai
52
+ self.is_secure = is_secure
53
+ self.thinking_type = thinking_type
54
+
55
+ self.kwargs = kwargs
56
+
57
+ self.client = None
58
+ try:
59
+ self.client = Ark(api_key=api_key, base_url=base_url, ak=ak, sk=sk, region=region)
60
+ except Exception as e:
61
+ logger.error(f"New ARK client failed: {e}")
62
+ raise AICCException("New ARK client failed")
63
+
64
+ def _chat_completion_to_str(self, chat_completion: ChatCompletion) -> str:
65
+ ret = dict()
66
+ ret["id"] = chat_completion.id
67
+ ret["object"] = chat_completion.object
68
+ ret["created"] = chat_completion.created
69
+ ret["model"] = chat_completion.model
70
+ ret["service_tier"] = chat_completion.service_tier
71
+
72
+ if chat_completion.usage:
73
+ ret["usage"] = json.loads(chat_completion.usage.json())
74
+ else:
75
+ ret["usage"] = None
76
+
77
+ ret["choices"] = list()
78
+ for choice in chat_completion.choices:
79
+ ret["choices"].append(json.loads(choice.json()))
80
+
81
+ return json.dumps(ret)
82
+
83
+ def _chat_completion_chunk_to_str(self, chat_completion_chunk: ChatCompletionChunk) -> str:
84
+ ret = dict()
85
+ ret["id"] = chat_completion_chunk.id
86
+ ret["object"] = chat_completion_chunk.object
87
+ ret["created"] = chat_completion_chunk.created
88
+ ret["model"] = chat_completion_chunk.model
89
+ ret["service_tier"] = chat_completion_chunk.service_tier
90
+ if chat_completion_chunk.usage:
91
+ ret["usage"] = json.loads(chat_completion_chunk.usage.json())
92
+ else:
93
+ ret["usage"] = None
94
+ ret["choices"] = list()
95
+ for choice in chat_completion_chunk.choices:
96
+ ret["choices"].append(json.loads(choice.json()))
97
+
98
+ return json.dumps(ret)
99
+
100
+ def chat_completions(self, messages: list, output_stream: IO = None) -> Union[str, None]:
101
+ """
102
+ :param messages:
103
+ :param output_stream:
104
+ :return:
105
+ """
106
+ if not messages:
107
+ raise AICCException("ARK completions, messages is NULL")
108
+
109
+ try:
110
+ thinking = {
111
+ "type": self.thinking_type
112
+ }
113
+
114
+ include_usage = True if self.kwargs.get("include_usage", "True").lower() == "true" and output_stream \
115
+ else False
116
+
117
+ if self.is_openai:
118
+ openai_messages = copy.deepcopy(messages)
119
+
120
+ client = OpenAI(base_url=self.base_url, api_key=self.api_key)
121
+ ark_client = Ark(base_url=self.base_url, api_key=self.api_key)
122
+
123
+ ark_certificate = ark_client._get_endpoint_certificate(self.ep)
124
+ if isinstance(ark_certificate, tuple):
125
+ cipher_client = ark_certificate[0]
126
+ ring_id = ark_certificate[1]
127
+ key_id = ark_certificate[2]
128
+ key, nonce, token = cipher_client.generate_ecies_key_pair()
129
+ elif isinstance(ark_certificate, key_agreement_client):
130
+ ring_id, key_id = ark_certificate.get_cert_ring_key_id()
131
+ key, nonce, token = ark_certificate.generate_ecies_key_pair()
132
+ else:
133
+ logger.error(f"get ark_certificate ERROR")
134
+ raise AICCException("get ark_certificate ERROR")
135
+
136
+ info = {
137
+ 'Version': 'AICCv0.1',
138
+ 'RingID': ring_id,
139
+ 'KeyID': key_id,
140
+ }
141
+
142
+ if self.is_secure:
143
+ extra_headers = {
144
+ "X-Session-Token": token,
145
+ "x-ark-moderation-scene": "aicc-skip",
146
+ "X-Encrypt-Info": json.dumps(info),
147
+ }
148
+ for i in range(len(openai_messages)):
149
+ content = openai_messages[i].get("content")
150
+
151
+ if isinstance(content, str):
152
+ openai_messages[i]["content"] = aes_gcm_encrypt_base64_string(key, nonce, content)
153
+ elif isinstance(content, list):
154
+ encrypted_content = []
155
+ for item in content:
156
+ if isinstance(item, dict) and "type" in item and item["type"] == "text":
157
+ # 加密文本
158
+ encrypted_item = item.copy()
159
+ encrypted_item["text"] = aes_gcm_encrypt_base64_string(key, nonce, item["text"])
160
+ encrypted_content.append(encrypted_item)
161
+ elif isinstance(item, dict) and "type" in item and item["type"] == "image_url":
162
+ # 加密图片
163
+ encrypted_item = item.copy()
164
+ encrypted_item["image_url"]["url"] = aes_gcm_encrypt_base64_string(
165
+ key, nonce, item["image_url"]["url"])
166
+ encrypted_content.append(encrypted_item)
167
+ elif isinstance(item, dict) and "type" in item and item["type"] == "video_url":
168
+ # 加密视频
169
+ error_info = f"Sorry, 密文豆包不支持openai格式"
170
+ logger.error(error_info)
171
+ raise AICCException(error_info)
172
+
173
+ # encrypted_item = item.copy()
174
+ # if isinstance(encrypted_item["video_url"], dict):
175
+ # encrypted_item["video_url"]["url"] = aes_gcm_encrypt_base64_string(
176
+ # key, nonce, item["video_url"]["url"])
177
+ # else:
178
+ # encrypted_item["video_url"] = aes_gcm_encrypt_base64_string(
179
+ # key, nonce, item["video_url"])
180
+ # encrypted_content.append(encrypted_item)
181
+ else:
182
+ encrypted_content.append(item)
183
+ openai_messages[i]["content"] = encrypted_content
184
+ else:
185
+ raise AICCException("no support this content type")
186
+ else:
187
+ extra_headers = {
188
+ }
189
+
190
+ completion = client.chat.completions.create(
191
+ model=self.ep,
192
+ messages=openai_messages,
193
+ stream_options={
194
+ "include_usage": include_usage
195
+ },
196
+ extra_headers=extra_headers,
197
+ stream=True if output_stream else False,
198
+ )
199
+ if output_stream:
200
+ for chunk in completion:
201
+ if self.is_secure and chunk.choices and chunk.choices[0].delta.content:
202
+ chunk.choices[0].delta.content = aes_gcm_decrypt_base64_string(
203
+ key, nonce, chunk.choices[0].delta.content)
204
+ output_stream.write(f"{self._chat_completion_chunk_to_str(chunk)}\n")
205
+ else:
206
+ if self.is_secure and completion.choices and completion.choices[0].message.content:
207
+ completion.choices[0].message.content = \
208
+ aes_gcm_decrypt_base64_string(key, nonce, completion.choices[0].message.content)
209
+ cont = self._chat_completion_to_str(completion)
210
+ return cont
211
+ else:
212
+ resp = self.client.chat.completions.create(
213
+ model=self.ep,
214
+ messages=messages,
215
+ thinking=thinking,
216
+ stream=True if output_stream else False,
217
+ stream_options={
218
+ "include_usage": include_usage
219
+ },
220
+ extra_headers={"x-is-encrypted": str(self.is_secure).lower(), "x-ark-moderation-scene": "aicc-skip"}
221
+ )
222
+
223
+ if output_stream:
224
+ for chunk in resp:
225
+ output_stream.write(f"{self._chat_completion_chunk_to_str(chunk)}\n")
226
+ else:
227
+ return self._chat_completion_to_str(resp)
228
+ except AICCException as e:
229
+ raise e
230
+ except Exception as e:
231
+ logger.error(f"ARK completions ERROR, e={e}")
232
+ raise AICCException("ARK completions ERROR")
233
+
234
+ def chat_completions_stream(self, messages: list, output_stream: IO) -> Union[str, None]:
235
+ return self.chat_completions(messages, output_stream)
236
+
237
+ def chat_completions_stream_yield(self, messages: list):
238
+ """
239
+ :param messages:
240
+ :return:
241
+ """
242
+ if not messages:
243
+ raise AICCException("ARK completions, messages is NULL")
244
+
245
+ try:
246
+ thinking = {
247
+ "type": self.thinking_type
248
+ }
249
+
250
+ include_usage = True if self.kwargs.get("include_usage", "True").lower() == "true" else False
251
+
252
+ if self.is_openai:
253
+ openai_messages = copy.deepcopy(messages)
254
+
255
+ client = OpenAI(base_url=self.base_url, api_key=self.api_key)
256
+ ark_client = Ark(base_url=self.base_url, api_key=self.api_key)
257
+ res_a = ark_client._get_endpoint_certificate(self.ep)
258
+ cipher_client = res_a[0]
259
+ ring_id = res_a[1]
260
+ key_id = res_a[2]
261
+ key, nonce, token = cipher_client.generate_ecies_key_pair()
262
+ info = {
263
+ 'Version': 'AICCv0.1',
264
+ 'RingID': ring_id,
265
+ 'KeyID': key_id,
266
+ }
267
+
268
+ if self.is_secure:
269
+ extra_headers = {
270
+ "X-Session-Token": token,
271
+ "x-ark-moderation-scene": "aicc-skip",
272
+ "X-Encrypt-Info": json.dumps(info),
273
+ }
274
+ for i in range(len(openai_messages)):
275
+ openai_messages[i]["content"] = aes_gcm_encrypt_base64_string(
276
+ key, nonce, openai_messages[i].get("content"))
277
+ else:
278
+ extra_headers = {
279
+ }
280
+
281
+ completion = client.chat.completions.create(
282
+ model=self.ep,
283
+ messages=openai_messages,
284
+ stream_options={
285
+ "include_usage": include_usage
286
+ },
287
+ extra_headers=extra_headers,
288
+ stream=True,
289
+ )
290
+
291
+ for chunk in completion:
292
+ if self.is_secure and chunk.choices and chunk.choices[0].delta.content:
293
+ chunk.choices[0].delta.content = aes_gcm_decrypt_base64_string(
294
+ key, nonce, chunk.choices[0].delta.content)
295
+ yield self._chat_completion_chunk_to_str(chunk)
296
+ else:
297
+ resp = self.client.chat.completions.create(
298
+ model=self.ep,
299
+ messages=messages,
300
+ thinking=thinking,
301
+ stream=True,
302
+ stream_options={
303
+ "include_usage": include_usage
304
+ },
305
+ extra_headers={"x-is-encrypted": str(self.is_secure).lower(), "x-ark-moderation-scene": "aicc-skip"}
306
+ )
307
+
308
+ for chunk in resp:
309
+ yield self._chat_completion_chunk_to_str(chunk)
310
+ except Exception as e:
311
+ logger.error(f"ARK completions ERROR, e={e}")
312
+ raise AICCException("ARK completions ERROR")
313
+
314
+ def function_call(self, messages: list, tools: list, output_stream: IO = None) -> str:
315
+ """
316
+ :param messages:
317
+ :param tools:
318
+ :param output_stream:
319
+ :return:
320
+ """
321
+ if not messages or not tools:
322
+ raise AICCException("doubao function_call params cannot be empty")
323
+
324
+ try:
325
+ resp = self.client.chat.completions.create(
326
+ model=self.ep,
327
+ messages=messages,
328
+ tools=tools,
329
+ )
330
+ return self._chat_completion_to_str(resp)
331
+ except AICCException as e:
332
+ raise e
333
+ except Exception as e:
334
+ logger.error(f"call AICC ARK service function_call error: {e}")
335
+ raise AICCException("AICC ARK service function_call error")
336
+
337
+ def function_call_stream(self, messages: list, tools: list, output_stream: IO) -> str:
338
+ return self.function_call(messages, tools, output_stream)
339
+
340
+ def asr_recognize(self, file_name: str) -> str:
341
+ error_info = "Sorry, this version does not support asr at this time."
342
+ logger.error(error_info)
343
+ return error_info
@@ -0,0 +1,158 @@
1
+ """
2
+ DeepSeek机密推理客户端
3
+ """
4
+ __all__ = ["ASRClient"]
5
+
6
+ import json
7
+ import uuid
8
+ import requests
9
+ import bytedance.jeddak_secure_channel as jsc
10
+ from typing import IO, Union
11
+ from .aicc_inference import AICCInference
12
+ from .common.constant import Constants
13
+ from .common.error import AICCException
14
+ from .common.log import logger
15
+ from .common.utils import file_to_base64
16
+
17
+
18
+ class ASRClient(AICCInference):
19
+ """
20
+ ASR客户端.
21
+ """
22
+
23
+ def __init__(self,
24
+ base_url: str = None,
25
+ aicc_service_name: str = None,
26
+ policy_id: str = None,
27
+ is_openai: bool = True,
28
+ is_secure: bool = True,
29
+ ak: str = None,
30
+ sk: str = None,
31
+ region: str = "cn-beijing",
32
+ **kwargs):
33
+ appid = kwargs.get("appid")
34
+ token = kwargs.get("token")
35
+ service_id = kwargs.get("service_id")
36
+
37
+ if not base_url or not appid or not token or not service_id or not \
38
+ aicc_service_name or not policy_id or not ak or not sk:
39
+ raise AICCException("New deepseek client failed, params error")
40
+
41
+ super().__init__(base_url, is_openai, is_secure, ak, sk, region)
42
+
43
+ self.appid = appid
44
+ self.token = token
45
+ self.service_id = service_id
46
+
47
+ self.aicc_service_name = aicc_service_name
48
+ self.policy_id = policy_id
49
+
50
+ self.kwargs = kwargs
51
+
52
+ self.jsc_client = None
53
+ self.max_retries = 3
54
+
55
+ if is_secure:
56
+ jsc_config = dict()
57
+ jsc_config["ra_service_name"] = aicc_service_name
58
+ jsc_config["ra_policy_id"] = policy_id
59
+ jsc_config["bytedance_top_info"] = dict()
60
+ jsc_config["bytedance_top_info"]["ak"] = ak
61
+ jsc_config["bytedance_top_info"]["sk"] = sk
62
+ jsc_config["bytedance_top_info"]["region"] = region
63
+ jsc_config["bytedance_top_info"]["url"] = self.kwargs.get("top_url", "open.volcengineapi.com")
64
+ jsc_config["bytedance_top_info"]["service"] = self.kwargs.get("top_service", "pcc")
65
+ jsc_config["log_config"] = self.kwargs.get("log_config", Constants.LOG_CONFIG)
66
+
67
+ try:
68
+ secure_channel_config = jsc.ClientConfig.from_dict(jsc_config)
69
+ self.jsc_client = jsc.Client(secure_channel_config)
70
+ except Exception as e:
71
+ logger.error(f"Error init jsc: {e}")
72
+ raise AICCException("New deepseek client failed")
73
+
74
+ def chat_completions(self, messages: list, output_stream: IO = None) -> Union[str, None]:
75
+ """
76
+ 生成聊天补全
77
+ :param messages:
78
+ :param output_stream:
79
+ :return:
80
+ """
81
+ pass
82
+
83
+ def function_call(self, messages: list, tools: list, output_stream: IO = None) -> str:
84
+ """
85
+ :param messages:
86
+ :param tools:
87
+ :param output_stream:
88
+ :return:
89
+ """
90
+ pass
91
+
92
+ def asr_recognize(self, file_name: str) -> Union[str, None]:
93
+ if not file_name:
94
+ raise AICCException("ASR asr_recognize file_name cannot be empty")
95
+
96
+ appid = self.appid
97
+ token = self.token
98
+ service_id = self.service_id
99
+ model_name = "bigmodel"
100
+
101
+ if self.base_url.endswith("flash"):
102
+ recognize_url = self.base_url
103
+ else:
104
+ if self.is_secure:
105
+ recognize_url = f"{self.base_url}/api/v2/auc/{model_name}/recognize/flash"
106
+ else:
107
+ recognize_url = f"{self.base_url}/api/v1/auc/{model_name}/recognize/flash"
108
+
109
+ try:
110
+ audio_data = None
111
+ enc_base64_data = file_to_base64(file_name) # 转换文件为 Base64
112
+
113
+ # 将转换后的base64数据写入文件
114
+ enc_key = None
115
+ if self.is_secure:
116
+ enc_base64_data, enc_key = self.jsc_client.encrypt_with_response(enc_base64_data)
117
+
118
+ audio_data = {
119
+ "data": enc_base64_data,
120
+ }
121
+
122
+ headers = {
123
+ "X-Api-App-Id": appid,
124
+ "X-Api-App-Key": token,
125
+ "X-Api-Aicc-Endpoint": service_id,
126
+ "X-Api-Request-Id": str(uuid.uuid4()),
127
+ }
128
+
129
+ if not audio_data:
130
+ raise AICCException("必须提供ASR文件内容")
131
+
132
+ request = {
133
+ "audio": audio_data,
134
+ "request": {
135
+ "model_name": model_name,
136
+ },
137
+ }
138
+
139
+ response = requests.post(recognize_url, json=request, headers=headers)
140
+ if response.status_code == 200: # task finished
141
+ result = response.json()
142
+ content = result["result"]
143
+ if self.is_secure and enc_key:
144
+ content = enc_key.decrypt(content)
145
+ # 检查 content 类型,如果是 bytes 则解码,否则直接使用
146
+ if isinstance(content, bytes):
147
+ content = json.loads(content.decode("utf-8"))
148
+ else:
149
+ content = json.loads(content)
150
+ result["result"] = content
151
+ return json.dumps(result)
152
+ else:
153
+ raise AICCException("ASR处理失败")
154
+ except AICCException as e:
155
+ raise e
156
+ except Exception as e:
157
+ logger.error(f"call AICC ASR service asr_recognize error: {e}")
158
+ raise AICCException("AICC ASR service asr_recognize error")