大模型应用(十)如何指导agent像人一样思考,一文看懂所有思维链范式,示例和最佳实践

前言

agent是模型面向应用的中间层,通常理解为是一个类人的智能体,为了让agent更像一个人,我们可以引导模型像人一样思考。

思维链(CoT)通常作为一种引导模型思考的方法被广泛使用。

什么是思维链 CoT(Chain-of-Thought)

思维链(CoT) 被认为最具开拓性和影响力的提示工程技术之一,它可以增强大型语言模型在决策过程中的表现。

与传统的提示方法强调直接的输入和输出互动不同,CoT迫使模型将推理过程划分为中间步骤。这种方法类似于人类的认知过程,将复杂的挑战分解为更小、更易于管理的部分。

通俗点说,就是引导模型一步一步思考,最终得到答案。

CoT的原理

CoT的原理目前还比较玄学,通常认为和两个因素有关,一个是模型的体量要超过100b左右,另一个是要在代码数据上做过训练。

那思维链能达到一个什么程度?参考论文中的对比,如下图:

  • 参数越大,思维链效果(蓝线)越明显,在100左右甚至是突变
  • 参数足够大时,思维链效果要超过标准指令(黑线,也就是standard prompting)
  • 参数足够大时,思维链效果接近,甚至超过有监督的效果(橙线)

image.png

看这个图你可能对标准prompt和思维链prompt效果差距体感不是很明显,看论文中的对比,效果是成倍数的提升。

受限于模型和训练方式,数据等等因素,会有一定差异。

image.png

CoT的使用

不再是一步到位得出答案,CoT的本质是让模型,一步一步推理,最终得出答案。

最初的CoT有两种使用姿势

zero-shot CoT

其实大模型是非常聪明的,我们只需要告诉它一步步执行,就能达到基本效果。

问题:两辆汽车从相距500千米的两城同时出发,相向而行.一辆摩托车以每小时80千米的速度在两辆汽车之间不断往返联络.已知这两辆汽车的速度分别是每小时40千米和60千米,求两汽车相遇时,摩托车共行驶了多少千米

正确答案是500/(40+60)*80 = 400千米

我们用gpt3测试一下,先用空prompt测试:

设摩托车共行驶了x千米,那么摩托车往返的次数为x/500次(往返一次表示两辆汽车相遇一次)。
摩托车每次往返的距离为2x千米。
根据题意,第一辆汽车每小时行驶40千米,所以两辆汽车相遇需要的时间为500/40 = 12.5小时。
同样的,第二辆汽车每小时行驶60千米,所以两辆汽车相遇需要的时间也为500/60 = 8.33小时。
因为摩托车以每小时80千米的速度在两辆汽车之间往返,所以在相遇的12.5小时内,摩托车往返的次数为12.5/8.33 = 1.5次(可以往返一次,再返回一次,再往返0.5次)。
那么摩托车共行驶的千米数为1.5 * 2x = 3x千米。
综上所述,摩托车共行驶了3x千米。

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,pormpt如下;

## 设定
根据输入的sql语句,指出存在的问题。

我们用这条sql测试一下:update student set name = 张三

模型给出的回复:

存在的问题是缺少 WHERE 子句来指定更新的行数。这将导致所有学生的姓名都被更改为"张三"。

这个sql明显有两个问题,一个是张三没有用引号,一个是会更新全表数据。但模型只发现了一个问题。

思考:

我们应该如何分析一条sql是否存在问题?大致有如下过程:

  1. 词法分析
  2. 语法分析
  3. 是否有操作风险
  4. 是否有安全风险

基于这种思考步骤,我们再prompt中,添加这样的内容:

## 示例
示例一:
输入:select * from user where a=1 -- name = '张三'
思考过程:
1. 词法分析,不存在问题
2. 语法分析,不存在问题
3. 操作风险:当数据表中行数较多时,会查询出大量数据
4. 安全风险:可能存在注入,因为 -- 后面通常不放置变量条件
输出:
该sql语句存在风险:
1. 当数据表中行数较多时,会查询出大量数据
2. 可能存在注入,因为 -- 后面通常不放置过滤条件

再次用上面的sql:update student set name = 张三语句进行测试,回复如下,能够看到回复会有明显改善,

该sql语句存在问题:
1.  缺少WHERE条件,将会更新所有学生的姓名为"张三",可能导致数据混乱。
1.  缺少引号,应该是"张三"而不是张三

进阶用法:Self-Consistency

Self-Consistency 是在few-shot-cot的基础上做了一些工作。

具体的思路就是,让模型多次生成结果,将出现次数最多的结果作为答案。

或者使用投票的方式来决定用哪个结果。

这也一定程度上解决了大模型的随机性问题。

这在固定结果的场景中通常是非常有用的。

进阶用法: Least-to-Most

如果说上面的Self-Consisty多少有点暴力出奇迹,那Least-to-Most明显更优雅一些。

思路很简单,在解决复杂问题时:

  • 第一步先引导模型把问题拆分成子问题;
  • 第二步逐一回答子问题,并把子问题的回答作为下一个问题回答的上文,直到给出最终答案,

主打一个循序渐进的解决问题。也可以理解为通过few-shot来引导模型给出更合理,更一致的推理思路,再根据这个思路在解决问题。

我们依然用上面验证sql的示例来展示一下操作流程,修改prompt如下:

## 设定
根据输入的sql语句,指出存在的问题。

## 示例
示例一:
输入:select * from user where 1=1 -- name = '张三'
输出:可以拆分这些子问题:"词法分析是否正确","语法分析是否正确","是否存在操作风险","是否存在注入风险"
输入:词法分析是否正确
输出:正确
输入:语法分析是否正确
输出:正确
输入:是否存在操作风险
输出:存在风险,会查询出大量数据
输入:是否存在注入风险
输出:存在注入风险,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 查询中的情况,比如在一个动态构建的 SQL 查询中,一个恶意用户可能在预期的输入之外提供额外的 SQL 语句,从而改变了原始 SQL 查询的意图。

//第六轮:总结答案
user: 总结一下,存在哪些问题
gpt4:
这条 SQL 语句存在两个主要的问题:
1.  词法错误:在 SET 子句中对 name 列赋值时,字符串值 '张三' 没有被单引号括起来。
1.  操作风险:SQL 语句没有使用 WHERE 子句进行条件限制,这可能导致 student 表中所有记录的 name 都被更新为 '张三',很可能是一种误操作。
需要注意轻易不要在没有指定 WHERE 子句的情况下执行 UPDATE 操作,以防对数据库中的大量数据进行无意的修改,除非你确实打算进行全表更新。同时在执行 SQL 语句时要格外注意词法和语法规则,以确保 SQL 语句的正确性。


  • 看起来效果是不是有进步,随着示例的增多,回复的内容也会表现的更好,尤其是对子问题的拆解,示例越多,拆解越准确。

  • Least-to-Most最重要的还是它问题拆分的思路,这在后面被广泛借鉴,例如Agent调用如何拆分每一步的调用步骤,以及如何先思考再生成下一步Action,在这些方案里都能看到Least-to-Most的影子。

思维树 Tree-of-Thoughts (ToT)

传统的CoT,通常有两个问题:

  • 不会探索不同的可能选择分支
  • 无法在节点进行前后向的探索

对于解决复杂问题,提出了一种ToT的推理范式,[论文传送门]。如下图:

image.png

ToT以树的形式组织其解决问题的策略。每个节点都被称为“思维”,是一个连贯的语言序列,是通往最终答案的一步。

ToT包括四个步骤:问题分解、想法生成,状态评价以及搜索算法的选择。

  • 问题分解:第一步首先在于将复杂问题拆解成为k个子问题集,(允许剪枝和回溯)
  • 想法生成:为每个子问题产生若干个方案
    • 对于开放问题,比如写作,可以用大模型生成几个方案
    • 对于封闭问题,比如分类,直接穷举给出方案
  • 搜索算法:深度优先,或者广度优先都可以
  • 状态评价:对于得到的每层结果,根据打分或者评价得出一个最终方案。

个人感受

在特定场景下,尤其是固定类型的问题,它是非常有效的,比如论文中的24点

但是,ToT实现起来很复杂,耗时也是个问题。衡量一下收益和付出,大多数时候,基础版的ToT并不是一个好的选的。

我们用了一个简化的版本,后面会提到。

思维图谱 Graph-of-Thoughts(GoT)

GoT【[论文传送门]】和ToT解决问题的思路差不多,只是GoT,将问题展开成一棵树(DAG)。如下图:

image.png

从图上,不难看出GoT的特点:

  • 想法聚合:下层节点会依赖多个上层节点,即将几个想法融合成一个统一的想法
  • 精炼:单个节点可以进行自我优化
  • 思想的多样性,对比左边的CoT和ToT,GoT能够从现有思想中产生新的思想

个人感受

核心是如何将问题变成DAG树。在实际应用中,除非是固定的场景,否则光靠模型,很难展开的特别好。论文中的几个例子数组排序,文档聚合,统计词频,求集合都比较简单。

总结,GoT变强了,也更复杂了。

思维算法 Algorithm-of-Thoughts(AoT)

ToT和GoT 的缺点很明显:

    1. 需要经过大量的节点,需要大量的llm调用
    1. 要有一个近似全量的遍历过程,尽管可以剪枝

而AoT【[论文传送门]】的思想是,直接找到尽可能正确的路径,而不是全量遍历过程,如下图,看他们的prompt,你大概就能理解了。

  • AoT prompt在示例中,模型在试图模仿这个遍历过程。

image.png

他们的遍历过程的差异如下图:

  • 最右边的AoT,直接尝试找到正确的路径来解决问题,每个节点上都试图找到更有前景的解

image.png

思维框架 Skeleton-of-Thought(SoT)

SoT【[论文传送门]】范式的独特设计主要是为了减少端到端生成延迟的挑战,而不是为了增强大型语言模型(LLM)的推理能力。

他的思路是,先生成推理骨架,再并行补充细节。

论文看的头大,我这里简单举个例子,更容易理解,还是上面的sql验证的例子,我们修改prompt如下:

## 设定
根据输入的sql语句,找到sql可能存在的问题。

## 示例
示例一:
输入:select * from user wher age=18 -- name = '张三'
输出:
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召回
  • prompt微调模型

7. 用了思维链之后,模型耗时增加非常严重怎么办?

从模型的思路上说几点,思路是 只让大模型执行关键流程。方法肯定不限于这些,需要结合你的场景进行链路排查。

  • 多模型融合:在思维链的多轮调用中,一些简单的任务用小模型执行,速度提升比较明显,比如意图识别的场景。
  • 固定场景的节点,可以用代码去执行,比如上文例子中的对sql的词法分析和语法分析。
  • 模型对tool的理解和使用是非常耗时的,如果是固定流程,那就不要挂tool。
  • 能用并行的地方尽量并行,比如流程图的并行结构。
  • 等等

尾语

效果和性能就像鱼和熊掌不可兼得。不同的应用,要在二者间找到对应的平衡点。

在这里插入图片描述

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

  • 13
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值