5.10 使用 create_agent 搭建 Mini ChatGPT#
在第4.10节内容中我们详细介绍了 ReAct 框架的原理并且知道了 LangChain 中 create_agent 函数背后的实现机制就是基于的 ReAct 范式。同时,在第5.6节和第5.9节我们也分别介绍了如何从零实现 ReAct 处理流程,为了后续能够更加方便及熟练地使用 LangChain 中的 creat_agent 来进行多 Agent 开发,在本节内容中将会介绍如何使用 create_agent 来完成 Mini ChatGPT 的构建。
5.10.1 整体设计思路#
create_agent 是 LangChain 基于 LangGraph 提供的一个Agent 快速构造函数(Factory Function),用于构建一个具备消息管理、工具调用、循环推理和状态控制能力的 Agent 运行时,使开发者无需手动搭建图结构就能够创建一个符合 ReAct 思想的智能体。直白一点,我们可以将 create_agent 理解成一个快速构建单一智能体的方法,它将大模型调用、工具管理以及 Agent 的执行流程进行了统一封装,开发者只需要提供模型、工具和必要的配置,即可获得一个可以独立完成任务的智能体。
正因为 create_agent 已经封装好了单一智能体的大部分运行逻辑,所以在绝大多数问答和 RAG 等场景中,我们只需要使用一个 create_agent 就能够完成需求。而当业务流程变得更加复杂,需要多个智能体协同工作时,则可以进一步利用 LangGraph 提供的图编排能力,将多个 Agent 组织成一个更复杂的 Multi-Agent 系统。
在本节内容中将要介绍的便是在所有功能一致的情况下如何使用单一的 create_agent 来完成 Mini ChatGPT 的构建,并且有了前面两种实现过程的对比,我们将对 create_agent 有着更加清晰地认识。需要说明的是,基于 create_agent 的版本将依然依赖于 LangGraph 中 PostgresSaver 与 PostgresStore 来分别完成短期记忆和长期记忆的管理,最终,构建完成后的 Agent 其内部编排逻辑如图5-16所示。
从图5-16可以看出,使用 create_agent 函数所搭建的 Agent 其内部编排逻辑的确就是一个符合 ReAct 思想的单一智能体。同时,由于 create_agent 内部依旧是基于 LangGraph 所实现,所以整个工程只需要对 agent.py 模块中的逻辑进行改造即可,完整示例代码可参见 Code/Chapter05/mini-chatgpt-agent 工程目录。
5.10.2 Agent 参数组装#
由于调用 create_agent 需要对应的参数及上下文环境, 这里通过CreateAgentApp 类来实现参数的构造及 Agent 对象的返回。首先定义初始化方法及 PostgresMemoryStore 实例化对象的获取,示例代码如下:
1 class CreateAgentApp:
2 def __init__(self, checkpointer: PostgresSaver, store: PostgresStore):
3 self.checkpointer = checkpointer
4 self.store = store
5
6 def get_memory_store(self, memory_root: str) -> PostgresMemoryStore:
7 return PostgresMemoryStore(self.store, memory_root)进一步,定义 build_runtime_agent 方法来完成 create_agent 的初始化,示例代码如下:
1 def build_runtime_agent(self, context, user_text: str,
2 search_memory_limit: int, recursion_limit: int = 20):
3 def build_system_prompt(memory_store: PostgresMemoryStore,
4 user_id: str,user_text: str,search_memory_limit: int, ) -> str:
5 memory_hits = memory_store.search(user_id, user_text, search_memory_limit)
6 return SYSTEM_PROMPT.format(user_info=_format_memories(memory_hits),
7 time=datetime.now().isoformat(timespec="seconds"))
8
9 system_prompt = build_system_prompt(context.memory_store, context.user_id,
10 user_text, search_memory_limit)
11 tool = build_postgres_memory_tool(context.memory_store, context)
12 return create_agent(load_chat_model(context.model),[tool],store=self.store,
13 checkpointer=self.checkpointer, system_prompt=system_prompt,
14 context_schema=Context).with_config(recursion_limit=recursion_limit)在上述代码中,第3~7行用于构建 Agent 对应的系统提示词。第11行返回对应的记忆插入及更新工具。第12~14行则是调用 create_agent() 把模型、工具、短期记忆检查点、长期记忆存储以及上下文结构统一封装为可运行的 Agent,其中第14行recursion_limit 表示指定最大循环步数,如果不指定则默认允许的最大循环步数是 9999 步。
最终,同之前一样依旧是通过 get_agent 函数来返回搭建完成的智能体,示例代码如下:
1 def get_agent(checkpointer: PostgresSaver, store: PostgresStore) -> CreateAgentApp:
2 return CreateAgentApp(checkpointer=checkpointer, store=store)5.10.3 Agent 循环构建#
在完成 create_agent() 的初始化以后需要定义一个循环来完成 Agent 的每一步执行,即“思考-行动-观察-思考”的迭代,示例代码如下:
1 def invoke_agent(agent: CreateAgentApp, thread_id: str,
2 user_text: str, args) -> str:
3 memory_store = agent.get_memory_store(args.memory_root)
4 context = Context(user_id=args.user_id, thread_id=thread_id, model=args.model,
5 memory_root=args.memory_root, memory_store=memory_store)
6 config = RunnableConfig({"configurable": {"thread_id": thread_id,
7 "user_id": context.user_id, "memory_root": context.memory_root,
8 "search_memory_limit": args.search_memory_limit}})
9 runtime_agent = agent.build_runtime_agent(context, user_text,
10 args.search_memory_limit, args.recursion_limit)
11 last_msg = ""
12 for i, event in enumerate(run_agent.stream({"messages": {"role": "user",
13 "content": user_text}]}, stream_mode="values", config=config)):
14 last_msg = message_text(event["messages"][-1])
15 return last_msg在上述代码中,第3~8行用于构建上下文即配置参数,其中第6行 "thread_id": thread_id 主要用于 PostgresSaver 中对于短期记忆的维护。第9~10行则是返回构建完成的 Agent 。第12~14行则是循环执行 ReAct 框架中 Agent 的每一步,其中第14行取出最后一条消息文本作为阶段性输出。这里的 stream() 本质上就是让 Agent 在 LangGraph 管理的状态流中逐步推进,每一次 event 都代表当前完整消息状态,当stream_mode="values"时表示每次全量输出完整消息,设为 "updates" 时表示每次输出增量内容。
到此,我们就把 agent.py 模块改造完了,后续运行方法参见第5.9.9节内容即可,这里就不再赘述。
5.10.4 小结#
本节基于 mini-chatgpt-agent 工程,介绍了一个更接近工程实践的 Mini ChatGPT 助手实现。与之前的版本相比,这一版的核心改变在于使用了集成封装度更高的 create_agent 来完成 Agent 的构建,这也为我们下一章内容的学习奠定了基础。