前言
很多人以为写 Prompt 就是"把问题说清楚",但当你需要在生产环境中稳定地获取 LLM 输出时,你就需要一套系统化的方法。这篇文章不讲玄学,全部来自线上实践。
Prompt 的四个原子组件
任何复杂的 Prompt 都可以拆解为四个基础组件:
┌──────────────────────────────────────────────┐
│ 1. 角色定义(WHO)—— 模型应该扮演什么角色 │
│ 2. 指令描述(WHAT)—— 需要模型做什么 │
│ 3. 上下文(CONTEXT)—— 完成任务所需的背景信息 │
│ 4. 输出格式(FORMAT)—— 输出的结构和样式 │
└──────────────────────────────────────────────┘
1. 角色定义
角色不是让你"扮演一个 AI 助手"这种废话,而是明确的能力边界和行为规范:
❌ 差:"你是一个 AI 助手。"
✅ 好:"你是一个资深的 Python 后端工程师,精通 FastAPI 和 SQLAlchemy。
你习惯写出有类型注解、有单元测试、遵循 PEP 8 的代码。
你的回答应该简洁务实,必要时才给出完整代码。"
好的角色定义能显著提升输出质量——本质上是激活了模型预训练中对应领域的能力分布。
2. 指令描述
指令要遵循单一职责原则:一条指令只做一件事。
❌ 差:"分析这段代码,找出 bug,优化性能,然后重写它,再写测试。"
✅ 好(分步):
Step 1: 分析以下代码中的 bug,列出每行代码的问题
Step 2: 针对每个问题,给出修复方案
Step 3: 修复代码后,为关键函数编写 pytest 测试
3. 上下文
上下文是 prompt 中最容易被低估的部分。好的上下文包含:
## 背景信息
- 项目:电商后台管理系统
- 技术栈:FastAPI + SQLAlchemy + PostgreSQL
- 用户角色:运营人员,非技术人员
- 关键约束:接口响应时间
你是一个翻译助手。将用户输入从英文翻译为中文。
这是一篇技术文档,用词要专业准确。
Transformer architecture
Transformer 架构
{user_input}
模式 3:Few-shot 示例
Few-shot 不是随便举几个例子就行。好的 Few-shot 设计:
提取用户评论中的关键信息。
示例 1:
输入:"这个手机的电池太差了,半天就没电"
输出:{"aspect": "电池", "sentiment": "负面", "detail": "续航时间短"}
示例 2:
输入:"拍照效果惊艳,夜景模式非常清晰"
输出:{"aspect": "拍照", "sentiment": "正面", "detail": "夜景模式清晰"}
示例 3(边界情况):
输入:"还行吧,一般般"
输出:{"aspect": "整体", "sentiment": "中性", "detail": ""}
现在请分析:{user_review}
Few-shot 要点:
- 示例覆盖:正向、负向、边界情况各一个
- 示例的格式必须与预期输出完全一致
- 示例数量:2-5 个效果最好,再多边际效益递减
思维链(Chain-of-Thought)
Zero-shot CoT
最简单有效的方法——加一句话:
❌ "计算 25 * 48 的结果。"
✅ "计算 25 * 48 的结果。请逐步思考。"
就这么简单,在复杂推理任务上准确率提升 10-30%。
Few-shot CoT
给出完整的推理步骤示例:
问:一个长方形的长是 12 米,宽是 8 米,求面积。
答:面积 = 长 × 宽 = 12 × 8 = 96 平方米。所以面积是 96 平方米。
问:一个正方形的边长是 15 厘米,求周长。
答:周长 = 4 × 边长 = 4 × 15 = 60 厘米。所以周长是 60 厘米。
问:一个三角形底边长 10 厘米,高 6 厘米,求面积。
答:
CoT 的最佳实践
- 分步指令:在 prompt 中明确要求"一步一步分析"
- 格式约束:让 CoT 推理过程以结构化方式输出(JSON、列表等)
- 自我校验:让模型在给出最终答案前先自我检查
任务:解决数学问题
第一步:理解问题(用自己的话重述问题)
第二步:拆解步骤(列出需要计算的中间结果)
第三步:逐步计算(每个步骤给出计算过程和结果)
第四步:验证答案(用另一种方法验证结果是否合理)
问题:{question}
生产级的 Prompt 管理系统
写几条 prompt 很简单,但你很快就会面临这些问题:
- 100 条 prompt 散落在代码里,改一个要到处找
- 产品说"这个翻译不对",你分不清是 prompt 问题还是模型问题
- 新 prompt 上线了,效果变好了还是变差了?
Prompt 版本管理
# prompts/translator.py
PROMPTS = {
"v1.0": {
"system": "你是一个翻译助手。",
"template": "将以下内容翻译成{target_lang}:
{text}",
},
"v2.0": {
"system": "你是一个专业的翻译助手,精通技术文档翻译。保持原文的格式和标点,专业术语要准确。",
"template": "# 翻译任务
源语言:{source_lang}
目标语言:{target_lang}
领域:{domain}
原文:
{text}
翻译:",
"context": {"domain": "technology"},
},
}
Prompt A/B 测试
import hashlib
def get_prompt_version(user_id: str) -> str:
# 根据用户 ID 哈希决定使用哪个 prompt 版本
hash_val = hashlib.md5(user_id.encode()).hexdigest()
return "v2.0" if int(hash_val[:8], 16) % 2 == 0 else "v1.0"
# 统计两个版本的效果
metrics = {"v1.0": {"total": 0, "good": 0}, "v2.0": {"total": 0, "good": 0}}
Prompt 监控指标
prompt_metrics = {
"avg_output_length": 0,
"parse_success_rate": 0.98, # 结构化输出解析成功率
"empty_response_rate": 0.01, # 空回复率
"avg_latency_ms": 1200, # 平均延迟
"token_usage": 850, # 平均 token 消耗
}
定期检查这些指标,任何一个指标偏离基线都要追查原因。
常见问题与调试方法
模型不遵循指令怎么办?
按优先级排查:
- 指令是否清晰 → 让另一个人读一遍,看能不能理解
- 角色是否明确 → 角色越具体,遵循度越高
- 指令是否在 prompt 末尾被其他内容淹没 → 把核心指令放到 prompt 开头和结尾(首尾效应)
- 示例是否足够 → 加 1-2 个 Few-shot 示例
- 模型本身能力不足 → 换更强的模型
输出格式不稳定怎么办?
# 在 prompt 中强调格式约束
"你的输出必须是合法的 JSON,不要包含任何多余的说明文字。
不要使用 markdown 代码块包裹 JSON。
直接输出 JSON 对象。"
如果还是不稳定,改用 Function Calling / Tool Use——模型对结构化工具调用的支持远好于自由格式。
总结
好的 Prompt Engineering 不是玄学,而是工程方法:
- 用四个原子组件(角色、指令、上下文、格式)搭建 prompt 骨架
- 选择合适的设计模式(Markdown、XML、Few-shot)
- 复杂推理任务启用 CoT
- 生产环境必须做 prompt 版本管理和 A/B 测试
- 持续监控输出质量指标
把 prompt 当做代码来管理——写测试、做版本控制、逐步迭代。