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 中显式复制所需字段
相关推荐
BD_Marathon2 小时前
LangChain的简介
langchain
ikun_文2 小时前
LangChain-常用场景
langchain·agent
刘 大 望5 小时前
Agent 的规划与执行范式:Plan-Execute-Replan 与 ReAct
java·python·ai·chatgpt·langchain·ai编程
张张123y6 小时前
后端第十二课:Agent 开发(让大模型从“会答“升级到“会做“)
前端·大模型·llm·agent·rag
昭昭日月明7 小时前
使用 Ragas 量化 RAG
python·langchain·ai编程
小易老师AI实战7 小时前
VLLM部署Qwen大模型性能压测实践:自研Python压测脚本+指标解读
大模型·私有化部署·qwen·vllm·llm推理·性能压测
云水初7 小时前
【agent篇】RAG Agent避坑指南(附高级RAG Agent汇总)
开发语言·笔记·python·学习·langchain·agent·rag
薛定猫AI8 小时前
【技术干货】多AI团队大模型协作编排与编程项目评测架构解析
python·机器学习·ai·大模型·技术实战
深海鱼肝油ya8 小时前
企业级RAG问答系统(一)数据处理模块
人工智能·大模型·pdf文件解析·rag问答系统·智能分块
小粉粉hhh8 小时前
大模型RAG和Agent智能体(一)——初了解
gpt·langchain·aigc