LangGraph — 做一个会停下来的智能体
目标
使用 LangGraph 创建一个查询库存的小型 agent。八个步骤涵盖 graph、累积状态、 条件分支、可停止的循环、tool node、失败路径、checkpointer 和路径记录。
不调用模型
负责判断的 node 使用规则实现。因为本实验教授的不是模型调用,而是 graph—— 何时停止、状态中携带什么、tool 失败时走向哪里。agent 真正困难的部分就在这里; 以后接入模型,只是替换一个 node。
格式
在 /root/work/agent/graph.py 中定义以下内容。
build_graph(checkpoint: bool = False)——返回 compile 后的 graph。CATALOG——按商品保存库存的字典(从第 5 步开始使用)。
状态中至少包含 question、steps(list)、tries(integer)和 answer。
搭建并运行一个 graph
执行 mkdir -p /root/work/agent 后,在 graph.py 中定义 build_graph()。创建 StateGraph,添加一个 node,并返回 compile() 的结果。在状态中放置 steps list,让 node 记录自己的名称。
build_graph().invoke() 可以运行,steps 中留下 node 名称
让状态不断累积
把 node 增加到两个,让它们都在 steps 中留下名称。如果不使用 Annotated[list, operator.add],只会保留最后一个值——走过的路径会消失。
经过至少两个不同 node,并且它们都保留在 steps 中
根据问题选择分支
用 add_conditional_edges 创建分支。包含“库存”的问题进入 lookup node,其他问题进入另一个 node。
“库存”问题经过 lookup,问候语不会经过 lookup
可以循环,但必须停止
找不到结果时重新尝试。状态中加入 tries,并设置上限(约 3 次)。没有上限会触及递归限制并以异常结束。
循环至少运行 2 次,并在 5 次以内自行停止
真正使用 tool 的结果
在 CATALOG 字典中放入至少 3 条数据(商品:数量),让 lookup 从问题中识别商品并查询。查询到的值必须真正写入 answer。
CATALOG 的值反映在 answer 中
tool 失败不是异常,而是一条路径
查询列表中不存在的商品时,进入 fallback node,并生成表示“未找到”的 answer。把空结果直接传下去会促使系统编造答案,这是产生幻觉最常见的路径。
查询不存在的商品时经过 fallback,answer 表达“不知道”的含义
把对话连接起来
支持 build_graph(checkpoint=True),并挂载 MemorySaver。确认状态会按 thread_id 隔离——相同 id 能延续,不同 id 分开保存。
可通过 get_state 看到保存的状态,并按 thread_id 分开管理
记录走过的路径
运行两个会走不同分支的问题,把 {질문: [노드, ...]} 保存到 /root/work/agent/08-trace.json。如果记录与真实执行不同,就无法用它诊断任何问题。
08-trace.json 中的路径与真实执行一致,并且两条路径彼此不同