0. AI Agent Loop 异步执行
AI Agents 在很多领域和行业得到广泛应用。在一些开源框架和闭源平台帮助下,开发一个AI Agent也变得更加轻松,开比如微软的 AutoGen, LangChain公司的 LangGraph都都对AI Agent执行过程 agent loop 进行了抽象和封装,方便开发者以较低代码量接入甚至0代码在平台上配置完成。具体的 AI Agent 的执行过程往往是一个异步执行的 loop,本篇博客会给大家介绍一下基础的 AI Agent的执行流程 agent loop定义,并且借助于开源框架 agentboard (github: https://github.com/AI-Hub-Admin/agentboard)来可视化Agent Loop的执行过程,比如(PLANNING/ACTION/REACT/REFLECT)每个阶段的输入、输出、执行时长等等。可以参考 agentboard 可视化 agent loop 的tutorial (http://www.deepnlp.org/blog/agentBoard-ai-agent-visualization-toolkit-agent-loop-workflow).
1. 什么是 AI Agent的Agent Loop
借助Open AI研究员Lilianweng的 AI Agent的架构图 (https://lilianweng.github.io/posts/2023-06-23-agent/),AI Agent 依赖大模型能力,进行规划 (PLAN) 和 执行 (ACTION),这个过程中会设计到 Tools工具使用 和 Memory 记忆模块更新。
具体到 AI Agent 开发,不同框架对于执行过程抽象不同。简单的Agent 执行逻辑可能只包含一次 LLM来根据用户输入 prompt和可以选择工具tools来进行决策和填充参数,然后本地 Agent 执行。复杂一些Agent Loop 会设计到更多阶段,我们可以参考 AutoGen(https://microsoft.github.io/autogen/0.2/), LangGraph(https://github.com/langchain-ai/langgraph), AutoAgent(https://ai-hub-admin.github.io/AutoAgent/), GPTeam(https://github.com/101dotxyz/GPTeam) 等等这些框架对于Agent Loop的抽象。
1.1 简单的 Function Calling Tools Use
AI Agent 执行简单的功能如:天气查询,股价查询,订单查询,基本只会调用一次 LLM,输入是prompt和可以选择的tools (函数的定义Schema),拿到返回结果之后给函数进行参数填充,然后运行 Function Calling调用。
例如:
OpenAI的 Function Calling
prompt = "Can you give me an example of python code usage of async await functions" messages.append({"role": "user", "content": prompt}) completion = client.chat.completions.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt} ] ) response_message = completion.choices[0].message print(response_message) # {"role":"xxx", "content":"xxx"} messages.append(response_message)
Anthropic Claude API Function Calling
client = Anthropic() MODEL_NAME = "claude-3-opus-20240229" response = client.messages.create( model=MODEL_NAME, max_tokens=4096, messages=[ {"role": "user", "content": user_message}, {"role": "assistant", "content": message.content}, { "role": "user", "content": [ { "type": "tool_result", "tool_use_id": tool_use.id, "content": tool_result, } ], }, ], tools=tools, )
1.2 更加复杂的自主Agent (Autonomous Agents)的 agent loop
a. LangChain的 GPTeam中每个Agent包含的 loop有: observe->plan->react->act->reflect
(Agent Loop的代码: https://github.com/101dotxyz/GPTeam/blob/34bdfb3b040258b2f414e3e61ba2761c7295ba3d/src/agent/base.py?ref=blog.langchain.dev#L1050)
(https://blog.langchain.dev/gpteam-a-multi-agent-simulation/)
其中核心Agent Loop 逻辑
b. AutoAgent库中抽象异步Agent Async Agent的Loop包含更加精简 plan->act->refect : (AutoAgent的AgentLoop: https://github.com/AI-Hub-Admin/AutoAgent/blob/main/src/AutoAgent/core.py)
async def run_loop(self): try: print ("%s|%s|run_loop start|0" % (self.name, get_current_datetime())) plan_duration = await self.plan() print ("%s|%s|Plan Complete|%s" % (self.name, get_current_datetime(), plan_duration)) act_duration = await self.act() print ("%s|%s|Act Complete|%s" % (self.name, get_current_datetime(), act_duration)) reflect_duration = await self.reflect() print ("%s|%s|Reflect Complete|%s" % (self.name, get_current_datetime(), reflect_duration)) total_duration = plan_duration + act_duration + reflect_duration return "%s|%s|run_loop complete|%s" % (self.name, get_current_datetime(), total_duration) except Exception as e: print (e) print (traceback.print_exc()) return "%s|%s|run_loop complete|%s" % (self.name, get_current_datetime(), 0)
2. 借助AgentBoard 来对不同框架下的Agent Loop可视化
首先需要安装 python库 AutoAgent 和 agentboard
pip install AutoAgent agentboard
2.1 基于AutoAgent框架的重新写 run_loop 函数
基础的 run_loop 函数中每个stage执行函数是灵活定义的,我们在定义的 plan, act, refect 函数中,只执行一段 sleep随机长度时间的逻辑,然后就结束,模拟执行一个真实 Agent 进行 RAG/爬虫的等待时间。我们继承基础类 AsyncAgent并且重写 async def run_loop 函数,包含了 self.plan(), self.act(), self.reflect() 3个函数,每个函数等待预期时间 est_time。
import time import agentboard as ab from agentboard.utils import function_to_schema from AutoAgent.core import AsyncAgent, AsyncAutoEnv from AutoAgent.utils import get_current_datetime class AutoAgentWorkflow(AsyncAgent): """ Agent who can plan a day and write blog/posts videos on the website execute cycle: plan->act->reflect """ async def run_loop(self): try: ## PLAN plan_duration = await self.plan() print ("%s|%s|PLAN Complete|%s" % (self.name, get_current_datetime(), plan_duration)) ## ACT act_duration = await self.act() print ("%s|%s|ACT Complete|%s" % (self.name, get_current_datetime(), act_duration)) ## REFLECT reflect_duration = await self.reflect() print ("%s|%s|REFLECTION Complete|%s" % (self.name, get_current_datetime(), reflect_duration)) total_duration = plan_duration + act_duration + reflect_duration print ("%s|%s|END|%s" % (self.name, get_current_datetime(), 0)) return "%s|%s|run_loop complete|%s" % (self.name, get_current_datetime(), total_duration) except Exception as e: print (e) return "%s|%s|run_loop complete|%s" % (self.name, get_current_datetime(), 0)
接着,我们初始化2个Agent,2个Agent的prompt 分别是让一个 做网站管理员Agent,一个做评论自动回复的Agent,之后新建一个异步执行的环境类,直接使用AutoAgent包中基础类 AsyncAutoEnv就行,里面封装了 agent 异步执行和 multi-thread的细节。初始化异步执行环境需要传入 OpenAI或者是LLM API提供商的 client,配置 get_openai_client,例子里面不用配置也可以先跑只是不会调用。
def get_openai_client(): from openai import OpenAI client = OpenAI(api_key="") return client def run_async_agents_env_agentboard(): """ """ agent1_prompt = """You are playing the role of a Web admin agent... """ agent2_prompt = """You are playing the role of a Automatic reply agent...""" agent_1 = AutoAgentWorkflow(name="agent 1", instructions=agent1_prompt) agent_2 = AutoAgentWorkflow(name="agent 2", instructions=agent2_prompt) agents = [agent_1, agent_2] env = AsyncAutoEnv(get_openai_client(), agents=agents) results = env.run() if __name__ == "__main__": run_async_agents_env_agentboard()
可以看到2个Agent的执行日志,我们发现2个Agent 同时间启动,然后每个Agent在 agent loop中不同阶段等待时间不同,最终执行完一个画了 18s,一个画了 19s。
ID|Timestamp|Stage|Duration
DEBUG: Futures [<Future at 0x11e423f90 state=pending>, <Future at 0x11e434150 state=pending>]
agent 1|2024-11-22 14:51:37|PLAN Complete|5
agent 2|2024-11-22 14:51:37|PLAN Complete|5
agent 2|2024-11-22 14:51:43|ACT Complete|6
agent 1|2024-11-22 14:51:45|ACT Complete|8
agent 1|2024-11-22 14:51:50|REFLECTION Complete|5
agent 1|2024-11-22 14:51:50|END|0
agent 2|2024-11-22 14:51:51|REFLECTION Complete|8
agent 2|2024-11-22 14:51:51|END|0
Results: ['agent 1|2024-11-22 14:51:50|run_loop complete|18', 'agent 2|2024-11-22 14:51:51|run_loop complete|19']
开发2个Agent输出日志量还可以接受,如果要开发100个Agent 甚至1000个agent同时执行任务呢?执行日志和debug 几乎没办法看了,这个时候我们可以借助agentboard 把agent执行过程的 输入input,输出output,prompt这些都保存下来,然后在 agentboard 服务网页上可视化出来,方便查找日志和debug,以及监控程序运行。
AgentBoard Tutorial http://www.deepnlp.org/blog/agentBoard-ai-agent-visualization-toolkit-agent-loop-workflow
2.2 在重写的run_loop 函数用agentboard 加日志打印每个stage的输入/输出
2.2.1. Agent Loop 开始和结束打印 START/END的 workflow
函数使用agentboard库的 ab.summary.agent_loop, 入参中:
- process_id: 代表了展现流程图中的一个 workflow
- workflow_type: 会决定最终流程图的形状,start/end 都会被展示为流程图中标准的圆 process。
ab.summary.agent_loop(name="START", data="This is start stage of %s" % self.name, agent_name = self.name, process_id="START", workflow_type="start", duration = 0) ab.summary.agent_loop(name="END", data="This is end stage of %s" % self.name, process_id="END", agent_name = self.name, workflow_type="end", duration = total_duration)
2.2.2. Agent Loop 打印 ACT具体执行阶段
我们打印三条日志,都使用相同的 process_id=ACT,代表需要聚合的维度,比如包含:Action阶段打印输入input, 输出output, 调用LLM的 prompt等信息, 这3词日志要使用用相同的 process_id="ACT"。我们为了记录异步信息,在name="EXECUTION", 可以支持拓展 kwargs 的信息,把 duration 执行时间信息也打印进去。
## ACT stage ab.summary.agent_loop(name="INPUT", data="This is Act Input of %s" % self.name, agent_name = self.name, process_id="ACT", duration = 0) act_duration = await self.act() ab.summary.agent_loop(name="EXECUTION", data="This is ACT Execution Input of %s" % self.name, agent_name = self.name, process_id="ACT", duration = act_duration) ab.summary.agent_loop(name="OUTPUT", data="This is ACT Output of %s" % self.name, agent_name = self.name, process_id="ACT", duration = 0)
2.2.3. Agent打印一个Decision判断逻辑 Process
在Agent Loop中,我们经常会遇到需要做执行workflow判断工作,比如 当用户不再输入,我们就终止流程,如果用户继续追问,我们就继续调用 PLAN-ACT-REFLECT 周期。
重点设置 process_id 参数为 DECISION
process_id="DECISION"
workflow_type 为 decision
workflow_type = "decision"
这样可视化时候 workflow_type=decision流程会可视化为 决策节点。
## add a decision node log ab.summary.agent_loop(name="DECISION", data="This is decision stage of %s" % self.name, process_id="DECISION", agent_name = self.name, workflow_type = "decision", duration = 0)
2.2.4 完整的 Agent Loop 执行
我们用命令行执行agentboard,然后就可以在浏览器看到可视化的agent loop的workflow,把鼠标放到比如 ACT的输入节点上,还可以看大打印的具体内容 (对应日志的 data 字段)。
## 执行异步流程,打印到本地日志 ./log 目录下 python run_agentboard_autoagent.py ## 命令行启动agentboard 可视化流程置顶 logdir agentboard --logdir=./log
就可以看到Agent执行的逻辑了,基于这个简单例子,我们可以通过继承基础类AsyncAgent,重写 run_loop 函数拓展更加复杂的AI Agent执行逻辑,然后按照对应格式来打印日志,并且通过 agentboard 工具来可视化。同时 agentboard 也提供了 多模态的数据可视化函数,来打印 图片,语音,视频的 tensor的数据,配合 pytorch 和 tensorflow 等框架一起使用。比如针对对话历史 Chat History Messages 的可视化等具体可以参考:
相关文档
1. AutoAgent Github:https://github.com/AI-Hub-Admin/AutoAgent
2. agentboard Github: https://ai-hub-admin.github.io/agentboard
3. agentboard Tutorial: http://www.deepnlp.org/blog/agentBoard-ai-agent-visualization-toolkit-agent-loop-workflow
4. agentboard Docs: https://github.com/AI-Hub-Admin/agentboard/blob/main/docs/agentboard_docs.md
5. agentboard AI Agent Chat visualizer: http://www.deepnlp.org/workspace/dialogue_visualization