热闻岛
返回全网热点

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?

3小时前6 阅读
AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图
一、Agent 为什么需要记忆? 没有记忆的 Agent,很像一个“每次见面都重新认识你”的助手。你今天告诉它代码风格要简洁,明天再让它写脚本,它可能又回到默认风格。原因不是模型不聪明,而是它没有把关键偏好沉淀下来。 所以,Agent 记忆
AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

一、Agent 为什么需要记忆?

没有记忆的 Agent,很像一个“每次见面都重新认识你”的助手。你今天告诉它代码风格要简洁,明天再让它写脚本,它可能又回到默认风格。原因不是模型不聪明,而是它没有把关键偏好沉淀下来。

所以,Agent 记忆不是把所有聊天记录无限塞进 Prompt,而是把“当前任务状态”和“跨任务经验”分开管理:短期记忆负责当下任务不断片,长期记忆负责跨会话持续积累。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

短期记忆与长期记忆的职责边界

二、一句话回答面试官

短期记忆通常存在当前会话的 messages、session 或 checkpoint 里,用来保存用户输入、模型输出、工具结果和任务中间状态;长期记忆通常存在持久化存储里,常见做法是“原文 + embedding + metadata”写入向量库,同时用 SQL/KV/图数据库保存权限、时间、版本、实体关系等结构化信息。

记忆粒度不能太细,也不能太粗。比较合理的是按“独立知识点”“关键事件”“一次完整交互摘要”来存。读取时也不能只拿向量 TopK,最好结合元数据过滤、时间衰减、重要度排序和重排。

三、短期记忆:LLM 当前任务的工作台

短期记忆最常见的形态,就是每次调用模型时传入的 messages 列表。它里面有用户的问题、模型刚才说了什么、调用工具得到了什么结果、当前任务进行到哪一步。

你可以把它理解成一张工作台:东西放在台面上,模型就看得见;台面太乱、太满,模型就容易被旧信息干扰,成本也会越来越高。

from dataclasses import dataclass, field

from typing import Literal

Role = Literal["system", "user", "assistant", "tool"]

@dataclass

class ShortTermMemory:

"""当前会话的工作台:只服务于当前任务。"""

messages: list[dict] = field(default_factory=list)

def add(self, role: Role, content: str):

self.messages.append({"role": role, "content": content})

def get_context(self) -> list[dict]:

return self.messages

def trim(self, max_turns: int = 12):

"""保留最近若干轮,避免上下文无限增长。"""

self.messages = self.messages[-max_turns:]

在生产环境里,短期记忆通常还会加上“断点恢复”。比如 Agent 调用工具失败了、任务暂停了、用户刷新页面了,下次还能从 checkpoint 恢复,而不是从头来一遍。

四、长期记忆:跨会话的档案库

长期记忆存的不是所有聊天流水,而是未来还可能有价值的信息。例如用户偏好、项目背景、历史决策、常用流程、失败经验、实体关系。

这类记忆必须能被检索、能被更新、能被删除、能被审计。只说“存在数据库里”是不够的,真正要回答的是:存什么字段?怎么召回?怎么过滤权限?怎么处理旧记忆和新记忆冲突?

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

生产级 Memory Service 架构

五、记忆存储的完整闭环

一条记忆从产生到被使用,大致会经历八步:捕获、提取、结构化、向量化、存储、检索、注入、更新/遗忘。

这里最容易出错的是“只写不管”。如果只要用户说一句话就写入长期记忆,记忆库会很快变成垃圾堆。正确做法是先判断这条信息是否值得长期保存,再决定写入粒度、类型和有效期。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

记忆写入与读取闭环

六、长期记忆到底存在哪?

向量数据库很重要,但它不是全部。向量库解决的是“语义相似召回”,不是权限管理、事务一致性、版本管理、原始日志归档和实体关系推理。

工程里更常见的是多存储组合:Redis 存热会话,Postgres 存结构化元数据,Vector DB 存语义索引,Elasticsearch 做关键词和混合检索,Graph DB 存实体关系,对象存储保留原始材料。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

不同存储在记忆系统中的位置

七、一条长期记忆应该怎么设计?

长期记忆的核心不是 content 字段,而是 content、embedding、metadata、namespace、version、score、status 的组合。

content 是真正给 LLM 看的内容;embedding 是语义索引;metadata 负责过滤;namespace 负责隔离;version 和 status 负责更新、失效和删除。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

MemoryRecord 数据模型

from dataclasses import dataclass

from typing import Literal, Optional

from datetime import datetime

MemoryType = Literal["semantic", "episodic", "procedural"]

MemoryStatus = Literal["active", "expired", "deleted"]

@dataclass

class MemoryRecord:

id: str

namespace: tuple[str, ...] # 例:("user_123", "coding")

type: MemoryType # 语义 / 情节 / 程序记忆

content: str # 给 LLM 注入的短文本

metadata: dict # source、tags、scope、created_at

embedding: Optional[list[float]] = None

importance: float = 0.5

confidence: float = 0.8

status: MemoryStatus = "active"

created_at: datetime = datetime.utcnow()

updated_at: datetime = datetime.utcnow()

八、记忆粒度:不要一句话一条,也不要一整场对话一条

粒度太细,检索时容易只命中碎片,LLM 拿不到完整背景。粒度太粗,检索命中了也会带入大量无关内容,浪费上下文,还会干扰回答。

更推荐的粒度,是“一个独立知识点”或“一个关键事件”。比如“用户偏好 Python、代码简洁、变量英文、注释英文”应该合并成一条偏好记忆,而不是拆成四条。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

九、长期记忆怎么写入?

写入长期记忆之前,先做一个判断:这条信息以后还会不会影响 Agent 的行为?如果不会,就不要存。

真正可用的写入链路通常是:原始对话 -> 记忆候选 -> 重要性评分 -> 去重/冲突检测 -> 向量化 -> 写入存储 -> 记录审计日志。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

def should_write_memory(candidate: dict) -> bool:

"""判断是否值得进入长期记忆。"""

if candidate["type"] not in {"semantic", "episodic", "procedural"}:

return False

if candidate.get("importance", 0) < 0.6:

return False

if candidate.get("contains_sensitive_data") and not candidate.get("user_allowed"):

return False

return True

async def save_memory(memory_store, embedder, record: MemoryRecord):

if not should_write_memory(record.metadata):

return None

# 1. 生成向量

record.embedding = await embedder.embed(record.content)

# 2. 用 namespace 做租户/用户/项目隔离

# 3. content 用于注入 Prompt,embedding 用于语义召回,metadata 用于过滤和审计

await memory_store.put(

namespace=record.namespace,

key=record.id,

value={

"content": record.content,

"type": record.type,

"metadata": record.metadata,

"importance": record.importance,

"confidence": record.confidence,

"status": record.status,

},

embedding=record.embedding,

)

return record.id

十、长期记忆怎么读取?

读取记忆时,千万不要简单地“向量 TopK 拿回来直接塞 Prompt”。这样很容易召回过期记忆、无权限记忆、低质量记忆。

更稳的方式是混合召回:先用 namespace 和 metadata 做过滤,再用向量检索找语义相似,再结合关键词检索补充精确匹配,最后按时间新鲜度、重要度、可信度做重排。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

def rank_memory(semantic_score: float,

freshness: float,

importance: float,

confidence: float) -> float:

"""记忆排序公式:不要只看语义相似度。"""

return (

semantic_score * 0.55 +

freshness * 0.20 +

importance * 0.15 +

confidence * 0.10

)

async def retrieve_memories(memory_store, query: str, user_id: str, top_k: int = 5):

query_vec = await embedder.embed(query)

candidates = await memory_store.search(

namespace=(user_id, "global"),

embedding=query_vec,

filters={"status": "active"},

limit=30,

)

reranked = sorted(

candidates,

key=lambda m: rank_memory(

semantic_score=m.score,

freshness=m.metadata["freshness"],

importance=m.metadata["importance"],

confidence=m.metadata["confidence"],

),

reverse=True,

)

return reranked[:top_k]

十一、更新与遗忘:长期记忆不是越多越好

用户偏好会变,项目状态会变,业务规则会变。如果长期记忆只追加不更新,时间久了反而会误导 Agent。

比较好的做法是:原始日志 append-only 保留用于审计;当前有效画像做可更新记录;旧记忆可以降权、过期、合并或标记删除。这样既保留历史,又不让旧信息污染当前决策。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

时间衰减、冲突检测与记忆合并

十二、安全治理:记忆越强,越要守边界

长期记忆会保存用户偏好、工作习惯、项目背景,甚至可能涉及敏感信息。只要跨会话保存,就必须设计用户可见、可改、可删的机制。

另外,检索出来的记忆不能直接当成最高优先级指令。记忆只是上下文,不应该覆盖系统安全策略,也不应该被用户通过 Prompt 注入污染。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

十三、一个更完整的 Agent 记忆执行流程

把上面的设计串起来,一个任务开始时先读取长期记忆,压缩后注入 Prompt;任务执行中靠短期记忆维持状态;任务完成后,再把真正有价值的新结论写入长期记忆。

async def run_agent_with_memory(user_id: str, user_request: str):

# 1. 读取长期记忆:只拿当前用户、当前任务相关的内容

memories = await retrieve_memories(memory_store, user_request, user_id, top_k=5)

memory_context = "\n".join([m.content for m in memories])

# 2. 初始化短期记忆:把相关长期记忆作为背景,而不是把所有历史塞进去

stm = ShortTermMemory()

stm.add("system", f"以下是与本次任务相关的历史记忆:\n{memory_context}")

stm.add("user", user_request)

# 3. Agent 执行任务:过程中持续追加工具结果和中间状态

result = await agent.run(stm.get_context())

stm.add("assistant", result.answer)

# 4. 任务结束:抽取真正值得长期保存的信息

candidates = await memory_extractor.extract(stm.get_context())

for candidate in candidates:

record = MemoryRecord(**candidate)

await save_memory(memory_store, embedder, record)

return result.answer

十四、常见踩坑

把长期记忆理解成“SQL LIKE 查询”:关键词不重合时召回不到,必须引入 embedding 或混合检索。

把每句话都存成一条记忆:召回时拿到碎片,LLM 不知道完整偏好。

把整场对话存成一条记忆:内容太长,注入 Prompt 后噪音大。

只写入不更新:用户偏好变化后,旧记忆仍然被召回。

没有 namespace:不同用户、项目、组织之间的记忆可能串库。

没有审计和删除:用户不知道系统记住了什么,也无法撤回。

AI Agent 的长短期记忆系统怎么做?记忆是怎么存的?配图

十五、总结

Agent 记忆系统,本质不是“多存点聊天记录”,而是一个可治理的数据系统。

短期记忆像工作台,服务当前任务;长期记忆像档案库,服务跨会话积累。短期记忆重点是压缩和恢复,长期记忆重点是粒度、检索、更新和权限。

真正能上线的方案,一定不是单一向量库,而是 Memory Service + 多存储组合:向量库负责语义召回,SQL/KV 负责结构化管理,搜索引擎补关键词,图数据库补实体关系,对象存储保留原始证据。

要点速读

一、Agent 为什么需要记忆? 没有记忆的 Agent,很像一个“每次见面都重新认识你”的助手。你今天告诉它代码风格要

  • 一、Agent 为什么需要记忆
  • 没有记忆的 Agent,很像一个“每次见面都重新认识你”的助手
  • 你今天告诉它代码风格要