LangChain 是什么
LangChain 是构建 LLM 应用的开发框架,它提供了:
- 统一的模型接口:一套代码适配多个 LLM 提供商
- 链式组合:像乐高一样组装 AI 能力
- 内置模块:记忆、检索、工具调用开箱即用
LangChain.js 是 LangChain 的 JavaScript/TypeScript 版本,适合前端和 Node.js 开发者。
安装与配置
# 核心包
npm install langchain @langchain/core
# 模型提供商(按需安装)
npm install @langchain/openai
npm install @langchain/anthropic
npm install @langchain/google-genai
环境配置
// .env
OPENAI_API_KEY=sk-xxx
ANTHROPIC_API_KEY=sk-ant-xxx
核心概念
1. Models(模型)
import { ChatOpenAI } from '@langchain/openai'
import { ChatAnthropic } from '@langchain/anthropic'
// OpenAI
const openai = new ChatOpenAI({
modelName: 'gpt-4-turbo-preview',
temperature: 0.7,
maxTokens: 1000
})
// Anthropic
const claude = new ChatAnthropic({
modelName: 'claude-3-opus-20240229',
temperature: 0.7
})
// 使用方式完全相同
const response = await openai.invoke('你好,请介绍一下自己')
2. Prompts(提示模板)
import { ChatPromptTemplate, HumanMessagePromptTemplate } from '@langchain/core/prompts'
// 简单模板
const simplePrompt = ChatPromptTemplate.fromMessages([
['system', '你是一个{role}专家'],
['human', '{question}']
])
const formatted = await simplePrompt.format({
role: '前端开发',
question: 'Vue 和 React 有什么区别?'
})
// 带示例的模板
const fewShotPrompt = ChatPromptTemplate.fromMessages([
['system', '你是一个代码翻译器,将自然语言转换为代码'],
['human', '创建一个数组'],
['assistant', 'const arr = []'],
['human', '给数组添加元素1'],
['assistant', 'arr.push(1)'],
['human', '{input}']
])
3. Chains(链)
链是 LangChain 的核心抽象——把多个操作组合成一个可复用的流程。
import { RunnableSequence, RunnablePassthrough } from '@langchain/core/runnables'
import { StringOutputParser } from '@langchain/core/output_parsers'
// 构建链
const chain = RunnableSequence.from([
{
context: (input) => input.context,
question: (input) => input.question
},
ChatPromptTemplate.fromMessages([
['system', '基于以下上下文回答问题:\n{context}'],
['human', '{question}']
]),
new ChatOpenAI(),
new StringOutputParser()
])
// 调用链
const result = await chain.invoke({
context: 'Vue 是一个渐进式 JavaScript 框架...',
question: 'Vue 的核心特点是什么?'
})
4. Output Parsers(输出解析)
import { StructuredOutputParser } from 'langchain/output_parsers'
import { z } from 'zod'
// 定义输出结构
const parser = StructuredOutputParser.fromZodSchema(
z.object({
name: z.string().describe('产品名称'),
price: z.number().describe('价格'),
features: z.array(z.string()).describe('特性列表')
})
)
// 获取格式化指令
const formatInstructions = parser.getFormatInstructions()
// 在 prompt 中使用
const prompt = ChatPromptTemplate.fromMessages([
['system', '分析产品信息并输出 JSON\n{format_instructions}'],
['human', '{product_description}']
])
const chain = prompt.pipe(model).pipe(parser)
const result = await chain.invoke({
format_instructions: formatInstructions,
product_description: 'iPhone 15 Pro,售价 7999 元,支持灵动岛、USB-C、A17 芯片'
})
// { name: 'iPhone 15 Pro', price: 7999, features: ['灵动岛', 'USB-C', 'A17 芯片'] }
高级功能
Memory(记忆)
让对话具有上下文记忆:
import { BufferMemory, ConversationSummaryMemory } from 'langchain/memory'
import { ConversationChain } from 'langchain/chains'
// 缓冲记忆(保存完整历史)
const bufferMemory = new BufferMemory({
memoryKey: 'history',
returnMessages: true
})
// 摘要记忆(大语言模型总结历史)
const summaryMemory = new ConversationSummaryMemory({
memoryKey: 'history',
llm: new ChatOpenAI({ modelName: 'gpt-3.5-turbo' })
})
// 在链中使用记忆
const conversation = new ConversationChain({
llm: new ChatOpenAI(),
memory: bufferMemory
})
await conversation.call({ input: '我叫张三' })
await conversation.call({ input: '我是一名前端工程师' })
const result = await conversation.call({ input: '你还记得我的信息吗?' })
// AI 会记住之前的对话内容
Vector Stores(向量存储)
存储和检索向量化的文档:
import { OpenAIEmbeddings } from '@langchain/openai'
import { MemoryVectorStore } from 'langchain/vectorstores/memory'
import { Document } from '@langchain/core/documents'
// 创建文档
const docs = [
new Document({ pageContent: 'Vue 是一个渐进式框架', metadata: { source: 'vue.md' } }),
new Document({ pageContent: 'React 使用虚拟 DOM', metadata: { source: 'react.md' } }),
new Document({ pageContent: 'Angular 是一个完整的框架', metadata: { source: 'angular.md' } })
]
// 创建向量存储
const embeddings = new OpenAIEmbeddings()
const vectorStore = await MemoryVectorStore.fromDocuments(docs, embeddings)
// 相似性搜索
const results = await vectorStore.similaritySearch('什么是渐进式?', 2)
// 返回最相关的 2 个文档
Retrievers(检索器)
// 从向量存储创建检索器
const retriever = vectorStore.asRetriever({
k: 4, // 返回数量
searchType: 'similarity' // 搜索类型
})
// 检索相关文档
const relevantDocs = await retriever.invoke('Vue 有什么特点?')
Tools(工具)
让 AI 能够调用外部工具:
import { DynamicStructuredTool } from '@langchain/core/tools'
import { z } from 'zod'
// 定义工具
const weatherTool = new DynamicStructuredTool({
name: 'get_weather',
description: '获取指定城市的天气信息',
schema: z.object({
city: z.string().describe('城市名称')
}),
func: async ({ city }) => {
// 调用真实的天气 API
const response = await fetch(`https://api.weather.com?city=${city}`)
const data = await response.json()
return JSON.stringify(data)
}
})
const calculatorTool = new DynamicStructuredTool({
name: 'calculator',
description: '进行数学计算',
schema: z.object({
expression: z.string().describe('数学表达式,如 2+3*4')
}),
func: async ({ expression }) => {
return String(eval(expression)) // 注意:生产环境需要安全的计算方式
}
})
Agents(智能体)
Agent 能自主决定使用哪些工具:
import { AgentExecutor, createOpenAIFunctionsAgent } from 'langchain/agents'
import { ChatOpenAI } from '@langchain/openai'
import { pull } from 'langchain/hub'
// 获取 Agent 提示模板
const prompt = await pull('hwchase17/openai-functions-agent')
// 创建 Agent
const agent = await createOpenAIFunctionsAgent({
llm: new ChatOpenAI({ modelName: 'gpt-4-turbo-preview' }),
tools: [weatherTool, calculatorTool],
prompt
})
// 创建执行器
const executor = new AgentExecutor({
agent,
tools: [weatherTool, calculatorTool],
verbose: true // 输出推理过程
})
// 执行
const result = await executor.invoke({
input: '北京今天天气怎么样?另外帮我算一下 15 * 37'
})
// Agent 会自动调用天气工具和计算器工具
实战案例
案例 1:文档问答系统
import { ChatOpenAI, OpenAIEmbeddings } from '@langchain/openai'
import { MemoryVectorStore } from 'langchain/vectorstores/memory'
import { createStuffDocumentsChain } from 'langchain/chains/combine_documents'
import { createRetrievalChain } from 'langchain/chains/retrieval'
async function createDocQA(documents: Document[]) {
// 1. 创建向量存储
const embeddings = new OpenAIEmbeddings()
const vectorStore = await MemoryVectorStore.fromDocuments(documents, embeddings)
// 2. 创建检索器
const retriever = vectorStore.asRetriever({ k: 4 })
// 3. 创建问答链
const llm = new ChatOpenAI({ modelName: 'gpt-4-turbo-preview' })
const prompt = ChatPromptTemplate.fromMessages([
['system', `基于以下上下文回答问题。如果上下文中没有相关信息,请说明。
上下文:
{context}`],
['human', '{input}']
])
const documentChain = await createStuffDocumentsChain({ llm, prompt })
const retrievalChain = await createRetrievalChain({
retriever,
combineDocsChain: documentChain
})
return retrievalChain
}
// 使用
const chain = await createDocQA(myDocuments)
const result = await chain.invoke({ input: '项目的技术栈是什么?' })
案例 2:代码生成助手
import { ChatOpenAI } from '@langchain/openai'
import { HumanMessage, SystemMessage } from '@langchain/core/messages'
const codeAssistant = new ChatOpenAI({
modelName: 'gpt-4-turbo-preview',
temperature: 0.2 // 低温度提高确定性
})
async function generateCode(requirement: string, language: string) {
const messages = [
new SystemMessage(`你是一个${language}专家。
根据需求生成高质量的代码,包含:
1. 完整的类型定义(如适用)
2. 详细的注释
3. 错误处理
4. 示例用法`),
new HumanMessage(requirement)
]
const response = await codeAssistant.invoke(messages)
return response.content
}
// 使用
const code = await generateCode(
'实现一个防抖函数,支持立即执行选项',
'TypeScript'
)
案例 3:多轮对话客服
import { ChatOpenAI } from '@langchain/openai'
import { BufferWindowMemory } from 'langchain/memory'
import { ConversationChain } from 'langchain/chains'
const customerService = new ConversationChain({
llm: new ChatOpenAI({ modelName: 'gpt-4-turbo-preview' }),
memory: new BufferWindowMemory({ k: 10 }), // 保留最近 10 轮对话
prompt: ChatPromptTemplate.fromMessages([
['system', `你是一个电商平台的客服助手。
- 态度友好专业
- 回答简洁明了
- 如需要人工服务,引导用户联系人工客服
对话历史:
{history}`],
['human', '{input}']
])
})
// 多轮对话
await customerService.call({ input: '我想退货' })
await customerService.call({ input: '买了 3 天了' })
await customerService.call({ input: '还没拆封' })
// AI 会根据上下文理解完整的退货需求
流式输出
import { ChatOpenAI } from '@langchain/openai'
const model = new ChatOpenAI({
modelName: 'gpt-4-turbo-preview',
streaming: true
})
// 方式 1:回调
await model.call('写一首诗', {
callbacks: [{
handleLLMNewToken(token) {
process.stdout.write(token)
}
}]
})
// 方式 2:流迭代器
const stream = await model.stream('写一首诗')
for await (const chunk of stream) {
process.stdout.write(chunk.content as string)
}
最佳实践
1. 错误处理
import { RunnableRetry } from '@langchain/core/runnables'
// 添加重试逻辑
const chainWithRetry = chain.withRetry({
stopAfterAttempt: 3,
onFailedAttempt: (error, attempt) => {
console.log(`尝试 ${attempt} 失败:`, error.message)
}
})
2. 成本控制
import { ChatOpenAI } from '@langchain/openai'
import { BaseCallbackHandler } from '@langchain/core/callbacks/base'
class TokenCounter extends BaseCallbackHandler {
totalTokens = 0
handleLLMEnd(output) {
const usage = output.llmOutput?.tokenUsage
if (usage) {
this.totalTokens += usage.totalTokens
console.log(`本次消耗: ${usage.totalTokens}, 累计: ${this.totalTokens}`)
}
}
}
const counter = new TokenCounter()
const model = new ChatOpenAI({
callbacks: [counter]
})
3. 缓存
import { InMemoryCache } from '@langchain/core/caches'
const cache = new InMemoryCache()
const model = new ChatOpenAI({ cache })
// 相同输入会命中缓存
await model.invoke('你好')
await model.invoke('你好') // 从缓存返回
总结
LangChain.js 核心模块:
| 模块 | 用途 |
|---|---|
| Models | 统一的模型接口 |
| Prompts | 提示模板管理 |
| Chains | 链式组合逻辑 |
| Memory | 对话记忆 |
| Retrievers | 文档检索 |
| Tools | 工具调用 |
| Agents | 自主决策 |
记住:LangChain 是脚手架,不是银弹。理解底层原理,按需使用。
相关文章推荐:


