Agent 概念
在日常生活中不难发现 ChatGPT 通过文本输入进行处理后返回的也是文本内容,就像是一个只有头的人,能听能思考能说话,但是无法行动。而 Agent 是一种能够自主决策、采取行动以达到某种目标的实体。被解释为"智能体"或者"代理"。
实际上,人类是这个星球上最强大的 Agent。Agent 是一个能感知并自主地采取行动的实体,这里的自主性极其关键,Agent 要能够实现设定的目标,其中包括具备学习和获取知识的能力以提高自身性能。Agent 的复杂程度各不相同,一个简单的恒温器可以是一个 Agent,一个大型的国家或者一个生物群体也可能是个 Agent。感知环境、自主决策、具备行动能力,设定明确的目标和任务,适应环境及学习能力,都是 Agent 的关键特点。
有人认为 Agent 技术是未来实现社会全面自动化的关键技术。
基于认知飞轮的 Agent
认知飞轮是指一个人通过不断学习、思考和实践,不断提升自己的认知能力,从而形成一个良性循环的过程。就像一个飞轮一样,开始的时候可能需要花费很多力气去推动它转动,但一旦转动起来,就会越来越快,带动个人认知能力的不断增长。人的行为过程主要由人对环境信息的获取、感知、处理和输出组成,即感知、认知、决策、行动的过程。我们思考一个问题,做一件事,开展一个项目,都需完成这个认知飞轮。简单来说,认知飞轮就是通过不断学习和思考,让自己的认知水平不断提升,并且这种提升会越来越快,形成一个良性循环。
众人熟知的认知飞轮,感知、认知、决策、行动,今天的人工智能代理更像是基于这个认知飞轮构建的。但是从本质上,人类智能远比这复杂。
在认知飞轮的框架下,Agent 可以通过不断地获取信息、分析数据、做出决策并执行行动来改善自身的认知能力。这种循环过程与认知飞轮中的学习、应用、评估和调整的环节相对应,从而使 Agent 能够不断地提升自身的智能水平。
下一代智能体发展的三大关键领域:规划、用户体验和记忆
规划是指 AI 智能体能够预先考虑多个步骤,并确定最佳行动方案的能力。目前,语言模型的规划能力还比较有限,主要依靠以下两种方法来加强:
- 外部提示策略:开发者通过设计特定的提示,引导语言模型进行规划。例如,可以要求模型在执行每个步骤之前,先列出所有可能的步骤并进行评估。
- 流程工程:通过设计预定义的流程图或状态机,将任务分解成多个步骤,并明确每个步骤的执行条件和顺序。这可以帮助语言模型更好地理解任务,并做出更合理的规划。未来,随着语言模型能力的提升,它们或许能够自主进行更有效的规划,而不再需要外部提示或流程工程的辅助。
目前,AI 智能体的用户体验仍有许多需要改进的地方,例如:
- 可靠性不足:由于语言模型的局限性,AI 智能体有时会犯错或无法理解用户的指令。这可能会导致用户感到沮丧和困惑。
- 可控性不足:用户往往无法完全控制 AI 智能体的行为,这可能会导致一些意外的后果。
- 缺乏个性化:现有的 AI 智能体大多缺乏个性化,无法根据用户的特定需求和偏好进行调整。
记忆是指 AI 智能体存储和使用信息的能力。记忆对于 AI 智能体完成各种任务都至关重要,例如:
- 程序记忆:记忆如何正确地执行任务,例如如何预订机票或如何撰写电子邮件。
- 个性化记忆:记忆与特定用户相关的信息,例如用户的姓名、喜好、经历等。目前,AI 智能体的记忆功能还比较简单,主要依靠以下两种方式实现:存储在数据库中:将信息存储在外部数据库中,并在需要时进行检索。嵌入语言模型中:将信息嵌入语言模型的参数中,使模型能够在生成文本时使用这些信息。
LangChain 中的 Agent 概念
代理的核心思想是通过大模型来选择要采取的一系列行动。在常规结构下,一系列行动都是硬编码,是已规定好的行为路线,而在代理中,是用大模型作为推理引擎来确定并采取行动的。通俗的讲就是给大模型配备工具,让大模型自己去判断在当前场景需要使用什么工具。
代理的效果与模型的智慧程度有关,大模型的训练集越大,代理的效果越好,差的模型进行代理会陷入某一个自问自答而死循环,好的模型会进行自我验证,验证这个答案是否与最初的问题相关,不相关进行修正。
举个例子:
链式结构:我会拿着螺丝刀去拧螺丝,拿着钥匙开锁,拿着斧头砍木头。我不会选择工具,而是按照规划的路线行动。也就是写死的逻辑,场景都是被预定好的,一旦遇到新的场景或者问题可能就会出现不理想的结果。
代理情况:我有螺丝刀,钥匙,斧头等工具,我遇到了一颗螺丝,我会用螺丝刀去拧螺丝。遇到了一把锁,我会用钥匙去开锁,遇到了木头,我会用斧头去砍木头。在不同的场景或者问题下会进行推理选择。工具与问题之间是没有直接的代码逻辑进行联系的。
总而言之:Agent = LLM(思考决策)+ prompt(思维链) + memory(记忆)+ tools(执行)
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
ReAct 是 Shunyu Yao 等人在 ICLR 2023 会议论文《ReAct: Synergizing Reasoning and Acting in Language Models》中提出的,一个关键启发在于:大语言模型可以通过生成推理痕迹和任务特定行动来实现更大的协同作用。具体来说,就是引导模型生成一个任务解决轨迹:观察环境 - 进行思考 - 采取行动,也就是观察 - 思考 - 行动。那么,再进一步进行简化,就变成了推理 - 行动。ReAct 框架会提示 LLMs 为任务生成推理轨迹和操作,这使得代理能系统地执行动态推理来创建、维护和调整操作计划,同时还支持与外部环境(例如 Google 搜索、Wikipedia)的交互,以将额外信息合并到推理中。
核心一-ReAct 提示词
尽你所能回答以下问题,你可以使用以下工具:
{tools}
请按照以下格式:
Question: 你必须回答的输入问题
Thought: 你应该始终考虑该怎么做
Action: 要采取的行动,应该是[{tool_names}]中的一个
Action Input: 行动的输入
Observation: 行动的结果
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: 我现在知道最终答案了
Final Answer: 原始输入问题的最终答案
开始吧!
Question: {input}
Thought:{agent_scratchpad}
- tools: 工具集,代理进行推断需要使用的工具,也是大模型与外界交互的方式,这也是与硬件结合的关键,后续详细解释
- tool_names: 这就是工具集中的工具的名字,进行工具加载时就将这些工具名字传输给了工具集
- input: 外界的输入,也就是人类的输入,一个认知推理循环的开始指令
- agent_scratchpad: 大模型进的推理记录,这样他才能知道他做了那些推理,是否进行验证问题等
在这个提示词中,可以对这个代理进行角色约束,可以约定工具的使用规则等,但是要考虑到效率问题,提示词会直接影响推理迭代的效果,或许会因为提示词而直接自问自答。
核心二 - 工具集
工具是 LangChain 中 Agent 的重要组成部分,他是大模型与外界交互的关键,如何与外界交互则是工具集中的逻辑了,还是摆脱不了需要硬编码的地方。langchain 只能进行调用这个工具,进行传参 (过度复杂的参数需要进行数据抽取) 才能进行调用,没有传参的工具会直接报错,只有返回值的工具我称之为白洞工具。工具需要返回一个结果给代理才能进行继续推理,若是没有返回结果,代理就要进行自我发挥然后出现两种结局死循环到设定次数而终止或者胡乱回答,没有返回值的工具我称之为黑洞工具。由于大模型只能识别字符串而且是有语义的字符串,乱码不能识别,也就是说返回值至少要描述,让大模型能够理解这个返回值。
LangChain 自定义工具的实现
from langchain.agents import tool
@tool
def tool_name(humanInput: str) -> str:
'''工具的描述'''
return "工具返回值"
tools = [tool_name]
自定义工具的关键在于工具的描述,没有对工具进行描述,代码会直接报错。ReAct_agent 是无法直接通过工具的名字得知适合使用的场景,这些都是需要人为定义的。工具的描述也相当于提示词的一部分,规定和约束工具的使用场景、参数,返回值等让 Agent 能够正确的使用工具。
工具内部的逻辑
工具内部逻辑属于链式结构,一环扣一环。例如搜索'地球的直径',工具内部逻辑则是:
- 接收参数中的搜索内容
- 将搜索内容传入搜索引擎,搜索引擎对内容进行搜索
- 将搜到的内容返回到代理。
若是将 b 节点取消,那么 c 节点也就没有内容进行返回。这部分内容的逻辑越严谨越好,特别是对硬件编程。对于一个工具而言,代理只能控制参数的传入,没办法直接对工具内部逻辑进行操作。也没办法对工具内部的结果进行推理,若工具也是一个代理那就另当别论的,但外层代理也不能推理工具内代理。
树莓派 PICO W
树莓派 Pico W 是树莓派基金会推出的一款微控制器开发板,它基于 RP2040 芯片,这是树莓派基金会与澳洲设计公司 Proant 合作开发的芯片。Pico W 是树莓派 Pico 的升级版本,主要特点包括:
- Wi-Fi 连接功能:Pico W 在 Pico 的基础上增加了 Wi-Fi 功能,使其更加便于连接到无线网络,实现更多应用场景。
- RP2040 芯片:RP2040 是一款由树莓派基金会自主设计的双核 ARM Cortex-M0+ 微控制器芯片,具有良好的性能和低功耗特性,适合用于物联网和嵌入式系统开发。
- MicroPython 和 C SDK 支持:Pico W 支持 MicroPython 和 C SDK,开发者可以使用这两种语言进行开发,方便快捷地实现各种项目。
- 丰富的接口:Pico W 拥有丰富的 GPIO 引脚和外设接口,可以连接各种传感器、显示屏和其他外部设备,满足不同项目的需求。
在一个硬件系统中,可以被视为系统的指挥者,负责协调各个部分的工作,确保系统运行顺畅。
硬件工具
之前提到的工具都是程序层面的工具,只能运行在计算机里面,交互的都是数据,不是实际的物体。而硬件工具是将树莓派 PICO W 中的控制硬件的代码进行封装成工具,这个工具能够使用硬件设备完成指定的动作。可以将这个工具的逻辑写死,对工具的返回值进行描述让代理能够理解,并且不使用参数的值。例如一个打开小灯的工具,调用工具就打开小灯。由此延伸,可以构建功能极其强大的工具。工具内部还能继续使用代理或者是特殊链,完成一系列高难度动作。
LLMs 与外界交互
原理:ReAct_Agent 框架 + 树莓派 PICO W 硬件工具。这就相当于一个比较智能的能实现一定动作的机器人
机器人部位
头部(机器大脑)
ReAct_Agent 框架会搭载 LLMs,LLMs 具有一定的理解能力,而 ReAct_Agent 则具有推理调用工具的能力,这就很逼近人类思考->行动的方式了。将大语言模型作为机器大脑与传统的机器大脑具有独特的优势
优势
学习能力:
- 传统的机器人大脑通常通过预先编程的算法和规则来执行任务,而大语言模型可以通过大量数据进行训练,从而学习并适应各种任务和情境。
灵活性:
- 大语言模型可以根据输入的信息生成复杂的自然语言文本,因此在处理自然语言交互时更加灵活。传统的机器人大脑可能需要更多的代码和规则来实现相同的任务。
创造性:
- 大语言模型可以生成新颖的文本、想法和概念,具有一定的创造性,而传统的机器人大脑更多地依赖于预定义的指令和规则。
适应性:
- 大语言模型可以通过不断的学习和更新来适应新的数据和情境,而传统的机器人大脑可能需要手动更新和修改程序来适应变化。
劣势
硬件适配度
- 传统机器大脑都是直接与硬件设备进行编码联系,有一套固定的运行逻辑且运行处理速度很快,而代理与硬件设备间没有直接的逻辑联系,在某场景下使用某个硬件设备的选择都是有代理根据场景进行选择的。会存在偏差。
资源消耗
- 传统机器大脑都是直接用代码实现逻辑,而代理使用现有的模型 API 需要消耗巨量的 token,使用本地的模型则需要较好的硬件设备 (显卡,CPU)。自己进行训练时耗费的人力物力是个人开发者难以承担的。
身体 (机器手脚)
软件工具是代理在计算机内的手脚,那硬件工具就是代理在现实生活中的工具。LLMs 通过硬件工具间接的与现实世界交互,可以给代理一些外界的输入,让他进行推理然后做出反应。被 Agent 控制的硬件设备与传统的机器大脑操控肯定也是存在了优劣的
优势
- 自主性:代理可以根据预先设定的规则或学习到的策略来自主地控制硬件设备,无需人为干预。
- 自动化:代理可以实现硬件设备的自动化控制,从而提高效率和减少人力成本。
劣势
- 稳定性:代理控制系统可能受到外部环境、噪声和不确定性的影响,导致控制效果不稳定。
- 安全性:代理控制系统可能存在安全漏洞,一旦被攻击或出现故障,可能导致硬件设备的损坏或安全风险。
内容构想
智能家居是一个典型的例子,但是我感觉它能实现的不仅仅是智能家居这种项目。当使用多模态的 LLMs 构建代理时,它能够直接理解图片或者视频并且它的智慧程度足够高时,一个摄像头,一个语音模块再加上树莓派 PICO W 就能够实现一个能够看到外界并且会说话的机器人,不过此时它看到的还是二维的世界。再加上雷达等设备,是否就能让它看到三维的世界呢,装上移动的脚或者轮,它是否可以通过它的'眼'判断出墙的位置而做出正确的反应呢。再给它一个应用场景,例如在医疗场景中,它通过摄像头在人体内部看到了肿瘤或者异物就能辅助医生判断,在模棱两可的情况或许这样一个机器人就能起到出色的作用。在农业场景中,通过土壤的酸碱度,湿度传感器,自行判断是否需要施肥,浇水。通过某些传感器,自行判断果实是否进行采摘。
项目的提示词
进行了一些关于 Agent 提示词的小实验,工具还是使用的程序工具。这里给它看了一个正在吃苹果的美女。给代理配备了一个眼睛 (图片识别模型) 和一张嘴巴 (打印语句)。想要单纯的直接使用工具进行看与说是有问题的。他看到的应该是根据返回的值,但是它在工具还没有调用情况下就说'我看到了一台电视',这显然是不对的。
也可以看到提示词部分有问题,在运行当中会直接造成思维链崩溃,但是理论上来说 ReAct 提示词是能够直接使用这些工具的。根据报错提示,进行了修改运行结果显而易见的有好转。
也就是说,根据项目的推进需要对提示词进行修改,不同的项目提示词是不相同,没用最好的提示词,只有最适合的提示词。
缺点与问题
- 目前市面上的大语言模型的智慧程度不高,多模态的大语言模型还不能对图片或者视频进行一个非常仔细的描述。
- 由于智慧程度问题,代理接入硬件的效果比预计的要差很多,做一些复杂的逻辑似乎是不太可行的
- 代理的执行速度很慢,相较于传统硬编码的工具毫秒级别的执行速度来讲,那就是一个天一个地了。
- 代理与工具的适配程度,理论上只要给工具描述清楚了,代理都是能使用的。问题又出在了大语言模型的智慧程度,对于一个问题就算使用了工具它的到的答案可能还是错的,而且常常会因为 ReAct 的提示词而自问自答或者陷入死循环。
- 对于大语言模型的直接调用都苦于 token 久矣,而代理进行推理与迭代无疑更是对 token 的巨量消耗,可能会让钱包爆炸。
实战代码示例
为了将理论落地,下面展示如何将树莓派的 GPIO 控制封装为 LangChain 工具,供 Agent 调用。
import RPi.GPIO as GPIO
from langchain.agents import tool
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
@tool
def control_led(state: str) -> str:
"""控制 LED 灯的开关,state 参数为 'on' 或 'off'"""
try:
if state == "on":
GPIO.output(18, GPIO.HIGH)
return "LED 已开启"
elif state == "off":
GPIO.output(18, GPIO.LOW)
return "LED 已关闭"
else:
return "无效的状态参数"
except Exception as e:
return f"控制失败:{str(e)}"
tools = [control_led]
在此示例中,control_led 函数被装饰为工具,Agent 在接收到如'打开房间灯光'的指令时,会根据工具描述自动匹配并调用此函数,从而实现物理世界的交互。
总结
本文深入探讨了 LangChain Agent 的概念及其与树莓派 PICO W 的结合方式。通过 ReAct 框架,Agent 具备了推理与行动的能力,配合自定义工具,能够有效桥接虚拟智能与物理设备。尽管目前在 Token 消耗、执行速度和稳定性方面仍存在挑战,但随着模型能力的提升和硬件成本的降低,Agent 在智能家居、工业自动化等领域的应用前景广阔。开发者应关注提示词工程与工具描述的优化,以提升 Agent 的可靠性和实用性。