《60天AI学习计划启动 | Day 16: LangChain 深入学习 - 高级 Chain 与 Memory》
Day 16: LangChain 深入学习 - 高级 Chain 与 Memory
学习目标
核心学习内容
1. LangChain 高级 Chain
Chain 类型:
- Sequential Chain:顺序执行
- Parallel Chain:并行执行
- Router Chain:路由选择
- Transform Chain:数据转换
2. Memory 管理
Memory 类型:
- Buffer Memory:简单记忆
- Summary Memory:摘要记忆
- Conversation Buffer Window:窗口记忆
- Entity Memory:实体记忆
3. 自定义 Chain
实现方式:
- 继承
Chain类 - 实现
_call方法 - 定义输入输出
实践作业
作业1:实现自定义 Chain
src/chains/custom-chain.js:
import { LLMChain } from 'langchain/chains';
import { BaseChain } from 'langchain/chains';
import { ChatOpenAI } from '@langchain/openai';
import { PromptTemplate } from '@langchain/core/prompts';
/**
* 自定义 Chain:代码审查链
*/
export class CodeReviewChain extends BaseChain {
constructor(llm) {
super();
this.llm = llm;
this.chainName = 'code_review';
}
_chainType() {
return 'code_review';
}
get inputKeys() {
return ['code', 'language'];
}
get outputKeys() {
return ['review', 'suggestions', 'score'];
}
async _call(inputs) {
const { code, language } = inputs;
// 步骤1:代码分析
const analysisPrompt = PromptTemplate.fromTemplate(
`分析以下{language}代码,识别潜在问题:
代码:
\`\`\`{language}
{code}
\`\`\`
请分析:
1. 代码质量问题
2. 性能问题
3. 安全问题
4. 最佳实践
分析:`
);
const analysisChain = new LLMChain({
llm: this.llm,
prompt: analysisPrompt
});
const analysis = await analysisChain.call({ code, language });
// 步骤2:生成建议
const suggestionPrompt = PromptTemplate.fromTemplate(
`基于以下分析,生成具体的改进建议:
分析:
{analysis}
请提供:
1. 具体改进建议
2. 优化后的代码示例
3. 评分(1-10)
建议:`
);
const suggestionChain = new LLMChain({
llm: this.llm,
prompt: suggestionPrompt
});
const suggestions = await suggestionChain.call({
analysis: analysis.text
});
// 步骤3:评分
const scorePrompt = PromptTemplate.fromTemplate(
`为以下代码评分(1-10分):
代码:
{code}
分析:
{analysis}
建议:
{suggestions}
请返回 JSON:
{
"score": 分数,
"reason": "评分理由"
}
评分:`
);
const scoreChain = new LLMChain({
llm: this.llm,
prompt: scorePrompt
});
const scoreResult = await scoreChain.call({
code,
analysis: analysis.text,
suggestions: suggestions.text
});
// 解析评分
let score = 5;
try {
const scoreData = JSON.parse(scoreResult.text);
score = scoreData.score || 5;
} catch (e) {
// 默认分数
}
return {
review: analysis.text,
suggestions: suggestions.text,
score: score
};
}
serialize() {
return {
_type: this._chainType(),
llm: this.llm.serialize()
};
}
}
作业2:实现 Memory 管理
src/services/memory-manager.js:
import {
ConversationBufferMemory,
ConversationSummaryMemory,
ConversationBufferWindowMemory,
ConversationSummaryBufferMemory
} from 'langchain/memory';
import { ChatOpenAI } from '@langchain/openai';
/**
* Memory 管理器
*/
export class MemoryManager {
constructor() {
this.memories = new Map();
this.llm = new ChatOpenAI({
temperature: 0.7,
openAIApiKey: process.env.OPENAI_API_KEY
});
}
/**
* 获取或创建 Memory
*/
getMemory(sessionId, type = 'buffer') {
const key = `${sessionId}_${type}`;
if (this.memories.has(key)) {
return this.memories.get(key);
}
let memory;
switch (type) {
case 'buffer':
// 简单记忆:保存所有对话
memory = new ConversationBufferMemory({
returnMessages: true,
memoryKey: 'history'
});
break;
case 'summary':
// 摘要记忆:总结历史对话
memory = new ConversationSummaryMemory({
llm: this.llm,
returnMessages: true,
memoryKey: 'history'
});
break;
case 'window':
// 窗口记忆:只保留最近N轮对话
memory = new ConversationBufferWindowMemory({
k: 5, // 保留最近5轮
returnMessages: true,
memoryKey: 'history'
});
break;
case 'summary_buffer':
// 摘要+缓冲:结合摘要和窗口
memory = new ConversationSummaryBufferMemory({
llm: this.llm,
maxTokenLimit: 2000,
returnMessages: true,
memoryKey: 'history'
});
break;
default:
memory = new ConversationBufferMemory({
returnMessages: true,
memoryKey: 'history'
});
}
this.memories.set(key, memory);
return memory;
}
/**
* 保存对话
*/
async saveMessage(sessionId, role, content, type = 'buffer') {
const memory = this.getMemory(sessionId, type);
if (role === 'user') {
await memory.saveContext(
{ input: content },
{ output: '' }
);
} else {
// 更新最后一条消息的输出
const messages = await memory.chatHistory.getMessages();
if (messages.length > 0) {
const lastMessage = messages[messages.length - 1];
if (lastMessage._getType() === 'human') {
await memory.saveContext(
{ input: lastMessage.content },
{ output: content }
);
}
}
}
}
/**
* 获取对话历史
*/
async getHistory(sessionId, type = 'buffer') {
const memory = this.getMemory(sessionId, type);
const messages = await memory.chatHistory.getMessages();
return messages;
}
/**
* 清空记忆
*/
clearMemory(sessionId, type = 'buffer') {
const key = `${sessionId}_${type}`;
this.memories.delete(key);
}
/**
* 获取记忆摘要
*/
async getSummary(sessionId) {
const memory = this.getMemory(sessionId, 'summary');
const summary = await memory.loadMemoryVariables({});
return summary;
}
}
export const memoryManager = new MemoryManager();
作业3:实现并行 Chain
src/chains/parallel-chain.js:
import { LLMChain } from 'langchain/chains';
import { ChatOpenAI } from '@langchain/openai';
import { PromptTemplate } from '@langchain/core/prompts';
/**
* 并行 Chain:同时执行多个任务
*/
export class ParallelChain {
constructor() {
this.llm = new ChatOpenAI({
temperature: 0.7,
openAIApiKey: process.env.OPENAI_API_KEY
});
}
/**
* 并行执行多个分析
*/
async parallelAnalysis(code, language) {
// 创建多个 Chain
const chains = {
// Chain 1: 代码质量分析
quality: new LLMChain({
llm: this.llm,
prompt: PromptTemplate.fromTemplate(
`分析以下{language}代码的质量:
代码:
\`\`\`{language}
{code}
\`\`\`
从代码规范、可读性、可维护性角度分析。`
)
}),
// Chain 2: 性能分析
performance: new LLMChain({
llm: this.llm,
prompt: PromptTemplate.fromTemplate(
`分析以下{language}代码的性能:
代码:
\`\`\`{language}
{code}
\`\`\`
从时间复杂度、空间复杂度、优化建议角度分析。`
)
}),
// Chain 3: 安全分析
security: new LLMChain({
llm: this.llm,
prompt: PromptTemplate.fromTemplate(
`分析以下{language}代码的安全性:
代码:
\`\`\`{language}
{code}
\`\`\`
从安全漏洞、数据保护、输入验证角度分析。`
)
})
};
// 并行执行
const [quality, performance, security] = await Promise.all([
chains.quality.call({ code, language }),
chains.performance.call({ code, language }),
chains.security.call({ code, language })
]);
return {
quality: quality.text,
performance: performance.text,
security: security.text
};
}
/**
* 综合报告
*/
async generateReport(analyses) {
const reportPrompt = PromptTemplate.fromTemplate(
`基于以下分析,生成综合报告:
质量分析:
{quality}
性能分析:
{performance}
安全分析:
{security}
请生成:
1. 总体评价
2. 关键问题
3. 改进建议
4. 优先级排序
报告:`
);
const reportChain = new LLMChain({
llm: this.llm,
prompt: reportPrompt
});
const report = await reportChain.call(analyses);
return report.text;
}
}
作业4:实现 Router Chain
src/chains/router-chain.js:
import { LLMRouterChain, RouterOutputParser } from 'langchain/chains';
import { ChatOpenAI } from '@langchain/openai';
import { PromptTemplate } from '@langchain/core/prompts';
import { LLMChain } from 'langchain/chains';
/**
* 路由 Chain:根据输入选择不同的处理链
*/
export class RouterChain {
constructor() {
this.llm = new ChatOpenAI({
temperature: 0.7,
openAIApiKey: process.env.OPENAI_API_KEY
});
this.destinationChains = new Map();
this.initializeChains();
}
/**
* 初始化目标链
*/
initializeChains() {
// 代码相关链
this.destinationChains.set('code', new LLMChain({
llm: this.llm,
prompt: PromptTemplate.fromTemplate(
`你是代码专家,回答代码相关问题。
问题:{input}
回答:`
)
}));
// 文档相关链
this.destinationChains.set('document', new LLMChain({
llm: this.llm,
prompt: PromptTemplate.fromTemplate(
`你是文档专家,回答文档相关问题。
问题:{input}
回答:`
)
}));
// 通用链
this.destinationChains.set('general', new LLMChain({
llm: this.llm,
prompt: PromptTemplate.fromTemplate(
`你是通用助手,回答各种问题。
问题:{input}
回答:`
)
}));
}
/**
* 路由决策
*/
async route(input) {
const routingPrompt = PromptTemplate.fromTemplate(
`根据用户问题,选择最合适的处理链。
可用链:
- code: 代码相关问题
- document: 文档相关问题
- general: 通用问题
问题:{input}
请返回 JSON:
{
"destination": "链名称",
"reason": "选择理由"
}
路由:`
);
const routingChain = new LLMChain({
llm: this.llm,
prompt: routingPrompt,
outputParser: new RouterOutputParser()
});
const result = await routingChain.call({ input });
try {
const route = JSON.parse(result.text);
return route.destination || 'general';
} catch (e) {
return 'general';
}
}
/**
* 执行路由
*/
async execute(input) {
// 1. 路由决策
const destination = await this.route(input);
// 2. 执行对应的链
const chain = this.destinationChains.get(destination) ||
this.destinationChains.get('general');
const result = await chain.call({ input });
return {
answer: result.text,
destination: destination
};
}
}
作业5:实现 Transform Chain
src/chains/transform-chain.js:
import { BaseChain } from 'langchain/chains';
/**
* 转换 Chain:数据预处理和后处理
*/
export class TransformChain extends BaseChain {
constructor(transformFn) {
super();
this.transformFn = transformFn;
}
_chainType() {
return 'transform';
}
get inputKeys() {
return ['input'];
}
get outputKeys() {
return ['output'];
}
async _call(inputs) {
const transformed = await this.transformFn(inputs.input);
return {
output: transformed
};
}
serialize() {
return {
_type: this._chainType()
};
}
}
/**
* 数据清理 Chain
*/
export class DataCleaningChain extends TransformChain {
constructor() {
super(async (input) => {
// 清理数据
let cleaned = input.trim();
// 移除多余空格
cleaned = cleaned.replace(/\s+/g, ' ');
// 移除特殊字符(保留基本标点)
cleaned = cleaned.replace(/[^\w\s.,!?;:()\-]/g, '');
return cleaned;
});
}
}
/**
* 数据格式化 Chain
*/
export class DataFormattingChain extends TransformChain {
constructor() {
super(async (input) => {
// 格式化数据
const lines = input.split('\n');
const formatted = lines
.map(line => line.trim())
.filter(line => line.length > 0)
.join('\n');
return formatted;
});
}
}
作业6:创建高级 Chain API
src/routes/advanced-chains.js:
import express from 'express';
import { CodeReviewChain } from '../chains/custom-chain.js';
import { ParallelChain } from '../chains/parallel-chain.js';
import { RouterChain } from '../chains/router-chain.js';
import { ChatOpenAI } from '@langchain/openai';
import { memoryManager } from '../services/memory-manager.js';
import { logger } from '../utils/logger.js';
export const advancedChainsRouter = express.Router();
// 初始化 LLM
const llm = new ChatOpenAI({
temperature: 0.7,
openAIApiKey: process.env.OPENAI_API_KEY
});
// POST /api/chains/code-review - 代码审查
advancedChainsRouter.post('/code-review', async (req, res) => {
try {
const { code, language = 'javascript' } = req.body;
if (!code) {
return res.status(400).json({
success: false,
error: '代码不能为空'
});
}
const chain = new CodeReviewChain(llm);
const result = await chain.call({ code, language });
res.json({
success: true,
data: result
});
} catch (error) {
logger.error('代码审查错误:', error);
res.status(500).json({
success: false,
error: error.message
});
}
});
// POST /api/chains/parallel-analysis - 并行分析
advancedChainsRouter.post('/parallel-analysis', async (req, res) => {
try {
const { code, language = 'javascript' } = req.body;
if (!code) {
return res.status(400).json({
success: false,
error: '代码不能为空'
});
}
const chain = new ParallelChain();
const analyses = await chain.parallelAnalysis(code, language);
const report = await chain.generateReport(analyses);
res.json({
success: true,
data: {
analyses,
report
}
});
} catch (error) {
logger.error('并行分析错误:', error);
res.status(500).json({
success: false,
error: error.message
});
}
});
// POST /api/chains/route - 路由 Chain
advancedChainsRouter.post('/route', async (req, res) => {
try {
const { question } = req.body;
if (!question) {
return res.status(400).json({
success: false,
error: '问题不能为空'
});
}
const chain = new RouterChain();
const result = await chain.execute(question);
res.json({
success: true,
data: result
});
} catch (error) {
logger.error('路由 Chain 错误:', error);
res.status(500).json({
success: false,
error: error.message
});
}
});
// POST /api/chains/chat-with-memory - 带记忆的聊天
advancedChainsRouter.post('/chat-with-memory', async (req, res) => {
try {
const { message, sessionId, memoryType = 'buffer' } = req.body;
if (!message || !sessionId) {
return res.status(400).json({
success: false,
error: '消息和会话ID不能为空'
});
}
// 获取记忆
const memory = memoryManager.getMemory(sessionId, memoryType);
const history = await memory.loadMemoryVariables({});
// 构建消息
const messages = [
...(history.history || []),
{ role: 'user', content: message }
];
// 调用 LLM
const response = await llm.invoke(messages);
// 保存记忆
await memoryManager.saveMessage(sessionId, 'user', message, memoryType);
await memoryManager.saveMessage(sessionId, 'assistant', response.content, memoryType);
res.json({
success: true,
data: {
message: response.content,
sessionId: sessionId
}
});
} catch (error) {
logger.error('带记忆聊天错误:', error);
res.status(500).json({
success: false,
error: error.message
});
}
});
遇到的问题
问题1:Memory 序列化
解决方案:
// 保存 Memory 状态
const memoryState = await memory.saveContext(
{ input: 'user message' },
{ output: 'ai response' }
);
// 加载 Memory 状态
await memory.loadMemoryVariables({});
问题2:Chain 错误处理
解决方案:
try {
const result = await chain.call(inputs);
return result;
} catch (error) {
logger.error('Chain 执行错误:', error);
// 降级处理
return { error: error.message };
}
学习总结
今日收获
- ✅ 掌握高级 Chain 类型
- ✅ 实现自定义 Chain
- ✅ 理解 Memory 机制
- ✅ 实现并行和路由 Chain
- ✅ 优化工具链
关键知识点
- 自定义 Chain,扩展功能
- Memory 管理,保持上下文
- 并行执行,提高效率
- 路由选择,智能分发
Chain 类型对比
Sequential: 顺序执行,适合步骤化任务
Parallel: 并行执行,适合独立分析
Router: 路由选择,适合多场景
Transform: 数据转换,适合预处理
明日计划
明天将学习:
期待明天的学习! 🚀
参考资源
代码仓库
项目已更新:
- ✅ 自定义 Chain
- ✅ Memory 管理
- ✅ 并行 Chain
- ✅ 路由 Chain
- ✅ 高级 API
GitHub 提交: Day 16 - LangChain 深入学习
标签: #AI学习 #LangChain #高级Chain #Memory #学习笔记
写在最后
今天深入学习了 LangChain 的高级功能,包括自定义 Chain 和 Memory 管理。
这些功能让 AI 应用更加强大和灵活。明天将继续学习 Agents 的深入应用!
继续加油! 💪
快速检查清单
完成这些,第十六天就达标了! ✅

浙公网安备 33010602011771号