LangGraph State 如何解决 Agent Tools 调用可用率?

35 阅读5分钟

LangGraph State 如何解决 Agent Tools 调用可用率?

【AI大模型教程】

最近在开发 Agent 场景中,有一个 Case 是要连续调用多个 tools: 有 A、B、C 三个 tool,分别执行不同的功能,且这三个 tools  有依赖关系:

A -> B -> C -> A

prompt 方案

最开始采用的方案是 prompt 约束 + few shot,prompt 如下:

**强制行动流程**:1. **第一步**: 调用 A 更新 website 字段   - 从用户输入中提取主要的公司网站URL   - 如果有多个URL,选择最能代表公司的主网站2. **第二步**: 调用 B 添加到附件列表   - 使用与第一步相同的URL   - 等待第一步成功后再调用3. **第三步**: 调用 C 提取公司信息   - 使用相同的URL从文档中提取公司详细信息   - 根据提取结果可能需要再次调用 A 更新其他业务字段

问题 - 不能保证 100% 可用率

prompt 方案带来最大的问题是执行流程不能保证 100% 执行,偶现个别 case 下 LLM 只调用了第一个 tool,然后就中断了流程。

更好的解决方案 - LangGraph State

State 的基本用法
1. 定义状态结构
from typing import TypedDictfrom langgraph.graph import StateGraph, ENDclass GraphState(TypedDict):    input: str    output: str    step_count: int
2. 创建StateGraph实例
# 创建StateGraph,指定状态类型workflow = StateGraph(GraphState)
3. 定义节点函数
def node_1(state: GraphState) -> GraphState:    """第一个节点的处理逻辑"""    return {        "input": state["input"],        "output": f"处理了: {state['input']}",        "step_count": state.get("step_count", 0) + 1    }def node_2(state: GraphState) -> GraphState:    """第二个节点的处理逻辑"""    return {        "input": state["input"],        "output": state["output"] + " -> 进一步处理",        "step_count": state["step_count"] + 1    }
4. 添加节点
workflow.add_node("step1", node_1)workflow.add_node("step2", node_2)
5. 定义边连接
# 设置入口点workflow.set_entry_point("step1")# 添加边workflow.add_edge("step1", "step2")workflow.add_edge("step2", END)
6. 条件边的使用
def should_continue(state: GraphState) -> str:    """决定下一步走向的条件函数"""    if state["step_count"] < 3:        return "continue"    else:        return "end"# 添加条件边workflow.add_conditional_edges(    "step1",    should_continue,    {        "continue": "step2",        "end": END    })
7. 编译并运行
# 编译图app = workflow.compile()# 运行图initial_state = {    "input": "Hello World",    "output": "",    "step_count": 0}result = app.invoke(initial_state)print(result)

什么是 LangGraph State?

LangGraph 中的 State 是一个类型化的数据结构,用于在图的节点之间传递和维护信息。它类似于一个共享的内存空间,所有节点都可以读取和更新,其贯穿了Langgraph的整个生命周期。

使用 State 解决依赖关系

基本架构设计
from langgraph.graph import StateGraph, ENDfrom langchain.tools import Tool# 定义各个工具节点def search_node(state: AgentState) -> AgentState:    """搜索节点"""def extract_node(state: AgentState) -> AgentState:    """提取节点 - 依赖搜索结果"""def analyze_node(state: AgentState) -> AgentState:    """分析节点 - 依赖提取数据"""def visualize_node(state: AgentState) -> AgentState:    """可视化节点 - 依赖分析结果"""
构建依赖图

# 创建状态图workflow = StateGraph(AgentState)# 添加节点workflow.add_node("search", search_node)workflow.add_node("extract", extract_node)workflow.add_node("analyze", analyze_node)workflow.add_node("visualize", visualize_node)# 定义依赖关系(边)workflow.set_entry_point("search")workflow.add_edge("search", "extract")workflow.add_edge("extract", "analyze")workflow.add_edge("analyze", "visualize")workflow.add_edge("visualize", END)# 编译图app = workflow.compile()
条件路由处理

对于更复杂的场景,我们可以使用条件边来处理动态依赖:

def should_continue(state: AgentState) -> str:    """根据状态决定下一步"""    if state.get("errors"):        return "error_handler"    elif state.get("extracted_data"):        # 根据数据类型选择不同的分析路径        if state["extracted_data"].get("type") == "numerical":            return "statistical_analysis"        else:            return "text_analysis"    return END# 添加条件边workflow.add_conditional_edges(    "extract",    should_continue,    {        "statistical_analysis": "statistical_node",        "text_analysis": "text_node",        "error_handler": "error_node",        END: END    })

高级特性

1. 并行执行无依赖工具

当多个工具之间没有数据依赖关系时,它们可以同时执行,而不需要等待彼此完成。

场景:收集多源数据

Task A: 从数据库查询用户信息
Task B: 从API获取天气数据
Task C: 从文件系统读取配置

这三个任务互不依赖,可以同时执行!

from langgraph.graph import START# 定义两个独立的搜索节点workflow.add_node("search_db", search_database_node)workflow.add_node("search_api", search_api_node)workflow.add_node("search_files", search_files_node)# 从起点并行执行workflow.add_edge(START, "search_db")workflow.add_edge(START, "search_api")workflow.add_edge(START, "search_files")# 汇聚到合并节点workflow.add_edge("search_db", "merge")workflow.add_edge("search_api", "merge")workflow.add_edge("search_files", "merge")
```![](http://cdn.zhipoai.cn/2a05e7af.jpg)

#### 2. 循环依赖处理

循环依赖(Loop/Cycle)指的是:工作流中某个节点的输出会再次回到之前的节点,形成一个循环,用于迭代优化、重试或渐进式改进结果。

![](http://cdn.zhipoai.cn/ac8d1b54.jpg)

循坏依赖通常用于需要评估生成结果的情况,比如生成结果不理想需要重试:

![](http://cdn.zhipoai.cn/a6bf559d.jpg)

```plaintext
def refine_node(state: AgentState) -> AgentState:    """迭代优化节点"""    iteration = state.get("iteration", 0)    result = refine_tool.run(state["current_result"])        return {        **state,        "current_result": result,        "iteration": iteration + 1    }def should_refine(state: AgentState) -> str:    """判断是否需要继续优化"""    if state.get("iteration", 0) < 3:        quality = evaluate_quality(state["current_result"])        if quality < 0.8:            return "refine"    return "finish"workflow.add_conditional_edges(    "refine",    should_refine,    {        "refine": "refine",  # 循环回自己        "finish": "output"    })
3. 状态持久化与恢复

状态持久化: 将工作流的执行状态保存到存储介质(内存、数据库、文件等)
状态恢复: 从保存的检查点恢复工作流,继续之前的执行

这就像游戏中的"存档"和"读档"功能!

from langgraph.checkpoint import MemorySaver# 使用检查点保存状态memory = MemorySaver()app = workflow.compile(checkpointer=memory)# 运行并保存状态config = {"configurable": {"thread_id": "task_123"}}result = app.invoke(initial_state, config=config)# 从检查点恢复并继续执行resumed_result = app.invoke(None, config=config)

最后

在完成通过 state 来处理依赖关系的改造后,tools 调用问题得以彻底解决,不再担心 LLM 只调用了其中某一个工具。