写 Prompt 谁都会,但把 Prompt 做成可复现、可评测、可持续改进的系统,才是 AI 工程的分水岭。这篇聊聊怎么从“手感调参”走向“数据驱动”。
一个好 Prompt 的结构
与其把要求堆成一段话,不如显式地分块:
# 角色
你是一位严谨的技术文档助手。
# 任务
根据【资料】回答【问题】,只依据资料作答。
# 约束
- 资料中没有的信息,回答“资料未提及”。
- 使用简体中文,控制在 200 字以内。
# 输出格式
{ "answer": string, "sources": number[] }
分块的好处是:每一块都能独立修改和 A/B 测试,而不会牵一发动全身。
进阶技巧
- 少样本(few-shot):给 2–3 个正例 + 1 个反例,比空讲规则更有效。
- 边界声明:明确“不要编造链接 / 不要输出隐私”。
- 失败模式:告诉模型在不确定时如何降级(拒答、追问、转人工)。
把 Prompt 当代码管理
- 版本化:Prompt 存进 Git,每次改动都有 diff 和 commit message。
- 参数化:把变量抽出来,用模板渲染,而不是字符串拼接。
- 环境隔离:开发、测试、生产用不同版本,灰度上线。
from string import Template
PROMPT = Template("""角色:$role
任务:$task
资料:$context
问题:$question""")
msg = PROMPT.substitute(role=role, task=task, context=ctx, question=q)
建议目录:
prompts/
answer_v3.md
answer_v3.eval.json
judge_v1.md
没有评测,就没有迭代
调 Prompt 最大的坑是“改完感觉变好了”——但感觉不可靠。你需要一个评测集:
- 收集真实问题,标注期望答案或期望要点。
- 每次改 Prompt 后,跑一遍评测集,看指标是否回归。
- 指标可以是精确匹配、要点覆盖率,或用一个更强的模型做“裁判”(LLM-as-a-Judge)。
def evaluate(prompt, dataset) -> float:
hits = 0
for item in dataset:
out = llm(render(prompt, item["input"]))
if judge(out, item["expected"]):
hits += 1
return hits / len(dataset) # 命中率,越高越好
有了这个数字,“改 Prompt”就从玄学变成了工程:每次改动都能量化收益或损失。
评测集怎么长出来
- 从线上日志抽样(注意脱敏)。
- 主动构造边界题:空资料、冲突资料、诱导越狱。
- 每周补 10 条失败样本,比一次性造 500 条空题更有用。
迭代的正确姿势
- 一次只改一个变量,方便归因。
- 保留失败样本,它们是最好的改进线索。
- 别过拟合评测集,定期用新数据刷新。
- 同时盯三项:质量、延迟、成本——只优化质量会悄悄把账单拉爆。
上线后的监控
- 拒答率 / 幻觉投诉率
- 平均 tokens 与 P95 延迟
- 用户重新提问率(高往往代表没答清楚)
把监控告警接进同一套仪表盘,Prompt 才算真正“进了生产”。
小结
Prompt 工程真正的门槛不在措辞,而在闭环:写 → 评测 → 分析失败 → 再写。把这个循环跑起来,你的 AI 系统才会稳定地越来越好。
