在Azure ML Studio中部署HuggingFace cross-encoder-nli-deberta-v3-base模型端点后调用失败,报Failed Dependency错误求助
你好!这个Failed Dependency错误的根源很明确:你的请求payload格式和Azure ML托管端点上模型的默认推理逻辑不兼容。错误信息里提到的"loc":["body","inputs"],"msg":"field required",说明端点期望请求体里必须有inputs字段,但你当前的test_payload.json用的是zero-shot分类的pipeline格式(text+candidate_labels),和模型原生的输入要求不匹配。
我给你两个解决方案,一个是快速验证的临时方案,另一个是推荐的长期方案,能让你直接用你想要的payload格式得到预期的分类结果:
方案1:快速适配模型原生输入(临时验证用)
cross-encoder-nli-deberta-v3-base的原生设计是处理文本对(NLI任务的前提+假设),要做zero-shot分类的话,你需要把待分类文本和每个候选标签配对,作为模型的输入。
修改你的test_payload.json为以下格式:
{ "inputs": [ ["I have a problem with my iphone that needs to be resolved asap!!", "urgent"], ["I have a problem with my iphone that needs to be resolved asap!!", "not urgent"], ["I have a problem with my iphone that needs to be resolved asap!!", "phone"], ["I have a problem with my iphone that needs to be resolved asap!!", "tablet"], ["I have a problem with my iphone that needs to be resolved asap!!", "computer"] ] }
调用端点后,你会得到每个文本对的相似度分数,之后可以自己计算分数最高的标签就是分类结果。
方案2:自定义推理脚本(推荐,还原pipeline式的易用性)
如果你想直接用你原来的text+candidate_labels格式的payload,并且让端点直接返回带标签和分数的分类结果,需要在部署时添加自定义的推理脚本,把用户输入转换成模型能处理的格式。步骤如下:
1. 创建推理脚本score.py
在你的代码目录下新建一个score.py文件,内容如下:
from transformers import AutoModelForSequenceClassification, AutoTokenizer, pipeline import json def init(): global classifier # 加载模型和tokenizer(Azure ML会自动把模型挂载到"model"目录) model = AutoModelForSequenceClassification.from_pretrained("model") tokenizer = AutoTokenizer.from_pretrained("model") # 初始化zero-shot分类pipeline classifier = pipeline( "zero-shot-classification", model=model, tokenizer=tokenizer ) def run(raw_data): # 解析用户传入的JSON payload data = json.loads(raw_data) # 调用pipeline执行zero-shot分类 result = classifier( text=data["text"], candidate_labels=data["candidate_labels"] ) # 返回JSON格式的结果 return json.dumps(result)
2. 修改部署代码,添加环境和代码配置
在你原来的部署代码中,添加环境配置和代码配置,让Azure ML知道用你的自定义脚本进行推理。修改后的部署相关代码如下:
首先,定义适配Hugging Face模型的环境:
from azure.ai.ml.entities import Environment, CodeConfiguration # 创建包含transformers等依赖的环境 hf_env = Environment( image="mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04:latest", conda_file={ "name": "zero-shot-env", "dependencies": [ "python=3.8", {"pip": ["transformers>=4.20.0", "torch>=1.12.0", "accelerate"]} ] } ) # 指定推理脚本的路径(假设score.py在当前工作目录) code_config = CodeConfiguration( code="./", scoring_script="score.py" )
然后,在创建ManagedOnlineDeployment时,把code_configuration和environment参数加进去:
ml_client.online_deployments.begin_create_or_update(ManagedOnlineDeployment( name="demo", endpoint_name=endpoint_name, model=model_id, instance_type="Standard_DS3_v2", instance_count=1, code_configuration=code_config, environment=hf_env )).wait()
3. 用原来的test_payload.json调用端点
重新部署完成后,你就可以用你原来的test_payload.json来调用端点了,返回的结果会和你预期的一样:包含分类后的标签和对应的分数,比如:
{ "sequence": "I have a problem with my iphone that needs to be resolved asap!!", "labels": ["urgent", "phone", "not urgent", "computer", "tablet"], "scores": [0.96, 0.92, 0.08, 0.03, 0.01] }
为什么原来的代码会报错?
因为你部署时没有指定自定义的推理脚本,Azure ML会使用自动生成的默认脚本,这个脚本是直接调用模型的forward方法,只接受模型原生的输入格式(也就是需要inputs字段的文本对),而不支持你想要的zero-shot pipeline格式,所以才会提示缺少inputs字段。
内容来源于stack exchange

