LangChain 设计与实现

深入 LangChain 1.0 的源码与架构。

prompt | model | parser 这三个竖线,是 LangChain 里最像魔法的一行。它凭什么能同步调、异步调、流式调、批量调,还自动带上重试、回调和配置?

答案是一个协议:Runnable。整个 LangChain 就是"把所有东西都变成 Runnable,然后让它们能用 | 拼起来"。本专栏以 langchain-core 1.2.26 / langchain-classic 1.0.3 源码快照为解剖对象,从这个协议开始往下拆。

flowchart TB
  subgraph R [Runnable 协议 · 一切的地基]
    direction LR
    SEQ[RunnableSequence<br/>管道骨架] --- PAR[RunnableParallel<br/>分叉汇聚]
    PAR --- BR[RunnableBranch<br/>条件分支]
    BR --- FB[WithFallbacks<br/>优雅降级]
  end
  PT[PromptTemplate] --> R
  R --> LM[BaseChatModel<br/>invoke / stream / bind_tools]
  LM --> OP[OutputParser<br/>Str / Json / 结构化]
  LM -.工具.-> TL["BaseTool<br/>@tool · StructuredTool"]
  R -.每一步都穿过.-> CB[Callbacks / Tracer<br/>astream_events]
  DOC[Documents] --> RET[Retrievers / VectorStore] --> R

为什么值得读源码。 LangChain 的文档教你怎么拼,但拼出来的东西为什么能流式、RunnableConfig 在嵌套调用里怎么传下去、with_structured_output 到底做了什么、回调是怎么穿过每一层的 —— 这些只有源码会告诉你。而它们恰恰是出问题时你必须知道的东西。

读完你能做到什么

  1. 手写一个 Runnable,并让它无缝接进任何管道。 | 操作符的实现、六个组合原语各自的职责、RunnableConfig 的完整生命周期,以及 fallback 的降级路径(第3章 Runnable 与 LCEL)。
  2. 说清一次 model.invoke() 的完整链路。BaseLanguageModelBaseChatModel,同步与异步两条路径、_generate 这个扩展点、token 计数与 UsageMetadata 从哪来(第5章 语言模型)。
  3. 驾驭流式输出。 MessageChunk 的增量合并规则、stream 的实现,以及 astream_events / astream_log 这两个调试利器(第4章 消息体系第12章 回调与追踪)。
  4. 写出模型第一次就能调对的工具。 @tool 装饰器背后的 create_schema_from_function、Tool 与 StructuredTool 的分野、InjectedToolArg 运行时注入、把 Runnable 和 Retriever 直接变成工具(第8章 工具系统)。
  5. 搭一条可控的 RAG 链路。 Document 抽象、检索器接口、create_history_aware_retriever 这类历史感知检索的实现(第9章 文档第10章 检索器)。
  6. 把老代码迁到 LCEL。 Chain 基类为什么是"连接两个时代的桥梁"、SequentialChain / RouterChain 对应到 LCEL 的哪个原语(第11章 Chain)。
  7. 理解 Agent 的执行循环。 规划、工具调用、结果回填,以及 tool-calling agent 与传统 ReAct agent 的差别(第14章 Agent第15章 工具调用 Agent)。

这个专栏的讲法

锚定版本,不讲"大概"。 所有分析都基于 langchain-core 1.2.26 / langchain-classic 1.0.3 这个确定的快照 —— LangChain 迭代快,不锚定版本的源码分析半年后就是误导。

每章末尾是「设计决策分析」。 为什么消息要拆成 Content Blocks、为什么回调用 Mixin 架构、为什么工具有两套范式 —— 讲取舍,不只讲实现。

覆盖到边界。 序列化机制、partner 包的组织方式(第16章 序列化第17章 生态)—— 你要写自己的集成时会用到这两章。

适合谁读

不适合:找 LangChain 入门教程或 API 速查的读者 —— 官方文档更合适。这里从第 3 章开始就在读源码。

目录

第一部分:开篇

第二部分:核心抽象

第三部分:模型与提示

第四部分:工具与检索

第五部分:组合与编排

第六部分:Agent 系统

第七部分:生产与进阶

源码版本

本专栏基于 langchain-core 1.2.26langchain-classic 1.0.3 源码分析。仓库为 monorepo, langchain-core 的每个发布版都有对应的 git tag,checkout 到本专栏的基准快照即可逐行对照:

git clone https://github.com/langchain-ai/langchain.git
cd langchain
git checkout langchain-core==1.2.26     # 对应 commit 0a1d290a,2026-04-03

该快照下三个包的对应关系(libs/ 目录名与包名并不一一对应,容易踩坑):

目录 包名 该快照版本 本专栏用量
libs/core/langchain_core/ langchain-core 1.2.26 主要解剖对象
libs/langchain/langchain_classic/ langchain-classic 1.0.3 Chain / Memory / 经典 Agent
libs/langchain_v1/langchain/ langchain 1.2.15 少量引用

别把 langchain-classic 1.0.3 当成 langchain 1.0.3

1.0 拆包后,0.x 时代的 ChainMemoryAgentExecutor 等被整体迁入独立发行的 langchain-classic。本专栏讲这些经典组件时引用的 1.0.3 是 langchain-classic 的版本号 (2026-03-13 发布);PyPI 上的 langchain 1.0.3 是 2025-10-29 发布的另一个包,不要混淆。

核心代码在 libs/core/libs/langchain/ 目录下。

版权声明

本专栏内容为 杨艺韬 版权所有,保留一切权利。未经书面许可,不得全文或大段转载、改编、翻译,或用于任何商业用途(含以本专栏内容训练模型、生成衍生课程或商品)。

欢迎分享本专栏的链接。引用少量内容用于评论、教学或研究时,请署名 杨艺韬 并附上原文链接。