前言:之前聊了提示词设计的三大原则和 System/User Prompt 的分工,今天咱们就聊三个真正能显著提升模型推理能力 的高级技巧------Few-shot(少样本学习) 、Chain-of-Thought(思维链) 、Self-Consistency(自一致性)。这三个技巧单独用就有效果,组合起来更是威力翻倍!
先看一张全景图:三个技巧的关系
rust
┌──────────────────────────────────────────────────────────────────┐
│ 高级提示技巧全景图 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ Zero-shot(零样本) │
│ "直接问,不给示例" │
│ → 基础能力 │
│ │
│ ▼ │
│ │
│ Few-shot(少样本) │
│ "给几个示例,让模型照着学" │
│ → 格式对齐、模式学习 │
│ │
│ ▼ │
│ │
│ Chain-of-Thought(思维链) │
│ "让模型一步步想,再给答案" │
│ → 推理能力大幅提升 │
│ │
│ ▼ │
│ │
│ Self-Consistency(自一致性) │
│ "多次推理,少数服从多数" │
│ → 准确率进一步提升 │
│ │
└──────────────────────────────────────────────────────────────────┘
这三个技巧是层层递进的关系:Few-shot 教模型"怎么做",CoT 让模型"想清楚",Self-Consistency 让模型"更可靠"。
一、Few-shot:用示例教模型"怎么做"
1.1 核心思想
Few-shot(少样本提示) 就是在 Prompt 中给模型几个"输入→输出"的示例,让它学会你想要的模式。
类比一下:就像教新员工做事,与其说一堆规则,不如直接给他看几个成功案例。
1.2 Zero-shot vs Few-shot
arduino
❌ Zero-shot(不给示例):
"判断以下评论的情感倾向:
- 这个产品真的太好用了
- 第三次坏了,再也不会买"
→ 模型可能输出格式不统一,或者判断标准不一致
✅ Few-shot(给示例):
"判断用户评论的情感倾向,输出:positive / negative / neutral
示例:
- "物流很快,包装也很好" → positive
- "第三次坏了,再也不会买" → negative
- "今天收到货了" → neutral
现在判断:
- "这个产品真的太好用了" →
- "第三次坏了,再也不会买" →"
1.3 Few-shot 的效果提升
| 任务类型 | Zero-shot 准确率 | Few-shot 准确率 | 提升 |
|---|---|---|---|
| 情感分类 | ~78% | ~92% | +14% |
| 意图识别 | ~72% | ~88% | +16% |
| 格式转换 | ~65% | ~95% | +30% |
| 命名实体识别 | ~70% | ~85% | +15% |
Few-shot 对格式对齐 和模式学习类任务效果最明显。如果你想让模型按特定格式输出(JSON、表格、特定模板),Few-shot 是最简单有效的方式。
1.4 Few-shot 的最佳实践
python
# ============ Few-shot 模板 ============
# 技巧 1:示例数量控制在 2-5 个
# 太少学不会,太多浪费 token 且边际收益递减
# 技巧 2:示例要覆盖多样性
few_shot_examples = {
"情感分类": [
# 正面 - 长评论
{"input": "用了三个月了,续航很给力,拍照也清晰,强烈推荐!", "output": "positive"},
# 正面 - 短评论
{"input": "不错,满意", "output": "positive"},
# 负面 - 具体问题
{"input": "屏幕有亮点,客服说正常现象,但我觉得不应该", "output": "negative"},
# 中性 - 客观描述
{"input": "今天到货了,还没拆封", "output": "neutral"},
],
}
# 技巧 3:用分隔符区分示例和待处理内容
prompt_template = """
{instruction}
<examples>
{examples}
</examples>
<query>
{user_input}
</query>
"""
# 技巧 4:示例的格式要和期望输出完全一致
# 如果你期望 JSON 输出,示例就必须是 JSON
1.5 Few-shot 的局限性
javascript
Few-shot 不是万能的
❌ 解决不了的问题:
• 需要复杂推理的任务(数学、逻辑)
• 模型完全没有见过的领域
• 需要大量知识的任务
✅ 擅长解决的问题:
• 格式对齐(输出 JSON、表格、特定模板)
• 模式学习(分类、提取、转换)
• 风格模仿(语气、用词习惯)
二、Chain-of-Thought:让模型"想清楚再说"
2.1 核心思想
Chain-of-Thought(思维链,简称 CoT) 是 2022 年 Google 提出的提示技术(论文:Chain-of-Thought Prompting Elicits Reasoning in Large Language Models)。
核心思想极其朴素:让模型先把推理过程写出来,再给最终答案。
类比一下:考试做数学题,直接写答案容易出错;先写解题步骤,再写答案,正确率会高很多。
2.2 Zero-shot CoT:最简单的用法
你甚至不需要给示例,只要在 Prompt 末尾加一句话:
arduino
"请一步步思考。"
"Let's think step by step."
"请先分析,再给出结论。"
"请详细说明你的推理过程。"
就这么简单,效果却非常显著:
arduino
❌ 不加 CoT:
"一个水池有两个水管,A 管单独注水 6 小时注满,B 管单独排水 8 小时排完。
如果同时打开两管,多久注满?"
→ 模型可能直接猜:"14小时"(错误)
✅ 加 CoT:
"一个水池有两个水管,A 管单独注水 6 小时注满,B 管单独排水 8 小时排完。
如果同时打开两管,多久注满?请一步步计算。"
→ 模型会:
1. A 管每小时注水:1/6
2. B 管每小时排水:1/8
3. 同时打开,每小时净注水:1/6 - 1/8 = 1/24
4. 注满需要:1 ÷ 1/24 = 24 小时
→ "24小时"(正确)
2.3 Few-shot CoT:更强大的用法
给模型展示"推理过程 + 最终答案"的完整示例:
ini
Q: 小明有 23 个苹果,给了小红 1/3,又买了 6 个,还剩多少个?
A: [思考过程]
原有 23 个苹果。
给小红 1/3:23 × 1/3 ≈ 7.67 个。因为苹果不能分,给 7 个,剩下 16 个。
又买了 6 个:16 + 6 = 22 个。
[最终答案] 22 个。
Q: 一列火车 3 小时行驶 360 公里,前 1.5 小时的速度是后 1.5 小时的 2 倍,
求前后两段的速度分别是多少?
A: [思考过程]
设后 1.5 小时的速度为 x 公里/小时,则前 1.5 小时的速度为 2x。
总路程 = 前段 + 后段
360 = 2x × 1.5 + x × 1.5
360 = 3x + 1.5x
360 = 4.5x
x = 80
所以后段 80 公里/小时,前段 160 公里/小时。
[最终答案] 前 1.5 小时 160 公里/小时,后 1.5 小时 80 公里/小时。
Q: 一件商品先涨价 20%,再打 8 折,最终价格是原价的百分之几?
A:
Few-shot CoT 的示例中,推理过程比最终答案更重要。模型通过学习推理的"模式"(如何拆解问题、如何逐步计算),比直接记住答案更有价值。
2.4 CoT 为什么有效?
arduino
CoT 有效的三个原因
① 分解问题
复杂问题被拆成多个小步骤,每步更简单
→ 每步出错的概率更低
② 中间状态可验证
推理过程中产生的中间结果可以被"检查"
→ 如果某一步错了,后面的步骤可能会自我纠正
③ 更多"思考时间"
生成推理过程需要更多 token
→ 等于给了模型更多"计算空间"来处理问题
2.5 CoT 的代码实现
python
import openai
def cot_prompt(question: str, few_shot_examples: list = None) -> str:
"""
CoT 提示函数
支持零样本 CoT 和少样本 CoT
"""
if few_shot_examples:
# Few-shot CoT:包含推理过程的示例
examples_text = ""
for ex in few_shot_examples:
examples_text += f"Q: {ex['question']}\nA: {ex['reasoning']}\n\n"
prompt = f"{examples_text}Q: {question}\nA:"
else:
# Zero-shot CoT:只加一句引导语
prompt = f"{question}\n\n请一步步思考,先给出推理过程,再给出最终答案。"
response = openai.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "你是一个善于推理的AI助手。回答问题时,请先展示详细的推理过程,最后用【最终答案】给出结论。"},
{"role": "user", "content": prompt}
],
temperature=0.3, # CoT 场景建议低温度
)
return response.choices[0].message.content
# ============ 使用示例 ============
# Zero-shot CoT
result = cot_prompt("一件商品先涨价20%再打8折,最终价格是原价的百分之几?")
# Few-shot CoT
examples = [
{
"question": "小明有15个苹果,给了小红1/3,又买了6个,还剩多少个?",
"reasoning": "原有15个。给小红1/3:15×1/3=5个,剩10个。又买6个:10+6=16个。\n【最终答案】16个"
},
{
"question": "一个水池A管6小时注满,B管8小时排完,同时开多久注满?",
"reasoning": "A管每小时注1/6,B管每小时排1/8。同时开:1/6-1/8=1/24。注满需要1÷1/24=24小时。\n【最终答案】24小时"
}
]
result = cot_prompt("一件商品先涨价20%再打8折,最终价格是原价的百分之几?", examples)
2.6 CoT 的最佳实践
| 技巧 | 说明 | 示例 |
|---|---|---|
| 引导语放在末尾 | 模型更关注最后的指令 | "...\n请一步步思考" |
| Temperature 设低 | 推理任务需要确定性 | T = 0.0 ~ 0.3 |
| 示例要展示完整推理 | 不要只给答案,要给过程 | "思考过程 → 最终答案" |
| 复杂问题拆分子问题 | 让模型分步处理 | "先计算A,再计算B" |
| 用分隔符标记答案 | 方便提取最终答案 | "【最终答案】xxx" |
三、Self-Consistency:多次推理,少数服从多数
3.1 核心思想
Self-Consistency(自一致性) 是 2022 年提出的进阶技术(论文:Self-Consistency Improves Chain of Thought Reasoning in Language Models)。
核心思想:同一个问题,让模型用 CoT 推理多次,然后取"多数答案"作为最终结果。
类比一下:考试做选择题,你算了一遍答案是 A,但不太确定。于是你又算了一遍,答案是 A。再算一遍,还是 A。三次都是 A,你就有信心选 A 了。
3.2 为什么需要 Self-Consistency?
CoT 虽然提升了推理能力,但有个问题:模型的推理路径不是唯一的。
同一个数学题,模型可能通过不同的思路来解:
- 路径 1:先算 A,再算 B → 答案 42 ✅
- 路径 2:先算 C,再算 D → 答案 42 ✅
- 路径 3:某个中间步骤算错了 → 答案 38 ❌
如果只推理一次,刚好走了路径 3,就错了。但如果推理 5 次,3 次得到 42,2 次得到 38,取多数答案 42,就对了。
3.3 Self-Consistency 的三步流程
rust
┌─────────────────────────────────────────────────────────────┐
│ Self-Consistency 三步流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 第一步:生成多条推理路径 │
│ ═════════════════════════════ │
│ 用 CoT Prompt + 较高的 Temperature,生成 N 个回答 │
│ (N 通常取 5~40) │
│ │
│ ▼ │
│ │
│ 第二步:提取每个回答的最终答案 │
│ ═════════════════════════════ │
│ 从每条推理路径中提取出最终答案(数字/选项/标签) │
│ │
│ ▼ │
│ │
│ 第三步:投票选多数 │
│ ═════════════════════════════ │
│ 统计每个答案出现的次数,取最多的作为最终结果 │
│ │
└─────────────────────────────────────────────────────────────┘
3.4 代码实现
python
import openai
from collections import Counter
def self_consistency(question: str, n_samples: int = 10) -> dict:
"""
Self-Consistency 实现
1. 用 CoT 生成多条推理路径
2. 提取最终答案
3. 投票选多数
"""
cot_prompt = f"""{question}
请一步步思考,先给出详细的推理过程,最后用【最终答案】给出结论。"""
# 第一步:生成多条推理路径
# 注意:这里用较高的 temperature 来增加多样性
reasoning_paths = []
for i in range(n_samples):
response = openai.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": cot_prompt}
],
temperature=0.7, # 较高温度 → 不同推理路径
)
reasoning_paths.append(response.choices[0].message.content)
# 第二步:提取最终答案
answers = []
for path in reasoning_paths:
# 从推理路径中提取【最终答案】后面的内容
if "【最终答案】" in path:
answer = path.split("【最终答案】")[-1].strip()
elif "最终答案" in path:
answer = path.split("最终答案")[-1].strip()
else:
answer = path.strip() # fallback:取最后一行
answers.append(answer)
# 第三步:投票选多数
answer_counts = Counter(answers)
most_common = answer_counts.most_common(1)[0]
return {
"question": question,
"final_answer": most_common[0],
"confidence": most_common[1] / n_samples, # 置信度 = 多数票占比
"answer_distribution": dict(answer_counts),
"all_reasoning_paths": reasoning_paths,
}
# ============ 使用示例 ============
result = self_consistency(
"一个水池A管6小时注满,B管8小时排完,同时开多久注满?",
n_samples=5
)
print(f"最终答案: {result['final_answer']}")
print(f"置信度: {result['confidence']:.0%}")
print(f"答案分布: {result['answer_distribution']}")
# 最终答案: 24小时
# 置信度: 80% (5次中有4次得到正确答案)
# 答案分布: {'24小时': 4, '12小时': 1}
3.5 效果对比
| 方法 | 数学推理准确率 | 常识推理准确率 | 符号推理准确率 |
|---|---|---|---|
| 直接回答(无 CoT) | ~45% | ~60% | ~40% |
| CoT(单次推理) | ~75% | ~72% | ~65% |
| Self-Consistency | ~85% | ~78% | ~75% |
Self-Consistency 对数学类任务提升最明显,因为数学答案通常是确定的(对就是对,错就是错),投票机制效果最好。对于开放性问题(如"写一篇文章"),Self-Consistency 就不太适用了。
3.6 Self-Consistency 的权衡
ini
┌─────────────────────────────────────────────────────────────┐
│ Self-Consistency 的成本与收益 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 采样次数 (N) 准确率提升 API 调用成本 延迟 │
│ ───────────────────────────────────────────── │
│ 1 (仅 CoT) 基准 1x 低 │
│ 5 +5~10% 5x 中 │
│ 10 +8~12% 10x 中高 │
│ 20 +10~15% 20x 高 │
│ 40 +12~17% 40x 很高 │
│ │
│ 💡 推荐配置: │
│ • 日常使用:N = 5(性价比最高) │
│ • 重要任务:N = 10~20 │
│ • 关键决策:N = 20~40 │
│ │
│ ⚠️ 注意:N 越大,延迟越高,成本越高 │
│ 可以通过并行请求来降低延迟 │
│ │
└─────────────────────────────────────────────────────────────┘
3.7 并行优化:降低延迟
python
import concurrent.futures
def self_consistency_parallel(question: str, n_samples: int = 10) -> dict:
"""
并行版 Self-Consistency
用多线程同时发送请求,大幅降低总延迟
"""
def single_sample(i):
response = openai.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": f"{question}\n\n请一步步思考,最后用【最终答案】给出结论。"}
],
temperature=0.7,
)
return response.choices[0].message.content
# 并行发送所有请求
with concurrent.futures.ThreadPoolExecutor(max_workers=n_samples) as executor:
futures = [executor.submit(single_sample, i) for i in range(n_samples)]
reasoning_paths = [f.result() for f in futures]
# 提取答案 + 投票(同上)
answers = []
for path in reasoning_paths:
if "【最终答案】" in path:
answers.append(path.split("【最终答案】")[-1].strip())
most_common = Counter(answers).most_common(1)[0]
return {
"final_answer": most_common[0],
"confidence": most_common[1] / len(answers),
"answer_distribution": dict(Counter(answers)),
}
四、三大技巧组合使用
4.1 组合策略矩阵
| 场景 | 推荐组合 | 原因 |
|---|---|---|
| 分类/格式转换 | Few-shot | 不需要推理,示例就够了 |
| 数学/逻辑推理 | CoT | 需要一步步思考 |
| 高准确率数学 | Few-shot CoT + Self-Consistency | 示例教方法 + 多次推理保准确 |
| 创意写作 | Few-shot(风格模仿) | 不需要 CoT,CoT 反而限制创意 |
| 代码生成 | Few-shot CoT | 示例教格式 + 推理保逻辑 |
| 复杂分析 | CoT + Self-Consistency | 推理 + 多数投票 |
4.2 终极组合:Few-shot CoT + Self-Consistency
这是目前最强的提示策略组合,特别适合高准确率要求的推理任务:
python
def advanced_reasoning(question: str, n_samples: int = 10) -> dict:
"""
终极组合:Few-shot CoT + Self-Consistency
"""
# Few-shot CoT 示例
few_shot_cot = """
Q: 一件商品原价 100 元,先涨价 25%,再打 8 折,最终价格是多少?
A: [推理过程]
原价 100 元。
涨价 25%:100 × 1.25 = 125 元。
打 8 折:125 × 0.8 = 100 元。
[最终答案] 100 元
Q: 小红有 50 元,买书花了 60% 的钱,又用剩下的钱买了一支笔花了 5 元,还剩多少?
A: [推理过程]
原有 50 元。
买书花了 60%:50 × 0.6 = 30 元,剩下 20 元。
买笔花了 5 元:20 - 5 = 15 元。
[最终答案] 15 元
"""
prompt = f"""{few_shot_cot}
Q: {question}
A:"""
# Self-Consistency:多次采样
answers = []
for _ in range(n_samples):
response = openai.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.7, # 需要多样性
)
content = response.choices[0].message.content
if "【最终答案】" in content:
answers.append(content.split("【最终答案】")[-1].strip())
most_common = Counter(answers).most_common(1)[0]
return {
"final_answer": most_common[0],
"confidence": most_common[1] / len(answers),
"distribution": dict(Counter(answers)),
}
写在最后
三个高级技巧,本质上是在回答一个问题:如何让模型"更聪明"?
- Few-shot 解决的是"怎么做"------用示例教模型你想要的模式
- CoT 解决的是"想清楚"------让模型一步步推理,而不是直接猜答案
- Self-Consistency 解决的是"更可靠"------多次推理取多数,降低偶然出错
记住一个原则:技巧越复杂,成本越高。不是所有场景都需要 Self-Consistency,简单的分类任务用 Few-shot 就够了。选择适合你场景的技巧,才是最好的。
觉得有用?点赞收藏!你在实际使用中遇到过哪些坑?评论区聊聊
#提示词工程 #Few-shot #Chain-of-Thought #自一致性 #CoT #Self-Consistency #大模型 #Prompt技巧 #AI推理 #技术分享 #程序员