news 2026/6/4 0:31:05

LangChain 框架大项目用起来有多痛苦?本文整理了一套工程化方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain 框架大项目用起来有多痛苦?本文整理了一套工程化方案

LangChain 框架大项目用起来有多痛苦?本文整理了一套工程化方案

前言

"老王,为什么本文们的 LangChain 服务一重启就丢记忆?" 全栈工程师小李一脸无奈。

本文看了看他的代码,发现他用的是默认的 BufferMemory。"你这是把记忆存在内存里啊!服务一重启当然就没了!"

"那应该怎么弄?"

看来得从 LangChain 的工程化讲起了。今天本文们聊聊 LangChain 长期记忆的工程化方案。

一、底层原理

1.1 LangChain 的长期记忆困境

LangChain 的核心是把 LLM 调用链式编排,但长期记忆缺乏工程化支持:

graph TD A["用户输入"] --> B["LangChain Chain"] B --> C["LLM 调用"] C --> D{"有记忆吗?"} D -->|有| E["ConversationBufferMemory"] D -->|无| F["每次都重新来"] E --> G["内存中累积"] G --> H["Token 超限"] H --> I["崩溃"] F --> J["用户体验差"]

核心问题:

  • ConversationBufferMemory 无限增长
  • 没有自动压缩机制
  • 状态丢失无法恢复
  • prompt 版本难管理

1.2 LangChain 长期记忆方案对比

方案容量持久化复杂度
BufferMemory
SummaryMemory
向量存储记忆
自定义记忆可控最高

二、快速上手

看默认的 BufferMemory 问题:

from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory() memory.chat_memory.add_user_message("你好") memory.chat_memory.add_ai_message("你好!") # 对话越长,memory 越大...

改进版,加摘要:

from langchain.memory import ConversationSummaryMemory from langchain.llms import OpenAI llm = OpenAI() memory = ConversationSummaryMemory(llm=llm) memory.save_context({"input": "你好"}, {"output": "你好!"}) memory.save_context({"input": "今天天气怎么样?"}, {"output": "今天是晴天。"}) # 自动总结 print(memory.load_memory_variables({}))

三、核心 API / 深水区

3.1 LangChain 记忆方案速查

记忆类型特点适合场景
BufferMemory保存所有短对话
SummaryMemory压缩总结中长对话
VectorStoreMemory向量检索知识问答
CombinedMemory混合使用复杂场景

3.2 自定义持久化记忆

import json import os from langchain.memory import BaseMemory class FilePersistedMemory(BaseMemory): def __init__(self, file_path="memory.json"): self.file_path = file_path self.memory = self._load() def _load(self): if os.path.exists(self.file_path): with open(self.file_path) as f: return json.load(f) return {"history": []} def save(self): with open(self.file_path, "w") as f: json.dump(self.memory, f, ensure_ascii=False) @property def memory_variables(self): return ["history"] def load_memory_variables(self, inputs): return self.memory def save_context(self, inputs, outputs): self.memory["history"].append({ "input": inputs.get("input", ""), "output": outputs.get("output", "") }) self.save() if len(self.memory["history"]) > 100: self._compress() def _compress(self): self.memory["history"] = self.memory["history"][-50:]

3.3 多轮记忆管理

from typing import Dict, List, Any from dataclasses import dataclass @dataclass class TurnContext: turn: int user_input: str assistant_output: str retrieved_docs: List[str] class MultiTurnMemory: def __init__(self, llm, max_turns=20): self.llm = llm self.max_turns = max_turns self.turns: List[TurnContext] = [] def add_turn(self, user_input: str, output: str, docs=None): self.turns.append(TurnContext( turn=len(self.turns) + 1, user_input=user_input, assistant_output=output, retrieved_docs=docs or [] )) if len(self.turns) > self.max_turns: self._summarize_old() def _summarize_old(self): old = self.turns[:5] text = "\n".join(f"U: {t.user_input}\nA: {t.assistant_output}" for t in old) prompt = f"总结前五轮对话:\n{text}" summary = self.llm(prompt) self.turns = self.turns[5:] print(f"历史摘要:{summary}") def get_context(self) -> str: recent = self.turns[-5:] return "\n".join( f"用户:{t.user_input}\n助手:{t.assistant_output}" for t in recent )

四、实战演练

完整工程化 LangChain 记忆系统:

from typing import Dict, List, Optional import json import time class EngineeringMemory: def __init__(self, llm, persist_path="memory.json"): self.llm = llm self.persist_path = persist_path self.short_term: List[Dict] = [] self.long_term: List[Dict] = [] self.summaries: List[str] = [] self._load() def add_interaction(self, user_input: str, output: str): interaction = { "user": user_input, "assistant": output, "timestamp": time.time() } self.short_term.append(interaction) self._balance() self._save() def _balance(self): if len(self.short_term) > 20: old_interactions = self.short_term[:-10] if old_interactions: text = "\n".join( f"U: {i['user']}\nA: {i['assistant']}" for i in old_interactions ) prompt = f"总结对话:{text[:1500]}" summary = self.llm(prompt) self.summaries.append(summary) self.short_term = self.short_term[-10:] def get_memory_context(self) -> str: parts = [] if self.summaries: parts.append("【历史摘要】") parts.extend(self.summaries[-3:]) if self.short_term: parts.append("【最近对话】") for i in self.short_term[-5:]: parts.append(f"用户:{i['user']}") parts.append(f"助手:{i['assistant']}") return "\n".join(parts) def _save(self): data = { "short_term": self.short_term, "summaries": self.summaries } with open(self.persist_path, "w") as f: json.dump(data, f, ensure_ascii=False) def _load(self): try: with open(self.persist_path) as f: data = json.load(f) self.short_term = data.get("short_term", []) self.summaries = data.get("summaries", []) except: pass memory = EngineeringMemory(llm) # 模拟 50 轮对话 for i in range(50): memory.add_interaction(f"第{i}次提问", f"第{i}次回复") print(memory.get_memory_context())

五、避坑指南与最佳实践

💡 **技巧:做好持久化
进程重启后记忆丢失,一定要持久化。

⚠️ **警告:BufferMemory 不要用太多
对话一长,Token 就爆了。

✅ **推荐:分层记忆
短期 + 短期摘要 + 长期,三级架构。

六、综合实战演示

生产级 LangChain 记忆系统:

from typing import Dict, List, Optional from datetime import datetime import json class LangChainPersistentMemory: def __init__(self, llm, user_id: str): self.llm = llm self.user_id = user_id self.short_memory: List[Dict] = [] self.long_memory: Dict[str, str] = {} self.last_summary_time = 0 def add(self, role: str, content: str): msg = { "role": role, "content": content, "time": datetime.now().isoformat() } self.short_memory.append(msg) if len(self.short_memory) >= 10: self._compress() def _compress(self): to_compress = self.short_memory[:-5] if not to_compress: return text = "\n".join(m["content"] for m in to_compress) summary = self.llm(f"总结:{text}") key = f"summary_{len(self.long_memory)}" self.long_memory[key] = summary self.short_memory = self.short_memory[-5:] def get_context(self, token_limit=3000) -> str: parts = [] # 长期记忆 for k, v in self.long_memory.items(): part = f"[历史] {v}" if sum(len(p) for p in parts) + len(part) > token_limit: break parts.append(part) # 短期记忆 for m in self.short_memory: part = f"{m['role']}: {m['content']}" parts.append(part) return "\n".join(parts) def to_dict(self) -> Dict: return { "user_id": self.user_id, "short": self.short_memory, "long": self.long_memory } memory = LangChainPersistentMemory(llm, "user_001") for i in range(15): memory.add("user", f"问题{i}") memory.add("assistant", f"回答{i}") print(memory.get_context())

七、总结

LangChain 的长期记忆工程化要点:

  • 不要只用 BufferMemory:它会无限增长,最终导致 Token 超限
  • 自动压缩 + 摘要:定期总结历史对话,控制上下文大小
  • 持久化存储:进程重启后记忆不丢失
  • 分层记忆架构:短期记忆 + 短期摘要 + 长期记忆

搞好了这些,LangChain 项目才能在真实场景稳定运行。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/4 0:27:01

Python为何成为TVA的神经与感官系统(9)

重磅预告:本专栏将独家连载系列丛书《AI智能体视觉技术与应用》部分精华内容,该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著,特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、…

作者头像 李华
网站建设 2026/6/4 0:27:01

Python为何成为TVA的神经与感官系统(10)

重磅预告:本专栏将独家连载系列丛书《AI智能体视觉技术与应用》部分精华内容,该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著,特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、…

作者头像 李华
网站建设 2026/6/4 0:18:24

边缘计算实战:无人工厂多楼层AGV物理隔离梯控状态机设计

摘要: 在无人工厂的多机协同配送业务中,如果上位机调度系统要求实施团队强行读取底层老旧货梯的协议来获取平层状态,往往会面临极大的联调阻力与特种设备违规风险。面对协议封闭与合规性紧迫的双重限制,架构师亟需一种高度物理隔离…

作者头像 李华