Skip to content

29. 如何在 LangGraph 中实现条件分支和循环? ​

难度 P0 必背 · 岗位 应用 · 频率 ★★★ · 预计阅读 7 min

本题阅读地图 ​

  1. 💡 简要回答
  2. 📝 详细解析
  3. 🎯 面试总结

👔面试官:如何在 LangGraph 中实现条件分支和循环?

🙋‍♂️我:条件分支用条件边,循环就是边连回前面的节点。

👔面试官:对,但要讲清楚:add_conditional_edges 的用法,路由函数怎么写,循环的退出条件怎么设。这些是实际编码的关键。

🙋‍♂️我:路由函数返回下一个节点名?

👔面试官:对,而且条件边可以返回多个可能的目标,在字典里映射。循环要配合退出条件(如最大步数、状态判断),否则可能无限循环。

TL;DR 速记 ​

  • 是什么:条件分支靠 add_conditional_edges,循环靠边连回前置节点。
  • 关键点:路由函数根据 State 返回路径名,再由映射表决定下一个节点。
  • 怎么答:能循环不等于能安全运行,必须同时设计退出条件,比如任务完成、步数上限、空结果次数和失败转人工。

图解 ​

💡 简要回答 ​

条件分支:

python
workflow.add_conditional_edges(
    "node_a",           # 源节点
    routing_function,   # 路由函数,返回下一个节点名
    {                   # 目标节点映射
        "path_1": "node_b",
        "path_2": "node_c"
    }
)

循环:

  • 边连回前面节点:workflow.add_edge("node_c", "node_a")
  • 退出条件:路由函数判断(如步数超限、任务完成)

📝 详细解析 ​

条件分支完整示例 ​

python
from langgraph.graph import StateGraph, END

class State(TypedDict):
    query: str
    documents: list
    answer: str
    should_continue: bool

def retrieve(state: State):
    docs = retriever.get_relevant_documents(state["query"])
    return {"documents": docs}

def generate(state: State):
    answer = llm.invoke(...)
    return {"answer": answer}

def rewrite(state: State):
    new_query = llm.invoke("改写查询:" + state["query"])
    return {"query": new_query, "should_continue": True}

def route(state: State) -> str:
    if len(state["documents"]) == 0 and state.get("should_continue", True):
        return "rewrite"
    elif len(state["documents"]) == 0:
        return "end"
    else:
        return "generate"

workflow = StateGraph(State)
workflow.add_node("retrieve", retrieve)
workflow.add_node("generate", generate)
workflow.add_node("rewrite", rewrite)

workflow.set_entry_point("retrieve")
workflow.add_conditional_edges("retrieve", route, {
    "rewrite": "rewrite",
    "generate": "generate",
    "end": END
})
workflow.add_edge("rewrite", "retrieve")  # 循环
workflow.add_edge("generate", END)

循环退出条件 ​

方式一:步数限制

python
def route(state: State) -> str:
    if state.get("step", 0) > 5:
        return "end"  # 超过5步,退出
    # ...
    return "continue"

方式二:状态判断

python
def route(state: State) -> str:
    if state.get("task_complete", False):
        return "end"
    # ...

方式三:条件组合

python
def route(state: State) -> str:
    step = state.get("step", 0)
    docs_found = len(state.get("documents", [])) > 0

    if step > 5 or docs_found:
        return "generate"
    return "rewrite"

常见踩坑与反例 ​

踩坑 1:路由函数返回节点名和映射混乱 ​

错误描述:路由函数返回 "generate",映射表里却写 "ok": "generate"。

正确做法:路由函数返回的是路径 key,必须和 add_conditional_edges 的映射 key 对齐;团队里最好用常量或枚举管理。

踩坑 2:循环没有退出条件 ​

错误描述:rewrite -> retrieve 无限连回去,期待模型自己停。

正确做法:State 中记录 step、失败次数、是否已找到结果;路由函数显式判断完成、超限和失败终态。

踩坑 3:状态字段没有被节点正确更新 ​

错误描述:路由函数判断 documents,但检索节点返回的字段名是 docs。

正确做法:先定义 State 契约,再写节点返回值;路由函数只依赖稳定字段,避免临时变量和隐式状态。

踩坑 4:把所有判断都交给 LLM ​

错误描述:「让模型判断要不要继续检索就行。」

正确做法:可让模型参与语义判断,但工程边界要用代码兜住,如最大步数、空结果、异常次数和超时。

面试官可能继续追问 ​

  • 追问 1:add_edge 和 add_conditional_edges 有什么区别? 答题要点:add_edge 是固定流转,源节点完成后一定去目标节点;add_conditional_edges 会先执行路由函数,根据 State 选择目标。

  • 追问 2:路由函数应该返回什么? 答题要点:返回路径标识,通常是字符串;这个标识再通过映射表转成具体节点或 END。

  • 追问 3:循环次数放在哪里记录? 答题要点:放在 State 里,每次进入关键节点或每轮循环时更新,路由函数基于它判断是否继续。

  • 追问 4:如何测试条件分支? 答题要点:构造不同 State 快照单测路由函数;再用端到端用例验证无结果、成功、超限、异常分支都能走到预期终态。

🎯 面试总结 ​

条件分支用 add_conditional_edges,循环是边连回+退出条件。退出条件可以是步数、状态判断或组合。


章节首页 · ← Q28 · Q30 →

最后更新2026-05-01
难度P0
频率medium
阅读7 min
主题framework
觉得有帮助?把这个链接转给正在求职的朋友 · 用 Ctrl + K 全站搜索其它题