
通用大模型都存在一个明显短板:上下文窗口有限。单次对话结束,超出窗口范围的历史信息就会丢失。想要实现长期对话、持续运行的AI智能体、自动化业务Agent,单纯依靠Prompt上下文远远不够。通常我们把全部历史对话直接塞进提示词,短期内尚可运行,随着交互次数增多,Token数量爆炸、推理成本飙升、大量冗余信息干扰模型判断,对话质量持续下滑。
要解决这个痛点,就需要一套独立于上下文窗口之外的记忆系统。一套完备的记忆系统不能只做到简单存储对话记录,必须拥有一整套生命周期管理机制:记忆写入、压缩精简、重复内容合并、信息迭代更新、基于时间的自然遗忘、多条记忆信息冲突时自动处理。
不少人会把记忆系统简单理解成数据库,仅仅做信息持久化。真正适配大模型的记忆引擎,核心价值是筛选有效信息,在合适时机召回合适内容,屏蔽噪声,模拟人类记忆规律。人类不会永久记住所有细节,旧记忆慢慢模糊,相似经历会合并,新旧认知矛盾时会修正想法。大模型记忆系统正是借鉴这一思路设计。

参考经典智能体记忆分层思路,我们将记忆划分为三层,各司其职,避免所有信息混杂在一起。

三层记忆形成流转链路:瞬时记忆提取信息 → 存入短期记忆 → 持续优化治理(压缩、去重)→ 满足条件晋升长期记忆;长期记忆也可被召回,临时加载进短期记忆参与交互。
任何记忆单元,都需要标准化字段,支撑后续所有运算。一份标准记忆对象基础字段设计如下:
memory_item = {
"memory_id": "uuid唯一标识",
"content": "记忆文本内容",
"embedding": "向量,用于相似度检索",
"create_time": "创建时间戳",
"last_access_time": "最后一次被召回时间戳",
"weight": "记忆权重(用于时间衰减)",
"tag": ["分类标签"],
"source": "对话/工具调用/外部输入",
"version": 1, # 记忆版本,用于更新、冲突处理
"is_valid": True
}
该示例定义了一个结构化的长期记忆存储模块:
import time
import uuid
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass
class MemoryItem:
memory_id: str = field(default_factory=lambda: str(uuid.uuid4()))
content: str
embedding: Optional[List[float]] = None
create_time: float = field(default_factory=time.time)
last_access_time: float = field(default_factory=time.time)
weight: float = 1.0
tags: List[str] = field(default_factory=list)
source: str = "chat"
version: int = 1
is_valid: bool = True
class BaseMemoryStore:
def __init__(self):
self.memory_pool: dict[str, MemoryItem] = {}
def add_memory(self, item: MemoryItem):
self.memory_pool[item.memory_id] = item
def get_all(self) -> List[MemoryItem]:
return list(self.memory_pool.values())原始对话文本存在大量冗余:客套话、重复语气、无效修饰、问答来回拉扯。如果直接原始文本存储,会带来三个严重问题:
记忆压缩目标不是简单删减文字,而是保留事实主体,剔除无效修辞,实现信息密度最大化。压缩分为两大路线:规则化轻量压缩、大模型语义压缩。
2.1 规则压缩(低成本,适合大批量预处理)
适用场景:实时高频产生记忆,不希望频繁调用LLM。 执行策略:
2.2 LLM语义压缩(主流方案,优先推荐)
设计专用压缩Prompt,引导模型提炼核心事实。 示例Prompt模板:
请提取下面对话中的客观事实,精简表述。 要求:只保留关键信息,删除闲聊、语气、重复语句;不要主观推测;输出简洁陈述句。 对话内容:{{content}}
压缩分级策略:
压缩存在信息丢失风险,必须设置约束:
该示例实现了一个基于大模型的对话记忆压缩函数,支持轻度和深度两种压缩级别:轻度保留细节仅去闲聊,深度只提取关键结论。通过动态构造Prompt调用LLM对长文本进行摘要,有效降低记忆存储成本并控制上下文窗口。
def compress_memory_content(raw_text: str, level: str = "light") -> str:
"""
level: light 轻度压缩 / deep 深度压缩
"""
if len(raw_text) < 120:
return raw_text
if level == "light":
prompt = f"""提取文本中的客观事实,精简语句,保留细节,删除闲聊话术:
{raw_text}"""
else:
prompt = f"""高度概括核心事实,去除全部过程描述,仅输出关键结论:
{raw_text}"""
# 此处替换为真实LLM调用接口
# result = llm.chat(prompt)
# return result
# 模拟返回
return f"【{level}压缩结果】提取核心事实:{raw_text[:60]}..."很多系统只做完全字符串匹配去重,在语义场景下完全不够。我们把重复划分为三类:
针对不同类型,采取不同处理策略,不能一刀切删除。
去重依托 Embedding 向量检索,标准执行流程:

阈值调优经验:

该示例实现了一个基于余弦相似度的记忆去重机制:计算新记忆与已有记忆的向量相似度,若超过阈值(0.85)则判定为重复,跳过入库并更新旧记忆的访问时间,避免语义重复内容堆积,保持记忆库的精简与高效。
import numpy as np
def cosine_similarity(vec1: List[float], vec2: List[float]) -> float:
a = np.array(vec1)
b = np.array(vec2)
return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
def deduplicate_memory(new_mem: MemoryItem, store: BaseMemoryStore, threshold=0.85) -> bool:
"""
返回True:存在重复,新记忆不入库;False:无重复,可以入库
"""
if not new_mem.embedding:
return False
all_mem = store.get_all()
for mem in all_mem:
if not mem.embedding or not mem.is_valid:
continue
sim = cosine_similarity(new_mem.embedding, mem.embedding)
if sim >= threshold:
# 更新旧记忆访问时间
mem.last_access_time = time.time()
return True
return False随着交互持续进行,用户信息会发生变化:喜好变更、计划调整、纠正之前说错的信息。 典型场景:
此时不能简单新增一条记忆,会造成信息冗余,埋下记忆冲突隐患。需要主动对旧记忆进行版本化更新。
记忆对象内置version版本号,更新逻辑规范:

两种更新模式:
该示例实现了一个记忆的更新机制:不直接覆盖旧记忆,而是将其标记为失效,同时基于旧记忆的标签和来源创建版本号递增的新记忆入库,实现记忆的版本化管理,便于后续追溯历史变更。
def update_memory(store: BaseMemoryStore, target_id: str, new_content: str):
if target_id not in store.memory_pool:
return None
old_mem = store.memory_pool[target_id]
# 旧记忆保留,标记可选失效
old_mem.is_valid = False
# 创建新版本记忆
new_mem = MemoryItem(
content=new_content,
tags=old_mem.tags.copy(),
source=old_mem.source,
version=old_mem.version + 1
)
store.add_memory(new_mem)
return new_mem人脑不会永久记住所有信息,久远记忆会慢慢淡化。映射到记忆系统:

如果没有衰减机制,记忆库会无限膨胀,越来越多过时信息持续参与检索,干扰模型判断。
行业主流使用指数衰减模型,公式:
优化改进方案:每次记忆被召回,重置衰减计时(模拟 “回忆一次,记忆加深”)。 可配置参数:
单独启动后台任务,周期性遍历短期记忆库批量更新权重。 执行间隔建议:5~30 分钟,根据业务并发调整,避免高频遍历造成性能压力。
该示例实现了一个基于时间衰减的记忆权重衰减函数:利用指数衰减公式,根据距上次访问的时间间隔自动降低记忆权重,并设置最低权重下限防止权重归零,模拟记忆随时间自然遗忘的机制。
import math
def decay_weight(mem: MemoryItem, decay_lambda=0.0001, min_weight=0.1):
now = time.time()
delta = now - mem.last_access_time
new_weight = mem.weight * math.exp(-decay_lambda * delta)
mem.weight = max(new_weight, min_weight)
mem.last_access_time = now
return mem.weight当记忆库中存在两条或多条描述同一对象,但事实相互矛盾的信息,即为记忆冲突。 示例:
如果不处理冲突,两条记忆同时被召回送入Prompt,模型收到矛盾信息,容易输出混乱答案。
冲突来源:信息更新不及时、用户前后说法变化、信息录入错误。

冲突检测 Prompt 参考:
判断下面两条描述是否事实冲突。 A:{{mem_a}} B:{{mem_b}} 输出:冲突/无冲突/信息不足无法判断
冲突消解策略的优先级依次从高到低:

生产环境通用组合方案:
该示例实现了一个记忆冲突检测函数:通过两两遍历记忆列表,调用大模型判断任意两条记忆内容是否存在语义冲突,返回冲突记忆对的 ID 组合,为后续冲突消解与记忆一致性维护提供依据。
def detect_memory_conflict(mem_list: List[MemoryItem]) -> List[tuple]:
conflict_pairs = []
# 两两对比送入模型判断冲突
for i in range(len(mem_list)):
for j in range(i+1, len(mem_list)):
m1, m2 = mem_list[i], mem_list[j]
# llm调用判断是否冲突
# result = llm.check_conflict(m1.content, m2.content)
# if result == "冲突":
# conflict_pairs.append((m1.memory_id, m2.memory_id))
return conflict_pairs记忆治理(压缩、去重、衰减、冲突处理)属于写入侧能力;召回是读取侧能力,二者配合才能生效。 标准召回链路:

不要盲目增加召回数量,过多记忆同样会造成Token浪费。一般Top 3~Top 8为常用区间。
经过过才明白,刚开始搭建智能体记忆系统,以为只要搭建向量数据库、实现检索就算完成。真正落地后才会发现,检索只是整套体系中很小一环。一套可用、稳定、长期运行的记忆引擎,核心在于记忆全生命周期治理:从信息提取、压缩精简,到重复信息合并、内容迭代更新,再到模拟人类记忆规律的时间衰减与动态遗忘,最后解决多条信息之间的事实冲突。
记忆的核心机制,本质是让大模型学会筛选记忆、淡化过时信息、修正旧认知。脱离上下文窗口的长期智能体,离不开这套能力。同时,如何让模型自主判断记忆价值、实现自适应衰减系数、复杂多条记忆链式冲突自动推理消解,也是现在项目中遇到的实际问题,先实现现有的基础,在逐步解决项目中的难题。
整合提取项目中用到的所有模块,包括:数据模型、记忆压缩、相似度去重、版本更新、时间衰减、冲突检测、记忆召回。
import time
import uuid
import math
import numpy as np
from dataclasses import dataclass, field
from typing import List, Optional, Dict, Tuple
# ======================
# 1. 基础数据模型定义
# ======================
@dataclass
class MemoryItem:
memory_id: str = field(default_factory=lambda: str(uuid.uuid4()))
content: str
embedding: Optional[List[float]] = None
create_time: float = field(default_factory=time.time)
last_access_time: float = field(default_factory=time.time)
weight: float = 1.0
tags: List[str] = field(default_factory=list)
source: str = "chat"
version: int = 1
is_valid: bool = True
class BaseMemoryStore:
def __init__(self):
self.memory_pool: Dict[str, MemoryItem] = {}
def add_memory(self, item: MemoryItem):
self.memory_pool[item.memory_id] = item
def get_all(self) -> List[MemoryItem]:
return list(self.memory_pool.values())
def get_by_id(self, mid: str) -> Optional[MemoryItem]:
return self.memory_pool.get(mid)
def list_valid_memories(self) -> List[MemoryItem]:
return [m for m in self.get_all() if m.is_valid]
# ======================
# 2. 工具函数:向量相似度
# ======================
def cosine_similarity(vec1: List[float], vec2: List[float]) -> float:
a = np.array(vec1)
b = np.array(vec2)
dot = np.dot(a, b)
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
if norm_a == 0 or norm_b == 0:
return 0.0
return float(dot / (norm_a * norm_b))
# 模拟 Embedding 生成(真实场景替换成 embedding 模型调用)
def mock_embedding(text: str) -> List[float]:
np.random.seed(hash(text) % 4294967295)
return list(np.random.rand(32))
# ======================
# 3. 记忆压缩模块
# ======================
def compress_memory_content(raw_text: str, level: str = "light") -> str:
"""
level: light 轻度压缩 / deep 深度压缩
"""
if len(raw_text) < 120:
return raw_text
if level == "light":
prompt = f"""提取文本中的客观事实,精简语句,保留细节,删除闲聊话术:
{raw_text}"""
else:
prompt = f"""高度概括核心事实,去除全部过程描述,仅输出关键结论:
{raw_text}"""
# ========== 这里替换成真实LLM调用 ==========
# resp = llm.chat(prompt)
# return resp
# 模拟压缩结果
if level == "light":
return f"[轻量压缩]{raw_text}"
else:
return f"[深度压缩]{raw_text[:70]}..."
# ======================
# 4. 记忆去重模块
# ======================
def deduplicate_memory(new_mem: MemoryItem, store: BaseMemoryStore, threshold=0.85) -> Tuple[bool, Optional[MemoryItem]]:
"""
:return: (是否重复, 匹配到的旧记忆)
"""
if not new_mem.embedding:
return False, None
valid_mems = store.list_valid_memories()
for mem in valid_mems:
if not mem.embedding:
continue
sim = cosine_similarity(new_mem.embedding, mem.embedding)
if sim >= threshold:
mem.last_access_time = time.time()
return True, mem
return False, None
# ======================
# 5. 记忆版本更新模块
# ======================
def update_memory(store: BaseMemoryStore, target_id: str, new_content: str) -> Optional[MemoryItem]:
old_mem = store.get_by_id(target_id)
if not old_mem:
return None
# 旧记忆软失效
old_mem.is_valid = False
# 构建新版本记忆
compressed = compress_memory_content(new_content, level="light")
new_emb = mock_embedding(compressed)
new_mem = MemoryItem(
content=compressed,
embedding=new_emb,
tags=old_mem.tags.copy(),
source=old_mem.source,
version=old_mem.version + 1
)
store.add_memory(new_mem)
return new_mem
# ======================
# 6. 时间衰减 & 遗忘模块
# ======================
def decay_weight(mem: MemoryItem, decay_lambda=0.0001, min_weight=0.1) -> float:
now = time.time()
delta = now - mem.last_access_time
new_weight = mem.weight * math.exp(-decay_lambda * delta)
mem.weight = max(new_weight, min_weight)
return mem.weight
def batch_decay_process(store: BaseMemoryStore, decay_lambda=0.0001, min_weight=0.1):
"""批量执行衰减 + 低权重记忆软遗忘"""
all_valid = store.list_valid_memories()
for m in all_valid:
decay_weight(m, decay_lambda, min_weight)
if m.weight <= min_weight:
m.is_valid = False
print(f"[遗忘触发] memory_id={m.memory_id}, weight={m.weight:.3f}")
# ======================
# 7. 冲突检测模块
# ======================
def detect_memory_conflict(mem_list: List[MemoryItem]) -> List[Tuple[str, str]]:
conflict_pairs = []
# 两两对比
for i in range(len(mem_list)):
for j in range(i + 1, len(mem_list)):
m1, m2 = mem_list[i], mem_list[j]
# ========== 替换为真实LLM冲突判断 ==========
# prompt = f"""判断两条事实是否冲突:
# A:{m1.content}
# B:{m2.content}
# 只输出:冲突 / 无冲突"""
# res = llm.chat(prompt).strip()
# if res == "冲突":
# conflict_pairs.append((m1.memory_id, m2.memory_id))
# 模拟规则测试:简单关键词模拟冲突
if "周末在家休息" in m1.content and "周末外出旅行" in m2.content:
conflict_pairs.append((m1.memory_id, m2.memory_id))
return conflict_pairs
# ======================
# 8. 记忆写入流水线(完整链路:压缩→向量化→去重→入库)
# ======================
def memory_pipeline(raw_text: str, store: BaseMemoryStore, dedup_threshold=0.85) -> Optional[MemoryItem]:
# 1. 压缩
compressed_text = compress_memory_content(raw_text, level="light")
# 2. 生成向量
emb = mock_embedding(compressed_text)
# 3. 构建记忆对象
new_mem = MemoryItem(content=compressed_text, embedding=emb)
# 4. 去重检测
is_dup, old_mem = deduplicate_memory(new_mem, store, dedup_threshold)
if is_dup:
print(f"[去重] 识别相似记忆,不新增,更新旧记忆访问时间 id={old_mem.memory_id}")
return None
# 5. 无重复则入库
store.add_memory(new_mem)
print(f"[入库成功] memory_id={new_mem.memory_id}")
return new_mem
# ======================
# 9. 记忆召回模块
# ======================
def recall_memory(query: str, store: BaseMemoryStore, top_k=5, threshold=0.6) -> List[MemoryItem]:
query_emb = mock_embedding(query)
candidates = []
valid_mems = store.list_valid_memories()
for m in valid_mems:
if not m.embedding:
continue
sim = cosine_similarity(query_emb, m.embedding)
if sim >= threshold:
candidates.append((sim, m))
# 相似度降序排序
candidates.sort(key=lambda x: x[0], reverse=True)
result = []
for sim, mem in candidates[:top_k]:
mem.last_access_time = time.time()
result.append(mem)
return result
# ======================
# 10. 主测试流程
# ======================
if __name__ == "__main__":
memory_store = BaseMemoryStore()
print("===== 步骤1:写入第一批记忆 =====")
memory_pipeline("用户周末打算在家休息", memory_store)
mid_test = memory_pipeline("用户喜欢喝美式咖啡", memory_store).memory_id
print("\n===== 步骤2:更新记忆(用户修改喜好) =====")
updated = update_memory(memory_store, mid_test, "用户现在更喜欢拿铁咖啡")
print(f"新版本记忆ID: {updated.memory_id}, version={updated.version}")
print("\n===== 步骤3:写入冲突记忆 =====")
memory_pipeline("用户周末计划外出旅行", memory_store)
print("\n===== 步骤4:批量衰减模拟 =====")
batch_decay_process(memory_store, decay_lambda=0.00001)
print("\n===== 步骤5:召回相关记忆 =====")
recall_res = recall_memory("用户周末安排", memory_store, top_k=5)
for item in recall_res:
print(f"- {item.content} weight={item.weight:.3f}")
print("\n===== 步骤6:冲突检测 =====")
conflicts = detect_memory_conflict(recall_res)
if conflicts:
for a, b in conflicts:
m1 = memory_store.get_by_id(a)
m2 = memory_store.get_by_id(b)
print(f"发现冲突:\n A:{m1.content}\n B:{m2.content}")
else:
print("未检测到冲突")原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。