ai-orchestration-langchain

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

LangChain.js Patterns

LangChain.js 模式

Quick Guide: Use LangChain.js (v1.x) to build composable LLM applications. Use LCEL (
prompt.pipe(model).pipe(parser)
) for all chain composition -- never use legacy
LLMChain
. Use
withStructuredOutput(zodSchema)
for typed responses. Use
createAgent()
(LangGraph-backed) for agentic workflows --
AgentExecutor
is legacy. All
@langchain/*
packages must share the same
@langchain/core
version or you get cryptic type errors at runtime.

<critical_requirements>
快速指南: 使用LangChain.js(v1.x)构建可组合的LLM应用。所有链组合都使用LCEL(
prompt.pipe(model).pipe(parser)
)——绝不要使用旧版
LLMChain
。使用
withStructuredOutput(zodSchema)
获取类型化响应。使用
createAgent()
(基于LangGraph)构建Agent工作流——
AgentExecutor
已过时。所有
@langchain/*
包必须共享相同版本的
@langchain/core
,否则运行时会出现难以理解的类型错误。

<critical_requirements>

CRITICAL: Before Using This Skill

重要提示:使用本技能前须知

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type
, named constants)
(You MUST use LCEL pipe composition (
prompt.pipe(model).pipe(parser)
) for all chains -- never use legacy
LLMChain
,
ConversationChain
, or
SequentialChain
)
(You MUST ensure all
@langchain/*
packages depend on the same version of
@langchain/core
-- version mismatches cause cryptic runtime errors)
(You MUST use
withStructuredOutput(zodSchema)
for structured LLM responses -- never manually parse JSON from completion text)
(You MUST use
createAgent()
from
langchain
for new agent code --
AgentExecutor
and
createToolCallingAgent
are legacy patterns)
(You MUST never hardcode API keys -- use environment variables (
OPENAI_API_KEY
,
ANTHROPIC_API_KEY
, etc.))
</critical_requirements>

Auto-detection: LangChain, langchain, @langchain/core, @langchain/openai, @langchain/anthropic, @langchain/google-genai, ChatOpenAI, ChatAnthropic, ChatPromptTemplate, StringOutputParser, RunnableSequence, pipe, withStructuredOutput, createAgent, createToolCallingAgent, AgentExecutor, tool, DynamicStructuredTool, RecursiveCharacterTextSplitter, MemoryVectorStore, OpenAIEmbeddings, LCEL, LangSmith, LANGCHAIN_TRACING_V2
When to use:
  • Building LLM applications that compose prompts, models, and output parsers into chains
  • Creating agentic workflows where models decide which tools to call
  • Implementing RAG pipelines with document loading, splitting, embedding, and retrieval
  • Needing structured output from LLMs with type-safe Zod schema validation
  • Streaming LLM responses token-by-token to users
  • Switching between LLM providers (OpenAI, Anthropic, Google) with a unified interface
  • Tracing and debugging LLM applications with LangSmith
Key patterns covered:
  • Chat model initialization and provider switching (ChatOpenAI, ChatAnthropic, ChatGoogleGenerativeAI)
  • LCEL chain composition with
    .pipe()
    and
    RunnableSequence
  • Prompt templates (
    ChatPromptTemplate
    ,
    MessagesPlaceholder
    )
  • Structured output with
    withStructuredOutput()
    and Zod schemas
  • Tool definition with
    tool()
    function and Zod schemas
  • Agent creation with
    createAgent()
    (LangGraph-backed)
  • RAG pipelines: document loaders, text splitters, vector stores, retrievers
  • Streaming from chains, models, and agents
  • LangSmith tracing setup
When NOT to use:
  • You only call one LLM provider and want the thinnest wrapper -- use the provider's SDK directly
  • You need React-specific chat UI hooks (
    useChat
    ,
    useCompletion
    ) -- use a framework-integrated AI SDK
  • You want a simple single-call completion with no chaining -- a direct SDK call is simpler
  • You need real-time bidirectional communication -- LangChain does not cover WebSocket/Realtime APIs

所有代码必须遵循CLAUDE.md中的项目约定(短横线命名法、命名导出、导入顺序、
import type
、命名常量)
(所有链必须使用LCEL管道组合(
prompt.pipe(model).pipe(parser)
)——绝不要使用旧版
LLMChain
ConversationChain
SequentialChain
(必须确保所有
@langchain/*
包依赖相同版本的
@langchain/core
——版本不匹配会导致难以排查的运行时错误)
(结构化LLM响应必须使用
withStructuredOutput(zodSchema)
——绝不要手动从补全文本中解析JSON)
(新的Agent代码必须使用
langchain
中的
createAgent()
——
AgentExecutor
createToolCallingAgent
是旧版模式)
(绝不要硬编码API密钥——使用环境变量(
OPENAI_API_KEY
ANTHROPIC_API_KEY
等))
</critical_requirements>

自动检测项: LangChain、langchain、@langchain/core、@langchain/openai、@langchain/anthropic、@langchain/google-genai、ChatOpenAI、ChatAnthropic、ChatPromptTemplate、StringOutputParser、RunnableSequence、pipe、withStructuredOutput、createAgent、createToolCallingAgent、AgentExecutor、tool、DynamicStructuredTool、RecursiveCharacterTextSplitter、MemoryVectorStore、OpenAIEmbeddings、LCEL、LangSmith、LANGCHAIN_TRACING_V2
适用场景:
  • 构建将提示词、模型和输出解析器组合成链的LLM应用
  • 创建模型可自主决定调用哪些工具的Agent工作流
  • 实现包含文档加载、拆分、嵌入和检索的RAG流水线
  • 需要通过类型安全的Zod模式验证获取LLM结构化输出
  • 向用户逐令牌流式传输LLM响应
  • 通过统一接口在不同LLM提供商(OpenAI、Anthropic、Google)之间切换
  • 使用LangSmith追踪和调试LLM应用
涵盖的核心模式:
  • 聊天模型初始化与提供商切换(ChatOpenAI、ChatAnthropic、ChatGoogleGenerativeAI)
  • 使用
    .pipe()
    RunnableSequence
    进行LCEL链组合
  • 提示词模板(
    ChatPromptTemplate
    MessagesPlaceholder
  • 使用
    withStructuredOutput()
    和Zod模式实现结构化输出
  • 使用
    tool()
    函数和Zod模式定义工具
  • 使用
    createAgent()
    (基于LangGraph)创建Agent
  • RAG流水线:文档加载器、文本拆分器、向量存储、检索器
  • 从链、模型和Agent进行流式传输
  • LangSmith追踪设置
不适用场景:
  • 仅调用一个LLM提供商且需要最精简的封装——直接使用提供商的SDK
  • 需要React特定的聊天UI钩子(
    useChat
    useCompletion
    )——使用集成AI的框架SDK
  • 仅需要简单的单次补全调用,无需链式操作——直接调用SDK更简单
  • 需要实时双向通信——LangChain不支持WebSocket/实时API

Examples Index

示例索引

  • Core: Setup, LCEL & Chat Models -- Package installation, chat model init, LCEL chains, prompt templates, output parsers
  • Structured Output & Tools --
    withStructuredOutput
    , tool definition, binding tools to models
  • Agents --
    createAgent
    , tool-calling agents, chat history, streaming agents
  • RAG Pipelines -- Document loaders, text splitters, vector stores, retrieval chains
  • Streaming -- Model streaming, chain streaming, agent streaming
  • Quick API Reference -- Package map, import paths, environment variables, model IDs

<philosophy>
  • 核心:设置、LCEL与聊天模型 —— 包安装、聊天模型初始化、LCEL链、提示词模板、输出解析器
  • 结构化输出与工具 ——
    withStructuredOutput
    、工具定义、将工具绑定到模型
  • Agent ——
    createAgent
    、工具调用Agent、聊天历史、流式Agent
  • RAG流水线 —— 文档加载器、文本拆分器、向量存储、检索链
  • 流式传输 —— 模型流式传输、链流式传输、Agent流式传输
  • 快速API参考 —— 包映射、导入路径、环境变量、模型ID

<philosophy>

Philosophy

设计理念

LangChain.js provides a composable framework for building LLM-powered applications. Its core abstraction is the Runnable -- any component that takes an input and produces an output. Runnables compose via LCEL (
.pipe()
) to form chains, and every Runnable supports
.invoke()
,
.stream()
,
.batch()
uniformly.
Core principles:
  1. Composability via LCEL -- Chains are built by piping Runnables:
    prompt.pipe(model).pipe(parser)
    . Each step is independently testable and replaceable. Legacy chain classes (
    LLMChain
    ,
    ConversationChain
    ) are deprecated.
  2. Provider-agnostic models -- Chat models (
    ChatOpenAI
    ,
    ChatAnthropic
    ,
    ChatGoogleGenerativeAI
    ) share a common interface. Swap providers by changing one import and model name. Use
    initChatModel()
    for runtime provider selection.
  3. Type-safe structured output --
    model.withStructuredOutput(zodSchema)
    constrains LLM responses to your schema. No manual JSON parsing.
  4. Split package architecture --
    @langchain/core
    holds abstractions, provider packages (
    @langchain/openai
    ,
    @langchain/anthropic
    ) hold implementations,
    langchain
    holds higher-level composables. All must share the same
    @langchain/core
    version.
  5. Observability built in -- Set
    LANGCHAIN_TRACING_V2=true
    and every chain/agent/tool call is traced to LangSmith automatically.
When to use LangChain:
  • You need to compose multi-step LLM workflows (prompt -> model -> parser -> next step)
  • You want to swap LLM providers without rewriting business logic
  • You need agent-style tool calling with automatic routing
  • You need RAG with document loading, chunking, embedding, and retrieval
  • You want built-in tracing and evaluation via LangSmith
When NOT to use:
  • Single-provider, single-call use cases -- the provider SDK is simpler and has less overhead
  • You want full control over HTTP requests -- LangChain abstracts the transport layer
  • Extremely latency-sensitive applications where the abstraction overhead matters
</philosophy>
<patterns>
LangChain.js是用于构建LLM驱动应用的可组合框架。其核心抽象是Runnable——任何接受输入并生成输出的组件。Runnable通过LCEL(
.pipe()
)组合成链,每个Runnable都统一支持
.invoke()
.stream()
.batch()
方法。
核心原则:
  1. 通过LCEL实现可组合性 —— 链通过管道连接Runnable构建:
    prompt.pipe(model).pipe(parser)
    。每个步骤均可独立测试和替换。旧版链类(
    LLMChain
    ConversationChain
    )已被弃用。
  2. 与提供商无关的模型 —— 聊天模型(
    ChatOpenAI
    ChatAnthropic
    ChatGoogleGenerativeAI
    )共享通用接口。只需更改一处导入和模型名称即可切换提供商。使用
    initChatModel()
    进行运行时提供商选择。
  3. 类型安全的结构化输出 ——
    model.withStructuredOutput(zodSchema)
    将LLM响应约束为指定模式。无需手动解析JSON。
  4. 拆分包架构 ——
    @langchain/core
    包含抽象层,提供商包(
    @langchain/openai
    @langchain/anthropic
    )包含实现,
    langchain
    包含更高阶的可组合组件。所有包必须共享相同版本的
    @langchain/core
  5. 内置可观测性 —— 设置
    LANGCHAIN_TRACING_V2=true
    后,所有链/Agent/工具调用都会自动追踪到LangSmith。
何时使用LangChain:
  • 需要构建多步骤LLM工作流(提示词 -> 模型 -> 解析器 -> 下一步)
  • 希望无需重写业务逻辑即可切换LLM提供商
  • 需要具备自动路由功能的Agent式工具调用
  • 需要包含文档加载、分块、嵌入和检索的RAG功能
  • 希望通过LangSmith实现内置追踪和评估
何时不使用:
  • 单一提供商、单一调用场景——提供商SDK更简单且开销更小
  • 需要完全控制HTTP请求——LangChain抽象了传输层
  • 对延迟极其敏感的应用——抽象层的开销会产生影响
</philosophy>
<patterns>

Core Patterns

核心模式

Pattern 1: Chat Model Initialization

模式1:聊天模型初始化

Initialize chat models from any provider. They all share the same interface.
typescript
import { ChatOpenAI } from "@langchain/openai";

const model = new ChatOpenAI({
  model: "gpt-4.1",
  temperature: 0,
});

const response = await model.invoke("Explain TypeScript generics.");
console.log(response.text);
Why good: Explicit model name, temperature set for determinism,
.text
accessor for content
typescript
// BAD: Hardcoded API key, no model specified
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({ apiKey: "sk-1234..." });
Why bad: Hardcoded API key is a security risk, missing model name uses unpredictable defaults
初始化任意提供商的聊天模型,它们都共享相同接口。
typescript
import { ChatOpenAI } from "@langchain/openai";

const model = new ChatOpenAI({
  model: "gpt-4.1",
  temperature: 0,
});

const response = await model.invoke("Explain TypeScript generics.");
console.log(response.text);
优势: 明确指定模型名称,设置temperature确保确定性,通过
.text
访问内容
typescript
// 错误示例:硬编码API密钥,未指定模型
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({ apiKey: "sk-1234..." });
问题: 硬编码API密钥存在安全风险,未指定模型名称会使用不可预测的默认值

Provider Switching

提供商切换

typescript
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({ model: "claude-sonnet-4-5-20250929" });

// Or use initChatModel for runtime provider selection
import { initChatModel } from "langchain";
const model = await initChatModel("openai:gpt-4.1", { temperature: 0 });
See: examples/core.md for full provider examples and configuration options

typescript
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({ model: "claude-sonnet-4-5-20250929" });

// 或使用initChatModel进行运行时提供商选择
import { initChatModel } from "langchain";
const model = await initChatModel("openai:gpt-4.1", { temperature: 0 });
参考: examples/core.md 获取完整的提供商示例和配置选项

Pattern 2: LCEL Chain Composition

模式2:LCEL链组合

Compose chains using
.pipe()
. Every component is a Runnable.
typescript
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";

const prompt = ChatPromptTemplate.fromTemplate(
  "Summarize this in one sentence: {text}",
);
const model = new ChatOpenAI({ model: "gpt-4.1" });
const parser = new StringOutputParser();

const chain = prompt.pipe(model).pipe(parser);
const result = await chain.invoke({ text: "LangChain is a framework..." });
// result is a plain string
Why good: Each step is independently testable, streaming propagates through the entire chain, swapping model is one line change
typescript
// BAD: Legacy LLMChain (deprecated)
import { LLMChain } from "langchain/chains";
const chain = new LLMChain({ llm: model, prompt });
Why bad:
LLMChain
is deprecated, does not support streaming propagation, harder to compose
See: examples/core.md for
RunnableSequence.from()
,
RunnablePassthrough
,
RunnableParallel

使用
.pipe()
组合链,每个组件都是Runnable。
typescript
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";

const prompt = ChatPromptTemplate.fromTemplate(
  "将以下内容概括为一句话:{text}",
);
const model = new ChatOpenAI({ model: "gpt-4.1" });
const parser = new StringOutputParser();

const chain = prompt.pipe(model).pipe(parser);
const result = await chain.invoke({ text: "LangChain是一个框架..." });
// result是纯字符串
优势: 每个步骤均可独立测试,流式传输可在整个链中传播,只需修改一行代码即可切换模型
typescript
// 错误示例:旧版LLMChain(已弃用)
import { LLMChain } from "langchain/chains";
const chain = new LLMChain({ llm: model, prompt });
问题:
LLMChain
已被弃用,不支持流式传输传播,组合难度更高
参考: examples/core.md 获取
RunnableSequence.from()
RunnablePassthrough
RunnableParallel
的相关内容

Pattern 3: Structured Output with Zod

模式3:基于Zod的结构化输出

Use
withStructuredOutput()
for type-safe LLM responses.
typescript
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";

const MovieSchema = z.object({
  title: z.string().describe("The movie title"),
  year: z.number().describe("Release year"),
  genres: z.array(z.string()).describe("List of genres"),
});

const structuredModel = new ChatOpenAI({
  model: "gpt-4.1",
}).withStructuredOutput(MovieSchema);
const movie = await structuredModel.invoke("Tell me about Inception.");
// movie is typed: { title: string; year: number; genres: string[] }
Why good: Output is validated against schema, fully typed, no manual JSON parsing
typescript
// BAD: Manual JSON parsing from completion text
const response = await model.invoke("Return JSON with title and year...");
const data = JSON.parse(response.text); // Fragile, untyped, can throw
Why bad: No schema validation, untyped result, model may return malformed JSON
See: examples/structured-output-tools.md for complex schemas and edge cases

使用
withStructuredOutput()
获取类型安全的LLM响应。
typescript
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";

const MovieSchema = z.object({
  title: z.string().describe("电影标题"),
  year: z.number().describe("上映年份"),
  genres: z.array(z.string()).describe("类型列表"),
});

const structuredModel = new ChatOpenAI({
  model: "gpt-4.1",
}).withStructuredOutput(MovieSchema);
const movie = await structuredModel.invoke("介绍一下《盗梦空间》。");
// movie的类型为:{ title: string; year: number; genres: string[] }
优势: 输出会根据模式进行验证,完全类型化,无需手动解析JSON
typescript
// 错误示例:手动从补全文本中解析JSON
const response = await model.invoke("返回包含标题和年份的JSON...");
const data = JSON.parse(response.text); // 脆弱、无类型、可能抛出异常
问题: 无模式验证,结果无类型,模型可能返回格式错误的JSON
参考: examples/structured-output-tools.md 获取复杂模式和边缘案例的相关内容

Pattern 4: Tool Definition

模式4:工具定义

Define tools with the
tool()
function and Zod schemas. Use
snake_case
for tool names.
typescript
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const getWeather = tool(
  async ({ location }) => {
    // Call real weather API here
    return `Weather in ${location}: 22C, sunny`;
  },
  {
    name: "get_weather",
    description: "Get current weather for a city",
    schema: z.object({
      location: z.string().describe("City name, e.g. 'San Francisco'"),
    }),
  },
);
Why good: Zod schema validates input,
.describe()
guides model's argument generation,
snake_case
name avoids provider compatibility issues
typescript
// BAD: Using DynamicStructuredTool (verbose, legacy pattern)
import { DynamicStructuredTool } from "@langchain/core/tools";
const tool = new DynamicStructuredTool({
  name: "getWeather",        // camelCase breaks some providers
  description: "...",
  schema: z.object({ ... }),
  func: async (input) => { ... },
});
Why bad:
DynamicStructuredTool
is verbose compared to
tool()
, camelCase name causes issues with some providers
See: examples/structured-output-tools.md for binding tools to models and handling tool calls

使用
tool()
函数和Zod模式定义工具,工具名称使用蛇形命名法(snake_case)。
typescript
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const getWeather = tool(
  async ({ location }) => {
    // 在此调用真实的天气API
    return `${location}的天气:22℃,晴天`;
  },
  {
    name: "get_weather",
    description: "获取城市当前天气",
    schema: z.object({
      location: z.string().describe("城市名称,例如'旧金山'"),
    }),
  },
);
优势: Zod模式验证输入,
.describe()
指导模型生成参数,蛇形命名法避免提供商兼容性问题
typescript
// 错误示例:使用DynamicStructuredTool(冗长的旧版模式)
import { DynamicStructuredTool } from "@langchain/core/tools";
const tool = new DynamicStructuredTool({
  name: "getWeather",        // 驼峰命名法会导致部分提供商出错
  description: "...",
  schema: z.object({ ... }),
  func: async (input) => { ... },
});
问题:
DynamicStructuredTool
相比
tool()
更冗长,驼峰命名法会导致部分提供商出现问题
参考: examples/structured-output-tools.md 获取将工具绑定到模型和处理工具调用的相关内容

Pattern 5: Agents with
createAgent()

模式5:使用
createAgent()
构建Agent

Use
createAgent()
for agentic workflows. It is backed by LangGraph and handles tool calling loops automatically.
typescript
import { createAgent } from "langchain";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const search = tool(async ({ query }) => `Results for: ${query}`, {
  name: "search",
  description: "Search for information",
  schema: z.object({ query: z.string() }),
});

const agent = createAgent({
  model: "openai:gpt-4.1",
  tools: [search],
  systemPrompt: "You are a helpful research assistant.",
});

const stream = await agent.stream({
  messages: [{ role: "user", content: "Find info about LangChain" }],
});
for await (const step of stream) {
  console.log(step.messages.at(-1));
}
Why good:
createAgent
handles the tool-call loop, supports streaming, manages state via LangGraph
typescript
// BAD: Legacy AgentExecutor pattern
import { AgentExecutor, createToolCallingAgent } from "langchain/agents";
const agent = createToolCallingAgent({ llm, tools, prompt });
const executor = new AgentExecutor({ agent, tools });
Why bad:
AgentExecutor
is legacy, does not integrate with LangGraph state management, less composable
See: examples/agents.md for chat history, custom state, and middleware patterns

使用
createAgent()
构建Agent工作流,它基于LangGraph,可自动处理工具调用循环。
typescript
import { createAgent } from "langchain";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const search = tool(async ({ query }) => `搜索结果:${query}`, {
  name: "search",
  description: "搜索信息",
  schema: z.object({ query: z.string() }),
});

const agent = createAgent({
  model: "openai:gpt-4.1",
  tools: [search],
  systemPrompt: "你是一个乐于助人的研究助手。",
});

const stream = await agent.stream({
  messages: [{ role: "user", content: "查找LangChain的相关信息" }],
});
for await (const step of stream) {
  console.log(step.messages.at(-1));
}
优势:
createAgent
处理工具调用循环,支持流式传输,通过LangGraph管理状态
typescript
// 错误示例:旧版AgentExecutor模式
import { AgentExecutor, createToolCallingAgent } from "langchain/agents";
const agent = createToolCallingAgent({ llm, tools, prompt });
const executor = new AgentExecutor({ agent, tools });
问题:
AgentExecutor
已过时,不与LangGraph状态管理集成,可组合性较差
参考: examples/agents.md 获取聊天历史、自定义状态和中间件模式的相关内容

Pattern 6: RAG Pipeline

模式6:RAG流水线

Load documents, split into chunks, embed, store in a vector store, and retrieve.
typescript
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { OpenAIEmbeddings } from "@langchain/openai";
import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";

const CHUNK_SIZE = 1000;
const CHUNK_OVERLAP = 200;

const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: CHUNK_SIZE,
  chunkOverlap: CHUNK_OVERLAP,
});
const chunks = await splitter.splitDocuments(docs);

const embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });
const vectorStore = new MemoryVectorStore(embeddings);
await vectorStore.addDocuments(chunks);

// Retrieve
const results = await vectorStore.similaritySearch("query", 3);
Why good: Named constants for chunk parameters, explicit embedding model,
MemoryVectorStore
for prototyping
See: examples/rag.md for full RAG chains, agent-based RAG, and production vector stores

加载文档、拆分为块、嵌入、存储到向量存储并进行检索。
typescript
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { OpenAIEmbeddings } from "@langchain/openai";
import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";

const CHUNK_SIZE = 1000;
const CHUNK_OVERLAP = 200;

const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: CHUNK_SIZE,
  chunkOverlap: CHUNK_OVERLAP,
});
const chunks = await splitter.splitDocuments(docs);

const embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });
const vectorStore = new MemoryVectorStore(embeddings);
await vectorStore.addDocuments(chunks);

// 检索
const results = await vectorStore.similaritySearch("查询内容", 3);
优势: 使用命名常量设置分块参数,明确指定嵌入模型,
MemoryVectorStore
适用于原型开发
参考: examples/rag.md 获取完整的RAG链、基于Agent的RAG和生产级向量存储的相关内容

Pattern 7: Streaming

模式7:流式传输

All Runnables support
.stream()
. Streaming propagates through LCEL chains.
typescript
const chain = prompt.pipe(model).pipe(parser);

const stream = await chain.stream({ text: "Explain quantum computing." });
for await (const chunk of stream) {
  process.stdout.write(chunk);
}
Why good: Streaming propagates through the entire chain, progressive output for better UX
typescript
// BAD: Collecting all output then displaying
const result = await chain.invoke({ text: "..." });
console.log(result); // User waits for full response
Why bad: User waits for full generation before seeing anything, bad UX for long responses
See: examples/streaming.md for model streaming, stream events, agent streaming

所有Runnable都支持
.stream()
,流式传输可在LCEL链中传播。
typescript
const chain = prompt.pipe(model).pipe(parser);

const stream = await chain.stream({ text: "解释一下量子计算。" });
for await (const chunk of stream) {
  process.stdout.write(chunk);
}
优势: 流式传输在整个链中传播,渐进式输出提升用户体验
typescript
// 错误示例:收集所有输出后再显示
const result = await chain.invoke({ text: "..." });
console.log(result); // 用户需等待完整响应
问题: 用户需等待完整生成才能看到内容,长响应时用户体验较差
参考: examples/streaming.md 获取模型流式传输、流事件、Agent流式传输的相关内容

Pattern 8: LangSmith Tracing

模式8:LangSmith追踪

Enable tracing by setting environment variables. No code changes needed.
bash
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=lsv2_...
LANGCHAIN_PROJECT=my-project
通过设置环境变量启用追踪,无需修改代码。
bash
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=lsv2_...
LANGCHAIN_PROJECT=my-project

Recommended for non-serverless environments:

非无服务器环境推荐设置:

LANGCHAIN_CALLBACKS_BACKGROUND=true

**Why good:** Zero-code setup, traces every chain/model/tool invocation, `LANGCHAIN_CALLBACKS_BACKGROUND=true` reduces latency in long-running processes

**See:** [reference.md](reference.md) for all environment variables

</patterns>

---

<decision_framework>
LANGCHAIN_CALLBACKS_BACKGROUND=true

**优势:** 零代码配置,追踪所有链/模型/工具调用,`LANGCHAIN_CALLBACKS_BACKGROUND=true`可减少长运行进程中的延迟

**参考:** [reference.md](reference.md) 获取所有环境变量的相关内容

</patterns>

---

<decision_framework>

Decision Framework

决策框架

When to Use LangChain vs Direct SDK

何时使用LangChain vs 直接使用SDK

Do you need multi-step LLM workflows (prompt -> model -> parser -> ...)?
+-- YES -> Use LangChain (LCEL chains)
+-- NO -> Do you need to swap between LLM providers?
    +-- YES -> Use LangChain (unified chat model interface)
    +-- NO -> Do you need RAG or agent tool calling?
        +-- YES -> Use LangChain
        +-- NO -> Use the provider SDK directly (simpler, fewer deps)
是否需要多步骤LLM工作流(提示词 -> 模型 -> 解析器 -> ...)?
+-- 是 -> 使用LangChain(LCEL链)
+-- 否 -> 是否需要在LLM提供商之间切换?
    +-- 是 -> 使用LangChain(统一聊天模型接口)
    +-- 否 -> 是否需要RAG或Agent工具调用?
        +-- 是 -> 使用LangChain
        +-- 否 -> 直接使用提供商SDK(更简单、依赖更少)

Which Chat Model Class

选择哪个聊天模型类

Which provider?
+-- OpenAI -> ChatOpenAI from @langchain/openai
+-- Anthropic -> ChatAnthropic from @langchain/anthropic
+-- Google -> ChatGoogleGenerativeAI from @langchain/google-genai
+-- Runtime selection -> initChatModel("provider:model") from langchain
+-- Other -> Check @langchain/community
选择哪个提供商?
+-- OpenAI -> 从@langchain/openai导入ChatOpenAI
+-- Anthropic -> 从@langchain/anthropic导入ChatAnthropic
+-- Google -> 从@langchain/google-genai导入ChatGoogleGenerativeAI
+-- 运行时选择 -> 从langchain导入initChatModel("provider:model")
+-- 其他 -> 查看@langchain/community

LCEL vs createAgent

LCEL vs createAgent

Does the model need to autonomously decide when to call tools?
+-- YES -> createAgent() (handles tool-call loops, state management)
+-- NO -> Is it a fixed sequence of steps?
    +-- YES -> LCEL chain (prompt.pipe(model).pipe(parser))
    +-- NO -> RunnableSequence.from() with branching
模型是否需要自主决定何时调用工具?
+-- 是 -> 使用createAgent()(处理工具调用循环、状态管理)
+-- 否 -> 是否为固定步骤序列?
    +-- 是 -> 使用LCEL链(prompt.pipe(model).pipe(parser))
    +-- 否 -> 使用带分支的RunnableSequence.from()

Legacy Chain vs LCEL

旧版链 vs LCEL

Are you writing new code?
+-- YES -> ALWAYS use LCEL (.pipe()) -- never legacy chains
+-- NO -> Is the existing code using LLMChain/ConversationChain?
    +-- YES -> Migrate to LCEL when touching the code
    +-- NO -> Keep as-is if it works
</decision_framework>

<red_flags>
是否在编写新代码?
+-- 是 -> 始终使用LCEL(.pipe())——绝不要使用旧版链
+-- 否 -> 现有代码是否使用LLMChain/ConversationChain?
    +-- 是 -> 修改代码时迁移到LCEL
    +-- 否 -> 若运行正常则保留原样
</decision_framework>

<red_flags>

RED FLAGS

警示事项

High Priority Issues:
  • Using legacy chains (
    LLMChain
    ,
    ConversationChain
    ,
    SequentialChain
    ) instead of LCEL -- these are deprecated
  • Mismatched
    @langchain/core
    versions across packages -- causes
    instanceof
    checks to fail silently, methods to be undefined, and type errors
  • Hardcoding API keys instead of using environment variables
  • Manually parsing JSON from LLM text output instead of using
    withStructuredOutput()
  • Using
    AgentExecutor
    for new code instead of
    createAgent()
Medium Priority Issues:
  • Using camelCase tool names (
    getWeather
    ) instead of snake_case (
    get_weather
    ) -- some providers reject camelCase
  • Not adding
    .describe()
    to Zod schema fields for tools -- model gets no guidance on argument format
  • Using
    BufferMemory
    /
    ConversationSummaryMemory
    -- these are deprecated, use LangGraph checkpointing or
    RunnableWithMessageHistory
  • Not setting
    LANGCHAIN_CALLBACKS_BACKGROUND=true
    in non-serverless environments -- adds latency to every LLM call when tracing is on
  • Importing from
    langchain/
    (main package) when the import should come from
    @langchain/core/
    or a provider package
Common Mistakes:
  • Installing
    langchain
    without
    @langchain/core
    --
    @langchain/core
    is a required peer dependency
  • Mixing
    @langchain/core
    v0.x with
    langchain
    v1.x -- all packages must be on compatible versions
  • Using
    RunnableLambda
    in a chain and expecting
    .stream()
    to work -- lambda functions do not propagate streaming by default; subclass
    Runnable
    and implement
    transform
    instead
  • Forgetting that
    ChatPromptTemplate.fromTemplate()
    creates a single user message -- use
    ChatPromptTemplate.fromMessages()
    for multi-message prompts with system/assistant/user roles
  • Using
    MemoryVectorStore
    in production -- it is in-memory only, all data is lost on restart; use a persistent vector store
Gotchas & Edge Cases:
  • @langchain/core
    is a peer dependency, not a transitive dependency. You must install it explicitly:
    npm install @langchain/core
    . If you see "cannot resolve @langchain/core" or
    instanceof
    checks failing, you likely have duplicate core versions -- run
    npm ls @langchain/core
    to check.
  • withStructuredOutput()
    uses function calling under the hood, not JSON mode. Not all models support it -- check provider docs. If the model does not support function calling, use
    JsonOutputParser
    with a prompt instead.
  • ChatPromptTemplate.fromMessages()
    uses tuple syntax
    ["system", "..."]
    or
    ["human", "..."]
    -- the role names are
    system
    ,
    human
    ,
    ai
    , not
    developer
    ,
    user
    ,
    assistant
    .
  • tool()
    from
    @langchain/core/tools
    vs
    tool()
    from
    langchain
    -- both exist. The
    langchain
    re-export is a convenience wrapper. Use whichever matches your import pattern but be consistent.
  • initChatModel()
    requires the provider package to be installed. If you call
    initChatModel("anthropic:claude-sonnet-4-5-20250929")
    without
    @langchain/anthropic
    installed, you get a confusing module resolution error, not a clear "package not installed" message.
  • Zod v4 works with
    StateSchema
    and
    createAgent
    , but
    withStructuredOutput()
    may have partial Zod v4 support -- test with your version and fall back to Zod v3.x if schema validation fails.
  • RecursiveCharacterTextSplitter
    now lives in
    @langchain/textsplitters
    (separate package), not
    langchain/text_splitter
    .
  • When using streaming with
    createAgent()
    , use
    streamMode: "values"
    to get full state at each step, or omit for incremental updates.
</red_flags>

<critical_reminders>
高优先级问题:
  • 使用旧版链(
    LLMChain
    ConversationChain
    SequentialChain
    )而非LCEL——这些已被弃用
  • 不同包之间
    @langchain/core
    版本不匹配——会导致
    instanceof
    检查静默失败、方法未定义和类型错误
  • 硬编码API密钥而非使用环境变量
  • 手动从LLM文本输出中解析JSON而非使用
    withStructuredOutput()
  • 新代码使用
    AgentExecutor
    而非
    createAgent()
中优先级问题:
  • 使用驼峰命名法(
    getWeather
    )而非蛇形命名法(
    get_weather
    )命名工具——部分提供商不接受驼峰命名
  • 工具的Zod模式字段未添加
    .describe()
    ——模型无法获取参数格式指导
  • 使用
    BufferMemory
    /
    ConversationSummaryMemory
    ——这些已被弃用,使用LangGraph检查点或
    RunnableWithMessageHistory
  • 非无服务器环境未设置
    LANGCHAIN_CALLBACKS_BACKGROUND=true
    ——启用追踪时会增加每个LLM调用的延迟
  • 应从
    @langchain/core/
    或提供商包导入时,却从
    langchain/
    (主包)导入
常见错误:
  • 安装
    langchain
    但未安装
    @langchain/core
    ——
    @langchain/core
    是必需的对等依赖
  • @langchain/core
    v0.x与
    langchain
    v1.x混合使用——所有包必须使用兼容版本
  • 在链中使用
    RunnableLambda
    并期望
    .stream()
    正常工作——lambda函数默认不传播流式传输;应继承
    Runnable
    并实现
    transform
    方法
  • 忘记
    ChatPromptTemplate.fromTemplate()
    仅创建单条用户消息——使用
    ChatPromptTemplate.fromMessages()
    创建包含系统/助手/用户角色的多消息提示词
  • 在生产环境中使用
    MemoryVectorStore
    ——它仅在内存中存储,重启后所有数据都会丢失;使用持久化向量存储
注意事项与边缘案例:
  • @langchain/core
    是对等依赖,而非传递依赖。必须显式安装:
    npm install @langchain/core
    。若出现"无法解析@langchain/core"或
    instanceof
    检查失败的情况,很可能存在重复的核心版本——运行
    npm ls @langchain/core
    检查。
  • withStructuredOutput()
    底层使用函数调用,而非JSON模式。并非所有模型都支持此功能——请查看提供商文档。若模型不支持函数调用,可使用带提示词的
    JsonOutputParser
    替代。
  • ChatPromptTemplate.fromMessages()
    使用元组语法
    ["system", "..."]
    ["human", "..."]
    ——角色名称为
    system
    human
    ai
    ,而非
    developer
    user
    assistant
  • @langchain/core/tools
    中的
    tool()
    langchain
    中的
    tool()
    ——两者都存在。
    langchain
    中的重导出是便利封装。选择与导入模式匹配的版本即可,但需保持一致。
  • initChatModel()
    要求安装对应的提供商包。若未安装
    @langchain/anthropic
    就调用
    initChatModel("anthropic:claude-sonnet-4-5-20250929")
    ,会出现混淆的模块解析错误,而非明确的"包未安装"提示。
  • Zod v4可与
    StateSchema
    createAgent
    配合使用,但
    withStructuredOutput()
    对Zod v4的支持可能不完善——请使用你的版本进行测试,若模式验证失败则回退到Zod v3.x。
  • RecursiveCharacterTextSplitter
    现在位于
    @langchain/textsplitters
    (独立包)中,而非
    langchain/text_splitter
  • 使用
    createAgent()
    进行流式传输时,使用
    streamMode: "values"
    可在每个步骤获取完整状态,省略则获取增量更新。
</red_flags>

<critical_reminders>

CRITICAL REMINDERS

重要提醒

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type
, named constants)
(You MUST use LCEL pipe composition (
prompt.pipe(model).pipe(parser)
) for all chains -- never use legacy
LLMChain
,
ConversationChain
, or
SequentialChain
)
(You MUST ensure all
@langchain/*
packages depend on the same version of
@langchain/core
-- version mismatches cause cryptic runtime errors)
(You MUST use
withStructuredOutput(zodSchema)
for structured LLM responses -- never manually parse JSON from completion text)
(You MUST use
createAgent()
from
langchain
for new agent code --
AgentExecutor
and
createToolCallingAgent
are legacy patterns)
(You MUST never hardcode API keys -- use environment variables (
OPENAI_API_KEY
,
ANTHROPIC_API_KEY
, etc.))
Failure to follow these rules will produce fragile, hard-to-debug LLM applications with version conflicts and untyped outputs.
</critical_reminders>
所有代码必须遵循CLAUDE.md中的项目约定(短横线命名法、命名导出、导入顺序、
import type
、命名常量)
(所有链必须使用LCEL管道组合(
prompt.pipe(model).pipe(parser)
)——绝不要使用旧版
LLMChain
ConversationChain
SequentialChain
(必须确保所有
@langchain/*
包依赖相同版本的
@langchain/core
——版本不匹配会导致难以排查的运行时错误)
(结构化LLM响应必须使用
withStructuredOutput(zodSchema)
——绝不要手动从补全文本中解析JSON)
(新的Agent代码必须使用
langchain
中的
createAgent()
——
AgentExecutor
createToolCallingAgent
是旧版模式)
(绝不要硬编码API密钥——使用环境变量(
OPENAI_API_KEY
ANTHROPIC_API_KEY
等))
不遵循这些规则将导致LLM应用脆弱、难以调试,出现版本冲突和无类型输出等问题。
</critical_reminders>