W4 · 知识点11:JSON结构化输出实战
学习目标:让大模型稳定输出结构化的维修工单数据,这是设备维修系统后端的核心能力。
一、为什么JSON输出对设备维修系统至关重要
你的系统需要把AI的诊断结果存入数据库、生成工单、推送通知。自由文本无法直接处理,JSON才是程序能"理解"的格式。
自由文本: "这个空压机应该是冷却器堵了,需要清洗,大概要2个小时,
准备清洗剂和一个扳手就行。"
→ 怎么提取故障原因?工时?备件?要写一堆正则表达式...
JSON: {
"root_cause": "冷却器堵塞",
"repair_hours": 2,
"spare_parts": [{"name": "清洗剂", "qty": 1}],
"tools": ["扳手"]
}
→ 直接解析入库,干净利落。
二、方法一:Prompt要求JSON
python
from openai import OpenAI
import json
client = OpenAI()
prompt = """
分析以下设备维修工单,提取结构化信息。
只输出JSON,不要其他内容。
{
"device_name": "设备名称",
"fault_type": "mechanical|electrical|hydraulic|pneumatic|other",
"priority": "urgent|high|medium|low",
"fault_description": "专业故障描述",
"diagnosis": "初步诊断",
"spare_parts": [{"name": "零件名", "spec": "规格", "qty": 数量}],
"estimated_hours": 0
}
工单内容:3号空压机的进气阀漏气了,需要换密封件,
型号是A-200的,要两个。估计1小时能搞定。这个影响生产,比较急。
"""
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": prompt}],
temperature=0,
)
try:
result = json.loads(response.choices[0].message.content)
print(f"设备: {result['device_name']}")
print(f"优先级: {result['priority']}")
print(f"备件: {result['spare_parts']}")
except json.JSONDecodeError as e:
print(f"JSON解析失败: {e}")
三、方法二:response_format(更稳定)
python
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{
"role": "system",
"content": "你是设备维修系统的工单解析引擎,始终以JSON格式输出。"
},
{
"role": "user",
"content": "解析维修工单:3号空压机进气阀漏气,需更换A-200密封件2个,约1小时"
}
],
response_format={"type": "json_object"},
temperature=0,
)
result = json.loads(response.choices[0].message.content)
四、方法三:Structured Outputs(最严格,推荐生产使用)
python
from pydantic import BaseModel, Field
from typing import Optional
# 定义设备维修工单的Schema
class SparePart(BaseModel):
name: str = Field(description="备件名称")
spec: Optional[str] = Field(default=None, description="规格型号")
qty: int = Field(description="数量", ge=1)
class WorkOrderParse(BaseModel):
device_name: str = Field(description="设备名称")
device_id: Optional[str] = Field(default=None, description="设备编号")
fault_type: str = Field(description="故障类型: mechanical|electrical|hydraulic|pneumatic|control|other")
priority: str = Field(description="优先级: urgent|high|medium|low")
fault_description: str = Field(description="专业的故障描述")
diagnosis: str = Field(description="初步诊断结论")
spare_parts: list[SparePart] = Field(description="所需备件列表")
estimated_hours: float = Field(description="预估维修工时(小时)")
safety_notes: list[str] = Field(description="安全注意事项")
# 调用API,传入Schema
response = client.beta.chat.completions.parse(
model="gpt-4o-mini", # 注意:Structured Outputs目前主要支持OpenAI模型
messages=[
{"role": "system", "content": "你是设备维修系统的工单解析引擎。"},
{"role": "user", "content": """解析以下维修信息:
3号空压机进气阀漏气,密封件型号A-200需要2个,
预计1小时完成。涉及压缩空气管路,需先泄压再操作。"""}
],
response_format=WorkOrderParse,
)
# 直接得到Pydantic对象
work_order = response.choices[0].message.parsed
print(f"设备: {work_order.device_name}")
print(f"故障类型: {work_order.fault_type}")
print(f"备件: {[(p.name, p.qty) for p in work_order.spare_parts]}")
print(f"工时: {work_order.estimated_hours}h")
print(f"安全: {work_order.safety_notes}")
五、实战:批量解析维修工单
python
work_orders_raw = [
"2号空压机运行时振动异常,检查发现底座螺栓松动,需要紧固和加防松垫圈,大概半小时",
"1号冷却塔风机皮带断了,换B-2380皮带2根,需要1.5小时,高空作业注意安全",
"3号注塑机加热圈烧了2个,型号HQ-220,换了新的顺便校准温控器,搞了一上午",
"输送带电机过载跳闸,检查发现轴承磨损严重,换6205-2RS轴承2个,预计2小时",
"液压站压力上不去,油泵密封件老化泄漏,更换全套密封件,需停机3小时",
]
for i, raw in enumerate(work_orders_raw, 1):
print(f"\n--- 工单 {i} ---")
print(f"原始: {raw}")
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "你是工单解析引擎,只输出JSON。"},
{"role": "user", "content": f"解析:{raw}"}
],
response_format={"type": "json_object"},
temperature=0,
)
result = json.loads(response.choices[0].message.content)
print(f"解析: 设备={result.get('device_name')}, "
f"类型={result.get('fault_type')}, "
f"工时={result.get('estimated_hours')}h")
六、动手练习
练习1:三种方法对比
用10条维修工单分别测试三种JSON输出方法的成功率和字段完整度。
练习2:构建工单解析API
python
# 实现一个函数:输入维修文本,输出标准化的工单对象
def parse_work_order(raw_text: str) -> dict:
"""
将维修描述解析为标准化工单
Args:
raw_text: 原始维修描述文本
Returns:
标准化的工单字典
Raises:
ValueError: 文本无法解析
json.JSONDecodeError: JSON格式错误
"""
# 你的实现...
pass
# 测试
order = parse_work_order("空压机进气阀漏气,换密封件A-200两个,约1小时")
assert order["device_name"] == "空压机"
assert order["fault_type"] == "pneumatic"
assert len(order["spare_parts"]) == 1
七、本知识点检验标准
- 掌握三种JSON输出方法及其适用场景
- 能用Structured Outputs实现类型安全的工单解析
- 完成批量工单解析,成功率>95%
- 实现了可复用的parse_work_order函数