本节在全册位置:图跑不通时,先看清结构。LangGraph 提供 get_graph().draw_mermaid() 导出结构图,也可 draw_mermaid_png 生成图片;Platform/LangGraph Studio 提供交互式调试。本地没有 GUI 时,先看 mermaid 文本。我们调试的第一原则:先结构后状态。
get_graph().draw_mermaid() 返回 mermaid 源码,能直接贴进支持渲染的地方看拓扑。运行时用 stream 逐节点观察状态变化;配合第四章检查点可回放某次运行的每一步。调试顺序建议:先看结构对不对,再看单次运行状态对不对,最后看循环是否收敛。类比建筑:结构图像施工图,轨迹像施工日志。结构对但状态错,是图调试最常见的一类,靠逐状态观察定位。
from typing import TypedDict from langgraph.graph import StateGraph, START, END class S(TypedDict): n: int def a(s: S): return {"n": s["n"] + 1} b = StateGraph(S) b.add_node("a", a) b.add_edge(START, "a") b.add_edge("a", END) g = b.compile() # 3.3 图的可视化与调试 print(g.get_graph().draw_mermaid()) # 逐节点流式观察 for chunk in g.stream({"n": 0}): print("状态切片:", chunk)
# 看到片段就能判断归约器是否如预期工作
背景:某图预期循环三次却一直跑,日志里只有不停的模型调用。
操作:用 stream 打印每轮状态,发现归约器把计数覆盖而非累加。
结果:改为 operator.add 后循环正常收敛,轮数受控。
解读:结构对但状态错,是图调试最常见的一类,靠逐状态观察定位,而不是盲改逻辑。
变式:接 Studio 后能点开每个节点看输入输出,省去手打 stream,调试长图尤其省力。

get_graph().draw_mermaid() 导出结构,stream 看逐节点状态,两步覆盖绝大多数调试场景。
调试顺序:先看结构对不对,再看单次运行状态,最后看循环是否收敛,别一上来就改逻辑。
Platform/Studio 把轨迹可视化,本地没 GUI 时先看 mermaid 文本,结构对但状态错靠 stream 定位。
结构对但状态错是最常见的一类,只画结构不 stream 就会漏掉归约器配错;逐状态观察比盲改逻辑高效得多,这也是图调试和链调试最大的不同。
stream 的 stream_mode 参数决定每一轮吐什么,选错模式看错数据,是调试时的常见浪费。四种模式对比如下:
| 模式 | 每轮输出 | 适合看 |
|---|---|---|
| values | 完整状态快照 | 整体进度、最终态 |
| updates | 每个节点返回的增量 | 谁改了什么 |
| messages | token 级消息 | 打字机效果 |
| debug | 运行时内部事件 | 深入执行器细节 |
# updates 模式:看每个节点改了什么 for step, update in g.stream(input, stream_mode="updates"): print(step, update) # {'node_a': {'x': 1}} ← 节点名 + 该节点返回的增量
debug 模式输出的事件最全,包含节点执行前后、状态归约前后、条件边求值结果,适合排查「条件边为什么没走对」这类问题。平时用 values/updates 就够,遇到诡异行为再开 debug,不必每轮都开。
循环相关的 bug 分三层,按顺序排查效率最高:
每一层都有对应的观察手段:条件边层打印路由函数返回值;归约层用 updates 看计数通道每轮的变化;副作用层在节点入口出口各打一行。三层查完,九成循环问题都有了答案,剩下的再去查检查点是否从旧快照恢复。
get_graph().draw_mermaid() 的文本输出里藏着结构信息,先学会抓几个关键点,再考虑渲染成图:
print(g.get_graph().draw_mermaid())
输出里 ___START__ 和 __END__ 分别是入口与出口;==> 是条件边,--> 是普通边;条件边的分支会以括号列出标签。看三件事:所有节点是否都在入口到出口的路径上;条件边标签覆盖了哪些分支;有没有意外多出来的边。文本先看结构,再渲染成图看观感,这两步配合能覆盖大多数结构类问题。
LangGraph Studio 把「结构图 + 检查点 + 逐节点输入输出」合在一个界面里,调试长图的效率比纯命令行高一个量级。上手先做三件事:
Studio 的局限也先说清:它适合交互式验证,不适合批量回归;批量场景还是要回到命令行写 pytest。两条路互补——开发期用 Studio 快速定位,上线前用测试固守住。
CI 或容器里没有 Studio,调试靠三种文本手段也能闭环。第一是 get_graph 的 mermaid 文本与 draw_ascii,draw_ascii 用字符画把结构打印在终端,几行代码就能看到图长什么样。第二是 stream 配合节点内 print,在关键节点打印状态摘要。第三是把检查点历史 dump 成 JSON 看每步变化。
# ASCII 结构图:终端直接可读 print(g.get_graph().draw_ascii()) # 节点内埋点:打印当前关键字段 def probe(s): print("probe:", s["step"], s["ok"]) return {}
这三个手段都不依赖外部服务,能写进测试、能留在 CI 日志里,是团队协作时传递「当时图是什么状态」的最低成本方式。线上环境禁止 print 时,把 probe 的输出改成写日志通道,用流式把它导出来,逻辑完全一样。