docs(memory): add document for memory

This commit is contained in:
2026-04-30 16:08:18 +08:00
parent 4a00e5f320
commit cbd926bd41
5 changed files with 271 additions and 3 deletions

View File

@@ -0,0 +1,45 @@
# AfterRolling
`AfterRolling``DialogRolling` 完成一次上下文滚动后的扩展点。它不生成原始记忆,而是消费已经生成的 `RollingResult`
,适用于维护组织层索引、补充组织信息,或执行与新记忆相关的异步副作用。
```mermaid
flowchart TD
A["DialogRolling.triggerRolling"] --> B["buildRollingResult"]
B --> C["MemoryCapability.updateMemoryUnit"]
C --> D["MemoryUnit / MemorySlice"]
D --> E["applyRolling"]
E --> F["dialog_history ContextBlock"]
E --> G["rollChatMessagesWithSnapshot"]
E --> H["AfterRollingRegistry.trigger"]
H --> I["AfterRolling consumer[]"]
```
rolling 的主流程先完成原始记忆写入和当前上下文窗口裁剪,然后再触发 `AfterRollingRegistry`。因此,`AfterRolling` consumer
面对的是已经稳定生成的记忆结果,而不是待写入的临时数据。
## RollingResult
`RollingResult` 是 rolling 阶段传递给后处理 consumer 的数据包。
| 字段 | 说明 |
|---------------------|-----------------------|
| `memoryUnit` | 本次 rolling 写入或更新的记忆单元 |
| `memorySlice` | 本次 rolling 新生成的记忆切片 |
| `incrementMessages` | 本次进入记忆的增量消息 |
| `summary` | 本次切片摘要 |
| `rollingSize` | rolling 发生时的对话窗口大小 |
| `retainDivisor` | rolling 后保留近期上下文的比例参数 |
这些字段让 consumer 可以同时看到三类信息:已经落盘的记忆对象、原始增量消息,以及本次 rolling 对上下文窗口的处理参数。
## 当前 consumer
当前 memory 侧的主要 consumer 是 `MemoryRecallProfileExtractor`。它消费 `RollingResult`,读取当前主题树、切片摘要和原始消息片段,提取:
- `topicPath`
- `relatedTopicPaths`
- `ActivationProfile`
随后它调用 `MemoryRuntime.recordMemory(...)`,把新切片写入主题索引和日期索引。也就是说,原始记忆的生成发生在
`DialogRolling` 中,索引和召回组织信息的补充发生在 `AfterRolling` consumer 中。

View File

@@ -0,0 +1,113 @@
# 记忆检索
本文说明 Partner 记忆系统的组织层。存储层只保存稳定的 `MemoryUnit``MemorySlice`,检索层在这些数据之上建立可替换的召回结构。
当前默认实现是 `MemoryRuntime`:它维护主题路径索引和日期索引,并把索引结果重新解析为可注入上下文的 `ActivatedMemorySlice`
| 索引 | 作用 |
|---------------------------|------------------------------------------|
| `TopicMemoryIndex` | 按主题路径组织 `MemorySlice`,支持主主题、父主题和相关主题扩散召回 |
| `DateMemoryIndex` | 按日期记录 `MemorySlice` 引用,支持按日期直接召回 |
| `MemoryRuntimeStateCodec` | 负责主题索引和日期索引的持久化与恢复 |
## 索引建立
`MemoryRuntime` 不直接生成原始记忆。原始记忆由 `DialogRolling` 写入 `MemoryUnit` 后,`AfterRolling` consumer 会消费
`RollingResult`,为新产生的 `MemorySlice` 提取主题路径、相关主题和激活参数,再调用 `MemoryRuntime.recordMemory(...)` 建立索引。
```mermaid
flowchart TD
A["DialogRolling"] --> B["RollingResult"]
B --> C["AfterRollingRegistry"]
C --> D["MemoryRecallProfileExtractor"]
D --> E["topicPath<br/>主主题路径"]
D --> F["relatedTopicPaths<br/>相关主题路径"]
D --> G["ActivationProfile<br/>激活 / 扩散 / 上下文独立权重"]
B --> H["MemoryUnit"]
B --> I["MemorySlice"]
H --> J["SliceRef<br/>unitId + sliceId"]
I --> J
I --> K["LocalDate<br/>由 slice timestamp 转换"]
J --> L["MemoryRuntime.recordMemory"]
E --> L
F --> L
G --> L
K --> L
L --> M["DateMemoryIndex.record"]
L --> N["TopicMemoryIndex.recordBinding"]
L --> O["TopicMemoryIndex.ensureTopicPaths"]
M --> P["date -> SliceRef[]"]
N --> Q["topicPath -> TopicBinding[]"]
O --> R["related topic path nodes"]
```
`TopicMemoryIndex` 的绑定对象不是完整记忆内容,而是 `SliceRef`。它只记录 `unitId``sliceId`、时间戳、相关主题路径和
`ActivationProfile`。真正需要展示原始消息时,`MemoryRuntime` 会再回到 `MemoryCapability` 读取对应 `MemoryUnit`
`MemorySlice`
主题路径使用 `->` 表示层级,例如:
```text
project->partner->memory
```
`TopicMemoryIndex` 会按路径建立树节点;绑定到某个节点的 slice 表示该记忆切片属于这个主题。相关主题路径不会直接复制
slice而是作为扩散召回的候选入口参与后续评分。
## 使用检索: 主题路径和日期索引
运行时召回由 `MemorySelector` 触发。它会收集输入,使用当前主题树和输入内容提取召回线索,再按线索类型分别查询主题索引或日期索引。
```mermaid
flowchart TD
subgraph Input["输入收集"]
A["PartnerRunningFlowContext"] --> B["MemorySelector.collectInputs"]
B --> C["collectedInputs"]
C --> D["drainMemoryRecall"]
end
subgraph Cue["召回线索抽取"]
D --> E["MemoryRuntime.getTopicTree"]
D --> F["MemoryRecallCueExtractor"]
E --> F
F --> G["ExtractorResult.matches"]
end
subgraph Lookup["索引查询"]
G --> H{"match.type"}
H -- " TOPIC " --> I["MemoryRuntime.queryActivatedMemoryByTopicPath"]
H -- " DATE " --> J["MemoryRuntime.queryActivatedMemoryByDate"]
I --> K["TopicRecallCollector.collect"]
J --> L["DateMemoryIndex.find"]
K --> M["SliceRef[]"]
L --> M
end
subgraph Materialize["切片还原"]
M --> N["MemoryCapability.getMemoryUnit"]
M --> O["MemoryCapability.getMemorySlice"]
N --> P["sliceMessages"]
O --> P
P --> Q["ActivatedMemorySlice"]
end
subgraph Evaluate["评估与上下文注入"]
Q --> R["MemoryRecallEvaluator"]
R --> S["activated_memory_slices ContextBlock"]
S --> T["ContextWorkspace"]
end
```
按主题召回时,`TopicRecallCollector` 会从三个来源收集候选:
| 来源 | 含义 |
|-----------|-----------------------|
| `PRIMARY` | 当前主题节点直接绑定的 slice |
| `PARENT` | 父主题节点的近期候选,用于保留上层语境 |
| `RELATED` | 由当前主题绑定声明的相关主题,用于扩散召回 |
候选会经过 `TopicRecallScorer` 打分。分数综合来源类型、时间新近性、激活权重、上下文独立权重和扩散权重。最终结果会限制数量,并转换成
`ActivatedMemorySlice`
`ActivatedMemorySlice` 包含 slice 摘要、日期、时间戳以及对应原始消息片段。`MemorySelector` 会基于这些结果构造
`activated_memory_slices` 上下文块,使后续 communication、cognition 或 action 模块能够读取被激活的记忆。

View File

@@ -0,0 +1,99 @@
# 记忆存储
本文说明 Partner 记忆系统的稳定存储模型和原始记忆生成方式。
## MemoryUnit 与 MemorySlice
### 数据模型
存储层由 `MemoryCore``MemoryUnit``MemorySlice` 三层组成。
`MemoryCore` 维护记忆单元集合和当前记忆会话 id`MemoryUnit` 是可持久化的记忆单元,保存一段对话消息及其摘要切片;
`MemorySlice` 是对 `MemoryUnit` 中一段消息区间的摘要。
```mermaid
flowchart TD
A["MemoryCore"] --> B["memorySessionId<br/>当前记忆会话"]
A --> C["memoryUnits<br/>Map&lt;unitId, MemoryUnit&gt;"]
C --> D["MemoryUnit"]
D --> E["id"]
D --> F["timestamp<br/>最近更新时间"]
D --> G["conversationMessages<br/>原始对话消息"]
D --> H["slices<br/>List&lt;MemorySlice&gt;"]
H --> I["MemorySlice"]
I --> J["id"]
I --> K["startIndex / endIndex<br/>对应 conversationMessages 区间"]
I --> L["summary<br/>该区间摘要"]
I --> M["timestamp<br/>切片创建时间"]
```
`MemoryUnit` 的核心作用是把原始消息和摘要切片绑定在一起。`conversationMessages` 保存完整消息序列,`MemorySlice`
只记录它覆盖的消息区间和摘要内容。这样,召回层可以先使用摘要切片进行轻量检索,再在需要时回到对应 `MemoryUnit` 读取原始消息。
`MemoryCore` 自身只保存 `memorySessionId``memory_unit_uuid_set`,每个 `MemoryUnit` 独立持久化到自己的 state
path。也就是说`MemoryCore` 负责管理有哪些记忆单元,而具体消息和切片内容保存在 `MemoryUnit` 中。
| 对象 | 作用 |
|---------------|------------------------------------|
| `MemoryCore` | 维护当前记忆会话 id、记忆单元集合并提供读写入口 |
| `MemoryUnit` | 保存一组原始对话消息及其摘要切片,是稳定落盘单元 |
| `MemorySlice` | 描述 `MemoryUnit` 中一段消息区间的摘要,可被索引和召回 |
`MemorySlice` 会按创建时间参与排序;`MemoryCore` 在更新记忆时会对 slice 的 id、时间戳和消息区间做规范化避免索引越界或缺失基础字段。
### 生成方式
`MemoryUnit``MemorySlice` 的原始材料来自对话轨迹。`CommunicationProducer` 在完成对外回复后,将本轮用户输入和 assistant
输出写回 `CognitionCapability` 维护的 chat messages`DialogRolling` 在对话窗口过长或长时间未交互时,基于这些 chat
messages 生成记忆切片。
```mermaid
flowchart TD
subgraph Communication["CommunicationProducer"]
A["PartnerRunningFlowContext<br/>本轮输入"] --> B["生成对外回复"]
B --> C["updateChatMessages"]
C --> D["CognitionCapability.chatMessages"]
end
subgraph Rolling["DialogRolling"]
D --> E{"触发 rolling?"}
E -- " 对话数量达到阈值 " --> F["triggerRolling(false)"]
E -- " 长时间未交互 " --> G["triggerRolling(true)"]
F --> H["snapshotChatMessages"]
G --> H
H --> I["resolveChatIncrement"]
I --> J["MessageCompressor"]
J --> K["MessageSummarizer"]
K --> L["MemoryCapability.updateMemoryUnit"]
L --> M["MemoryUnit"]
L --> N["MemorySlice"]
end
subgraph Context["滚动后的上下文处理"]
N --> O["dialog_history ContextBlock"]
O --> P["ContextWorkspace"]
M --> Q["RollingResult"]
N --> Q
Q --> R["AfterRollingRegistry.trigger"]
end
```
生成流程可以分成两段:
1. **对话轨迹写入**`CommunicationProducer` 负责把本轮交流结果追加到 `chatMessages`。这里保存的是后续 rolling
能够消费的原始对话轨迹。
2. **对话滚动入库**`DialogRolling` 从当前对话快照中计算尚未进入当前 `MemoryUnit` 的增量消息,压缩并总结后调用
`MemoryCapability.updateMemoryUnit(chatMessages, summary)`。该调用会把消息增量追加到 `MemoryUnit.conversationMessages`
,并创建一个覆盖这段消息区间的 `MemorySlice`
`DialogRolling` 有两类触发方式:
| 触发方式 | 含义 |
|----------|------------------------------------------------|
| 对话数量达到阈值 | 当前上下文对话过长时触发 rolling只保留部分近期上下文 |
| 长时间未交互 | 定时检查发现距离上次交互超过阈值时触发 rolling并刷新 memory session |
rolling 完成后,系统会把新切片摘要注册为 `dialog_history` 上下文块,并裁剪当前 chat messages。随后 `AfterRollingRegistry`
会异步触发已注册的 `AfterRolling` consumer。这里的 consumer 只消费 `RollingResult`
,用于在原始记忆生成后执行额外维护逻辑;具体索引构建与召回组织在 [记忆检索](memory-retrieval.md)
中说明,扩展点机制见 [AfterRolling](after-rolling.md)。

View File

@@ -0,0 +1,14 @@
# 记忆存储与组织
本文是 Partner 记忆系统文档索引。Partner 的记忆系统分为两个层面:
- **存储层**:负责保存稳定的记忆数据。当前核心模型是 `MemoryUnit``MemorySlice`
- **组织层**:负责在存储数据之上建立可替换的召回结构。当前默认实现基于主题路径和日期索引;如果替换召回实现,需要由新实现自行维护对应索引。
这种划分让记忆落盘格式保持稳定,同时允许上层召回策略独立演进。
## 目录
- [`memory-storage.md`](memory-storage.md):说明 `MemoryCore``MemoryUnit``MemorySlice` 的数据模型,以及原始记忆如何由 `CommunicationProducer``DialogRolling` 生成。
- [`memory-retrieval.md`](memory-retrieval.md):说明默认组织层 `MemoryRuntime`,包括主题路径索引、日期索引、索引建立和运行时召回。
- [`after-rolling.md`](after-rolling.md):说明 `DialogRolling` 后的扩展触发点,以及 memory 侧如何通过 `AfterRolling` consumer 补充索引信息。