告别“随机盲盒”:深度解析 Prompt Engineering 高级技巧 (CoT 与 Few-Shot)

在人工智能(尤其是大语言模型,LLM)席卷软件开发的今天,我们正处于一个范式转移的十字路口。过去,程序员通过严谨的语法和逻辑与机器对话;现在,我们开始使用自然语言与拥有千亿参数的“超级大脑”交流。

然而,很多开发者在初次接触 ChatGPT 或 Claude 时,往往会经历一个从“震惊”到“沮丧”的过程。震惊于它的无所不知,沮丧于它的“难以控制”——有时它聪明绝顶,有时却又像在“胡言乱语”(业内戏称为 Hallucination/幻觉)。

为什么会出现这种差异? 答案往往隐藏在你的 Prompt(提示词)中。

如果说基础的 Prompt Engineering 是“提出好问题”,那么高级技巧就是**“设计思维框架”**。今天,我们将深入探讨 Prompt Engineering 中最强大、最核心的两个高级技巧:Few-Shot Prompting(少样本提示)Chain of Thought (CoT,思维链)

本文不仅会讲解其背后的逻辑,还将结合实际的业务场景与 Python 代码片段,为你提供一套可直接落地的工程指南。


一、 核心基石:Few-Shot Prompting(少样本提示)

1. 什么是 Few-Shot?

在机器学习的传统语境中,“Shot”指的是训练样本。大模型在出厂时已经经过了海量数据的预训练,这被称为 Zero-Shot(零样本)。理论上,你可以直接对模型下达指令:“请把这段话翻译成法文”,它能完美执行。

但在现实业务中,我们的需求往往非常具体。比如:“提取用户评论中的实体,并按照我们公司自定义的 JSON 格式输出”。此时,Zero-Shot 往往会翻车。

Few-Shot Prompting 的核心思想是:不要只告诉模型“做什么”,而是直接展示几个“怎么做”的例子。

通过在 Prompt 中提供少量的【输入 -> 输出】示范,我们实际上是在微调模型的“上下文注意力”。模型无需更新任何权重,就能迅速捕捉到你的意图、格式和特定领域的规则。这在学术上被称为 In-Context Learning (ICL,上下文学习)

2. Few-Shot 的进阶用法与最佳实践

写几个例子很简单,但如何写出高质量的例子却是一门学问。

  • 格式一致性: 你的例子必须严格遵循相同的结构。推荐使用诸如 Input:Output:<Q><A> 等明确的分隔符。
  • 分布代表性: 例子应该尽可能覆盖各种边缘情况。如果你的分类任务有 3 个类别,不要给出 3 个同类的例子。
  • 顺序敏感性: 研究表明,大模型存在“近因效应”,即 Prompt 末尾的例子对模型的影响最大。把最典型、最符合预期的例子放在最后。

3. 实战代码:结构化数据提取

假设我们需要从非结构化的用户反馈中,提取出具体的设备信息和故障现象,并严格输出为 JSON。

Python 代码示例 (使用 OpenAI API):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import json
from openai import OpenAI

client = OpenAI(api_key="your-api-key")

# 构造 Few-Shot Prompt
system_prompt = """
你是一个专业的客服工单信息提取助手。请根据用户的输入,提取出【设备类型】、【故障现象】和【用户情绪】。
严格按照 JSON 格式输出,不要包含任何多余的解释。

这里有一些例子:
输入:我的 iPhone 14 昨天摔了一下,现在屏幕全是花屏,气死我了!
输出:{"device": "iPhone 14", "issue": "屏幕花屏", "sentiment": "愤怒"}

输入:MacBook Pro 的键盘突然没反应了,连着重启了三次都不行,明天还要开会,急!
输出:{"device": "MacBook Pro", "issue": "键盘无响应", "sentiment": "焦虑"}

输入:AirPods Pro 降噪感觉不如以前好了,有点漏音,不过将就用吧。
输出:{"device": "AirPods Pro", "issue": "降噪减弱/漏音", "sentiment": "平和"}
"""

user_input = "刚买的 Apple Watch Ultra 续航崩了,半天就没电,是不是买到假货了?好烦啊!"

response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": f"输入:{user_input}\n输出:"}
],
temperature=0.0, # 保持温度极低以确保输出稳定
response_format={"type": "json_object"}
)

result = json.loads(response.choices[0].message.content)
print(json.dumps(result, ensure_ascii=False, indent=2))

运行结果:

1
2
3
4
5
{
"device": "Apple Watch Ultra",
"issue": "续航时间短/掉电快",
"sentiment": "烦躁"
}

通过 Few-Shot,我们不仅让模型完成了实体抽取,还顺手解决了“大模型输出 JSON 经常多出废代码”的痛点。


二、 灵魂觉醒:Chain of Thought (CoT,思维链)

如果说 Few-Shot 解决了**“输出格式和风格”的问题,那么 Chain of Thought 解决的就是“复杂推理和逻辑”**的问题。

1. 为什么需要 CoT?

大语言模型的本质是一个“下一个 Token 预测器”。当你问一个复杂的数学题时,如果要求它直接给出答案,它相当于要在一次前向传播中,从海量概率中“蒙”出那个最终的数字。这也就是为什么大模型在处理稍微复杂的算术、逻辑推理或多步规划时,经常会犯下低级错误。

谷歌在 2022 年的一篇经典论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》中提出了解决方案:让模型像人类一样,把思考的中间步骤写出来。

人类在解决复杂问题时,很难心算得出答案,我们需要在草稿纸上一步步推导。CoT 就是给大模型提供了一张“草稿纸”。

  • 增加计算量: 将一次性预测拆解为多次预测。每一个生成的中间 Token,都为最终答案的预测提供了更丰富的上下文。
  • 可解释性: 我们可以通过检查模型的推理步骤,来判断它是在哪里出了错,而不是面对一个莫名其妙的结果束手无策。

2. CoT 的几种实现方式

CoT 并不是单一的语法,而是一系列策略的统称。

(1) Zero-Shot CoT (零样本思维链)

最简单、最著名的魔法咒语。你不需要提供任何例子,只需要在 Prompt 的末尾加上一句简单的提示。

  • 经典咒语: 请一步步思考
  • 进阶咒语: 请深度思考,并给出详细的推导过程。

(2) Few-Shot CoT (少样本思维链)

结合了 Few-Shot 和 CoT 的双重优势。你不仅给出例子,而且给出包含详细推理过程的例子。这对于复杂的逻辑任务(如代码分析、法律合同审查)尤为有效。

(3) Auto-CoT (自动化思维链)

手工编写高质量的 CoT 例子非常耗时。Auto-CoT 的思路是:利用大模型自己生成推理链。你可以先抛给模型一堆问题,让它自己生成步骤和答案,经过一致性检验(多数投票)后,把筛选出来的优质 Q&A 作为后续任务的 Few-Shot 示例。

3. 实战代码:业务逻辑推理

假设我们有一个业务场景:根据用户的购买历史、当前购物车金额以及平台的满减规则,计算最终需要支付的金额,并给出对应的等级积分。

Python 代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from openai import OpenAI

client = OpenAI(api_key="your-api-key")

system_prompt = """
你是一个电商结算引擎。你需要根据给定的规则,计算用户的最终应付金额和获取的积分。
请务必展示你的计算过程(Chain of Thought),最后以 JSON 格式输出最终结果。

规则:
1. 满 200 减 30,满 400 减 80。
2. 积分 = (最终支付金额 / 10) 向下取整。
3. 如果是 VIP 用户,额外赠送 50 积分。

【示例】
输入:购物车金额 250 元,普通用户。
思考过程:
1. 购物车金额为 250 元。
2. 判断满减:250 >= 200,触发"满 200 减 30"。
3. 最终应付金额 = 250 - 30 = 220 元。
4. 计算积分:220 / 10 = 22 分。非 VIP,不赠送。
5. 输出结果。
输出:{"amount_to_pay": 220, "points": 22}
"""

user_input = "购物车金额 450 元,VIP 用户。"

response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": f"输入:{user_input}"}
],
temperature=0.0
)

print(response.choices[0].message.content)

运行结果:

1
2
3
4
5
6
7
8
9
思考过程:
1. 购物车金额为 450 元。
2. 判断满减:450 >= 400,触发"满 400 减 80"。
3. 最终应付金额 = 450 - 80 = 370 元。
4. 计算积分:370 / 10 = 37 分。
5. 该用户是 VIP 用户,额外赠送 50 积分。总积分 = 37 + 50 = 87 分。
6. 输出结果。
输出:
{"amount_to_pay": 370, "points": 87}

通过强制模型输出思考过程,复杂的逻辑错误被极大地降低了。你甚至可以在代码中通过正则表达式提取出“思考过程”记录到日志中,方便后续的审计和 Debug。


三、 高阶组合与衍生变体:将技巧推向极致

当掌握了 Few-Shot 和 CoT 后,我们还可以将它们与现代的一些前沿技术结合,以应对更极端的业务场景。

1. Self-Consistency(自洽性):解决推理的不确定性

即便使用了 CoT,大模型偶尔还是会得出荒谬的结论。Self-Consistency 是一种解码策略。

  • 原理: 让模型针对同一个问题,使用 CoT 生成多个(比如 5 个)不同的推理路径和答案。然后,采用“多数投票”的机制,选择出现次数最多的答案作为最终答案。
  • 适用场景: 数学计算、逻辑谜题、多选项判断。它牺牲了速度(并发调用多次),但极大地提高了解决难题的准确率。

2. Tree of Thoughts (ToT,思维树)

如果说 CoT 是一条道走到黑的“单行道”,那么 ToT 就是允许探索和回溯的“迷宫寻路”。

  • 原理: 在解决问题的每一步,模型都会生成多个可能的“下一步计划”。然后由一个评估机制(可以是大模型自己扮演评估者)对这些计划打分,放弃死胡同,只沿着得分最高的分支继续往下走。
  • 适用场景: 复杂的游戏策略(如 24 点游戏、填字游戏)、长期项目规划、复杂的架构设计。

3. Least-to-Most Prompting(从少到多提示)

  • 原理: 面对非常复杂的问题时,大模型往往无从下手。Least-to-Most 的策略是:首先将复杂问题分解为一系列简单的子问题;然后依次解决这些子问题,并将前一个子问题的答案作为下一个子问题的上下文。
  • 适用场景: 复杂的数据透视、多重条件的信息检索。

四、 生产环境下的避坑指南

虽然这些技巧非常强大,但在实际的生产环境(如构建智能客服、自动化数据流处理)中,仍需注意以下几点:

1. Token 成本与延迟的权衡

Few-Shot 需要在每次请求中附带大量的示例文本,CoT 需要模型生成长篇大论的思考过程。这两者都会显著增加 Token 的消耗(直接影响 API 费用)和首字响应时间(TTFT)

  • 建议: 不要盲目堆砌例子。3 个高质量的 Few-Shot 通常就能达到饱和收益。对于简单的任务(如情感分析、简单翻译),坚决不要使用 CoT,直接 Zero-Shot 即可。

2. 输入长度限制

如果你的业务需求极其复杂,包含几十种分类或规则,Few-Shot 的例子可能会超出模型的上下文窗口限制。

  • 建议: 引入向量数据库,使用 Dynamic Few-Shot(动态少样本提示)。即:根据用户的当前输入,在向量数据库中实时检索出最相似的 3 个案例,动态拼接到 Prompt 中。这既保证了相关性,又控制了 Token 长度。

3. 严格约束输出格式

在生产环境中,大模型的输出往往要交给下游代码(如 Python 脚本)继续处理。如果模型在 CoT 的思考过程中自作主张地输出了一段废话,会导致 JSON 解析失败。

  • 建议: 使用最新的结构化输出功能(如 OpenAI 的 response_format={"type": "json_object"}),或者在 Prompt 中明确规定:请将思考过程放在 <thought> 标签中,将最终的 JSON 结果放在 <result> 标签中。。然后在代码层面通过 XML Parser 或正则提取。

五、 总结

在 AI 时代,Prompt Engineering 绝不是一门“玄学”,而是一门结合了语言学、逻辑学和软件工程的严谨科学

  • Few-Shot Prompting 是教不会听话的学生的最佳方式。它通过构建明确的【示范】,消除了模型对指令理解的歧义,极大地提升了输出格式的稳定性。
  • Chain of Thought (CoT) 则赋予了大模型处理复杂问题的能力。它通过显式地要求模型进行【中间推理】,降低了逻辑错误的发生率,也让 AI 的决策变得更加透明和可追溯。

“编写 Prompt 本质上是在编写函数的说明书。” 你的输入定义决定了输出的质量。

作为开发者,我们需要摒弃“调戏 AI”的随意心态,将 Prompt 视为系统架构的一部分,进行版本控制、持续测试和迭代优化。掌握 CoT 和 Few-Shot,不仅能让你在日常工作中事半功倍,更是构建未来基于 Agent(智能体)的复杂 AI 系统的必经之路。