LLM 应用(01):Prompt 工程——提示词设计、Few-shot、思维链、结构化输出与评估
更新时间:2026-09-02。本文是
data-ai/llm-app/第 01 篇,在LLM 应用索引下。大模型应用的"编程"很大一部分就是写好提示词。本文讲提示词的构成、几种核心技法、如何让模型稳定输出结构化结果,以及——最容易被忽视的——怎么评估提示词好坏。
本文要回答的问题
- 一个有效的提示词由哪些部分组成?上下文窗口怎么分配?
- 零样本、少样本、思维链分别什么时候用?
- 怎么让模型稳定输出可被程序解析的 JSON?
- temperature 等参数怎么影响结果?
- 提示词改没改好,靠什么判断?
一、提示词的构成
一次给模型的输入(context)通常包含:
+---------------------------------------------------+
| 系统指令(system):角色、规则、输出格式、约束 | 稳定部分
+---------------------------------------------------+
| 知识/上下文(retrieved):RAG 检索到的资料 | 每次变化
+---------------------------------------------------+
| 少量示例(few-shot):输入->输出 的示范 | 稳定部分
+---------------------------------------------------+
| 用户问题(user):本次实际查询 | 每次变化
+---------------------------------------------------+
总长度受上下文窗口限制(如 8k/32k/128k token)写好指令的基本原则:
- 明确、具体、可执行。"写得专业点"是坏指令,"用 3 个要点、每点不超过 30 字、面向初级工程师"是好指令。
- 给约束和格式。说清楚输出结构、长度、语气、不要做什么。
- 把重要信息放头尾。长上下文中模型对开头和结尾注意力最强("Lost in the Middle"),关键指令放 system 或最后重申。
- 拆解复杂任务。一步做不好的事,拆成多步或让模型"先列计划再执行"。
二、核心技法
1. 零样本 vs 少样本(Zero-shot / Few-shot)
零样本:直接下指令
"将下列评论分类为 正面/负面/中性:\n{评论}"
少样本:先给几个范例,让模型模仿格式与判断标准
"评论:太好用了 -> 正面
评论:一般般吧 -> 中性
评论:老闪退,垃圾 -> 负面
评论:{新评论} ->"- 任务简单、模型够强 → 零样本即可。
- 有微妙的判断标准、或要求特定输出格式 → 少样本最有效,示例比长篇规则更能传达意图。
- 示例要有代表性、覆盖边界情况,且标签分布均衡,否则模型会被带偏。
2. 思维链(Chain-of-Thought, CoT)
让模型"先推理、再给结论",显著提升数学、逻辑、多步问题的正确率:
直接问:"小明有 3 个苹果,吃了 1 个又买了 2 打(24个),共几个?"
模型可能直接答错。
加 CoT 引导:
"请一步步思考,先列出计算过程,最后在 '答案:' 后给出结果。"
模型:原有3个,吃1个剩2个,买24个,2+24=26 -> 答案:26- 触发方式:写"让我们一步步思考 / 先推理再作答 / 先列步骤"。
- 复杂任务可用 显式分步:先让模型输出分析,再在下一轮基于分析给结论;或要求把推理放进特定字段。
- 代价:输出 token 变多、延迟和成本上升;简单任务不必用。
- 注意:CoT 会让模型"编造推理",高风险场景仍需校验结论。
3. 角色与分隔
system: 你是一名资深数据库运维专家,回答严谨,不确定时明确说明。
只依据<资料>中的内容回答,资料中没有就说"根据现有资料无法确定"。
user: <资料>
{retrieved_docs}
</资料>
问题:{question}- 用清晰的分隔符(XML 标签、三引号、markdown)区分"指令/资料/问题",防止资料里的内容被当成指令(提示注入防护,见 RAG)。
三、结构化输出:让结果可被程序解析
LLM 应用要接进系统,必须拿到稳定的 JSON 而不是自由文本。
1. 手段阶梯
1) 提示词约定格式 + 给出 JSON 示例(few-shot)
2) JSON mode / response_format={"type":"json_object"} —— 保证是合法 JSON
3) 结构化输出 / function calling / tool use
—— 按给定 schema 保证字段、类型、枚举(最可靠,首选)2. 示例(function/tool 风格)
python
tools = [{
"type": "function",
"function": {
"name": "submit_ticket",
"description": "提取工单信息",
"parameters": {
"type": "object",
"properties": {
"priority": {"type": "string", "enum": ["P0","P1","P2"]},
"summary": {"type": "string"},
"category": {"type": "string", "enum": ["网络","存储","应用"]}
},
"required": ["priority", "summary", "category"]
}
}
}]
# 模型会返回符合该 schema 的结构化参数,可直接 json.loads工程兜底:即使有 JSON mode,也要校验 + 容错重试(解析失败时把错误回喂模型让它修正,或用 Pydantic 校验后重试)。永远不要假设模型一定返回合法内容。
四、生成参数
| 参数 | 作用 | 调参建议 |
|---|---|---|
temperature | 随机性,0 确定、越高越发散 | 抽取/分类/代码用 0~0.3;脑暴/文案用 0.7~1.0 |
top_p | 核采样,限制候选词累计概率 | 与 temperature 二选一调,通常不动 |
max_tokens | 输出上限 | 防跑飞、控成本;要留够 CoT 长度 |
stop | 停止序列 | few-shot 批量生成时防止续写 |
seed | 固定随机种子 | 复现/调试用(不保证跨版本完全一致) |
结构化/抽取类任务把 temperature 调到接近 0,追求稳定可复现;创作类才需要高温。
五、提示词评估:别靠"我试了一下感觉不错"
提示词工程最被忽视、也最专业的一环是评估。没有评估集,改提示词就是玄学。
建一个评估集(几十~几百条真实样本):
{ 输入, 期望输出/期望要点, 参考资料 }
|
每次改 prompt / 换模型,批量跑一遍
|
用指标衡量:
- 有标准答案:准确率 / 格式合法率 / JSON 解析成功率
- 开放式:要点命中率、人工打分,或用 LLM-as-judge(让强模型按 rubric 打分)
|
对比基线,确认"改好了"再上线,并把这个集子留着做回归关键指标(LLM 应用特有):
- 格式合规率:结构化输出能否 100% 被解析。
- 任务正确率/要点召回:该抽的字段抽到没、该答的点答到没。
- 拒答合理性:该说"不知道"时有没有乱说(幻觉率)。
- 稳定性:同输入多次运行结果是否一致。
六、常见失败模式与对策
| 失败 | 表现 | 对策 |
|---|---|---|
| 格式漂移 | 时而是 JSON 时而加废话 | 用 function calling/JSON mode + 校验重试 |
| 幻觉 | 编造资料里没有的内容 | 限定"只依据资料"、要求引用来源、无依据则拒答 |
| 忽略指令 | 长上下文里忘了约束 | 关键规则放头尾、重申、减少无关上下文 |
| 示例带偏 | few-shot 分布不均导致偏见 | 示例覆盖各类别与边界、数量均衡 |
| 提示注入 | 资料里藏"忽略上述指令" | 分隔指令与数据、过滤/转义、用系统消息固化规则 |
| 不稳定 | 同一输入结果飘 | temperature 调低、输出格式收紧、加校验 |
小结
Prompt 工程的核心是把模糊需求变成明确、具体、带格式约束和示例的指令:简单任务零样本,微妙判断用少样本,多步推理用思维链,要进系统就用 function calling/JSON mode 拿结构化输出并做校验重试;抽取类任务低温、创作类高温。但最重要的纪律是建评估集、用指标驱动迭代——没有回归集的提示词调优都是碰运气。下一篇讲当前 LLM 应用最主流的架构:RAG 检索增强生成。