开启左侧

LangGraph基础知识( Multi-agent)(六)

[复制链接]
米落枫 发表于 昨天 22:36 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
作者:CSDN博客
一、Single-Agent 架构的局限

随着需求越来越复杂,能够预想到的以下几个非常关键的问题是:
- `Agent` 有太多工具可供使用,会导致对下一步调用哪个工具做出了混乱的决定。
- 上下文变得过于复杂,无法清晰的跟踪并传递有效信息。
- 系统中需要多个专业领域(例如规划师、研究人员、数学专家等),单一的角色背景设定没有办法匹配不同的需求。

从而引出多Multi-agent(智能体)。
二、Multi-agent

Multi-agent architectures 架构

`LangGraph`利用基于图的结构来定义代理并在它们之间建立连接。在此框架中,每个代理都表示为图中的一个节点,并通过边链接到其它代理。每个代理通过接收来自其他代理的输入并将控制权传递给下一个代理来执行其指定的操作。在`LangGraph` 框架的设计中,主要通过如下几种方法来建立各个子代理之间的通信连接:
- NetWork(网络):每个代理都可以与其他每个代理通信。任何代理都可以决定接下来要呼叫哪个其他代理。
- Supervisor(主管):每个代理都与一个 `Supervisor` 代理通信。由 `Supervisor` 代理决定接下来应调用哪个代理。
- Hierarchical(分层):定义具有 `supervisor` 嵌套 `supervisor`多代理系统。这是 `Supervisor` 架构的一种泛化,允许更复杂的控制流。
LangGraph基础知识( Multi-agent)(六)-1.png


LangGraph基础知识( Multi-agent)(六)-2.png


由此引出了一个问题:在具体实践各个不同多代理架构下的具体应用方法之前,我们需要结合`LangGraph`构建图的机制去思考一个问题:通过`State`可以让一个图中的所有节点共享全局的信息,那么在多代理架构中,当每一个图变成了一个节点,那么不同图之间的状态,应该怎么传递?
LangGraph 中引入Subgraphs (子图)处理的。
三、Subgraphs

`Subgraphs`(子图)指的是能够用作另一个图中的节点的图。简单理解就是:把一个已经编译好的图,嵌入到另一个已经编译好的图中,并且两个独立图的中的状态可以信息共享。一个典型的应用就是构建多代理系统架构。它所做的事情是:当把每个独立的`Agent`图结构定义为一个子图时,只要遵守子图的接口(输入和输出模式)规范,那么子图中定义的共享状态就可以在父图中进行使用。如下图所示:
LangGraph基础知识( Multi-agent)(六)-3.png


在这个图结构中,`final_answer`作为父图的全局共享状态,被`Sub Graph `子图访问。这个子图通过共享状态键`final_answer`进行交互,同时各自自己独立的内部状态键`summary_answer`。这种设计允许父图与子图之间通过共享状态键`final_answer`进行通信,同时保持各自的状态独立性,实现数据隔离与信息共享的平衡。
第一种情况:父、子图有共同键进行共享信息

代码示例
  1. import getpass
  2. import os
  3. from langchain_openai import ChatOpenAI
  4. from dotenv import load_dotenv
  5. from typing import TypedDict
  6. from langchain_core.messages import AnyMessage, SystemMessage, HumanMessage, AIMessage
  7. load_dotenv()
  8. llm = ChatOpenAI(model="deepseek-chat")
  9. # 定义父图中的状态
  10. class ParentState(TypedDict):
  11.     user_input: str   # 用来接收用户的输入
  12.     final_answer: str   # 用来存储大模型针对用户输入的响应
  13. def parent_node(state: ParentState):
  14.     response = llm.invoke(state["user_input"])
  15.     return {"final_answer": response}
  16. # 定义子图中的状态
  17. class SubgraphState(TypedDict):
  18.     # 这个 key 是和 父图(ParentState)共享的,
  19.     final_answer: str
  20.     # 这个key 是 子图 (subgraph) 中独享的
  21.     summary_answer:str
  22. def subgraph_node_1(state: SubgraphState):
  23.     system_prompt = """
  24.     Please summary the content you receive to 50 words or less
  25.     """
  26.     messages = state['final_answer']  # 这里接收父图传递过来的响应
  27.     messages = [SystemMessage(content=system_prompt)] + [HumanMessage(content=messages.content)]
  28.     response = llm.invoke(messages)
  29.     return {"summary_answer": response}
  30. def subgraph_node_2(state: SubgraphState):
  31.     # final_answer 仅能在 子图中使用
  32.     messages = f"""
  33.     This is the full content of what you received:{state["final_answer"]} \n
  34.     This information is summarized for the full content:{state["summary_answer"]}
  35.     Please rate the text and summary information, returning a scale of 1 to 10. Note: Only the score value needs to be returned.
  36.     """
  37.   
  38.     response = llm.invoke([HumanMessage(content=messages)])
  39.     # 发送共享状态密钥('user_input')的更新
  40.     return {"final_answer": response.content}
复制代码
定义子图的图结构并且进行编译
  1. from langgraph.graph import START, StateGraph
  2. subgraph_builder = StateGraph(SubgraphState)
  3. subgraph_builder.add_node(subgraph_node_1)
  4. subgraph_builder.add_node(subgraph_node_2)
  5. subgraph_builder.add_edge(START, "subgraph_node_1")
  6. subgraph_builder.add_edge("subgraph_node_1", "subgraph_node_2")
  7. subgraph = subgraph_builder.compile()
复制代码
定义父图的图结构,并将子图作为节点添加至父图
  1. builder = StateGraph(ParentState)
  2. builder.add_node("node_1", parent_node)
  3. # 将编译后的子图作为一个节点添加到父图中
  4. builder.add_node("node_2", subgraph)
  5. builder.add_edge(START, "node_1")
  6. builder.add_edge("node_1", "node_2")
  7. graph = builder.compile()
复制代码
原文地址:https://blog.csdn.net/m0_37242314/article/details/148656455
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题
阅读排行更多+

Powered by Discuz! X3.4© 2001-2013 Discuz Team.( 京ICP备17022993号-3 )