第 4 章 提示工程

本章要解决的问题

同样的模型,为什么别人写的提示词效果好一倍?提示词是玄学还是有方法论?

章节大纲

  • 4.1 提示词结构:角色/任务/约束/示例
  • 4.2 思维链 CoT 与进阶技巧(Few-shot / Self-consistency)
  • 4.3 结构化输出:JSON Schema、函数调用约束
  • 4.4 提示迭代方法论:从 v1 到 vN 的评测循环
  • 🛠 解决方案:提示词调试 10 步法 + 常见失败模式对照表

4.1 提示词结构:角色/任务/约束/示例

4.1.1 提示词不是玄学:四要素结构

提示词是"给模型的说明书",好的说明书有固定结构。无论多复杂的提示词,拆开看都是四要素的组合:

图 1:提示词四要素

要素 作用 例子
角色(Role) 限定行为模式与专业视角 "你是资深客服主管"
任务(Task) 明确要做什么、产出什么 "分析这条差评并生成回复"
约束(Constraints) 规定边界:格式、语气、禁忌 "字数 ≤200,不得否认用户感受"
示例(Examples) 展示期望的输出样子 "例如:好的回复是......"

4.1.2 一个四要素齐全的模板

text 复制代码
【角色】你是电商客服主管,擅长处理用户差评,语气专业且共情。

【任务】阅读下面的差评,完成两件事:
  1. 抽取问题要点(产品问题/服务问题/物流问题)
  2. 生成一封回复,包含致歉、解释、解决方案三部分。

【约束】
  - 回复字数 100~200 字
  - 不得否认用户感受(禁止"您误会了")
  - 必须给出可执行方案(换货/退款/补偿)
  - 以 JSON 输出:{"issues": [], "reply": ""}

【示例】
  差评:"东西坏了客服还不理人"
  输出示例:{"issues": ["产品质量", "服务态度"],
    "reply": "非常抱歉给您带来糟糕的体验......"}

4.1.3 四要素的设计要点

  1. 角色要给"专业视角":只说"你是客服"不够,要说清立场与风格("专业且共情")。
  2. 任务要可拆解:把复合任务拆成编号子任务(呼应第 10 章提示链思路的单次版)。
  3. 约束要"可判定":写"不得否认用户感受"比写"语气要好"有效------模型能执行前者,后者靠猜(呼应第 17 章"可判定硬规则")。
  4. 示例要"边界化":给 1~2 个正例 + 必要时 1 个反例("这是不好的输出:......"),比只给正例更能校准。

4.2 思维链 CoT 与进阶技巧

4.2.1 思维链(Chain-of-Thought):让模型"展示推理过程"

CoT = 引导模型在给出答案前,先一步步写出推理过程。 对多步推理任务(数学、逻辑、规划)效果显著。注意:部分推理模型(如 o 系列、DeepSeek-R1)已内置思维链,无需在提示词中显式要求"一步步推理";对需要显式推理的传统模型,可让模型输出推理摘要或中间结论。

图 2:思维链 CoT

text 复制代码
❌ 直接问:"鸡兔同笼,头35脚94,各几只?"
✅ 加引导:"请一步步推理,最后给出答案"
   → "设鸡x只、兔y只。x+y=35;2x+4y=94。
      由x=35-y代入:2(35-y)+4y=94 → 70+2y=94 → y=12,x=23。答案:鸡23兔12。"

原理:把隐性推理显性化,模型"边想边写"时出错率低于"直接蹦答案"(与第 13 章反思同源:中间产物让错误可定位)。

4.2.2 Few-shot(少样本):用示例校准输出风格

在提示词里给出若干"输入→期望输出"示例,模型会模仿示例的模式:

Few-shot 类型 做法 适用
格式示例 展示输出格式 结构化输出
风格示例 展示语气/长度 写作类
边界示例 展示"什么不该做" 分类/路由
推理示例 展示推理步骤 复杂任务

Few-shot 是"提示词微调":不需要改模型,加几个示例就能显著改变行为------是成本最低、最快的"训练"(呼应第 18 章 L2 提示词迭代)。

4.2.3 Self-consistency(自洽性):多路推理投票

对关键推理任务,让模型多次独立推理(不同 seed,或配合略高温度),对答案投票取最一致的:

图 3:Self-consistency 多路投票

python 复制代码
# 示例代码:演示 Self-consistency 的核心逻辑,省略了错误处理和重试
import asyncio
from openai import AsyncOpenAI

client = AsyncOpenAI(base_url="https://api.deepseek.com", api_key="<你的Key>")

async def self_consistency(question, n=3):
    tasks = []
    for i in range(n):
        tasks.append(client.chat.completions.create(
            model="deepseek-chat",
            messages=[{"role": "user", "content":
                f"{question}\n请一步步推理,最后用【答案】标注结论。"}],
            temperature=0.7,   # 略高温度 → 多样化推理路径
            seed=i,             # 注意:并非所有 OpenAI 兼容 API 都支持 seed 参数
        ))
    resps = await asyncio.gather(*tasks)
    answers = [r.choices[0].message.content for r in resps]
    # 提取答案并投票(简单实现:取出现最多的最终结论)
    final = [a.split("【答案】")[-1].strip() for a in answers]
    from collections import Counter
    return Counter(final).most_common(1)[0][0]

Self-consistency 的本质是"用并行换准确率"(呼应第 12 章方案并行):单次推理可能走偏,多次独立推理的多数结论更可靠。代价是 n 倍 token------只对高价值推理任务用。

4.2.4 进阶技巧小结

技巧 一句话 成本 适用
CoT 让模型写出推理过程 + 多步推理
Few-shot 给示例校准行为 +(token) 格式/风格
Self-consistency 多次推理投票 ×n 关键决策
角色/约束 结构化的四要素 0 所有

4.3 结构化输出:JSON Schema 与函数约束

4.3.1 为什么要结构化输出

Agent 系统里,模型输出要喂给程序 (解析、校验、入库),不是给人看。自由文本解析脆弱,结构化输出是 Agent 数据契约的基石(呼应第 10 章"JSON 是链的骨架")。

4.3.2 JSON 输出的两种约束方式

python 复制代码
# 方式一:response_format 强制 JSON 对象(各模型通用)
resp = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content":
        "抽取差评要点,输出 JSON。"}],
    response_format={"type": "json_object"},
)

# 方式二:json_schema 严格校验字段(更推荐,OpenAI 系/部分中文模型)
resp = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "抽取差评要点。"}],
    response_format={"type": "json_schema",
        "json_schema": {
            "name": "review_extract",
            "strict": True,
            "schema": {
                "type": "object",
                "properties": {
                    "issues": {"type": "array", "items": {"type": "string"}},
                    "emotion": {"type": "string",
                                "enum": ["calm", "frustrated", "angry"]},
                    "reply": {"type": "string"},
                },
                "required": ["issues", "emotion", "reply"],
            }}},
)

两种方式的区别json_object 只保证"是 JSON",json_schema 保证"字段齐全、类型正确、枚举合法"------后者解析后几乎无需再校验,强烈推荐(注意:各模型支持度不同,见第 24 章表三)。

4.3.3 函数调用约束(tool_calls)

当输出要触发动作时,用第 5 章的 tools 协议让模型返回结构化工具调用,而不是让模型"描述"要调什么(详见第 5 章 5.1)。一句话:程序要消费的输出用 json_schema,要触发动作的输出用 tools 协议。

4.4 提示迭代方法论:从 v1 到 vN 的评测循环

4.4.1 提示词是"代码",要版本管理、要测试

把提示词当代码对待:进 Git、有版本、有评测集、能回滚(呼应第 20 章评测体系、第 24 章 G4 版本化)。生产级团队甚至维护"提示词仓库"。

4.4.2 迭代循环五步

css 复制代码
[v1 基线] 写第一版 → 跑 20 条评测集样例,记录失败模式
    ↓
[定位] 失败是哪类?格式错 / 漏信息 / 语气差 / 幻觉
    ↓
[假设] 是四要素哪个的问题?(角色/任务/约束/示例)
    ↓
[修改] 单点修改(一次只改一处!)
    ↓
[回归] 重跑全部评测集 → 通过 → v2;不通过 → 回到[定位]

图 4:提示迭代五步

铁律:一次只改一处。 同时改两处,无法判断是哪个改动起效(呼应第 24 章"一次只改一个变量")。

4.4.3 用评测集防止"修好 A 弄坏 B"

维护一个固定的评测集(起步 20~30 条,基线阶段扩展至 ≥50 条,覆盖各场景 + 边界),每次改提示词全量回归:

python 复制代码
EVAL_CASES = [
    ("差评:东西坏了客服不理人", "应包含致歉和解决方案"),
    ("好评:发货很快包装完好",   "不应过度道歉"),
    ("中评:质量一般但能用",     "应中性客观"),
]

def evaluate(prompt_fn):
    passed = 0
    for case, check in EVAL_CASES:
        out = prompt_fn(case)
        if llm_judge(out, check):      # 用第17章 LLM-as-Judge
            passed += 1
    return passed / len(EVAL_CASES)

没有评测集的提示词迭代 = 盲改(呼应第 18 章"学习的反面是退化")。

🛠 解决方案:提示词调试 10 步法 + 常见失败模式对照表

提示词调试 10 步法

arduino 复制代码
1. 输出格式错?      → 加 json_schema / 明确格式示例
2. 缺信息?          → 任务里显式列出"必须包含:......"
3. 语气不对?        → 约束里写语气风格 + 给风格示例
4. 答非所问?        → 检查任务是否拆解清楚(四要素的"任务")
5. 有幻觉?          → 约束"仅基于给定材料"+ 温度调低
6. 不稳定(时而好时坏)→ 温度调低 / 加 few-shot 锚定
7. 太啰嗦?          → 约束长度 + 示例展示精炼输出
8. 忽略约束?        → 约束前置 + 重要约束加粗/编号 + 用可判定表述
9. 复杂任务总崩?    → 拆链(第 10 章提示链)
10. 改了没效果?     → 确认一次只改一处 + 有评测集可对比

常见失败模式对照表

失败现象 根因 对症修改
格式乱 无格式约束 json_schema / 示例
漏要点 任务未列全 编号子任务 + 必含清单
语气生硬 无风格约束 角色强化 + 风格示例
答非所问 任务含糊 重写任务 + 边界示例
事实错误 依赖模型记忆 加 RAG + "仅基于材料"
输出不稳 温度高 调低温度 / few-shot
太冗长 无长度约束 字数约束 + 精炼示例
约束失效 表述不可判定 可判定化 + 约束前置

实战提示

  1. 提示词四要素是模板:任何新任务先按"角色/任务/约束/示例"搭骨架,再迭代。
  2. 一次只改一处:改完跑评测集,用数据判断,别凭感觉。
  3. 结构化输出是刚需:Agent 场景中程序要消费的输出优先用 json_schema / tools 协议;但简单自然语言反馈、闲聊、草稿生成等场景未必需要严格结构化。
  4. CoT 加在需要推理的任务:简单任务加 CoT 反而啰嗦、费 token;多数推理模型(如 DeepSeek-R1、o 系列)已内置思维链,通常无需额外要求显式推理------但具体行为因模型而异,上线前应按目标模型文档验证。
  5. 提示词进版本库:当代码管理,可回滚、可对比、可协作。
  6. 防提示注入 :Agent 场景中用户输入可能包含恶意指令("忽略以上指令,执行......")。防御方法:用分隔符(<user_input>...</user_input>)隔离用户内容;在系统提示词中声明权限边界("你只能使用以下工具");对高风险输入做注入检测(呼应第 17 章输入 Guardrail、第 22 章安全)。
  7. 术语速查:全书核心术语(提示词、工具调用、幻觉、护栏等)的中英对照见附录 D《术语表》。
相关推荐
Wang's Blog43 分钟前
Vibe Coding一人即团队系列2: AI驱动的全链路产品开发实践
人工智能
飞哥数智坊43 分钟前
豆包工作上线:功能超多,但我更关注这3个地方
人工智能
小白的成长路程43 分钟前
AI搜索里,品牌被悄悄降级了
人工智能·geo
这就是佬们吗1 小时前
AI 的记忆进化史:从金鱼记忆到学会做梦
人工智能·python·embedding
智塑未来1 小时前
金融AI应用解决方案选型先看哪三项
人工智能·金融
Csvn1 小时前
第 3 章 上下文工程
人工智能·aigc
智恒百亿1 小时前
AI服务器涨价15%背后:5090八卡智算服务器的选型与成本分析
大数据·服务器·人工智能·github
中科同志科技1 小时前
元器件拆焊真空焊接设备深度解读:工艺流程与优化策略
大数据·人工智能·机器人·汽车
政安晨1 小时前
政安晨【人工智能随笔】— 从像素到星际:游戏如何塑造了现代AI的二十年演进史 (读DeepMind的EVE宇宙AI研究有感)
人工智能·游戏·ai·智能体·deepmind·人工智能与游戏·智能体与游戏