想要 JSON 却得到废话?Prompt 工程的三大核心技巧
你希望得到 JSON,模型却给了一段解释文字;你要求表格化输出,它偏要自由发挥;你设计好了工具调用格式,它却说”我会调用 search 工具”——然后输出纯文本。
这不是模型能力的问题,是 Prompt 设计的问题。
做 Agent、自动化流程、知识库问答时,最头疼的往往不是模型”不够聪明”,而是输出格式飘忽不定、行为不可控。下游要解析 JSON、要触发工具、要入库——模型不按格式来,整个链路就断了。
本篇讲三个可落地的技巧:明确角色、思维链进阶、结构化输出。掌握它们,你就能让模型稳定产出可解析的结果。
💡 Prompt 工程是什么,不是什么?
在深入技巧之前,我们需要先澄清一个关键问题:什么是 Prompt 工程?
常见的误解
很多人以为 Prompt 工程就是:
- 多写一点 — 把问题描述得更详细
- 描述清楚一点 — 用更准确的语言表达需求
- 提示模型输出你想要的内容 — 告诉模型”请输出 JSON”
这些做法有一定效果,但不是真正的 Prompt 工程。
Prompt 工程的真正内涵
真正的 Prompt 工程是一个系统化的工程方法,包含以下维度:
| 类别 | 说明 | 对应本篇技巧 |
|---|---|---|
| 角色定位 | 明确模型应该以谁的身份工作 | 技巧一:明确角色(Persona Defining) |
| 任务描述 | 清晰、结构化地说明任务是什么,不是什么 | 贯穿所有技巧 |
| 输入格式 | 明确用户会提供什么格式的数据 | 技巧三:结构化输出保障(分隔符) |
| 输出格式 | 强制模型使用特定结构输出(JSON、表格等) | 技巧三:结构化输出保障(Schema) |
| 推理约束(Chain-of-Thought) | 控制思考过程,为模型提供思路或限制思路 | 技巧二:思维链进阶(ReAct) |
| 抗偏差与抗幻觉设计 | 明确禁止模型编造、要求引用来源、允许拒答 | 技巧一:明确角色(限制条件) |
| 错误恢复机制 | 当输入异常时如何自我修正 | 技巧二:思维链进阶(Self-Correction) |
💡 核心理解:Prompt 工程不是技巧,是规范化 + 工程化。
- 规范化:用统一的标准和模板设计 Prompt
- 工程化:考虑边界情况、错误处理、可维护性
这就像写代码一样:
- ❌ 不是:想到什么写什么,能跑就行
- ✅ 而是:遵循规范、考虑异常、可测试、可维护
🎯 三大核心技巧概览
基于 Prompt 工程的内涵,本篇将介绍 三大核心技巧,帮助你获得稳定、可解析的结构化输出:
明确角色(Persona Defining) — 让模型”入戏”,聚焦专业领域
- 对应:角色定位、抗偏差设计
思维链进阶(Advanced CoT / ReAct) — 外化思考过程,实现可控决策
- 对应:推理约束、错误恢复机制
结构化输出保障(Schema + 分隔符) — 确保机器可读、程序可解析
- 对应:输入格式、输出格式
👑 技巧一:明确角色(Persona Defining)
定义一个清晰、专业的角色,是高质量输出的第一步。
为什么定义角色很重要?
聚焦领域:让模型扮演”资深测试架构师”,它会使用更专业的术语和逻辑。
约束语气:确保输出专业、简洁、不冗长。
减少幻觉:专业角色能减少随意编造信息的可能。
角色定义要点
| 要点 | 描述 | 示例 |
|---|---|---|
| 身份 | 具体且权威 | “你是一位经验丰富的 Python 后端工程师。” |
| 目标 | 唯一任务目标,消除歧义 | “你的目标是生成符合 PEP 8 的代码。” |
| 限制 | 明确禁止或必须遵守的行为 | “禁止在代码块之外添加任何解释性文字。” |
完整示例:
System Prompt: |
🔧 实战提示:
- 将角色定义放在 System Prompt 中,以赋予最高权重和持续性
- 身份要具体:避免”你是一个助手”这样的模糊表达,改为”你是一位测试架构师”
- 目标要唯一:一个角色只负责一个核心任务,避免职责混乱
- 限制要明确:用”禁止”、”必须”等明确词汇,避免模糊表达
🔗 技巧二:思维链进阶(Advanced CoT / ReAct)
在复杂任务中,单纯的 Prompt 可能不够。
ReAct(Reasoning + Acting) 能让 LLM 在行动前先思考,再执行工具调用,实现闭环决策。
ReAct 步骤
| 步骤 | 内容 | 作用 |
|---|---|---|
| Thought | 分析任务,决定下一步 | 激活内部逻辑,将复杂任务拆解 |
| Action | 决定调用工具或执行函数 | 明确执行路径,如 Search(Query) |
| Observation | 接收工具结果 | 为下一次 Thought 提供输入,形成反馈闭环 |
Prompt 模板示例
你需要按照以下格式输出: |
实际应用示例:
System Prompt: |
CoT 与自我修正(Self-Correction)
当 Observation 阶段出现错误,可在下一次 Thought 中要求模型识别并修正错误:
|
🔹 这让复杂任务更可控,避免错误累积。
自我一致性检查(Self-Consistency)
对于需要高准确性的任务(如代码生成、数学计算),可以要求模型生成多个答案,然后选择最一致的:
System Prompt: |
💡 适用场景:适合需要高准确性的任务,但会增加 Token 消耗,需要权衡成本。
🧱 技巧三:确保结构化输出(Schema + 分隔符)
这是最关键的一环,尤其当下游程序需要 JSON / YAML / XML 时。
核心方法:使用 Schema 约束
定义:Schema 描述输出数据结构(JSON Schema、Pydantic 等)
作用:不仅告诉模型”输出 JSON”,还规定字段名、类型、必选项
示例
| 步骤 | 方法 | Prompt 片段 |
|---|---|---|
| 1. 格式声明 | 明确仅输出 JSON | “你的输出必须且只能是 JSON 格式,不要添加任何解释性文字。” |
| 2. 注入 Schema | 将 JSON Schema 文本加入 Prompt | {"type":"object","properties":{"user_id":{"type":"integer"},"task_list":{"type":"array","items":{"name":"string","status":"string"}}}} |
| 3. 使用工具 | 高级:调用 function_call / tool_call |
模型直接输出符合 Schema 的函数对象 |
完整示例:
System Prompt: |
💡 关键点:
- 明确格式要求:在 System Prompt 中强调”仅输出 JSON”
- 提供完整 Schema:不仅告诉模型”输出 JSON”,还要规定字段名、类型、必选项
- 禁止解释文字:避免模型在 JSON 前后添加说明
使用分隔符
分隔符帮助模型专注核心任务,区分指令、上下文和用户输入:
|
🏗️ 工程化实践:从技巧到系统
掌握了三大核心技巧后,我们需要将 Prompt 设计工程化,实现可复用、可维护、可测试。
核心检查清单:角色是否明确?输出格式是否用 Schema/分隔符约束?是否有 Few-Shot 示例?边界与异常是否有说明?
模板工程(Template Engineering)
将 Prompt 设计成可复用、可维护的模板,就像代码中的函数一样。
为什么需要模板?
- 一致性:确保相同任务使用相同的 Prompt 结构
- 可维护性:修改模板即可影响所有使用该模板的地方
- 可测试性:可以针对模板进行测试和优化
模板设计示例:
# Prompt 模板 |
工程化结构(Prompt as Code)
什么是 Prompt as Code?
就像写代码一样管理 Prompt:模块化、版本控制、可测试、可复用。
💡 比喻理解:
- 传统方式:每次都在聊天框里写 Prompt,像写临时脚本
- Prompt as Code:把 Prompt 写成代码文件,像写正式项目
为什么要这样做?
- 可复用:一次写好,多处使用
- 可维护:修改一处,全局生效
- 可测试:验证 Prompt 效果,确保质量
- 可协作:团队共享,统一标准
1. 模块化设计:像搭积木一样组合 Prompt
问题:如果每个 Prompt 都写完整的角色、约束、格式,会重复且难维护。
解决:把 Prompt 拆成小模块,按需组合。
示例:
# 第一步:创建可复用的组件(像函数一样) |
好处:
- ✅ 修改角色定义时,只需改
persona.py,所有使用该角色的 Prompt 都会更新 - ✅ 可以轻松替换组件:把
PERSONA_TEST_ARCHITECT换成PERSONA_DEVELOPER - ✅ 代码清晰,易于理解
2. 版本控制:记录 Prompt 的演进历史
问题:Prompt 改来改去,不知道哪个版本效果好。
解决:像代码一样,用版本号管理 Prompt。
示例:
# prompts/v1/test_case_generator.py |
好处:
- ✅ 可以对比不同版本的效果
- ✅ 如果新版本有问题,可以快速回退到旧版本
- ✅ 记录 Prompt 的改进历程
3. 测试:确保 Prompt 质量
问题:Prompt 改完后,不知道效果如何。
解决:像测试代码一样,测试 Prompt 的输出。
示例:
# tests/test_prompts.py |
好处:
- ✅ 修改 Prompt 后,运行测试就知道是否破坏了功能
- ✅ 可以对比不同版本的效果(A/B 测试)
- ✅ 确保 Prompt 质量稳定
💡 最佳实践:
- 使用配置文件:将 Prompt 模板存储在 YAML/JSON 中,便于非技术人员修改
- A/B 测试:对比不同版本的 Prompt 效果
- 监控与日志:记录 Prompt 的使用情况和效果,持续优化
🎯 完整实战案例:三大技巧综合应用
让我们通过一个完整的案例,看看如何将三大技巧结合起来,解决一个实际问题。
场景:自动生成测试用例
需求:根据功能描述,自动生成结构化的测试用例 JSON。
挑战:
- 输出格式必须严格符合 JSON Schema
- 需要覆盖正常流程和异常流程
- 测试步骤要清晰、可执行
- 需要处理边界情况
解决方案:结合三大技巧
第一步:明确角色(Persona Defining)
System Prompt: |
第二步:结构化输出(Schema + 分隔符)
输出格式:必须且只能是 JSON 格式,不要添加任何解释性文字。 |
第三步:使用分隔符明确输入
User Prompt: |
第四步:思维链(ReAct)处理复杂场景
如果功能描述复杂,可以要求模型先分析,再生成:
System Prompt(增强版): |
完整 Prompt 示例
System Prompt: |
预期输出
{ |
关键成功因素
- 角色明确:测试架构师的身份让模型使用专业术语,输出更规范
- 格式严格:JSON Schema 确保输出可解析
- 输入清晰:分隔符让模型明确知道哪里是功能描述
- 约束到位:禁止模糊表达、禁止编造,确保输出质量
💡 实战提示:
- 如果输出不符合 Schema,检查是否在 System Prompt 中强调了”仅输出 JSON”
- 如果测试用例覆盖不全,在 User Prompt 中明确要求”必须覆盖 XX 场景”
- 如果步骤不够清晰,在角色定义中强调”测试步骤要清晰、可执行”
🔍 总结:Prompt Engineering 的设计哲学
| 目标 | 原则 | 技巧 |
|---|---|---|
| 高质量输出 | 限制自由度,聚焦专业 | 明确角色(Persona) |
| 复杂任务分解 | 外化思维过程,便于检查与修正 | ReAct 范式 |
| 程序化对接 | 确保机器可读、可验证 | Schema + 分隔符 |
三大技巧结合使用,你的 Prompt 从模糊提问升级为精确指令。
⚠️ 常见错误与修正
在实际使用中,经常会遇到以下问题。了解这些错误及其修正方法,可以帮你快速定位和解决问题:
| 错误 | 原因 | 修复方式 |
|---|---|---|
| 输出太随意 | 没有输出格式约束 | 使用 JSON Schema 或明确格式要求 |
| 幻觉严重 | 没有限制与拒绝条件 | 加入禁止推测、要求引用来源、允许拒答 |
| 内容缺失 | 输入不规范 | 声明输入格式,使用分隔符区分输入区域 |
| 格式混乱 | Prompt 太自由 | 使用固定模板,明确每个部分的作用 |
| 多轮对话偏移 | 没有保持上下文 | 用 System Prompt 设置全局约束,在每轮对话中重申关键要求 |
💡 关键理解:大多数 Prompt 问题都可以通过明确约束和结构化设计来解决。
🔧 进阶优化技巧
掌握了核心技巧和工程化实践后,我们还需要掌握一些进阶优化技巧,让 Prompt 更高效、更稳定。
1. 调试技巧:如何定位和修复 Prompt 问题
当 Prompt 效果不理想时,如何快速定位问题?
方法一:逐步简化法
原理:从最简单的 Prompt 开始,逐步增加复杂度,找出问题所在。
步骤:
1. 最简版本:只保留核心任务 |
好处:能快速定位是哪个部分导致的问题。
方法二:对比测试法
原理:同时测试多个版本的 Prompt,对比效果。
示例:
# 测试不同版本 |
💡 实战提示:
- 先用逐步简化法定位问题:找出是哪个部分导致的问题
- 再用对比测试法优化效果:对比不同版本,选择最佳方案
- 遇到具体错误时:参考常见错误与修正部分,快速找到修复方法
2. Token 成本优化:在保证效果的同时减少消耗
Token 消耗直接影响成本,如何在保证效果的同时减少 Token?
策略一:精简 Prompt 内容
原则:保留必要信息,删除冗余描述。
❌ 冗余版本(约 200 Token): |
优化技巧:
- 删除重复描述(如”经验丰富”、”资深”等)
- 用列表代替长段落
- 合并相似的要求
策略二:使用 Few-Shot 而非 Many-Shot
原则:Few-Shot(1-3 个示例)通常足够,Many-Shot(5+ 个示例)成本高但效果提升有限。
# Few-Shot(推荐) |
策略三:压缩历史对话
方法:将历史对话压缩为摘要,而不是完整保留。
# 完整保留(消耗大量 Token) |
策略四:使用分隔符而非长描述
方法:用分隔符标记输入区域,而不是用长段落描述。
❌ 长描述版本: |
💡 成本对比:
- 精简 Prompt:可节省 30-50% Token
- 使用 Few-Shot:可节省 40-60% Token(相比 Many-Shot)
- 压缩历史对话:可节省 70-90% Token(长对话场景)
3. 不同模型的 Prompt 适配技巧
不同模型对 Prompt 的响应有差异,如何针对不同模型调整 Prompt?
GPT-4 / GPT-4 Turbo
特点:
- 对 System Prompt 响应好
- 结构化输出能力强
- 对长 Prompt 理解好
适配技巧:
- ✅ 可以使用详细的 System Prompt
- ✅ 可以使用复杂的 JSON Schema
- ✅ 可以使用长 Few-Shot 示例
示例:
System Prompt(详细版,适合 GPT-4): |
Claude 3 / Claude 3.5
特点:
- 对 System Prompt 响应好
- 对格式要求理解准确
- 对长上下文处理能力强
适配技巧:
- ✅ 可以使用详细的 System Prompt
- ✅ 可以使用 XML 标签(Claude 推荐)
- ✅ 可以使用长 Few-Shot 示例
示例:
System Prompt(适合 Claude): |
开源模型(Llama、Mistral 等)
特点:
- System Prompt 支持可能较弱
- 对复杂格式理解有限
- 需要更明确的指令
适配技巧:
- ⚠️ System Prompt 要简洁
- ⚠️ 格式要求要明确且简单
- ⚠️ 使用 Few-Shot 而非 Zero-Shot
- ⚠️ 避免过于复杂的 JSON Schema
示例:
User Prompt(适合开源模型): |
通用适配原则
| 模型类型 | System Prompt | 格式要求 | Few-Shot | 建议 |
|---|---|---|---|---|
| GPT-4 | 详细 | 复杂 Schema | 3-5 个 | 充分利用能力 |
| Claude | 详细 | XML 标签 | 3-5 个 | 充分利用能力 |
| 开源模型 | 简洁 | 简单格式 | 1-3 个 | 降低复杂度 |
💡 实战提示:
- 先设计通用 Prompt:适用于大多数模型
- 再针对特定模型优化:根据实际使用的模型调整
- 使用 A/B 测试:对比不同 Prompt 在不同模型上的效果
注意:详细的模型对比和选型建议将在第 5 篇《评估与选型》中深入讲解。
📚 延伸阅读(含可直接访问链接)
以下资源按主题分类,每个资源都附有简要说明,帮助你选择合适的学习材料。
🎭 Persona Defining(角色定义)
System Prompt Best Practices(System Prompt 最佳实践):OpenAI 关于 System Prompt 的最佳实践指南。强烈推荐,适合所有开发者。
Prompt Engineering for Claude(Claude Prompt 指南):Anthropic 关于 System Prompt 的详细指南。适合使用 Claude 的开发者。
Prompt Engineering Guide(提示工程综合指南):社区维护的 Prompt 工程综合指南,包含角色定义、Few-Shot 等多种技巧。适合想系统学习的读者。
🔗 ReAct & Chain-of-Thought(思维链与推理行动)
ReAct: Synergizing Reasoning and Acting in Language Models(ReAct 原始论文):ReAct 范式的开创性论文,展示了如何结合推理和行动。必读论文,适合所有读者。
Chain-of-Thought Prompting Elicits Reasoning in Large Language Models(CoT 原始论文):CoT 的开创性论文,展示了如何通过思维链提升模型推理能力。必读论文,适合所有读者。
Self-Correction Mechanisms in LLMs(自我修正机制):研究 LLM 如何识别和修正错误的论文。适合想实现自我修正功能的开发者。
Tree of Thoughts: Deliberate Problem Solving with Large Language Models(思维树):CoT 的进阶方法,通过树状结构探索多种推理路径。适合想处理复杂推理任务的读者。
🧱 Schema & Structured Output(结构化输出)
Pydantic 官方文档:Python 中最流行的数据验证库,常用于定义 LLM 输出的 Schema。强烈推荐,适合 Python 开发者。
OpenAI Function Call 文档:OpenAI 官方的 Function Calling 指南,展示了如何使用 Schema 约束模型输出。必读,适合使用 OpenAI API 的开发者。
Anthropic Tool Use(Claude 工具使用):Anthropic 关于工具调用和结构化输出的指南。适合使用 Claude 的开发者。
JSON Schema 规范:JSON Schema 的官方规范,用于定义数据结构。适合需要深入理解 Schema 的开发者。
📖 Prompt Engineering 综合指南
OpenAI Prompt Engineering Guide(OpenAI 官方指南):OpenAI 官方的 Prompt 工程指南,涵盖基础技巧和最佳实践。强烈推荐新手阅读,内容全面且实用。
Prompt Engineering Guide(社区指南):社区维护的 Prompt 工程综合指南,包含大量示例和技巧。适合想系统学习的读者,内容更新及时。
Anthropic Prompt Engineering(Claude 指南):Anthropic 官方的 Prompt 工程指南,特别针对 Claude 模型优化。适合使用 Claude 的开发者。
🛠️ 实战工具与框架
LangChain Prompt Templates(LangChain Prompt 模板):LangChain 的 Prompt 模板系统,方便构建复杂 Prompt。适合使用 LangChain 的开发者。
LangChain Output Parsers(LangChain 输出解析器):LangChain 的输出解析器,帮助将模型输出转换为结构化数据。适合使用 LangChain 的开发者。
PromptLayer(Prompt 管理工具):Prompt 版本管理和分析工具,帮助优化 Prompt 效果。适合需要管理大量 Prompt 的团队。
OpenAI Evals(评估框架):OpenAI 开源的 Prompt 评估框架,帮助测试和优化 Prompt。适合需要系统评估 Prompt 的开发者。
🇨🇳 中文资源
Prompt Engineering 中文指南:Prompt Engineering Guide 的中文版本,内容全面。适合中文读者。
LLM 应用开发实践(中文博客):Lilian Weng 的 Prompt Engineering 博客文章,有中文翻译版本。适合中文读者,内容深入。
🔔 系列说明
本文是《🧠 LLM/Agent 从入门到精通:告别浅尝辄止》系列第 3 篇。上一篇:理解 LLM 的”语言”:Prompt、上下文与 In-Context Learning。下一篇:RAG 机制:解决大模型幻觉的核心技术 —— 如何让 LLM 访问最新信息?如何理解私有文档?检索 → 分块 → 重排 → 融合的完整流程。













