跳到主要内容

创建日期:2026-09-14 | 最近更新:2026-09-14 版本基线:LangChain.js 1.5.11 / @langchain/core 1.2.11 / @langchain/langgraph 1.4.15(2026-09 npm 核对)。本系列全部代码本机真实运行,走 DeepSeek 的 Anthropic 兼容端点(api.deepseek.com/anthropic,模型 deepseek-v4-flash)。

LangChain.js 与 LangGraph.js 入门 0:它俩是什么关系

一句话:LangChain.js 是「组件库」(模型、提示、解析、工具、检索……每样给你一个标准件,再用 LCEL 管起来);LangGraph.js 是「编排引擎」(把多步流程画成带状态、可循环、可持久化的图)。

两者同一团队,常一起用,但解决的问题不同:LangChain 让「一次模型调用/一条链」变简单;LangGraph 让「多轮、带状态、要分支和记忆的 Agent」变得可控。如果你已经跟着本站的 frontend-agent 系列 手写过工具循环,这个系列会让你看清:框架到底把你手写的哪部分接了过去。

1. 先分清两者的边界

LangChain.jsLangGraph.js
定位组件 + 组合(LCEL)有状态图编排
核心抽象Runnable(可 invoke/batch/stream)StateGraph(状态 + 节点 + 边)
擅长单次调用、提示模板、结构化输出、工具调用多步循环、条件分支、记忆/持久化、人工介入
能循环吗不建议(链是 DAG)能,这是它的主业
典型用途「问一句、抽个 JSON、调个工具」「像 Agent 那样多轮干一件事」

一个记忆锚点:LangChain 的「链」是有向无环的(DAG);Agent 需要环(loop),所以要有 LangGraph。 你手写过的 while (有 tool_use) { 执行; 回填 } ——LangGraph 把这个 while 变成图里的一条回边

2. 安装与环境

npm i langchain @langchain/core @langchain/langgraph @langchain/anthropic zod
  • @langchain/core:核心抽象(消息、Runnable、工具)——很多包都依赖它;
  • langchain:更高层的整合包(预置 agent、工具集等);
  • @langchain/langgraph:图引擎;
  • @langchain/anthropic:模型接入(本系列用它连「Anthropic 兼容端点」);
  • zod:给工具/结构化输出定义 schema(呼应本站 Zod 入门)。
  • Node:langchainNode ≥ 20langgraph 要 ≥ 18——按 20+ 准备。

3. 接入模型:一个实例,处处可用

// model.mjs —— 全系列共用
import { ChatAnthropic } from '@langchain/anthropic';

const BASE = (process.env.ANTHROPIC_BASE_URL || 'https://api.deepseek.com/anthropic').replace(/\/+$/, '');
export const model = new ChatAnthropic({
model: process.env.ANTHROPIC_MODEL || 'deepseek-v4-flash',
apiKey: process.env.ANTHROPIC_AUTH_TOKEN,
anthropicApiUrl: BASE, // ← 换成你的兼容端点即可(Claude 官方则不用传)
temperature: 0,
maxTokens: 1024, // ← 见下面的坑
});

最小验证:

import { model } from './model.mjs';
const r = await model.invoke('请只回复两个字:pong');
console.log('text =', JSON.stringify(r.text));

实测输出:

text = "pong"

⚠️ 两个真实踩到的坑(都是推理模型带来的)

  1. maxTokens 太小时,token 全被 thinking 吃掉、拿不到正文。 实测把 maxTokens 设 64,返回的 content只有 thinking 块text 是空串;设 1024 就有正常文本。
  2. content 是「块数组」,不是字符串。 推理模型的回复形如:
content 块类型: thinking,text
r.text = "pong"

所以别直接打印 r.content(你会看到一坨 thinking),用 r.text 取正文(LangChain 已帮你把 text 块拼好)。

4. 看一眼 LangGraph:最小状态图

先建立「图」的直觉——两个节点,一条流水线:

import { StateGraph, Annotation, START, END } from '@langchain/langgraph';

const S = Annotation.Root({ n: Annotation({ reducer: (a, b) => b, default: () => 0 }) });

const g = new StateGraph(S)
.addNode('inc', (s) => ({ n: s.n + 1 })) // 节点:接收状态,返回状态的“增量”
.addNode('double', (s) => ({ n: s.n * 2 }))
.addEdge(START, 'inc') // 边:START → inc → double → END
.addEdge('inc', 'double')
.addEdge('double', END)
.compile();

console.log(await g.invoke({ n: 5 }));

实测输出:

{"n":12} // (5+1)*2 = 12

看懂两个词就够了:节点(node)是函数,边(edge)是顺序;Annotation 定义「状态长什么样」。剩下的(条件边、循环、记忆)全都建立在这三件东西上。

5. 本系列路线

你会得到
1 LangChain 核心消息类型、提示模板、LCEL 管道、结构化输出(含推理模型的限制与替代方案)
2 LangGraph 入门状态/reducer、条件边、循环、MemorySaver 记忆
3 实战 ReAct AgentcreateReactAgent 搭一个真会调工具的 Agent,并与手写循环对照
4 LangGraph 图解如果 2 没看懂看这篇:mermaid 画图 + 逐步执行轨迹,把「状态怎么合并、循环怎么转」摊开讲

关联:手写版循环看 frontend-agent 2/3;模型协议看 llm-format;工具协议看 MCP

动手

  1. 装好依赖,跑通 §3 的 pong;
  2. maxTokens 改成 64 再跑一次,亲眼看看「只有 thinking、没有 text」;
  3. 跑通 §4 的最小图,改成 (n+2)*3 看结果。

自测

  1. LangChain 和 LangGraph 各解决什么问题?
  2. 为什么「链」不适合做 Agent 循环?
  3. 推理模型的回复里,thinkingtext 怎么区分?
  4. maxTokens 太小会怎样?
  5. LangGraph 里状态是由什么定义的?