输出格式控制:让LLM输出精准的结构化内容
LLM 的原生输出是自然语言文本,但在生产环境中,我们往往需要特定格式的输出——JSON 用于程序消费、Markdown 用于文档渲染、表格用于对比展示。格式控制是 Prompt 工程中最基础也最重要的技能之一。
一、为什么格式控制如此重要?
1.1 无格式的代价
无格式控制时的输出(不可靠):
"分析:这款产品很不错...
评分:我给它打8分...
价格方面呢...哦对,价格是...
"
有格式控制时的输出(可靠):
{
"analysis": "产品设计精良,性能出色",
"rating": 8,
"price_tier": "中高端"
}
1.2 格式控制的收益
| 维度 | 无控制 | 有控制 | 提升 |
|---|---|---|---|
| 解析成功率 | 40-60% | 95-99% | 2x |
| 下游处理 | 需NLP解析 | 直接消费 | 10x |
| 错误率 | 20-30% | 1-3% | 10x |
| 调试成本 | 高 | 低 | 5x |
二、基础格式控制技术
2.1 JSON 格式控制
# 方法1:示例驱动
json_prompt_1 = """
分析以下文本,以JSON格式返回:
文本:{text}
输出格式:
{
"sentiment": "正面/负面/中性",
"key_points": ["要点1", "要点2"],
"summary": "一句话总结(20字以内)"
}
"""
# 方法2:Schema驱动
json_prompt_2 = """
{text}
从以上文本中提取信息,严格按照以下JSON Schema输出:
{
"type": "object",
"properties": {
"title": {"type": "string", "description": "标题"},
"author": {"type": "string"},
"date": {"type": "string", "format": "date"},
"tags": {"type": "array", "items": {"type": "string"}},
"word_count": {"type": "integer"},
"summary": {"type": "string", "maxLength": 100}
},
"required": ["title", "author", "date"]
}
"""
# 方法3:使用 Structured Output API(OpenAI/Anthropic)
from pydantic import BaseModel
from openai import OpenAI
class Analysis(BaseModel):
sentiment: str
score: float
keywords: list[str]
summary: str
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": text}],
response_format={"type": "json_object"}
)
2.2 Markdown 格式控制
# 表格输出
table_prompt = """
比较Python和JavaScript的特性,输出Markdown格式表格:
| 特性 | Python | JavaScript |
|------|--------|------------|
| 类型系统 | [填写] | [填写] |
| 执行方式 | [填写] | [填写] |
| 主要用途 | [填写] | [填写] |
| 学习难度 | [填写] | [填写] |
请填写上述表格中的空白处。
"""
# 结构化Markdown
markdown_prompt = """
请以Markdown格式生成一份API文档:
## {api_name}
### 接口说明
{描述}
### 请求方法
{method}
### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| ... | ... | ... | ... |
### 响应示例
```json
{
"code": 0,
"data": {}
}
错误码
| 错误码 | 说明 |
|---|---|
| … | … |
| """ |
## 三、高级输出控制
### 3.1 约束条件
```python
# 数值约束
constraint_prompt_1 = """
只输出一个数字(0-100之间的整数),表示评分:
产品:{product_name}
评分:
"""
# 枚举约束
constraint_prompt_2 = """
分类结果只能是以下之一:
[A] 技术问题
[B] 账单问题
[C] 产品咨询
[D] 投诉建议
用户问题:{question}
分类:[只输出字母]
"""
# 长度约束
constraint_prompt_3 = """
用不超过50个字总结以下内容:
{text}
字数统计:___字
"""
3.2 链式格式控制
# 多轮格式控制
chain_prompt = """
第1步:提取信息
输出JSON:
{
"entities": [],
"relations": []
}
第2步:生成摘要
基于第1步的结果,生成一段100字以内的摘要。
第3步:翻译
将第2步的摘要翻译成英文。
请按顺序执行以上三步,每一步的执行结果都必须输出,
不要跳过任何步骤。
"""
四、格式控制实战
4.1 客户评论分析
review_prompt = """
分析以下客户评论,输出结构化结果:
评论:{review}
{
"sentiment": "positive" | "negative" | "neutral",
"rating": 1-5分,
"aspects": {
"product_quality": "good" | "average" | "poor" | "not_mentioned",
"customer_service": "good" | "average" | "poor" | "not_mentioned",
"price_value": "good" | "expensive" | "fair" | "not_mentioned",
"delivery": "fast" | "slow" | "not_mentioned"
},
"key_quotes": ["引用原文中最关键的2-3句"],
"actionable": true | false,
"action_items": ["需要处理的改进点"]
}
要求:
1. 所有字段都必须填写
2. key_quotes必须引用原文
3. 如果某个aspect未提及,填写"not_mentioned"
"""
4.2 代码生成控制
code_prompt = """
请生成一个Python函数,要求:
功能:{description}
输出格式:
```python
def function_name(params):
\"\"\"
文档字符串
\"\"\"
# 实现
return result
# 使用示例
example_result = function_name(...)
print(example_result)
约束:
- 包含类型注解
- 包含详细的文档字符串
- 包含至少一个使用示例
- 代码必须能直接运行 """
## 五、常见问题与解决方案
### 5.1 格式不一致
| 问题 | 表现 | 原因 | 解决方案 |
|------|------|------|---------|
| JSON 无效 | 缺少逗号、引号不匹配 | 模型对格式不够敏感 | 使用 Structured Output API |
| 字段缺失 | 部分字段没有输出 | 约束不够明确 | 添加 required 列表 |
| 额外内容 | 在JSON前后加了说明文字 | 模型习惯增加解释 | 明确"只输出JSON" |
| 类型错误 | 数字变成了字符串 | Schema 不够严格 | 使用 Pydantic 模型 |
### 5.2 调试技巧
```python
def validate_json_output(response):
"""验证JSON输出并给出反馈"""
try:
data = json.loads(response)
print("✅ JSON有效")
return data
except json.JSONDecodeError as e:
print(f"❌ JSON无效: {e}")
print(f" 位置: 第{e.lineno}行, 第{e.colno}列")
print(f" 附近文本: ...{response[max(0, e.pos-20):e.pos+20]}...")
return None
六、最佳实践 Checklist
- 提供明确的输出模板/示例
- 使用 Schema 定义约束(JSON Schema, Pydantic)
- 指定缺失字段的默认值
- 添加”只输出指定格式”的硬约束
- 验证输出格式并反馈修正
- 考虑使用 Structured Output / Function Calling
- 对关键输出做格式校验
总结
输出格式控制是 Prompt 从”能用”到”好用”的关键一跃。掌握 JSON Schema、Structured Output、长度/枚举约束等技巧,能让 LLM 输出从”自然语言”变为”机器可消费的数据”。