O-Mem:让 AI Agent 真正“认识你“的全能记忆框架
导言: 当你和 AI 助手聊了几百轮之后,它还记得你是谁吗?大多数情况下——不记得。这正是当前 AI Agent 最大的短板之一:缺乏真正的长期记忆。2025 年 11 月,来自 AIWaves 的研究团队提出了 O-Mem(Omni Memory System),一个基于主动用户画像的全能记忆框架,在多个权威 benchmark 上刷新了 SOTA,同时将 token 消耗降低了 94%。本文带你全面解读这项工作。
📄 论文:O-Mem: Omni Memory System for Personalized, Long Horizon, Self-Evolving Agents 🔗 arXiv:[2511.13593] O-Mem: Omni Memory System for Personalized, Long Horizon, Self-Evolving Agents
目录
为什么 AI Agent 需要记忆?
想象一个场景:你向 AI 健康助手说过"我有乳糖不耐受",三天后你问它"帮我推荐一个下午茶",它却给你推荐了一杯拿铁……
这不是笑话,这是当前大多数 AI 系统面临的真实问题:每次对话都像第一次见面。
LLM 本身没有跨会话的记忆能力,所有上下文必须装入有限的 context window。一旦对话历史超出窗口长度,早期信息就会被丢弃。为了解决这个问题,外部记忆系统(Agent Memory System) 应运而生。
传统 LLM 模式: 用户: "我不喜欢辣的" AI: 好的![下次对话完全忘记] 带记忆的 Agent: 用户: "帮我点个外卖" Agent: [查询记忆] → 记得你不喜欢辣的 → 推荐清淡口味 ✅
现有记忆系统的困境
在 O-Mem 之前,已有多个记忆框架被提出,但它们普遍存在两个核心问题:
问题一:语义检索的盲区
现有系统(如 Mem0、A-Mem)大多基于"先分组,再检索"的范式:将历史对话按语义相似度分组,检索时找最相关的组。
问题在于:语义相关 ≠ 信息相关。
用户问:"这个周末我应该去哪里玩?" 基于语义检索: → 找到"旅游、活动、周末"相关的记忆 → 忽略了:"用户最近在加班"、"用户有腰伤" → 推荐了爬山…… O-Mem 的做法: → 同时考虑用户的健康状态、近期日程、兴趣偏好 → 推荐了一个轻松的室内展览 ✅
问题二:分组检索引入噪声
当历史信息被分进"不够好"的组时,系统可能不得不从多个组里拼凑信息,带来大量冗余检索,直接拉高 latency 和 token 消耗。
O-Mem 核心设计思路
O-Mem 的核心哲学是一次根本性的视角转变:
从"存储对话记录" → 到"主动理解这个人"
不是简单地把聊天记录存下来备查,而是像一个真正了解你的朋友一样,持续构建和更新对你的理解:你是什么样的人?你经历了什么?你现在在关注什么?
O-Mem 借鉴了人类大脑的记忆架构,将记忆分为三个相互协作的组件:
┌─────────────────────────┐ │ O-Mem │ │ │ 用户交互 ──→ │ ┌─────────────────┐ │ │ │ Persona Memory │ │ ← "你是谁" │ │ (长期人格画像) │ │ │ └─────────────────┘ │ │ ┌─────────────────┐ │ │ │ Episodic Memory │ │ ← "你经历了什么" │ │ (情节记忆) │ │ │ └─────────────────┘ │ │ ┌─────────────────┐ │ │ │ Working Memory │ │ ← "当下在说什么" │ │ (工作记忆) │ │ │ └─────────────────┘ │ └─────────────────────────┘
三大记忆组件详解
1. Persona Memory(人格记忆)—— "你是谁"
Persona Memory 负责构建和维护用户的长期静态特征画像,包含两个维度:
-
Persona Attributes(人格属性):用户的稳定特征
{ "职业": "软件工程师", "饮食习惯": "素食主义者", "性格": "内向,偏好独处", "健康状况": "腰椎不好,不适合久坐" } -
Persona Facts(人格事实):用户经历的重要事件
{ "events": [ "2025-03 参加了马拉松,成绩 4:20", "2025-05 换了新工作,压力较大", "2025-06 开始学习日语" ] }
每次对话结束后,O-Mem 会自动提取新信息并更新这个画像,解决信息冲突(如用户说"我戒掉咖啡了",系统自动更新旧记录)。
2. Episodic Memory(情节记忆)—— "你经历了什么"
仿照人类的情景记忆,Episodic Memory 建立了线索词 → 具体对话场景的映射索引:
线索词: "项目截止日" → 对应 2025-05-10 那次对话:用户说截止日快到了,压力很大,请求帮助排期 线索词: "妈妈" → 对应多次对话:询问妈妈病情,给妈妈买礼物建议...
这样,当用户提到某个关键词时,O-Mem 能精准关联到相关的历史情境,而不是泛泛地做语义匹配。
3. Working Memory(工作记忆)—— "当下在说什么"
Working Memory 负责当前会话的主题追踪,建立 topic → 相关交互 的实时索引,确保同一话题下的对话保持连贯性:
当前 topic: "周末计划" Working Memory 汇总: - 用户提到想放松 - 上次聊过最近工作压力大 - Persona Memory 显示用户有腰伤 → 综合以上,给出个性化建议
分层检索机制
O-Mem 的检索不是一次性的暴力搜索,而是分层协作的过程:
用户输入查询 Q │ ▼ ┌──────────────────┐ │ Step 1: 主题识别 │ → 提取当前话题 t └──────────────────┘ │ ▼ ┌──────────────────┐ │ Step 2: 检索 │ → 从三类记忆并行检索: │ Persona Attrs │ · 人格属性(全量) │ + Topic Events │ · 话题相关情节 │ + Clue Words │ · 线索词触发的历史场景 └──────────────────┘ │ ▼ ┌──────────────────┐ │ Step 3: 融合上下│ → 将检索结果注入 LLM prompt │ 文生成回复 │ └──────────────────┘
这种设计避免了"检索噪声"问题:每层检索都有明确职责,不需要从所有分组里捞信息。
代码实战:用 Python 模拟 O-Mem 核心逻辑
下面实现一个简化版的 O-Mem,展示其核心的用户画像更新与分层检索逻辑:
import json
from dataclasses import dataclass, field
from typing import Dict, List, Optional
from datetime import datetime
# ==================== 数据结构 ====================
@dataclass
class PersonaMemory:
"""人格记忆:存储用户的长期特征"""
attributes: Dict[str, str] = field(default_factory=dict) # 稳定属性
facts: List[Dict] = field(default_factory=list) # 历史事件
@dataclass
class EpisodicMemory:
"""情节记忆:线索词 → 对话场景 的映射"""
clue_index: Dict[str, List[str]] = field(default_factory=dict)
@dataclass
class WorkingMemory:
"""工作记忆:当前 topic → 相关对话 的映射"""
topic_index: Dict[str, List[str]] = field(default_factory=dict)
# ==================== O-Mem 核心类 ====================
class OMem:
def __init__(self, llm_client=None):
"""
llm_client: 调用 LLM 的客户端(如 openai.Client),
本示例用 mock 函数代替
"""
self.persona = PersonaMemory()
self.episodic = EpisodicMemory()
self.working = WorkingMemory()
self.llm = llm_client
# ---------- 1. 记忆写入 ----------
def update_from_interaction(self, user_message: str, timestamp: str = None):
"""
从用户消息中主动提取并更新记忆
(实际系统中,这里调用 LLM 来做信息抽取)
"""
if timestamp is None:
timestamp = datetime.now().isoformat()
# Step 1: 提取人格属性(模拟 LLM 提取)
extracted_attrs = self._extract_persona_attributes(user_message)
for key, value in extracted_attrs.items():
# 处理冲突:新信息覆盖旧信息
if key in self.persona.attributes:
print(f"[Persona Update] {key}: '{self.persona.attributes[key]}' → '{value}'")
self.persona.attributes[key] = value
# Step 2: 提取事件记录
event = self._extract_event(user_message, timestamp)
if event:
self.persona.facts.append(event)
# Step 3: 建立线索词索引(情节记忆)
clue_words = self._extract_clue_words(user_message)
for word in clue_words:
if word not in self.episodic.clue_index:
self.episodic.clue_index[word] = []
self.episodic.clue_index[word].append(user_message)
# Step 4: 更新话题索引(工作记忆)
topic = self._extract_topic(user_message)
if topic not in self.working.topic_index:
self.working.topic_index[topic] = []
self.working.topic_index[topic].append(user_message)
# ---------- 2. 分层检索 ----------
def retrieve(self, query: str) -> Dict:
"""
分层检索:综合三类记忆,返回与 query 相关的上下文
"""
context = {}
# Layer 1: 全量人格属性(始终注入)
context["persona_attributes"] = self.persona.attributes
# Layer 2: 情节记忆(线索词匹配)
clue_words = self._extract_clue_words(query)
episodic_hits = []
for word in clue_words:
if word in self.episodic.clue_index:
episodic_hits.extend(self.episodic.clue_index[word])
context["episodic_context"] = list(set(episodic_hits))[:3] # 取前3条去重
# Layer 3: 话题相关事件(工作记忆)
topic = self._extract_topic(query)
context["topic_context"] = self.working.topic_index.get(topic, [])[:3]
# Layer 4: 相关人格事件
context["related_facts"] = self._search_facts(query)
return context
def build_prompt(self, user_query: str) -> str:
"""将检索结果注入 prompt"""
ctx = self.retrieve(user_query)
prompt = f"""你是用户的个人 AI 助手。以下是你对该用户的了解:
## 用户画像
{json.dumps(ctx['persona_attributes'], ensure_ascii=False, indent=2)}
## 相关历史经历
{chr(10).join(f'- {f}' for f in ctx['related_facts']) or '暂无'}
## 当前话题的历史对话
{chr(10).join(f'- {c}' for c in ctx['topic_context']) or '暂无'}
## 触发的情节记忆
{chr(10).join(f'- {c}' for c in ctx['episodic_context']) or '暂无'}
---
用户当前问题:{user_query}
请结合以上用户信息,给出个性化的回复:"""
return prompt
# ---------- 3. 辅助方法(实际使用时替换为 LLM 调用)----------
def _extract_persona_attributes(self, text: str) -> Dict:
"""模拟:从文本中提取人格属性"""
attrs = {}
if "不吃辣" in text or "不喜欢辣" in text:
attrs["饮食偏好"] = "不吃辣"
if "素食" in text:
attrs["饮食偏好"] = "素食主义"
if "工程师" in text or "程序员" in text:
attrs["职业"] = "软件工程师"
if "腰" in text and ("痛" in text or "不好" in text):
attrs["健康状况"] = "腰部不适,不宜久坐或剧烈运动"
return attrs
def _extract_event(self, text: str, timestamp: str) -> Optional[Dict]:
"""模拟:从文本中提取事件"""
keywords = ["换工作", "搬家", "结婚", "毕业", "生病", "出差", "旅行"]
for kw in keywords:
if kw in text:
return {"time": timestamp, "event": text[:100], "keyword": kw}
return None
def _extract_clue_words(self, text: str) -> List[str]:
"""模拟:提取关键线索词"""
# 实际使用 NER 或 LLM 提取
common_words = {"的", "了", "是", "在", "我", "你", "他", "她", "它",
"和", "与", "或", "但", "因为", "所以"}
words = [w for w in text.split() if w not in common_words and len(w) > 1]
return words[:5]
def _extract_topic(self, text: str) -> str:
"""模拟:识别当前话题"""
topic_map = {
"吃": "饮食", "餐": "饮食", "菜": "饮食",
"运动": "健康", "锻炼": "健康", "跑步": "健康",
"工作": "职业", "项目": "职业", "代码": "职业",
"周末": "计划", "旅行": "计划", "假期": "计划",
}
for kw, topic in topic_map.items():
if kw in text:
return topic
return "通用"
def _search_facts(self, query: str) -> List[str]:
"""从人格事件中检索相关内容"""
results = []
for fact in self.persona.facts:
if any(kw in fact["event"] for kw in query.split()):
results.append(f"[{fact['time'][:10]}] {fact['event'][:60]}")
return results[:3]
# ==================== 使用示例 ====================
if __name__ == "__main__":
omem = OMem()
# 模拟多轮历史对话
history = [
"我是一名软件工程师,最近在做一个推荐系统项目",
"我不吃辣,也不吃牛肉,最近在尝试素食",
"我腰不太好,医生说不适合剧烈运动",
"上个月换了新工作,压力比较大,经常加班到很晚",
"我喜欢看科幻小说,最近在看刘慈欣的《三体》",
]
print("=== 构建用户记忆 ===")
for msg in history:
omem.update_from_interaction(msg)
print("\n=== 用户画像 ===")
print(json.dumps(omem.persona.attributes, ensure_ascii=False, indent=2))
print("\n=== 处理新查询 ===")
query = "这个周末我应该去哪里放松一下?"
prompt = omem.build_prompt(query)
print(prompt)
输出示例:
=== 构建用户记忆 ===
[Persona Update] 饮食偏好: '不吃辣' → '素食主义'
=== 用户画像 ===
{
"职业": "软件工程师",
"饮食偏好": "素食主义",
"健康状况": "腰部不适,不宜久坐或剧烈运动"
}
=== 处理新查询 ===
你是用户的个人 AI 助手。以下是你对该用户的了解:
## 用户画像
{
"职业": "软件工程师",
"饮食偏好": "素食主义",
"健康状况": "腰部不适,不宜久坐或剧烈运动"
}
## 相关历史经历
- [2025-06-01] 上个月换了新工作,压力比较大,经常加班到很晚
用户当前问题:这个周末我应该去哪里放松一下?
实验结果:SOTA 性能 + 极致效率
O-Mem 在三个主流 persona benchmark 上进行了评测:
| Benchmark | 评测任务 | O-Mem 得分 | 上一 SOTA | 提升 |
|---|---|---|---|---|
| LoCoMo | 长对话问答 | 51.76% | LangMem: 49.1% | +2.66% |
| PERSONAMEM | 人格对话生成 | 62.99% | A-Mem: 59.5% | +3.49% |
| 报告生成 | 深度用户分析 | SOTA | — | — |
效率对比(与最接近竞争对手相比):
Token 消耗: O-Mem ↓ 94% ✅✅✅ 推理延迟: O-Mem ↓ 80% ✅✅✅ 性能: O-Mem ↑ 3%+ ✅
O-Mem 在 Pareto 前沿上同时实现了更好的性能和更低的开销,这在记忆框架领域极为罕见——通常提高性能都需要牺牲效率。
横向对比:主流记忆框架一览
| 框架 | 核心机制 | 优势 | 劣势 |
|---|---|---|---|
| Mem0 | 提取关键信息独立存储 | 部署简单,API 友好 | 缺乏用户整体理解 |
| A-Mem | Zettelkasten 链表组织 | 记忆关联性强 | 检索噪声,扩展性有限 |
| MemoryOS | OS 架构,FIFO 队列 | 层次清晰 | 语义检索盲区 |
| LangMem | LangChain 生态集成 | 生态丰富 | 性能略低 |
| MemoryBank | 艾宾浩斯遗忘曲线 | 模拟人类遗忘 | 实时性不足 |
| O-Mem | 主动用户画像 + 分层检索 | 性能+效率双 SOTA | 论文仍在审稿阶段 |
应用场景展望
O-Mem 的设计使它特别适合以下场景:
🏥 AI 健康助手:记住用户的过敏史、用药记录、生活习惯,给出真正个性化的健康建议
📚 AI 教育导师:追踪学生的学习进度、薄弱点、学习风格,自适应调整教学策略
💼 AI 职场助手:了解用户的工作背景、项目上下文、沟通风格,提供更精准的职业建议
🎮 AI 游戏伴侣:记住玩家的游戏偏好、历史成就、习惯策略,提供沉浸式个性化体验
🤝 长期关系 AI:随着时间推移,真正"认识"用户,建立有深度的持续对话关系
总结
O-Mem 代表了 AI Agent 记忆系统的一次重要范式转变:
| 维度 | 传统记忆系统 | O-Mem |
|---|---|---|
| 核心任务 | 存储和检索对话记录 | 主动构建用户理解 |
| 记忆组织 | 语义分组 | 三层认知架构 |
| 检索方式 | 单一语义匹配 | 分层协作检索 |
| 用户建模 | 静态、被动 | 动态、主动、持续演进 |
| 效率 | 高 token 消耗 | 降低 94% token 消耗 |
如果说过去的 AI 只是一个"会搜索历史记录的工具",那么 O-Mem 开启的方向,是让 AI 成为一个真正了解你的伙伴。
随着 Agent 时代的到来,记忆系统将成为 AI 个性化能力的核心基础设施。O-Mem 这类工作的价值,远不止于 benchmark 上的几个百分点。
📌 如果觉得有帮助,欢迎点赞收藏!有问题欢迎在评论区交流~
更多推荐


所有评论(0)