🧠 让 AI 像乐高一样搭建:LangChain 入门与实战指南

5 阅读5分钟

🧠 让 AI 像乐高一样搭建:LangChain 入门与实战指南

在 AI 时代,大模型(LLM)就像一个拥有海量知识但性格古怪的“超级大脑”。它知道所有答案,但你很难直接指挥它完成复杂的任务。LangChain 就是那个能让你指挥这个“超级大脑”的指挥棒,它是一个用于开发由语言模型驱动的应用程序的开源框架。

🍳 第一部分:什么是 LangChain?—— 让 AI 变得“工程化”

LangChain 不仅仅是一个调用 API 的库,它是一个应用开发框架。它的核心理念是将复杂的 AI 任务拆解为可复用的模块,就像搭乐高积木一样。

核心组件概念:

  • Model (模型): 即 LLM,如 DeepSeek、GPT 等,负责生成文本。
  • Prompt (提示词): 引导模型如何回答的模板,决定了模型的“人设”和“任务”。
  • Chain (链): 将多个步骤(如:格式化提示词 -> 调用模型 -> 后处理)串联起来,形成一个工作流。

🧱 第二部分:代码实战详解 —— 从“单次调用”到“复杂流水线”

🟢 阶段一:基础调用

场景: 就像直接问主厨:“RAG 是什么?” 核心概念: 初始化模型与单次交互。

import 'dotenv/config'; 
import { ChatDeepSeek } from '@langchain/deepseek';

// 1. 初始化模型
// 这里使用了适配器模式(Adapter Pattern)。
// 无论底层是 OpenAI 还是 DeepSeek,LangChain 都提供了统一的接口。
const model = new ChatDeepSeek({
  model: 'deepseek-reasoner', // 指定模型名称
  temperature: 0, // 严谨模式,不加随机性
});

// 2. 调用 (Invoke)
// 直接向模型发送纯文本指令。
const res = await model.invoke('一句话解释什么是RAG');
console.log(res.content);

💡 解析: 这是最原子的操作。优点是简单,缺点是如果逻辑复杂,代码会变得难以维护,且提示词和逻辑混杂。


🟡 阶段二:提示词工程

场景: 你不仅想问问题,还想规定主厨的“身份”和“回答长度”。 核心概念: PromptTemplate(提示词模板)。

import { PromptTemplate } from '@langchain/core/prompts';

// 1. 定义模板
// 使用 {variable} 占位符,就像做菜前先准备好填空题。
const prompt = PromptTemplate.fromTemplate(`
  你是一个{role}. 请用不超过{limit}字回答以下问题: {question} 
`);

// 2. 格式化 (Format)
// 将具体的变量值填入模板。
// 这一步是手动的:先填空,再把填好后的字符串给模型。
const promptStr = await prompt.format({ 
  role: '前端面试官', 
  limit: 50, 
  question: '什么是闭包?' 
});

// 3. 调用模型
const res = await model.invoke(promptStr);
console.log(res.content);

💡 解析: 这里展示了最基础的逻辑分离:模板数据分离。但代码流程是割裂的(先处理字符串,再调用模型),LangChain 的强大之处在于能将这两步合并。


🔵 阶段三:管道连接 —— 什么是 Pipe?

场景: 你不想手动把填好的菜谱写下来再递给主厨,你希望“填空”和“烹饪”自动完成。 核心概念: pipe (管道操作符)

const model = new ChatDeepSeek({ model:'deepseek-reasoner', temperature:0.7 });
const prompt = PromptTemplate.fromTemplate(` 你是一个前端专家,用一句话解释:{topic} `);

// 核心:使用 pipe 连接
// pipe 的意思是“流向”。它将两个 Runnable 对象连接起来。
// 数据流向:Input (输入) -> Prompt (填空) -> Model (生成) -> Output (输出)
const chain = prompt.pipe(model); 

// 执行
// 你只需要给 chain 一个输入对象,它内部会自动:
// 1. 拿着输入对象去填充 prompt 模板
// 2. 拿着填充好的字符串去调用 model
const response = await chain.invoke({ topic: '闭包' });
console.log(response.content);

❓ 为什么要用 Pipe?

  1. 声明式编程: 你只需要声明“流程是什么”(先提示词,后模型),而不需要写“过程怎么执行”(先调 format,再调 invoke)。
  2. 复用性: 这个 chain 可以被多次调用,甚至作为更大流程的一个环节。
  3. 简洁性: 它消除了中间变量的繁琐处理,让代码逻辑一目了然。

🟣 阶段四:复杂工作流 —— RunnableSequence

场景: 你需要做一个“解释 + 总结”的复杂任务。先让主厨写一篇长文,然后把长文拿给助厨总结成要点。 核心概念: RunnableSequence (可运行序列)

// 定义两个独立的链
const explainChain = explainPrompt.pipe(model); // 链1: 负责详细解释
const summaryChain = summaryPrompt.pipe(model); // 链2: 负责总结

// 组装复杂流水线
const fullChain = RunnableSequence.from([
  // 步骤 1: 接收输入,调用 explainChain
  // 注意:这里 explainChain.invoke 返回的是一个 Promise,所以我们用 then 获取结果
  (input) => explainChain.invoke({topic: input.topic}).then(res => res.content),
  
  // 步骤 2: 接收步骤1的输出(即详细解释),调用 summaryChain
  // 这体现了数据的“流式处理”:前一步的输出是后一步的输入
  (explanation) => summaryChain.invoke({explanation})
]);

// 执行
// 输入一个简单的主题,输出一个经过两步处理的复杂结果
const response = await fullChain.invoke({ topic:'闭包' });
console.log(response);

💡 解析: 这是 LangChain 的高阶用法。RunnableSequence 允许你定义任意复杂的逻辑。在这个例子中,我们没有使用简单的 A.pipe(B),而是使用 RunnableSequence 来组合两个已经存在的 Chain。这模拟了真实业务中的复杂 Agent(智能体)逻辑:规划 -> 执行 -> 总结


📊 总结:LangChain 的核心价值

通过这四个文件的演进,我们可以清晰地看到 LangChain 解决了什么问题:

阶段关键技术代码特征适用场景
基础.invoke()直接调用,硬编码简单的问答测试
模板PromptTemplate模板与数据分离需要动态填充变量的场景
链式.pipe()声明式流水线绝大多数标准的 LLM 任务
编排RunnableSequence复杂异步流程需要多步推理、循环或条件判断的 Agent 应用

LangChain 的本质,就是将不可控的黑盒模型,变成了可控的、可调试的、工程化的软件系统