# 记忆树（src/openhuman/memory\_tree/）

`src/openhuman/memory_tree/` 是 **通用树引擎** 位于面向用户的 [Memory Tree 功能](/openhuman/zh/gong-neng/obsidian-wiki/memory-tree.md)。它负责与类型无关的机制——追加叶子、级联桶封存、将一层汇总到下一层、评分与嵌入、供代理检索——这些都是每种具体树变体（`源`, `全局`, `主题`）所共享的。它刻意 **不知道** 一棵树属于哪种变体。

与类型相关的策略——何时生成主题树、全局树覆盖什么范围、摘要如何写入——都位于 `src/openhuman/memory/tree_global` 和 `src/openhuman/memory/tree_topic`中。持久化（单一的 `Tree` 表及其模式）位于下一级的 `memory_store::trees`中。本模块位于它们之间。

```
memory（编排器） ──┐
                        │ 通过 TreeWriteRequest 写入叶子
                        ▼
memory_tree            （本模块——通用机制）
   ├── tree/           追加 + 级联封存 + 刷新
   ├── summarise.rs    通过聊天模型将 L_n -> L_{n+1} 文本
   ├── retrieval/      面向代理的读取工具（walk、drill、fetch）
   ├── score/          评分、嵌入、实体提取
   ├── tools.rs        从 memory::query 重新导出
   └── io.rs           规范的 Tree{Write,Read}{Request,Outcome,Result}
                        │
                        ▼
memory_store::trees    （持久化：一张 Tree 表，一个模式）
```

## 布局

| 路径                                                                                               | 角色                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory_tree/mod.rs) | 重新导出 `io::*` 以及托管在 `memory`中的控制器模式注册表。还重新导出 `memory::tree_global` + `memory::tree_topic` ，用于向后兼容的旧版 `memory_tree::tree_{global,topic}` 路径。                       |
| `io.rs`                                                                                          | 规范契约类型： `TreeWriteRequest` / `TreeWriteOutcome`, `TreeReadRequest` / `TreeReadHit` / `TreeReadResult`, `TreeLeafPayload`, `TreeLabelStrategy`。纯类型，无 IO。          |
| `tree/`                                                                                          | `bucket_seal` （追加叶子 + 级联封存）， `flush` （基于时间的部分封存）， `registry` （按类型参数化的 `get_or_create_tree` ，并处理 UNIQUE 冲突恢复）， `mod.rs` （重新导出 + `memory_store::trees` 旧版路径的兼容封装）。 |
| `summarise.rs`                                                                                   | 一个函数：为某个桶生成下一层的摘要文本。使用固定提示词和令牌预算封装聊天模型。                                                                                                                          |
| `retrieval/`                                                                                     | 面向代理的工具。读取： `walk` （代理式）， `drill_down`, `fetch_leaves`, `query_{source,global,topic}`, `search_entities`。写入： `ingest_document` （面向编排器）。                          |
| `score/`                                                                                         | 评分信号、嵌入（云端 / Ollama / 惰性后端）、实体提取（先正则，LLM 可选）、规范解析器、实体索引存储。                                                                                                       |
| `tools.rs`                                                                                       | 从 `memory::query` 重新导出，以保持向后兼容。                                                                                                                                  |
| `tree_runtime/`                                                                                  | Tree 汇总器控制器注册表——通过以下内容暴露： `all_tree_summarizer_controller_schemas` / `all_tree_summarizer_registered_controllers` 在 `mod.rs`.                                    |

## 层级规则

这些是不容破坏的关键不变量——破坏任意一条，引擎就不再与类型无关：

* **这里不进行树类型分支。** `bucket_seal`, `flush`, `registry`，以及 `summarise` 都将 `TreeKind` 作为参数，或者将其视为不透明值。针对“这是不是 Source 树？”的条件判断应放在编排器（`src/openhuman/memory/`）中，而不是这里。
* **这里没有持久化。** 读写都通过 `memory_store::trees::{store, registry, hotness}`。本模块不会直接打开 SQLite 句柄。
* **这里没有策略。** 策展门槛（热度阈值）、摘要节奏、全局范围哨兵都位于 `memory::tree_{global,topic}`中。本模块响应策略决策，而不制定策略。

## 写入如何流入

1. 编排器（`memory::*`）构造一个 `TreeWriteRequest` 带有一个 `TreeKind` 和一个 `TreeLeafPayload`.
2. `tree::bucket_seal` 将叶子追加到 L0 的打开桶中。如果桶满了，就会封存—— `summarise.rs` 生成 L1 摘要，它会成为 L1 桶中的一个叶子，并且级联会继续向上，直到遇到一个未满的桶。
3. `score/` 在后台运行：嵌入（云端 / Ollama / 惰性后端）、实体提取（先正则，LLM 可选）、热度信号。这些都不会阻塞写入路径。
4. 结果（`TreeWriteOutcome`）会同步返回给编排器；评分会异步追赶。

`tree::flush` 用于有时间边界的情况——如果一个桶在其 TTL 内还未填满，就会进行部分封存，这样下一层总能有一些新鲜内容可供摘要。

## 读取如何流出

代理通过 `retrieval/`:

* `walk` 中的工具访问本模块——代理式探索；代理选择要深入的摘要节点。
* `drill_down` ——从已知起始摘要进行确定性遍历。
* `fetch_leaves` ——为已封存的桶提取原始叶子。
* `query_{source,global,topic}` ——按类型范围检索；由编排器的树类型策略决定代理能看到哪一个。
* `search_entities` ——由 `score/`.

所有检索处理器都会查询 `memory_store::trees::hotness` ，以便先展示较热的内容。

## 控制器注册表

`memory_tree::mod.rs` 重新导出两个控制器注册表，它们会被接入 `src/core/all.rs`:

* `all_memory_tree_controller_schemas` / `all_memory_tree_registered_controllers` ——来源于 `memory::schema` （编排器托管它们；本模块仅将它们以 `memory_tree` 路径暴露出来）。
* `all_retrieval_controller_schemas` / `all_retrieval_registered_controllers` ——上面列出的面向代理的读取工具。
* `all_tree_summarizer_controller_schemas` / `all_tree_summarizer_registered_controllers` ——来自 `tree_runtime`，用于汇总器管理/检查。

## 相关

* [`memory_tree/README.md`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory_tree/README.md) ——本页所对应的权威内部读者概览。
* [Memory Tree 功能](/openhuman/zh/gong-neng/obsidian-wiki/memory-tree.md) ——终端用户看到的内容。
* [架构概览](https://github.com/tinyhumansai/openhuman/blob/main/gitbooks/developing/architecture.md) ——它在更大系统中的位置。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tinyhumans.gitbook.io/openhuman/zh/kai-fa/architecture/memory-tree.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
