Skip to content

L1 auto-recall needs atomization and token-budget safeguards #70

@leoge007

Description

@leoge007

问题:L1 Atom 由 LLM 抽取,但 auto-recall 直接注入 L1 topK,容易导致上下文膨胀和记忆漂移

我们在实际使用 TencentDB-Agent-Memory 做长期个人 Agent 记忆时,观察到一个比较核心的设计风险:

当前实现中,auto-recall 会直接搜索 L1 memories,并把 topK L1 文本注入到本轮上下文中。源码里也能看到类似逻辑:

  • auto-recall hook searches L1 memories using keyword / embedding / hybrid
  • recall.maxResults 默认 5
  • L1 relevant memories 会进入 prependContext
  • L3 persona / L2 scene navigation 会进入 system context

这套机制在 L1 足够“原子化”的情况下是合理的。但实际运行中,L1 的生成依赖 LLM extraction prompt。如果模型输出风格不稳定、prompt 约束不够强,或者输入本身是复杂多阶段事件,L1 可能不再是 Atom,而会变成较长的 incident summary / workflow report。

这会带来几个问题:

  1. recall.maxResults 只能限制条数,不能限制上下文体积

    即使 topK=5,如果单条 L1 有 1500-3000 字,一轮 recall 仍然会注入大量 token。

  2. L1 偏离 Atom 设计后,会直接影响 recall 质量

    例如一个复杂事件包含:旧状态、修复、回滚、再次修复、最终状态。若被压成一条长 L1,后续 recall 时容易把过时状态和当前状态一起带入上下文。

  3. LLM extraction 的变数会传导到 recall

    L1 是 LLM 生成的。如果模型偷懒、输出长摘要、误分类,或者将临时流程抽成 instruction/persona,那么这些问题会被 auto-recall 放大。

  4. L2/L3 的分层理念很好,但当前 auto-recall 仍然直接依赖 L1 文本

    README 中的分层理念是 Persona / Scenario → Atom → Conversation 的 progressive disclosure。但当前 auto-recall 实现会直接注入 topK L1,因此 L1 的长度和原子性变得非常关键。

建议

希望官方考虑增加以下机制,避免 L1 过胖导致上下文膨胀:

1. L1 长度约束

增加配置项,例如:

{
  "recall": {
    "maxCharsPerMemory": 800,
    "maxTotalRecallChars": 3000
  }
}

当单条 L1 超过阈值时:

  • recall 阶段截断;或
  • 使用该 L1 的短摘要;或
  • 改为提示 agent 通过 tdai_memory_search / L0 drill-down 查询详情。

2. L1 Atomization Quality Gate

在 L1 写入前增加 doctor / validator:

  • 标记超长 L1
  • 标记包含多个时间段 / 多个状态变更的 L1
  • 标记同时包含 old state + new state 的 L1
  • 标记任务级 instruction 是否误泛化为全局 instruction
  • 标记 persona/instruction/episodic 的分类风险

这些可以先只做 warning,不一定阻断写入。

3. Recall 阶段的 token budget

不仅限制 maxResults,还限制总注入体积:

  • 按 score 排序
  • 逐条加入 memory
  • 达到 token/char budget 后停止
  • 超长条目使用 compressed version

4. Supersede / valid_until / stale state 支持

对于配置、任务状态、导入状态等容易过期的信息,希望 L1 能支持:

  • superseded_by
  • valid_until
  • status: active | stale | superseded

否则旧状态可能长期被 recall 到上下文中。

5. 将复杂 incident 更明确地归入 L2 Scenario,而不是 L1 Atom

如果一次 L1 extraction 检测到某条 memory 包含多阶段过程,应优先生成多个短 L1 atom,或者将长叙事交给 L2 scene block 承载,而不是写成单条超长 L1。

期望结果

TDB 的分层架构方向非常好。这个 issue 的重点不是否定 L1 recall,而是希望让 L1 更符合 “Atom” 设计,并避免 LLM extraction 的不稳定性直接膨胀上下文。


English summary

We observed a design risk in the current auto-recall path: L1 memories are extracted by an LLM, but auto-recall directly injects topK L1 records into the prompt context.

This works well only if L1 records are truly atomic. In practice, when the extraction model or prompt produces long incident summaries instead of atomic facts, recall.maxResults limits only the number of records, not the token budget. A few long L1 records can still inject thousands of tokens and mix stale state with current state.

Suggested improvements:

  1. Add recall.maxCharsPerMemory and recall.maxTotalRecallChars.
  2. Add an L1 atomization doctor / quality gate for overly long or multi-state records.
  3. Enforce a recall-time token/char budget, not just topK.
  4. Support superseded_by, valid_until, or stale-state markers for L1 records.
  5. Route complex multi-stage incidents to L2 Scenario blocks or split them into multiple short L1 atoms.

The goal is to preserve the value of TDB's layered memory architecture while preventing L1 extraction variability from directly causing context bloat or recall drift.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions