Prompt 工程
Written: 2026.06第 11 章跟敲代码:上一讲:RAG Pipeline 主流程深度解析codealong/chapters/ch11_prompt_engineering。 这部分代码是本章跟敲版,用来先跑通核心闭环;完整项目源码仍以本讲后文标注的qa_core/、scripts/等路径为准。
下一讲:FastAPI 与异步 Web 框架
1. 本讲目标
- 理解 Prompt Profile 的概念和设计动机
- 掌握 System Prompt 的编写原则(身份、边界、约束)
- 理解问题类别与 Prompt 模板的映射关系
- 理解为什么让 LLM 自行判断模板会引入不稳定性
2. 前置知识 — Prompt 工程基础
2.1 什么是 Prompt 工程
Prompt 工程是设计和优化发送给 LLM 的指令文本的过程。 一个完整的 Chat Prompt 通常由两部分组成:2.2 为什么 System Prompt 很重要
没有 System Prompt 的 LLM 是一个”通用聊天机器人”,它可能会:- 用搞笑的口吻回答严肃的企业制度问题
- 在没有资料的情况下自信地编造答案
- 忘记自己的专业领域,回答任何问题
3. Prompt Profile 系统设计
3.1 什么是 Prompt Profile
Prompt Profile 是一组预设的 System Prompt + User Prompt 模板,针对不同类型的问题使用不同的回答策略。 当前代码中共有 8 个最终回答档位:faq_answer、knowledge_answer、follow_up、pricing_guard、compliance_guard、troubleshooting_steps、source_bound_summary、default_answer。其中前 3 个按意图兜底选择,后 4 个按问题类别优先选择,default_answer 只用于未知意图或新增意图兜底。
3.2 模板注册
3.3 场景变量注入
注意模板中的{assistant_name}、{business_domain}、{industry} 等变量。这些变量在运行时从场景配置注入:
4. 问题类别的严格模板
4.1 费用类(Pricing)模板
4.2 合规类(Compliance)模板
4.3 问题类别与模板的映射
4.4 选择优先级
5. 为什么不用 LLM 选择模板
这是一个值得讨论的设计决策。 方案 A(不使用):让 LLM 每次自己判断该用哪个模板。- 检索策略和 Prompt 模板必须一致:如果检索时判断为 FAQ_QUERY(FAQ 优先),但 Prompt 时 LLM 判断为 knowledge_answer(综合分析),就会出现”只召回了 FAQ 但要求综合分析”的不匹配。
- 减少一次 LLM 调用:每次生成答案前再让 LLM 选一次模板,增加延迟和成本。
- 确定性 > 灵活性:在高风险场景(费用、合规),我们希望模板选择是 100% 确定的,不能依赖 LLM 的”判断”。LLM 可能在一次调用中正确选择了合规模板,下一次却用了默认模板。
6. System Prompt 编写原则
从本项目的 Prompt 设计中可以总结出几个原则:6.1 身份明确
6.2 行为边界清晰
6.3 对高风险场景做显式约束
6.4 提供失败兜底行为
7. 本讲实践闭环
| 项目 | 内容 |
|---|---|
| 本讲类型 | 项目实现 |
| 实践产物 | prompts/profiles.py、prompts/selector.py 和场景化 Prompt Profile |
| 是否进入最终项目 | 是 |
| 验收方式 | 不同问题类别命中不同模板,高风险问题进入安全约束模板 |
| 后续落点 | 第 10 讲生成阶段使用,第 17/19 讲观察答案质量和 trace |
7.1 本讲从 0 到 1 实现闭环
这一讲要完成的是“Prompt 可治理”,不是写一个越来越长的大提示词。实现顺序如下:- 先把回答模板抽象成
PromptProfile,每个 profile 说明适用场景和选择原因。 - 再把 FAQ、知识问答、追问、高风险费用/合规问题拆成不同 profile。
- 然后实现确定性的选择器:先看问题类别,再看意图,最后才用默认模板。
- 最后把场景配置中的助手名称、业务领域、兜底话术注入模板。
qa_core/prompts/profiles.py。
qa_core/prompts/selector.py::build_answer_prompt_profile()。
assistant_name、business_domain、fallback_contact 等配置注入进去。
来源:真实代码逻辑压缩版,对应 qa_core/prompts/selector.py::_scenario_prompt_context()。
tests/test_retrieval_and_prompt.py。
| 验证项 | 输入条件 | 期望结果 |
|---|---|---|
| FAQ 模板 | intent=FAQ_QUERY | 命中 FAQ 直出模板 |
| 知识问答模板 | intent=KNOWLEDGE_QUERY | 命中知识回答模板 |
| 追问模板 | intent=FOLLOW_UP | 命中追问上下文模板 |
| 费用类保护 | category=pricing | 命中费用安全模板 |
| 合规类保护 | category=compliance | 命中合规安全模板 |
| 场景变量 | 切换业务场景 | assistant/domain 等变量正确注入 |
| 默认兜底 | 新增未知 intent | 使用 DEFAULT_PROMPT_PROFILE |
| 模板脱敏 | 调试信息 | as_dict() 只返回 name/reason,不暴露完整 prompt |
8. 重点掌握
| 优先级 | 内容 | 原因 |
|---|---|---|
| ★★★ 必会 | Prompt Profile 的概念和结构:name + system_template + user_template + reason,8 个最终回答档位 | 本项目的提示词管理方式 |
| ★★★ 必会 | Profile 选择优先级:问题类别(pricing/compliance/troubleshooting/summary)> 意图(FAQ_QUERY/KNOWLEDGE_QUERY/FOLLOW_UP)> 默认模板 | 确定性的选择策略,面试常问 |
| ★★★ 必会 | 高风险问题类别的特殊模板:费用类(不得估算金额)、合规类(不得主观判断合规性) | 高风险场景的 Prompt 安全约束 |
| ★★ 理解 | 确定性选择 > LLM 判断的原因:检索策略和 Prompt 模板必须一致、减少一次 LLM 调用、高风险场景必须 100% 确定 | 重要的设计决策依据 |
| ★★ 理解 | 场景变量注入(_scenario_prompt_context):assistant_name、business_domain 等从 TOML 注入 | 同一套模板跨 8 个场景复用的机制 |
| ★★ 理解 | build_answer_prompt_profile() 的完整选择逻辑 | Profile 选择的代码实现 |
| ★ 了解 | System Prompt 编写原则:身份明确、行为边界清晰、高风险显式约束、提供失败兜底 | Prompt 工程通用技巧 |
| ★ 了解 | CATEGORY_PROMPT_PROFILES 和 PROMPT_PROFILES 两个字典的注册方式 | 了解模板组织方式 |
9. 本讲小结
- Prompt Profile 是预设的 System/User Prompt 模板集合,针对不同问题类别使用不同策略
- 选择优先级:问题类别(费用/合规等)> 意图(FAQ/知识咨询)> 默认模板
- 场景变量注入使同一套模板可以跨 8 个场景复用
- 确定性选择 > LLM 判断:高风险模板(费用、合规)的选择必须是 100% 确定的
- 关键在于让 LLM 知道”能做什么”比”不能做什么”更难,所以约束性指令要明确

