我在公众号文章中提出了“面向AI编程”的说法,与“面向对象编程”对应,以完成AI基础单元为编程目标,按照AI特性来设计代码结构,通过AI能力来实现具体功能。同时,面向AI的另外一方面是,与传统面向机器编程相比,我们生产的代码不再提供给机器消费,而是主要提供给AI进行消费,或者说让AI在机器上按照我们的预设进行工作。再有,面向AI的再一方面是,与传统的面向需求编程相比,我们编码的目标是通过调动AI来完成目标需求,而非直接写代码完成需求,这个过程中,只要能满足需求,可以让AI自由选择实现方式,不一定是编程方式。随着LLM逐渐成熟,过往我们只能通过代码实现人机,而现在我们可以通过自然语言实现人机,这对于技术的发展有着巨大的意义,因为原本不会编码的人也可以指挥机器按照其创意进行生产。那么,在当下这个阶段,我们如何才能让不会编程的人指挥机器呢?本文就来具体聊一聊,2024年的今天,开发者们是如何解决这个问题的。
LLM驱动的Agent
由复旦NLP和米哈游调查完成的文献综述《The Rise and Potential of Large Language Model Based Agents: A Survey》详细阐述了LLM-based Agent的相关理论、实践模型和深度思考,知乎上有大神做了详细的解读,我下面基于此再做白话版总结。
首先,为什么是“Agent”这一概念?因为它是一个人工智能领域延续至今的设定,随着时代的推移,它的概念内涵在扩大,但是无论再哪个时代,它都能一针见血的概括人工智能的终极目标——自主思考和行动的机器体。很多人一听到“自主思考和行动”就会担心将来机器人会灭了人类。这是因为普通人并不了解人工智能领域的覆盖范围,里面有一个方向是研究智能的社会性,任何智能都需要具备社会性,那么就会有其行为准则。总之,在人工智能领域,Agent不是这两年冒出来的新概念,而是始终贯穿人工智能领域研究的核心概念之一,过去、现在和将来都将作为一个核心词汇存在。人工智能的代际,从Agent的角度来看,可以分为:Symbolic Agents -> Reactive Agents -> RL-based Agents -> Agent with transfer learning and meta learning -> LLM-based Agent。其中AlphaGo和DQN是RL-based时代的产物。“学习如何学习”则是在LLM出现之前的重要课题。知道GPT引爆业界,才标志着新一代Agent时代的到来。
Agent的构成模块
Agent由大脑模块、感知模块、行动模块构成。作为人工智能工程的最小单位,Agent的功能可以不同,但构成模块的设计完全符合了人类的认知,因此,三模块结构缺一不可。
中枢大脑
在2024年的今天,因为我们已经有了LLM,因此,当我们再去思考一个Agent的大脑应该具备哪些能力时,和前面代际的思考方式完全不同。LLM-based时代下,Agent的大脑主要包含:
- 自然语言交互,包含自然语言理解、多轮对话、自然语言(高质量)生成、意图和含义理解
- 知识,包括语言知识、常识知识、专业领域知识,当然这里需要考虑赋予Agent通过外部知识库实时获取知识的能力
- 记忆,提高记忆能力的方法有提高Trransformer的输入长度限制、总结记忆、用向量或数据结构压缩记忆,同时需要注意记忆检索的最近性、相关性和重要性
- 推理和规划,推理依赖LLM本身的训练程度,规划包括两个阶段:计划制定和计划反思。
- 可迁移性和通用性,我个人理解主要是指可以把发生过的事自己再学习为模型本身的一部分,从而越来越接近人类的思考水平
感知
Agent本身作为一个最小单位,必然需要根据环境做出反应,对环境的感知能力往往意味着这个Agent的功能主要是什么,就像人类的各个器官,感知痛觉和味觉,往往意味着它的功能。从LLM的角度,Agent的感知对象主要为:
- 文本输入
- 视觉输入,包含静态图片和连续图帧(视频、gif等)
- 听觉输入,主要指音频,包含已有的音频文件和实时的声音收录
- 其他输入,我个人认为主要包含各类智能硬件传感器、软件触发、结合各类信息综合计算结果、其他关联Agent的输出信息、中枢大脑的指令。
行动
Agent的真正发挥作用的部分,从编程的角度,中枢大脑的功能可以富余,但感知和行动定义了该Agent的边界,决定了该Agent的实际功能。从LLM的角度,Agent的行动主要包括:
- 输出文本
- 输出图片、音频、视频
- 使用工具,如Functional call等,同时,Agent需要反馈工具的处理结果,此处需要考虑是将工具处理结果作为另外一个Agent的输入,再由另外一个Agent将其作为输入再给当前这个Agent,这种模式使得架构设计上更容易理解,但是Agent的数量会变多
- 具身行动,Agent的智能来源于与环境的持续互动和反馈,而不是仅仅依赖于精心编辑的预训练数据,它们应该能够主动感知、理解物理环境并与之互动,根据 LLM 丰富的内部知识做出决策并产生特定行为来改变环境,这个和我上面提到的把发生过的事自己再学习为模型本身的一部分有类似的意思
从具身行动的角度看,Agent本身不是静态的,它应该像人的细胞一样,具有新陈代谢的能力,当Agent本身能够感知环境,学习和互动,沉淀为模型本身的部分,并基于此来做出适应环境的决策,那么这也就意味着,大脑部分需要新增内容,从编程的角度看,可能就是动态训练模型,并在训练后热替换当前模型,如此反复循环。
Agent的治理模式
在之前的文章中,我有详细介绍过Agent的治理模式,不过在这篇文章中,它的提法更加全面。就2024年的今天,可见的模式主要包含3种:Single Agent、Multi-Agents、Human-Agent。
Single Agent
简单讲就是,一个Agent就是一个应用,直接给到用户去使用。这类Agent往往是一个软件,接收用户输入,按照其功能设定,返回给用户结果。例如现在的ChatGPT、GPTs、RGA知识库等应用,其中最值得一提的是LangChain和AutoGPT。
虽然Single这个词听上去让人感觉很单薄,觉得好像做不出什么特别的产品,但是我们可以通过合理的架构,使得Agent具备优秀的创意。例如现在figma上面有非常多的智能插件,它们的出现可以快速帮助我们解决一些场景,而这些插件,虽然本身入口很单薄,但是它们背后可能由一整家公司和庞大的技术支撑。从这种设计的角度讲,Single Agent可以按下方的角度分类:
- 面向任务的,用以完成人们提出的任务,以提升生产效率
- 面向创新的,用以在特定领域进行快速验证,以极大的缩减实验时间,例如在蛋白质构型编排上,今天1分钟就可以完成过去10年的编排发现
- 面向生命周期的,简单将就是这类Agent设计出来没有具体目标,就是让它自己在开放自由的环境中自生自灭,自己生长,看它能长成什么样子,我们从之吸取有益的部分
现阶段而言,上面三种类型都已经是被实现了的,只不过从大规模应用、对现实工作影响最大、可以马上立竿见影的,主要是第一种。
Multi-Agents
早在 1986 年,马文-明斯基就做出了前瞻性的预测。他在《心灵社会》一书中提出了一种新颖的智能理论,认为智能产生于许多具有特定功能的小型Agent的相互作用。例如,某些Agent可能负责模式识别,而其他Agent可能负责决策或生成解决方案。简单讲,从人类已知的系统论角度去看,分工可以解决非常多问题。让不同功能的Agent由系统协调来完成目标,可以使得该系统更具有未来的持续可前瞻性。也就是说,一个系统(如公司)比一个封闭的个体(如个体户)更有发展前景。
不同的Agents之间,它们的分工固然重要,然而,相互联系才能形成系统,因此,我们更多的是探讨它们的联系方式。
- 互补性合作
- 无序合作,agents之间没有顺序,每个agent都是对环境(把其他agent当作环境因素)做出响应,所有agent的行为结果总和起来就是我们需要的结果
- 有序合作,当前agent只接收上一个agent的输出作为输入,所有agents串联在一起
- 对抗性互动,agents之间有监督、对抗关系,例如有一些扮演测试、评审等角色的agent
微软的AutoGen和LangChain的LangGraph都是multi-agents的构建框架,在这些框架中,把不同功能的agent进行分工,扮演特定角色,并对多个agent进行分组,使agents可以像一个系统中的各个角色一样工作,从而从一个系统的角度完成用户交给的工作。
Human-Agent
由人来指导和监督Agent的工作过程,以确保更高质量的产出。人与Agent交互来完成工作,里面涉及到交互的方式、关系等,例如人和Agent的地位是否是平等的?Agent给出的反馈是定性的还是定量的?人参与的程度究竟有多大,是关键节点还是每一个节点都需要人的参与?如何确保人的输入是准确的,不会给agent增加额外的负担?等等。
我们都知道AI的智能程度依赖于LLM本身的智能程度,AI的理解和规划能力,目前来看还是受限的,还没有达到我们普通成年人的水平。另外,Agents之间的互动解释性弱,需要人的参与来确保解释是按照人的意志执行的。而且,由于这种解释偏差,很可能会带来严重的恶劣后果,人的参与也可能在一定程度上规避。
人类参与互动,可以是1对1的人-Agent互动,也可以是1对多的人-Agents互动,也可以是人类作为一个Agent参与到Agents间有序合作的链条中。
Agent社会性
社会的本质,是“规则下的团体”,没有规则就没有社会,有了规矩往往形成社会。在一套系统中,Agents可能是由不同的服务商提供,基于AI的训练,Agent表现出自己的认知、情感、个性,这些抽象的表现定性,是我们对它社会行为的总结。
当一个Agent总是表现的很积极,无论输入简单还是详细,它都尽可能做出规划,我们就认为它具有开放人格;当一个Agent总是表现的消极,总是在输入简单的时候,反馈出不愿意做规划,打回让上有重新发出指令时,我们认为它具有较为封闭的人格。而作为系统,需要制定社会性规则,以在Agent的个性和达成目标之间实现平衡。
AI编程
通过驱动AI来完成某些任务,以编程的方式安排细节与逻辑,由AI来解释任务和完成规划。我们只需要验收结果,或者再在关键环节参与交互。那么,我们应该如何来设计一套系统,实现这样的诉求呢?
Agent功能分类
我们按照最小职责原则,将所有的功能进行划分,尽可能的把功能拆分开,每一个功能,都有一个Agent与之对应。我们可以从不同的角度进行分类,以覆盖我们的功能需求:
- 推理解释类,对输入进行理解以按照某种规则输出理解后的DSL,例如输入一张流程图,获得该图对应的DSL
- 数据转化类,对输入进行数据理解和提炼,例如输入一篇年鉴文章返回所需数据的JSON格式
- 工具执行类,按DSL调用工具,传入参数,执行完获得结果
- 人机互动类,也就是上面Human-Agent所提到的
这里需要注意,我没有把传感器类作为一类Agent,下文会提到,我们的硬件传感器本质上只是信号的输入端,基于某种协议,千奇百怪的传感器,最终给到AI的输入,都可以是统一标准的数据结构,这个部分需要传感器的开发者去做,作为AI系统的开发人员,无法触达这个部分。同样的道理,我们会让用于执行任务的硬件也与系统本身解耦,不过由于执行硬件是被调用方,因此,这部分封装需要我们AI系统的开发者来完成。
AI系统设计
现在,让我们想象,我们已经有了一台机器人,现在它需要完成一个炒鸡蛋的任务,那么,从我们编程的角度,这里面都由哪些东西构成呢?数据和指令的流动是怎样的呢?
首先是指令的接收和理解,我们通过麦克风接收指令,此时麦克风接收的是音频信息,我们通过一个agent将其转化为文本信息;接着,我们将该文本输入到一个用于理解指令的agent,该agent从自身支撑的所有功能中,理解了该指令的意图,并将指令以固定协议文本发送给中枢agent;中枢agent的主要能力是理解和规划,它在接收指令之后,正确理解了该指令,并发通过functional call功能,创建了一个任务,并将该任务id保持在记忆中;接下来,它开始规划该任务,第一步是确认自身所处环境,第二步是确认炒鸡蛋的条件是否满足,第三步是准备食材,第四步是烹饪……;完成规划后,将该规划进行进一步细化,把所有关联的agent都挑选出来,并建立了任务地图;之后开始执行任务,它通过打开摄像头和毫米波雷达全屋扫描设备,这些设备在被打开后,会将信息通过响应的agent层层上报,最终被中枢确认;之后再发送执行履带滚动的指令,控制电机运转,实现移动和各种硬件设备的控制;最终完成炒鸡蛋,并通知主人任务完成。
我们可以看到,这是一个非常复杂的细节超多的系统,虽然难度大,但是也不是不可能对吧。
![](https://static.tangshuang.net/wp-content/uploads/2024/03/截屏2024-03-24-18.30.54.png)
AI系统设计示意图(注意,这里的中枢层和Agent的中枢大脑是两个概念)
对于我们开发者,主要是在软件侧做一些事情,不同的硬件传感器它的数据结构是不同的,因此,我们需要有一个针对性的agent来处理这类传感器的信号。同样,行动端的逻辑是一样的。有些硬件本身即是传感器也是执行器,我们需要把这些硬件拆开来看,在概念上它和现实是不同的。
在平台端,我们用“事件代理层”来实现具体agent和平台的解耦。我们的平台会对接无数的agent,通过解耦,我们不需要针对不同的agent进行设计,而是提供统一的协议,agent通过协议订阅或发布事件,无需关心自己的所处环境。在信号的传输上,我们设计为单向信息流,这样可以让每一个agent都只有一个输入和一个输出,以让实现更加简单。由于一项工作具有时间延续性,因此,我们设计任务调度层来维持一个任务队列,通过中枢层来为任务调度提供方案。而且,我考虑到有一种情况是任务在执行过程中,由于传感器发现了新的环境变量,此时我们可能需要插入新任务或者立即停止当前任务。
另外,我们没有让行动端端反馈直接返回给任务,因为这样就会导致数据流向不再是单向的。我们需要将硬件执行器的反馈转换为感知端的信号,重新发送事件给中枢,由中枢来决定当前的执行是否符合预期。
AI应用架构
如果我们需要将AI应用进行部署,就需要考虑如何在我们现有的条件下去充分利用好各种资源。随着LLM的基座越来越出色,我们将来必然出现完全智能化的应用。
通过这一架构,我们可以让Agent被无限扩展,而无需调整已有代码。随着agents的数量越来越多,系统能支持的能力也越来越强。我们只需要利用这些agents来进行调用编排,即可实现让系统按需完成我们的任务,例如:
当 @agent1 发生xx时,且 @agent2 状态为xx时,@agent3 执行xxx
基于该指令,平台层可以基于已有的agents被无限的设计出特定的功能。
结语
随着我们对人工智能的研究,我们越来越开始理解人类大脑的工作原理。本文通过对复旦论文的解读,提出了一种可以实现自执行的任务处理系统架构。一个agent本身的实现可以很复杂,但是在概念上,它只是一个“input -> agent -> output”的处理单元,是非常简单的。随着我们在技术上的深入,我们会越来越接近AI编程。就如上文展示的一样,将来,在AI系统的基础上,我们只需要使用非常简单的自然语言,就能设计出以目标为导向的任务,而无需关心它的具体实现,以及它的内部原理。如此依赖,即使没有接触过编程的普通人(甚至是障碍人士)也可以轻松的借助机器完成自己的创意或工作。