LLM prompt engineering 实战 6 个 pattern(少花钱 + 多对题)

起因

接了一个"自动分类客服工单" 的任务。最 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。

技巧:

  1. 删冗余形容词:"请帮忙仔细认真地分析下面..." → "分析:"
  2. 缩短例子:3 个例子够时不放 10 个
  3. 不重复 system + user:system 里写完类别后 user 不重复
  4. truncate 长输入:保留 ticket 前 1000 字符(多数信号在开头)
  5. 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

踩过的坑

  1. 改 prompt 不跑 eval:"感觉变好了"是偏见。每次改后跑测试集
    验证。

  2. prompt 越改越长:加 patch 修 case → 长 prompt → 模型 confused。
    定期 refactor 简化。

  3. 生产环境模型版本变:OpenAI / Anthropic 偶尔 silent 升级模型,
    prompt 行为变化。pin model name 包括 date suffix
    (gpt-4o-2024-08-06) + 监控 metrics。

  4. temperature:分类 / 提取类 task 设 0 (deterministic)。
    创意写作设 0.7-1.0。

  5. 隐私数据:不要把客户 PII 直接发 OpenAI。先 mask 邮箱 / 手机
    / 信用卡再调 API。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。