LLM JSON Schema实战:构建结构化输出的高效解决方案
·
当LLM输出变成开发者的噩梦
上周对接某电商客服系统时,我们让LLM生成订单查询响应。理想中的数据结构应该是这样的:
{
"order_id": "12345",
"status": "shipped",
"estimated_delivery": "2023-12-25"
} 但实际收到的是这种自由发挥版本:
{
"您的订单": "#12345",
"当前状态": "已发货",
"预计到达时间": "圣诞节当天"
}

为什么选择JSON Schema
| 方案 | 开发成本 | 可维护性 | 错误定位 | 扩展性 | |----------------|----------|----------|----------|--------| | 正则表达式 | 高 | 差 | 困难 | 弱 | | 自定义解析器 | 中 | 中 | 一般 | 中 | | JSON Schema | 低 | 优秀 | 精确 | 强 |
核心实战四步走
1. Schema语法三件套
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["order_id", "status"],
"properties": {
"order_id": {
"type": "string",
"pattern": "^\\d{5}$"
},
"status": {
"enum": ["processing", "shipped", "delivered"]
}
}
}
2. 与LangChain集成示例
from langchain.output_parsers import StructuredOutputParser
from jsonschema import validate
schema = {
# 上述schema定义
}
def validate_with_retry(llm_output, max_retries=3):
for attempt in range(max_retries):
try:
validate(instance=llm_output, schema=schema)
return llm_output
except Exception as e:
print(f"Attempt {attempt + 1} failed: {str(e)}")
# 这里可以加入自动修正逻辑
raise ValueError("Max retries exceeded")

3. 动态Schema生成
def build_dynamic_schema(user_query):
base_schema = {
"type": "object",
"properties": {}
}
if "日期" in user_query:
base_schema["properties"]["date"] = {
"type": "string",
"format": "date"
}
return base_schema
4. 性能优化三板斧
- Schema缓存:使用
@lru_cache装饰器缓存编译后的验证器 - 批量验证:采用
jsonschema.Draft7Validator预编译实例 - 框架集成:FastAPI示例:
@app.post("/validate") async def validate_data(data: dict): try: validate(instance=data, schema=settings.SCHEMA) return {"status": "valid"} except ValidationError as e: return JSONResponse( status_code=422, content={"detail": e.message} )
生产环境血泪教训
- 递归深度:限制
$ref嵌套不超过5层 - 字符集陷阱:始终指定
"contentEncoding": "UTF-8" - 版本管理:使用
$schema字段声明版本
终极思考题
我们是否应该允许LLM在additionalProperties: false时依然能创造性地返回metadata字段?这个平衡点该如何把握?

更多推荐


所有评论(0)