第11课:LangChain|SequentialChain顺序链|路由链多任务智能分发实战
摘要:本文系统介绍了LangChain中任务编排的核心技术,从传统顺序链到现代LCEL流水线的演进路径。主要内容包括: 编排范式对比:传统SimpleSequentialChain与现代RunnableSequence的差异,后者支持流式处理和异步调用 核心组件解析: RunnableSequence实现线性数据管道 RunnableBranch完成条件路由分发 RunnableParallel实

文章目录
课程导读 & 学习目标
在前面的课程中,我们已经构建了完整的LangChain技术栈。第5-8课我们练就了精准的"提示词手艺",第9课我们理清了RunnableSequence的本质。但大多数真实业务永远不是"Prompt → LLM → 输出"这一刀切的线性流程——它可能同时包含"先总结后翻译"的多步传递,也可能根据用户意图分发给不同的处理路径。这些任务编排能力,才是LangChain区别于纯openai.Completion.create调用的核心竞争力。
本节课,你将站在LangChain 0.3.x的思维高度,从经典SequentialChain(旧版顺序链)到现代LCEL流水线,再到RunnableBranch智能路由,系统掌握LangChain中编排多条执行链的核心能力。我会带你亲身经历这些组件的历史演变,并在LCEL的基础上构建功能更强大、可观测性更强的多任务智能分发系统。
学完本节课,你将达到以下目标:
- 透彻理解顺序链的两种形态:掌握
SimpleSequentialChain(单输入单输出)的适用场景、局限性,以及它与更通用的SequentialChain(多输入多输出)之间的对比。 - 精通LCEL的多步编排语法:用
RunnableSequence实现顺序步骤,掌握RunnableParallel并行分组执行,熟练使用RunnableLambda完成中间数据映射。 - 彻底掌握路由链核心机制:理解
RunnableBranch条件分发的工作原理,并掌握"先分类→后路由"的标准两段式架构。 - 理解废弃Chain类的迁移路径:掌握从旧版
SimpleSequentialChain、SequentialChain、LLMRouterChain到RunnableSequence和RunnableBranch的完整演进路径。 - 完成四个完整项目实战:从简单的顺序链、多依赖顺序链,到并行数据处理,再到大规模多任务智能分发路由链。
前置知识与环境准备
1.1 Python版本与开发工具
继续使用前几课的langchain_course虚拟环境,确保Python 3.10+。
1.2 依赖包安装
# 激活虚拟环境
source venv/bin/activate # Mac/Linux
# venv\Scripts\activate # Windows
# 基础依赖
pip install langchain==0.3.7 langchain-core==0.3.21 langchain-openai==0.2.8 python-dotenv==1.0.1
# 验证安装
python -c "from langchain_core.runnables import RunnableSequence, RunnableBranch, RunnableParallel, RunnableLambda; print('✓ LCEL组合组件导入成功')"
1.3 API密钥与模型选择
沿用前几课的.env配置(智谱GLM-4或Ollama本地模型)。本节课编排逻辑不涉及模型种类特殊限制,本地模型可流畅运行。
核心概念深度拆解
2.1 什么是Chain——LangChain中的"执行管道"
如果把PromptTemplate、ChatModel、OutputParser比作AI应用工具箱里的三把"精密改锥"——它们功能单一但超好用。那么,本节课要介绍的Chain(链) 就是那把"多功能螺丝刀头":它允许你把多个改锥头串联成一个完整的工序流程,一次扭转一颗螺丝。
从LangChain 0.3.x的视角重新定义Chain,这句话最为精确:Chain就是一个RunnableSequence——由多个Runnable组件通过|管道符串联而成的线性数据管道。
这个定义揭示了现代Chain的两个本质特征:
- 组件即Runnable —— Chain的每一个构成单元(提示模板、模型、解析器、自定义函数)都实现了
Runnable接口,意味着它天生具备.invoke()、.stream()、.batch()三种标准调用方式。 |即拼接 —— 管道符|在底层对应RunnableSequence的构造,输出类型兼容是数据流转的前提,前一步的输出必须能被后一步的输入接收。
2.2 废弃的旧世界:SimpleSequentialChain与SequentialChain
LangChain早期版本,开发者往往通过SimpleSequentialChain和SequentialChain这两个类来实现多步骤流水线。前者将多个LLMChain串联成一个单输入/单输出链,一条链的输出直接作为下一条链的输入。后者则更通用,允许多输入/多输出,需要在每个步骤中手动指定输入映射和输出映射,配置起来较为繁琐。
这两个旧式Chain的核心问题在于:
- 继承自
LLMChain体系 ——LLMChain本身已在v0.1.17被标记为废弃,将在v1.0中被彻底移除。 - 灵活性与扩展性严重不足 —— 无法与现代LCEL生态无缝集成,难以实现条件分支、流式输出等先进特性。
- 代码冗余且可读性差 —— 相比于
prompt | model | parser,旧式写法需要大量样板代码。
2.3 现代的RunnableSequence——LCEL顺序编排范式
LCEL的出现重新定义了LangChain中的Chain构建方式。它通过管道符|以声明式描述数据流转,一条链的构建完全类比Unix Shell的管道操作——输入从最左端流入,从最右端流出。LangChain官方将LCEL称为"Unix pipes for AI"。
LCEL构建的链具备以下核心优势:支持流式输出、批处理、异步调用等高级功能,且与LangChain所有新组件无缝集成。
2.4 路由链(Routing)——根据上下文智能分发
当单一流水线无法满足多元化业务场景时,需要路由链来根据用户输入自动选择执行路径。典型的场景包括:
- 意图分流:用户问数学题走"数学专家子链",问SQL查询走"数据库子链"
- 成本控制:轻量级问题走廉价模型,复杂推理才调用高性能模型
- 多用户角色匹配:普通用户走通用提示,VIP用户走定制化场景
RunnableBranch是LangChain官方提供的条件分发组件,它设计为链式的if/elif/else执行器。执行时从左到右依次评估各分支的条件函数,命中第一个返回True的分支即执行对应子链,无命中则执行默认分支。
2.5 并行执行链——多个独立任务同时处理
当流程中的某些步骤互不依赖时,可同时执行以提高效率。LCEL通过RunnableParallel实现这种并行模式,接收一个字典,键值各自对应独立的Runnable。执行时所有键值Runnable并发运行,结果合并为字典输出,然后将完整数据交给后续组件处理。
底层运行原理剖析
3.1 LCEL链的执行路径追踪
一条典型的prompt | model | parser链在执行invoke时具体发生了什么?前一个组件的原始输出不会直接流入下一个组件,数据经过的中间转换过程对于链式编排至关重要:
- 提示模板 (Runnable):接收用户输入字典,按模板填充
{variable}占位符,生成字符串格式的提示词。 - 模型 (ChatModel):接收字符串提示词,发送HTTP请求,返回
AIMessage对象。 - 解析器 (OutputParser):接收
AIMessage,提取.content属性,返回纯字符串。
RunnableSequence在这个链条中扮演"指挥者"的角色:接收到外部输入后,依次调用列表中的每个Runnable的invoke方法,并用前者的输出作为后者的输入。
3.2 RunnableBranch的条件匹配机制
RunnableBranch以闭包形式捕获条件函数和对应子链。执行时,invoke方法将输入逐一遍历条件函数,一旦某条件返回True,即调用对应子链的invoke,直接返回其结果,不再检查剩余分支。若无分支匹配,则调用默认子链。若未配置默认分支也无匹配,抛出异常。
3.3 RunnableParallel的并发调度
RunnableParallel初始化时接收一个字典,每个键值代表一个Runnable及其参数。当invoke被调用时,它会同时并发执行字典中所有的Runnable任务,待全部任务完成后,将所有结果按原键名合并为一个字典,并作为最终输出。此模式对于同时查询多个知识库、调用多个独立API等场景极为适用,可有效降低整体延迟。
核心API/组件源码解读
4.1 RunnableSequence——串联一切Runnable
RunnableSequence接收任意数量的Runnable对象,按顺序存入列表。
4.2 RunnableBranch——条件分发器
RunnableBranch接收条件函数+子链对列表,并附带一个默认子链。invoke执行时遍历所有条件函数,调用它们并传入当前输入,若函数返回True则立即调用对应子链并返回结果。若无匹配,执行默认子链。
条件函数可以是普通的Pythonlambda表达式,也可以是任何可调用对象。分支的顺序决定了优先级,因此通常应将最具体、最严格的条件放在最前面。
4.3 RunnableParallel——并发调度器
RunnableParallel将输入同时分发到多个可运行链中。初始化接收一个字典,定义多个任务,键名会在结果字典中保留。执行时所有任务并发运行,完成后将各分支的输出按字典形式合并输出。
4.4 RunnableLambda——纯函数转Runnable
RunnableLambda包装普通Python函数为Runnable对象。当输入数据需要清洗或数据格式转换时,这是一个轻量又灵活的办法,无需定义复杂的自定义类。
4.5 旧路由模块的废弃与演进
LLMRouterChain、MultiRouteChain等旧路由类在LangChain v0.1中曾被广泛使用,现已被官方标记为deprecated,并在v1.0中彻底移除。现代路由标准方案是:用RunnableBranch实现条件路由,被路由到的子链即为LCEL风格的RunnableSequence。
手把手项目实战教学
实战一:多步顺序链——“先大纲再写作”
目标:构建两级顺序链,第一步生成短视频脚本大纲,第二步基于大纲扩展出完整视频脚本。体验子链与输入输出如何序列传递。
实战二:顺序链中的多步数据映射——“先总结再翻译”
目标:先对长文本生成中文摘要,再将摘要翻译成英文。这是一条完全线性的两步链:第一步的输出作为第二步的输入,不需要额外的数据映射逻辑。
实战三:RunnableParallel并行执行——多源信息同时处理
目标:同时询问三个AI专家对"可再生能源"的看法,一次性并发获取所有专家的回答。通过RunnableParallel显式定义并行分支,将所有专家独立的推理任务并发执行。
实战四:RunnableBranch多任务智能客服路由链
目标:构建智能路由系统,根据用户问题的类别(技术/产品/售后/其他),自动将请求分发到不同的子链处理。架构清晰分为两个阶段:先调用分类器提取意图关键词,再通过RunnableBranch路由。
分类器本身就是一个极简单的prompt | model | parser链,输出意图类别。主路由组件接收分类结果后,根据类别执行相应的子链。这种设计使得路由逻辑与业务逻辑彻底解耦。
完整可运行Python代码
首次运行时,请确保激活虚拟环境并已安装依赖,同时配置好.env文件中的API密钥。
环境依赖安装命令
# 激活虚拟环境
source venv/bin/activate # Mac/Linux
# venv\Scripts\activate # Windows
# 核心依赖(确保0.3.x版本)
pip install langchain==0.3.7 langchain-core==0.3.21 langchain-openai==0.2.8 python-dotenv==1.0.1
# 仅当使用本地Ollama模型时才安装此包
pip install langchain-ollama
# 一键安装所有依赖
pip install langchain==0.3.7 langchain-core==0.3.21 langchain-openai==0.2.8 python-dotenv==1.0.1 langchain-ollama
常见报错坑点与避坑方案
坑1:TypeError: 'AIMessage' object is not callable 链组合出错
现象:链中出现TypeError,错误指向AIMessage不可调用。
原因:链中直接拼接了model对象和后续组件,但LCEL的|运算符要求右侧必须是Runnable。由于AIMessage不是Runnable,管道操作会失败。
解决:在model之后总是通过StrOutputParser()或JsonOutputParser()将模型输出解析为基本类型。
坑2:路由链命中分支不符合预期
现象:条件函数明明匹配,却走了默认路径。
原因:RunnableBranch的条件函数必须能接收当前输入作为唯一参数。多数错误都是传入方式不一致引起——输入是字符串时,条件函数应直接检查x,而不是从字典取值。
解决:仔细检查条件函数签名和返回值类型,在分支前使用RunnableLambda打印或调试输入内容,确认输入格式与条件判断逻辑匹配。
坑3:RunnableParallel中某一分支失败,整个链崩溃
现象:并行执行时,一个API调用错误引发整个链失败。
原因:RunnableParallel默认是所有任务全成功才能返回结果。
解决:为关键分支配置RunnableWithFallback兜底逻辑,或使用RunnableRetry优化重试策略。
坑4:顺序链中输出格式不兼容导致链断裂
现象:prompt | model | model_2时报错,第二个模型的输入不能接收AIMessage。
原因:第一个model的输出是AIMessage对象,而第二个model期望的输入是字符串或消息列表。不添加解析器直接拼接第二个模型会中断自动适配链的流程。
解决:在第一个model后添加.invoke()并配合StrOutputParser(),或者用RunnableLambda显式做映射lambda x: x.content。
坑5:LangChainDeprecationWarning 提示 LLMChain 被废弃
现象:导入langchain.chains.LLMChain或使用SequentialChain时看到废弃警告。
原因:LLMChain在v0.1.17中被标记为废弃,将在v1.0中移除。任何建立在此之上的旧Chain类都会触发警告并官方推荐迁移。
解决:迁移到RunnableSequence或prompt | llm。若遗留代码必须兼容,继续使用旧API但接受警告;新项目严禁使用。
本节核心知识点总结
📌 顺序链的体系演进:旧版LangChain的SimpleSequentialChain和更强大的SequentialChain已随LLMChain被标记为废弃,现代版本推荐使用LCEL的RunnableSequence范式进行顺序编排。
📌 内部组件RunnableSequence —— 通过管道符|组装任意Runnable组件形成执行链,输入从左流入,从右流出,自动获取stream、batch、ainvoke等高级能力。
📌 并行执行RunnableParallel —— 同时执行多个分支任务并将结果合并输出。适合向多个独立知识源发送同个问题的召回场景,能显著降低整体延迟。
📌 条件路由RunnableBranch —— 实现if/elif/else条件分发。构建"先分类→后路由"的两步架构:先用轻量分类链将输入分"类",再通过RunnableBranch将任务分发给不同的子链。
📌 数据映射RunnableLambda —— 将普通Python函数包装成Runnable嵌入LCEL链中,适合做清洗数据、格式转换等中间处理。
📌 废弃组件的迁移路线图:SimpleSequentialChain→RunnableSequence(顺序链);LLMRouterChain→RunnableBranch(路由链);所有旧Chain类都在通往LangChain 1.0的路上被清理干净。
课后练习题
选择题
1. 在现代LangChain(v0.3.x)中构建顺序链推荐的写法是?
A. SequentialChain(chains=[chain1, chain2])
B. SimpleSequentialChain(chains=[chain1, chain2])
C. chain1 | chain2
D. Chain.compose([chain1, chain2])
答案及解析:【C】。LCEL通过管道符实现RunnableSequence的组合,是LangChain 0.3.x的推荐模式。SequentialChain和SimpleSequentialChain属于旧版API,已被标记为废弃。
2. 以下哪个组件最适合实现“给话题,先写大纲,再扩充内容”的两步骤执行?
A. RunnableParallel
B. RunnableLambda
C. RunnableSequence
D. RunnableBranch
答案及解析:【C】。将两个Runnable顺序拼接,前一个处理完的数据直接用于第二个。RunnableParallel为并发设计,RunnableBranch用于多条件分发,不符合需求。
3. RunnableBranch的执行顺序是?
A. 同时执行所有分支,选择最快的结果。
B. 随机选择一个分支,随机后执行。
C. 从左到右依次评估条件,命中第一个就执行对应分支。
D. 从右到左依次评估条件,命中最后一个就执行对应分支。
答案及解析:【C】。RunnableBranch严格按照声明顺序评估条件,首个条件满足的分支被执行。
简答题
4. 请分别说明RunnableSequence和RunnableParallel的适用场景,并举例。
参考答案:
RunnableSequence:适用于严格的顺序流程,例如先调用模型生成大纲,再调用另一个模型扩充内容;或先提取JSON字段,再将字段传递给新模板。RunnableParallel:适用于多个独立、互不依赖的任务同时执行,例如同时向三个知识库检索同一问题、并行调用三个不同的API。
5. 描述RunnableBranch实现条件路由的两阶段架构。
参考答案:条件路由分为两阶段:第一阶段是"意图分类阶段",用一个简单的分类链(通常一个prompt | llm | parser)分析输入,输出意图关键词。第二阶段是"路由执行阶段",RunnableBranch接收该输出,通过条件函数匹配分支,将请求分发到针对性的子链。此架构的好处是分类器与业务链解耦。若新增业务场景,只需扩展分类器输出和RunnableBranch分支,无需修改已有子链。
实践题
6. 编写代码实现RunnableBranch多分支智能客服助手。要求:
- 用户输入"天气查询:北京"时,走天气查询分支。
- 用户输入"计算:100*0.85"时,走数学计算分支。
- 默认分支走通用闲聊分支。
- 必须使用
RunnableBranch实现。
参考答案:
from langchain_core.runnables import RunnableBranch, RunnableLambda
def classify_weather(x):
return "weather" in x.lower()
def classify_calc(x):
return "计算" in x or any(op in x for op in ['+', '-', '*', '/'])
weather_chain = RunnableLambda(lambda x: f"北京天气:晴天,24℃")
calc_chain = RunnableLambda(lambda x: f"计算结果:100 * 0.85 = {100 * 0.85}")
general_chain = RunnableLambda(lambda x: f"通用回答:我收到你的消息“{x}”')
branch = RunnableBranch(
(classify_weather, weather_chain),
(classify_calc, calc_chain),
general_chain
)
print(branch.invoke("天气查询:北京"))
print(branch.invoke("计算:100*0.85"))
print(branch.invoke("你好"))
🔗《30节课 LangChain 从入门到精通》系列课程导航
🌟 感谢您耐心阅读到这里!
💡 如果本文对您有所启发欢迎:
👍 点赞📌 收藏 📤 分享给更多需要的伙伴。
🗣️ 期待在评论区看到您的想法, 共同进步。
🔔 关注我,持续获取更多干货内容~
🤗 我们下篇文章见~
更多推荐


所有评论(0)