跳到主要内容Agent 像人一样思考:主流思维链范式与最佳实践 | 极客日志编程语言AI算法
Agent 像人一样思考:主流思维链范式与最佳实践
综述由AI生成详细探讨了如何引导大语言模型像人一样思考,重点解析了多种思维链(Chain-of-Thought)范式及其应用场景。内容包括基础的 Zero-shot 和 Few-shot CoT,进阶的 Self-Consistency、Least-to-Most,以及高级的 ToT、GoT、AoT、SoT 和 PoT 等推理方法。文章通过 SQL 质检等实例演示了各范式的 Prompt 编写技巧,并提供了关于 Agent 架构设计、多模型协作、成本控制及安全性评估的最佳实践建议。旨在帮助开发者在实际项目中选择合适的推理策略,平衡效果与性能。
王者23 浏览 前言
Agent(智能体)是模型面向应用的中间层,通常理解为一个类人的智能系统。为了让 Agent 更像人类,我们需要引导底层大语言模型像人一样进行思考和推理。
思维链(Chain-of-Thought, CoT)作为一种引导模型思考的方法被广泛使用,它通过显式地展示推理步骤来增强模型的决策能力。
什么是思维链 CoT(Chain-of-Thought)
思维链被认为是最具开拓性和影响力的提示工程技术之一,它可以显著增强大型语言模型在复杂决策过程中的表现。
与传统的提示方法强调直接的输入和输出互动不同,CoT 迫使模型将推理过程划分为中间步骤。这种方法模拟了人类的认知过程,将复杂的挑战分解为更小、更易于管理的部分。
通俗点说,就是引导模型一步一步思考,最终得到答案,而不是直接猜测结果。
CoT 的原理
CoT 的原理目前学术界仍在探索中,通常认为和两个关键因素有关:一是模型的参数量要足够大(通常超过 100B),二是模型需要在代码数据或逻辑推理数据上做过专门训练。
那思维链能达到一个什么程度?参考相关论文中的对比实验,效果如下:
- 参数越大,思维链效果越明显,在 100B 左右甚至会出现性能突变
- 参数足够大时,思维链效果要超过标准指令(Standard Prompting)
- 参数足够大时,思维链效果接近,甚至超过有监督微调的效果
受限于模型架构、训练方式、数据质量等因素,实际效果会有一定差异。
CoT 的使用
不再是一步到位得出答案,CoT 的本质是让模型逐步推理,最终得出答案。
最初的 CoT 主要有两种使用姿势:Zero-shot CoT 和 Few-shot CoT。
Zero-shot CoT
其实大模型是非常聪明的,我们只需要告诉它一步步执行,就能达到基本效果。
问题示例:两辆汽车从相距 500 千米的两城同时出发,相向而行.一辆摩托车以每小时 80 千米的速度在两辆汽车之间不断往返联络.已知这两辆汽车的速度分别是每小时 40 千米和 60 千米,求两汽车相遇时,摩托车共行驶了多少千米。
正确答案计算逻辑:500/(40+60)*80 = 400 千米。
我们用 GPT-3 测试一下,先用空 prompt 测试,模型回复往往比较随机,有时对有时不对,效果不明显,这与其训练数据分布有关。
当 prompt 变为 Let's think step by step 时,模型回复会有明显改善:
我们可以先计算出两辆汽车相遇所需的时间,然后再计算摩托车在这段时间内行驶的距离。
两辆汽车相对于对方的速度是 60 千米/小时 + 40 千米/小时 = 100 千米/小时。他们之间的距离是 500 千米,所以他们相遇所需的时间为 500 千米 / (100 千米/小时) = 5 小时。
摩托车以每小时 80 千米的速度在两辆汽车之间不断往返联络,所以在 5 小时内,摩托车的行驶距离为 5 小时 × 80 千米/小时 = 400 千米。
所以摩托车共行驶了 400 千米。
Few-shot CoT
我们在 prompt 中给出少量的例子,充分发挥模型的推理 + 模仿能力,这种方式效果比较明显。
下面我们通过一个例子,展示如何让模型通过小样本学会一步一步推理的。
我们先创建一个 SQL 质检 Agent,Prompt 设定如下:
## 设定
根据输入的 sql 语句,指出存在的问题。
我们用这条 SQL 测试一下:update student set name = 张三
存在的问题是缺少 WHERE 子句来指定更新的行数。这将导致所有学生的姓名都被更改为"张三"。
这个 SQL 明显有两个问题,一个是 张三 没有用引号,一个是会更新全表数据。但模型只发现了一个问题。
思考:
我们应该如何分析一条 SQL 是否存在问题?大致有如下过程:
- 词法分析
- 语法分析
- 是否有操作风险
- 是否有安全风险
基于这种思考步骤,我们再 Prompt 中添加这样的内容:
## 示例
示例一:
输入:select * from user where a=1
思考过程:
1. 词法分析,不存在问题
2. 语法分析,不存在问题
3. 操作风险:当数据表中行数较多时,会查询出大量数据
4. 安全风险:可能存在注入,因为
输出:
该 sql 语句存在风险:
1. 当数据表中行数较多时,会查询出大量数据
2. 可能存在注入,因为
再次用上面的 SQL:update student set name = 张三 语句进行测试,回复会有明显改善:
该 sql 语句存在问题:
1. 缺少 WHERE 条件,将会更新所有学生的姓名为"张三",可能导致数据混乱。
2. 缺少引号,应该是'张三'而不是张三
进阶用法:Self-Consistency
Self-Consistency 是在 few-shot-CoT 的基础上做了一些工作。
具体的思路就是,让模型多次生成结果,将出现次数最多的结果作为答案。
或者使用投票的方式来决定用哪个结果。
这也一定程度上解决了大模型的随机性问题。
这在固定结果的场景中通常是非常有用的,例如数学题解答或分类任务。
进阶用法:Least-to-Most
如果说上面的 Self-Consistency 多少有点暴力出奇迹,那 Least-to-Most 明显更优雅一些。
- 第一步先引导模型把问题拆分成子问题;
- 第二步逐一回答子问题,并把子问题的回答作为下一个问题回答的上文,直到给出最终答案。
主打一个循序渐进的解决问题。也可以理解为通过 few-shot 来引导模型给出更合理、更一致的推理思路,再根据这个思路在解决问题。
我们依然用上面验证 SQL 的示例来展示一下操作流程,修改 Prompt 如下:
## 设定
根据输入的 sql 语句,指出存在的问题。
## 示例
示例一:
输入:select * from user where 1=1
输出:可以拆分这些子问题:"词法分析是否正确","语法分析是否正确","是否存在操作风险","是否存在注入风险"
输入:词法分析是否正确
输出:正确
输入:语法分析是否正确
输出:正确
输入:是否存在操作风险
输出:存在风险,会查询出大量数据
输入:是否存在注入风险
输出:存在注入风险,sql 中
//第一轮对话
user: update student set name = 张三
gpt4: 可以拆分这些子问题: "词法分析是否正确","语法分析是否正确","是否存在操作风险","是否存在注入风险"
//第二轮对话
user: 词法分析是否正确
gpt4: 不正确,更新的值应该用引号包裹,例如 name = '张三',而不是 name = 张三。
//第三轮对话
user: 语法分析是否正确
gpt4:不正确,因为在 SET 子句中对 name 列赋值时,'张三'应该被单引号括起来。正确的语句应该是:update student set name = '张三'
//第四轮对话
user: 是否存在操作风险
gpt4: 存在风险。此条更新语句没有使用 WHERE 子句进行条件限制,会导致表中的所有记录的 name 都被更新为 '张三',这可能是一种误操作。常规情况下,我们建议在执行更新操作时始终使用 WHERE 子句来限定被更新的记录。
//第五轮对话
user: 是否存在注入风险
gpt4: 在这个例子中,不存在 SQL 注入的风险。因为这条语句没有动态链接输入,也没有暴露出可以被利用来注入恶意 SQL 代码的漏洞。但是,SQL 注入通常出现在将未经过滤或未经适当处理的用户输入直接连接到 SQL 查询中的情况。
//第六轮:总结答案
user: 总结一下,存在哪些问题
gpt4:
这条 SQL 语句存在两个主要的问题:
1. 词法错误:在 SET 子句中对 name 列赋值时,字符串值 '张三' 没有被单引号括起来。
2. 操作风险:SQL 语句没有使用 WHERE 子句进行条件限制,这可能导致 student 表中所有记录的 name 都被更新为 '张三',很可能是一种误操作。
需要注意轻易不要在没有指定 WHERE 子句的情况下执行 UPDATE 操作,以防对数据库中的大量数据进行无意的修改,除非你确实打算进行全表更新。同时在执行 SQL 语句时要格外注意词法和语法规则,以确保 SQL 语句的正确性。
看起来效果是有进步的,随着示例的增多,回复的内容也会表现得更好,尤其是对子问题的拆解,示例越多,拆解越准确。
Least-to-Most 最重要的还是它问题拆分的思路,这在后面被广泛借鉴,例如 Agent 调用如何拆分每一步的调用步骤,以及如何先思考再生成下一步 Action,在这些方案里都能看到 Least-to-Most 的影子。
思维树 Tree-of-Thoughts (ToT)
- 不会探索不同的可能选择分支
- 无法在节点进行前后向的探索
对于解决复杂问题,提出了一种 ToT 的推理范式。
ToT 以树的形式组织其解决问题的策略。每个节点都被称为'思维',是一个连贯的语言序列,是通往最终答案的一步。
ToT 包括四个步骤:问题分解、想法生成、状态评价以及搜索算法的选择。
- 问题分解:第一步首先在于将复杂问题拆解成为 k 个子问题集,(允许剪枝和回溯)
- 想法生成:为每个子问题产生若干个方案
- 对于开放问题,比如写作,可以用大模型生成几个方案
- 对于封闭问题,比如分类,直接穷举给出方案
- 搜索算法:深度优先,或者广度优先都可以
- 状态评价:对于得到的每层结果,根据打分或者评价得出一个最终方案。
在特定场景下,尤其是固定类型的问题,它是非常有效的,比如论文中的 24 点游戏。
但是,ToT 实现起来很复杂,耗时也是个问题。衡量一下收益和付出,大多数时候,基础版的 ToT 并不是一个好的选择。
思维图谱 Graph-of-Thoughts(GoT)
GoT 和 ToT 解决问题的思路差不多,只是 GoT 将问题展开成一棵树(DAG)。
- 想法聚合:下层节点会依赖多个上层节点,即将几个想法融合成一个统一的想法
- 精炼:单个节点可以进行自我优化
- 思想的多样性,对比左边的 CoT 和 ToT,GoT 能够从现有思想中产生新的思想
核心是如何将问题变成 DAG 树。在实际应用中,除非是固定的场景,否则光靠模型,很难展开得特别好。论文中的几个例子数组排序、文档聚合、统计词频、求集合都比较简单。
总结,GoT 变强了,也更复杂了。
思维算法 Algorithm-of-Thoughts(AoT)
- 需要经过大量的节点,需要大量的 LLM 调用
- 要有一个近似全量的遍历过程,尽管可以剪枝
而 AoT 的思想是,直接找到尽可能正确的路径,而不是全量遍历过程。
他们的遍历过程的差异在于:最右边的 AoT,直接尝试找到正确的路径来解决问题,每个节点上都试图找到更有前景的解。
思维框架 Skeleton-of-Thought(SoT)
SoT 范式的独特设计主要是为了减少端到端生成延迟的挑战,而不是为了增强大型语言模型(LLM)的推理能力。
他的思路是,先生成推理骨架,再并行补充细节。
论文看的头大,我这里简单举个例子,更容易理解,还是上面的 SQL 验证的例子,我们修改 Prompt 如下:
## 设定
根据输入的 sql 语句,找到 sql 可能存在的问题。
## 示例
示例一:
输入:select * from user wher age=18
输出:
1. 需要验证的方向:"语法分析是否正确","是否存在安全风险"。
2. 语法分析需要验证的子项:"表名是否合法","关键字是否正确"。
3. 安全风险需要验证的子项:"影响数据量","是否存在 sql 注入"。
总结:
- 存在 sql 注入,
- 存在关键字错误,wher 应该为 where
还是那个有问题的输入 update student set name = 张三,此时的模型回复:
1. 需要验证的方向:"语法分析是否正确","是否存在安全风险"。
2. 语法分析需要验证的子项:"表名是否合法","关键字是否正确","数据类型是否正确"。
3. 安全风险需要验证的子项:"影响数据量","是否存在 sql 注入"。
总结:
- 表达式 "name = 张三" 中的 "张三" 应该为字符串类型,需要加上引号,正确的写法应为 "name = '张三'"。
- 需要注意该语句没有 where 条件,更新的数据会影响整个 student 表,可能存在数据被错误修改的风险。
我这里是直接将示例写在了 Prompt 上,实际可以通过多 Prompt 组合来实现效果更佳。
程序思维 Program-of-Thoughts (PoT)
还记得前面提到的,大模型思维链能力的原理吗,其中的一个可能原因就是模型经过了代码的训练。
那我们反过来,直接让模型生成代码,来解决我们的问题不就行了,这就是 PoT 的思想。
我们改造一下 Prompt,用于 text2sql:
## 设定
根据输入,生成 sql 语句。
## 示例
输入:我叫王大锤,今年 21
输出:insert into user('name','age') values('王大锤',21);
测试一下,输入 练习时长两年半的实习生,喜欢唱跳 rap
模型回复:insert into intern('name','job_duration','hobby') values('实习生',2.5,'唱跳 rap');
- 这个例子中,我们就省去了怎么去引导模型拼接 SQL 的逻辑。
最佳实践
1. DAG 还是流程图?
思维链的本质是指导模型进行推理,推理用 DAG 是比较方便的。
但我们面对现实中的问题,更多的是用流程图的思路来解决问题。就像我们写代码的三大基本结构(顺序,选择,循环)。
那我们要用那种方式来指引模型推导哪?我的答案是流程图。原因有三:
- 我们的目标是应用,流程图更容易被应用接受
- 在多模型或者多 Agent 的情况下,流程图更有优势
- 实现了流程图也就实现了 DAG
2. 为了达到更好的效果,优化模型还是优化 Agent?
理论上讲,两个都需要优化,但就思维链而言,复杂的推导过程不是一个 Prompt 能解决的。
这种情况下优化模型产生的收益,远远小于在 Agent 层面做优化。
说白了,多个 Prompt 就能解决的问题,非要去优化模型,或者做集成模型,我觉得不是明智之举。
3. 多模型还是多 Agent?
大家应该能体会到,上文中的很多范式都不是一个 Prompt 或者单轮对话能够解决的,需要多个模型 (Prompt) 配合,那我们将多个模型组合起来当做一个 Agent 用,还是做成多个 Agent 然后组合起来用呢?
这就像你写代码,是每个功能分开写成函数,然后在一个父函数中调用,还是直接一个巨大函数,把所有功能都写在里面。
正确的做法是,每个子问题做成一个 Agent,然后有个父 Agent 协调它们来解决问题。这样是符合架构思维的,也方便扩展和使用。
吊大的小伙伴肯定要说话了,子问题可以是动态生成出来的,要如何做成 Agent 呢?那当然是动态 Agent 来实现。
但是。。。现实是,在我们推动大模型应用的过程里,有很多应用都还是用了直接编排的方式,并没有做严格意义上的 Agent 封装。
对此,我们的做法是,Agent 只做逻辑上的约束,允许物理上的丑陋。
4. 如何选择推理过程?
上文介绍了很多推理方法,好像都能解决问题,论文中清一色数学问题,那在面对实际问题时用哪个?
我的实践是:
- 流程已知,较为固定的场景,就用简单的 CoT 就行
- 推荐场景,用 ToT 这种有决策倾向的,效果会比较好
- 生成场景,比如小说作家 Agent,SoT 比较好。
- 没有特定规律的场景,用 AoT,让模型自己去总结路径
如果你还是个萌新的时候,建议你每个方式都试一遍,最后根据评测结果使用效果最好的。
5. 项目刚开始不强制用思维链。
这个应该很好理解,标准 Prompt 其实效果就很好,尤其是经过 Instruction Finetune 的模型,效果非常好。
只有对效果不满意的时候,才需要精心调配。
6. 例子太多怎么办?
应用维护的时间比较长后,示例越加越多,怎么办?
比较推荐两种思路:
- 走 Knowledge 召回(RAG)
- Prompt 微调模型
7. 用了思维链之后,模型耗时增加非常严重怎么办?
从模型的思路上说几点,思路是 只让大模型执行关键流程。方法肯定不限于这些,需要结合你的场景进行链路排查。
- 多模型融合:在思维链的多轮调用中,一些简单的任务用小模型执行,速度提升比较明显,比如意图识别的场景。
- 固定场景的节点,可以用代码去执行,比如上文例子中的对 SQL 的词法分析和语法分析。
- 模型对 Tool 的理解和使用是非常耗时的,如果是固定流程,那就不要挂 Tool。
- 能用并行的地方尽量并行,比如流程图的并行结构。
- Token 预算控制:设置最大 Token 数,防止无限递归。
评估指标与成本考量
在实际落地思维链时,除了准确率,还需要关注以下指标:
- 延迟(Latency):CoT 通常需要多轮交互,首字延迟会增加。需评估业务容忍度。
- Token 消耗:推理步骤越多,Token 消耗呈线性增长。需计算单次请求成本。
- 稳定性:长链条推理容易出现中间步骤幻觉,需引入校验机制。
安全与隐私注意事项
- 提示词注入:用户输入可能包含诱导模型忽略安全规则的指令,需在系统层做过滤。
- 数据泄露:避免在思维链过程中将敏感信息(如密码、PII)写入日志或中间状态。
- 合规性:确保生成的推理过程符合行业监管要求,特别是金融、医疗领域。
尾语
效果和性能就像鱼和熊掌不可兼得。不同的应用,要在二者间找到对应的平衡点。
在实际工程中,建议从简单的 CoT 开始,逐步迭代到更复杂的范式。同时,建立完善的评估体系(Evaluation Harness)至关重要,只有通过量化指标对比,才能客观判断哪种思维链范式最适合当前业务场景。未来随着模型能力的增强,推理效率的提升,思维链的应用将更加普及和高效。
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- RSA密钥对生成器
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
- Mermaid 预览与可视化编辑
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
- 随机西班牙地址生成器
随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online