AskTable
sidebar.freeTrial

AskTable 永久记忆系统:让 AI 记住每一次对话

AskTable 团队
AskTable 团队 2026-04-03

每一次对话都是孤岛——这是传统 AI 助手的痛点。用户说过的偏好、纠正过的错误、建立过的上下文,在下一次对话中全部丢失。AskTable 最新引入的永久记忆系统,正在打破这一困局。


一、问题的本质

1.1 对话式 AI 的记忆困境

┌─────────────────────────────────────────┐
│         对话 1                           │
│  用户:华东销售是多少?                  │
│  AI:1200 万                           │
│  用户:什么时间的?以后回答销售额这类指标,│
│       应该带上具体时间                   │
│  AI:好的。2026年Q1华东销售是1200万    │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│         对话 2(之后任意时间)           │
│  用户:华东利润怎么样?                  │
│  AI:2026年Q1净利润350万,            │
│      同比+18%,环比+5%               │  ← 自动带上时间
└─────────────────────────────────────────┘

问题根源:传统架构中,对话历史只在单次会话内有效。

1.2 用户体验的割裂

这种"失忆"导致:

  • 重复说明:每次都要重新描述偏好
  • 上下文断层:AI 无法理解用户的历史行为模式
  • 智能化程度低:看起来聪明,实则每次都是从头开始

二、技术方案选型

2.1 为什么选择 mem0?

AskTable 选择了 mem0 OSS 作为记忆框架,核心原因:

考量mem0 优势
开箱即用内置去重、冲突消解、过期机制
API 简洁add / search / get_all / delete 四个核心方法
可替换性通过 Protocol 抽象,后续可切换到自研方案
异步支持原生 AsyncMemory,与 asyncio 架构完美契合

2.2 向量存储:复用 Qdrant

┌─────────────────────────────────────────────────────────────┐
│                    AskTable 向量存储架构                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌──────────────┐        ┌──────────────┐                 │
│   │   Qdrant      │        │   Qdrant      │                 │
│   │  (已有)        │        │  (记忆专用)    │                 │
│   │  元数据检索    │        │  跨会话记忆    │                 │
│   └──────────────┘        └──────────────┘                 │
│                                                             │
│   共享基础设施,降低运维成本                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

复用已有的 Qdrant 实例,不引入新的基础设施依赖。


三、系统架构

3.1 整体流程

┌─────────────────────────────────────────────────────────────┐
│                    记忆系统工作流                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  对话开始                                                     │
│      │                                                       │
│      ▼                                                       │
│  ┌─────────────────┐                                        │
│  │  Memory Search  │  ← 用当前问题检索相关记忆                 │
│  └────────┬────────┘                                        │
│           │                                                  │
│           ▼                                                  │
│  ┌─────────────────┐                                        │
│  │  格式化并注入    │  ← 拼入 System Prompt                  │
│  │  memory_context │                                        │
│  └────────┬────────┘                                        │
│           │                                                  │
│           ▼                                                  │
│  ┌─────────────────┐                                        │
│  │  Agent 生成回复  │  ← 携带记忆上下文                       │
│  └────────┬────────┘                                        │
│           │                                                  │
│           ▼                                                  │
│  ┌─────────────────┐                                        │
│  │  Memory Write   │  ← 对话结束后异步写入(fire-and-forget)  │
│  └─────────────────┘                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.2 读写分离设计

读取(Search)在请求开始时

  • 用用户问题做语义搜索
  • 取 Top-K 条相关记忆
  • 注入 System Prompt

写入(Add)在回复完成后

  • 异步执行,不阻塞响应
  • mem0 内部调用 LLM 提取结构化事实
  • 自动去重和冲突消解

3.3 隔离粒度:Data Agent 级别

┌─────────────────────────────────────────────────────────────┐
│                    记忆隔离模型                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   DataAgent-A                                               │
│   ┌─────────────────────────────────┐                      │
│   │ 记忆空间:agent_id = "agent-a"   │                      │
│   │ - 用户偏好                       │                      │
│   │ - 常用报表                       │                      │
│   │ - 分析习惯                       │                      │
│   └─────────────────────────────────┘                      │
│                                                             │
│   DataAgent-B (独立记忆)                                    │
│   ┌─────────────────────────────────┐                      │
│   │ 记忆空间:agent_id = "agent-b"   │                      │
│   │ - 不同的用户偏好                  │                      │
│   │ - 不同的业务场景                  │                      │
│   └─────────────────────────────────┘                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

设计原则:同一 Data Agent 下的所有用户共享记忆(团队知识库模式)。


四、核心实现

4.1 MemoryService 抽象层

class MemoryService(Protocol):
    """记忆服务抽象,支持后续替换"""

    async def add(
        self,
        messages: list[dict],
        agent_id: str,
        metadata: dict | None = None
    ) -> list[str]: ...

    async def search(
        self,
        query: str,
        agent_id: str,
        top_k: int = 5
    ) -> list[MemoryItem]: ...

    async def get_all(
        self,
        agent_id: str
    ) -> list[MemoryItem]: ...

    async def delete(
        self,
        memory_id: str
    ) -> None: ...

价值:通过 Protocol 抽象,确保 mem0 只是实现之一,后续可平滑切换到自研方案。

4.2 记忆上下文格式化

# 从记忆中提取关键信息,格式化为自然语言
MEMORY_CONTEXT_TEMPLATE = """
## 历史记忆
{relevance_memories}

以下是与你相关的历史信息,请结合这些上下文来回答用户的问题。
"""

示例输出:

## 历史记忆
- 用户提问销售额、利润率等指标时,应带上具体时间段(2026-04-01)
- 用户主要关注华东区域的数据(2026-03-15)
- 偏好在图表中显示同比和环比增长率(2026-03-20)

以下是与你相关的历史信息,请结合这些上下文来回答用户的问题。

4.3 异步写入实现

async def run_conversation_task(ctx: Context, ...):
    # ... 执行对话 ...

    # 释放锁之后,异步写入记忆
    await release_lock()
    await stream_end()

    # Fire-and-forget,不阻塞用户收到回复
    asyncio.create_task(
        memory_service.add(
            messages=full_conversation,
            agent_id=data_agent_id
        )
    )

五、产品价值

5.1 用户体验升级

Before(无记忆)

用户:华东销售是多少?
AI:1200 万
用户:什么时间的?
AI:这是 Q1 的数据

用户(另一天):华东利润怎么样?
AI:2026年Q1净利润350万
    [没有时间维度,不知道是哪个时间段]

After(有记忆)

用户:华东销售是多少?
AI:1200 万
用户:什么时间的?以后回答销售额这类指标,应该带上具体时间
AI:好的。2026年Q1华东销售是1200万

用户(另一天):华东利润怎么样?
AI:2026年Q1净利润350万,同比+18%,环比+5%
    ← 自动带上时间维度,无需重复说明

5.2 智能化场景

场景无记忆有记忆
数据查询每次问区域、时间范围自动使用偏好设置
报表生成每次指定格式自动按习惯生成
异常分析每次说明关注指标自动追踪历史关注点
趋势解读每次解释业务背景自动关联历史洞察

5.3 前端交互

系统为 Data Agent 配置页面新增了 "Memories" Tab:

  • 开关控制:启用/禁用记忆功能
  • 记忆列表:查看当前 Agent 的所有记忆
  • 手动添加:补充重要偏好
  • 搜索记忆:检索特定记忆
  • 删除记忆:移除不需要的记忆

六、技术挑战与应对

6.1 LLM 调用成本

挑战:mem0 每次 add() 需要 1-2 次 LLM 调用提取事实。

应对

  • 写入异步化,不阻塞响应
  • 批量处理,积累多轮对话后统一写入
  • 按需开启(通过 memory_enabled 开关)

6.2 中文场景质量

挑战:mem0 的事实提取 prompt 主要面向英文。

应对

  • 评估文档显示 AskTable 记忆偏结构化(表名、指标名)
  • 这类记忆的提取相对简单,中英文差异影响小
  • 持续监控提取质量,必要时调整 prompt

6.3 调试困难

挑战:记忆错误时,需要 trace mem0 内部链路。

应对

  • 完善的日志记录
  • 前端可见记忆列表,便于人工验证
  • Protocol 抽象确保可替换

七、与业界方案的对比

方案记忆粒度实现难度维护成本适用场景
Session Storage会话级临时存储
User KV Store用户级简单偏好
mem0Agent 级复杂上下文
自研向量库灵活深度定制

AskTable 的选择:mem0 是"快速验证"路径,Protocol 抽象为"长期演进"留有余地。


八、未来演进

8.1 潜在优化方向

  • 记忆分级:重要记忆 vs 临时记忆,设置不同过期时间
  • 主动记忆:Agent 主动判断是否写入记忆
  • 记忆可视化:图形化展示记忆关联
  • 记忆评估:量化记忆带来的效果提升

8.2 自研路径

如果 mem0 在中文数据分析场景表现不佳,可切换到自研方案:

已有基础设施:
├── Qdrant (向量存储)
├── BAAI/bge-small-zh-v1.5 (Embedding)
└── Langfuse (观测)

自研需解决:
├── 事实提取 Prompt
├── 去重/冲突策略
└── 记忆衰减机制

九、总结

AskTable 永久记忆系统的引入,标志着 AI 数据分析助手从"响应式工具"向"智能化伙伴"的进化:

核心价值

  1. 上下文连续性:跨越会话记住用户偏好
  2. 主动学习:从对话中自动提取有价值的信息
  3. 个性化服务:每次交互都比上一次更懂用户

技术亮点

  1. mem0 + Qdrant 的组合,平衡了开发效率和长期可维护性
  2. Protocol 抽象确保技术选型不锁定
  3. 读写分离设计,兼顾性能和效果

产品意义: 记忆系统让 AI 真正"认识"了用户,而不只是回答问题。这是从"工具"到"助手"的关键一步。


相关阅读

cta.readyToSimplify

sidebar.noProgrammingNeededsidebar.startFreeTrial

cta.noCreditCard
cta.quickStart
cta.dbSupport