LangGraph控制流:条件边、循环与并行(二)

上篇文章中介绍的图是"一条直线走到底",但真实业务往往需要分支、循环和并行。这一篇涵盖了 LangGraph 怎么实现这三种控制流。

一、条件边:让图学会"分岔"

固定边只能走一条路,但很多场景需要根据数据决定下一步:

  • 用户意图是"退款"还是"咨询"?走不同分支

  • 工具调用成功还是失败?走不同处理

  • 内容审核通过还是拒绝?走不同出口

2. 基本用法

条件边由三部分组成:源节点 + 路由函数 + 映射表。

复制代码
from langgraph.graph import StateGraph, START, END

def router(state) -> str:
    """路由函数:读取 state,返回一个字符串"""
    if state["score"] >= 60:
        return "pass"
    else:
        return "fail"

builder.add_conditional_edges(
    "check_node",     # 从哪个节点出发
    router,           # 用哪个函数决定去向
    {
        "pass": "pass_node",   # 返回值 → 真实节点
        "fail": "fail_node"
    }
)

3. 执行流程

4. 简化写法

如果路由函数直接返回真实节点名,映射表可以省略:

复制代码
def router(state):
    return "pass_node" if state["score"] >= 60 else "fail_node"

builder.add_conditional_edges("check_node", router)

5. 路由函数可以返回列表(并行分发)

如果返回的是节点名列表 ,LangGraph 会并行执行这些节点:

复制代码
def router(state):
    return ["branch_a", "branch_b"]  # 两个分支并行执行

6. 路由函数可以返回 END

复制代码
def router(state):
    if state["done"]:
        return END       # 直接结束
    return "continue_node"

二、循环:让图"转起来"

LangGraph 的图是允许循环的,这是它比普通工作流引擎强大的地方。

1. 最简单的循环:节点连回自己

复制代码
builder.add_node("agent", agent_node)
builder.add_edge("agent", "agent")  # 自己连自己

但这样会无限循环,必须配合条件边来终止。

2. 用条件边实现循环

最经典的 Agent 循环模式:

复制代码
def should_continue(state) -> str:
    """判断是否继续循环"""
    messages = state["messages"]
    last_message = messages[-1]
    
    # 如果还有工具调用,继续
    if last_message.tool_calls:
        return "continue"
    # 否则结束
    return "end"

builder.add_node("agent", agent_node)
builder.add_node("tools", tool_node)

builder.add_edge(START, "agent")
builder.add_conditional_edges(
    "agent",
    should_continue,
    {
        "continue": "tools",   # 有工具调用 → 去执行工具
        "end": END             # 没有 → 结束
    }
)
builder.add_edge("tools", "agent")  # 工具执行完 → 回到 agent

3. 循环流程图

这个循环就是 ReAct 模式的核心:Agent 思考 → 调用工具 → 观察结果 → 继续思考,直到不再需要工具。

4. 防止死循环

LangGraph 提供了 recursion_limit 参数来限制最大迭代次数:

复制代码
graph.invoke(
    {"messages": []},
    config={"recursion_limit": 25}  # 最多执行 25 步
)

超过限制会抛出 GraphRecursionError。

三、并行:让图"分头行动"

1. 静态并行(多个边指向多个节点)

最直接的方式:从一个节点出发,连多条边到不同节点。

复制代码
builder.add_edge("start_node", "branch_a")
builder.add_edge("start_node", "branch_b")
builder.add_edge("start_node", "branch_c")

三个分支会并行执行 ,都完成后才进入 merge_node。

2. 用 Send 实现动态并行(Map-Reduce)

静态并行需要提前知道有几个分支。如果分支数量是动态的 ,就要用 Send。

复制代码
from langgraph.types import Send

def dispatch(state):
    """根据状态动态生成子任务"""
    return [
        Send("process_item", {"item": item})
        for item in state["items"]
    ]

builder.add_conditional_edges("split_node", dispatch, ["process_item"])

执行流程:

3. Send 与普通边的区别

特性 普通边 Send
分支数量 固定 动态
子任务状态 共享全局 State 每个子任务独立 State
典型场景 固定多分支 Map-Reduce

4. 并行分支的结果合并

多个分支同时更新 State 时,必须用 reducer 避免冲突:

复制代码
class MyState(TypedDict):
    results: Annotated[list, add]  # 多个分支的返回会追加到同一个列表

如果不用 add,后执行的分支会覆盖先执行的结果。

四、三种控制流的组合

真实业务往往是三者组合使用:

  • 条件边:意图识别分流

  • 并行:多个子任务同时处理

  • 循环:结果不满意时回到起点重试

注意

坑点 说明 解决
死循环 循环没有终止条件 设置 recursion_limit
并行覆盖 多个分支同时写同一个字段 用 Annotated + reducer
条件边不生效 路由函数返回值与映射表不匹配 检查返回值是否在映射表中
Send 子任务丢失上下文 Send 只传 state,不继承 runtime 在 state 中显式复制所需字段
相关推荐
User_芊芊君子1 小时前
一张手写菜单,我用 Seed-2.1-pro-0915 开了一家数字咖啡馆
ai·大模型·aigc
Maiko Star8 小时前
* LangChain 提示词模板详解:ChatPromptTemplate 的使用与高级特性
java·人工智能·langchain
段一凡-华北理工大学8 小时前
大模型应用开发 100 天:Python + LLM 从入门到精通 day26~Prompt 调试与优化——A/B 测试与效果评估
windows·python·大模型·prompt·智能体·提示词工程·高炉智能化
白萝卜弟弟9 小时前
【大模型Qwen3.8 27B】llama.cpp 本地大模型部署与使用
ai·大模型·agent·llama·qwen3.8
染指111011 小时前
128.Agent-LangChain核心组件-中间件-调用模型的时候
人工智能·windows·中间件·langchain·agent
做cv的小昊12 小时前
【World Model】π0.5:a Vision-Language-Action Model with Open-World Generalization
人工智能·算法·机器学习·大模型·多模态·vla·世界模型
不好听61314 小时前
LangSmith 入门:让你的Agent链路可追踪
langchain
博士僧小星15 小时前
人工智能|大模型——“痛苦向量”的定义、由来与缓解详述
人工智能·大模型·网络攻击模型·内容安全·痛苦向量
小爷毛毛(卓寿杰)16 小时前
【Agent 意图识别】输出协议、评估与置信度
人工智能·算法·大模型·prompt·大语言模型·agent