导言: 当你和 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


目录

  1. 为什么 AI Agent 需要记忆?

  2. 现有记忆系统的困境

  3. O-Mem 核心设计思路

  4. 三大记忆组件详解

  5. 分层检索机制

  6. 代码实战:用 Python 模拟 O-Mem 核心逻辑

  7. 实验结果:SOTA 性能 + 极致效率

  8. 横向对比:主流记忆框架一览

  9. 应用场景展望

  10. 总结


为什么 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 上的几个百分点。


📌 如果觉得有帮助,欢迎点赞收藏!有问题欢迎在评论区交流~

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐