@@ -53,91 +53,92 @@ def deploy_model(model_id: str, region: str = "cn-hangzhou", storage: str = "nas
5353 Returns:
5454 tuple: (部署的URL, 配置文件路径)
5555 """
56- # 生成函数名称
57- # 加个随机数
58- function_name = f"test-{ simple_hash (model_id )} -{ secrets .token_hex (4 )} "
59-
60- # 准备请求数据
61- deploy_data = {
62- "functionName" : function_name ,
63- "region" : region ,
64- "authType" : "bearer" ,
65- "tokenData" : token ,
66- }
56+ s_yaml_file = f"s.yaml"
57+
58+ try :
59+ # 生成函数名称
60+ # 加个随机数
61+ function_name = f"test-{ simple_hash (model_id )} -{ secrets .token_hex (4 )} "
62+
63+ # 准备请求数据
64+ deploy_data = {
65+ "functionName" : function_name ,
66+ "region" : region ,
67+ "authType" : "bearer" ,
68+ "tokenData" : token ,
69+ }
70+
71+ # 打印生成的token
72+ print (f"生成的随机token: { token } " )
73+
74+ # URL编码模型ID
75+ encoded_model_id = urllib .parse .quote (model_id , safe = "" )
6776
68- # 打印生成的token
69- print (f"生成的随机token: { token } " )
77+ # 调用部署接口
78+ model_registry_url = os .getenv ("MODEL_REGISTRY_URL" , "model-registry.devsapp.cn" )
79+ deploy_url = (
80+ f"http://{ model_registry_url } /api/v1/models/{ encoded_model_id } /deploy-info"
81+ )
82+ print (f"deploy url: { deploy_url } " )
83+ print (f"正在部署模型: { model_id } " )
84+ print (f"请求URL: { deploy_url } " )
85+ print (f"请求数据: { json .dumps (deploy_data , indent = 2 )} " )
7086
71- # URL编码模型ID
72- encoded_model_id = urllib .parse .quote (model_id , safe = "" )
87+ response = requests .post (
88+ deploy_url ,
89+ headers = {"accept" : "application/json" , "Content-Type" : "application/json" },
90+ data = json .dumps (deploy_data ),
91+ )
7392
74- # 调用部署接口
75- model_registry_url = os .getenv ("MODEL_REGISTRY_URL" , "model-registry.devsapp.cn" )
76- deploy_url = (
77- f"http://{ model_registry_url } /api/v1/models/{ encoded_model_id } /deploy-info"
78- )
79- print (f"deploy url: { deploy_url } " )
80- print (f"正在部署模型: { model_id } " )
81- print (f"请求URL: { deploy_url } " )
82- print (f"请求数据: { json .dumps (deploy_data , indent = 2 )} " )
83-
84- response = requests .post (
85- deploy_url ,
86- headers = {"accept" : "application/json" , "Content-Type" : "application/json" },
87- data = json .dumps (deploy_data ),
88- )
93+ if response .status_code != 200 :
94+ raise Exception (f"部署请求失败: { response .status_code } - { response .text } " )
95+
96+ result = response .json ()
97+ print (f"部署响应: { json .dumps (result , indent = 2 )} " )
98+
99+ # 检查响应是否成功
100+ if not result .get ("success" , False ):
101+ raise Exception (f"部署失败: { result .get ('error' , 'Unknown error' )} " )
102+
103+ # 提取部署信息
104+ deploy_info = result .get ("data" , {})
105+
106+ # 使用当前文件夹下的s.yaml内容作为基础配置
107+ with open ("s.yaml" , "r" , encoding = "utf-8" ) as f :
108+ s_yaml = yaml .safe_load (f )
109+
110+ # 更新resources中的props
111+ s_yaml ["resources" ]["test_func" ]["props" ] = deploy_info
112+
113+ # 下载到 oss
114+ if storage == "oss" :
115+ s_yaml ["resources" ]["test_func" ]["props" ].pop ("nasConfig" , None )
116+ s_yaml ["resources" ]["test_func" ]["props" ].pop ("vpcConfig" , None )
117+ s_yaml ["resources" ]["test_func" ]["props" ]["ossMountConfig" ] = f"auto|bucketPath={ function_name } "
118+ s_yaml ["resources" ]["test_func" ]["props" ][
119+ "role"
120+ ] = "acs:ram::${config('AccountID')}:role/aliyunfcdefaultrole"
121+ s_yaml ["resources" ]["test_func" ]["props" ]["annotations" ]["modelConfig" ][
122+ "storage"
123+ ] = storage
124+ # 修改 customContainerConfig.entrypoint 中的路径
125+ custom_container_config = s_yaml ["resources" ]["test_func" ]["props" ].get ("customContainerConfig" , {})
126+ if "entrypoint" in custom_container_config :
127+ entrypoint = custom_container_config ["entrypoint" ]
128+ if isinstance (entrypoint , list ):
129+ # 遍历 entrypoint 数组,替换包含 /mnt/ 的路径
130+ for i , item in enumerate (entrypoint ):
131+ if isinstance (item , str ) and "/mnt/" in item and not item .startswith ("vllm" ) and not item .isdigit () and item not in ["--port" , "--served-model-name" , "--trust-remote-code" ]:
132+ entrypoint [i ] = f"/mnt/serverless-{ region } -d70a9a8a-c817-5ed1-a293-4be0908f0a5"
133+ custom_container_config ["entrypoint" ] = entrypoint
89134
90- if response .status_code != 200 :
91- raise Exception (f"部署请求失败: { response .status_code } - { response .text } " )
92-
93- result = response .json ()
94- print (f"部署响应: { json .dumps (result , indent = 2 )} " )
95-
96- # 检查响应是否成功
97- if not result .get ("success" , False ):
98- raise Exception (f"部署失败: { result .get ('error' , 'Unknown error' )} " )
99-
100- # 提取部署信息
101- deploy_info = result .get ("data" , {})
102-
103- # 使用当前文件夹下的s.yaml内容作为基础配置
104- with open ("s.yaml" , "r" , encoding = "utf-8" ) as f :
105- s_yaml = yaml .safe_load (f )
106-
107- # 更新resources中的props
108- s_yaml ["resources" ]["test_func" ]["props" ] = deploy_info
109-
110- # 下载到 oss
111- if storage == "oss" :
112- s_yaml ["resources" ]["test_func" ]["props" ].pop ("nasConfig" , None )
113- s_yaml ["resources" ]["test_func" ]["props" ].pop ("vpcConfig" , None )
114- s_yaml ["resources" ]["test_func" ]["props" ]["ossMountConfig" ] = "auto"
115- s_yaml ["resources" ]["test_func" ]["props" ][
116- "role"
117- ] = "acs:ram::${config('AccountID')}:role/aliyunfcdefaultrole"
118- s_yaml ["resources" ]["test_func" ]["props" ]["annotations" ]["modelConfig" ][
119- "storage"
120- ] = storage
121- # 修改 customContainerConfig.entrypoint 中的路径
122- custom_container_config = s_yaml ["resources" ]["test_func" ]["props" ].get ("customContainerConfig" , {})
123- if "entrypoint" in custom_container_config :
124- entrypoint = custom_container_config ["entrypoint" ]
125- if isinstance (entrypoint , list ):
126- # 遍历 entrypoint 数组,替换包含 /mnt/ 的路径
127- for i , item in enumerate (entrypoint ):
128- if isinstance (item , str ) and "/mnt/" in item and not item .startswith ("vllm" ) and not item .isdigit () and item not in ["--port" , "--served-model-name" , "--trust-remote-code" ]:
129- entrypoint [i ] = f"/mnt/serverless-{ region } -d70a9a8a-c817-5ed1-a293-4be0908f0a5"
130- custom_container_config ["entrypoint" ] = entrypoint
131-
132- # 保存配置到临时文件
133- s_yaml_file = f"s.yaml"
134- with open (s_yaml_file , "w" , encoding = "utf-8" ) as f :
135- yaml .dump (s_yaml , f , default_flow_style = False , allow_unicode = True )
135+ # 保存配置到临时文件
136+ with open (s_yaml_file , "w" , encoding = "utf-8" ) as f :
137+ yaml .dump (s_yaml , f , default_flow_style = False , allow_unicode = True )
136138
137- print (f"使用配置文件部署: { s_yaml_file } " )
139+ print (f"使用配置文件部署: { s_yaml_file } " )
138140
139- # 执行部署命令
140- try :
141+ # 执行部署命令
141142 # 下载模型
142143 print ("正在下载模型..." )
143144 subprocess .check_call (f"s model download -y -t { s_yaml_file } " , shell = True )
@@ -160,6 +161,13 @@ def deploy_model(model_id: str, region: str = "cn-hangzhou", storage: str = "nas
160161 return deploy_url , s_yaml_file
161162
162163 except subprocess .CalledProcessError as e :
164+ print (f"部署过程失败: { e } " )
165+ print ("即使部署失败,仍将尝试执行清理操作..." )
166+ # 即使部署失败,也要尝试清理资源
167+ try :
168+ cleanup_deployment (s_yaml_file )
169+ except Exception as cleanup_error :
170+ print (f"清理操作也失败了: { cleanup_error } " )
163171 raise Exception (f"部署过程失败: { e } " )
164172 except Exception as e :
165173 raise Exception (f"获取部署信息失败: { e } " )
@@ -349,15 +357,19 @@ def cleanup_deployment(s_yaml_file: str):
349357 Args:
350358 s_yaml_file: Serverless Devs 配置文件路径
351359 """
360+ if not s_yaml_file or not os .path .exists (s_yaml_file ):
361+ print (f"配置文件不存在: { s_yaml_file } " )
362+ return
363+
352364 try :
353365 print (f"正在清除部署资源: { s_yaml_file } " )
354366 # 清除模型
355- subprocess .check_call (f"s model remove -y -t { s_yaml_file } " , shell = True )
367+ print ("正在清除模型..." )
368+ subprocess .run (f"s model remove -y -t { s_yaml_file } " , shell = True , check = False )
356369 # 清除函数
357- subprocess .check_call (f"s remove -y -t { s_yaml_file } --skip-push" , shell = True )
370+ print ("正在清除函数..." )
371+ subprocess .run (f"s remove -y -t { s_yaml_file } --skip-push" , shell = True , check = False )
358372 print ("部署资源清除完成!" )
359- except subprocess .CalledProcessError as e :
360- print (f"清除部署资源失败: { e } " )
361373 except Exception as e :
362374 print (f"清除部署资源时发生错误: { e } " )
363375
@@ -379,6 +391,8 @@ def main():
379391
380392 args = parser .parse_args ()
381393
394+ s_yaml_file = None
395+
382396 try :
383397 if args .cleanup :
384398 # 只执行清除操作
@@ -411,6 +425,14 @@ def main():
411425
412426 except Exception as e :
413427 print (f"错误: { e } " )
428+ # 如果启用了自动清理且有配置文件,即使出错也要尝试清理
429+ if args .auto_cleanup and s_yaml_file :
430+ print ("尝试执行清理操作..." )
431+ try :
432+ cleanup_deployment (s_yaml_file )
433+ print ("清理操作完成!" )
434+ except Exception as cleanup_error :
435+ print (f"清理操作失败: { cleanup_error } " )
414436 return 1
415437
416438 return 0
0 commit comments