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,416 @@
1
+ import hashlib
2
+ import os
3
+ import tarfile
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+ from time import time
7
+ from multiprocessing import Pool
8
+ import concurrent.futures
9
+ from functools import reduce
10
+
11
+ import shutil
12
+ import requests
13
+ import tos
14
+ from tos.utils import SizeAdapter, MergeProcess
15
+ from tos import DataTransferType
16
+ from typing_extensions import TYPE_CHECKING, Dict, List, Optional
17
+ from bytedance.tks.client import TKSClient, TKSConfig, utc8_timestamp
18
+ from bytedance.tks.crypto.aes import gcm_decrypt, gcm_encrypt
19
+
20
+ if TYPE_CHECKING:
21
+ from _typeshed import GenericPath
22
+ else:
23
+ GenericPath = str
24
+
25
+
26
+ def upload_files(args):
27
+ bucket_name = args["bucket_name"]
28
+ path = args["path"]
29
+ volc_ak = args["volc_ak"]
30
+ volc_sk = args["volc_sk"]
31
+ region = args["region"]
32
+ endpoint = args["endpoint"]
33
+
34
+ tos_client = tos.TosClientV2(volc_ak, volc_sk, endpoint, region)
35
+
36
+ total_size = os.path.getsize(path)
37
+ part_size = 5 * 1024 * 1024
38
+
39
+ def percentage(consumed_bytes: int, total_bytes: int, rw_once_bytes: int, type: DataTransferType):
40
+ if total_bytes:
41
+ rate = int(100 * float(consumed_bytes) / float(total_bytes))
42
+ if rw_once_bytes != 0 and ((consumed_bytes // rw_once_bytes) % 1000 == 0):
43
+ print(
44
+ " [{}] rate:{}, consumed_bytes:{},total_bytes{}, rw_once_bytes:{}, type:{}".format(
45
+ path, rate, consumed_bytes, total_bytes, rw_once_bytes, type))
46
+
47
+
48
+ # 配置进度条,与普通上传不同的是需将分片上传的进度聚合
49
+ data_transfer_listener = MergeProcess(percentage, total_size, (total_size + part_size - 1) // part_size, 0)
50
+ # 初始化上传任务
51
+ # 若需在初始化分片时设置对象的存储类型,可通过storage_class字段设置
52
+ # 若需在初始化分片时设置对象ACL,可通过acl、grant_full_control等字段设置
53
+ multi_result = tos_client.create_multipart_upload(bucket_name, path, acl=tos.ACLType.ACL_Public_Read,
54
+ storage_class=tos.StorageClassType.Storage_Class_Standard)
55
+
56
+ upload_id = multi_result.upload_id
57
+ parts = []
58
+
59
+ # 上传分片数据
60
+ with open(path, 'rb') as f:
61
+ part_number = 1
62
+ offset = 0
63
+ while offset < total_size:
64
+ num_to_upload = min(part_size, total_size - offset)
65
+ out = tos_client.upload_part(bucket_name, path, upload_id, part_number,
66
+ content=SizeAdapter(f, num_to_upload, init_offset=offset),
67
+ data_transfer_listener=data_transfer_listener)
68
+ parts.append(out)
69
+ offset += num_to_upload
70
+ part_number += 1
71
+
72
+ # 完成分片上传任务
73
+ tos_client.complete_multipart_upload(bucket_name, path, upload_id, parts)
74
+
75
+
76
+ def _compress_model_dir(model_dir: GenericPath) -> Path:
77
+ compressed_file_name = os.path.basename(model_dir) + ".tar"
78
+ compressed_file_path = Path(compressed_file_name)
79
+ with tarfile.open(compressed_file_path, "w") as tar:
80
+ tar.add(model_dir, arcname=os.path.basename(model_dir))
81
+ return compressed_file_path
82
+
83
+
84
+ def _decompress_model_dir(compressed_file: GenericPath, output_path: GenericPath) -> None:
85
+ with tarfile.open(compressed_file, "r") as tar:
86
+ tar.extractall(path=output_path)
87
+
88
+
89
+ DEFAULT_PARTITION_SIZE = 2 * 1024 * 1024 * 1024
90
+
91
+
92
+ def _partition(model_file: GenericPath, partition_size=DEFAULT_PARTITION_SIZE) -> List[bytes]:
93
+ with open(model_file, "rb") as fin:
94
+ plaintext_bytes = fin.read()
95
+ chunks: List[bytes] = []
96
+ offset = 0
97
+ while offset < len(plaintext_bytes):
98
+ chunks.append(plaintext_bytes[offset : offset + partition_size]) # noqa: E203
99
+ offset += partition_size
100
+ return chunks
101
+
102
+
103
+ def _decrypt_chunk(params):
104
+ enc_chunk_path = params["enc_chunk_path"]
105
+ key = params["key"]
106
+ t0 = time()
107
+ with open(enc_chunk_path, "rb") as fin:
108
+ enc_chunk = fin.read()
109
+ chunk = gcm_decrypt(key, enc_chunk)
110
+ print(f"Decrypt chunk: {enc_chunk_path} done, costs {time() - t0} seconds.")
111
+ return chunk
112
+
113
+
114
+ def md5_hash(data: bytes, salt: str = "") -> str:
115
+ return hashlib.md5(data + salt.encode()).hexdigest()
116
+
117
+
118
+ def copy_folder(source_folder, destination_folder):
119
+ """
120
+ Copy the entire contents of a folder to a new location.
121
+
122
+ :param source_folder: Path to the folder to copy.
123
+ :param destination_folder: Path to the destination folder.
124
+ """
125
+ try:
126
+ # Check if source folder exists
127
+ if not os.path.exists(source_folder):
128
+ print(f"Source folder '{source_folder}' does not exist.")
129
+ return
130
+
131
+ # Copy folder
132
+ shutil.copytree(source_folder, destination_folder)
133
+ print(f" Folder copied from '{source_folder}' to '{destination_folder}'.")
134
+
135
+ except FileExistsError:
136
+ print(f" Destination folder '{destination_folder}' already exists.")
137
+ except PermissionError:
138
+ print(" Permission denied: Unable to copy folder.")
139
+ except Exception as e:
140
+ print(f" An error occurred: {e}")
141
+
142
+
143
+ @dataclass
144
+ class EncryptionConfig:
145
+ app_id: str
146
+
147
+ password: str
148
+
149
+ ring_id: Optional[str] = None
150
+
151
+ key_id: Optional[str] = None
152
+
153
+
154
+ class JeddakModelEncrypter:
155
+ def __init__(self, encryption_config: EncryptionConfig = None):
156
+ if encryption_config is not None:
157
+ self.app_id = encryption_config.app_id
158
+ self.password = encryption_config.password
159
+ self.ring_id = encryption_config.ring_id
160
+ self.key_id = encryption_config.key_id
161
+
162
+ tks_config = TKSConfig(enable_tls=True)
163
+ self.tks_client = TKSClient(self.app_id, tks_config)
164
+
165
+ self.login_url = "https://jeddakchain.bytedance.com/api/user/login"
166
+
167
+ def encrypt_model(self, model_path: GenericPath, output_path: GenericPath) -> bytes:
168
+ os.makedirs(output_path, exist_ok=True)
169
+
170
+ data_key = os.urandom(32)
171
+
172
+ print(" Start compressing model files.")
173
+ # compress if the `model_path` is directory
174
+ t0 = time()
175
+ if os.path.isdir(model_path):
176
+ model_file = _compress_model_dir(model_path)
177
+ else:
178
+ model_file = model_path
179
+ print(f" Compress done, costs {time() - t0} seconds.")
180
+
181
+ chunks = _partition(model_file)
182
+ print(f" Total {len(chunks)} chunks.")
183
+
184
+ t0 = time()
185
+ for i, chunk in enumerate(chunks):
186
+ enc_chunk = gcm_encrypt(data_key, chunk)
187
+ with open(os.path.join(output_path, f"enc-part-{i:05}"), "wb") as fout:
188
+ fout.write(enc_chunk)
189
+ print(f" Encrypt done, costs {time() - t0} seconds.")
190
+
191
+ return data_key
192
+
193
+ def decrypt_model(
194
+ self, enc_model_path: GenericPath, key: bytes, output_path: GenericPath, processes=8
195
+ ) -> None:
196
+ os.makedirs(output_path, exist_ok=True)
197
+ pool = Pool(processes)
198
+ t0 = time()
199
+ plaintext_bytes = bytearray()
200
+ if os.path.isdir(enc_model_path):
201
+ print(f"Start decrypt enc_model_path: {enc_model_path}")
202
+ params_list = []
203
+ for filename in sorted(os.listdir(enc_model_path)):
204
+ params_list.append({"enc_chunk_path": os.path.join(enc_model_path, filename), "key": key})
205
+ chunks = pool.map(_decrypt_chunk, params_list)
206
+ print(f"Pool map done, costs {time() - t0} seconds.")
207
+ for chunk in chunks:
208
+ plaintext_bytes += chunk
209
+ else:
210
+ with open(enc_model_path, "rb") as fin:
211
+ enc_chunk = fin.read()
212
+ chunk = gcm_decrypt(key, enc_chunk)
213
+ plaintext_bytes += chunk
214
+ plaintext_bytes = bytes(plaintext_bytes)
215
+ print(f"Decrypt done, costs {time() - t0} seconds.")
216
+
217
+ plaintext_compressed_file = "./decrypted_model.tar"
218
+ with open(plaintext_compressed_file, "wb") as fout:
219
+ fout.write(plaintext_bytes)
220
+
221
+ t0 = time()
222
+ _decompress_model_dir(plaintext_compressed_file, output_path)
223
+ print(f"Decompress done, costs {time() - t0} seconds.")
224
+
225
+ # def compute_model_baseline(self, model_dir: GenericPath) -> str:
226
+ # baseline = b""
227
+ # file_path_list = []
228
+ # for dirpath, _, filenames in os.walk(model_dir):
229
+ # for filename in filenames:
230
+ # file_path = os.path.join(dirpath, filename)
231
+ # file_path_list.append(file_path)
232
+
233
+ # for file_path in sorted(file_path_list):
234
+ # with open(file_path, "rb") as fin:
235
+ # file_bytes = fin.read()
236
+ # baseline = hashlib.sha256(baseline + file_bytes).digest()
237
+
238
+ # return baseline.hex()
239
+
240
+ def compute_file_hash(self, file_path: str) -> bytes:
241
+ with open(file_path, "rb") as fin:
242
+ return hashlib.sha256(fin.read()).digest()
243
+
244
+ def compute_model_baseline(self, model_dir: str) -> str:
245
+ file_path_list: List[str] = []
246
+
247
+ for dirpath, _, filenames in os.walk(model_dir):
248
+ for filename in filenames:
249
+ file_path_list.append(os.path.join(dirpath, filename))
250
+
251
+ file_path_list.sort()
252
+
253
+ num_threads=os.cpu_count()
254
+ print(f" Using {num_threads} threads")
255
+
256
+ with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
257
+ file_hashes = list(executor.map(self.compute_file_hash, file_path_list))
258
+ baseline = reduce(lambda acc, x: hashlib.sha256(acc + x).digest(), file_hashes, b"")
259
+
260
+ return baseline.hex()
261
+
262
+ def import_key(self, ring_id: str, key: bytes, key_name: str, desc="") -> None:
263
+ # login
264
+ ts = str(utc8_timestamp())
265
+ req_body = {"Username": self.app_id, "Password": md5_hash(self.password.encode(), ts)}
266
+
267
+ response = requests.post(self.login_url, headers={"TimeStamp": ts}, json=req_body)
268
+ cookies = response.cookies
269
+ jeddak_pcc_session = cookies.get("jeddak_pcc_session")
270
+ cookies = {"jeddak_pcc_session": jeddak_pcc_session,
271
+ "usage_scenario": "ModelEncryption"}
272
+
273
+ self.tks_client.import_key(
274
+ ring_id=ring_id,
275
+ algo="SYMMETRIC_256",
276
+ key=key,
277
+ key_name=key_name,
278
+ desc=desc,
279
+ cookies=cookies,
280
+ )
281
+
282
+ def get_key(self, ring_id: str, key_id: str) -> bytes:
283
+ cookies = self._pcc_login()
284
+ key = self.tks_client.get_key(ring_id, key_id, cookies=cookies)
285
+ return key
286
+
287
+ def upload_model_to_tos(self, model_path: str, bucket_name: str, volc_ak: str, volc_sk: str, region: str, endpoint: str, processes: int = 10):
288
+ try:
289
+ pool = Pool(processes)
290
+
291
+ def upload_dir(root_dir):
292
+ files = [str(file) for file in Path(root_dir).rglob('*') if file.is_file()]
293
+ param_list = []
294
+ for file in files:
295
+ params = {
296
+ "bucket_name": bucket_name,
297
+ "path": file,
298
+ "volc_ak": volc_ak,
299
+ "volc_sk": volc_sk,
300
+ "region": region,
301
+ "endpoint": endpoint
302
+ }
303
+ param_list.append(params)
304
+ pool.map(upload_files, param_list)
305
+ pool.close()
306
+ pool.join()
307
+
308
+ upload_dir(model_path)
309
+ except tos.exceptions.TosClientError as e:
310
+ # 操作失败,捕获客户端异常,一般情况为非法请求参数或网络异常
311
+ print('fail with client error, message:{}, cause: {}'.format(e.message, e.cause))
312
+ except tos.exceptions.TosServerError as e:
313
+ # 操作失败,捕获服务端异常,可从返回信息中获取详细错误信息
314
+ print('fail with server error, code: {}'.format(e.code))
315
+ # request id 可定位具体问题,强烈建议日志中保存
316
+ print('error with request id: {}'.format(e.request_id))
317
+ print('error with message: {}'.format(e.message))
318
+ print('error with http code: {}'.format(e.status_code))
319
+ print('error with ec: {}'.format(e.ec))
320
+ print('error with request url: {}'.format(e.request_url))
321
+ except Exception as e:
322
+ print('fail with unknown error: {}'.format(e))
323
+
324
+ def encrypt_model_and_upload(self,
325
+ model_path: str, bucket_name: str, volc_ak: str, volc_sk, region: str, endpoint: str, app_id: str, top_ak: str = "", top_sk: str = "",
326
+ processes: int = 10, ring_id: str = "", ring_name: str = "", ring_desc: str = "", key_name: str = "", key_desc: str = "", service: str = "pcc",
327
+ tks_addr: str = "pcc.volcengineapi.com", encrypt_flag: bool = True
328
+ ) -> dict:
329
+ # Example usage
330
+ if encrypt_flag:
331
+ print(" Step1.1: model needs encryption")
332
+ top_conf = {
333
+ "ak": volc_ak,
334
+ "sk": volc_sk,
335
+ "service": service,
336
+ "region": region,
337
+ }
338
+
339
+ tks_config = TKSConfig(addr=tks_addr, enable_tls=True, top_config=top_conf)
340
+ tks_client = TKSClient(app_id=app_id, config=tks_config)
341
+
342
+ step = 1
343
+ if not ring_id:
344
+ print(" Step1.2: ring_id is not provided, start creating.")
345
+ assert ring_name, "ring_name should provided when create"
346
+ ring_id = tks_client.create_ring(ring_name=ring_name, desc=ring_desc)["RingID"]
347
+ print(" Step1.3: create ring successfully.")
348
+ step = 3
349
+
350
+ model_name = os.path.basename(model_path)
351
+ enc_output_path = "enc-" + model_name
352
+ data_key = self.encrypt_model(model_path, output_path=enc_output_path)
353
+
354
+ print(" Step1.{}: start import key to tks...".format(1+step))
355
+ assert key_name, "key_name should provided"
356
+ key_id = tks_client.import_key(ring_id=ring_id, algo="SYMMETRIC_256", key=data_key, key_name=key_name, desc=key_desc, usage_scenario="ModelEncryption")["KeyID"]
357
+ print(" Step1.{}: import key to tks successfully.".format(2+step))
358
+
359
+ print(" Step1.{}: start compute model baseline".format(3+step))
360
+ baseline = self.compute_model_baseline(model_path)
361
+ print(" Step1.{}: compute model baseline done.".format(4+step))
362
+
363
+ print(" Step1.{}: start upload enc model to tos...".format(5+step))
364
+ t0 = time()
365
+ self.upload_model_to_tos(model_path=enc_output_path + "/", bucket_name=bucket_name, volc_ak=volc_ak, volc_sk=volc_sk, region=region, endpoint=endpoint, processes=processes)
366
+ print(" Step1.{}: upload to tos done, costs: {} seconds.".format(6+step, time() - t0))
367
+
368
+ if region == "e28-env":
369
+ tos_url = f"https://{bucket_name}.tos-vpc-{region}.e28.inspirecloud.io/{enc_output_path}/"
370
+ elif region == "neimeng-1":
371
+ tos_url = f"https://{bucket_name}.tos-vpc-neimeng-1.pcc.lenovo.com/{enc_output_path}/"
372
+ else:
373
+ tos_url = f"https://{bucket_name}.tos-{region}.ivolces.com/{enc_output_path}/"
374
+ return {
375
+ "ring_id": ring_id,
376
+ "key_id": key_id,
377
+ "baseline": baseline,
378
+ "model_name": model_name,
379
+ "tos_url": tos_url
380
+ }
381
+ else:
382
+ print(" Step1.1: model doesn't need encryption")
383
+ source = model_path
384
+ model_name = os.path.basename(model_path)
385
+ destination = "plain-" + model_name
386
+ copy_folder(source, destination)
387
+ model_name = os.path.basename(model_path)
388
+ print(" Step1.2: start compute model baseline")
389
+ baseline = self.compute_model_baseline(model_path)
390
+ print(" Step1.3: compute model baseline done.")
391
+ print(" Step1.4: start upload model to tos...")
392
+ t0 = time()
393
+
394
+ self.upload_model_to_tos(model_path=destination + "/", bucket_name=bucket_name, volc_ak=volc_ak, volc_sk=volc_sk, region=region, endpoint=endpoint, processes=processes)
395
+ print(f" Step1.5: upload to tos done, costs: {time() - t0} seconds.")
396
+ if region == "e28-env":
397
+ tos_url = f"https://{bucket_name}.tos-vpc-{region}.e28.inspirecloud.io/{destination}/"
398
+ elif region == "neimeng-1":
399
+ tos_url = f"https://{bucket_name}.tos-vpc-neimeng-1.pcc.lenovo.com/{destination}/"
400
+ else:
401
+ tos_url = f"https://{bucket_name}.tos-{region}.ivolces.com/{destination}/"
402
+ return {
403
+ "baseline": baseline,
404
+ "model_name": model_name,
405
+ "tos_url": tos_url
406
+ }
407
+ def _pcc_login(self) -> Dict[str, str]:
408
+ ts = str(utc8_timestamp())
409
+ req_body = {"Username": self.app_id, "Password": md5_hash(self.password.encode(), ts)}
410
+
411
+ response = requests.post(self.login_url, headers={"TimeStamp": ts}, json=req_body)
412
+ cookies = response.cookies
413
+ jeddak_pcc_session = cookies.get("jeddak_pcc_session")
414
+ assert jeddak_pcc_session is not None
415
+ cookies = {"jeddak_pcc_session": jeddak_pcc_session}
416
+ return cookies
@@ -0,0 +1,116 @@
1
+ from bytedance.jeddak_secure_model.model_encryption import EncryptionConfig, JeddakModelEncrypter
2
+ from bytedance.jeddak_secure_model.rds_utils import register_to_rds
3
+ from huggingface_hub import snapshot_download
4
+ import argparse
5
+ import os
6
+ import shutil
7
+ from pathlib import Path
8
+
9
+ parser = argparse.ArgumentParser(description="An useful tool to host a new model for adminstrator.")
10
+ parser.add_argument("--huggingface_model", type=str, default="Qwen/Qwen2.5-0.5B", help="the huggingface modelname")
11
+ parser.add_argument("--rds_url", type=str, default="", help="the rds url used for storing model table")
12
+ parser.add_argument("--bucket_name", type=str, default="jeddakpcc-platform-hosted-models", help="the bucket_name of tos")
13
+ parser.add_argument("--volc_ak", type=str, default="", help="the bucket_name of tos")
14
+ parser.add_argument("--volc_sk", type=str, default="", help="the bucket_name of tos")
15
+ parser.add_argument("--region", type=str, default="cn-beijing", help="the bucket_name of tos")
16
+ parser.add_argument("--endpoint", type=str, default="tos-cn-beijing.volces.com", help="the bucket_name of tos")
17
+ args = parser.parse_args()
18
+
19
+ model_name = args.huggingface_model
20
+ rds_url = args.rds_url
21
+ bucket_name = args.bucket_name
22
+ volc_ak = args.volc_ak
23
+ volc_sk = args.volc_sk
24
+ region = args.region
25
+ endpoint = args.endpoint
26
+ assert rds_url != "", "rds_url is missing"
27
+ assert bucket_name != "", "bucket_name is missing"
28
+ assert volc_ak != "", "volc_ak is missing"
29
+ assert volc_sk != "", "volc_sk is missing"
30
+ assert region != "", "region is missing"
31
+ assert endpoint != "", "endpoint is missing"
32
+ app_id = ""
33
+ top_ak = ""
34
+ top_sk = ""
35
+ ring_id = ""
36
+ ring_name = ""
37
+ ring_desc = ""
38
+ key_name = ""
39
+ key_desc = ""
40
+ service = ""
41
+
42
+
43
+ def replace_symlinks_with_copies(model_name, directory):
44
+ folder_path = Path(model_name)
45
+ folder_path.mkdir(parents=True, exist_ok=True)
46
+ print(f"making dir for {model_name}")
47
+ for root, _, files in os.walk(directory):
48
+ for file in files:
49
+ file_path = os.path.join(root, file)
50
+ if os.path.islink(file_path): # 检测是否是符号链接
51
+ real_path = os.readlink(file_path)
52
+ abs_file_path = Path(file_path)
53
+ real_relative_path = Path(real_path)
54
+ abs_real_path = (abs_file_path.parent / real_relative_path).resolve()
55
+ model_file_path = folder_path / file_path.split("/")[-1]
56
+ print(f"copying {abs_real_path} to {model_file_path}")
57
+ shutil.copy(abs_real_path, model_file_path) # 复制实际文件
58
+ os.unlink(file_path) # 删除符号链接
59
+ # tmp_root_path = Path(directory).parts[0]
60
+ # print(f"removing {tmp_root_path}")
61
+ # shutil.rmtree(tmp_root_path)
62
+
63
+ # Safely remove only the intended cache directory itself.
64
+ tmp_root_path = Path(directory).resolve()
65
+ if tmp_root_path in (Path('/'), Path('.').resolve()) or str(tmp_root_path) in ('/', '.'):
66
+ raise ValueError(f"Refusing to remove dangerous path: {tmp_root_path}")
67
+ print(f"removing {tmp_root_path}")
68
+ shutil.rmtree(tmp_root_path)
69
+
70
+
71
+ local_dir = snapshot_download(repo_id=model_name, cache_dir="./")
72
+ # replace_symlinks_with_copies(model_name, local_dir)
73
+
74
+ old=Path(local_dir)
75
+ new=old.parent / model_name.split("/")[-1]
76
+ try:
77
+ shutil.rmtree(new)
78
+ except Exception as e:
79
+ print(e)
80
+ old.rename(new)
81
+
82
+ model_path = str(new) # 模型的文件夹路径
83
+
84
+
85
+ config = EncryptionConfig("", "")
86
+ encrypter = JeddakModelEncrypter(config)
87
+
88
+ res = encrypter.encrypt_model_and_upload(
89
+ model_path=model_path,
90
+ bucket_name=bucket_name,
91
+ volc_ak=volc_ak,
92
+ volc_sk=volc_sk,
93
+ region=region,
94
+ endpoint=endpoint,
95
+ top_ak=top_ak,
96
+ top_sk=top_sk,
97
+ ring_id=ring_id,
98
+ ring_name=ring_name,
99
+ ring_desc=ring_desc,
100
+ key_name=key_name,
101
+ key_desc=key_desc,
102
+ app_id=app_id,
103
+ service=service,
104
+ encrypt_flag=False
105
+ )
106
+
107
+ model = model_name.split("/")[-1]
108
+ tos_url = f"https://{bucket_name}.{endpoint}/plain-{model}/".replace("volces", "ivolces")
109
+ baseline = res["baseline"]
110
+ model_meta_data = {
111
+ "model_name": model_name,
112
+ "tos_url": tos_url,
113
+ "baseline": baseline
114
+ }
115
+
116
+ register_to_rds(rds_url, model_meta_data)