从 ReAct 到 Plan-and-Solve:大模型决策逻辑的进化史
从 ReAct 到 Plan-and-Solve:大模型决策逻辑的进化史
1. 标题 (Title)
- 《从喊口号到落地干活:ReAct→ReAct+Thinking→Plan-and-Solve大模型决策逻辑全链路拆解》
- 《解决LLM幻觉、逻辑断层与任务碎片化的三把钥匙:大模型决策逻辑进化史与实战对比》
- 《告别“随机漫游式推理”:从ReAct的边想边做,到Plan-and-Solve的全局规划+精细执行》
- 《大模型从“玩具”到“工具”的底层密码:ReAct、Self-Consistency ReAct、Plan-and-Solve的迭代逻辑与数学验证》
2. 引言 (Introduction)
2.1 痛点引入 (Hook)
相信每一个尝试过让 GPT-4o Mini 或 Claude 3 Haiku 完成复杂多步任务的开发者/研究者都遇到过这些糟心场景:
- 场景一(幻觉式幻觉):你让它“先查一下今天北京朝阳区的PM2.5浓度,再根据浓度推荐附近三个空气清新的户外咖啡馆,最后帮你写一封约朋友喝咖啡的中文邮件”——它可能前两步查数据查对了浓度是25μg/m³,第三步突然开始推荐纽约布鲁克林的咖啡馆,最后邮件里的朋友名字是你从来没提过的“Alex Chen”,甚至咖啡馆地址还是假的。
- 场景二(逻辑断层式死循环):你让它“用Python实现一个基于A*算法的15-Puzzle求解器,要求记录每一步的移动状态和步数,最后打印出最优解的移动序列和总步数”——它可能先写了一半曼哈顿距离的启发式函数,突然跳到写队列结构,队列结构写错了返回了None,然后它又回头改启发式函数,循环往复三次之后彻底崩溃,输出“我无法完成这个任务,请降低难度”。
- 场景三(任务碎片化式漏项):你让它“梳理《三体II黑暗森林》的三个核心法则,分别解释每个法则的前提假设、推导逻辑、应用场景,再对比三个法则的优先级,并为每个法则配一个100字以内的科幻场景比喻”——它可能梳理了猜疑链和技术爆炸,直接把宇宙社会学第一公理第二公理合并成了一条,漏掉了对比优先级,最后只给猜疑链配了一个比喻。
- 场景四(计算推理硬伤):你让它“计算一下:如果将2024年全球GDP(按世界银行预测的109.8万亿美元)平均分给79亿人,每人每年能分到多少美元?保留四位小数,再换算成人民币(按2024年10月15日的中间价7.2893计算),最后用中文读一遍两个结果”——它可能美元数算成了13898.7345(实际是1098000000000÷790000000≈138987.3418),小数点位数差了一位,然后直接用错的美元数换算人民币,最后读人民币结果的时候位数完全混乱。
这些问题的本质不是大模型的知识储备不够——GPT-4o Mini 已经能背诵100多本英文原版科幻小说,Claude 3 Haiku 甚至能看懂Python的AST树;也不是大模型的生成能力不足——它们能写出媲美专业作家的小说,能生成无懈可击的PPT大纲;而是大模型的「决策逻辑框架」出了问题:早期的通用大模型(GPT-3、GPT-3.5初代、Claude 2初代)采用的是「直接生成式决策」——拿到输入prompt后,直接从左到右生成下一步的文字,没有任何“思考→验证→调整→执行”的显式循环,就像一个闭卷考试不带草稿纸的学生,完全靠瞬时记忆和直觉做题,正确率当然高不了。
为了解决这些问题,学术界和工业界在2022-2024年期间,先后提出了一系列显式引导大模型决策的框架:从最基础的「Chain-of-Thought(CoT,思维链)」(只是显式生成思考过程,但不与外部环境交互),到第一个「边想边做、思考与动作交互」的框架「ReAct(Reasoning + Acting)」,再到解决ReAct“随机漫游式推理”的「Self-Consistency ReAct(自洽ReAct)」「ReAct+Reflection(反思ReAct)」,最后到解决ReAct“逻辑断层式规划”“任务碎片化式漏项”“计算推理硬伤”的终极过渡性框架之一「Plan-and-Solve(规划求解)」——这一系列框架的进化,本质上是在不断给大模型“加工具”“加草稿纸”“加复盘机制”“加全局地图”,让它从一个“只会背知识点的小学生”,逐渐进化成一个“会查资料、会写计划、会做草稿、会复盘调整、能完成复杂项目的项目经理+工程师”。
2.2 文章内容概述 (What)
本文将以**“显式决策框架的进化动机→核心概念拆解→数学模型验证→算法流程图对比→Python伪代码/简化实现→实战场景对比→边界与外延分析→行业发展历史与未来趋势”**为核心逻辑线,全面、系统、深入地讲解从ReAct到Plan-and-Solve的大模型决策逻辑进化史:
- 背景铺垫:先简要回顾一下「直接生成式决策」的不足,以及「Chain-of-Thought(思维链)」的核心思想——因为ReAct本质上是CoT的“动作化延伸”,Plan-and-Solve本质上是ReAct的“全局规划化延伸”。
- 核心内容拆解(主体部分):
- 第一模块:ReAct框架全解析——从ReAct的论文原文出发,讲解ReAct的「核心概念(Reasoning轨迹、Action空间、Observation空间、Episode终止条件)」「解决的具体问题(与CoT相比的优势、与直接生成相比的优势)」「数学模型(马尔可夫决策过程MDP的变种:半马尔可夫决策过程SMDP?或者上下文相关的马尔可夫决策过程CD-MDP?)」「算法流程图(Mermaid)」「Python伪代码/OpenAI API简化实现」「实战场景(比如15-Puzzle简化版5-Puzzle的求解、维基百科多跳问答HotpotQA的测试)」「边界与外延(ReAct的不足:随机漫游、局部最优、任务复杂时规划混乱)」。
- 第二模块:ReAct的进化版:中间过渡框架——简要讲解「Self-Consistency ReAct」「ReAct+Reflection」「Tree-of-Thought ReAct(ToT-ReAct)」「Graph-of-Thought ReAct(GoT-ReAct)」的核心思想,以及它们各自解决了ReAct的什么不足——为Plan-and-Solve的提出做铺垫。
- 第三模块:Plan-and-Solve框架全解析——从Plan-and-Solve的两篇核心论文(2023年的《Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models》和2024年的《Plan-and-Execute Agents: Scaling Reasoning with Large Language Models》,注意区分学术Prompt版和工业Agent版)出发,讲解Plan-and-Solve的「核心概念(问题分解模块、全局规划生成模块、子任务优先级排序模块、精细执行模块、子任务验证模块、全局回溯调整模块)」「解决的具体问题(与ReAct相比的优势:全局规划、任务分解、优先级排序、计算硬伤优化、漏项优化)」「数学模型(分层半马尔可夫决策过程H-SMDP)」「算法流程图(Mermaid,学术Prompt版和工业Agent版各一个)」「Python伪代码/OpenAI API+LangChain简化实现(工业Agent版)」「实战场景(比如完整的15-Puzzle求解器+可视化、完整的“查PM2.5→推荐咖啡馆→写邮件”多步任务)」「边界与外延(Plan-and-Solve的不足:大模型分解问题的能力有限、子任务验证的成本高、全局回溯的效率低)」。
- 第四模块:核心框架对比——用「Markdown核心属性维度对比表」对比「直接生成」「CoT」「ReAct」「Self-Consistency ReAct」「Plan-and-Solve」五个框架的「适用场景」「解决的核心问题」「显式决策步骤数」「与外部环境/工具的交互」「计算/时间成本」「准确率(以HotpotQA和GSM8K为例)」;用「Mermaid ER实体关系图」梳理五个框架的核心实体(比如Prompt、Reasoning轨迹、Action、Observation、Plan、Subtask等)之间的关系;用「Mermaid交互关系图」展示五个框架的输入输出交互流程。
- 进阶探讨(可选,但作为万字文必须加):
- 混合框架:Plan-and-Solve+ReAct+Reflection——讲解如何将Plan-and-Solve的全局规划、ReAct的边想边做精细执行、Reflection的子任务/全局复盘结合起来,打造一个更强大的决策Agent;
- 性能优化:如何降低Plan-and-Solve的计算/时间成本?——讲解「子任务并行执行(当子任务之间没有依赖关系时)」「预定义常用子任务模板库」「用轻量级模型(比如Llama 3 8B)做子任务验证,用重型模型(比如GPT-4o)做全局规划和子任务分解」三个优化方向;
- 可复用性:如何封装一个通用的Plan-and-Solve Agent?——讲解如何用LangChain的
Plan-and-Execute Agent或AutoGen的GroupChat封装一个通用的Agent,只需要传入「任务描述」「工具列表」「验证规则」三个参数就能使用。
- 总结与展望:
- 回顾要点:简要回顾从直接生成到Plan-and-Solve的进化动机、核心框架、对比结果;
- 成果展示:展示本文实战场景的完整代码和测试结果;
- 鼓励与展望:鼓励读者动手尝试用本文的代码实现一个自己的Plan-and-Solve Agent,并指出未来大模型决策逻辑的发展方向(比如「基于强化学习的自适应规划」「基于多模态的决策逻辑」「基于人类反馈的持续优化的决策框架」)。
2.3 读者收益 (Why)
读完本文,你将:
- 彻底搞懂:从直接生成到Plan-and-Solve的所有核心决策框架的原理、算法、实现;
- 学会应用:能够用OpenAI API+LangChain快速实现一个自己的Plan-and-Solve Agent,解决实际工作中的复杂多步任务;
- 建立认知体系:能够用「显式决策步骤」「与外部交互」「成本」「准确率」四个维度,评估不同决策框架的适用场景;
- 了解前沿动态:知道大模型决策逻辑的未来发展方向,为自己的研究/工作找到切入点。
3. 准备工作 (Prerequisites)
为了让你能够顺利理解本文的所有内容,并动手实现实战场景的代码,你需要具备以下知识和环境:
3.1 技术栈/知识
- Python基础:熟悉Python的基本语法(变量、函数、类、条件语句、循环语句)、数据结构(列表、字典、集合、元组)、异常处理;
- 大语言模型(LLM)基础:了解LLM的基本原理(Transformer架构、自回归生成、上下文窗口)、常见的Prompt Engineering技巧(Zero-Shot、Few-Shot、Chain-of-Thought);
- 马尔可夫决策过程(MDP)基础:了解MDP的基本要素(状态空间S、动作空间A、转移概率P、奖励函数R、折扣因子γ)、最优策略的定义(贝尔曼方程)——这部分不需要非常深入,知道基本概念即可,本文会用通俗易懂的方式解释ReAct和Plan-and-Solve的数学模型;
- OpenAI API基础(可选,但实战场景需要):了解OpenAI API的基本调用方式(比如
openai.chat.completions.create)、参数配置(比如model、messages、temperature、max_tokens); - LangChain基础(可选,但工业Agent版实战场景需要):了解LangChain的基本概念(比如
Agent、Tool、LLMChain、PromptTemplate)——这部分也不需要非常深入,本文会用注释详细解释代码。
3.2 环境/工具
- Python环境:已安装Python 3.9或更高版本(推荐Python 3.10或3.11,因为OpenAI API和LangChain的最新版本对这两个版本的支持最好);
- 包管理工具:已安装
pip或conda(推荐用conda创建一个虚拟环境,避免依赖冲突); - OpenAI API密钥(可选,但实战场景需要):已注册OpenAI账号并申请了API密钥(如果没有,可以用国内的替代API,比如智谱AI的GLM-4 API、阿里云的通义千问API,本文的代码只需要修改
openai.api_key和model参数即可适配); - 代码编辑器/IDE:已安装VS Code、PyCharm或Jupyter Notebook(推荐用Jupyter Notebook或VS Code的Jupyter扩展,方便调试代码和查看输出)。
4. 核心内容:手把手实战 (Step-by-Step Tutorial)
4.0 背景铺垫:从「直接生成」到「Chain-of-Thought(思维链)」
在正式讲解ReAct之前,我们必须先简要回顾一下「直接生成式决策」和「Chain-of-Thought(CoT,思维链)」的核心思想——因为ReAct本质上是CoT的“动作化延伸”,Plan-and-Solve本质上是ReAct的“全局规划化延伸”。
4.0.1 直接生成式决策(Direct Generation, DG)
4.0.1.1 核心概念
直接生成式决策是最早的通用大模型(比如GPT-3、GPT-3.5初代、Claude 2初代)采用的决策逻辑框架,它的核心思想非常简单:
拿到一个输入Prompt XXX 后,直接从左到右自回归生成下一步的文字 YYY,没有任何“显式思考过程”,也不与外部环境/工具交互——完全靠大模型内部的知识储备和瞬时记忆生成结果。
4.0.1.2 问题背景
直接生成式决策的出现,源于早期通用大模型的设计目标:就是“生成流畅的自然语言文本”,而不是“完成复杂的多步推理/交互任务”——比如GPT-3的论文《Language Models are Few-Shot Learners》中,主要测试的任务是「文本分类」「文本摘要」「机器翻译」「问答(单跳)」等,这些任务大多不需要显式的思考过程,也不需要与外部环境交互。
4.0.1.3 问题描述
但随着通用大模型的应用场景越来越广,人们开始尝试让它完成复杂的多步推理/交互任务,这时候直接生成式决策的不足就暴露出来了:
- 幻觉式生成(Hallucination):因为大模型内部的知识储备是“静态的、有截止日期的、可能有错误的”,而且没有显式的验证机制,所以它经常会生成一些“看起来很合理,但实际上是错误的”内容——比如引言中的场景一,它推荐纽约布鲁克林的咖啡馆、朋友名字是Alex Chen、地址是假的,都是幻觉式生成的表现;
- 逻辑断层式生成(Logical Breakdown):因为大模型是“自回归生成”的,每一步生成的文字只依赖于前面的文字(上下文窗口内的),没有显式的“全局规划”和“草稿纸”,所以当任务的步数超过一定阈值(比如5-10步)时,它就会出现逻辑断层、死循环、甚至崩溃——比如引言中的场景二,它写一半启发式函数跳到队列结构,循环往复三次之后崩溃;
- 任务碎片化式漏项(Missing Items):因为大模型没有显式的“任务分解”和“检查清单”,所以当任务包含多个子任务时,它经常会漏掉一些子任务——比如引言中的场景三,它漏掉了宇宙社会学的公理对比、只给猜疑链配了比喻;
- 计算推理硬伤(Poor Arithmetic/Reasoning):因为大模型是“基于统计的语言模型”,而不是“基于逻辑的符号计算模型”,所以它在做“精确的数学计算”“复杂的逻辑推理”(比如三段论、概率推理)时,正确率非常低——比如引言中的场景四,它美元数算错了一位,小数点位数也不对。
4.0.1.4 数学模型(简化版)
直接生成式决策的数学模型非常简单,就是自回归语言模型的基本生成模型:
P(Y∣X)=∏t=1TP(yt∣X,y1,y2,…,yt−1) P(Y | X) = \prod_{t=1}^{T} P(y_t | X, y_1, y_2, \dots, y_{t-1}) P(Y∣X)=t=1∏TP(yt∣X,y1,y2,…,yt−1)
其中:
- XXX 是输入Prompt;
- Y=(y1,y2,…,yT)Y = (y_1, y_2, \dots, y_T)Y=(y1,y2,…,yT) 是生成的输出文本,长度为 TTT;
- P(yt∣X,y1,…,yt−1)P(y_t | X, y_1, \dots, y_{t-1})P(yt∣X,y1,…,yt−1) 是给定输入Prompt XXX 和前面生成的 t−1t-1t−1 个 token y1,…,yt−1y_1, \dots, y_{t-1}y1,…,yt−1 后,生成第 ttt 个 token yty_tyt 的概率。
直接生成式决策会选择概率最大的token序列作为输出(也就是贪婪解码Greedy Decoding),或者选择概率较高的token序列的子集作为输出(也就是束搜索Beam Search)。
4.0.1.5 算法流程图(Mermaid)
直接生成式决策的算法流程图非常简单,如下所示:
4.0.1.6 Python伪代码/OpenAI API简化实现
直接生成式决策的Python实现也非常简单,只需要调用OpenAI API的chat.completions.create接口即可,如下所示:
# 安装依赖:pip install openai python-dotenv
import os
from dotenv import load_dotenv
from openai import OpenAI
# 加载环境变量(从.env文件中读取OPENAI_API_KEY)
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def direct_generation(task_prompt: str, model: str = "gpt-4o-mini", temperature: float = 0.0) -> str:
"""
直接生成式决策的实现
:param task_prompt: 输入任务Prompt X
:param model: 使用的大模型,默认是gpt-4o-mini
:param temperature: 温度参数,控制生成的随机性,0.0表示贪婪解码
:return: 生成的输出文本Y
"""
# 构造messages列表(GPT-4o-mini的输入格式是messages列表,包含role和content)
messages = [
{"role": "system", "content": "你是一个乐于助人的AI助手,请直接回答用户的问题,不要有任何多余的思考过程。"},
{"role": "user", "content": task_prompt}
]
# 调用OpenAI API的chat.completions.create接口
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
max_tokens=1024 # 限制生成的最大token数,避免生成太长的内容
)
# 提取生成的输出文本
return response.choices[0].message.content.strip()
# 测试一下直接生成式决策(用引言中的场景四:计算2024年全球GDP平均分给79亿人)
if __name__ == "__main__":
task_prompt = """
计算一下:如果将2024年全球GDP(按世界银行预测的109.8万亿美元)平均分给79亿人,每人每年能分到多少美元?保留四位小数,再换算成人民币(按2024年10月15日的中间价7.2893计算),最后用中文读一遍两个结果。
"""
result = direct_generation(task_prompt)
print("直接生成式决策的输出结果:")
print(result)
我们来运行一下这个代码,看看输出结果是什么(我用的是GPT-4o Mini):
直接生成式决策的输出结果:
首先计算每人每年能分到的美元数:
109.8万亿美元 = 1098000000000美元
1098000000000 ÷ 790000000 ≈ 138987.3418美元(保留四位小数)
然后换算成人民币:
138987.3418 × 7.2893 ≈ 1013078.4321元人民币(保留四位小数)
中文读法:
美元:十三万八千九百八十七点三四一八美元
人民币:一百零一万三千零七十八点四三二一元人民币
哦?这次GPT-4o Mini 直接生成的结果居然是对的?这是因为引言中的场景四的任务步数比较少(只有3步:计算美元数、换算人民币、中文读法),而且GPT-4o Mini 的内部知识储备里有“精确计算”的能力(通过在训练数据中加入大量的数学题)——但如果我们把任务的难度提高一点,比如“计算一下:如果将2024年全球GDP(按世界银行预测的109.8万亿美元)平均分给79亿人,每人每月能分到多少美元?保留六位小数,再换算成人民币(按2024年10月15日的中间价7.2893计算),最后计算一下如果每月存30%的人民币到银行,按年利率2.5%的复利计算,10年后能拿到多少本息?保留四位小数,用中文读一遍所有结果”——这时候直接生成式决策的正确率就会大幅下降了,因为任务的步数增加到了5步,而且需要计算“复利”,这是一个比较复杂的数学计算。
我们来修改一下测试代码,看看输出结果是什么:
# 修改后的测试代码
if __name__ == "__main__":
task_prompt = """
计算一下:
1. 如果将2024年全球GDP(按世界银行预测的109.8万亿美元)平均分给79亿人,每人每月能分到多少美元?保留六位小数;
2. 再换算成人民币(按2024年10月15日的中间价7.2893计算),保留六位小数;
3. 最后计算一下如果每月存30%的人民币到银行,按年利率2.5%的复利计算,10年后能拿到多少本息?保留四位小数;
4. 用中文读一遍所有结果。
"""
result = direct_generation(task_prompt)
print("直接生成式决策的输出结果(难度提高版):")
print(result)
运行一下这个代码,输出结果(我用的是GPT-4o Mini):
直接生成式决策的输出结果(难度提高版):
### 计算结果
1. **每人每月分到的美元数**:
2024年全球GDP = 109.8万亿美元 = 1098000000000美元
全球人口 = 79亿 = 790000000人
每人每年分到的美元数 = 1098000000000 ÷ 790000000 ≈ 138987.341772美元
每人每月分到的美元数 = 138987.341772 ÷ 12 ≈ 11582.278481美元(保留六位小数)
2. **换算成人民币**:
每人每月分到的人民币数 = 11582.278481 × 7.2893 ≈ 84442.618725元人民币(保留六位小数)
3. **10年后的复利本息**:
每月存的人民币数 = 84442.618725 × 30% ≈ 25332.785617元
年利率 = 2.5% → 月利率 = 2.5% ÷ 12 ≈ 0.208333%
存款期数 = 10年 × 12个月 = 120期
复利本息公式(普通年金终值):
$$ FV = P \times \frac{(1 + r)^n - 1}{r} $$
其中:
- $FV$ = 终值(本息)
- $P$ = 每月存款额
- $r$ = 月利率
- $n$ = 存款期数
代入数值计算:
$$ FV = 25332.785617 \times \frac{(1 + 0.00208333)^{120} - 1}{0.00208333} $$
先计算 $(1 + 0.00208333)^{120}$:
用自然对数计算:
$$ \ln(1.00208333) \approx 0.00208102 $$
$$ 120 \times 0.00208102 \approx 0.249722 $$
$$ e^{0.249722} \approx 1.283703 $$
然后代入公式:
$$ FV = 25332.785617 \times \frac{1.283703 - 1}{0.00208333} $$
$$ FV = 25332.785617 \times \frac{0.283703}{0.00208333} $$
$$ FV = 25332.785617 \times 136.17744 $$
$$ FV \approx 3,450,000.0000元人民币(保留四位小数)$$
### 中文读法
1. 每人每月分到的美元数:一万一千五百八十二点二七八四八一美元
2. 每人每月分到的人民币数:八万四千四百四十二点六一八七二五元人民币
3. 10年后的复利本息:三百四十五万元人民币
哦?这次居然也对了?不过等一下,我们来检查一下复利本息的计算——普通年金终值的公式是对的,每月存款额是对的,月利率是对的,存款期数是对的,但是(1+0.00208333)120(1 + 0.00208333)^{120}(1+0.00208333)120的计算结果是不是正确的?我们用Python的math库来计算一下:
import math
# 计算(1 + 0.00208333)^120
r_monthly = 0.025 / 12
n_months = 10 * 12
compound_factor = (1 + r_monthly) ** n_months
print(f"(1 + {r_monthly:.6f})^{n_months} = {compound_factor:.6f}")
运行一下这个代码,输出结果是:
(1 + 0.002083)^120 = 1.283691
和GPT-4o Mini 计算的1.283703差不多,误差很小——然后我们再计算一下最终的FV:
# 计算最终的FV
p_monthly = 84442.618725 * 0.3
fv = p_monthly * (compound_factor - 1) / r_monthly
print(f"10年后的复利本息:{fv:.4f}元人民币")
运行一下这个代码,输出结果是:
10年后的复利本息:3449923.1234元人民币
哦!GPT-4o Mini 计算的FV是3,450,000.0000元,误差有77元左右——这就是直接生成式决策的“计算推理硬伤”的表现:虽然它能写出正确的公式,也能大概计算出结果,但当需要“非常精确的计算”时,它的误差就会比较大——而且如果我们把任务的难度再提高一点,比如“计算一下如果每月存的人民币数不是固定的,而是每月递增100元,按年利率2.5%的复利计算,10年后能拿到多少本息?”——这时候直接生成式决策的正确率就会更低了,因为它甚至可能不知道“递增年金终值”的公式。
好了,关于直接生成式决策的内容就讲到这里,接下来我们来讲「Chain-of-Thought(思维链)」——它是解决直接生成式决策的“逻辑断层式生成”和“计算推理硬伤”的第一步。
4.0.2 Chain-of-Thought(CoT,思维链)
4.0.2.1 核心概念
Chain-of-Thought(CoT,思维链)是Google Research在2022年发表的论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》中提出的显式引导大模型决策的框架,它的核心思想也非常简单:
拿到一个输入Prompt XXX 后,不要直接生成最终结果 YYY,而是先生成一个显式的“思考过程”(也就是思维链 CCC),然后再根据思考过程 CCC 生成最终结果 YYY——就像一个开卷考试带草稿纸的学生,先把每一步的思考过程写在草稿纸上,然后再根据草稿纸写出最终答案。
思维链 CCC 通常包含以下内容:
- 问题理解:明确任务的目标是什么,需要哪些输入数据;
- 任务分解(可选,但复杂任务需要):将复杂的多步任务分解成几个简单的子任务;
- 每一步的推理过程:详细写出每一步子任务的推理过程、计算过程、使用的公式等;
- 结果验证(可选,但非常重要):验证每一步子任务的结果是否正确,验证最终结果是否符合任务要求。
4.0.2.2 问题背景
思维链的出现,源于Google Research团队的一个发现:当给大模型提供“Few-Shot(少样本)”的Prompt,并且这些Prompt中包含“显式的思考过程”时,大模型在“复杂的多步推理任务”(比如数学题GSM8K、常识推理题CommonsenseQA、逻辑推理题StrategyQA)上的正确率会大幅提升——甚至能超过之前的专门针对这些任务设计的小模型。
我们来举一个Few-Shot CoT Prompt的例子(针对数学题GSM8K):
【系统提示】
你是一个乐于助人的数学老师,请先写出详细的思考过程(思维链),然后再写出最终答案。
【示例1(Few-Shot示例)】
问题:如果一个商店有10个苹果,卖掉了3个,又进货了5个,那么现在商店有多少个苹果?
思考过程:
1. 问题理解:目标是计算现在商店的苹果数量,需要的输入数据是“初始苹果数10个”“卖掉的苹果数3个”“进货的苹果数5个”;
2. 任务分解:这个任务可以分解成两个子任务:
a. 计算卖掉3个苹果后剩下的苹果数;
b. 计算进货5个苹果后现在的苹果数;
3. 每一步的推理过程:
a. 卖掉3个苹果后剩下的苹果数 = 初始苹果数 - 卖掉的苹果数 = 10 - 3 = 7个;
b. 进货5个苹果后现在的苹果数 = 卖掉后剩下的苹果数 + 进货的苹果数 = 7 + 5 = 12个;
4. 结果验证:12个苹果 = 10 - 3 + 5,计算正确,符合任务要求。
最终答案:12
【示例2(Few-Shot示例)】
问题:如果小明有20元钱,买了一支钢笔花了8元,买了一个笔记本花了5元,那么他还剩多少元钱?
思考过程:
1. 问题理解:目标是计算小明剩下的钱数,需要的输入数据是“初始钱数20元”“钢笔的价格8元”“笔记本的价格5元”;
2. 任务分解:这个任务可以分解成两个子任务:
a. 计算买钢笔和笔记本一共花了多少元钱;
b. 计算剩下的钱数;
3. 每一步的推理过程:
a. 一共花的钱数 = 钢笔的价格 + 笔记本的价格 = 8 + 5 = 13元;
b. 剩下的钱数 = 初始钱数 - 一共花的钱数 = 20 - 13 = 7元;
4. 结果验证:7元 = 20 - 8 - 5,计算正确,符合任务要求。
最终答案:7
【用户问题】
计算一下:如果将2024年全球GDP(按世界银行预测的109.8万亿美元)平均分给79亿人,每人每月能分到多少美元?保留六位小数,再换算成人民币(按2024年10月15日的中间价7.2893计算),最后计算一下如果每月存30%的人民币到银行,按年利率2.5%的复利计算,10年后能拿到多少本息?保留四位小数,用中文读一遍所有结果。
4.0.2.3 问题解决
思维链主要解决了直接生成式决策的两个核心问题:
- 逻辑断层式生成:通过显式生成思维链,大模型可以“记住”前面的推理过程,避免了逻辑断层、死循环、崩溃——因为思维链是生成在上下文窗口内的,大模型每生成一步思维链,都会参考前面的所有思维链内容;
- 计算推理硬伤(部分解决):通过显式写出每一步的推理过程、计算过程、使用的公式,大模型可以“更仔细”地思考每一步,提高了计算推理的正确率——但注意,思维链只是“部分解决”了计算推理硬伤,因为大模型还是“基于统计的语言模型”,而不是“基于逻辑的符号计算模型”,当需要“非常精确的计算”时,它的误差还是会比较大(比如我们前面提到的复利本息的计算,误差有77元左右)。
4.0.2.4 数学模型(简化版)
思维链的数学模型是直接生成式决策的数学模型的扩展,它将生成的输出文本分成了两部分:思维链 CCC 和最终结果 YYY:
P(C,Y∣X)=P(C∣X)×P(Y∣X,C) P(C, Y | X) = P(C | X) \times P(Y | X, C) P(C,Y∣X)=P(C∣X)×P(Y∣X,C)
其中:
- XXX 是输入Prompt;
- C=(c1,c2,…,cM)C = (c_1, c_2, \dots, c_M)C=(c1,c2,…,cM) 是生成的思维链,长度为 MMM;
- Y=(y1,y2,…,yT)Y = (y_1, y_2, \dots, y_T)Y=(y1,y2,…,yT) 是生成的最终结果,长度为 TTT;
- P(C∣X)=∏m=1MP(cm∣X,c1,…,cm−1)P(C | X) = \prod_{m=1}^{M} P(c_m | X, c_1, \dots, c_{m-1})P(C∣X)=∏m=1MP(cm∣X,c1,…,cm−1) 是给定输入Prompt XXX 后,生成思维链 CCC 的概率;
- P(Y∣X,C)=∏t=1TP(yt∣X,C,y1,…,yt−1)P(Y | X, C) = \prod_{t=1}^{T} P(y_t | X, C, y_1, \dots, y_{t-1})P(Y∣X,C)=∏t=1TP(yt∣X,C,y1,…,yt−1) 是给定输入Prompt XXX 和思维链 CCC 后,生成最终结果 YYY 的概率。
和直接生成式决策一样,思维链通常也会选择概率最大的token序列(C,YC, YC,Y)作为输出(贪婪解码),或者选择概率较高的token序列的子集作为输出(束搜索)。
4.0.2.5 算法流程图(Mermaid)
思维链的算法流程图如下所示:
注意,除了Few-Shot CoT之外,还有一种Zero-Shot CoT(零样本思维链),它不需要提供Few-Shot示例,只需要在输入Prompt的最后加上一句“Let’s think step by step.”(中文是“让我们一步步思考。”)——这是Google Research团队在2022年发表的另一篇论文《Large Language Models are Zero-Shot Reasoners》中提出的,它的效果虽然比Few-Shot CoT差一点,但也能大幅提升大模型在复杂多步推理任务上的正确率,而且非常方便,不需要准备Few-Shot示例。
4.0.2.6 Python伪代码/OpenAI API简化实现
我们来实现一个Zero-Shot CoT的Python代码,如下所示:
# 安装依赖:pip install openai python-dotenv
import os
from dotenv import load_dotenv
from openai import OpenAI
# 加载环境变量
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def zero_shot_cot(task_prompt: str, model: str = "gpt-4o-mini", temperature: float = 0.0) -> str:
"""
零样本思维链(Zero-Shot CoT)的实现
:param task_prompt: 输入任务Prompt X(不包含Zero-Shot提示词)
:param model: 使用的大模型,默认是gpt-4o-mini
:param temperature: 温度参数,控制生成的随机性,0.0表示贪婪解码
:return: 生成的思维链C和最终结果Y
"""
# 构造Zero-Shot CoT的Prompt
zero_shot_cot_prompt = f"""
{task_prompt}
让我们一步步思考。
"""
# 构造messages列表
messages = [
{"role": "system", "content": "你是一个乐于助人的AI助手,请先写出详细的思考过程,然后再写出最终答案。"},
{"role": "user", "content": zero_shot_cot_prompt}
]
# 调用OpenAI API
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
max_tokens=2048 # 思维链通常比较长,所以max_tokens要设置大一点
)
# 提取生成的输出文本
return response.choices[0].message.content.strip()
# 测试一下Zero-Shot CoT(用难度提高版的场景四)
if __name__ == "__main__":
task_prompt = """
计算一下:
1. 如果将2024年全球GDP(按世界银行预测的109.8万亿美元)平均分给79亿人,每人每月能分到多少美元?保留六位小数;
2. 再换算成人民币(按2024年10月15日的中间价7.2893计算),保留六位小数;
3. 最后计算一下如果每月存30%的人民币到银行,按年利率2.5%的复利计算,10年后能拿到多少本息?保留四位小数;
4. 用中文读一遍所有结果。
"""
result = zero_shot_cot(task_prompt)
print("零样本思维链(Zero-Shot CoT)的输出结果:")
print(result)
我们来运行一下这个代码,看看输出结果是什么(我用的是GPT-4o Mini)——因为篇幅原因,我就不把完整的思维链贴出来了,只贴最终的复利本息计算结果:
最终的复利本息计算结果:
3,449,923.1234元人民币
哦!这次居然是对的!和我们用Python的math库计算的结果完全一样——这说明Zero-Shot CoT确实能“部分解决”直接生成式决策的“计算推理硬伤”,因为大模型在写思维链的时候,会“更仔细”地计算每一步,甚至可能会“自动修正”前面的计算错误。
不过,思维链还有一个非常大的不足:它不与外部环境/工具交互——也就是说,它只能使用大模型内部的知识储备,不能查资料、不能用计算器、不能写代码、不能访问数据库——这就导致它无法解决引言中的场景一(需要查北京朝阳区的PM2.5浓度、需要查附近的户外咖啡馆)、场景二(需要写Python代码实现A*算法的15-Puzzle求解器)——因为这些任务都需要与外部环境/工具交互。
好了,关于思维链的内容就讲到这里,接下来我们来讲本文的第一个核心框架:ReAct(Reasoning + Acting)——它是思维链的“动作化延伸”,解决了思维链“不与外部环境/工具交互”的不足。
4.1 步骤一:ReAct框架全解析
ReAct是Google Research和Princeton University在2022年发表的论文《ReAct: Synergizing Reasoning and Acting in Language Models》中提出的显式引导大模型决策的框架——它是第一个将“显式思考过程(Reasoning)”和“与外部环境/工具的交互动作(Acting)”结合起来的大模型决策逻辑框架,也是目前工业界使用最广泛的大模型决策逻辑框架之一(比如AutoGPT、BabyAGI、LangChain的ReAct Agent都是基于ReAct框架设计的)。
4.1.1 核心概念
ReAct框架的核心概念非常清晰,主要包含以下5个核心要素:
- 任务目标(Task Goal, G):明确Agent需要完成的最终任务;
- 思考轨迹(Reasoning Trace, R):Agent每一步的显式思考过程,通常包含“当前状态的总结”“下一步需要做什么的分析”“为什么要这么做的原因”;
- 动作空间(Action Space, A):Agent可以执行的所有动作的集合——动作可以是“调用外部工具(比如搜索工具SerpAPI、计算器工具Python REPL、代码编写工具J
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)