结构化输出不能证明事实正确

采购、工单和文档抽取常需要稳定JSON,而不是模型加一段解释再包围代码块。vLLM提供结构化输出约束,可以降低格式不一致,但它不保证名称、数字和结论来自原文。本文以vLLM 0.18.0接口为例,使用已经运行的本地Qwen3服务,先固定非思考模式与短输入验证。

较早版本使用的guided_json等旧字段与近期structured_outputs并非完全通用。安装时核对版本,遇到字段无效不继续把普通文本当作结构化结果。模型、Tokenizer与约束后端也要包含在运行清单中。

一个明确的业务Schema

schema={
 'type':'object',
 'properties':{
   'gpu_model':{'type':['string','null']},
   'gpu_count':{'type':['integer','null'],'minimum':1},
   'memory_gb':{'type':['number','null'],'minimum':0},
   'missing_fields':{'type':'array','items':{'type':'string'}}
 },
 'required':['gpu_model','gpu_count','memory_gb','missing_fields'],
 'additionalProperties':False
}

允许null表示原文没有信息,避免模型为满足必填字段编造配置。missing_fields记录待确认项,但也需要业务程序核验。Schema支持范围取决于后端,不是所有复杂JSON Schema关键字都能直接使用;先用小结构再增加组合条件。

发起请求并进行双重验证

pip install requests jsonschema
import json, requests
from jsonschema import validate
source='需要两张RTX 5090,每张32GB显存,用于内网问答。'
payload={
 'model':'qwen3-8b','temperature':0,'max_tokens':400,
 'messages':[
  {'role':'system','content':'只从材料抽取。没有的信息用null,不把总显存当作单卡显存。'},
  {'role':'user','content':source}
 ],
 'chat_template_kwargs':{'enable_thinking':False},
 'structured_outputs':{'json':schema}
}
r=requests.post('http://127.0.0.1:8000/v1/chat/completions',
                json=payload,timeout=(5,120))
r.raise_for_status()
choice=r.json()['choices'][0]
if choice['finish_reason']=='length':
 raise ValueError('输出被截断,不能入库')
obj=json.loads(choice['message']['content'])
validate(instance=obj,schema=schema)
assert obj['gpu_count']==2
assert obj['memory_gb']==32
print(obj)

实际运行时将上一个代码块的schema与本块保存在同一文件。这里的assert只针对这条已知样本,正式程序需要领域规则和人工复核,而不是对任意输入都强制得到两张5090。单卡与总显存、GB与GiB、含税与未税等口径应明确。

把异常分成三类

网络失败、输出不合法和事实不可靠分别处理。连接超时可以有限重试;输出截断可以在上限内增加预算或缩短材料;Schema合法但原文缺信息,应进入待确认状态而不是反复让模型补齐。每次保留请求ID、尝试次数和失败原因。

重试应有上限与退避,非幂等业务不能因为模型响应失败就重复创建订单。先抽取成候选,再由确定性代码验证并写入数据库。涉及付款、合同或高风险操作时,模型输出不能直接触发执行。

验收集不能全是标准格式

准备至少50段材料,包含完整配置、缺失数量、模糊单位、否定信息、两个候选和恶意指令。分别统计JSON合法率、字段准确率、缺失项识别率和误补率。原文中的“忽略前面要求”应作为数据,不应改变系统规则;结构约束本身不能消除提示注入。

一次抽取成功不证明能够批量发布。先给管理员可编辑候选,显示原材料与字段对照,确认后再发布。这样也方便定位数据来自模型误读还是原提交不清楚。

常见故障与回退

字段报错先查vLLM版本与JSON后端;超时检查约束编译、输入长度和GPU队列;返回思考文本检查模板开关;合法JSON出现错误数字检查提示和业务单位,不通过放宽Schema解决。回退到旧版本前复跑同一套50条材料,保留失败队列,不丢弃原始输入。

官方依据:vLLM 0.18.0结构化输出。

把来源证据绑定到字段

实际抽取建议为关键字段同时保存原文片段、位置和候选值。比如显卡数量来自哪一句,显存是单卡还是整机,预算是否含税,都应能回到原材料核对。模型给出的证据片段也可能不存在,程序需检查它是否确实属于输入;对于扫描件,保存页码与截图区域,而不是仅保留识别后的文字。

多候选材料不要强行压成一个配置。用户可能同时比较两卡工作站和四卡服务器,输出应保存候选列表与各自字段,或提示人工选择。Schema应与业务真实结构一致,不因界面只有一行数据就要求模型抹掉不同方案。单位换算由确定性程序完成,原始单位同时保存。

缺失信息与确认流程

没有明确数量、租期或用途时,标记待确认,允许管理员补充但保留原提交。不要自动把“几张卡”解释成两张,把“长期”解释成一年。模型抽取与人工修改分别记录操作者、时间和版本,发布前检查必须项。这样出现争议时能够区分原始描述、模型理解与运营人员整理。

对否定信息单独设计样本,例如“不接受消费卡”“不是整机租赁”。原句与字段含义不一致时进入复核。系统提示即使要求只读材料,也不能彻底防止提示注入,应限制模型执行权限,不提供订单修改或支付能力。资料中的链接和代码作为文本处理,不自动访问或执行。

批量任务的稳定性

每条材料分配唯一任务ID,记录模型revision、模板、Schema版本和请求参数。网络重试只重跑推理阶段,数据库写入使用幂等键,避免同一提交生成多条公开信息。候选结果先写暂存状态,管理员确认后再发布;输出不完整时保留失败原因,不能用空字符串代替所有异常。

验收报告按字段列出正确、错误、缺失和误补,不只统计整体合法率。金额、数量、日期与否定条件使用更严格规则,长文本加入截断检查。新模型或新Schema上线时对历史测试集回归,观察错误是否集中在某一来源。日志需脱敏,保存原材料的访问权限与业务记录保持一致。

来源、翻译与版权说明

来源:网昱算力学院 · 技术编辑。第三方内容版权归原作者或发布机构所有;本站仅在许可证或明确授权允许时提供本地原文。

原文语言
ZH
原文更新时间
未提供
许可证
原创工程内容