告别“盲盒”:全面解锁 LLM 的高阶 Prompt 工程指南——CoT 与 Few-Shot 的深度解析与实战

在过去的两年里,大语言模型(LLM)如 ChatGPT、Claude、GLM等以前所未有的速度重塑了软件开发的范式。然而,许多开发者在初次接触 LLM 时,往往将其视作一个“黑盒”或者“高级搜索引擎”——只是简单地输入一段话,然后期望模型返回完美的结果。

当输出不尽如人意时,人们常常抱怨“模型太笨”。但事实上,模型并不笨,它只是没有收到足够清晰的“指令上下文”。 决定 LLM 输出质量的终极杠杆,往往掌握在写 Prompt 的人手中。这就是 Prompt Engineering(提示词工程) 的核心价值所在。

如果说基础的 Prompt 技巧(如设定角色、明确步骤、规定格式)是“外家功夫”,那么本文将要深入探讨的 Few-Shot(少样本提示)Chain of Thought(思维链,简称 CoT) 则是名副其实的“内功心法”。掌握它们,你将能从根本上改变 LLM 处理复杂逻辑、专业领域任务时的表现。

本文将从底层原理出发,结合真实的业务场景与代码实战,带你全面吃透这两种高级 Prompt 技术。


一、 基石:从 Zero-Shot 到 In-Context Learning

在进入高阶技巧之前,我们需要先理解 LLM 的一种神奇特性:上下文学习

传统的机器学习模型想要适应新任务,必须经过“微调”,即使用成百上千条数据重新训练模型的权重。但对于参数量巨大的 LLM 而言,它的预训练数据已经足够广泛,使得它具备了极强的泛化能力。

当你向模型输入一段包含任务描述和示例的文本时,模型能够在不更新任何权重的情况下,仅通过理解当前上下文来学习如何完成任务。这就是 ICL。

根据提供给模型的上下文多寡,我们可以将 Prompt 分为三类:

  1. Zero-Shot(零样本):只提供任务描述,不给任何示例。
  2. Few-Shot(少样本):提供少量高质量的示例。
  3. CoT(思维链):不仅提供示例,还提供推导过程的示例。

接下来,我们将重点剖析后两者。


二、 Few-Shot(少样本提示):给 AI 的“岗前培训”

1. 为什么需要 Few-Shot?

当我们在 Zero-Shot 中要求模型完成任务时,模型往往会按照它默认的“舒适区”来回答。例如,如果你要求模型提取一段文本中的实体,它可能会把实体以散文的形式列出来,而不是以 JSON 数组的形式返回。

Few-Shot 的本质,就是通过提供 K 个(通常是 1 到 5 个)高质量的【输入-输出】对,为模型建立一个“模板”和“基调”。

它解决了以下几个核心痛点:

  • 格式对齐:强制模型按照特定的 JSON、XML 或 Markdown 格式输出。
  • 语气控制:让模型模仿特定的文风(如鲁迅的文风、专业的医生口吻)。
  • 边界界定:告诉模型在遇到模糊输入时,应该如何取舍(例如遇到矛盾信息时该标记为 Error 还是忽略)。

2. Few-Shot 的工程实践与代码示例

假设我们正在开发一个情感分析模块,我们不仅需要模型输出“正向”或“负向”,还需要它以特定的 JSON 结构输出,并且要处理一些非典型的边界情况。

下面是一个使用 Python 和 OpenAI API 编写的标准 Few-Shot 请求示例:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import openai
import json

# 准备 Few-Shot 示例
# 关键点:示例必须具有代表性,且格式严格统一
few_shot_examples = [
{
"role": "user",
"content": "分析这句评论的情感倾向:'这家餐厅的菜味道还不错,但是服务员态度太差了,等了半个小时都没人理。'"
},
{
"role": "assistant",
"content": """
{
"sentiment": "负向",
"confidence": 0.85,
"reason": "尽管提到菜品味道不错,但后半句强烈表达了对服务态度和等待时间的不满,这是评论的核心痛点。"
}
"""
},
{
"role": "user",
"content": "分析这句评论的情感倾向:'昨天看了新上映的科幻片,特效真的绝了!'"
},
{
"role": "assistant",
"content": """
{
"sentiment": "正向",
"confidence": 0.98,
"reason": "使用了感叹号和极度赞赏的词汇(绝了),表达了对电影特效的高度认可。"
}
"""
}
]

# 构造完整的对话
messages = [
{
"role": "system",
"content": "你是一个专业的商品/影视评论情感分析助手。你只输出 JSON 格式的数据,不要输出任何其他解释性文字。"
},
*few_shot_examples, # 将 Few-Shot 示例注入上下文
{
"role": "user",
"content": "分析这句评论的情感倾向:'新买的手机电池续航崩了,但是客服给换新了,还不赖。'"
}
]

# 调用 LLM API
response = openai.chat.completions.create(
model="gpt-4o", # 或其他模型
messages=messages,
temperature=0.1 # 降低温度以确保格式稳定
)

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

# 预期输出将会完美遵循上面两个示例的 JSON 结构和推理逻辑
parsed_result = json.loads(result_str)
print(f"提取的情感倾向: {parsed_str['sentiment']}")

3. Few-Shot 的高阶使用原则

  • K 值的选择:通常 3 到 5 个示例性价比最高。过多的示例不仅会浪费 Token(增加成本和延迟),还可能导致模型“过拟合”于特定的示例,丧失泛化能力。
  • 示例的多样性:不要提供三个极其相似的示例。如果任务包含简单和复杂的情况,确保示例中两者都有。
  • 顺序的影响:由于 LLM 存在 “Lost in the Middle”(中间迷失) 现象,模型对 Prompt 开头和结尾的内容更加敏感。建议将最重要、最复杂的示例放在开头,最简单的放在结尾。
  • **动态 Few-Shot (Semantic Search):在实际企业级应用中,Hardcoded(硬编码)的示例往往不够用。高级做法是将成百上千个示例存入向量数据库,根据用户的输入进行语义检索,动态地将最相关的前 3 个示例拼接到 Prompt 中。这就是 Advanced RAG 的一种常见形态。

三、 Chain of Thought (CoT,思维链):让 AI 学会“深思熟虑”

如果说 Few-Shot 教会了模型“照猫画虎”,那么 CoT 则赋予了模型“逻辑推理”的能力。

1. LLM 的缺陷与 CoT 的诞生

大语言模型本质上是自回归的“概率预测机”——它们根据前面的 Token 预测下一个最有可能的 Token。这种机制导致 LLM 在面对需要多步推理的任务(如复杂数学题、逻辑谜题、深度代码分析)时,容易出现幻觉或逻辑断层。

如果直接让模型给出最终答案,它往往是在“盲猜”(虽然是基于庞大数据的高概率猜测)。

Google 在 2022 年发表了一篇里程碑式的论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》,首次提出了 CoT。其核心思想极其简单:强制模型在给出最终答案之前,先展示一步步的思考过程。

2. CoT 的分类与实现机制

CoT 可以分为 Zero-shot CoT 和 Few-shot CoT。

(1) Zero-shot CoT:一句话魔法

最简单触发 CoT 的方式是在你的 Prompt 末尾加上一句神奇的咒语:“Let’s think step by step.”(让我们一步步来思考。)

对比示例:

  • 普通 Prompt

    问:游乐场有 15 个孩子。如果 3 个孩子回家拿防晒霜,2 个去买水,剩下的孩子中有 2 个被叫去帮忙拿行李。最后还剩多少孩子在游乐场?
    答:[模型可能直接回答:8 个(错误的直觉)]

  • Zero-shot CoT Prompt

    问:游乐场有 15 个孩子。如果 3 个孩子回家拿防晒霜,2 个去买水,剩下的孩子中有 2 个被叫去帮忙拿行李。最后还剩多少孩子在游乐场?让我们一步步来思考。
    答:
    首先,一开始有 15 个孩子。
    3 个孩子去拿防晒霜,剩下 15 - 3 = 12 个孩子。
    2 个去买水,剩下 12 - 2 = 10 个孩子。
    在剩下的 10 个孩子中,有 2 个去帮忙拿行李,所以剩下 10 - 2 = 8 个孩子。
    最终答案是 8。

为什么“Let’s think step by step”如此有效?因为它改变了模型的预测路径。它要求模型首先生成一段解释 Token,这些解释 Token 实际上为后续计算最终答案提供了中间跳板,降低了单次推理的认知负荷。

(2) Few-shot CoT:言传身教的逻辑

Zero-shot CoT 靠模型自由发挥,但遇到极度专业的领域(如医疗诊断、复杂的财务报表分析),模型可能“一步步”想偏了。这时,我们需要结合 Few-Shot,不仅给出示例的答案,还要给出推导的过程。

Prompt 模板示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
你是一个资深的财务分析师。请根据提供的企业财务状况,分析其是否存在破产风险。

示例 1:
[企业财务数据 A]
思考过程:
1. 观察到资产负债率达到了 90%,远超安全红线 70%。
2. 流动比率仅为 0.5,说明短期偿债能力极弱。
3. 经营活动现金流连续三个季度为负。
结论:该企业存在极高的破产风险。

示例 2:
[企业财务数据 B]
思考过程:
1. 资产负债率稳定在 40% 左右,处于健康水平。
2. 净利润同比增长 15%,营收稳步上升。
结论:该企业财务状况良好,无明显破产风险。

现在,请分析以下数据:
[用户输入的企业财务数据 C]
思考过程:

(注意:在 Prompt 的最后以“思考过程:”结尾,可以强制模型继续补全思考链路,而不是直接抛出结论。)

3. 进阶 CoT 技巧:Self-Consistency 与 ToT

随着技术发展,CoT 也衍生出了更高级的形态:

  • 自洽性
    单一的 CoT 可能会走错分支。Self-Consistency 的做法是:使用较高的 Temperature(如 0.7),让模型针对同一个问题生成 5 条不同的 CoT 路径和答案。然后统计这 5 次推理中出现频率最高的答案作为最终答案。这极大地提高了复杂逻辑题的准确率。
  • 思维树
    CoT 是一条直线走到底,而 ToT 允许模型在推理的每一步进行评估、回溯和分支搜索。例如在解数独或制定商业计划时,模型可以想出多个可能的下一步,评估哪个最好,然后再继续。这种方法通常需要结合 Agent 框架(如 LangGraph)来实现状态机的循环。

四、 王者结合:Few-Shot CoT 的生产级代码架构

在现代 AI 工程中,Few-Shot 和 CoT 往往是结合使用的。通过 Few-shot 提供格式规范思考范式,通过 CoT 保证逻辑的严密性

下面我们来看一个更贴近生产的架构示例:带输出解析器的 CoT 提取系统

假设我们要从非结构化的客服投诉中提取结构化的工单信息,我们需要模型不仅要提取,还要说明为什么这么提取,以便人类审核。

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from pydantic import BaseModel, Field
from typing import Optional
import json

# 1. 定义期望的输出结构
class ServiceTicket(BaseModel):
reasoning: str = Field(description="从文本中推导出分类和优先级的一步步思考过程")
customer_name: str = Field(description="客户姓名")
issue_category: str = Field(description="问题分类:如 '物流', '质量', '态度'")
priority: str = Field(description="优先级:'High', 'Medium', 'Low'")
summary: str = Field(description="50字以内的问题总结")

# 2. 构造 Few-Shot CoT Prompt
# 将 Pydantic 结构转化为 JSON Schema 作为 System Prompt 的一部分
output_schema = ServiceTicket.model_json_schema()

system_prompt = f"""
你是一个高级客服工单分析助手。
请仔细阅读用户的投诉内容,进行推理,并以严格的 JSON 格式输出结果。
输出的 JSON 必须符合以下 Schema:
{json.dumps(output_schema, indent=2, ensure_ascii=False)}
"""

# 这里的 few-shot 示例融合了 CoT 推理
few_shot_examples = [
{
"role": "user",
"content": "我叫张三,昨天买的手机屏幕碎了,你们顺丰快递简直是暴力运输!我马上要出差,必须今天就给我解决!"
},
{
"role": "assistant",
"content": """
{
"reasoning": "1. 客户姓名明确为'张三'。2. 提到'手机屏幕碎了'且'顺丰暴力运输',可以判断这是物流环节导致的产品损坏。3. 客户表达了极强的时间诉求('马上出差', '必须今天解决'),情绪激动,如果不及时处理可能导致严重客诉。因此判定为 High 优先级。",
"customer_name": "张三",
"issue_category": "物流",
"priority": "High",
"summary": "客户因暴力快递导致手机屏幕损坏,因急需出差要求当日解决。"
}
"""
}
]

# 3. 模拟新的用户输入
new_input = "李四留的言:你们客服什么态度啊,问了半天不回消息。不过后来换了个叫王五的客服帮我处理了退款,还挺快。就算了吧,但前面那个客服得批评。"

messages = [
{"role": "system", "content": system_prompt},
*few_shot_examples,
{"role": "user", "content": new_input}
]

# 4. 调用 API (这里以伪代码/通用格式为例)
"""
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
temperature=0.0 # 确保输出格式稳定
)
result_json = json.loads(response.choices[0].message.content)
parsed_obj = ServiceTicket(**result_json)
print(parsed_obj.reasoning) # 你可以检查它是如何推断出优先级为 Low 的
"""

通过这种方式,我们将非结构化文本的解析变成了一个高度可控、有逻辑可追溯的工程系统。这里的 reasoning 字段就是 CoT 的具象化体现。 这在医疗、法律、金融等对准确性要求极高的行业(即“高风险领域”)是必不可少的。


五、 避坑指南与最佳实践

尽管 Few-Shot 和 CoT 功能强大,但在实际生产落地中,依然有许多坑需要避开。以下是几条用血泪总结出的黄金法则:

1. 注意 Token 消耗与延迟

长篇大论的 Few-shot 示例和 CoT 推理会极速消耗 Input Tokens。更可怕的是,LLM 生成 CoT 的过程也是在消耗 Output Tokens,并且生成 500 个 Token 的思考过程必然比直接生成 5 个 Token 的结论要慢。
建议:在实时性要求极高的场景(如用户实时聊天),谨慎使用过长的 CoT。如果不需要对外展示思考过程,可以考虑让模型在后台输出 CoT,最终只提取结果呈现给用户。

2. “思考过程”不要暴露给用户

如果你使用 CoT 让模型进行了复杂的内部推理,请务必在 UI 界面上做好区隔,或者使用 System Prompt 指示模型将推理过程放在特定的标签(如 <scratchpad>...</scratchpad>)中。由于模型在思考时有时会表现出不确定性(如“其实用户可能是A,但也可能是B…”),将这些原始的犹豫过程展示给终端用户会破坏专业感。

3. Negative Prompts (负面示例) 并不总是有效

LLM 的逻辑是基于“下一个 Token 的概率”。如果你在 Few-shot 中提供了一个“错误示例”并告诉它“不要这样做”,模型往往只会记住那个错误的模式,而忽略掉“不要”这个修饰词。
建议:在 Prompt 中永远使用正向引导。不要说“不要输出 XML 格式”,而是明确说“请务必以纯文本格式输出”。

4. 模型能力的不对等

CoT 尤其吃模型的推理能力。在 GPT-4 或 Claude 3.5 Sonnet 等旗舰模型上表现完美的 CoT,如果直接迁移到一些较弱的模型(如早期的 Llama 7B、Mistral 7B 等小参数模型)上,可能会导致模型胡言乱语。对于小模型,需要使用更加简单、粗暴的 Few-shot,并尽量将 CoT 的步骤拆解得极其详细。


六、 总结与展望

在 AI 应用开发(AI Native App / Agent 开发)的浪潮中,架构范式正在悄然发生改变。过去我们是“数据驱动”,而现在我们正走向**“提示词与上下文驱动”**。

  1. Few-Shot 教会了模型如何严格遵循我们的格式、语气和特定领域的边缘规则。它是解决 LLM 输出格式不稳定、定制化程度低的最具性价比的手段。
  2. Chain of Thought 则打破了 LLM 单次预测的性能天花板,赋予了模型深度推理和自我纠错的能力,是构建复杂 Agent 逻辑的基石。

掌握这两者,意味着你已经从一个“只会调 API 的码农”,蜕变成了一个懂得如何与底层神经网络进行“深度通信”的 Prompt 架构师

未来,随着模型原生支持超长上下文(如 Google 的 1M/2M Context 长度),以及 OpenAI 的 o1 等模型在底层原生内置 CoT 推理机制,我们可能会减少在 Prompt 中手动构建复杂 CoT 的工作。但是,如何为模型精准地挑选和组织高质量的上下文信息,将永远是 AI 工程师的核心竞争力。

种一棵树最好的时间是十年前,其次是现在。优化 Prompt 最好的时机是在上线前,其次是在看到这篇文章的现在。赶快打开你的开发环境,为你的 LLM 应用加上 Few-Shot 和 CoT 的魔法吧!