LangChain.js 深度学习指南

2 阅读9分钟

项目简介

LangChain.js 是一个 TypeScript 框架,用于构建 LLM(大语言模型)驱动的应用。它将模型调用、工具使用、提示词模板、向量存储、文档检索等能力封装为统一的 Runnable 接口,让开发者可以像搭积木一样组合这些组件,构建从简单聊天到复杂 Agent 的各种 AI 应用。

项目规模

  • 1035+ 个 TypeScript 源文件
  • 40+ 个 npm 包(monorepo 结构)
  • 33 个 provider 集成(OpenAI、Anthropic、Google 等)
  • 支持 Node.js、Deno、Bun、Browser、Edge Functions 等多运行时

技术栈

维度选型说明
语言TypeScriptstrict mode, target ES2022
包管理pnpm 10.14workspace monorepo
构建编排Turborepo增量构建,任务依赖
编译tsdownESM + CJS 双输出
测试Vitest单元/集成/类型测试
Lintoxlint不是 ESLint,更快
格式化oxfmt不是 Prettier
SchemaZod v3 + v4双版本兼容

仓库结构全景

langchainjs/
├── libs/
│   ├── langchain-core/           # [核心] 所有抽象接口的定义
│   │   └── src/
│   │       ├── runnables/        # Runnable 体系 — 万物基石
│   │       ├── language_models/  # LLM/ChatModel 抽象
│   │       ├── messages/         # 消息数据模型
│   │       ├── tools/            # 工具系统
│   │       ├── prompts/          # 提示词模板
│   │       ├── output_parsers/   # 输出解析器
│   │       ├── callbacks/        # 回调/事件系统
│   │       ├── tracers/          # 追踪/观测
│   │       ├── retrievers/       # 检索器
│   │       ├── document_loaders/ # 文档加载器
│   │       ├── embeddings.ts     # 向量嵌入
│   │       ├── vectorstores.ts   # 向量存储
│   │       ├── agents.ts         # Agent 接口
│   │       ├── caches/           # 缓存
│   │       ├── load/             # 序列化/反序列化
│   │       └── utils/            # 工具函数
│   │
│   ├── langchain/                # [上层] Agent 编排、高级 Chain
│   │   └── src/
│   │       ├── agents/           # Agent 实现 (ReactAgent 等)
│   │       ├── chat_models/      # ChatModel 工厂
│   │       ├── tools/            # 内置工具
│   │       └── prompts/          # 预置提示词
│   │
│   ├── langchain-textsplitters/  # 文本分割工具
│   ├── langchain-mcp-adapters/   # MCP 协议适配
│   ├── langchain-classic/        # 旧版 API 兼容层
│   │
│   └── providers/                # 33 个第三方集成
│       ├── langchain-openai/     # OpenAI (GPT-4o 等)
│       ├── langchain-anthropic/  # Anthropic (Claude)
│       ├── langchain-google-genai/ # Google (Gemini)
│       ├── langchain-deepseek/   # DeepSeek
│       ├── langchain-ollama/     # Ollama (本地模型)
│       ├── langchain-pinecone/   # Pinecone 向量数据库
│       ├── langchain-mongodb/    # MongoDB 向量搜索
│       └── ...
│
├── examples/                     # 使用示例
│   └── src/
│       ├── createAgent/          # Agent 创建示例
│       ├── multi-agent/          # 多 Agent 协作
│       ├── llms/                 # LLM 调用示例
│       └── provider/             # 各 Provider 示例
│
├── internal/                     # 内部构建工具
│   ├── build/                    # @langchain/build
│   └── tsconfig/                 # 共享 TS 配置
│
├── AGENTS.md                     # AI Agent 开发指南 (重要参考)
├── CONTRIBUTING.md               # 贡献指南
├── turbo.json                    # Turborepo 配置
└── pnpm-workspace.yaml           # workspace 定义

核心概念深度解析

概念 1: Runnable — 万物基石

文件: libs/langchain-core/src/runnables/base.ts (3542 行)

这是整个框架最重要的抽象。LangChain.js 中的一切组件 — ChatModel、Tool、Prompt、Parser — 都是 Runnable

abstract class Runnable<RunInput, RunOutput> extends Serializable {
  // 核心方法
  abstract invoke(input: RunInput): Promise<RunOutput>;   // 单次调用
  async stream(input: RunInput): AsyncGenerator<RunOutput>; // 流式调用
  async batch(inputs: RunInput[]): Promise<RunOutput[]>;    // 批量调用

  // 组合方法 — 这是 LangChain 的灵魂
  pipe(next: Runnable): RunnableSequence;    // A.pipe(B) = A | B
  withRetry(): RunnableRetry;                // 自动重试
  withFallbacks(fallbacks): RunnableWithFallbacks; // 降级策略
  withConfig(config): RunnableBinding;       // 绑定配置
}

为什么重要:统一接口意味着任意组件可以自由组合:

// Prompt → Model → Parser 组成一条链
const chain = prompt.pipe(model).pipe(parser);
// 一行代码调用整条链
const result = await chain.invoke({ topic: "cats" });

相关文件

  • runnables/base.ts — 核心类: Runnable, RunnableSequence, RunnableParallel, RunnableLambda
  • runnables/branch.ts — 条件分支 (RunnableBranch)
  • runnables/passthrough.ts — 透传 (RunnablePassthrough)
  • runnables/router.ts — 路由分发
  • runnables/config.ts — 运行时配置 (callbacks, tags, metadata)

概念 2: Messages — 对话数据模型

文件: libs/langchain-core/src/messages/

LLM 对话的核心数据结构。所有消息都继承自 BaseMessage

BaseMessage
  ├── HumanMessage       // 用户消息 — role: "human"
  ├── AIMessage          // 模型回复 — role: "ai" (含 tool_calls)
  ├── SystemMessage      // 系统指令 — role: "system"
  ├── ToolMessage        // 工具返回值 — role: "tool"
  └── FunctionMessage    // (旧版, 已弃用)

消息内容支持多模态:

  • 纯文本: string
  • 混合内容: ContentBlock[] (文本、图片 URL、Base64 数据等)

关键设计AIMessage.contentBlocks 属性可以懒解析 provider 特定格式为标准格式。


概念 3: Language Models — 模型抽象

文件: libs/langchain-core/src/language_models/

Runnable
  └── BaseLanguageModel (base.ts)
      ├── token 计算 (getNumTokens)
      ├── 模型上下文窗口 (getModelContextSize)
      └── BaseChatModel (chat_models.ts)
          ├── invoke() → AIMessage
          ├── stream() → AsyncGenerator<AIMessageChunk>
          ├── bindTools(tools) → 绑定工具
          ├── withStructuredOutput(schema) → 结构化输出
          └── _generate() ← 子类实现此方法

Provider 只需实现 _generate() 和可选的 _streamResponseChunks() 即可接入框架。


概念 4: Tools — 工具系统

文件: libs/langchain-core/src/tools/index.ts (1076 行)

工具让 LLM 能调用外部函数。框架提供多种创建方式:

// 方式 1: tool() 函数 (推荐)
const weatherTool = tool(
  async ({ city }) => `${city} 天气: 晴, 25°C`,
  {
    name: "get_weather",
    description: "获取城市天气",
    schema: z.object({ city: z.string() }),
  }
);

// 方式 2: 继承 StructuredTool 类
class WeatherTool extends StructuredTool {
  name = "get_weather";
  description = "获取城市天气";
  schema = z.object({ city: z.string() });
  async _call({ city }) { return `${city}: 晴`; }
}

概念 5: Prompts — 提示词模板

文件: libs/langchain-core/src/prompts/

BasePromptTemplate
  ├── PromptTemplate          // 简单字符串模板
  ├── ChatPromptTemplate      // Chat 消息模板 (最常用)
  ├── FewShotPromptTemplate   // Few-shot 示例模板
  ├── PipelinePromptTemplate  // 组合多个模板
  └── ImagePromptTemplate     // 图片提示模板

使用示例:

const prompt = ChatPromptTemplate.fromMessages([
  ["system", "你是一个 {role}"],
  ["human", "{question}"],
]);
// prompt 也是 Runnable,可以 pipe
const chain = prompt.pipe(model);

概念 6: Output Parsers — 输出解析

文件: libs/langchain-core/src/output_parsers/

将 LLM 的原始文本输出解析为结构化数据:

BaseOutputParser
  ├── StringOutputParser    // 提取纯文本
  ├── JsonOutputParser      // 解析 JSON
  ├── StructuredOutputParser // Zod schema 验证
  ├── ListOutputParser      // 解析列表
  ├── XMLOutputParser       // 解析 XML
  └── BytesOutputParser     // 二进制流

概念 7: Callbacks & Tracers — 可观测性

文件: libs/langchain-core/src/callbacks/ + tracers/

LangChain 的事件系统,用于追踪、日志、调试:

CallbackManager
  ├── handleLLMStart/End/Error     // LLM 调用生命周期
  ├── handleChainStart/End/Error   // Chain 执行生命周期
  ├── handleToolStart/End/Error    // Tool 调用生命周期
  └── handleLLMNewToken            // 流式 token 回调

Tracers (内置)
  ├── ConsoleCallbackHandler       // 控制台输出
  ├── LangChainTracer              // LangSmith 追踪
  ├── LogStreamCallbackHandler     // 日志流
  └── EventStreamCallbackHandler   // SSE 事件流

概念 8: Agents — 智能体

文件: libs/langchain/src/agents/

Agent = LLM + Tools + 推理循环。框架实现了 ReAct 模式:

Agent 执行循环:
  1. LLM 接收消息 + 可用工具列表
  2. LLM 决定: 直接回复 or 调用工具
  3. 如果调用工具 → 执行工具 → 结果送回 LLM → 回到步骤 2
  4. 如果直接回复 → 返回结果

关键文件:

  • agents/ReactAgent.ts — ReAct Agent 实现
  • agents/model.ts — 模型节点
  • agents/state.ts — Agent 状态管理
  • agents/middleware/ — 中间件系统
  • agents/nodes/ — 图节点

学习路线图

第一阶段: 环境搭建与初体验 (1-2 天)

目标: 能运行项目,跑通一个最简单的例子

  1. 克隆 & 安装依赖

    cd langchainjs
    pnpm install
    pnpm --filter @langchain/core build
    
  2. 运行单元测试,确认环境正常

    pnpm --filter @langchain/core test
    
  3. 阅读入门文件

    • AGENTS.md — 项目总览、开发规范、核心抽象说明
    • CONTRIBUTING.md — 贡献流程
  4. 浏览 examples 目录

    • examples/src/llms/ — 最基础的 LLM 调用
    • examples/src/createAgent/tools.ts — 工具定义和使用

第二阶段: 掌握核心抽象 (3-5 天)

目标: 理解 Runnable 体系,能解释各组件如何组合

按以下顺序精读源码:

顺序文件重点关注
1langchain-core/src/runnables/types.tsRunnableInterface 定义
2langchain-core/src/runnables/config.tsRunnableConfig: callbacks, tags, metadata
3langchain-core/src/runnables/base.tsRunnable 抽象类, invoke/stream/batch/pipe 实现
4langchain-core/src/messages/base.tsBaseMessage 数据结构
5langchain-core/src/messages/ai.tsAIMessage, tool_calls, contentBlocks
6langchain-core/src/language_models/base.tsBaseLanguageModel 抽象
7langchain-core/src/language_models/chat_models.tsBaseChatModel._generate()
8langchain-core/src/tools/index.tsStructuredTool, tool() 函数
9langchain-core/src/prompts/chat.tsChatPromptTemplate
10langchain-core/src/output_parsers/string.ts最简单的 Parser,理解 Runnable 如何串联

练习: 手动用 RunnableSequence 将 Prompt → Model → Parser 串起来,在测试文件中验证。


第三阶段: 深入一个 Provider (2-3 天)

目标: 理解抽象如何落地为具体实现

推荐从 @langchain/openai 入手(最成熟、代码量适中):

顺序文件重点关注
1providers/langchain-openai/src/chat_models/index.tsChatOpenAI 类
2关注 _generate() 方法如何将 BaseMessage 转为 OpenAI API 格式
3关注 _streamResponseChunks()流式响应如何转为 AIMessageChunk
4关注 bindTools() 实现工具描述如何转为 API 的 functions 参数
5tests/ 目录单元测试和集成测试的写法

对比练习: 再看 @langchain/anthropic,对比两个 Provider 的实现差异,体会抽象的价值。


第四阶段: 理解 Agent 系统 (3-5 天)

目标: 理解 Agent 的执行模型和状态管理

顺序文件重点关注
1langchain/src/agents/state.tsAgent 状态定义
2langchain/src/agents/model.ts模型调用节点
3langchain/src/agents/ReactAgent.tsReAct 循环的完整实现
4langchain/src/agents/middleware.ts中间件拦截点
5examples/src/createAgent/各种 Agent 创建示例
6examples/src/multi-agent/多 Agent 协作模式

练习: 构建一个带自定义工具的 Agent,观察日志理解执行流程。


第五阶段: 回调、追踪与可观测性 (1-2 天)

目标: 理解事件系统如何贯穿整个框架

顺序文件重点关注
1langchain-core/src/callbacks/base.tsBaseCallbackHandler 接口
2langchain-core/src/callbacks/manager.tsCallbackManager 事件分发
3langchain-core/src/tracers/console.ts最简单的 Tracer 实现
4langchain-core/src/tracers/event_stream.tsSSE 事件流 (理解 streamEvents)

练习: 自定义一个 CallbackHandler,在 invoke/stream 时打印执行耗时。


第六阶段: 高级主题 (按需深入)

根据你的兴趣方向选择:

方向 A: MCP 协议适配

  • libs/langchain-mcp-adapters/src/ — 将 MCP Server 的 tools 转为 LangChain tools
  • 重点文件: tools.ts, client.ts, connection.ts

方向 B: 文本分割与检索 (RAG)

  • libs/langchain-textsplitters/ — 文本分块策略
  • langchain-core/src/retrievers/ — 检索器抽象
  • langchain-core/src/vectorstores.ts — 向量存储接口
  • langchain-core/src/embeddings.ts — 嵌入模型接口

方向 C: 序列化与加载

  • langchain-core/src/load/serializable.ts — Serializable 基类
  • langchain-core/src/load/index.ts — 动态加载机制

方向 D: 构建系统

  • internal/build/ — @langchain/build 包
  • turbo.json — Turborepo 任务编排
  • 各包的 tsdown.config.ts — ESM/CJS 双输出配置

第七阶段: 贡献代码 (进阶)

  1. 用脚手架创建 Provider

    npx create-langchain-integration
    
  2. 实现标准测试

    import { ChatModelUnitTests } from "@langchain/standard-tests";
    // 用 standard tests 验证你的实现是否符合规范
    
  3. 提交 PR 前检查清单

    • pnpm lint 通过
    • pnpm format 格式化
    • 添加/更新单元测试 (*.test.ts)
    • 添加/更新集成测试 (*.int.test.ts)
    • 无循环依赖

阅读源码的实用技巧

1. 从测试看用法

每个模块旁边都有 tests/ 目录,测试文件是最好的使用文档:

# 查看 Runnable 的测试用例
ls libs/langchain-core/src/runnables/tests/

# 查看消息系统的测试
ls libs/langchain-core/src/messages/tests/

2. 从 FakeModel 理解抽象

@langchain/core/utils/testing 提供了 FakeChatModelFakeListChatModel 等, 它们是最小化实现,适合用来理解抽象层需要实现什么。

3. 利用 TypeScript 类型系统

泛型传递是理解组件组合的关键:

  • Runnable<RunInput, RunOutput> — 输入输出类型
  • RunnableSequence — 前一个的 Output 必须匹配后一个的 Input
  • BaseChatModel — Input 是 BaseMessage[],Output 是 AIMessage

4. 关注 Zod 的使用

项目同时支持 Zod v3 和 v4,工具系统的 schema 定义重度依赖 Zod:

import { z } from "zod/v3";    // v3 写法
import { z as z4 } from "zod/v4"; // v4 写法

5. 调试技巧

# 跑单个测试文件
pnpm --filter @langchain/core test src/runnables/tests/runnable.test.ts

# Watch 模式
pnpm --filter @langchain/core test:watch

# 构建 + 监听变化
pnpm watch

常见问题

Q: langchain 和 @langchain/core 的区别?

  • @langchain/core 定义抽象接口(Runnable、BaseMessage、BaseChatModel 等)
  • langchain 提供上层实现(Agent、高级 Chain 等),依赖 core

Q: Provider 包为什么分开?

每个 provider 包是独立的 npm 包,用户只安装需要的。比如只用 OpenAI 就只装 @langchain/openai,不用拖入 Anthropic 的 SDK。

Q: 为什么用 oxlint/oxfmt 而不是 ESLint/Prettier?

性能。oxlint 用 Rust 写的,对 1000+ 文件的 monorepo,速度提升 10-100 倍。

Q: 什么是 Standard Tests?

@langchain/standard-tests 定义了一套标准测试用例,所有 Provider 都跑同一套测试,确保行为一致性。这是"面向接口编程"在测试层面的体现。


推荐资源