发布时间:2026/7/30 1:57:04
langgraph教程系列-02-让流程分叉-条件边与路由 本文是「LangGraph 教程系列」第 2 篇。写作时基于 langgraph 1.2.10、langchain 1.3.14、langchain-deepseek 1.1.0、Python 3.12。配套代码仓库 https://github.com/wxj006007/deep-research-assistant 本篇对应 tagv0.1。上一篇我们用 State / Node / Edge 三件套把 v0 跑了起来还立了个 flag链和循环都是图的特例Agent 需要的判断和分叉只有图能表达。这一篇就来兑现「分叉」。一、v0 撞的墙一条道走到黑给 v0 提两个问题LangGraph 是哪家公司开源的为什么 Agent 框架纷纷从链式结构转向图结构第一个是事实型问题有客观标准答案好的回答应该准确、简短。LangChain Inc.完事。第二个是分析型问题没有标准答案好的回答应该多角度展开、给出推理过程。但 v0 只有一个answer节点、一套系统提示词。结果就是两头不讨好事实型问题它答出一篇小作文分析型问题它草率地丢一个结论。你想想看「简洁准确」和「充分展开」这两个目标本身就是矛盾的一套提示词没法同时优化。解法很自然先判断问题类型再走不同的分支。这在链里做不到管道在写代码时就焊死了。在图里这就是一条条件边conditional edge。二、v0.1 的图结构factualanalyticalSTARTclassify判断问题类型factual_answer简洁准确地回答analytical_answer多角度展开分析END实线是普通边必然走虚线是条件边运行时二选一。整个 v0.1 相比 v0 的变化answer节点一分为二前面加了一个classify节点中间用条件边接起来。三、动手实现3.1 State加一个字段classResearchState(TypedDict):question:strquestion_type:str# factual | analyticalanswer:str相比 v0 只多了question_type。分类结果要写进 state因为路由的依据必须存在于 state 里。这是 LangGraph 的基本纪律节点之间不直接传参一切经过 state。3.2 分类节点让 LLM 当裁判defclassify_node(state:ResearchState)-dict:llmget_llm()responsellm.invoke([(system,你是一个问题分类器。判断用户问题属于哪一类\n- factual有客观标准答案的事实型问题是什么、何时、多少\n- analytical需要推理和多角度讨论的分析型问题为什么、如何评价、利弊\n只输出 factual 或 analytical 这一个单词不要输出其他内容。),(human,state[question]),])labelresponse.content.strip().lower()# 兜底分类器输出意外内容时按分析型处理iflabelnotin(factual,analytical):labelanalyticalreturn{question_type:label}这里有两个工程细节。一个是强约束输出提示词里写死「只输出一个单词」。分类节点的输出要喂给程序逻辑不是给人看的越死板越好。另一个是必须有兜底LLM 是概率模型总有一天它会给你输出Factual.或者一段解释。这个事儿我也踩过坑strip().lower()处理大小写和空白白名单校验兜住其余所有意外。宁可答得啰嗦走分析型不可让图在运行时崩掉。3.3 两个回答节点各自优化各自的目标deffactual_answer_node(state:ResearchState)-dict:llmget_llm()# temperature0要稳responsellm.invoke([(system,你是一个研究助手。这是一个事实型问题请给出准确、简洁的答案不要展开议论。),(human,state[question]),])return{answer:response.content}defanalytical_answer_node(state:ResearchState)-dict:llmget_llm(temperature0.7)# 分析型允许更发散responsellm.invoke([(system,你是一个研究助手。这是一个分析型问题请从多个角度展开分析给出推理过程最后总结你的观点。),(human,state[question]),])return{answer:response.content}分支的价值在这里显形。两个节点不只提示词不同连 temperature 都不同事实型要 0稳定可复现分析型给 0.7允许发散。如果没有分叉这种「按题施策」根本无从谈起。3.4 路由函数条件边的扳道工defroute_by_type(state:ResearchState)-Literal[factual,analytical]:returnstate[question_type]就这三行就这三行。路由函数的职责被刻意压到最小读 state返回一个字符串别的什么都不干。新手最容易犯的错是把分类逻辑写进路由函数在里面调 LLM、做判断。不是说这样跑不起来而是说它违背了 LangGraph 的设计意图节点干活边选路。节点classify可以调用模型、可以有副作用、结果写进 state可以被 checkpoint 记录第 6 篇会讲为什么这很重要。路由函数应该是纯函数只读 state 做决定快进快出。把它们分开图的每一步都有据可查。混在一起路由就成了监控和调试的盲区。3.5 组装add_conditional_edgesbuilderStateGraph(ResearchState)builder.add_node(classify,classify_node)builder.add_node(factual_answer,factual_answer_node)builder.add_node(analytical_answer,analytical_answer_node)builder.add_edge(START,classify)builder.add_conditional_edges(classify,# 从哪个节点出发route_by_type,# 用哪个函数选路{# 返回值 - 目标节点 的映射factual:factual_answer,analytical:analytical_answer,},)builder.add_edge(factual_answer,END)builder.add_edge(analytical_answer,END)graphbuilder.compile()add_conditional_edges三个参数出发节点、路由函数、映射表。映射表把路由函数的返回值翻译成目标节点名。这里两个键恰好和节点名部分重合但它们是两个命名空间路由函数返回的是「路名」映射表才决定「路通向哪」。第三个参数可以省略此时路由函数直接返回节点名。但我自己的感受是显式写映射表更划算LangGraph 能据此画出准确的图结构而且路由逻辑和图拓扑解耦改节点名不用改路由函数。3.6 跑起来questions[LangGraph 是哪家公司开源的,为什么 Agent 框架纷纷从链式结构转向图结构,]forquestioninquestions:resultgraph.invoke({question:question})print(f分类{result[question_type]})print(f回答{result[answer]}\n)第一个问题被分到factual回答一两句话。第二个被分到analytical回答分点展开。同一个图两条执行路径这就是条件边。四、几个值得记住的点顺着上面的再聊聊有三个点值得单独拎出来。条件边是「运行时」的决策。普通边在你写代码时就定了条件边到invoke那一刻才知道走哪条。这是图对链最根上的超越流程结构可以响应数据。路由依据一定要落在 state 里。你可能想分类和路由合成一步多省事。这个想法不是没道理代码确实能少几行。但 state 里留下question_type好处是调试时能看到分类结果下游节点能引用它将来做 checkpoint 回放时它是历史的一部分。state 是图的记忆别绕过它抄近道。分支可以不止两条。映射表想加几个键就加几个键。将来你的助手可能要区分闲聊、事实、分析、需要检索四种类型条件边的写法不变只是映射表变长。五、本篇小结回到「分叉」这块v0 撞的墙是一套提示词无法同时服务事实型和分析型问题解法是classify节点判断类型再用add_conditional_edges按类型选路。过程中我们顺手立了三条纪律节点干活边选路路由函数保持纯函数。路由依据写进 state不走私下传参。LLM 分类必须有兜底白名单校验防止图崩溃。v0.1 会分叉了但它还有个隐患没暴露。目前每个字段都是「整存整取」新值直接覆盖旧值。等到下一步我们让助手做多轮检索问题就来了第二次检索的结果会把第一次的覆盖掉。检索结果应该是累积的不是覆盖的。状态如何累加而不是覆盖下一篇reducer 登场。赞或收藏 关注 我们下次再见

相关新闻

2026/7/30 1:57:04

【项目】uni-app校园课程管理系统(源码+文档)【独一无二】

校园课程管理系统项目说明 项目描述 校园课程管理系统是一款基于 Vue 3 与 uni-app 开发的跨平台课程信息管理应用,可面向 H5、App及微信小程序等终端运行。项目围绕学生查看课表和管理员维护课程两类需求,将月历展示、课程查询、详情浏览、身份登录与数…

2026/7/30 1:57:03

AI内容检测率不降反升的原因与解决方案

1. 问题现象:AI检测率为何越改越高?最近不少开发者反馈一个诡异现象:使用AI工具修改AI生成内容后,检测平台的AI率不降反升。某技术社区用户实测显示,一篇原始AI率为37%的文案,经过三次"优化"后飙…

2026/7/30 1:57:03

C语言字符串处理函数深度解析:从原理到实战避坑指南

1. 为什么C语言字符串处理函数值得你花时间?在嵌入式开发、系统编程或者任何需要与底层内存打交道的场景里,C语言依然是那个绕不开的基石。而字符串处理,作为程序与用户、程序与文件、程序与网络之间最常见的交互形式,其效率和正确…

2026/7/30 3:07:09

MATLAB实战:白噪声、粉红噪声与布朗噪声的生成与验证

1. 从“沙沙声”到“轰鸣声”:噪声世界的分类与初探在信号处理、通信系统、音频工程乃至金融数据分析的日常工作中,“噪声”是一个我们既爱又恨的伙伴。恨它,因为它会淹没我们想要的有用信号;爱它,因为一个设计良好的系…

2026/7/30 3:07:09

香橙派Zero 2驱动ILI9341 SPI LCD屏幕:设备树配置与驱动调试全攻略

1. 项目概述与核心价值最近在折腾香橙派Zero 2这块小板子,手头正好有一块闲置的2.4寸SPI接口LCD屏,驱动芯片是经典的ILI9341。在最新的Linux 6.1.31内核下,想把这块屏幕点亮,整个过程踩了不少坑,也总结了一些在主流教程…

2026/7/30 3:07:09

游戏角色技能设计:从机制到平衡的完整指南

卡通宇宙角色与技能介绍(第二期)在上一期内容中,我们初步探索了卡通宇宙中几位经典角色的基础设定与能力体系。本期将深入解析更多具有代表性的角色,从技能机制、战斗风格到背景故事,为开发者提供完整的角色设计参考模…

2026/7/30 3:07:09

Python项目部署实战:从环境配置到Nginx+Gunicorn生产级部署

1. 从本地到云端:一个Python项目的完整部署旅程作为一名在开发一线摸爬滚打了十多年的老码农,我见过太多优秀的Python项目,在本地开发环境里跑得风生水起,一到部署上服务器就“水土不服”,各种报错、依赖缺失、环境冲突…

2026/7/30 3:07:09

Unity游戏移植微信小游戏:三步法避坑与性能优化实战

1. 项目概述:从原生App到微信小游戏的“惊险一跃”如果你是一个Unity开发者,手头有一个已经跑得不错的原生游戏(比如iOS/Android的.apk或.ipa),现在老板或者市场部门跟你说:“咱们把这个游戏搬到微信小游戏…

2026/7/30 3:02:09

HarmonyOS NEXT 企业级记账APP:设计 Repository 与数据模型

设计 Repository 与数据模型 本文是《HarmonyOS NEXT 企业级开发实战:30篇打造智能记账APP》系列的第 07 篇,对应 Git Tag v0.0.7。承接第 06 篇的 BillCard 组件,本篇设计 BaseRepository 抽象基类与三个具体 Repository,并完成 …

2026/7/29 22:32:30

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

2026/7/30 0:01:39

[GESP202606 四级] 扫雷

B4557 [GESP202606 四级] 扫雷 https://www.luogu.com.cn/problem/B4557 中国计算机学会(CCF)2026年6月C四级讲解——扫雷 https://www.bilibili.com/video/BV1MCMg6AEXR/ B4557 [GESP202606 四级] 扫雷 https://www.bilibili.com/video/BV1ZKTj6ZEVh/ 2…

2026/7/30 0:01:39

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/29 13:12:43

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…