引言:为什么在 2025 年我们需要 LangChain?
2022 年底,ChatGPT 的横空出世标志着大模型(LLM)时代的到来。但在实际开发中,我们很快发现:直接调用大模型接口就像是在裸奔。 当你的业务逻辑变得复杂------需要动态构造提示词、需要串联多个任务、需要根据不同模型进行适配时,简单的 fetch 或官方 SDK 就会显得捉襟见肘。
这正是 LangChain 存在的意义。它不仅是一个 AI 开发框架,更是一套关于 "如何构建 AI 应用" 的方法论。
第一层:基础适配------让 LLM "拔插式"接入
在传统的开发模式中,如果你想从 OpenAI 切换到 DeepSeek,可能需要重写大量的接口调用逻辑。LangChain 通过适配器模式(Adapter Pattern)解决了这个问题。
1.1 环境搭建与依赖
基于 Node.js 环境,我们首先在 package.json 中配置 "type": "module",并安装核心包:
Bash
pnpm i langchain @langchain/deepseek dotenv
1.2 像配置驱动一样配置模型
通过 dotenv 管理环境变量,代码会自动识别.env文件中的 DEEPSEEK_API_KEY。
JavaScript
import { ChatDeepSeek } from '@langchain/deepseek';
const model = new ChatDeepSeek({
model: 'deepseek-reasoner',
temperature: 0.7,
});
1.3 实战:如何"一行代码"换模型?
这是最体现工程化价值的地方。 假设今天 DeepSeek 维护,你需要紧急切换到 OpenAI,你只需要做两件事:
- 安装新适配器 :
pnpm add @langchain/openai - 修改导入与实例化:
JavaScript
// 只需要改动这两行
import { ChatOpenAI } from '@langchain/openai';
const model = new ChatOpenAI({ model: 'gpt-4o' });
// --- 以下所有业务代码一个字都不用改 ---
const res = await model.invoke("什么是闭包?");
console.log(res.content);
为什么能这么快?
因为在 LangChain 的世界里,所有的模型对象(model)都继承自同一个基类。它们拥有统一的接口规范:无论底层是 DeepSeek 还是 OpenAI,它们都认识 .invoke()。这种解耦意味着你的业务逻辑(Chain、Agent、Tooling)被保护在一个稳定的"外壳"里,不受底层模型更迭的影响。
核心价值: 此时的 LLM 变得可拔插。你可以随时通过更改一行代码,将 DeepSeek 换成 Anthropic 或其他模型,而不需要改动核心业务逻辑。
第二层:提示词工程------将"黑盒"转化为结构化资产
在 AI 应用开发中,开发者常说 LLM 是一个"黑盒"。要打开这个黑盒,关键就在于 Prompt(提示词) 。LangChain 并不是简单地发送一段话给模型,而是通过工程化的手段,将提示词转化为可复用、可变量化、可维护的模板。
2.1 从"硬编码"到"模板化"
在早期的 AI 开发中,我们可能会直接拼凑字符串。但在 LangChain 中,我们使用 PromptTemplate。
JavaScript
import { PromptTemplate } from '@langchain/core/prompts';
// 使用静态方法 fromTemplate 创建模板
const prompt = PromptTemplate.fromTemplate(`
你是一个{role},
请用不超过 {limit} 字回答以下问题:
{question}?
`);
这种做法的工程价值在于:
- 解耦逻辑与内容:提示词的"结构"被固定下来,而"角色"、"字数"、"内容"(具体问题)则通过变量动态注入。
- 静态方法与类属性 :
PromptTemplate.fromTemplate是一个静态方法,它直接属于类而非实例,这使得模板的创建更加标准和统一。
2.2 变量注入:赋予 AI 不同的"灵魂"
通过模板的 .format() 方法,我们可以轻松地改变 AI 的行为模式。通过传入不同的参数,AI 瞬间从一个通用助手变成了一个严苛的"前端面试官":
JavaScript
const promptStr = await prompt.format({
role: '前端面试官',
limit: '50',
question: '什么是闭包'
});
这种参数化设计是实现自动化测试 和动态响应 的基础。你可以预设一套角色库,根据用户的不同需求,动态切换 role 参数,而无需修改底层的模型调用代码。
2.3 迈向可预测的输出
为模型设置了 temperature: 0.7。在提示词工程中,模板 + 温度控制 是一套组合拳。
-
模板保证了输入结构的稳定性。
-
温度控制(Temperature)决定了输出的创造性与确定性。
对于面试官这种场景,0.7 的温度既能保持专业性,又能让回答不那么机械死板。
第三层:LCEL 与 Chain------构建 AI 应用的"流水线"
在 LangChain 1.0+ 版本中,最重大的变革莫过于 LCEL(LangChain Expression Language,LangChain 表达式语言) 的引入。如果你熟悉 Linux 的管道符 | 或者 JavaScript 的函数组合,你会发现 LCEL 的逻辑如出一辙。
3.1 什么是 LCEL?
Chain(链) 是 LangChain 的灵魂,它将多个原子化的组件(提示词、模型、解析器)连接成一个可执行的任务序列。而 LCEL 则是构建这些链的"粘合剂"。
最简洁的 LCEL 写法:
js
const chain = prompt.pipe(model);
这行代码看似简单,实际上它在底层实现了一套极其复杂的协议映射 。prompt 输出的是一个 PromptValue 对象,而 model 能够自动识别并接收这个对象,将其转化为 LLM 需要的 API 调用格式。
下面是一段完整使用代码:
JavaScript
import 'dotenv/config';
import { ChatDeepSeek } from '@langchain/deepseek';
import { PromptTemplate } from '@langchain/core/prompts';
const model = new ChatDeepSeek({
model: 'deepseek-reasoner',
temperature: 0.7
})
const prompt = PromptTemplate.fromTemplate(`
你是一个前端专家,用一句话解释: {topic}
`);
// 提示词节点 -> 模型节点 -> 自动执行
const chain = prompt.pipe(model);
const response = await chain.invoke({
topic: '闭包',
});
console.log(response.text);
3.2 深度解析:Runnable 协议
LCEL 的强大源于所有组件都遵循统一的 Runnable 协议 。这意味着无论是一个简单的提示词模板,还是一个复杂的业务函数,只要它符合 Runnable 规范,就可以被 .pipe()。
当你调用 chain.invoke() 时,内部发生了以下链式反应:
- 输入转化 :将
{ topic: '闭包' }注入PromptTemplate。 - 渲染:模板生成最终的字符串提示词。
- 预测 :将字符串传递给
ChatDeepSeek,模型进行推理。 - 返回 :模型返回一个
BaseMessage对象,包含生成的文本。
第四层:复杂逻辑编排------从"对话框"走向"工作流"
在实际的业务场景中,AI 任务往往不是一次 invoke 就能解决的。例如,你需要先让 AI 检索资料,再根据资料生成草案,最后对草案进行精简。这种**多步推理(Multi-step Reasoning)**正是 LangChain 1.2+ 版本中 RunnableSequence 的用武之地。
4.1 核心逻辑:解耦与职责分明
实现一个"知识精炼"系统。它的核心思想是将一个复杂的长任务拆解为两个原子级的子任务:
- 子任务 A(解释链) :负责生成深度内容,覆盖定义、原理和使用方式。
- 子任务 B(总结链) :负责对 A 的输出进行二次加工,提炼出 3 个核心要点。
JavaScript
// 子任务 A:专家模式,负责产出深度内容
const explainPrompt = PromptTemplate.fromTemplate(`
你是一个前端专家,请详细介绍以下概念: {topic}
要求: 覆盖定义、原理、使用方式、不超过300字。
`);
// 子任务 B:精简模式,负责产出核心要点
const summaryPrompt = PromptTemplate.fromTemplate(`
请将以下前端概念解释总结为3个核心要点(每点不超过20字):
{explanation}
`);
const explainChain = explainPrompt.pipe(model);
const summaryChain = summaryPrompt.pipe(model);
4.2 深度解析:数据的流水线流动
最精妙的部分------如何将上一步的输出精准地喂给下一步。
在 RunnableSequence.from([...]) 中,每一步不仅仅是在调用模型,还在进行数据清洗和重新包装:
JavaScript
const fullChain = RunnableSequence.from([
// 第一步:处理原始 topic,调用 explainChain,并提取 text 属性
(input) => explainChain.invoke({ topic: input.topic }).then(res => res.text),
// 第二步:接收第一步产生的字符串(explanation),作为第二步的输入
(explanation) => summaryChain.invoke({ explanation: explanation }).then(res =>
`知识点详解:${explanation}\n\n总结要点:${res.text}`
)
]);
为什么这种"编排"比直接拼字符串更强?
- 状态管理:每一步的输出都可以被单独拦截、记录或修改。
- 类型安全:在复杂的应用中,你可以确保传给模型 B 的数据一定是模型 A 处理过的纯文本,而不是包含原始 Metadata 的复杂对象。
- 并发潜力 :虽然这里是顺序执行,但
RunnableSequence允许你轻松切换到RunnableParallel(并行执行),这在需要同时调用多个模型对比结果时非常有用。
总结:从"调包侠"到"AI 架构师"
通过这四层递进的学习,我们不难发现 LangChain 的核心逻辑:
LangChain = 统一接口 (Language Model) + 灵活组合 (Chain)
- 解耦:不绑定特定的模型供应商。
- 结构化:用模板管理提示词,告别乱糟糟的字符串拼接。
- 流式化:用 LCEL 构建清晰的业务逻辑流水线。
- 工程化:将复杂的 AI 任务转化为可预测、可扩展的代码结构。
LangChain 并不是让事情变得复杂,而是为日益复杂的 AI 应用提供了工业级的脚手架。如果你正准备从简单的 API 调用转向开发复杂的 AI Agent 或 RAG 系统,那么掌握这套组合拳将是你的必修课。