起因
接了一个"自动分类客服工单" 的任务。最 naive prompt:
分类下面的客服请求到一个类别:
{ticket}
效果:60% 正确率 + 经常输出无关解释 + 偶尔编造类别。
调了几轮 prompt 后到 92%,token 使用减半。下面是几个真正提分的
pattern,不是"魔法咒语"。
Pattern 1: 明确角色 + 任务 + 输出格式
你是客服工单分类专家。
任务:把客户请求归到下面一个类别。
类别(严格选其中一个):
- billing (付款 / 发票 / 退款)
- bug (产品故障 / 异常报错)
- feature_request (希望新增功能)
- account (账号登录 / 权限 / 密码)
- other (上面都不对)
输出格式:
{"category": "<类别名>", "confidence": <0-1>}
不要输出任何额外解释。
客户请求:
{ticket}
为什么有效:
- 角色:把模型从"通用助手" 引导到"分类专家"语境
- 限制类别:明确告诉它可选范围,减少幻觉
- JSON 输出:好解析 + 没散文废话
- "不要输出额外解释":明确禁止前/后缀闲话
立刻从 60% → 80%。
Pattern 2: Few-shot 例子
光描述类别不够,给具体例子:
[上面的 prompt...]
例子:
输入:「我的卡被扣了两次,请退一次」
输出:{"category": "billing", "confidence": 0.95}
输入:「点击保存按钮后页面卡死」
输出:{"category": "bug", "confidence": 0.9}
输入:「能不能加个深色模式?」
输出:{"category": "feature_request", "confidence": 0.95}
输入:{ticket}
输出:
3-5 个例子覆盖"边界 / 容易混淆" 的情况效果最好。
"为什么这个分到 billing 而不是 account" 类的边界 case 用例子讲清楚。
→ 80% → 90%。
Pattern 3: Chain of thought(思考过程)
对推理类任务(不是简单分类)让模型先"想"再答:
你是数学题解题专家。
题目:一个商店周一卖了 23 件商品,周二是周一的 1.5 倍,
周三是周一周二之和的一半。三天总共卖了多少?
要求:
1. 先逐步推理(标 [思考])
2. 再给最终答案(标 [答案])
模型输出:
[思考]
- 周一:23 件
- 周二:23 × 1.5 = 34.5 件 → 取整 35(实际 35 才合理)
- 周三:(23 + 35) / 2 = 29 件
- 总:23 + 35 + 29 = 87 件
[答案] 87
直接问"答案是?"很多时候算错。让它写推理过程后准确率显著上升。
适合:数学 / 推理 / 多步逻辑。
不适合:简单 lookup / 分类(CoT 浪费 token)。
Pattern 4: Structured output (JSON mode / function call)
不要让 LLM 用 markdown 包 JSON 后让你正则提取——浪费 token + 不稳定。
直接用 API 的 structured output:
from openai import OpenAI
import json
client = OpenAI()
resp = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}],
response_format={
'type': 'json_schema',
'json_schema': {
'name': 'ticket_classification',
'schema': {
'type': 'object',
'properties': {
'category': {
'type': 'string',
'enum': ['billing', 'bug', 'feature_request', 'account', 'other'],
},
'confidence': {'type': 'number', 'minimum': 0, 'maximum': 1},
},
'required': ['category', 'confidence'],
'additionalProperties': False,
},
'strict': True,
}
}
)
result = json.loads(resp.choices[0].message.content)
strict: true 让模型在 decoding 时只产生 schema 合法 token。
100% 合规 JSON,从此不需要 try/except parse。
Anthropic 用 tool use / Gemini 用 response_schema 同理。
Pattern 5: 减少 token = 省钱 + 快
token 不仅是钱,还是延迟。每个 token 大模型 50-200ms。
技巧:
- 删冗余形容词:"请帮忙仔细认真地分析下面..." → "分析:"
- 缩短例子:3 个例子够时不放 10 个
- 不重复 system + user:system 里写完类别后 user 不重复
- truncate 长输入:保留 ticket 前 1000 字符(多数信号在开头)
- batch 处理:5 个工单一起喂("分析下面 5 个 ticket")省 system token
# 单条 vs batch
single_cost = (system_tokens + ticket_tokens + output) * N
batch_cost = (system_tokens + N * ticket_tokens + N * output)
# batch 省的是 N 份 system tokens
我们 batch=10 后 token 量降 30%。注意 batch 太大模型 attention 分散
精度反而降,5-15 是甜点。
Pattern 6: 自检 / verifier loop
对关键任务,跑两次让另一个 prompt 验证:
# Pass 1: 主分类
result = classify(ticket)
# Pass 2: 验证
verify_prompt = f"""
有人把这个工单分类为 '{result['category']}'。是否合理?
工单:{ticket}
输出 JSON: {{"agree": true|false, "reason": "..."}}
"""
verify = llm(verify_prompt)
if not verify['agree']:
# 退到人工 review 队列
flag_for_human(ticket, result, verify['reason'])
cost 翻倍但低置信度 ticket 被人工接管,整体准确率上 96%+。
一些反 pattern
❌ 写一堆"必须 / 不要 / 绝对"
你必须按下面规则。
你绝对不能输出 X。
你一定要返回 JSON。
你不允许加任何解释。
你必须用中文。
模型对负面指令响应一般。改成正面:
输出只包含 JSON。返回的语言是中文。
❌ 提供模糊定义
分类为:
- 重要的问题
- 不重要的问题
"重要" 没定义 → 模型自己猜 → 不稳定。
给具体标准 + 例子。
❌ "请尽量准确" 这种废话
模型不会因为你 polite 就更努力。直接指令。
❌ 给"超过 100k token" 的 context
大 context 时模型有"middle lost in the haystack" 效应——中间的信息
被忽略。能 chunk + RAG 的就别一次塞。
调试 / 评估
写个 eval set(30-100 个 ground truth 例子):
test_cases = [
{'ticket': '...', 'expected': 'billing'},
{'ticket': '...', 'expected': 'bug'},
...
]
correct = 0
for tc in test_cases:
pred = classify(tc['ticket'])
if pred['category'] == tc['expected']:
correct += 1
print(f'accuracy: {correct/len(test_cases):.2%}')
每改 prompt 跑一遍 eval。比"感觉好像准了" 客观。
用 LangSmith / Promptfoo / weave 等工具系统化跑 A/B prompt 对比。
模型选择
不同任务用不同模型:
| 任务 | 推荐 |
|---|---|
| 简单分类 / 提取 | gpt-4o-mini / claude-haiku(便宜 + 快) |
| 推理 / 代码 | gpt-4o / claude-sonnet-4-5 |
| 极致难推理 | o1 / claude opus-4-7 / DeepSeek-R1 |
| 本地隐私 | qwen2.5:14b / llama3.1:8b(Ollama) |
强行用大模型做简单分类 = 浪费钱。
效果
工单分类项目最终:
- 准确率 60% → 92% (+ verifier 后 96%)
- 单 ticket 成本 $0.012 → $0.003(batch + 改 mini)
- P95 延迟 5s → 1.2s(mini + structured output)
- 总 month cost 从 $800 → $150
踩过的坑
-
改 prompt 不跑 eval:"感觉变好了"是偏见。每次改后跑测试集
验证。 -
prompt 越改越长:加 patch 修 case → 长 prompt → 模型 confused。
定期 refactor 简化。 -
生产环境模型版本变:OpenAI / Anthropic 偶尔 silent 升级模型,
prompt 行为变化。pin model name 包括 date suffix
(gpt-4o-2024-08-06) + 监控 metrics。 -
temperature:分类 / 提取类 task 设 0 (deterministic)。
创意写作设 0.7-1.0。 -
隐私数据:不要把客户 PII 直接发 OpenAI。先 mask 邮箱 / 手机
/ 信用卡再调 API。
登录后参与评论。