news 2026/5/18 23:23:04

Runnable 才是 LangChain 真正的骨架:一次读懂 Invoke、Batch、Stream

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Runnable 才是 LangChain 真正的骨架:一次读懂 Invoke、Batch、Stream

读完这篇,你应该会把LangChain 的理解顺序彻底倒过来,不是先有 Chain、再有Agent、最后才碰Runnable。而是恰恰相反。LangChain 先把几乎所有能力都压成Runnable,再在它上面长出 LCEL、RAG、Chain、Agent 和一整套运行时能力。


你会在这篇文章里得到什么

  • 一张看清Runnable在 LangChain 里的总骨架图
  • 一套读懂 invoke、batch、stream的统一协议心智模型
  • 一个判断“为什么 stream 没有流起来”的源码级排障框架

适合谁

  • 工程实践者、框架阅读者、需要讲清 LangChain 内核的人。
  • 如果你已经会写prompt | model | parser,但还是觉得 LangChain 的概念太散,这篇会很有用。

01

背景:为什么我说骨架不是 Chain,而是 Runnable

很多人第一次学 LangChain,是从LLMChain、RetrievalQA、AgentExecutor 这种“现成对象”入手的。但沿着源码往下走,你会发现这些名字更像“产品层包装”,真正稳定的执行面其实是 Runnable。一个非常强的信号是:在源码 langchain/langchain_classic/chains/llm.py 里,LLMChain已经被标记为 deprecated,替代方案直接写成 RunnableSequence, e.g: prompt | llm。

这不是小改名。这意味着官方自己的抽象重心,已经从“预制 Chain 类”转向“可组合的统一执行协议”。

一句话结论,Runnable统一了三件事:

  1. 统一能力对象:Prompt、Model、Retriever、Tool、Parser、History 都能落到同一执行面
  2. 统一组合方式:串联是RunnableSequence,并联是 RunnableParallel
  3. 统一运行时能力:config、tracing、retry、fallback、history、dynamic config 都跟着协议走

02

总骨架:LangChain 先把一切压成 Runnable

如果只看`libs/core/langchain\_core/runnables/\_\_init\_\_.py`和 `base.py`(langchain源码) 的导出面,你会发现一个非常清晰的世界:
  • 核心抽象是Runnable
  • 组合原语是RunnableSequenceRunnableParallel
  • 包装器生态包括RunnableBindingRunnableWithFallbacksRunnableWithMessageHistory
  • 结构改写工具包括RunnableAssignRunnablePickRunnablePassthrough
  • 控制流扩展包括RunnableBranchRouterRunnable

也就是说,LangChain 并不是让每个高层对象都自带一套独立调用协议。它做的事更像是:先把异构对象都压扁成Runnable,再让它们用同一种方式被调用、被组合、被追踪。这就是“骨架”的定义。


03

三个名字,其实是一套协议:invokebatchstream

源码里最值得反复看的,其实不是某个具体子类,而是libs/core/langchain\_core/runnables/base.py这一层的默认实现关系。

invoke是单输入、单输出。

batch默认不是“模型厂商的原生批量接口”,而是“并发地调用很多次 invoke”。同步版本默认走线程池,异步版本默认走 gather_with_concurrency。

stream默认也不是天然 token streaming。对于基类来说,它只是把invoke的最终结果yield出去。

最容易被忽略的一层其实是transform

  • stream面向“单个输入,输出一个迭代器”
  • transform面向“输入本身就是 chunk 流,输出也是 chunk 流”

而基类默认的transform会先把输入 chunk 缓冲起来,再去调stream

所以从源码角度讲,真正决定“是不是边算边出”的,不是接口名里有没有stream,而是中间节点有没有认真实现transform

最小伪代码其实只有这一段:

chain = prompt | model | parser chain.invoke(x) # 单次执行 chain.batch([x1, x2]) # 并发批量 for chunk in chain.stream(x): ...

对调用者来说,链没变。变的只是“消费方式”。这正是统一协议的价值。


04

真正的组合原语只有两个:串联和并联

RunnableSequence 是 LangChain 里最重要的组合器,这句话甚至直接写在base.py的 docstring 里。

它的本质非常直接:上一个 step 的输出,就是下一个 step 的输入。

但源码里有两个细节非常关键:

  1. batch不是把整条链一起批量化,而是“一层一层向前推进”,每个 step 都调用自己的step.batch()

  2. tracing 不是糊成一团的,子运行会被打上seq:step:n这样的child callback

标记RunnableParallel则是另一种完全不同的语义:

  • 同一个输入,被扇出给多个子 Runnable
  • invoke时并发执行
  • stream时交错吐出 keyed chunks,最后再合成字典

这也是为什么在 LCEL 里,一个普通的 Pythondict能直接成为并联节点。

因为coerce\_to\_runnable()会把它自动提升为RunnableParallel

所以从读源码的角度,LCEL 其实不是“新语言”。

它只是把两种最核心的图结构写得更顺手了:

  • |= 串联
  • {...}= 扇出并联

05

为什么很多 stream 看起来不流?答案在transform边界

这是Runnable体系里最容易讲错的一点。很多人会下意识地认为:只要我调用了stream(),系统就应该一边生成一边往下游传。源码告诉你,不一定。

RunnableSequence的实现里,整条链能不能真正连续 streaming,取决于每一个组件是否都实现了transform。只要中间有一步是阻塞型的,后面的流就会被截断。

最典型的就是RunnableLambda。它非常好用,但base.py的说明写得也很直白:它默认并不擅长 streaming;如果你要做“边接收上游 chunk,边吐下游 chunk”的逻辑,更合适的是RunnableGenerator或者你自己实现transform

所以一个特别实用的排障句式是:

不是“为什么stream()失效了?”而是“这条链中间哪个节点没有实现transform,导致出现了 stream boundary?”这个判断一旦建立起来,你看 LangChain 的 streaming 问题会快很多。


06

Runnable 的外骨骼:为什么 retry、fallback、history 都能无缝粘上来

如果说SequenceParallel负责的是“结构”,那Binding和各种 wrapper 负责的就是“运行时外骨骼”。源码里这一层也非常漂亮。

你会看到很多能力都不是重写一套新协议,而是在保留invoke/batch/stream的前提下,包一层:

  • bind()负责绑定额外 kwargs
  • with\_config()负责绑定运行配置
  • with\_retry()负责失败重试
  • with\_fallbacks()负责降级切换
  • RunnableWithMessageHistory负责会话历史
  • DynamicRunnable负责运行时可配置替换

这件事的威力在于:你不用为了 tracing 造一套新对象,也不用为了 fallback 再改一套链路。因为大家都认同同一个协议面,所以能力可以横向叠加。再往下一层看libs/core/langchain\_core/runnables/config.py,你会发现RunnableConfig也不是“可选参数包”这么简单。

它真正承担的是协议传播:

  • tags
  • metadata
  • callbacks
  • max\_concurrency
  • recursion\_limit
  • configurable

ensure\_config()负责兜底和继承,patch\_config()负责给 child run 打补丁,ContextThreadPoolExecutor负责把上下文拷进并发线程里。

这就是为什么Runnable不只是“能跑”。它还负责把运行时语义完整地带着一起跑。


07

读完源码后,我会这样定义 Runnable

如果让我用一句更工程化的话来下定义:

Runnable是 LangChain 的统一执行协议。它把“单次执行、批量执行、流式执行、异步执行、结构组合、配置传播、Tracing、Fallback、History”全部压到了同一个抽象层上。所以我们平时看到的 Prompt、Model、Parser、Retriever、Tool、Agent,看起来像不同东西。但进入运行时之后,它们尽量都变成一类东西。这才是骨架。不是因为它名字底层,而是因为它承担了整个系统最稳定的“连接规则”。

三个最值得记住的坑:

  1. 不要把batch()直接理解成“底层厂商真的提供了批量 API”。在Runnable基类里,它的默认含义更接近“并发地跑很多次invoke()”。
  2. 不要把stream()直接理解成“天然逐 token 透传”。如果中间节点没有实现transform,你拿到的可能只是“最终结果的迭代器包装”。
  3. 不要把 retry、fallback、history、config 当成和主链并列的另一套系统。它们在源码里更像协议包装器,核心价值是“附着在同一执行面上”。

学AI大模型的正确顺序,千万不要搞错了

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/18 23:18:42

模型驱动应用自定义连接器:SecondaryRecordSource实战指南

模型驱动应用自定义连接器:SecondaryRecordSource实战指南 【免费下载链接】PowerApps-Samples Sample code for Power Apps, including Dataverse, model-driven apps, canvas apps, Power Apps component framework, portals, and AI Builder. 项目地址: https:…

作者头像 李华
网站建设 2026/5/18 23:16:49

Apex Legends终极压枪指南:免费自动武器检测与精准射击优化

Apex Legends终极压枪指南:免费自动武器检测与精准射击优化 【免费下载链接】Apex-NoRecoil-2021 Scripts to reduce recoil for Apex Legends. (auto weapon detection, support multiple resolutions) 项目地址: https://gitcode.com/gh_mirrors/ap/Apex-NoReco…

作者头像 李华
网站建设 2026/5/18 23:16:18

NoFences:免费开源桌面分区工具,让你的Windows桌面整洁高效

NoFences:免费开源桌面分区工具,让你的Windows桌面整洁高效 【免费下载链接】NoFences 🚧 Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences 你是否厌倦了杂乱的Windows桌面&#xff1…

作者头像 李华
网站建设 2026/5/18 23:15:08

如何实现跨设备书架同步:终极指南保持阅读进度不中断

如何实现跨设备书架同步:终极指南保持阅读进度不中断 想要在不同设备间无缝切换阅读,却总是找不到上次的阅读进度?GitHub_Trending/boo/books书架同步功能正是你需要的解决方案!这个强大的开源项目让多设备阅读体验变得前所未有的…

作者头像 李华