代理架构¶
许多LLM应用在LLM调用之前和/或之后实现特定的控制流程。例如,RAG执行与问题相关的文档检索,并将这些文档传递给LLM以确定模型的响应。
我们有时希望LLM系统能够选择自己的控制流程,以解决更复杂的问题,而不是硬编码固定的控制流程!这就是代理的一种定义:代理是一个使用LLM来决定应用程序控制流程的系统。 LLM可以以多种方式控制应用:
- LLM可以在两个潜在路径之间进行路由
- LLM可以决定调用多个工具中的哪一个
- LLM可以决定生成的答案是否足够,或者是否需要更多工作
因此,有许多不同类型的代理架构,这些架构赋予LLM不同级别的控制。

路由器¶
路由器允许LLM从指定的一组选项中选择一个步骤。这是一种代理架构,展现了相对有限的控制级别,因为LLM通常只管理一个决策,且可以返回一小组输出。路由器通常采用几种不同的概念来实现这一点。
结构化输出¶
使用LLM的结构化输出通过提供LLM在响应中应遵循的特定格式或模式来工作。这类似于工具调用,但更为广泛。虽然工具调用通常涉及选择和使用预定义的函数,结构化输出可以用于任何类型的格式化响应。实现结构化输出的常见方法包括:
- 提示工程:指示LLM以特定格式进行响应。
- 输出解析器:使用后处理从LLM响应中提取结构化数据。
- 工具调用:利用某些LLM的内置工具调用功能生成结构化输出。
结构化输出对于路由至关重要,因为它确保LLM的决策可以被系统可靠地解释和执行。有关结构化输出的更多信息,请参见此指南。
工具调用代理¶
虽然路由器允许LLM做出单个决策,更复杂的代理架构在两个关键方面扩展了LLM的控制:
- 多步骤决策:LLM可以控制一系列决策,而不仅仅是一个。
- 工具访问:LLM可以选择并使用多种工具来完成任务。
ReAct是一种流行的通用代理架构,它结合了这些扩展,整合了三个核心概念。
工具调用:允许LLM按需选择和使用各种工具。记忆:使代理能够保留并使用来自先前步骤的信息。规划:使LLM能够创建和遵循多步骤计划以实现目标。
这种架构允许更复杂和灵活的代理行为,超越简单的路由,实现跨多步骤的动态问题解决。您可以通过create_react_agent使用它。
工具调用¶
只要您希望代理与外部系统互动,工具都是非常有用的。外部系统(例如,API)通常需要特定的输入模式或负载,而不是自然语言。例如,当我们将API绑定作为工具时,我们给模型提供了所需输入模式的意识。模型将基于用户的自然语言输入选择调用某个工具,并返回符合该工具模式的输出。
许多LLM提供商支持工具调用,而LangChain中的工具调用接口非常简单:您只需将任何Python function传递给ChatModel.bind_tools(function)。

记忆¶
记忆对于代理至关重要,使它们能够在多个问题解决步骤中保留和利用信息。它在不同层面上运作:
- 短期记忆:允许代理访问在序列中早期步骤中获得的信息。
- 长期记忆:使代理能够回忆起先前互动中的信息,例如对话中的过往消息。
LangGraph提供了对记忆实现的完全控制:
State:用户定义的模式,指定要保留的记忆的确切结构。Checkpointers:在不同互动的每一步存储状态的机制。
这种灵活的方法使您能够根据特定代理架构的需求量身定制记忆系统。有关如何将记忆添加到图表的实用指南,请参见本教程。
有效的记忆管理增强了代理保持上下文、从过去经验学习和随时间作出更明智决策的能力。
规划¶
在ReAct架构中,LLM在while循环中被重复调用。在每一步,代理决定调用哪些工具,以及这些工具的输入应该是什么。然后执行这些工具,并将输出反馈到LLM作为观察。当代理决定不再调用更多工具时,while循环终止。
ReAct实现¶
本文和预构建的create_react_agent实现之间存在几个差异:
- 首先,我们使用工具调用让LLM调用工具,而本文使用的是提示 + 原始输出解析。这是因为在撰写本文时工具调用并不存在,但通常更好且更可靠。
- 其次,我们使用消息来提示LLM,而本文使用字符串格式。这是因为在撰写时,LLM甚至没有暴露基于消息的接口,而现在是它们唯一暴露的接口。
- 第三,本文要求对工具的所有输入必须是一个单一的字符串。这在很大程度上是因为当时的LLM能力有限,实际上只能生成单个输入。我们的实现允许使用需要多个输入的工具。
- 第四,本文仅查看一次调用单个工具,这在很大程度上是由于当时LLM性能的限制。我们的实现允许一次调用多个工具。
- 最后,本文要求LLM在决定调用哪些工具之前明确生成“思考”步骤。这是“ReAct”的“推理”部分。我们的实现默认不这样做,主要是因为LLM已经变得更强大,而这并不是那么必要。当然,如果您希望提示它这样做,您当然可以。
自定义代理架构¶
尽管路由器和工具调用代理(如ReAct)很常见,但定制代理架构往往会导致特定任务的更好性能。LangGraph提供了多个强大功能来构建定制的代理系统:
人机协同¶
人类的参与可以显著提高代理的可靠性,尤其是在敏感任务中。这可能涉及:
- 批准特定行动
- 提供反馈以更新代理状态
- 在复杂决策过程中提供指导
当完全自动化不可行或不可取时,人机协同模式至关重要。在我们的人机协同指南中了解更多。
并行化¶
并行处理对于高效的多代理系统和复杂任务至关重要。LangGraph通过其Send API支持并行化,使得:
- 同时处理多个状态
- 实现类似于映射-归约的操作
- 高效处理独立子任务
有关实际实施,请参见我们的映射-归约教程。
子图¶
子图对于管理复杂的代理架构至关重要,特别是在多代理系统中。其允许:
- 各个代理的独立状态管理
- 代理团队的分层组织
- 代理与主系统之间的受控通信
子图通过状态模式中的重叠键与父图进行通信。这使灵活和模块化的代理设计成为可能。有关实施细节,请参阅我们的子图如何做指南。
反思¶
反思机制可以显著提高代理的可靠性,通过:
- 评估任务完成情况和正确性
- 提供反馈以实现迭代改进
- 实现自我修正和学习
虽然通常基于LLM,反思也可以使用确定性方法。例如,在编码任务中,编译错误可以作为反馈。这种方法在此视频中展示,使用LangGraph进行自我纠正的代码生成。
通过利用这些功能,LangGraph可以创建复杂的、特定任务的代理架构,处理复杂的工作流,有效协作,并持续提高其性能。