简介
比尔·盖茨:AI Agent将彻底改变人类生活方式尽管软件在过去几十年里取得了显著的进步,但是,从很多方面来看,它依然有些 “笨拙”。在计算机上完成任务时,你需要告诉设备使用哪个应用程序。例如,你可以用微软 Word 和谷歌文档撰写商业提案,但它们无法帮你发送邮件、分享自拍、分析数据、策划派对或购买电影票。即便是最优秀的网站,也只能片面地了解你的工作、个人生活、兴趣及人际关系,在利用这些信息来为你服务方面能力有限。但在未来五年内,这一切将彻底改变。你不再需要针对不同的任务使用不同的应用。你只需用日常语言告诉你的设备你想要做什么,软件将能够根据你愿意分享的信息量做出个性化的回应,因为它将深入理解你的生活。在不远的将来,任何联网的人都将能夠拥有一个由 AI 驱动的个人助理,其能力将远超现今的技术水平。这种能够理解自然语言并根据对用户的了解来完成多种任务的软件,被称为 “Agent”。PS:各个app 不再直面用户,而是通过接入Agent,由Agent来完成和用户之间的交互,Agent 将成为下一个平台。具象化一下,就是钢铁侠中的Javis。
企业AI智能体、数字化与行业分工现代企业是由人和机器组成的。
- 人:负责完成复杂的、具有不确定性的任务。人是一种高度智能化的智能体。
- 机器(蓝色方形节点):负责完成简单的、确定性的任务。包括软件、设备等,属于工具。 于是,在这两类节点之间,就产生了三种关系:
- 人与人之间:沟通关系。为了完成企业的目标,企业内部的人和人之间需要通过沟通的方式来协作。可能是小团队内紧密的team work,也可能是跨团队之间的沟通,或者是上下级之间的沟通。
- 人与机器之间:人机交互。人和机器之间需要通过产品界面来交互。
- 机器与机器之间:API。机器与机器之间通过API调用来协作,它们之间沟通所使用的,属于机器语言。 人是智能体,机器是工具。AI智能体加入进来以后,它兼具智能体和工具两种属性:
- 半智能体:可以提供知识,且是海量的知识。
- 半工具:可以自动化调用真正的工具。甚至,现在以大模型为基础的AI智能体,还能将一定程度的规划工作也自动化掉。 Agentic可以理解为“具有智能体特性”。一个系统越“具有智能体特性”,就意味着LLM在决定系统行为方面的作用越大。AI智能体可能扮演三种角色:
- AI-0:直接参与业务流程自动化。作为自动化流程中的一个节点,完成以前只能由人完成的工作。需要与企业数据对接。场景举例:从文档中批量抽取信息;文档批量翻译;批量的数据挖掘、预测等。LLM的作用仅仅是提供信息或执行简单的指令。
- AI-1:作为提供知识的Copilot。不直接面向企业的业绩目标,作为人的辅助。需要与人频繁交互,通常以Chat的形式。不需要与企业数据对接。场景:知识问答、总结、文段翻译、数据可视化分析、公开文献阅读、写报告、画图表、写代码,以及其它的各种创作性任务,等等。ChatGPT承担的主要就是这种角色。
- AI-2:作为新型的人机交互接口。提供更自然的交互界面,主要也是Chat的形式。需要与企业数据对接。这一角色承担的任务可大可小。可以是简单的企业私有文档问答,用于替代传统的文档检索;也可以具备非常复杂的逻辑,成为企业大脑,驱动人机协作更有效率。场景:企业私域问答;用自然语言执行命令,查询企业内部数据,驱动自动化流程编排,等等。
- AI-2xx:完全Agentic的系统。 这些系统的行为完全由LLM决定,甚至可以自己设定目标和计划。 理想的AI智能体产品形态,应该是AI-1和AI-2相结合的。用户既能从AI智能体获取企业外部的海量知识和专业数据,又能通过它与背后的企业内部数据或软件工具交互,让更多的工作由AI来完成。
下一代智能体发展的三大关键领域:规划、用户体验和记忆。
- 规划是指 AI 智能体能够预先考虑多个步骤,并确定最佳行动方案的能力。目前,语言模型的规划能力还比较有限,主要依靠以下两种方法来加强:
- 外部提示策略:开发者通过设计特定的提示,引导语言模型进行规划。例如,可以要求模型在执行每个步骤之前,先列出所有可能的步骤并进行评估。
- 流程工程:通过设计预定义的流程图或状态机,将任务分解成多个步骤,并明确每个步骤的执行条件和顺序。这可以帮助语言模型更好地理解任务,并做出更合理的规划。 未来,随着语言模型能力的提升,它们或许能够自主进行更有效的规划,而不再需要外部提示或流程工程的辅助。
- 目前,AI 智能体的用户体验仍有许多需要改进的地方,例如:
- 可靠性不足:由于语言模型的局限性,AI 智能体有时会犯错或无法理解用户的指令。这可能会导致用户感到沮丧和困惑。
- 可控性不足:用户往往无法完全控制 AI 智能体的行为,这可能会导致一些意外的后果。
- 缺乏个性化:现有的 AI 智能体大多缺乏个性化,无法根据用户的特定需求和偏好进行调整。
- 记忆是指 AI 智能体存储和使用信息的能力。记忆对于 AI 智能体完成各种任务都至关重要,例如:
- 程序记忆:记忆如何正确地执行任务,例如如何预订机票或如何撰写电子邮件。
- 个性化记忆:记忆与特定用户相关的信息,例如用户的姓名、喜好、经历等。 目前,AI 智能体的记忆功能还比较简单,主要依靠以下两种方式实现:存储在数据库中:将信息存储在外部数据库中,并在需要时进行检索。嵌入语言模型中:将信息嵌入语言模型的参数中,使模型能够在生成文本时使用这些信息。
简单使用LLM 是不够的
纯问答的场景只是大模型落地的第一步,还有许许多多场景是需要AI大模型与现实世界进行“连接”才能完成的。我们并不需要一个只知道聊天的机器人“玩具”,我们需要的正是这种“有手有脚”的大模型、能做事情的大模型。比如客户的问题是“退款”,那么客户想要执行退款这个操作,而不是大模型提供一堆退款的规则和步骤,因为绝大多数的人对于很长的文字是很难完全有耐心能阅读下去的。试想一下,当你躺在家里的床上准备睡觉的时候,突然发现窗帘没有关上,如果这时候跟大模型说“请帮我关闭我家的窗帘”,其实我们并不想听到大模型回复了一大段的“关闭窗帘的步骤”,如果大模型真的像一个人一样能够完成这件事情,那该有多酷!甚至当你说出一些稍微复杂指令,比如“窗帘不用全部关上,给我留一个缝”,如果大模型也能“理解”并且能自动将“留一个缝”这种自然语言转换为控制“窗帘闭合百分比”这样的一个量化参数并且真正将窗帘关闭到合适位置的时候,那么大模型才真正能在各行各业的落地中带来一波大的浪潮。
目前的大模型一般都存在知识过时、逻辑计算能力低等问题,通过Agent访问工具,可以去解决这些问题。Agent是指能够感知环境、做出决策和采取行动的实体。本质上还是prompt工程,通过Prompt去驱动模型进行 计划和工具调用。PS:你知道一个工具的存在,约等于你会调用这个工具;你会调用这个工具,约等于你会学习使用这个工具;会学习这个工具,约等于你已经会用这个工具;所以,你知道工具的存在,约等于你能把这件事做出来。搜索高于学习, 学习高于熟练。
吴恩达:目前,我们使用大语言模型的主要方式是一种non-agentic工作流程,即您输入一个提示,模型就生成一个回答。这有点像让一个人坐下来一次性从头到尾编写一篇文章,而不允许使用退格键,尽管这样做很难,但大语言模型的表现出奇地出色。相比之下,代理工作流程看起来是这样的:首先,让人工智能大语言模型写一个文章大纲,如果需要进行网络研究就先做研究,然后写出第一稿,然后阅读并思考需要修订的部分,再修改这一稿,如此循环往复、迭代多次。很多人没有意识到,这种做法可以带来显著的改进效果。我自己在使用这些代理工作流程时也感到非常惊讶,它们工作得如此之好。研究发现,GPT-3.5使用零样本提示时只有48%的正确率,GPT-4提高到了67%。但如果在GPT-3.5上使用一个代理工作流程,它的表现实际上比GPT-4还要好。如果在GPT-4上使用代理工作流程,它的表现也非常出色。这意味着采用代理工作流程对于构建应用程序至关重要。不过我们需要改变一种习惯,那就是习惯了在提示语言模型后立即获得响应。在代理工作流程中,我们需要学会能够耐心等待几分钟甚至几个小时,才能得到响应,就像我们交代任务给人时需要适当地等待一段时间再进行检查一样。
Agent不只是一个工具
- 一开始大家玩 Prompt 工程(把大模型当做工具来调用,工具模式),接着是Prompt Chain或Flow,再到Agent,多Agent,很清晰的一个脉络架构。
- 我们回到 Agent 这个概念上,实际上,人类是这个星球上最强大的 Agent。Agent是一个能感知并自主地采取行动的实体,这里的自主性极其关键,Agent要能够实现设定的目标,其中包括具备学习和获取知识的能力以提高自身性能。Agent 的复杂程度各不相同,一个简单的恒温器可以是一个 Agent,一个大型的国家或者一个生物群体也可能是个 Agent。感知环境、自主决策、具备行动能力,设定明确的目标和任务,适应环境及学习能力,都是 Agent 的关键特点。
- 我们认为Agent技术是未来实现社会全面自动化的关键技术。在大模型出现之前,自动化更多的是一些偏结构化固定模式环境中通过实现固定算法流程来完成自动化任务,而大模型智能体的通用性带来了灵活性,使其可能应对人类在脑力劳动中面临的各种复杂长尾任务,进一步实现体力和脑力任务的全面自动化。PS:LLM本质是文字接龙,看你让大模型接什么,如果使用大模型接出来的东西。有点一生二、二生三、三生万物的意思,就好像无论汽油机、还是电动机,基本的动力输出形式是转圈圈,但是经过一些机械传导,可以转为各种机械运动形式:水平、垂直(打夯机)、椭圆运动等等,简单机械运动组合起来可以进行复杂机械运动比如纺织机,进而推动了大部分手工劳动的自动化。
- 在通用人工智能(AGI)的漫长旅途中,大模型虽显强大,仍存在着显著的技术天花板。许多人开始探索如何挖掘大模型在大任务执行能力上的可能性,其中一个基本策略就是能够分解和组合。例如,经典的 MapReduce 模式可以将一个大型文本进行摘要,因为它的上下文有限,一种解决办法是扩大 context 的范围。另一个解决方案是,在有限的 context 中,我们先将文本拆分成小片段,对每个片段进行摘要,然后再将其组合,从而得出结果。大家也发现大模型直接给出答案似乎并不靠谱,那么是否可以让它像人类一样,一步一步思考呢?毕竟,人类在解决问题时,也是逐渐构建解决方案,而并非立即给出答案。因此,开始出现了一系列的尝试解法,比如思维链、多思维链、思维树和思维图等。上述的讨论主要是任务分解和组合,他们尽管强大,却不能与外界进行互动,这就不得不讲到反馈机制了。反馈是整个控制论的基石,也是动物体从诞生之初就具备的基本能力。最经典的方法实际就是 ReACT,ReACT让大模型先进行思考,思考完再进行行动,然后根据行动的结果再进行观察,再进行思考,这样一步一步循环下去。这种行为模式基本上就是人类这样的智能体主要模式。
- 众人熟知的认知飞轮,感知、认知、决策、行动,今天的人工智能代理更像是基于这个认知飞轮构建的。但是从本质上,人类智能远比这复杂。
- 智能究竟是什么?人类对世界进行建模,把世界以实体、关系、属性描绘出来。然而,这也是我们认知的极限,我们只能理解一个对象化的世界,非对象化的世界我们无法理解。比如,当我们探索量子的时候,我们还常常用对事物进行对象化的方式去理解,但是发现我们的理解力有时候是有限的,因为量子世界的真相超出了人类认知能力的范围,我们智能使用低维空间的投影去推断它,就像我们无法在三维世界去想象十一维世界的样子。
- 其实在大模型Agent技术出现之前,人们就已经意识到,试图集成各种深度学习模型以实现人工普遍智能(AGI)并不够,还需要更高层次的认知模型。Agent都必须对世界有准确的理解才能做出正确的决策。当模型不能正确运行时,决策就会出错;只有当世界模型构建的正确,才能选择正确的模型,进而做出正确的决策。
- 今天计算机领域的工程实践中,人们更多采用的是面向过程架构,无论是接口、函数、UI界面,还是组件,又或者是一个应用程序,都是以接口的形式存在的。而这个接口实质上是一种被调用的子流程,借此过程的完成,我们希望执行结果符合我们的预期,但程序并不为结果负责。它解决的是过程和流程问题,系统内没有目标的概念。当然,也存在一些以目标导向为核心理念的的软件工程,例如声明式编程,它只需要你描述你想要什么,而无需关心执行的过程,像HTML和SQL便是其经典例子。在这样的架构下,程序能够自行寻找达成目标的方法。然而问题在于,这种面向目标的架构只能应用于垂直领域,而无法普遍应用到所有领域,只有在特定的领域内才能发挥作用,这就限制了它的应用范围。总的来说,尽管面向目标架构在计算机领域有一席之地,但由于其只能在特定领域发挥作用,而无法解决所有领域的问题,因此它的应用还是有所限制,更多出现在特定的DSL(领域特定语言)中,这种架构的确也发挥了巨大的作用。在软件工程的范式迁移中,我们发现面向过程架构与面向目标架构之间的重要区别点:随着人类的生产方式的变化,软件工程可能正逐步演化为智能体工程(Agent Engineering);以前我们主导的生产方式是人类处于中心位,AI做辅助。而未来可能会变成以 AI 为中心,人类变为辅助。由此,整个产品形态和平台的构成可能会发生这样的转变。
智能体是一个利用LLM来决定应用程序控制流程的系统,智能体的基本概念是在没有人工定义工作流(Workflow)的情况下,利用外部工具或功能,选择要执行的一系列操作,在没有人类控制的情况下独立运行(自主性,无需持续的人工干预或输入)。对于 toB 产品,智能体能够解决功能点繁多、使用链路冗长、使用方法复杂难上手等问题。从技术角度来看,智能体通过大模型理解用户意图并生成结构化描述,进而执行相关操作。因此,智能体在实际应用中扮演着至关重要的角色,成为了连接大模型和现有应用的桥梁。
Agent和过去程序代码不一样的地方就是它或多或少是有一些智能的,和过去一个函数或者应用写好之后就处于不可改动的情况不同。也就是意味着,利用Agent或者Multi-Agent实现的应用程序是有可能实现进化的。传统的应用程序不过是为Agent提供了一个基本的”环境”,Agent可以通过与人(“用户”)的交互以及环境的互动过程中,通过数据和反馈来感知外部,并且不断生成代码和使用工具来优化应用。例如,过去人们购买的应用软件都需要等待厂家的升级来进行版本的改动和调整,但是基于Agent的应用程序就有可能通过自然语言来构筑新的功能,而无需等待版本的更新。也就是说,应用应该是”成长”出来。如果将来LLM能够收集数据来更新自己,那么人类就真的变成了超级智能的引导程序。
规划与COT
- 什么是“语言智能”?语言智能可以被理解为“使用基于自然语言的概念对经验事物进行‘理解’以及在概念之间进行‘推理’的能力”,随着参数量的飞升,以 Transformer 为基础架构的大规模语言模型以 “Chat” 的方式逐渐向人们展现出了它的概念理解与概念推理的能力。直观上,作为“语言模型”的大模型具备概念理解能力并不难理解,但是仅仅像 Word2vec 一样只能得到“国王”与“男人”的“距离”更近的结论对于语言智能而言必然远远不够。真正引发人们对大模型逼近“语言智能”无限遐想的,在于大模型展现出的概念推理能力。推理,一般指根据几个已知的前提推导得出新的结论的过程,区别于理解,推理一般是一个“多步骤”的过程,推理的过程可以形成非常必要的“中间概念”,这些中间概念将辅助复杂问题的求解。
- 2022 年,在 Google 发布的论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》中首次提出,通过让大模型逐步参与将一个复杂问题分解为一步一步的子问题并依次进行求解的过程可以显著提升大模型的性能。而这一系列推理的中间步骤就被称为思维链(Chain of Thought)。区别于传统的 Prompt 从输入直接到输出的映射
<input——>output>
的方式,CoT 完成了从输入到思维链再到输出的映射,即<input——>reasoning chain——>output>
。如果将使用 CoT 的 Prompt 进行分解,可以更加详细的观察到 CoT 的工作流程。- 虽然与传统的直进直出的Prompt相比,COT能让模型带来更多的思考(其实只是更多tokens自回归带来的准确性提升)。但是它很多时候的结果产出与我们人类的预期还是会有偏差,抽奖不可避免。
- 在许多 Agent 需要处理的任务中,Agent 的“先天知识”并不包含解决任务的直接答案,因此 Agent 需要在一系列与外部环境的交互循环中,制定计划,做出决策,执行行动,收到反馈……在一整个计划、决策与控制的循环中,大模型需要具备“感知”,“记忆”与“推理”的能力。无论是环境的反馈,还是人类的指令,Agent 都需要完成一个对接收到的信息进行“理解”,并依据得到的理解进行意图识别,转化为下一步任务的过程。而使用 CoT 可以大大帮助模型对现有输入进行“感知”,譬如,通过使用“Answer: Let’s think step by step. I see $$, I need to …”的 Prompt,可以让模型逐步关注接收到的信息,对信息进行更好的理解。
ReACT框架的一个关键特点是其任务拆解模块,能够将复杂的任务拆解成一系列更小、更明确的子任务,这些子任务更容易被模型理解和执行,让模型不再“消化不良”。一篇大模型Agent工具使用全面研究综述任务规划的方法:
- 无需调整的方法(Tuning-free Methods):利用LLMs的内在能力,通过少量示例或零示例提示来实现任务规划。例如,使用CoT(Chain of Thought)或ReACT等框架来引导LLMs逐步思考和规划。
- 基于调整的方法(Tuning-based Methods):通过在特定任务上微调LLMs来提高任务规划能力。例如,Toolformer等方法通过微调来增强LLMs对工具使用的意识和能力。
在技术理念上,我们认为智能体的应用主要有两种场景。
- 比较开放性的问题,比如制定一个旅行计划,这类问题的编排可以用智能体AutoPlan
- 但绝大多数场景是有固定流水线的,尤其在工业尤为明显。这类确定性的领域,需要有智能体的确定性编排。
工具选择的分类:
- 基于检索器的工具选择(Retriever-based Tool Selection):当工具库庞大时,使用检索器(如TF-IDF、BM25等)来从大量工具中检索出与子问题最相关的前K个工具。这种方法侧重于通过关键词匹配和语义相似性来快速缩小工具选择范围。
- 基于LLM的工具选择(LLM-based Tool Selection):当工具数量有限或者在检索阶段已经缩小了工具范围时,可以直接将工具描述和参数列表与用户查询一起提供给LLM。
工具选择的方法:
- 无需调整的方法(Tuning-free Methods):利用LLMs的上下文学习能力,通过策略性提示来增强工具选择能力。例如,通过链式思维(Chain of Thought)或ReACT框架来引导LLMs进行推理和行动。
- 基于调整的方法(Tuning-based Methods):通过在工具学习数据集上微调LLMs的参数来提高工具选择的能力。
工具学习范式:
- 没有反馈的计划制定。一步任务解决,这种范式涉及到在收到用户问题后,LLMs立即分析用户请求,理解用户意图,并规划出所有需要的子任务来解决问题。在这个过程中,LLMs会直接生成一个基于选定工具返回结果的响应,而不会考虑过程中可能出现的错误或根据工具的反馈调整计划。
- 有反馈的计划制定。这种范式允许LLMs与工具进行迭代交互,不预先承诺一个完整的任务计划。相反,它允许基于工具的反馈逐步调整子任务,使LLMs能够一步步地解决问题,并根据工具返回的结果不断完善计划。这种方法增强了LLMs的问题解决能力,因为它允许模型在响应工具反馈时进行适应和学习。
工具调用的步骤:
- 参数提取:LLMs必须能够从用户查询中提取出符合工具描述中指定格式的参数。
- 调用工具:使用提取的参数向工具服务器发送请求,并接收响应。
现有方案如CoT和基于分解的提示,都有擅长的任务类型,适合作为独立的原子模块,不具有普适性;大模型自动推理?谷歌等发布SELF-DISCOVER!
猴版实现
class Agent:
def __init__(self, system=""):
self.system = system
self.messages = []
if self.system:
self.messages.append({"role": "system", "content": system})
def __call__(self, message):
self.messages.append({"role": "user", "content": message})
result = self.execute()
self.messages.append({"role": "assistant", "content": result})
return result
def execute(self):
completion = client.chat.completions.create(
model="gpt-4o",
temperature=0,
messages=self.messages)
return completion.choices[0].message.content
def query(question, max_turns=5): # 驱动Agent执行
i = 0
bot = Agent(prompt)
next_prompt = question
while i < max_turns:
i += 1
result = bot(next_prompt)
print(result)
actions = [
action_re.match(a)
for a in result.split('\n')
if action_re.match(a)
]
if actions:
# There is an action to run
action, action_input = actions[0].groups()
if action not in known_actions:
raise Exception("Unknown action: {}: {}".format(action, action_input))
print(" -- running {} {}".format(action, action_input))
observation = known_actions[action](action_input)
print("Observation:", observation)
next_prompt = "Observation: {}".format(observation)
else:
return
question = """我有两只狗,一只边境牧羊犬和一只苏格兰梗犬。
它们的总体重是多少"""
query(question)
langchain使用
在chain中,操作序列是硬编码的。智能体通过将LLM与动作列表结合,自动选择最佳动作序列,从而实现自动化决策和行动。Agent在LangChain框架中负责决策制定以及工具组的串联,可以根据用户的输入决定调用哪个工具。通过精心制定的提示,我们能够赋予代理特定的身份、专业知识、行为方式和目标。提示策略为 Agent 提供了预设模板,结合关键的指示、情境和参数来得到 Agent 所需的响应。具体的说,Agent就是将大模型进行封装来简化用户使用,根据用户的输入,理解用户的相应意图,通过action字段选用对应的Tool,并将action_input作为Tool的入参,来处理用户的请求。当我们不清楚用户意图的时候,由Agent来决定使用哪些工具实现用户的需求。
自定义tool 实现
from langchain.tools import BaseTool
# 天气查询工具 ,无论查询什么都返回Sunny
class WeatherTool(BaseTool):
name = "Weather"
description = "useful for When you want to know about the weather"
def _run(self, query: str) -> str:
return "Sunny^_^"
async def _arun(self, query: str) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("BingSearchRun does not support async")
# 计算工具,暂且写死返回3
class CustomCalculatorTool(BaseTool):
name = "Calculator"
description = "useful for when you need to answer questions about math."
def _run(self, query: str) -> str:
return "3"
async def _arun(self, query: str) -> str:
raise NotImplementedError("BingSearchRun does not support async")
# 这里使用OpenAI temperature=0,temperature越大表示灵活度越高,输出的格式可能越不满足我们规定的输出格式,因此此处设置为0
llm = OpenAI(temperature=0)
tools = [WeatherTool(), CalculatorTool()]
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
agent.run("Query the weather of this week,And How old will I be in ten years? This year I am 28")
# 执行结果
I need to use two different tools to answer this question
Action: Weather
Action Input: This week
Observation: Sunny^_^
Thought: I need to use a calculator to answer the second part of the question
Action: Calculator
Action Input: 28 + 10
Observation: 3
Thought: I now know the final answer
Final Answer: This week will be sunny and in ten years I will be 38.
LangChain Agent中,内部是一套问题模板(langchain-ai/langchain/libs/langchain/langchain/agents/chat/prompt.py):
PREFIX = """Answer the following questions as best you can. You have access to the following tools:"""
FORMAT_INSTRUCTIONS = """Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question"""
SUFFIX = """Begin!
Question: {input}
Thought:{agent_scratchpad}"""
这个提示词就是 Agent 之所以能够趋动大模型,进行思考 - 行动 - 观察行动结果 - 再思考 - 再行动 - 再观察这个循环的核心秘密。有了这样的提示词,模型就会不停地思考、行动,直到模型判断出问题已经解决,给出最终答案,跳出循环。
通过这个模板,加上我们的问题以及自定义的工具,会变成下面这个样子(# 后面是增加的注释)
Answer the following questions as best you can. You have access to the following tools: # 尽可能的去回答以下问题,你可以使用以下的工具:
Calculator: Useful for when you need to answer questions about math.
# 计算器:当你需要回答数学计算的时候可以用到
Weather: useful for When you want to know about the weather # 天气:当你想知道天气相关的问题时可以用到
Use the following format: # 请使用以下格式(回答)
Question: the input question you must answer # 你必须回答输入的问题
Thought: you should always think about what to do
# 你应该一直保持思考,思考要怎么解决问题
Action: the action to take, should be one of [Calculator, Weather] # 你应该采取[计算器,天气]之一
Action Input: the input to the action # 动作的输入
Observation: the result of the action # 动作的结果
... (this Thought/Action/Action Input/Observation can repeat N times) # 思考-行动-输入-输出 的循环可以重复N次
Thought: I now know the final answer # 最后,你应该知道最终结果了
Final Answer: the final answer to the original input question # 针对于原始问题,输出最终结果
Begin! # 开始
Question: Query the weather of this week,And How old will I be in ten years? This year I am 28 # 问输入的问题
Thought:
我们首先告诉 LLM 它可以使用的工具,在此之后,定义了一个示例格式,它遵循 Question(来自用户)、Thought(思考)、Action(动作)、Action Input(动作输入)、Observation(观察结果)的流程 - 并重复这个流程直到达到 Final Answer(最终答案)。如果仅仅是这样,openai会完全补完你的回答,中间无法插入任何内容。因此LangChain使用OpenAI的stop参数,截断了AI当前对话。"stop": ["\nObservation: ", "\n\tObservation: "]
。做了以上设定以后,OpenAI仅仅会给到Action和 Action Input两个内容就被stop停止。以下是OpenAI的响应内容:
I need to use the weather tool to answer the first part of the question, and the calculator to answer the second part.
Action: Weather
Action Input: This week
这里从Tools中找到name=Weather的工具,然后再将This Week传入方法。具体业务处理看详细情况。这里仅返回Sunny。 由于当前找到了Action和Action Input。 代表OpenAI认定当前任务链并没有结束。因此向tool请求后拼接结果:Observation: Sunny 并且让他再次思考Thought。开启第二轮思考:下面是再次请求的完整请求体:
Answer the following questions as best you can. You have access to the following tools:
Calculator: Useful for when you need to answer questions about math.
Weather: useful for When you want to know about the weather
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [Calculator, Weather]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: Query the weather of this week,And How old will I be in ten years? This year I am 28
Thought: I need to use the weather tool to answer the first part of the question, and the calculator to answer the second part.
Action: Weather
Action Input: This week
Observation: Sunny^_^
Thought:
同第一轮一样,OpenAI再次进行思考,并且返回Action 和 Action Input 后,再次被早停。
I need to calculate my age in ten years
Action: Calculator
Action Input: 28 + 10
由于计算器工具只会返回3,结果会拼接出一个错误的结果,构造成了一个新的请求体进行第三轮请求:
Answer the following questions as best you can. You have access to the following tools:
Calculator: Useful for when you need to answer questions about math.
Weather: useful for When you want to know about the weather
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [Calculator, Weather]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: Query the weather of this week,And How old will I be in ten years? This year I am 28
Thought: I need to use the weather tool to answer the first part of the question, and the calculator to answer the second part.
Action: Weather
Action Input: This week
Observation: Sunny^_^
Thought:I need to calculate my age in ten years
Action: Calculator
Action Input: 28 + 10
Observation: 38
Thought:
此时两个问题全都拿到了结果,根据开头的限定,OpenAi在完全拿到结果以后会返回I now know the final answer。并且根据完整上下文。把多个结果进行归纳总结:下面是完整的相应结果:
I now know the final answer
Final Answer: I will be 38 in ten years and the weather this week is sunny.
可以看到。ai严格的按照设定返回想要的内容,并且还以外的把28+10=3这个数学错误给改正了。通过 verbose=True
可以动态查看上述过程。 PS: 通过prompt 引导llm 进行文字接龙,通过解析文字接龙来进行tool 的调用。
根据输出再回头看agent的官方解释:An Agent is a wrapper around a model, which takes in user input and returns a response corresponding to an “action” to take and a corresponding “action input”. 本质上是通过和大模型的多轮对话交互来实现的(对比常规聊天时的一问一答/单轮对话), 不断重复“Action+ Input -> 结果 -> 下一个想法”,一直到找到最终答案。通过特定的提示词引导LLM模型以固定格式来回复,LLM模型回复完毕后,解析回复,这样就获得了要执行哪个tool,以及tool的参数。然后就可以去调tool了,调完把结果拼到prompt中,然后再让LLM模型根据调用结果去总结并回答用户的问题。
大多数 Agent 主要是在某种循环中运行 LLM。目前,我们使用的唯一方法是 AgentExecutor。我们为 AgentExecutor 添加了许多参数和功能,但它仍然只是运行循环的一种方式。langgraph是一个新的库,旨在创建语言 Agent 的图形表示。这将使用户能够创建更加定制化的循环行为。用户可以定义明确的规划步骤、反思步骤,或者轻松设置优先调用某个特定工具。
原理
在 Agent 应用的开发和实践中,核心挑战之一是如何优雅地实现一个可控的循环(Loop)机制。这个循环机制不仅需要能够自动化地执行任务,还要能够在执行过程中根据反馈进行自我调整和优化(Loop+Feedback )。通过这种方式,LLM 能够模仿人类解决问题的基本方法论,如 PDCA(计划-执行-检查-行动)循环,从而更有效地拆解和解决问题。
认知框架Cognitive Architecture
AgentType 对应一个Agent class,对应一个prompt(又是prompt 起了关键作用),AgentType 有以下几种选择
- zero-shot ReAct,完全依靠对所用到的tools 的说明书来理解和使用tools,理论上支持无限多个。
- Structured tool chat,跟第一个不同的地方在于接收一个结构化的dict 作为参数且能记住上下文。
- OpenAI functions,OpenAI 在大模型层面针对 API的调用做了训练,相当于帮大家做了SFT,可以想象效果必然好。
- conversational,类似于第一、二类型,针对对话场景做了优化,比如聊天记录、聊天轮次等meta-data
- self-ask,通过自问自答的方式把大问题拆解成小问题之后再组成最终的单子。
ReAct是 Shunyu Yao 等人在 ICLR 2023 会议论文《ReAct: Synergizing Reasoning and Acting in Language Models》中提出的,一个关键启发在于:大语言模型可以通过生成推理痕迹和任务特定行动来实现更大的协同作用。具体来说,就是引导模型生成一个任务解决轨迹:观察环境 - 进行思考 - 采取行动,也就是观察 - 思考 - 行动。那么,再进一步进行简化,就变成了推理 - 行动,是一种将推理和行动相结合的思考链模式(PS:知行合一?),以交错的方式产生与任务相关的语言推理轨迹和行动。ReAct 框架会提示 LLMs 为任务生成推理轨迹和操作,这使得代理能系统地执行动态推理来创建、维护和调整操作计划,同时还支持与外部环境(例如 Google 搜索、Wikipedia)的交互,以将额外信息合并到推理中。PS:使用LLM来做ifelse,ReAct提示大型语言模型为给定任务生成口头推理历史步骤和操作。这些提示由少量的上下文示例组成,这些示例指导模型的思考和操作生成。
与CoT推理一样,ReAct 也是一种提示工程方法,它使用少量学习来教模型如何解决问题。CoT 被认为是模仿人类如何思考问题,ReAct 也包括了这个推理元素,但它更进一步,允许Agent操作文本,让它与环境互动。人类使用语言推理来帮助我们制定策略并记住事情,但也可以采取行动来获得更多的信息并实现目标。这就是 ReAct 的基础(PS:知行合一?)。ReAct 提示包括行动的例子、通过行动获得的观察结果,以及人类在过程中各个步骤中转录的思想(推理策略)。LLM 学习模仿这种交叉思考和行动的方法,使其成为其环境中的Agent。
一定要记住,观察结果不是由 LLM 生成的,而是由环境生成的,环境是一个单独的模块,LLM 只能通过特定的文本操作与之交互。因此,为了实现 ReAct,需要:
- 一种环境,它采取一个文本操作, 从一组可以根据环境的内部状态改变的潜在操作中返回一个文本观察。
- 一个输出解析器框架,一旦Agent编写了一个有效的操作,它就停止生成文本,在环境中执行该操作,并返回观察结果, 一般是将其追加到目前生成的文本中,并用该结果提示 LLM。
- 人工产生的示例,混合了思想,行动和观察,在环境中可以使用few-shot,例子的数量和细节取决于目标和开发者的设计
ReAct Agent 的一般提示词结构:
前缀:引入工具的描述
格式:定义React Agent的输出格式
问题:用户输入的问题
思考:React Agent推理如何行动
行动:需要使用的工具
行动输入:工具所需输入
观察:行动执行后得到的结果
(按需重复:思考-行动-观察流程)
终点推理:产生最终结论
最后回答:问题的答案
stop token
How to Get Better Outputs from Your Large Language ModelIt is especially useful to design a stopping template in a few-shot setting so the model can learn to stop appropriately upon completing an intended task. Figure shows separating examples with the string “===” and passing that as the stop word.我们知道一般 LLM 都会长篇大论,说一大堆废话,我们希望 LLM 在返回了我们需要的信息后就停止输出,这里就需要用到stop参数,这个参数是一个列表,列表中的每个元素都是一个字符串,代表了 LLM 输出中的某一句话,当 LLM 输出中包含了这句话时,LLM 就会停止输出,这样我们就可以只获取到我们需要的信息了
langchain源码
Agent 可以看做在Chain的基础上,进一步整合Tool 的高级模块。与Chain 相比,Agent 具有两个新增的能力:思考链和工具箱。能根据环境变化更新计划,使决策更加健壮。思考链释放了大模型的规划和调度潜能,是Agent的关键创新,Agent 定义了工具的标准接口,以实现无缝集成。与Chain 直接调用模块/Runnable相比,它只关心tool 输入和输出,tool内部实现对Agent 透明,工具箱大大扩展了Agent的外部知识来源,使其离真正的通用智能更近一步。
LangChain关键组件
- 代理(Agent):这个类决定下一步执行什么操作。它由一个语言模型和一个提示(prompt)驱动。提示可能包含代理的性格(也就是给它分配角色,让它以特定方式进行响应)、任务的背景(用于给它提供更多任务类型的上下文)以及用于激发更好推理能力的提示策略(例如 ReAct)。LangChain 中包含很多种不同类型的代理。PS: 一般情况下,一个Agent 像Chain一样,都会对应一个prompt。
- 工具(Tools):工具是代理调用的函数。这里有两个重要的考虑因素:一是让代理能访问到正确的工具,二是以最有帮助的方式描述这些工具。如果你没有给代理提供正确的工具,它将无法完成任务。如果你没有正确地描述工具,代理将不知道如何使用它们。LangChain 提供了一系列的工具,同时你也可以定义自己的工具,或者将函数转换为tool。
class BaseTool(RunnableSerializable[Union[str, Dict], Any]): name: str description: str def invoke(self, input: Union[str, Dict],config: Optional[RunnableConfig] = None,**kwargs: Any,) -> Any: ... return self.run(...) class Tool(BaseTool): description: str = "" func: Optional[Callable[..., str]] coroutine: Optional[Callable[..., Awaitable[str]]] = None
- 代理执行器(AgentExecutor):代理执行器是代理的运行环境,它调用代理并执行代理选择的操作。执行器也负责处理多种复杂情况,包括处理代理选择了不存在的工具的情况、处理工具出错的情况、处理代理产生的无法解析成工具调用的输出的情况,以及在代理决策和工具调用进行观察和日志记录。AgentExecuter负责迭代运行Agent,直至满足设定的停止条件,这使得Agent能够像生物一样循环处理信息和任务。
AgentExecutor由一个Agent和Tool的集合组成。AgentExecutor负责调用Agent,获取返回(callback)、action和action_input,并根据意图将action_input给到具体调用的Tool,获取Tool的输出,并将所有的信息传递回Agent,以便猜测出下一步需要执行的操作。AgentExecutor.run也就是chain.run ==> AgentExecutor/chain.__call__ ==> AgentExecutor._call()
和逻辑是 _call 方法,核心是 `output = agent.plan(); tool=xx(output); observation = tool.run();
def initialize_agent(tools,llm,...)-> AgentExecutor:
agent_obj = agent_cls.from_llm_and_tools(llm, tools, callback_manager=callback_manager, **agent_kwargs)
AgentExecutor.from_agent_and_tools(agent=agent_obj, tools=tools,...)
return cls(agent=agent, tools=tools, callback_manager=callback_manager, **kwargs)
# AgentExecutor 实际上是一个 Chain,可以通过 .run() 或者 _call() 来调用
class AgentExecutor(Chain):
agent: Union[BaseSingleActionAgent, BaseMultiActionAgent]
tools: Sequence[BaseTool]
"""Whether to return the agent's trajectory of intermediate steps at the end in addition to the final output."""
max_iterations: Optional[int] = 15
def _call(self,inputs: Dict[str, str],...) -> Dict[str, Any]:
while self._should_continue(iterations, time_elapsed):
next_step_output = self._take_next_step(name_to_tool_map,inputs,intermediate_steps,...)
# 返回的数据是一个AgentFinish类型,表示COT认为不需要继续思考,当前结果就是最终结果,直接将结果返回给用户即可;
if isinstance(next_step_output, AgentFinish):
return self._return(next_step_output, intermediate_steps, run_manager=run_manager)
if len(next_step_output) == 1:
next_step_action = next_step_output[0]
# See if tool should return directly
tool_return = self._get_tool_return(next_step_action)
if tool_return is not None:
return self._return(tool_return, intermediate_steps, run_manager=run_manager)
iterations += 1
time_elapsed = time.time() - start_time
return self._return(output, intermediate_steps, run_manager=run_manager)
def _take_next_step(...):
# 调用LLM决定下一步的执行逻辑
output = self.agent.plan(intermediate_steps,**inputs,...)
if isinstance(output, AgentFinish): # 如果返回结果是AgentFinish就直接返回
return output
if isinstance(output, AgentAction): # 如果返回结果是AgentAction,就根据action调用配置的tool
actions = [output]
result = []
for agent_action in actions:
tool = name_to_tool_map[agent_action.tool]
observation = tool.run(agent_action.tool_input,...)
result.append((agent_action, observation)) # 调用LLM返回的AgentAction和调用tool返回的结果(Obversation)一起加入到结果中
return result
Agent.plan() 可以看做两步:
- 将各种异构的历史信息转换成 inputs,传入到 LLM 当中;
- 根据 LLM 生成的反馈,采取决策。LLM 生成的回复是 string 格式,langchain 中ZeroShotAgent 通过字符串匹配的方式来识别 action。
因此,agent 能否正常运行,与 prompt 格式,以及 LLM 的 ICL 以及 alignment 能力有着很大的关系。
- LangChain主要是基于GPT系列框架进行设计,其适用的Prompt不代表其他大模型也能有相同表现,所以如果要自己更换不同的大模型(如:文心一言,通义千问…等)。则很有可能底层prompt都需要跟著微调。
- 在实际应用中,我们很常定期使用用户反馈的bad cases持续迭代模型,但是Prompt Engeering的工程是非常难进行的微调的,往往多跟少一句话对于效果影响巨大,因此这类型产品达到80分是很容易的,但是要持续迭代到90分甚至更高基本上是很难的。
# 一个 Agent 单元负责执行一次任务
class Agent(...):
llm_chain: LLMChain
allowed_tools: Optional[List[str]] = None
# agent 的执行功能在于 Agent.plan()
def plan(self,intermediate_steps: List[Tuple[AgentAction, str]],callbacks: Callbacks = None,**kwargs: Any,) -> Union[AgentAction, AgentFinish]:
# # 将各种异构的历史信息转换成 inputs,传入到 LLM 当中
full_inputs = self.get_full_inputs(intermediate_steps, **kwargs)
# 根据 LLM 生成的反馈,采取决策
full_output = self.llm_chain.predict(callbacks=callbacks, **full_inputs)
# full_output 是纯文本,通过断点调试可以看到,真的就是靠正则表达式提取tool的名称
# 最后的输出 AgentAction 中会包括:需要使用的 tool,使用该 tool 时候,对应的执行命令。
return self.output_parser.parse(full_output)
有人希望通过一些开源的 LLM 来实现 ReAct Agent,但实际开发过程中会发现开源低参数(比如一些 6B、7B 的 LLM)的 LLM 对于提示词的理解会非常差,根本不会按照提示词模板的格式来输出(例如不按Action: xx Action Input: xx
返回),这样就会导致我们的 Agent 无法正常工作,所以如果想要实现一个好的 Agent,还是需要使用好的 LLM,目前看来使用gpt-3.5模型是最低要求。
代码解释器
ChatGLM3 的代码解释器(Code Interpreter)实现原理:背后的原理其实跟工具调用是一样的。无非就是将普通的函数替换成代码解释器,大模型预测的结果不再是函数的入参,而是具体的代码,根据这些代码我们调用代码解释器执行,然后在界面上面支持显示代码执行的结果。
要了解大模型是如何学会使用代码解释器的,就要先看训练样本是如何构造的。下面是一个官方提供的例子:
<|system|> 你是一位智能AI助手,你叫ChatGLM3,你连接着一台电脑,但请注意不能联网。在使用Python解决任务时,你可以运行代码并得到结果,如果运行结果有错误,你需要尽可能对代码进行改进。你可以处理用户上传到电脑上的文件,文件默认存储路径是/mnt/data/。 <|user|> 帮我画一个爱心 <|assistant|>interpreter ```python import numpy as np import matplotlib.pyplot as plt # 爱心形状的参数方程 def heart(t): x = 16 * np.sin(t) ** 3 y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t) return x, y t = np.linspace(0, 2 * np.pi, 1000) x, y = heart(t) plt.figure(figsize=(6, 6)) plt.plot(x, y, color='red') plt.axis('equal') plt.axis('off') plt.show() ``` <|observation|> ```result 【image】 ``` <|assistant|> 这是一个爱心形状。我使用了参数方程来描述这个形状,并使用matplotlib进行了绘制。如果您有任何其他需求或问题,请随时告诉我。 <|user|> # End
调优
模型AgentTuning
AgentLM:能打的 Agent 模型来了!开源模型并非没有完成智能体任务的能力,可能只是在智能体任务上缺乏对齐。对于 Agent 能力提升的策略,现有许多工作多使用 Prompt / 微调方法优化模型,在单项智能体任务上取得了卓越的表现,但智能体任务之间的促进及泛化效果有待进一步探索。智谱AI&清华KEG提出了一种对齐 Agent 能力的微调方法 AgentTuning,该方法使用少量数据微调已有模型,显著激发了模型的 Agent能力,同时可以保持模型原有的通用能力。AgentTuning 主要包括 2 个阶段。首先,我们收集并过滤得到一个多任务指令微调数据集 AgentInstrcut;然后,我们将 AgentInstruct 数据集与通用数据对模型进行混合微调。评估结果表明,AgentTuning 能让 LLM 的 Agent 能力在未见过的 Agent 任务中展现出强大的泛化,同时保持良好的通用语言能力。AgentInstruct 是一个经过筛选的智能体任务数据集。其包含 6 项智能体任务,从 Shell 交互到数据库操作,平均回合数从 5 到 35 不等,每条轨迹都有 ReAct 形式的 CoT 标注,帮助模型深入理解决策过程。PS: 大家发现Agent/react 有用,就微调LLM强化这方面的能力。
工程调优
使用langchain中自带的react框架进行text2api的构造,发现几个问题:
- langchain完全依赖底座模型,在chatgpt4上表现很好。但在一些中文模型上无法很好识别api的输入参数,经常出现幻觉导致乱编参数的现象。
- langchain调用链路很长,导致我们在改写较复杂问题text2api的时候会有大量的工作。并且react框架因为没有penalty机制,如果出现调用错误的情况,只能人工检查然后通过增强prompt的方式进行修正。 后来我们尝试引进了Reflexion框架,相较于传统的Reactor,Reflexion提供了自我反思机制,然后在memory模块中保存之前的短期记忆和长期记忆,从而在之后的决策中,基于储存的记忆诱导大模型生成更好的答案。
应用
大佬:这一波Agent热潮爆发,其实是LLM热情的余波,大家太希望挖掘LLM潜力,为此希望LLM担任各方面的判断。但实际上有一些简单模块是不需要LLM的,不经济也不高效。例如我们要抽取每轮对话的情绪,可以用LLM,其实也可以用情绪识别模型。例如我们希望将长对话压缩后作为事件记忆存储,可以用LLM,也可以用传统摘要模型,一切只看是否取得ROI的最佳平衡,而不全然指望LLM。
- 创作与生成类助手,简单的借助Prompt工程即可实现
- 企业知识助手,本质上也是一种提示工程:借助于在大模型输入时携带相关的私有知识上下文,让大模型理解、总结、整理并回答用户问题。只是这里的私有知识上下文需要借助嵌入模型(Embedding Model)、向量数据库(Vector Store)、文档加载分割(Document Loader&Splitter)等相关技术来获得。
- 数据分析助手,基本以三种方式为主:自然语言转API、转SQL、以及代码解释器(转代码)。DB-GPT、OpenAgents、OpenInterpreter
- 应用/工具助手,能够把自然语言转换成对企业应用或者互联网开放API调用的一种基础Agent形式。比如:如果你需要AI帮你在协同办公系统中提交一个付款申请,那么你需要调用办公系统的接口;当然,在复杂任务场景下的这种调用往往不是单一的,复杂性主要体现在大模型对自然语言转API的能力:能否根据上下文理解,精确匹配到需要使用的API(一个或者多个);能否准确地提取或生成每个API的调用参数。LangChain、Assistants API、OpenAgents。
- Web操作助手,主要能力是自动化Web网络浏览、操作与探索的动作与过程,以简化web浏览访问与操作。对于个人来说,可以作为个人数字助理,简单对话即可让AI帮你完成Web浏览与操作,比如在线订票。而对于企业来说,则可以作为企业的数字员工,来简化企业日常工作中重复性较高、流程与规则固定、大批量的前端操作性事务。比如批量订单处理、批量客户联络、批量网站抓取等,提高效率,降低错误率。传统的RPA机器人也是用来完成此类工作的AI形式,由于这种AI机器人工作在软件的最上层即操作层面,好处是流程直观、简单、也可以配置化,且对应用无侵入性;但其缺点是与前端应用耦合性大,每个任务需要根据前端应用界面做精心配置与调试,自适应能力较差。在大模型出现以后,给这一类RPA智能也带来了新的优化空间。
- 自定义流程助手,严格来说是上面的几种基础Agent能力的组合,理想中的AI Agent是在丢给他一个工具包与一些知识以后,借助于大模型的理解、推理能力,完全自主的规划与分解任务,设计任务步骤,并智能的使用各种工具,检索知识,输出内容,完成任务。但是在企业应用中,由于企业知识、应用、业务需求的千差万别,以及大模型自身的不确定性,如果这么做,那么结果很可能是“开盲盒”一样的不可控。所以这也是越来越多的Agents项目要强调可控性的原因,即能够对AI智能体的执行过程与细节进行更多的控制,来让AI按照人类确认过的工作流程来完成任务。 PS: 人规定流程 + 单个步骤代码化(有些场景代码无法实现 或 个性化成本太高) ==> 人规定流程 + 单个步骤智能化 ==> 自动分析流程 + 单个步骤智能化
从需求满足的角度来聊一聊:我们首先以“用户去某地旅游”为需求来解释LLM、RAG、Agent三者的能力边界以及需求满足度。
- LLM:能够生成“无法考证可能正确”以及“不一定及时”的相关行程攻略,景点等信息。
- RAG:能够检索一些时效性高、内容可靠的信息源的内容,并生成相关的行程信息。PS:看能召回什么内容了
- Agent:能够基于用户的需求目标完成,通过使用各种工具和系统交互完成攻略制定,订票,制定行程日历等过程任务。PS:先去搜一些攻略,再去订酒店 ==> 从景色、经济、时间等各个角度做一些对比。
阿里云服务领域Agent智能体:从概念到落地的思考、设计与实践
- 工具API尽可能的将场景端到端的进行了封装,做到每个场景的API都能“开箱即用”,比如“退款”的API可以支持实例ID、订单号等多种入参,“ECS无法连接”的API也支持实例ID、IP地址等多种入参,尽量避免出现客户提供一种入参的情况下还需调用另一种API去转换的情况,这样算法侧就可以减少多步调用的场景,从而优化耗时。
- 根据用户Query的分布特点,在阿里云客服场景下,大部分客户的问题中缺失具体信息的较多,很多问题都是“ECS连不上”、“备案进度查询”这类简明的意图名称,因此很难一次性直接提取出必填的参数信息,所以绝大多数的场景都需要参数“反问”的能力,那么涉及到反问澄清,就需要具备多轮的Agent对话能力,也就在客户提供了相应信息的情况下,Agent还能够接得上之前的意图,并且继续完成调用的链路,除此之外,还需要增加不需要调用API的情况,以及无参数提取等情况,让大模型能够知道在什么场景下要调用什么API、调用的动作、参数的提取、API的执行情况等等。
- 在训练完成后,我们也构建了一个服务领域的Agent benchmark评测集,用于对比不同模型的Agent能力情况,这个benchmark中有多个维度的评估,包括API选择准确率、动作执行(反问、直接调用、拒识等)准确率、入参抽取准确率、端到端成功率、生成文案的BLEU和Rouge-L等指标,最终需要经过各维度的权衡决策哪版本模型作为线上模型。
其它
一句指令帮你操作手机,最新多模态手机助手Mobile-Agent来了!为了便于将文本描述的操作转化为屏幕上的操作,Mobile-Agent生成的操作必须在一个定义好的操作空间内。这个空间共有8个操作,分别是:打开App(App名字);点击文本(文本内容);点击图标(图标描述);打字(文本内容);上翻、下翻;返回上一页;退出App;停止。点击文本和点击图标设计了输入参数。
- 在迭代开始之前,用户需要输入一个指令。我们根据指令生成整个流程的系统提示。在每次迭代开始时,Mobile-Agent会获取手机屏幕的截图,通过观察系统提示、操作历史和当前屏幕截图,输出下一步操作。如果Mobile-Agent输出的是结束,则停止迭代;否则,继续新的迭代。Mobile-Agent利用操作历史记录了解当前任务的进度,并根据系统提示对当前屏幕截图进行操作,从而实现迭代式自我规划流程。
- 在迭代过程中,Mobile-Agent可能会遇到错误,导致无法完成指令。为了提高指令的成功率,我们引入了一种自我反思方法。这种方法将在两种情况下生效。第一种情况是生成了错误或无效的操作,导致进程卡住。当Mobile-Agent注意到某个操作后截图没有变化,或者截图显示了错误的页面时,它会尝试其他操作或修改当前操作的参数。第二种情况是忽略某些复杂指令的要求。当通过自我规划完成所有操作后,Mobile-Agent会分析操作、历史记录、当前截图和用户指令,以确定指令是否已完成。如果没有,它需要继续通过自我规划生成操作。
别指望 AI 一次生成,其实不论是文本生成,还是代码生成,都涉及到生成式 AI 的能力问题:
- 用户无法提供所有上下文给模型。既然能提供,提供的成本往往过高(大于 AI 生成的时间)
- 模型无法理解你提供的所有上下文。
Agently AI应用开发框架由浅入深的应用开发指导 - 应用开发者入门篇 在Agently框架的演进过程中,Agent实例是模型能力的放大器这个关键认知深切地影响了框架的设计思想。应该如何理解这个认知?回想一下,当你最初开始使用ChatGPT或者与其类似的聊天机器人(Chat Bot)产品的时候,你对于在聊天框中输入信息并获得返回结果的期待是什么?是不是除了获得对当前一次输入问题的直接回答之外,还期望这次返回结果能够结合之前的几句对话记录,甚至是更远的几天、几周前的对话记录进行回答?是不是还期望聊天机器人能够具备更加生动的形象,并且更了解你的喜好和个人情况,给出更具有针对性的回复?是不是还期望它的回复内容中,除了从模型自身的预训练知识储备中抽取和组织信息,也希望它能够更多地结合外界的信息进行回答?是不是甚至期待它除了给出一条回复之外,还能够真切地帮你写下一段笔记、记录一个提醒、定上一个闹钟?当然了,如果你已经看到了这个章节,你也一定明白,这些期待并不能够通过直接对模型发起一次请求而得到实现,在模型之上,似乎需要有一个结构体,通过一定的结构设计和运行逻辑,来完成这些期待,对于使用者而言,他们仍然可以将这个结构体视作一个加强版的模型,通过简单的输入交互向它发起请求(例如我们在第二部分提供的方法)。在Agently框架中,这样的结构体就是Agent实例。PS: 非常深刻的一个认知
在理解了Agently框架对Agent实例这个结构体的基础设计思想之后,接下来我们来进一步说明在代码编写和运行过程中,Agent实例到底进行了哪些工作?
demo_agent = agent_factory.create_agent()
result = (
demo_agent
# Agent Component 能力插件提供的交互指令
.set_role("角色", "你是一个幼儿教师")
.set_role(
"回复规则",
"你需要将晦涩难懂的专业知识理解之后转化成小孩子能听懂的故事讲给用户听," +
"注意,虽然是讲故事,但是要保证专业知识的准确真实"
)
.on_delta(lambda data: print(data, end=""))
# 基础请求指令
.instruct("如果搜索结果中包含较多内容,请尽可能将这些内容有条理系统地转化成多段故事")
.input("天空为什么是蓝色的")
# 请求启动指令
.start()
)
print("\n[最终回复]: ", result)