docs: restructure documentation and update content organization (#339)

* docs: restructure documentation and update content organization

* docs: update documentation structure and add application scenarios
This commit is contained in:
Sen Huang 2026-07-13 17:50:46 +09:00 committed by GitHub
parent b1c9bf67bf
commit 6a2dd02e48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 741 additions and 5397 deletions

155
AGENTS.md Normal file
View file

@ -0,0 +1,155 @@
# AGENTS.md
This file guides coding agents working in the ReMe repository. Keep changes small,
testable, and consistent with the contracts already expressed by the code.
## Project Principles
ReMe is a local-first, file-native memory system for agents.
- User-owned memory files are the source of truth.
- Indexes, caches, metadata, and generated state must be rebuildable.
- Prefer transparent formats and behavior over hidden state.
- Preserve user control over storage, configuration, and service boundaries.
- Keep concepts focused on project intent; let code and schemas describe implementation.
When a proposed convenience conflicts with these principles, favor data ownership,
recoverability, and predictable behavior.
## Sources of Truth
Use this order when documentation and implementation disagree:
1. Current code and public Pydantic schemas.
2. Tests that describe supported behavior.
3. CLI help and the built-in configuration.
4. Development documentation and historical notes.
Do not copy large implementation descriptions into documentation. Link to the relevant
module or express the stable contract instead. If behavior changes intentionally, update
the code, schema, tests, configuration, and concise documentation together as needed.
## Repository Map
- `reme/reme.py`: CLI entry point and client/server dispatch.
- `reme/application.py`: application assembly, dependency ordering, and lifecycle.
- `reme/config/default.yaml`: built-in jobs, components, and defaults.
- `reme/schema/`: public and runtime Pydantic contracts.
- `reme/components/`: services, stores, clients, jobs, and component registration.
- `reme/steps/`: executable job steps.
- `tests/unit/`: primary fast validation suite.
- `tests/integration/`: tests that may require real credentials or services.
- `tests/vector/` and `tests/light/`: specialized suites.
- `plugins/reme/`: Claude Code integration.
- `skills/reme_memory/`: skill that communicates with the ReMe service.
- `skills/qwenpaw_memory/`: separate direct-file memory convention; it does not call ReMe.
- `docs/`: pages and assets that support the repository README; not the deployed docs site.
## Development Setup
ReMe requires Python 3.11 or newer.
```bash
pip install -e ".[dev,core]"
```
Before changing behavior, inspect the adjacent implementation, schemas, configuration,
and focused tests. Follow existing patterns unless the task explicitly calls for a new
contract or architecture.
## Change Workflow
1. Identify the narrowest supported contract affected by the request.
2. Read the relevant implementation and tests before editing.
3. Make the smallest coherent change; avoid unrelated cleanup.
4. Update related schemas, defaults, registrations, and imports when required.
5. Add or adjust focused tests for observable behavior.
6. Run proportionate validation and report anything not run.
Component and step discovery depends on registration imports:
- Components use `R.register(...)` in `reme/components/component_registry.py`.
- Component packages must be reachable through `reme/components/__init__.py`.
- Step modules must be reachable through `reme/steps/__init__.py`.
Adding an implementation without its registration import can leave it undiscoverable at
runtime. Treat the implementation, registry entry, and import side effect as one change.
Do not silently change stable CLI flags, configuration keys, workspace layouts, serialized
schemas, or service interfaces. When such a change is required, preserve compatibility
where practical and make the migration explicit.
## Validation
Use the narrowest useful check while iterating, then broaden it according to risk.
Run a focused test:
```bash
pytest tests/unit/path/to/test_file.py -v
```
Run the main unit suite:
```bash
pytest tests/unit -v --tb=long -s --log-cli-level=WARNING
```
Run repository formatting and lint checks when the change warrants it:
```bash
pre-commit run --all-files
```
Formatting and lint configuration is authoritative. Python code currently uses a maximum
line length of 120 for Black and Flake8, with Pylint also run by pre-commit.
Integration tests may contact real services and require credentials such as
`LLM_API_KEY` or `EMBEDDING_API_KEY`. Do not run credentialed or externally mutating tests
automatically. Run them only when the task requires them and the user has supplied or
authorized the necessary environment.
## Coding and Test Conventions
- Target Python 3.11+ and follow the surrounding typing and async style.
- Keep public schemas explicit and backward-compatible where practical.
- Close async clients, services, tasks, and other lifecycle resources deterministically.
- Prefer clear failures over silently falling back to corrupt or ambiguous state.
- Keep indexes and caches derivable from user-owned source files.
- Use `tmp_path` or another isolated temporary workspace in tests.
- Never write test state into the repository's `.reme/` directory.
- Mock network or model boundaries in unit tests.
- Do not commit `.env` files, credentials, runtime memory, logs, indexes, or caches.
## Documentation Boundaries
ReMe's local docs and the deployed documentation site have separate responsibilities.
- Keep `docs/` focused on content and assets used by `README.md` and `README_ZH.md`.
- Preserve README-linked pages under `docs/en/` and `docs/zh/`, including their relative
paths, unless the README is updated in the same change.
- Keep README-required images under `docs/figure/`.
- Keep the README's main documentation index pointed at `docs.agentscope.io` or the
`agentscope-ai/docs` repository, following the existing link style.
- Do not treat local README-supporting pages as the source for the deployed website.
The separate `agentscope-ai/docs` repository owns website content, navigation, versioning,
and deployment. Public ReMe pages live there under `reme/<version>/`. Make website changes
in that repository and follow its existing version-management conventions.
Do not add website build configuration or deployment workflows to ReMe unless the task
explicitly changes this repository boundary.
## Agent Guardrails
- Preserve unrelated user changes in a dirty working tree.
- Do not edit generated output when the source can be changed instead.
- Do not delete or rewrite user data to make a test pass.
- Avoid broad refactors unless they are necessary for the requested outcome.
- Do not introduce dependencies without a concrete need and repository-level justification.
- Treat network access, real credentials, and external service mutations as opt-in.
- State which validations passed and which were not run in the final handoff.
If a requirement is ambiguous, first infer intent from nearby code, tests, and schemas. Ask
the user only when the remaining choice would materially alter a public contract, user data,
or external system.

1
CLAUDE.md Normal file
View file

@ -0,0 +1 @@
AGENTS.md

View file

@ -289,17 +289,16 @@ are mainly for maintenance, debugging, or advanced integration. Run `reme help`
- **Issues and requests**: Check [Open Issues](https://github.com/agentscope-ai/ReMe/issues) first. If there is no
related discussion, open a new issue with background, expected behavior, and impact scope.
- **Code contributions**: Before making changes, read the [contribution guide](docs/en/contributing.md)
and [code framework](docs/en/framework.md), and follow the CLI / Service / Application / Job / Step / Component
layering.
- **Documentation contributions**: For user-visible installation, configuration, invocation, or behavior changes, update
`docs/en/`, `docs/zh/`, or the README files accordingly.
- **Code contributions**: Before making changes, read the [contribution guide](https://docs.agentscope.io/reme/stable/en/contributing). Source,
schemas, and tests are the authoritative architecture and extension guide.
- **Documentation contributions**: Submit user-facing documentation changes to the
[unified documentation repository](https://github.com/agentscope-ai/docs) under `reme/<version>/{en,zh}/`.
- **Commit convention**: Conventional Commits are recommended, for example `feat(search): add link expansion option` or
`docs(zh): update quick start`.
- **Pre-submit checks**: Before submitting a PR, try to run `pre-commit run --all-files` and `pytest`. If tests that
depend on LLMs, embeddings, or external services cannot run, explain that in the PR.
- **Get help**: Use [GitHub Issues](https://github.com/agentscope-ai/ReMe/issues) for bugs and feature requests. Project
documentation is available at [https://reme.agentscope.io/](https://reme.agentscope.io/).
documentation is available at [https://docs.agentscope.io/](https://docs.agentscope.io/reme/stable/en/).
### Contributors
@ -323,7 +322,3 @@ Thanks to everyone who has contributed to ReMe:
## ⚖️ License
This project is open source under the Apache License 2.0. See [LICENSE](./LICENSE) for details.
## 📈 Star History
[![Star History Chart](https://api.star-history.com/svg?repos=agentscope-ai/ReMe&type=Date)](https://www.star-history.com/#agentscope-ai/ReMe&Date)

View file

@ -279,15 +279,14 @@ frontmatter 和文件操作接口主要用于维护、调试或高级集成。
- **问题反馈与需求**:请先查看 [Open Issues](https://github.com/agentscope-ai/ReMe/issues);如无相关讨论,可新建 Issue
说明背景、目标行为和影响范围。
- **代码贡献**:改动前建议阅读 [贡献指南](docs/zh/contributing.md) 和 [代码框架](docs/zh/framework.md),遵循 CLI /
Service / Application / Job / Step / Component 的分层。
- **文档贡献**:用户可见的安装、配置、调用或行为变化,请同步更新 `docs/en/``docs/zh/` 或 README 文件。
- **代码贡献**:改动前建议阅读 [贡献指南](https://docs.agentscope.io/reme/stable/zh/contributing)。架构与扩展方式以源码、schema 和测试为准。
- **文档贡献**:用户可见文档请提交到[统一文档仓库](https://github.com/agentscope-ai/docs)的 `reme/<version>/{en,zh}/` 目录。
- **提交规范**:建议使用 Conventional Commits例如 `feat(search): add link expansion option`
`docs(zh): update quick start`
- **提交前检查**:提交 PR 前请尽量运行 `pre-commit run --all-files``pytest`;如有依赖 LLM、embedding 或外部服务的测试无法运行,请在
PR 中说明。
- **获取帮助**:如需反馈 Bug 或功能请求,请使用 [GitHub Issues](https://github.com/agentscope-ai/ReMe/issues);项目文档见
[https://reme.agentscope.io/](https://reme.agentscope.io/)。
[https://docs.agentscope.io/](https://docs.agentscope.io/reme/stable/zh/)。
### 贡献者
@ -311,7 +310,3 @@ frontmatter 和文件操作接口主要用于维护、调试或高级集成。
## ⚖️ 许可证
本项目基于 Apache License 2.0 开源,详情参见 [LICENSE](./LICENSE) 文件。
## 📈 Star 历史
[![Star History Chart](https://api.star-history.com/svg?repos=agentscope-ai/ReMe&type=Date)](https://www.star-history.com/#agentscope-ai/ReMe&Date)

23
docs/README.md Normal file
View file

@ -0,0 +1,23 @@
# ReMe 仓库文档
本目录保存 ReMe 仓库 README 直接引用的中英文补充说明和图片资源,不作为文档站点的构建或部署来源。
面向用户发布的中英文文档位于 [agentscope-ai/docs](https://github.com/agentscope-ai/docs) 仓库,并由该仓库统一完成版本管理和 Mintlify 部署。
## 目录用途
```text
docs/
├── README.md 本目录的维护说明
├── doc.md 当前文档设计与维护边界
├── en/ README 引用的英文补充说明
├── zh/ README 引用的中文补充说明
└── figure/ ReMe README 使用的图片资源
```
## 维护原则
- `en/``zh/` 保持精简,服务 README 中需要进一步解释的功能与场景;修改路径时同步更新 README 链接。
- 具体实现以源码、schema、测试和运行时帮助为准避免维护重复且容易过期的开发手册。
- README 引用的图片保留在 `figure/`;发布文档需要图片时,在统一文档仓库的 `images/reme/` 中维护对应副本。
- 网页文档、导航、版本和部署在统一文档仓库中维护。

View file

@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ReMe Documentation</title>
<link rel="canonical" href="en/">
<!-- Default to the English docs; the sidebar switcher offers 中文. -->
<meta http-equiv="refresh" content="0; url=en/">
<script>location.replace("en/");</script>
</head>
<body>
<p>Redirecting to the <a href="en/">ReMe documentation</a></p>
</body>
</html>

View file

@ -1,78 +0,0 @@
/* Heading sizes — tighten furo's defaults */
h1, .bd-article h1 {
font-size: 1.8rem !important;
}
h2, .bd-article h2 {
font-size: 1.5rem !important;
}
h3, .bd-article h3 {
font-size: 1.25rem !important;
}
h4, .bd-article h4 {
font-size: 1.1rem !important;
}
h5, .bd-article h5 {
font-size: 1rem !important;
}
h6, .bd-article h6 {
font-size: 0.9rem !important;
}
/* Centered brand in the sidebar */
.sidebar-brand {
text-align: center;
}
.sidebar-brand .sidebar-logo {
max-width: 60%;
margin: 0 auto;
}
/* Language switcher (injected by switcher.js) */
.lang-switch {
display: flex;
gap: 0.4rem;
justify-content: center;
margin: 0.4rem 0 0.9rem;
}
.lang-switch a {
font-size: 0.8rem;
line-height: 1.4;
padding: 0.12rem 0.7rem;
border-radius: 999px;
border: 1px solid var(--color-background-border);
color: var(--color-foreground-secondary);
text-decoration: none;
cursor: pointer;
}
.lang-switch a:hover {
border-color: var(--color-brand-primary);
color: var(--color-brand-primary);
}
.lang-switch a.active {
background: var(--color-brand-primary);
border-color: var(--color-brand-primary);
color: #fff;
cursor: default;
}
.lang-switch--float {
position: fixed;
top: 0.6rem;
right: 0.8rem;
z-index: 50;
margin: 0;
background: var(--color-background-primary);
padding: 0.3rem 0.4rem;
border-radius: 999px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
}

View file

@ -1,54 +0,0 @@
// Language switcher for the ReMe docs.
//
// Each language is a separate Jupyter Book served under /zh/ and /en/ with the
// same page filenames. This injects a 中文 / EN toggle into the furo sidebar
// (falling back to a floating control) that swaps the language path segment of
// the current URL.
(function () {
"use strict";
var path = window.location.pathname;
var current, otherHref;
if (path.indexOf("/en/") !== -1) {
current = "en";
otherHref = path.replace("/en/", "/zh/");
} else if (path.indexOf("/zh/") !== -1) {
current = "zh";
otherHref = path.replace("/zh/", "/en/");
} else {
return; // not inside a language book (e.g. the root landing page)
}
function makeLink(label, lang) {
var a = document.createElement("a");
a.textContent = label;
if (lang === current) {
a.className = "active";
} else {
a.href = otherHref;
}
return a;
}
var wrap = document.createElement("div");
wrap.className = "lang-switch";
wrap.appendChild(makeLink("中文", "zh"));
wrap.appendChild(makeLink("EN", "en"));
function inject() {
var brand = document.querySelector(".sidebar-brand");
if (brand && brand.parentNode) {
brand.parentNode.insertBefore(wrap, brand.nextSibling);
} else {
wrap.classList.add("lang-switch--float");
document.body.appendChild(wrap);
}
}
if (document.readyState !== "loading") {
inject();
} else {
document.addEventListener("DOMContentLoaded", inject);
}
})();

85
docs/doc.md Normal file
View file

@ -0,0 +1,85 @@
# ReMe 文档设计
本文定义 ReMe 文档的内容边界和维护方式。目标是让文档保持精简、稳定,并适合用户与 AI coding agent 快速理解。
## 两类文档,两种职责
| 位置 | 用途 | 是否部署 |
|---|---|---|
| `ReMe/docs/` | README 引用的中英文补充说明和图片 | 否 |
| `agentscope-ai/docs/reme/<version>/` | 面向用户的中英文产品文档 | 是 |
ReMe 仓库维护 `docs/en/``docs/zh/` 中供 README 直接引用的页面,但不把它们作为网页部署来源。网站内容、发布、版本选择、
导航和重定向都由统一文档仓库负责。
## 内容原则
### Concepts 只讲理念
Concepts 应解释 ReMe 为什么这样设计,而不是逐项描述组件和流水线实现。核心判断包括:
- **Memory as File**:记忆首先是用户拥有、可读写和可迁移的文件。
- **Memory from Experience**:长期记忆来自经验的提炼、修正和合并,而不是无限累积上下文。
- **Human-Agent Shared Memory**:用户和 Agent 共同读写同一份可见记忆。
- **Connected and Traceable**:长期结论可以通过链接回到来源和上下文。
算法、索引、Job、Step 和存储实现只有在帮助解释理念取舍时才进入 Concepts。
### Development 保持轻量
现代开发主要由 AI 直接阅读源码、schema 和测试完成。Development 只需要提供:
- 开发环境和最小验证命令;
- 代码目录入口;
- 兼容性与贡献要求;
- 哪些源码或 schema 是权威依据。
不为每个类、组件或扩展点编写重复的开发手册,也不维护 `generic_agent` 一类泛化教程。
### Reference 只记录稳定契约
Reference 记录 workspace、配置入口、CLI、HTTP、MCP 和文件格式的稳定语义。精确参数交给运行时帮助、Pydantic schema 和源码,避免文档复制一份容易失真的接口定义。
### Guides 只保留已验证路径
接入文档应对应真实、可验证的工作流。目前优先维护 Claude Code、QwenPaw以及 Skill、CLI、MCP、HTTP、Python 的选择说明。没有可验证实现的框架不提前创建占位页。
## 发布文档结构
ReMe 参考 AgentScope 的版本目录和导航方式:
```text
agentscope-ai/docs/
├── reme/
│ └── 0.4.0.6/
│ ├── en/
│ └── zh/
└── images/
└── reme/
```
每个语言版本保持三组导航:
1. **Get Started / 快速开始**Index、Overview、Quick Start、Concepts。
2. **Integrate / 接入**接入选择、Claude Code、QwenPaw。
3. **Reference / 查阅与参与**Reference、Support、Contributing。
ReMe 使用项目级别的 `/reme/latest/``/reme/stable/` 别名,不影响 AgentScope 自己的 `/latest/``/stable/`
## 变更应该写在哪里
| 变更类型 | ReMe 仓库 | 统一文档仓库 |
|---|---|---|
| 产品理念或长期设计判断 | 更新 `docs/doc.md` 或相关设计记录 | 必要时同步 Concepts |
| 用户可见的安装、配置或行为 | 源码、schema、测试影响 README 时同步 `docs/en/``docs/zh/` | 更新对应版本的用户文档 |
| 内部重构或组件调整 | 以代码和测试表达 | 稳定契约未变时无需更新 |
| README 图片 | 更新 `docs/figure/` | 发布页使用时同步到 `images/reme/` |
| 新版本发布 | 更新版本号和代码 | 新建版本目录、双语导航与 ReMe 别名 |
## 质量要求
- 每个用户流程必须能够在当前版本运行和验证。
- 文档不复制能够从代码可靠获得的细节。
- 删除过期内容优先于继续叠加补丁说明。
- 中英文页面保持信息等价,不要求逐句直译。
- 发布前在统一文档仓库运行 Mintlify 严格校验。

View file

@ -1,68 +0,0 @@
# Jupyter Book settings — English docs (built as a standalone book, served at /en/).
# Learn more at https://jupyterbook.org/customize/config.html
project: "ReMe"
title: "<div style='text-align:center'>
<span style='font-weight:700;color:#2196f3;'>AgentScope</span><br>
<span style='font-weight:900;color:#ff5722;'>ReMe</span>
</div>"
author: Alibaba Tongyi Lab
logo: ../figure/reme_logo.png
copyright: "2025, Tongyi Lab, Alibaba Inc."
only_build_toc_files: true
execute:
execute_notebooks: off
parse:
myst_enable_extensions:
- colon_fence
- deflist
- attrs_inline
- dollarmath
sphinx:
extra_extensions:
- sphinx_design
- sphinxcontrib.mermaid
config:
# Render ```mermaid fences as diagrams; generate heading anchors for in-page links.
myst_fence_as_directive:
- mermaid
myst_heading_anchors: 4
# Theme
html_theme: furo
pygments_style: "friendly"
html_show_sphinx: false
html_last_updated_fmt: "%Y-%m-%d"
html_copy_source: false
html_show_sourcelink: false
# Shared assets live in docs/_static (custom.css + the language switcher).
html_static_path:
- "../_static"
html_css_files:
- custom.css
html_js_files:
- switcher.js
use_multitoc_numbering: false
html_theme_options:
sidebar_hide_name: false
source_repository: "https://github.com/agentscope-ai/ReMe"
source_branch: "main"
source_directory: "docs/en/"
footer_icons:
- name: GitHub
url: "https://github.com/agentscope-ai/ReMe"
html: |
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
</svg>
class: ""
light_css_variables:
color-brand-primary: "#2196f3"
color-brand-content: "#2196f3"
color-admonition-background: "#f8f9fa"
dark_css_variables:
color-brand-primary: "#64b5f6"
color-brand-content: "#64b5f6"

View file

@ -1,24 +0,0 @@
format: jb-book
root: index
parts:
- caption: Getting Started
chapters:
- file: quick_start
- caption: Core Concepts
chapters:
- file: memory_as_file
- file: framework
- caption: Memory
chapters:
- file: auto_memory
- file: auto_resource
- file: auto_dream
- file: auto_link
- caption: Retrieval & Proactive
chapters:
- file: memory_search
- file: proactive
- caption: Community
chapters:
- file: contributing

View file

@ -1,106 +0,0 @@
# Overview
<p align="center"><em>Remember Me, Refine Me — a memory management toolkit for AI agents</em></p>
<p align="center">
<img src="../figure/design-philosophy.svg" alt="ReMe Design Philosophy" width="92%">
</p>
ReMe turns conversations and resources into **readable, editable, and searchable
file-based long-term memory**. Long-term memory no longer hides inside a black-box
database — it lives as Markdown files in a workspace directory that both users and
agents can read, write, move, and delete.
```{note}
English documentation is in progress. The pages below mirror the Chinese structure;
some currently link back to the complete <a href="../zh/index.html">中文文档</a>.
```
## ✨ Core Ideas
::::{grid} 1 1 2 2
:gutter: 3
:::{grid-item-card} 📄 Memory as File
Markdown files with frontmatter and wikilinks act as memory nodes that users and
agents can edit directly.
:::
:::{grid-item-card} 🌱 Self-evolving knowledge base
Auto Memory / Resource / Dream progressively distill conversations and resources into
long-term memory, weaving wikilink relationships automatically.
:::
:::{grid-item-card} 🔎 Progressive hybrid search
wikilinks + BM25 + embeddings combine keyword matching, semantic recall, and
relationship expansion.
:::
:::{grid-item-card} 🤝 Agent-friendly integration
`SKILL.md` + CLI integration lets different agents read, write, maintain, and reuse memory.
:::
::::
## 🔄 Memory Pipeline
ReMe's capabilities follow a **capture → consolidate → recall** pipeline:
- **Capture** — [Auto Memory](auto_memory.md) distills conversations into daily cards;
[Auto Resource](auto_resource.md) interprets resource files.
- **Consolidate** — [Auto Dream](auto_dream.md) extracts and integrates daily notes into
long-term `digest/`; [Auto Link](auto_link.md) weaves source and related wikilinks.
- **Recall** — [Memory Search](memory_search.md) does hybrid retrieval with link expansion;
[Proactive](proactive.md) surfaces "what's worth attention today".
The underlying file model and runtime are covered in
[Memory as File](memory_as_file.md) and [Framework](framework.md).
## 📚 Start Reading
::::{grid} 1 2 2 3
:gutter: 3
:::{grid-item-card} 🚀 Quick Start
:link: quick_start
:link-type: doc
Install, launch, and run your first write, index, and retrieval.
:::
:::{grid-item-card} 📄 Memory as File
:link: memory_as_file
:link-type: doc
The file-based memory model: layering, frontmatter, wikilinks, chunking.
:::
:::{grid-item-card} 🏗️ Framework
:link: framework
:link-type: doc
The Application / Service / Job / Step runtime and dependency injection.
:::
:::{grid-item-card} 🧠 Auto Memory
:link: auto_memory
:link-type: doc
How conversations become daily memory cards with preserved provenance.
:::
:::{grid-item-card} 🔎 Memory Search
:link: memory_search
:link-type: doc
Index building, hybrid recall, and progressive link expansion.
:::
:::{grid-item-card} ✨ Proactive
:link: proactive
:link-type: doc
Reading the day's interest topics to drive proactive reminders and insights.
:::
::::

465
docs/en/reme_scene.md Normal file
View file

@ -0,0 +1,465 @@
# ReMe Application Scenarios
This document describes how ReMe is used in real agent workflows. Directory names, Job names, and capability boundaries are
based on the latest code under `reme/`.
The common ReMe pattern is:
```text
Conversations / external resources
|
+--> auto_memory / auto_resource
| write to daily/
|
+--> auto_dream
| distill daily/ into digest/{personal,procedure,wiki}/
| and write daily/<date>/interests.yaml
|
+--> search / node_search / read / traverse / proactive
let agents retrieve, associate, read, and inspect interest topics
```
## Scenario 1: A Supply-Chain Knowledge Base for a Financial Analyst
**Persona**: Analyst Wang, a new-energy industry researcher. Every day, Wang processes research reports, industry news,
company interviews, and spoken post-market notes.
**Pain point**: Information is scattered across text reports, web clippings, group messages, interview notes, and
conversations. A few days later, when asking, "How did the cobalt-price issue come up in the last CATL interview?", it is
difficult to reconnect the original event, company, material route, and upstream mining companies.
### Day 1: Post-market discussion and reports enter Daily
Analyst Wang synchronizes three reports to `resource/2026-05-18/`, then tells the agent:
```text
Glencore released its third-quarter report today, with cobalt output down 18% year over year.
We need to closely track how mining-rights policy changes in the DRC affect CMOC's KFM mine.
Downstream ternary-cathode manufacturers continue to move toward high-nickel, low-cobalt chemistry.
```
ReMe produces two kinds of lightly processed files:
```text
resource/
└── 2026-05-18/
├── glencore-q3.md
├── cobalt-policy.md
└── cathode-trend.md
session/
└── dialog/
└── 2026-05-18-close.jsonl
daily/
├── 2026-05-18.md
└── 2026-05-18/
├── 2026-05-18-close.md
├── glencore-q3.md
├── cobalt-policy.md
├── cathode-trend.md
└── interests.yaml # generated after auto_dream
```
The corresponding flow is:
- `auto_memory` saves the original conversation to `session/dialog/<session_id>.jsonl`, then asks the agent to write
important facts to `daily/<date>/<session_id>.md`.
- `resource_watch_loop` watches text-file changes under `resource/` and triggers `auto_resource_step` to write a
same-named daily note.
- `daily_create` maintains `daily/<date>.md` as the index page for that day.
### Day 1 evening: Auto Dream writes to Digest
Run:
```bash
reme auto_dream date=2026-05-18
```
`auto_dream` is a four-step pipeline:
```text
dream_extract_step
scan daily/2026-05-18.md and changed files under daily/2026-05-18/
output units and topics
dream_integrate_step
recall existing digest nodes with node_search for each unit
decide CREATE / CORROBORATE / REFINE / CORRECT
dream_topics_step
write daily/2026-05-18/interests.yaml
dream_finish_step
checkpoint successfully processed daily inputs
```
Outputs in this scenario:
```text
digest/
└── wiki/
├── glencore.md
├── cobalt.md
└── ternary-cathodes.md
```
Example `digest/wiki/cobalt.md`:
```markdown
---
name: Cobalt
description: A key raw material for lithium-battery cathodes, with production concentrated in the DRC
---
downstream_product:: [[digest/wiki/ternary-cathodes.md]]
producer:: [[digest/wiki/glencore.md]]
source_event:: [[daily/2026-05-18/2026-05-18-close.md]]
# Cobalt
## Supply
Glencore's third-quarter cobalt output fell 18% year over year. Continue monitoring how tighter supply affects prices.
## Policy risk
Changes to mining-rights policy in the DRC may affect KFM mine operations and should be tracked together with CMOC.
```
Note that wikilinks use literal path semantics. Prefer complete workspace-relative paths with the `.md` extension. ReMe
does not automatically resolve `[[cobalt]]` to a particular file.
### Day 2: Interview findings refine existing nodes
Analyst Wang attends a CATL investor interview:
```text
CATL is switching fully to high-nickel 9-series ternary cathodes this year, so cobalt usage will keep falling.
Capacity utilization is 85%, five percentage points higher than last quarter.
```
`auto_memory` writes:
```text
daily/2026-05-19/catl-interview.md
```
During `auto_dream date=2026-05-19`:
- `dream_extract_step` extracts "CATL's switch to high-nickel ternary cathodes" and "CATL capacity utilization."
- `dream_integrate_step` uses `node_search` to recall `digest/wiki/ternary-cathodes.md` and
`digest/wiki/cobalt.md` from `digest/`.
- The agent applies `REFINE` to `ternary-cathodes.md`, adding CATL's 9-series transition as a case.
- The agent applies `CREATE` to, or updates, `digest/wiki/catl.md`.
The graph gradually grows into:
```text
digest/wiki/
├── glencore.md
├── cobalt.md
├── ternary-cathodes.md # REFINE: high-nickel, low-cobalt trend + CATL case
└── catl.md # CREATE: capacity utilization + 9-series transition
```
### Day 5: The user searches for "upstream and downstream battery companies"
Analyst Wang asks:
```text
Help me analyze the upstream and downstream lithium-battery supply chain.
```
The agent calls:
```bash
reme search query="lithium battery upstream downstream ternary cathode cobalt CATL" limit=5
```
`search` returns chunk content, line numbers, scores, and outlink/inlink directories for matched files. With the default
configuration, results come from BM25 plus graph expansion.
The result shape is:
```text
========== digest/wiki/cobalt.md:8-20 [score=0.0148 keyword=3.7112] ==========
# Cobalt
## Supply
Glencore's third-quarter cobalt output fell 18% year over year...
outlinks:
-> digest/wiki/ternary-cathodes.md name="Ternary Cathodes" via predicate=downstream_product
-> digest/wiki/glencore.md name="Glencore" via predicate=producer
inlinks:
<- digest/wiki/ternary-cathodes.md name="Ternary Cathodes" via predicate=upstream_material
========== digest/wiki/ternary-cathodes.md:5-18 [score=0.0139 keyword=3.2017] ==========
...
```
The agent can assemble a supply-chain outline from the neighbor directory alone. When it needs details, it can call:
```bash
reme read path=digest/wiki/catl.md
reme traverse path=digest/wiki/cobalt.md depth=2 direction=both
```
The final response might be:
```text
The lithium-battery chain can be divided into three segments:
1. Upstream raw materials: cobalt supply is concentrated in the DRC. Glencore is a major producer, and the policy impact
on CMOC's KFM mine should be monitored.
2. Midstream materials: ternary cathodes continue to move toward high-nickel, low-cobalt chemistry.
3. Downstream batteries: CATL's move to 9-series high-nickel ternary cathodes confirms the downstream demand direction.
These conclusions come from the post-market conversation on 2026-05-18, the Glencore quarterly-report resource note, and
the CATL interview record on 2026-05-19.
```
### Proactive: Read the day's interest topics
`auto_dream` writes:
```text
daily/2026-05-18/interests.yaml
```
Example:
```yaml
date: 2026-05-18
topic_count: 3
diversity_days: 7
topics:
- title: Impact of DRC mining-rights policy on cobalt supply
reason: The user repeatedly mentioned KFM and cobalt-price risk today
keywords: [cobalt, DRC, CMOC, KFM]
paths:
- daily/2026-05-18/2026-05-18-close.md
```
Call:
```bash
reme proactive date=2026-05-18
```
The `proactive` Job returns the topics from `interests.yaml` and, optionally, the raw YAML content.
### Value of this scenario
- The analyst focuses on reading materials and expressing judgments. ReMe writes facts to daily and distills long-lived
concepts into digest.
- `node_search` lets dream find existing digest nodes before writing, preventing a new file for the same concept every day.
- Graph expansion in `search` lets the agent inspect structure before reading full content, reducing wasted context.
- Every conclusion is stored in Markdown and can be audited with an ordinary editor.
## Scenario 2: Cross-session Procedural Memory for a Coding Agent
**Persona**: Developer Zhang, who works on project issues over time in Claude Code, AgentScope, or other agents.
**Pain point**: The same kind of bug appears repeatedly, but the agent starts its investigation from scratch each time. The
user's coding style, testing habits, and project preferences exist only in the current conversation.
### First session: The build stalls
The user says:
```text
pnpm build stalls at 92%. CPU usage is low, but memory keeps growing.
```
The agent's investigation:
```text
1. Clear caches: no effect.
2. Upgrade the terser plugin: no effect.
3. Discover that fork-ts-checker is running out of memory.
4. Set NODE_OPTIONS=--max-old-space-size=8192: the build succeeds.
```
`auto_memory` writes:
```text
session/dialog/build-oom-2026-03-10.jsonl
daily/2026-03-10/build-oom-2026-03-10.md
```
After `auto_dream`, ReMe generates:
```text
digest/
├── procedure/
│ └── typescript-build-oom.md
└── personal/
└── code-style.md
```
Example `digest/procedure/typescript-build-oom.md`:
```markdown
---
name: TypeScript project build OOM diagnostic path
description: When a build stalls and memory grows, check the type-checking process first
---
source_event:: [[daily/2026-03-10/build-oom-2026-03-10.md]]
related_preference:: [[digest/personal/code-style.md]]
# TypeScript Project Build OOM Diagnostic Path
## Symptoms
The build stalls near the end. CPU usage is low, but memory keeps growing.
## Preferred path
1. Check whether fork-ts-checker or another type-checking subprocess is running out of memory.
2. Try `NODE_OPTIONS=--max-old-space-size=8192` first.
3. Clear caches or upgrade the minification plugin only when there is specific evidence to do so.
## Known ineffective paths
- Deleting `.cache` alone did not resolve the issue on 2026-03-10.
- Upgrading the terser plugin did not resolve the issue on 2026-03-10.
```
Example `digest/personal/code-style.md`:
```markdown
---
name: User coding-style preferences
description: Engineering preferences repeatedly expressed by the user
---
# User Coding-style Preferences
## Comments
The user dislikes comments that restate what the code literally does. Comments should explain WHY or a complex constraint.
## Tests
The user prefers focused tests around the risk and dislikes broad, unrelated refactoring.
```
### Second session: Quickly recalling a similar problem
Six weeks later, the user asks:
```text
vite build also stalls during bundling. Is it the same kind of issue?
```
The agent first calls:
```bash
reme search query="vite build stalls memory growth TypeScript OOM" limit=5
```
Matches:
```text
digest/procedure/typescript-build-oom.md
daily/2026-03-10/build-oom-2026-03-10.md
```
The agent can skip low-value paths in its response:
```text
The previous similar issue was an out-of-memory failure in the TypeScript type-checking process. I suggest checking memory
during the build and the type-checking subprocess first, then trying NODE_OPTIONS=--max-old-space-size=8192. Clearing caches
and upgrading the minification plugin did not help last time.
```
### Value of this scenario
- `digest/procedure/` stores both "how to do it" and "which paths failed," letting the agent reuse diagnostic experience.
- `digest/personal/` stores user preferences so the agent can follow the same engineering style across sessions.
- The original conversation remains under `session/dialog/`; daily records stay traceable, and digest is only the
long-term distilled result.
## Scenario 3: A Personal Second Brain
**Persona**: Engineer Li, who talks with an agent about work, books, family plans, running, and travel.
**Pain point**: Ordinary chat history accumulates chronologically. Three months later, it supports only full-text search and
struggles with associative questions such as "What was the book Alice recommended?" or "Why did I change my training plan?"
### Daily input
One day produces:
```text
daily/2026-04-20/
├── lunch-with-alice.md
├── running-plan.md
└── frontend-design-review.md
```
`auto_dream` extracts:
```text
digest/
├── personal/
│ ├── alice.md
│ └── exercise-preferences.md
├── procedure/
│ └── frontend-review-checklist.md
└── wiki/
└── deep-work.md
```
Example:
```markdown
---
name: Alice
description: A friend of the user who often recommends reading material
---
recommended_book:: [[digest/wiki/deep-work.md]]
source_event:: [[daily/2026-04-20/lunch-with-alice.md]]
# Alice
## Reading recommendations
At lunch on 2026-04-20, Alice recommended a book about attention and deep work.
```
### An associative recall
The user asks:
```text
What was the book about attention that Alice recommended last time?
```
The agent can search first:
```bash
reme search query="Alice recommendation attention book deep work" limit=5
```
Matches:
```text
digest/personal/alice.md
outlinks:
-> digest/wiki/deep-work.md via predicate=recommended_book
daily/2026-04-20/lunch-with-alice.md
```
Then read:
```bash
reme read path=digest/wiki/deep-work.md
```
Final response:
```text
It was "Deep Work." The record shows that Alice recommended it at lunch on 2026-04-20, and you later categorized it under
attention and working methods.
```
### Value of this scenario
- daily preserves "what happened at the time."
- digest/personal records people, preferences, and long-term relationships.
- digest/wiki records books, concepts, and topics.
- Wikilinks connect "person -> book -> topic -> original event," which is closer to human recall than browsing chat history
only by time.

View file

@ -1,330 +0,0 @@
# auto-cognition 设计(顶层:心智循环)
> 本文档:reme 中**长期记忆系统**的顶层认知模型 —— 把 agent 的记忆生命周期类比人类睡眠/觉醒回路,推导出**三阶段分工**与**15 维能力清单**。
>
> **三阶段实现各有专属文档**:
> - Stage 1 写入(REM 重放抽象) → `auto_dream_design.md`
> - Stage 2 巩固(NREM 深度整合) → `auto_consolidate_design.md`
> - Stage 3 检索(觉醒态提取) → `auto_recall_design.md`
>
> 配套阅读:
> - `auto_memory_design.md`:入流端(daily 写入),与 cognition 平行 —— cognition 负责"已落地后的认知循环",memory 负责"经历落地"
> - `structure.md` §4(retrieve 三种问法)
>
> **核心立场**:
> - 长期记忆不是"存 + 取"两个动作,是**写入 → 巩固 → 提取**的循环 —— 三段时间尺度不同(同步 / 周期 / 同步),设计形态不同
> - workspace 是**事实层**,只承载经过 LLM 写入认证的关系;`meta/` 是**派生层**,承载概率推断的统计信号
> - 任一阶段独立演化,任一信号缺失系统降级而不崩
---
## 0. 心智循环:reme 的认知模型
agent 的长期记忆系统在概念上对应人脑的**海马—皮层回路 + 睡眠—觉醒周期**:
```
┌─────────────────────────────────┐
│ 外部经验(daily / resource) │
└─────────────┬───────────────────┘
│ (auto-memory 写 daily)
┌─────────────────────────────────────────────────┐
│ │
│ ┌────────────────┐ 抽象 / 关系编织 │
│ │ Stage 1 │ ◄─ 类比 REM 睡眠 │
│ │ auto-dream │ "重放 + 写进 schema" │
│ └───────┬────────┘ │
│ │ 写 workspace(digest body + wikilink) │
│ ▼ │
│ ┌────────────────┐ │
│ │ workspace(事实) │ │
│ └───────┬────────┘ │
│ │ 只读 │
│ ▼ │
│ ┌────────────────┐ 长期组织 / 派生指标 │
│ │ Stage 2 │ ◄─ 类比 NREM 慢波睡眠 │
│ │ auto-consol- │ "巩固 + 修剪 + 集群" │
│ │ idate │ │
│ └───────┬────────┘ │
│ │ 写 meta/ + audit/(派生层) │
│ ▼ │
│ ┌────────────────┐ │
│ │ meta(派生) │ │
│ └───────┬────────┘ │
│ │ 只读 │
│ ▼ │
│ ┌────────────────┐ query → 答案合成 │
│ │ Stage 3 │ ◄─ 类比觉醒态 cue retrieval│
│ │ auto-recall │ "融合 + pattern complete"│
│ └───────┬────────┘ │
│ │ │
└───────────┼─────────────────────────────────────┘
│ 召回结果给 agent
┌─────────────────────────────────┐
│ agent query │
└─────────────────────────────────┘
```
**心智循环回答四个根本问题**:
| 问题 | 谁回答 |
|---|---|
| 我经历过什么? | auto-memory(daily 入流) |
| 我从中学到什么? | Stage 1 — auto-dream |
| 这些知识如何长期组织? | Stage 2 — auto-consolidate |
| 我需要时如何调用? | Stage 3 — auto-recall |
memory 负责"经历落地",cognition 三阶段负责"已落地经历的认知循环"。
---
## 1. 三阶段全景
| 阶段 | 神经科学类比 | 时间尺度 | 改 workspace | 实现归属 |
|---|---|---|---|---|
| **Stage 1 dream** | REM 重放抽象 | 同步(随入流即跑) | 是(写 digest body) | `auto_dream_design.md` |
| **Stage 2 consolidate** | NREM 深度巩固 | 周期 / idle(daily / weekly)| **否**(写 `meta/` + `audit/`)| `auto_consolidate_design.md` |
| **Stage 3 recall** | 觉醒态 cue retrieval | 同步(query 触发) | 否(只读;唯一对外写是 `meta/access_log.json`)| `auto_recall_design.md` |
**关键的不对称**:
- 写入与检索是**同步**的(用户 / agent 等待),巩固是**离线**的(idle / 周期)
- 改 workspace 的资格被严格限制在 **dream + consolidate 中的 split** —— 其它阶段全只读
- 三阶段时间尺度差三个数量级,这是设计形态(同步 vs 异步 vs idle)的根本来源
---
## 2. 系统级能力(贯穿三阶段)
不属任何单阶段,但任一阶段不能违反:
| 能力 | 含义 |
|---|---|
| **事实层 vs 派生层分离** | workspace 只承载经 LLM 写入认证的关系(显式 wikilink);`meta/` 承载概率推断的派生指标(community / recency / archived);两者绝不混同 |
| **不变量守恒** | F-invariants(0 文件移动 / 改正文限定 subject / wikilink 是 body 一部分)+ E-invariants(边守恒 E-1/E-2/E-3)横跨三阶段;详 `auto_dream_design.md` §4.3-§4.4 |
| **阶段独立演化** | 任一阶段算法升级不破坏其它阶段(community 算法换 → dream 不变;打分公式调 → consolidate 不变) |
| **缺失即降级** | 任一派生信号缺失,系统降级而不崩;冷启动可用 |
| **全程可审计** | 每阶段产 audit / report / log,人 / agent 可检视追溯 |
---
## 3. Stage 1 — auto-dream:经验 → 抽象
**类比**:REM 睡眠的记忆重放与抽象提炼。脑在做梦时把白天事件拆解、重组,提取出可泛化的模式,登记进皮层 schema。
**根本目的**:把"原始经历"转化为"长期值得调取的教训",同时把它编织进已有知识图谱。
### 3.1 五个能力维度
逻辑递进 —— 输入 → 抽象 → 整合 → 编织 → 写入:
| # | 能力 | 它在问什么 | 失效后果 |
|---|---|---|---|
| 1 | **抽象判断**(gate) | 这段材料里有"值得长期记住"的东西吗? | 噪声进 workspace / 只蒸馏不抽象 |
| 2 | **经验重放**(召回) | 这个抽象在已有记忆里**已经存在**吗?以什么形式? | 重复节点 / 错过整合机会 |
| 3 | **整合决策** | 创建新节点,还是丰富已有节点?若已有 —— 是再次印证 / 精化范围 / 修正错误? | 已有信息丢失 / 错误没纠正 |
| 4 | **关系编织** | 这个抽象与谁有关系?谁是它的来源? | wikilink 缺失,后续 retrieve 漏召 |
| 5 | **写入安全** | 写入会不会破坏 workspace 既有事实?并发冲突如何处理? | 边丢失 / race condition |
### 3.2 关键定性
- dream 是 workspace 的**唯一写者**(在 cognition 三阶段里;memory 写 daily 不算)
- **写入瞬间是关系建立的唯一可信时机** —— 错过的关系不靠后台扫回(那不是 consolidate 的工作)
- 一次写入,所有未来检索受益(持久化优于实时计算)
详细机制见 `auto_dream_design.md`
---
## 4. Stage 2 — auto-consolidate:抽象 → 网络
**类比**:NREM 慢波睡眠的系统巩固 + 突触代谢稳态。脑在深睡时把分散事件融入 schema、修剪弱连接、把长期不用的记忆淡出意识可达范围。
**根本目的**:跨时间累积地把 workspace 从"一堆节点"组织成"有结构、有权重、有时效的网络",但**只产派生信号,不污染事实层**。
### 4.1 五个能力维度
按作用尺度从微观到宏观:
| # | 能力 | 作用尺度 | 类比 | 输出形态 |
|---|---|---|---|---|
| 1 | **结构维护** | 节点级 | 海马表征过密 → 分化新单元 | 改 workspace(split,唯一例外)|
| 2 | **跨节点关系发现** | 节点对级 | 多次睡眠中识别"同一件事" → schema | `audit/` 报告 |
| 3 | **主题集群形成** | 子图级 | 皮层网络的功能性分区 | `meta/communities.json` |
| 4 | **时效性管理** | 节点级 / 时间维度 | 突触代谢稳态 + 遗忘 | `meta/access_log.json` + `meta/archived.json` |
| 5 | **健康监控** | 系统级 | 神经环路诊断 | 告警 / 严重告警 |
### 4.2 关键定性
- consolidate 是**纯只读 + 派生写**(读 workspace,写 `meta/` + `audit/`)
- **唯一例外是 split** —— 改 workspace 的维护任务,但触发严格(D3 inline 写后)且只改自身负责的 parent + children
- **关系判断有错率 → 报告优先,人/agent 介入,不主动合并**(夸大置信度的代价是污染事实层)
- 离线 / 周期 / idle —— 与前台不抢资源;失败不影响主流程,下次重跑
详细机制见 `auto_consolidate_design.md`
---
## 5. Stage 3 — auto-recall:网络 → 答案
**类比**:觉醒态的 cue-driven retrieval + pattern completion。脑接到 query,激活相关皮层模式,补全成完整答案;同时召回过程本身强化被用到的记忆痕迹。
**根本目的**:接到当前 query 时,从 workspace + 派生信号合成最相关的过去经验 —— 既要**覆盖率**(不漏)也要**信噪比**(不冗余)。
### 5.1 五个能力维度
按召回流程从输入到输出:
| # | 能力 | 它在解决什么 |
|---|---|---|
| 1 | **多路召回** | 不同问法走不同算子(state / semantic / topological 三分立);agent 自选,不强加聚合 verb |
| 2 | **多信号融合** | 单一文本相似度不够 —— 还要节点权威性 / 主题集群 / 时效性;乘法融合 |
| 3 | **信噪比管理** | 节点级去重 + 节点级 surface(frontmatter 一同呈现)+ multi-hop 可控展开 + 冷藏过滤 |
| 4 | **召回反馈** | 被命中的节点 → 写访问日志 → 影响下次 recency / archived 判定 |
| 5 | **鲁棒降级** | 派生信号缺失 → 退到基础召回;version 不兼容 → warning + 跳过该因子 |
### 5.2 关键定性
- recall 是**只读** —— 唯一对外写入是 `meta/access_log.json`(经 ring buffer + consolidate 聚合)
- recall **不引入新 L4 模块**(`structure.md` ✗-15)—— 三种问法分别由 L3 原子工具(`list_step` / `search_step` / `traverse_step`)直接覆盖
- 默认路径 **0 LLM 调用**(信号都是离线维护好的);LLM rerank / query rewrite 是 SDK 上层选项
详细机制见 `auto_recall_design.md`
---
## 6. 能力地图(横切视角)
15 维按"作用对象"重排,可以看到三阶段如何分工:
| 作用对象 | dream(写入) | consolidate(巩固)| recall(检索)|
|---|---|---|---|
| **节点(单个)** | 1 抽象判断 / 3 整合决策 / 5 写入安全 | 1 结构维护(split) | 3 信噪比(节点级合并/surface) |
| **节点对 / 关系** | 4 关系编织(wikilink) | 2 跨节点关系发现(dups 报告) | (消费已有边,不产新关系) |
| **子图 / 集群** | 2 经验重放(召回邻居) | 3 主题集群形成(community)| 2 多信号融合(community boost) |
| **时间维度** | (写入瞬间) | 4 时效性管理(decay / archived)| 4 召回反馈(access log)|
| **系统健康** | 5 守恒校验 | 5 健康监控(D1 / D10) | 5 鲁棒降级 |
| **入口形态** | 异步 fan-out per sub-unit | 周期 batch / idle | 同步 query response |
**几个观察**:
- "节点对 / 关系"列在 recall 是空 —— recall 不产新关系,只用已有边(避免 query-time 高成本推断)
- "时间维度"行 dream 缺位 —— 写入瞬间无"时间维度"概念(那是 consolidate 后续才能提取的统计)
- 每行至少有一个阶段负责 —— 没有能力被全阶段忽略
---
## 7. 跨阶段不变量
所有阶段共同遵守的硬约束。任何阶段越界 = 设计错误。
### 7.1 F-invariants(继承 `auto_dream_design.md` §4.3)
| # | 约束 | 跨阶段含义 |
|---|---|---|
| F-1 | 0 文件移动 | 没有任何阶段可以 move 文件;rename 走 `wikilink_handler.retarget_links` 显式路径 |
| F-2 | 改正文限定 subject | dream 改 subject body / consolidate split 改 parent + children body;**recall 绝不改任何 body** |
| F-3 | maintainer 只做 split | consolidate 内的结构维护只做 split;无 merge / dissolve / re-edge |
| F-10 | inbound 不动 | split 后外部 wikilink 仍指 parent,不强制重定向 |
| F-11 | wikilink 是 body 一部分 | 没有"独立的边";所有关系变化是 body 编辑副作用 |
### 7.2 E-invariants(边守恒)
- E-1:dream update 出边 ⊇ 原出边
- E-2:split 后 `(parent_new children_outbound) ⊇ parent_old`
- E-3:inbound wikilink split 时不动
**recall 不写 body** → E-* 与之无关;但 recall 看到的 wikilink 图永远是 dream / split 守恒后的状态。
### 7.3 派生信号边界
- **consolidate / recall 不写 workspace** —— 关系判断、活跃度统计、社区划分都是概率推断,不污染事实层
- **`meta/*.json` 不被 retrieve 召回** —— 只作权重信号,不进入"召回结果"集合
- **audit/ 不被自动消费** —— 报告永远等待人 / agent 介入,不闭环回写
---
## 8. 跨阶段数据流(契约总览)
```
┌──────────────┐ wikilink ┌──────────────┐
│ auto-dream │─落 body──►│ workspace/ │
│ (Stage 1) │ │ (事实层) │
└──────────────┘ └──────┬──────┘
│ 只读
┌──────────────────┐
│ auto-consolidate │
│ (Stage 2) │
└─┬────────┬───────┘
│ │
meta/ 元数据───┘ └─── audit/ 报告
(派生层) (人工介入)
│ 只读
┌──────────────┐
│ auto-recall │ ◄─ user query
│ (Stage 3) │
└──────┬───────┘
│ 命中钩子(异步)
meta/access_log.json
(recall 唯一对外写入,经 consolidate 聚合)
```
| 产物 | 路径 | 写入者 | 读取者 | 缺失行为 |
|---|---|---|---|---|
| **workspace wikilink** | `digest/**.md` body | dream / split | recall(图遍历) | — |
| **dups 报告** | `audit/<date>/auto_link_dups.md` | consolidate | 人 / agent | — |
| **communities** | `meta/communities.json` | consolidate | recall | 不做同社区 boost |
| **access log** | `meta/access_log.json` | recall(写命中) + consolidate(聚合) | recall(读 recency)| recency_factor = 1.0 |
| **archived list** | `meta/archived.json` | consolidate | recall(默认过滤)| 不过滤 |
| **centrality** | `file_graph` 反向索引(实时,不存)| 自动 | recall(O(1) 查) | — |
**契约稳定性**:`meta/*.json` 都带 `version` + `computed_at`;recall 启动时校验 version,不兼容则降级。
**冷启动**:`meta/` 为空 → recall 仍能跑(base + centrality + 图)→ 排序略弱不崩。
---
## 9. 系统级断言(把"要什么"提炼到 5 条)
1. **抽象与事实分层** —— workspace 是经 LLM 写过的事实;`meta/` 是统计 / 算法的派生;两者绝不混同
2. **关系建立的时机集中在写入瞬间** —— dream 写入是关系唯一可信来源;consolidate 不补 workspace 关系,recall 不预存关系矩阵
3. **维护是离线的派生劳动,不是补救** —— consolidate 不修 dream 的疏漏(那叫返工),它做的是 dream 不擅长的事(全局视角 / 统计视角 / 时间视角)
4. **检索是融合,不是检索** —— recall 的价值不在"找文本相似",而在"把文本 / 图 / 时效 / 权威多个独立信号合成一个答案"
5. **整个心智循环可降级** —— 任一阶段失效或失准,整个系统降级而不崩;冷启动有意义;dogfooding 可演进
---
## 10. 与 auto-memory 的边界
auto-memory 写入的 daily event 节点也是图的一部分(承载 daily → digest 的 `derived_from::` 边)。但 daily 节点**不参与 cognition 三阶段的全部改造**:
| cognition 阶段 | 是否触及 daily |
|---|---|
| **dream** | 只读(作为入流之一) |
| **consolidate** | 不参与 dups / community / decay(daily 是时间索引,本质不去重 / 不冷藏) |
| **recall** | 三层并行召回时 daily 也参与命中(`structure.md` R-2 默认 `digest > daily > resource`) |
**关键约束**:cognition 三阶段任何子阶段都**不改写 daily**(无写回路径);daily 由 auto-memory 写完即只读。
---
## 11. 演进 / 待补
**当前实现状态**:
- ✅ Stage 1 dream 已实现并跑通(`reme/steps/evolve/dream.py` + `dream.yaml`)
- ⏳ Stage 2 consolidate split 部分将实现;dups / community / decay / archived 待实现
- ⏳ Stage 3 recall 增强未实现(当前 search.py 已有 vector + keyword + RRF + 一跳 expand)
**顶层级演进议题**(不属任何单阶段):
- ⏳ **能力成熟度路标** —— 把 15 个能力维度按 M0(必须)/ M1(期望)/ M2(演进)分级
- ⏳ **跨阶段集成测试** —— workspace 从空到充实的端到端 dogfooding,验证三阶段配合是否符合"心智循环"预期
- ⏳ **可观测性聚合** —— 三阶段各自的 audit / log 现在分散;是否需要统一的 cognition 健康面板
各阶段实现进度详见各自文档的"下一步"章节。

View file

@ -1,741 +0,0 @@
# auto-consolidate 设计(Stage 2 巩固:主动解决 workspace 长期演化的实际问题)
> 本文档:reme 中 **auto-cognition 三阶段****Stage 2 — 巩固阶段** 实现。覆盖 workspace 长期演化中累积的实际问题(冗余 / 过载 / 稀疏 / 腐败 / 抽象缺位),通过周期 batch + 写后 inline 的方式**主动改 workspace**,让记忆系统保持健康。
>
> 配套阅读:
> - `auto_cognition_design.md`:三阶段顶层心智循环
> - `auto_dream_design.md`:Stage 1 写入 / 节点 + 边模型 / F-invariants 原始定义 / 边守恒
> - `auto_recall_design.md`:Stage 3 检索 —— 消费本文档产出的信号
> - `auto_memory_design.md`:auto-memory 写 daily,daily 节点不参与本文档的巩固改造
> - `structure.md` §3.6(maintain 动作语义)
>
> **核心立场**:
> - consolidate **不是产报告等人介入**,是**主动解决问题** —— 类比 NREM 慢波睡眠的 systems consolidation:跨多事件抽 schema、修剪弱连接、稳态突触强度。这些都是真实发生的改造
> - workspace **会被 consolidate 改**,但每个动作有严格的**置信度门槛 + 守恒规则 + 审计 trail + 渐进 rollout**
> - 灰色地带(置信度不够)才产报告等人介入;高置信度自己解决
> - **community detection 是巩固的中枢** —— P0 基础设施,P1-P3 三个动作(abstract / merge / reinforce)都依赖它
---
## 0. 问题陈述与五大动作全景
dream 写入是单点视角,有三类视野局限:**写入瞬间没有跨节点视角 / 跨时间视角 / 全局拓扑视角**。这些局限会让 workspace 长期演化中累积五类实际问题:
| # | 问题 | 类比 | 表现 | 解决 |
|---|---|---|---|---|
| 1 | **冗余** | 同事件留下重复记忆痕迹 | dream 漏判去重 / 术语演化 / 跨桶建成两份 | merge |
| 2 | **过载** | 单一突触表征过密 | 节点 body 累积过长 / 单节点杂糅多主题 | split |
| 3 | **稀疏** | 应有连接未建立 | dream 写入瞬间漏召回的相关节点 / 反复共现但无 wikilink | reinforce |
| 4 | **腐败** | 长期不激活的痕迹 | 旧节点过时 / 半年没人读 / 内容已被矛盾 | archive |
| 5 | **抽象缺位** | 跨多 instance 缺 schema | workspace 只有原子节点,没有"主题层"视角承接全局问 | abstract |
### 0.1 四大动作 + 优先级
| 优先级 | 动作 | 解决问题 | 触发节奏 | 改 workspace | 风险 | 收益 |
|---|---|---|---|---|---|---|
| **P0** | **community detection** | (基础设施) | weekly batch | 否 | 0(只产 meta) | 基础(下游动作的依据)|
| **P1** | **abstract** | 抽象缺位 | weekly batch(基于 P0) | 是(新建 summary) | 低(additive) | **最高**(GraphRAG 核心) |
| **P2** | **merge** | 冗余 | weekly batch(基于 P0) | 是(合并 + retarget) | 高(lossy) | 中(消除可见冗余) |
| **(独立)** | **split** | 过载 | inline 写后(D3) | 是(拆 parent + children) | 低 | 中 |
| **(独立)** | **archive** | 腐败 | daily batch | 软(meta 标记) | 0 | 中 |
| ~~P3 reinforce~~ | **已并入 dream synapse** | 稀疏 wikilink | 由 dream Phase 2 step 4 织突触承担 | (不在 consolidate 范围内) | — | — |
**关键论断**:
- **P1 比 P2 优先** —— abstract additive 失败可逆且回报最大;merge lossy 失败要回滚 inbound,价值是消除冗余(必要但不增能力)。
- **reinforce 已取消**(2026-06-02)—— 详 §4 标作废说明;wikilink 稀疏的解决方案是 dream Phase 2 在写入瞬间多召回 + 织突触(详 `auto_dream_design.md` §4.2.2),不再由 consolidate 周期补救。
### 0.2 实施路径
```
M0: P0 community detection (基础设施)
+ split (已实现)
+ archive (软标记,完全可逆)
M1.1: P1 abstract (additive,最低风险开始改 workspace)
M1.2: P2 merge (lossy,高门槛 + 多数票)
M2+: 多层 abstract (L2 super-community) / delete
reinforce: 不再排期 —— 已由 dream Phase 2 synapse 织突触承担
```
### 0.3 显式排除
- ❌ 重做"抽象判断" —— gate 决策只在 dream(consolidate 不重新判定"该不该记")
- ❌ 重做"语义内容" —— UPDATE 三种 flavor(CORROBORATE / REFINE / CORRECT)只在 dream;consolidate 做结构层,不做语义层
- ❌ 改 daily / resource —— consolidate 只动 digest 节点(I-2 / I-3 仍守)
---
# Part A — community 工作群(本文档核心)
P0-P3 四件套围绕 community detection 协同工作:**community 提供"哪些节点同主题"的判据,abstract / merge / reinforce 各自利用这个判据做不同的解决动作**。
## 1. community detection(P0,基础设施)
**目的**:在 workspace wikilink 图上做 community detection,产出"节点 → community_id"映射。这是 P1-P3 三个动作的**唯一前置**。
### 1.1 算法选择:Leiden
| 选项 | 评估 |
|---|---|
| Louvain | 经典,但有 resolution limit + disconnected community 风险 |
| **Leiden** ✅ | Louvain 改进版(2019),稳定性显著好;GraphRAG 采用;Python `igraph.community_leiden` 现成 |
| label propagation | 实现最简,但结果不稳定(随机种子敏感) |
**首版决策:Leiden**,直接对齐 GraphRAG 路线,后续接它的多层抽象更顺。
### 1.2 图的形态
| 维度 | 决策 |
|---|---|
| **节点范围** | **只 digest 节点**;daily / resource 不参与 |
| **边权重** | **首版 unweighted undirected**(所有 wikilink 等权)—— 加权方案(predicate 类型加权)留 M2+ 视效果 |
| **跨桶 community** | **必须允许** —— bucket 是物理归档,community 是语义聚合,二者本就正交。"错桶节点"会被自然纳入 community,可作 audit 信号但不强制 move(F-1 守住)|
| **resolution** | **1.0 起步**(Leiden 默认 / GraphRAG 默认)—— dogfooding 后视 community 平均规模(理想 5-15 节点)调 |
| **更新模式** | **全量重算**;workspace 千节点级 Leiden < 1 ,M0/M1 不引入增量复杂度 |
### 1.3 多层级:M1 只 L1
| 层数 | 适用 | reme 决策 |
|---|---|---|
| 单层 L1(原子 → community)| workspace < 500 节点足够 | **M1 起步** |
| 双层 L1 + L2(community → super-community) | workspace > 500 节点 / 跨主题大类涌现 | M2+ 视规模 |
| GraphRAG 4 层 | 大规模文档库 | M3+ 不优先 |
理由:GraphRAG 论文证明 L1 拿走 60-80% 效果。先把 L1 跑稳,L2 看实际是否需要。
### 1.4 输出
**`meta/communities.json`**:
```json
{
"version": 1,
"computed_at": "2026-06-08T03:00:00Z",
"algorithm": "leiden",
"resolution": 1.0,
"communities": {
"digest/auth/jwt-rotation.md": "c_07",
"digest/auth/oauth-flow.md": "c_07",
"digest/api/rate-limit.md": "c_12"
},
"stats": {
"n_communities": 14,
"median_size": 7,
"max_size": 23
}
}
```
**`meta/community_changes.json`**(供 abstract 稳定度判据):
```json
{
"computed_at": "...",
"previous": "...",
"stability_per_community": {
"c_07": 0.92, // 1 - (Jaccard 距离与上周该 community 节点集)
"c_12": 0.45 // 不稳定,abstract 跳过
}
}
```
### 1.5 community_id 不需要稳定
下游(abstract / merge / reinforce)只关心"两节点是否同 community";id 本身可重排。每周重算后 id 不需要保持与上周对齐。stability 信号通过节点集 Jaccard 距离计算,不依赖 id。
### 1.6 用途总览
| 下游 | 用法 |
|---|---|
| **abstract**(§2)| 判据"该 community 节点数 ≥ N + 稳定度满足 + 无 hub" → 创建 summary |
| **merge**(§3)| 候选 pair 必须在同 community(降错率;不同 community 的相似 description 多是同名异义)|
| **reinforce**(§4)| 候选 wikilink 必须在同 community(避免假关联)|
| **recall**(`auto_recall_design.md` §3) | 同 community 节点 boost |
---
## 2. abstract(P1,抽象提升)
**类比**:NREM systems consolidation —— 跨多次睡眠把分散事件抽出共同 schema,从 episodic 升到 semantic。
**目的**:workspace 演化到一定规模后,某些 community 形成稳定主题群,需要一个 hub 节点统领,让 retrieve 能召回到"主题概览"而非散点。
### 2.1 等价处理立场(关键)
**summary 节点完全等同普通节点**:
| 维度 | 决策 |
|---|---|
| **路径** | LLM 选桶,正常 slug 命名(如 `digest/auth/authentication-mechanisms.md`);**无 `__community__` / `__hub__` 等结构性标识** |
| **frontmatter** | 仅 `name + description`(reme 核心保留);**无 `kind: community_summary`、无 `auto_generated`** |
| **summary 性质** | 完全体现在 **body 形态** —— 主题概述 + 列出 source 节点 wikilink + 跨节点 pattern;但这是内容自然形态,不是结构性宣告 |
| **后续维护** | **无** —— 跟其它节点等价,被 dream / split / merge / archive 自然演化(参见 §2.6) |
这跟 dream 的核心立场对齐:"节点角色由 body 内容决定,不由 frontmatter 类型标记"。abstract 是"用一种新方式创造节点",不是"创造一种新节点类型"。
### 2.2 触发判据(组合门槛)
```
weekly batch:
for community in communities.json:
if community_has_hub(community): # §2.5 结构化判据
continue
if len(community) < MIN_NODES (5): # 节点数门槛
continue
if stability(community) < 0.7: # 稳定度门槛
continue
if active_node_count(community, 30d) < 3: # 活跃度门槛
continue
if name_diversity(community) < 0.5: # 多样性门槛
continue
→ enqueue abstract job
```
| 门槛 | 默认 | 含义 | 防的是 |
|---|---|---|---|
| **节点数** | ≥ 5 | community 大小 | 给 2-3 节点造 hub 不划算 |
| **稳定度** | ≥ 0.7 | 与上周边界 Jaccard 距离 | 给短命 community 造 hub 浪费 |
| **活跃度** | ≥ 3 节点近 30 天 hit | community 仍在用 | 给死社区造 hub(下次没人看)|
| **多样性** | name 差异度 ≥ 0.5 | frontmatter `name` 互不相同 | 给"一组重复节点"造 summary —— 那是 merge 的事 |
### 2.3 创建动作 + grounding 守恒
```
LLM 看 community 内所有节点 (frontmatter + body)
产 planned summary body (三段):
1. 主题概述 (1-2 段,跨多节点共同主题)
2. 关键支柱 (列表,3-5 节点 + 一句话 + wikilink)
3. 不在概览的细节 (明说哪些细节留原节点)
长度限制: summary body < 1500 token
(防 abstract 创建后立刻被 split 触发,§5)
LLM 决定 path: digest/<bucket>/<slug>.md
CAS 写入 (§9) + 双重守恒校验:
- 机械: 出边集合 ⊇ "关键支柱"声称引用的节点 (防套话)
- 机械: 出边集合 ⊇ source_nodes 的至少 60% (allow LLM 漏列少数)
audit 记录: audit/<date>/consolidate_actions.md
```
**grounding 守恒**:summary body 中**声称引用某节点必须真写 wikilink**。LLM 不能仅口头提及"我们在 X 中看到..."而不带 `[[X.md]]`。这是机械可校验的,LLM 跑不掉。
### 2.4 长度限制为什么重要
summary body < 1500 token ** split 互锁的机制**:
- 不限长 → LLM 会写"完整覆盖" → 最终 body 累积接近 split 阈值(2000 token)→ 下次 D3 触发拆 → 拆出来的 children 又被 community 视为同主题 → 下次 abstract 又造一个 hub → 循环
- 限长 1500 → summary 留出 split 阈值的 25% buffer,稳定不触发拆
### 2.5 "community 已有 hub"的结构化判据
不靠 frontmatter / 路径标识,靠**结构**:
```
def community_has_hub(community):
for node in community:
out_targets = outbound(node) ∩ community
if len(out_targets) / len(community) >= 0.6:
return True # 该节点出边覆盖 community 60% 以上 → 它已是 hub
return False
```
**好处**:
- split parent overview 自然被识别为 hub(split parent 出边覆盖大部分 children)→ abstract **复用** split 的工作,不重复创建
- 已有 abstract 创建过的节点,只要它出边没退化,下次 batch 自然识别为 hub,不重复创建
- 节点被 dream update 后形态变化,出边变了 → 自动重新评估
**M1 实施关键验证点**:跑实测验证这个涌现 —— split parent 是否真被识别为 hub。如有 corner case,调阈值 0.6 → 0.5 / 0.7。
### 2.6 后续维护:无 —— 完全靠 5 大动作演化
abstract 创建即放归 workspace,**consolidate 不再"管"它**。后续命运:
| 演化路径 | 结果 |
|---|---|
| 新材料触及该主题 | dream update 自然修正 body(走 CORROBORATE / REFINE / CORRECT)|
| 老 summary 长期不被引用 | archive 自动归档(§6)|
| community 边界变了 → 下次 batch 创建新 summary | 新老 summary 描述同主题 → merge 自动合并(§3)|
| summary body 累积过长 | split 自动拆(§5)|
这是真正的"workspace 自我代谢"。**没有特殊维护通道**。
---
## 3. merge(P2,同概念合并)
**类比**:NREM 跨多次睡眠识别"同一件事" → 合一个记忆痕迹。
**目的**:消除 workspace 内的冗余 —— 同概念多节点。
### 3.1 候选挖掘(community 内三层过滤)
```
weekly batch (依赖 community detection):
for community in communities:
pairs = all_pairs(community)
for (A, B) in pairs:
if description_sim(A, B) < 0.6: # 第一层: frontmatter 相似
continue
if body_topic_overlap(A, B) < 0.5: # 第二层: body 主题词重合
continue
if cooldown_active(A) or cooldown_active(B): # 第三层: cooldown 检查
continue
candidates.append((A, B))
```
**关键约束**:候选必须在**同 community**(降错率)。
### 3.2 多数票决策
merge 是高风险动作(lossy + 改 inbound),用多数票降错:
```
for (A, B) in candidates:
votes = parallel_run(N=3, prompt="A 和 B 是否同一概念? 返回 {is_same, confidence}")
agree = sum(v.is_same and v.confidence >= 0.8 for v in votes)
if agree >= 2:
→ enqueue merge job
elif agree == 1:
→ 写 audit/<date>/dups_uncertain.md (灰色地带,人介入)
else:
→ 丢弃
```
### 3.3 merge 动作:body 重写归 consolidate(方案 B)
**关键决策**:merge 后的 body 由 **consolidate 自跑合并 prompt**,不走 dream update 路径。
| 方案 | 评估 | 决策 |
|---|---|---|
| A. 走 dream update 路径(把 loser body 作"新材料")| 优雅但跨阶段;dream 不应知道 caller 是 consolidate 还是新材料 | ❌ |
| **B. consolidate 自跑合并 prompt** | 简单自包含;通过严格 prompt 约束化解"做语义工作"张力 | ✅ |
| C. 不重写 body(留 redirect stub) | 完全不做语义,但 workspace 留无用节点 | ❌ |
**B 方案的边界守住**(避免 consolidate 真在做语义判断):
| 边界 | 含义 |
|---|---|
| **prompt 严格约束** | "只合并不精化" —— 不重写措辞、不加新内容、不做精化决策 |
| **机械守恒** | 出边 ⊇ A.outbound B.outbound + provenance 全保留(LLM 跑不掉) |
| **信息守恒抽样** | LLM 自检 "merged.body ⊇ A.body B.body 全部信息";audit 抽样人审 |
| **失败拒写** | 守恒校验失败 → LLM 重试一次 → 二次失败拒写 + audit |
### 3.4 完整动作流
```
A, B → 选择 winner (path):
- inbound 数大者赢 (保护既有 inbound,降 retarget 量)
- 平局取路径短者
LLM 跑 merge prompt → planned merged_body (B 方案)
机械 retarget 准备:
- 扫所有 inbound(loser): [[loser.md]] → [[winner.md]]
- alias 保留;predicate 保留
- 这是机械算子,非 LLM
事务式 CAS 写入:
1. winner body 改写
2. 所有 inbound 节点 body 改写 (retarget)
3. 删除 loser 文件
任一步失败 → 全部回滚
audit 记录 + cooldown 设置 (winner 进 cooldown 2 weeks)
```
### 3.5 灰色地带:报告
- 多数票通过(agree ≥ 2)→ 自动 merge
- 仅 1 票通过 → 写报告 `audit/<date>/dups_uncertain.md`,人 / agent 介入
- 0 票 → 丢弃
报告格式:
```markdown
# dups uncertain 2026-06-08
## pair 1 (1/3 votes)
- A: digest/auth/jwt-rotation.md ("JWT 密钥轮换")
- B: digest/security/key-rotation.md ("密钥轮换原则")
- vote 1 (yes, 0.85): "同一概念,A 偏 JWT 场景"
- vote 2 (no, 0.72): "B 是通用原则,A 是具体应用"
- vote 3 (no, 0.68): "粒度不同,不应合并"
建议:走 dream update 通道把 A 内容作为 B 的实例并入。
```
---
## 4. ~~reinforce~~(**已作废,2026-06-02**)
> ⚠️ **本节作废,reinforce 已并入 dream Phase 2 synapse 织突触**(详 `auto_dream_design.md` §4.2.2)。理由:
> - reinforce 的本质 = "找语义相关但 wikilink 缺失的节点对,补 wikilink"
> - 但 dream Phase 2 在写入新节点瞬间已经在做同样的事(多召回 + 内化判 related + 织 `[[Y.md]]`)
> - 让 consolidate 周期事后补 wikilink = dream RECALL 不充分的兜底,与其兜底不如把 dream 召回做强
> - F-2 自然守住:dream 只动新节点 body(自己的 subject),不需要 consolidate 改 leaf body 这种 F-2 破例
>
> **新立场**:wikilink 的稀疏由 dream Phase 2 在写入瞬间一次性解决,workspace 不维护"事后周期补 wikilink"的通道(`auto_cognition_design.md` §9.2 立场:关系建立在写入瞬间)。详 `hierarchical_summary.md` §13.2 Q4。
>
> 以下保留原 reinforce 设计内容作为历史快照,**不实施**。
**(以下内容已作废,仅作历史快照)**
**类比**:NREM 突触强化 LTP —— 反复共激活的连接被强化。
**目的**:workspace 演化中,某些节点对应该有 wikilink 但 dream 写入时漏召。reinforce 周期检测并 additive 补。
### 4.1 候选挖掘(三层过滤)
```
weekly batch (依赖 community detection):
for community in communities:
for (A, B) in all_pairs(community):
if has_wikilink(A, B):
continue
# 第一层: 字符串 mention 锚点
if not has_mention(A.body, B.frontmatter.name):
continue
# 第二层: embedding 相似度验证
if embedding_sim(A.context_around_mention, B.body) < 0.7:
continue
# 第三层: 同 community (已经是,但显式说明)
candidates.append((A, mention_pos, B))
```
**三层过滤的角色**:
| 层 | 防的是 |
|---|---|
| 字符串 mention | 大幅降候选数(从 O(N²) 降到 O(实际共现)) |
| embedding 相似度 | 防同名异义("Apple" 公司 vs 水果)|
| 同 community | 防表面术语共现但语义无关 |
### 4.2 决策(单票即可,门槛较高)
reinforce 是 additive 低风险动作,不需要多数票:
```
for (A, mention_pos, B) in candidates:
vote = LLM("A.body 在该位置提到 B 的概念。是否合理加 [[B.md]] 链接?")
if vote.confidence >= 0.85:
additive_wikilink(A, mention_pos, target=B.path)
→ CAS 写入 (E-1 自动满足:additive 只增不删)
→ audit 记录
else:
丢弃
```
### 4.3 边界
| 维度 | 决策 |
|---|---|
| **只 additive 加 wikilink** | 不改 body 文字,不升级 typed predicate(predicate 升级是语义判断,留 dream)|
| **alias 保留原文** | `[[B.md\|<原文 mention>]]`;原文一字不改 |
| **写入位置** | mention 第一次出现处加;后续保持原文(防 wikilink 满文) |
| **不动 anchor** | 与 dream 一致 |
| **守恒** | E-1 天然满足(纯增) |
| **rollback** | 误链发生时,人 / agent 直接编辑 body 删除 wikilink 即可;reinforce 不维护"我加过哪些"audit log(每次动作进 `audit/<date>/consolidate_actions.md`)|
### 4.4 reinforce 与 dream 的边界
dream 写入时 LLM 应已尽力召回相关节点 + 加 wikilink。reinforce 是**周期性兜底** —— 写入瞬间漏的、术语后才一致的、被 split 拆出来后才相关的,在 reinforce batch 里被检出。
这不违反"consolidate 不修 dream 漏的"立场 —— **dream 漏的 wikilink 在巩固阶段补,是合法工作**(它的依据是 dream 单点视角永远做不到的"周期统计 + 全局视角");**dream 漏的语义抽象在巩固阶段不补**(那是 dream 的语义判断,consolidate 不重做)。
---
# Part B — 独立工作
P0-P3 围绕 community,这两个动作独立运行。
## 5. split(过载分化:inline 写后)
**类比**:海马表征过密 → 分化新单元。
**目的**:节点 body 累积过长 / 主题离散后,拆成 parent overview + N children,保持单节点"一个原子语义单元"的粒度。
### 5.1 触发模型(写后立即,inline)
split 是 5 大动作中**唯一 inline** 的 —— 跟 dream 写入流强耦合,不走 weekly batch:
```
dream / split 写 body 成功 (CAS 通过)
└─ if len(body) > T_token (default 2000):
└─ LLM 判离散度
└─ if is_overloaded:
└─ enqueue split job (FIFO, CAS-protected)
└─ return (不阻塞 dream)
```
理由:节点过载是**写入瞬间的本地信号**(token + 离散度),延后无价值;反应即时。
### 5.2 split 动作
```
LLM 看 parent body:
- 拆成 1 个 parent overview body + N 个 children body
- 每个 child 自带 [[parent]] 反向链接
- inbound 不动 (F-10)
机械 outbound 守恒校验 (E-2):
(parent_new children_outbound) ⊇ parent_old
失败 → LLM 重试 → 二次失败拒写 + audit
事务式 CAS 写入: parent body 改写 + N 个新 children 文件创建
audit + cooldown 设置 (parent + children 进 cooldown,与 merge 互锁)
```
### 5.3 split 与 abstract 的协同(关键)
| | 起源 | 方向 | 触发 |
|---|---|---|---|
| split overview | 单节点过载分化 | 自上而下(一拆多)| inline 写后 D3 |
| abstract summary | 多节点抽象凝聚 | 自下而上(多归一)| weekly batch + 稳定度阈值 |
**协同**:split 产出的 overview 节点会被 §2.5 的"已有 hub"判据识别,abstract 不重复创建。两者互补,不冲突。
---
## 6. archive(时效衰减:让长期不激活的节点淡出)
**类比**:突触代谢稳态 —— 长期不用的连接被减弱,但不删除。
**目的**:让 retrieve 默认排除"已不活跃"的节点,提升信噪比;不删 workspace 文件,保持可逆。
### 6.1 recency_score:连续衰减信号
```
recency_score(node) =
exp(-(now - last_update) / τ_update) # 时间衰减
× (1 + log(1 + last_hit_count_30d)) # 活跃度增强
× (1 + log(1 + inbound_count) / SCALE) # 中心性 cushion(避免 hub 被冷藏)
```
| 参数 | 默认 | 含义 |
|---|---|---|
| τ_update | 60 days | 时间衰减常数 |
| SCALE | 10 | 中心性 cushion 缩放 |
输出:`meta/recency.json`,每节点 0.0~1.0 连续值。
### 6.2 archived 派生快照
archived 是 recency_score 的二元化派生:
```
archived = {node | recency_score(node) < 0.15}
```
输出:`meta/archived.json`,recall 默认过滤这个列表。
### 6.3 解冻
任何动作触及节点 → 自动从 archived 移除:
- retrieve 命中(写 access_log)
- dream update 触及
- merge / reinforce 触及
下次 batch 时 recency_score 重算自然超过阈值。
### 6.4 daily 节奏
archive 是唯一不需要 community detection 的动作 → 节奏可以更快(daily batch),让冷启动后第二天就能影响 recall。
```
daily batch:
1. 读 access_log (retrieve / dream / consolidate 钩子记录的命中事件)
2. 重算 recency_score for all digest nodes
3. 输出 meta/recency.json
4. 阈值过滤 → meta/archived.json
```
---
# Part C — 共享基础设施
## 7. F-invariants 松绑与守恒规则
旧 F-invariants(`auto_dream_design.md` §4.3)在"workspace 只读"立场下定义,新立场要松绑。但松绑不是"自由改",是用**动作级守恒规则**换"一刀切禁令"。
### 7.1 F-invariants 修订
| # | 旧约束 | 新立场 |
|---|---|---|
| **F-1** | 0 文件移动 | **改为**:"非 consolidate 动作不移动文件";merge 删除 loser 文件是**合法移动**(逻辑上等价 retarget) |
| **F-2** | 改正文限定 subject | **改为**:"dream / split / reinforce 改 subject body;merge 在受控算子内可改 inbound 节点 body";其它阶段(recall)绝不改 |
| **F-3** | maintainer 只做 split | **作废** —— consolidate 5 大动作合法 |
| **F-10** | inbound 不动 | **改为**:"split 时 inbound 不动";merge 必须 retarget inbound(机械算子) |
| **F-11** | wikilink 是 body 一部分 | **保留** —— 没有"独立的边"基础设施 |
### 7.2 动作级守恒规则矩阵
| 动作 | 置信度门槛 | 守恒规则 |
|---|---|---|
| **abstract** | community 节点 ≥ 5 + 稳定度 ≥ 0.7 + 活跃度 ≥ 3 + 多样性 ≥ 0.5 + 无 hub | 出边 ⊇ "关键支柱"列表 + 出边 ⊇ source 节点 60%(机械)|
| **merge** | LLM 多数票 ≥ 2/3 + similarity ≥ 0.6 + body overlap ≥ 0.5 | 信息守恒(merged.body ⊇ A B)+ 出边 ⊇ A.out B.out + inbound 全 retarget(机械)|
| **reinforce** | LLM 单票 ≥ 0.85 + 同 community + mention 锚点存在 + embedding ≥ 0.7 | E-1 天然(additive)|
| **archive** | recency_score < 0.15 | 软标记,无破坏性 |
| **split** | token > T + LLM 判离散 | E-2(parent children ⊇ parent_old)+ inbound 不动 |
---
## 8. cooldown 与防循环
5 大动作之间的潜在循环:
```
A merge B → AB body 长 → split AB 回 A' + B' → 又 merge → ...
```
防御:
| 互锁对 | 窗口 | 实现 |
|---|---|---|
| **split → merge** | 2 weeks | 刚 split 出的兄弟节点不参与 merge 候选 |
| **merge → split** | 2 weeks | 刚 merge 的节点不参与 split 评估(D3 检测时跳过)|
| **merge → merge**(同对反复) | 12 weeks | 同一 path 12 周内被 merge 又被识别为新 merge 候选 → audit 警报,人介入 |
| **abstract → merge**(同主题反复 abstract) | 4 weeks | 刚 abstract 出的 hub 节点 4 周内不参与 merge 候选 |
cooldown 状态外置 `meta/cooldowns.json`,不污染 workspace。
---
## 9. CAS 写入协议(共享基础设施)
CAS 是 dream(`auto_dream_design.md` §4.2)、split / merge / reinforce / abstract(本文档)**多方共用**的 workspace 写入协议。归本文档因 consolidate 是写入主战场。
archive 不写 workspace → 不走 CAS;它写 `meta/`,各任务的 atomic write(write-temp + rename)即可。
### 9.1 协议
```
1. 读 + 记戳: read body → version_stamp = sha256(body) | mtime
2. 决策: LLM / 算法 → 产 planned new_body
3. CAS 写入: 重读 body 比 version_stamp
- 未变: 跑动作级守恒校验 → 通过 → atomic write (write-temp + rename) → done
- 已变: 丢弃 planned new_body, 带最新 body 重走 step 1
4. 守恒校验失败: LLM 重试一次, 二次失败拒写 + audit
5. 重做次数上限: 3 次 → 跳过候选 + audit log
```
### 9.2 事务式 merge / split 写入
merge 涉及多文件写入(winner body + N 个 inbound retarget + loser 删除);split 涉及多文件创建(parent body + N children)。需要事务语义:
- 准备阶段:全部 planned new_body 写到 temp 区(带 version_stamp)
- 提交阶段:逐个 CAS 检查 + atomic write(write-temp + rename)
- 任一 CAS 失败 → 全部回滚(temp 区清理,已 rename 的恢复)
实现细节:可借 fs-level 事务库(如 `pyrsistent` 模式)或自实现 journal。M0 起步用最简的"先全部检查 → 再全部写入"两阶段,接受窗口期(检查到写入间)的极小并发风险。
### 9.3 create 路径 race
merge / abstract 都可能并发 create 同一 path → atomic create(`O_CREAT | O_EXCL`)只让一个赢;输者 EEXIST → 重走 step 1(此时大概率改判 update 或丢弃)。
### 9.4 不解决
- 跨进程并发(多 reme 实例同 workspace)→ 不在 M0,需 fs lock(M1+)
- 高冲突 workload(同候选反复触发)→ 重做上限触发后 audit
---
## 10. D 健康检查(D1 / D10)
不属"巩固"主语义,但跟 consolidate 同节奏(周期 batch 顺手跑),归本文档:
| # | 信号 | 节奏 | 修复策略 |
|---|---|---|---|
| **D1** | 断链(wikilink → 不存在 path) | 写时 inline + weekly batch 巡检(双重保险)| 就地删 wikilink 或保留 alias 文本 → audit |
| **D10** | provenance 断裂(digest 反指的 daily/resource 不可达)| 同上 | I-不变量违反 → 严重告警 + 人介入 |
D1 / D10 不算 5 大动作之一(它们不解决"workspace 演化问题",只检测异常)。但它们的修复(就地删 wikilink)需要走 CAS,所以协议共享。
---
# Part D — 契约与实施
## 11. 维护 → 检索契约
5 大动作产物给 retrieve 消费(详细 retrieve 逻辑见 `auto_recall_design.md`):
| 产物 | 路径 | 写入者 | 读取者 | 缺失行为 |
|---|---|---|---|---|
| **workspace 节点变化** | `digest/**.md` | merge / split / reinforce / abstract | recall(图遍历 / 命中) | — |
| **communities** | `meta/communities.json` | community detection | recall + abstract / merge / reinforce | 不做同社区 boost / 三个动作跳过 |
| **community changes** | `meta/community_changes.json` | community detection | abstract 决策 | abstract 跳过(无稳定度判据)|
| **recency** | `meta/recency.json` | archive daily batch | recall | recency_factor = 1.0 |
| **archived** | `meta/archived.json` | archive daily batch | recall(默认过滤)| 不过滤 |
| **cooldowns** | `meta/cooldowns.json` | split / merge | consolidate 内部 | 无防御循环 |
| **access_log** | `meta/access_log.json` | recall(写命中) + archive(聚合) | archive(读 recency) | recency 不衰减 |
| **dups uncertain** | `audit/<date>/dups_uncertain.md` | merge | 人 / agent | — |
| **consolidate actions** | `audit/<date>/consolidate_actions.md` | 全部 5 动作 | 审计 | — |
| **D1 / D10 健康** | `audit/<date>/health_*.md` | inline check + weekly | 人 / agent | — |
**契约稳定性**:`meta/*.json` 都带 `version` + `computed_at`;recall 启动时校验 version,不兼容则降级。
---
## 12. 与 dream 模型的引用关系
本文档松绑了部分 F-invariants(§7),但仍在 dream 定义的底层模型上工作:
| 引用 | 来源 |
|---|---|
| wikilink 基础语法 | `auto_dream_design.md` §3 |
| 节点 / 边模型 | `auto_dream_design.md` §4 / §2 / §3 |
| F-invariants 原始定义 | `auto_dream_design.md` §4.3(本文档 §7 修订)|
| 边守恒 E-1 / E-2 / E-3 | `auto_dream_design.md` §4.4 |
| 路径即 ID / rename | `auto_dream_design.md` §2 |
| anchor 不引入 | `auto_dream_design.md` §3 |
| provenance 载体形态 | `auto_dream_design.md` §4.2 |
| dream 写入路径 | `auto_dream_design.md` §4.2 |
---
## 13. 下一步(M0 → M1.1 → M1.2 → M1.3 → M2)
实现进入 `reme/steps/consolidate/` 时,本文档与 `auto_dream_design.md` / `auto_cognition_design.md`(顶层)/ `auto_recall_design.md` 共同作为契约依据。
### M0:基础设施 + 完全可逆动作
- ✅ split inline 触发 + LLM 离散度判 + E-2 守恒(基础部分)
- ⏳ **community detection weekly batch**(Leiden via `igraph`)+ `meta/communities.json` + `meta/community_changes.json`
- ⏳ **archive daily batch** + recency_score + access_log 收集
- ⏳ CAS 写入框架 + version_stamp + EEXIST race + 重做上限 + audit
- ⏳ D1 / D10 写时 inline 检测 + weekly 巡检
### M1.1:abstract(P1,additive 最低风险)
- ⏳ abstract 候选挖掘(community 大小 + 稳定度 + 活跃度 + 多样性 + 无 hub 五重判据)
- ⏳ abstract LLM prompt(三段输出 + 长度限制 1500 token)
- ⏳ grounding 守恒校验(出边 ⊇ 关键支柱 + 出边 ⊇ source 60%)
- ⏳ "已有 hub" 结构化判据(outbound 覆盖度 ≥ 60%)
- ⏳ **关键验证点**:实测 split parent 是否被识别为 hub
### M1.2:merge(P2,lossy 高门槛)
- ⏳ 候选挖掘(community 内 description 相似 + body 重合 + cooldown 检查)
- ⏳ 多数票框架(N=3 LLM,2/3 通过)
- ⏳ merge prompt(B 方案:"只合并不精化")
- ⏳ inbound retarget 机械算子(扫所有 `[[loser.md]]``[[winner.md]]`,alias / predicate 保留)
- ⏳ 事务式多文件 CAS 写入
- ⏳ 灰色地带报告(`audit/<date>/dups_uncertain.md`)
- ⏳ cooldown 框架(`meta/cooldowns.json` + 各动作互锁)
### M1.3:reinforce(P3,价值最低,可缓做)
- ⏳ 候选挖掘(三层过滤:mention + embedding + 同 community)
- ⏳ 单票决策(门槛 0.85)
- ⏳ additive wikilink 写入(alias 保留原文)
### M2+:演进
- ⏳ 多层级 community(L2 super-community)+ L2 abstract
- ⏳ delete(永久删除 workspace 文件)—— 视 dogfooding 效果决定是否开启
- ⏳ predicate upgrade(typed link reinforce —— 当前 reinforce 只 additive 加无谓词)
- ⏳ PageRank 替代 simple inbound count(若 retrieve 质量瓶颈在中心性)
- ⏳ 跨进程并发(fs lock 支持多 reme 实例同 workspace)
- ⏳ Leiden 边权重(按 predicate 类型加权)

View file

@ -1,352 +0,0 @@
# auto-dream 设计(桶 / 节点 / 边 / 演化)
> 本文档:digest 沉淀层的**桶**(物理布局)/ **节点**(原子单元)/ **边**(wikilink)/ **演化**(dream create_or_update;split 归 maintain)。
>
> 配套阅读:
> - `structure.md` §1.2(数据视角)/ §2(三层存储)/ §3.5(digest 动作)
> - `auto_memory_design.md`:daily 实时事件 = dream 的入流之一
> - `auto_consolidate_design.md`:M split / D 检测 / CAS 写入协议(dream 模型的运行时实现)
> - `auto_cognition_design.md`:auto-cognition 三阶段顶层思想 —— dream 是其 Stage 1(写入阶段)的实现
>
> **核心**:digest = **浅桶(shallow bucket)+ flat .md** + **一张图(节点 + 边)**;dream 定义模型与主流程(create_or_update),maintain 负责 split / 写入运行时。
>
> **关键收敛**:digest 不分"逻辑层"。所有 .md 文件都是同一种节点,内容决定它扮演什么角色(主题概览 / 概念定义 / 方法描述 / 实体记录 ...)。"主题"从图中涌现,不是结构性宣告。
---
## 0. 问题陈述
digest 是 agent 长期记忆的"组织化沉淀"层,与三层架构的另两层职责互补:
| 层 | 组织主轴 | 形态 |
|---|---|---|
| resource/ | 时间(`<date>/<name>`) | 外部原始资料,不可变 |
| daily/ | 时间 + 任务(`<date>/<event-slug>/`) | agent 任务过程,半可变 |
| **digest/** | **语义** | **跨任务知识,可重组** |
dream 设计回答四个问题:**桶**怎么布局 / **节点**长什么样 / **边**怎么连 / **演化**谁负责怎么做。
---
## 1. 桶(物理布局)
| 维度 | 决策 |
|---|---|
| **物理几何** | `digest/<bucket>/<slug>.md`;**浅桶一层**(顶多两层),桶内 flat |
| **bucket 角色** | **仅承担物理归档 + OS-level 浏览锚点**;不承担语义本体角色 —— 主题由图中节点表达 |
| **bucket 集合** | **代码内 hard-coded**(`reme/steps/evolve/dream.py``BUCKETS` 常量),不通过配置外置,不由 dreamer / maintainer 动态生成 —— 三桶设定是 dream 模型本身的一部分(Phase 2 prompt 按 bucket 专化),不是可调参数 |
| **集合视图** | 桶名内嵌在 prompt 中(extract 阶段三桶判别启发 + 三份独立 integrate prompt);不再生成独立 `_buckets.md` 视图 |
| **初始化** | opinionated **三桶**,按"答什么问 + 谁在问"划分:`procedure`(答"怎么做 X" —— 步骤 / 方法 / runbook)/ `personal`(答"X 是谁 / 喜欢什么 / 不要做什么" —— 用户 / 团队 specific 身份 + 偏好)/ `wiki`(答"X 是什么 / 发生了什么 / 决策依据是什么" —— 通用知识 / 定义 / 原则 / 观察 / 决策先例;**也是默认兜底**) |
| **bucket 主页** | 不强制存在;split 累积出层级时 parent 节点天然成为浏览主页(中心性涌现,非架构必需) |
| **新节点归属** | bucket 由 **Phase 1** 在 unit 级别分配(写进 `MemoryUnit.bucket`),Phase 2 据此分发到对应 bucket 的专用 prompt;LLM 不能造新桶 |
| **未归类节点** | Phase 1 找不到更明确归属时强制归入 `wiki` —— 它就是默认兜底,不是失败状态 |
| **跨桶 move** | F-1 已禁止;若必须做(人工介入修错桶),走一次 `wikilink_handler.retarget_links(old, new)` |
**`wiki` 兜底桶**:
| 维度 | 内容 |
|---|---|
| **语义** | "通用知识 / 默认归属" —— `wiki` 在三桶中 scope 最广(定义 / 原则 / 观察 / 决策先例),Phase 1 没有更明确归属(不属于 `procedure` 的可执行流程,也不属于 `personal` 的用户 specific 偏好)时归入此桶;**是合法常态,不是故障状态** |
| **路径** | `digest/wiki/<slug>.md`,与其它 bucket 完全等同;节点演化与其它桶一致 |
| **错桶后续** | 不主动跨桶 move;若严重,人工 mv + `retarget_links(old, new)` |
**为什么 `wiki` 兜底,而不是另设 `unknown`**:三桶设计中 `procedure` / `personal` 都有明确语义边界,剩下的"X 是什么 / 决策依据 / 一般原则"自然落在通用知识那一边 —— 这恰好就是 `wiki` 的本职。再设独立 `unknown` 会出现两类语义重叠的兜底(`wiki` 的"通用知识" vs `unknown` 的"分类未定"),反倒让 LLM 在 Phase 1 多一道无意义的犹豫。`wiki` 节点本身就是合法常态,不需要后续清理。
**为什么是浅桶而不是深树**:
- 物理浏览有"主题轮廓"(打开 `digest/wiki/` 能看到这一族节点),不像纯 flat 那样毫无锚点
- 节点不被深路径绑死("属 wiki/auth 还是 wiki/session"这种归属焦虑被消解 —— 一个节点可以同时被多个主题通过 wikilink 引用)
- F-1(0 文件移动)+ 平铺后,深树的核心收益(子树重组)消失,只剩深路径维护负担
- **固定三桶的关键意义**:LLM 在 dream 桶决定时只做"分类"(三选一),不做"造类" —— 决策面坍缩,跨任务跨时间稳定;不会出现 "knowledge" / "wiki" / "concepts" 三个语义重叠的桶共存。三桶覆盖 personal-knowledge 的核心切片(做什么 / 谁喜欢什么 / 知识本身),进一步细分由桶内 wikilink 图自然涌现
**已排除**:动态扩桶 / 拒绝写入(候选丢失)/ 强行选最近似专属桶(本体污染) / 把 bucket 数推回 6+(决策面失控)。
---
## 2. 节点
| 维度 | 决策 |
|---|---|
| **粒度** | atomic;一个 .md 文件 = 一个原子单元(概念 / 方法 / 实体 / 案例 / 原则 / 主题概览)|
| **节点角色** | **由 body 内容决定,不由 frontmatter 类型标记**;同一节点扮演"主题概览"还是"具体方法",看它的 body 写了什么 |
| **身份(ID)** | **workspace-relative 路径(含 `.md`)即节点身份** —— `digest/auth/jwt-rotation.md` |
| **`name` frontmatter** | 文件名 basename(不含扩展名),与文件名同步 —— 检索 hint / 人读标签,**不当 ID 用** |
| **frontmatter 保留字段** | 只有 `name` + `description`(reme 核心保留)|
| **可选 `kind` 字段** | 例:concept / procedure / preference / observation / ...;**消费层 schema 提示**,reme 核心透明,不读它做结构决策。与 bucket 是不同概念 —— bucket 决定物理归档(三桶)+ Phase 2 prompt 走哪份;`kind` 是更细粒度的 frontmatter 标签,留给消费层自由使用 |
| **文件名冲突** | 同 bucket 内文件名冲突 → 文件系统层断言(写入即拒);不需要独立检测信号 |
| **rename** | 一次 `wikilink_handler.retarget_links(old_path, new_path)`(机制现成);无 alias 表,无透明展开 |
**为什么 atomic + 路径即 ID**:
- **节点粒度 = retrieve 精度上限** —— semantic 检索召回 "一个原子单元" 远比召回 "一个 5000 字的主题文档" 信噪比高
- **wikilink 在 atomic 粒度才真有意义** —— `[[digest/auth/jwt-rotation.md]]` 指向"一个具体方法"比指向"auth 主题文档"精确一个数量级
- F-1 + 平铺 + 下层 immutable 后,slug abstraction 的核心价值(移动鲁棒性)蒸发;路径作 ID 与 `wikilink_handler.py` 默认形态完全对齐(*Recommended form: full path relative to the workspace with extension*)
- provenance wikilink 反指 daily/resource 本来就用路径,统一后整个 workspace 一种 wikilink 形态
**"主题概览节点"靠内容识别,不靠前缀 / kind**:`hub__` / `topic__` 前缀**不存在**;文件名自然命名(`auth-fundamentals.md` / `jwt-rotation.md`)。主题概览身份是图位置(中心性 / split parent)+ body 形态共同涌现。
---
## 3. 边
参考实现:`reme/utils/wikilink_handler.py` + `reme/schema/file_link.py`
| 形态 | 写法 | 说明 |
|---|---|---|
| **基础** | `[[<workspace-path>.md]]` | literal,不隐含 `.md`,不自动短链补全 |
| **alias** | `[[path.md\|display-text]]` | rewrite 时 alias 保持 |
| **image** | `![[image.png]]` | 资源引用,不是知识边 |
| **可选谓词** | `predicate:: [[path.md]]`(行级)/ `[predicate:: [[path.md]]]`(内联) | Dataview 风格;谓词在 `[[]]` 外,`[[]]` 内只保留纯目标 |
| **谓词标识符** | `[A-Za-z][A-Za-z0-9_]*`(`is_a` / `extends` / `causes` / `references` ...) | 词表**开放**,任意标识符 |
| **未类型化合法** | 绝大多数 wikilink 不加 predicate;`predicate=None` 是默认 / 常态 | |
| **边唯一性键** | `(target_path, predicate)` 二元组 | 同源同标不同 predicate = 不同边 |
| **不引入 anchor** | digest 设计层不使用 `[[path.md#section]]` | `FileLink.target_anchor` schema 保留(供其它消费层),digest 层永远写 `None` |
**reme 核心对 predicate 的"透明"边界**(关键):
- 横向 link/ retrieve 中心性 —— 都**聚合所有 predicate** 算,不分桶
- 只有 edge 唯一性 / 反向索引会用到 predicate(否则 `[[A]]``is_a:: [[A]]` 会被当作同一条边互相覆盖)
- 消费层若要按 predicate 做更精细的推理(如"taxonomic 路径只走 `is_a` 边"),自己读 `FileLink.predicate` 即可
**与 `kind` 一致的立场**(与 [[reme_schema_layering]] 对齐):reme 核心**只有节点 + 边两种结构类型**;`kind` / `predicate` 都是内容标签,绝不参与"hub / topic / leaf"这类结构角色判断。
**为什么不引入 anchor**:LLM 想"指向具体子主题"时,**正确做法是让那个子主题升级为独立节点**(必要时通过 split),不在过载 parent 内部用 anchor 凑合。anchor 在 digest 层无语义;prompt 必须明确告知 LLM 写 wikilink 时不带 `#section`
---
## 4. 演化
### 4.1 演化只做两件事
| op | 谁 | 何时 | 改什么 |
|---|---|---|---|
| **dream**(create_or_update) | dreamer(本文档 §4.2) | 入流(新材料进入) | 创建新节点 / update 已有节点 body(语义守恒重写;UPDATE 内分 **CORROBORATE / REFINE / CORRECT** 三种 flavor,详 §4.2.3) |
| **M split** | maintainer(`auto_consolidate_design.md` §1) | 节点过载(token / 主题离散度超阈值) | 把 parent body 拆成 parent overview + N children;parent 文件原地 |
> **关键观察**:"主题概览节点"不是一种 kind,也不是 maintainer 主动涌现的产物 —— 它是 split 的副产品(parent 节点天然成为该 cluster 的 overview,中心性自然高)。
显式排除:
- ❌ merge / dissolve / re-edge / unify —— 跨节点重组不做(同概念二次进入靠 dream update;错桶节点不主动 move)
- ❌ 完美归簇 —— F-5 留白,不确定就不动
- ❌ 实时一致 —— 异步 / eventual
### 4.2 dream(create_or_update)流程
**dream = dreamer 入流唯一改 body 的操作,且只改 subject node。**
#### 4.2.0 digest 是抽象记忆层
Digest 是 agent 长期记忆的**抽象层** —— 类比前额叶对认知的聚合。原始细节(数字、流程文本、谁说了什么)留在材料(daily / resource),digest 只承载细节淡忘后仍想调取的那一层:原则、模式、可作为先例的决策、认知要点。这一立场决定了 dream 流程的形态:**Phase 1 识别抽象,Phase 2 把抽象登记到 digest 节点**。
#### 4.2.1 两阶段流程
```
material 进入(daily / resource 选定 scope)
Phase 1 — extract (轻量)
LLM 读材料 → 识别其中教导的"抽象"(原则 / 模式 / 先例)
→ 为每个 unit **分配 bucket**(procedure / personal / wiki)
→ 发出 ExtractedUnits 结构化输出 = K 个 sub-unit
(每个: {name, bucket, summary})
说明:多个支撑事实说明同一抽象 → 合并为同一 sub-unit
(倾向少而精);Phase 1 是 gate ——
无新抽象时发空列表,Phase 2 跳过整轮;
bucket 由 Phase 1 一次性决定,Phase 2 不再回选
▼ (Python 外循环,K 次)
Phase 2 — integrate (per sub-unit,**按 bucket 分发到独立 prompt**)
│ system prompt = integrate_system_prompt_<unit.bucket>
│ procedure / personal / wiki 三份独立 prompt,**不共用一套**
│ sub-unit ↔ digest 节点 1:1;Phase 2 必写,无 SKIP 出口
├─ RECALL: search(关键词 + 向量 + RRF) + traverse(对 top hit
│ 做图扩展,**跨 bucket**) → 候选路径集
├─ HIT: frontmatter_read 廉价 triage → read 完整 body
│ 确认候选是否承载同一抽象 → hit 集合
├─ 决策:
│ ├─ hit 空 → CREATE 在 digest/<unit.bucket>/<slug>.md
│ └─ hit 非空 → UPDATE 路径 (CORROBORATE / REFINE / CORRECT;
│ 目标可在任意桶 —— 召回是跨桶的)
写入(canonical write 创建 / canonical edit 改正文)
agent 上报 IntegrateOutcome {action, target_path}
```
**两阶段 trade-off**:Phase 2 把完整材料发 LLM K 次(一次一 sub-unit),不做 summary loss;代价是 K 倍 prompt token。换来的是 Phase 1 只做"识别抽象 + 分类 bucket"两件事(粒度集中在一个 prompt),Phase 2 每次会话上下文干净、bucket-specific prompt 让推理聚焦于"这一桶要怎么写 / 怎么改"。
**Phase 2 的 bucket 专化**:三桶各有独立 system prompt,因为各桶的 body 形态、决策偏置不同 —— `procedure` 节点是 runbook 风(触发 / 步骤 / 前置 / 失败模式),`personal` 节点是规则风(rule + Why + How to apply),`wiki` 节点是百科风(定义 + 性质 + 关系)。共用一份通用 prompt 会让"应该写成什么样"的指导被稀释,bucket 信号靠一段 if-this-then-that 散文承载,效果劣于让每桶自带专属 prompt。
#### 4.2.2 召回 → 内化分类 → 决策 → 织突触(ReAct agent 一体完成)
Phase 2 是单个 ReAct agent 在一个 loop 内完成 4 件事 —— **不拆 stage,不引入外部机械步骤**,只通过 prompt 引导 agent 把 dedup 与 synapse 这两类判断都做透。当前默认 `search(limit=5)` 不够,prompt 已显式引导更深召回。
**4 步流程**(整段由 ReAct agent 自主组织调用):
| # | 步 | 关键动作 |
|---|---|---|
| 1 | **召回 —— 多角度宽召** | 显式 `limit=20-30` × 两轮 search(一次 hybrid,一次 `vector_weight=1.0` 纯语义)+ `traverse depth=2` 拓扑补充 |
| 2 | **内化分类** | `frontmatter_read` triage + 必要时 `read` body;对每个候选**内化打 label**(只在思考中分类,不输出):`same_abstraction` / `related` / `unrelated` |
| 3 | **决策** | 0 个 `same_abstraction` → CREATE;1 个 → UPDATE(选 flavor) |
| 4 | **织突触** | CREATE 或 UPDATE 都把所有 `related` 候选织入 body 作 `[[Y.md]]`;CREATE 一次性织全;UPDATE additive 加 wikilink |
**两类内化判断的本质**:
| 判断 | 服务 | 输出形态 |
|---|---|---|
| **同抽象?**(dedup)| 决定 CREATE / UPDATE | 0/1 个 target(决策面排他) |
| **相关?**(synapse)| 决定织哪些 wikilink | N 个 related 候选(决策面累加) |
两者是同一个 ReAct agent 在看完 candidates 后的**两层独立判断**,共享同一批召回结果,**不需要分两轮 LLM 调用**。
**召回**(对应 prompt step 1):dream 用专属的 `node_search`(`reme/steps/index/node_search.py`),**不**用通用 `search`,**也不用 `traverse`** —— 详 §4.2.2.1(traverse 是 retrieve-time 子图挖掘工具,跟 dream 写入场景错位)。
| 调用 | 找什么 |
|---|---|
| `node_search(query=<...>, limit=20-30)` | digest 内节点级 hybrid 召回(vector + BM25 RRF),返回 path + frontmatter |
**召回结果服务两类判断**:dedup(`same_abstraction` label,是否同抽象 → CREATE / UPDATE)和 synapse(`related` label,是否相关 → 织 wikilink)是 LLM 在**同一批 candidates** 上的两类内化 label。原"两轮 search(hybrid + vector_only)"是设计冗余 —— 同一批候选 LLM 自己能判 same/related/unrelated,模式切换无意义。**调用次数由 agent 自决**:一次通常够;若 unit 跨多个概念维度,agent 可发起多次不同 query 的召回,prompt 不强约束。
**HIT = `node_search` 返回 + read**:`node_search` 已内嵌返回每个 hit 的 frontmatter(`name + description`),agent 直接据此 triage,**不需要额外调 `frontmatter_read` 批量取 metadata**;仅对需要看 body 的少数候选用 `read`。**不可仅凭 frontmatter 决定 UPDATE**,body 才是判定依据。
##### 4.2.2.1 node_search vs 通用 search 的差别 + 为什么 dream 不用 traverse
**node_search vs 通用 search**:dream 的召回需求跟外部 agent 的 RAG 检索**结构性不同**,因此用专属 step 而非复用 `search`:
| 维度 | 通用 `search`(外部 agent)| `node_search`(dream Phase 2) |
|---|---|---|
| 用户 | 用户/外部 agent 的自然语言 query | dream 内部生成的 unit.summary |
| 结果粒度 | **chunk 级**(可能同一 node 多个 chunk)| **node 级**(同 path 聚合 max score)|
| 返回信息 | 完整 chunk text + scores | **path + name + description**(frontmatter 内嵌,无 body)|
| 范围 | 全 workspace(daily / resource / digest) | **digest-only**(dream 永远只在 digest 找候选)|
| expand_links | 默认 `True`(给 agent 更多上下文)| **永远 `False`**(synapse 找的就是未 link 的)|
| 默认 limit | 5 | **20**(dream 需要宽召覆盖 synapse)|
复用通用 `search` 会让 dream 拿到的候选**既粒度不对**(chunk 级,同 node 多次出现)**又信息冗余**(chunk text 不必要)**又被噪声污染**(daily / resource hits 永远不是 dream 的 UPDATE 候选)**又召回偏窄**(expand_links 把已 link 的拖回来,挤掉真正未 link 的 synapse 候选)。所以 dream 需要自己的 `node_search`
**为什么 dream toolkit 不包含 traverse(或 dream_traverse)** —— traverse 是 **retrieve-time 子图挖掘工具**,跟 dream 写入场景**结构性错位**:
| 维度 | traverse 的本性(retrieve / RAG)| dream 的真实需求(写入)|
|---|---|---|
| 方向 | 从已知中心向外扩散 | 从外部新材料找 workspace 内相关候选 |
| 输入 | 已知种子节点 | 新材料的 unit.summary |
| 输出语义 | "X 的子图"(给读者上下文) | "X 应该 link 到哪些 Y" |
| 图遍历的角色 | 主操作 | 召回兜底(可有可无) |
dream 写新节点要回答"workspace 中谁跟我相关",这是**召回**问题(给 query 找相关),不是**遍历**问题(给中心找邻居)。**召回工具 = node_search;遍历工具 = traverse(留给 retrieve / 外部 agent 用)。dream 不需要遍历**。
(早期曾实现 `dream_traverse` 准备作为 dream toolkit 一员,后撤销 —— 实测拓扑遍历 vs vector 召回重叠率 ~95%,真正独特贡献 < 2%,且引入 LLM 调用 / 上下文 / 复杂度成本 git log。)
**node_search 参数极简**(`query / limit` 两个):**mode 不需要**(同一批候选服务双判断);**exclude_paths 不需要**(self 由 LLM 自己识别,frontmatter 内嵌让 agent 一眼看出"这就是我");**min_score 不需要**(RRF 分数范围 0~0.025,跟 cosine 0~1 量纲完全不同,召回深度由 `limit` 控制就够)。**调用次数 agent 自决**:prompt 不约束"必须一次",unit 跨多个概念维度时 agent 可多次召回。
**node_search 召回算法:weighted node-level RRF**(vector + BM25 hybrid):
- vector + BM25 各自独立召回 → 各自得到 chunk list(按各自 score 排序)
- 同 path 多 chunk 合并:取该 path 在两个 list 中的 max chunk score 位置作为 node rank
- RRF 融合:`score(path) = vector_weight × 1/(60 + rank_v) + (1-vector_weight) × 1/(60 + rank_k)`
- `vector_weight=0.7`(默认),vector 主导,BM25 作为兜底(覆盖专有名词 / 缩写等 embedding 可能 struggle 的字面 case)
- 输出 score 是 RRF 分(0~0.025 量级,不是 cosine);LLM 不依赖具体分数,内化判 same/related/unrelated
**reinforce 并入立场**(对照 `auto_consolidate_design.md` §4 标作废):reinforce 不再是独立的 consolidate 动作 —— 它就是 step 4 的"织突触"。新节点写入瞬间一次性建立关系,workspace 不维护"事后周期 batch 补 wikilink"的通道。F-2 自然守住 —— dream 只动新节点 body,不动其它节点。
**关键约束**(诚实承认):
- **写入即定型** —— 今天没织的 wikilink 以后没机会再织;workspace 单调演化
- **一次性 commit,无事后兜底** —— prompt 明示"宁可多织"(false positive 一眼能否决;false negative 永远沉默)
- **召回深度取决于 prompt 引导 + agent 配合** —— 不引入外部机械召回 step;prompt 已明示 `limit=20-30 × 两轮`,但仍是 ReAct agent 的开放执行
- **dedup 与 synapse 在一次 LLM 调用内完成** —— 不拆独立 stage,共享召回结果,内化分类是免费的
#### 4.2.3 UPDATE 三种 flavor
| flavor | 何时 | body 怎么动 |
|---|---|---|
| **CORROBORATE**(最常见)| 已有节点已覆盖此抽象,材料是又一个实例 | body 实质不变 —— 追加 `derived_from::` 溯源,可选强化措辞("似乎"→"确实") |
| **REFINE**(常见)| 已有节点覆盖了核心,但材料揭示新的范围 / 边界 / 维度 | 改相关片段使更精确,加新维度,加 `derived_from::`。正文在**精度**上长,不在**细节**上膨胀 |
| **CORRECT**(少见)| 材料与已有抽象矛盾 / 表明它被夸大 | 收紧到新旧证据都支持的窄形式,或内联标注 `> note: contradicted by [[...]]` 不仲裁。仍加溯源 |
三种都受 §4.4 E-1 强守恒约束(出边集合不能缩)。
#### 4.2.4 关键边界
- **Phase 1 是 gate + 分类器** —— "不值得记忆"在 Phase 1 过滤(空列表);此外 Phase 1 还为每个进入 Phase 2 的 unit 分配 bucket(procedure / personal / wiki),决定 Phase 2 走哪份专用 prompt;Phase 2 必然写,sub-unit 与 digest 节点 1:1
- **Phase 2 prompt 按 bucket 分发** —— `integrate_system_prompt_procedure` / `_personal` / `_wiki` 三份独立 system prompt,各自承载该桶的 body 形态指南与决策偏置,**不共用一份通用 prompt**
- **CREATE 写入桶 = Phase 1 分配的桶**;**UPDATE 目标可在任意桶**(召回跨桶,UPDATE 命中谁就写谁)
- **dream update 必须语义守恒** —— LLM 重写 body 时只能"融入"新内容,不能删除已有信息(只增不删 / 不改原意;冲突标注 `> 注:不同来源记载...`,不擅自仲裁);**当前实现下 E-1 强守恒是 prompt-only 自律**(canonical edit 不做机械 outbound diff;早期 `digest_edit` 子类的机械校验已在切到 canonical 工具时移除,详 §4.4)
- **Phase 2 用 canonical write / edit** —— 不再有 `digest_write_step` / `digest_edit_step` 子类;桶归位与边守恒都是 prompt-level 纪律
- **dream 不改其它节点正文**(F-2) —— 只动 subject
- **dreamer 不做事件级伞节点** —— 材料本身(daily / resource 文件)就是 fan-out 点,每个 sub-unit 的 `derived_from::` 让材料天然聚合到所有派生节点
- **0 出边节点合法**(没识别到合适邻居),后续 dream 进入时其它节点可以反向链回来 —— 不强求 LLM 一次性给全
- **dream 漏判去重**(同概念建成新节点)→ 不主动兜底,接受重复;若 workspace 累积明显重复,由 auto-consolidate 的 dups 检测周期 batch 产报告(`auto_consolidate_design.md` §3)
- **召回不做 bucket 粗筛** —— LLM 拥有完整跨桶视野,可识别"概念跨桶同抽象"(例如同一原则在 wiki 已有节点而 Phase 1 把新材料归入 personal,此时 UPDATE wiki 节点而非新建 personal 节点)
- **reinforce 已并入 dream synapse recall** —— 不存在独立的 reinforce 动作或周期 batch;突触构建(原 `auto_consolidate_design.md` §4 reinforce 的职责)在 dream Phase 2 synapse recall 阶段完成,新节点写入瞬间织全(详 §4.2.2)
- **workspace 不维护事后补 wikilink 通道** —— 上一条的直接推论;cognition §9.2 立场("关系建立在写入瞬间")在此自然守住
**provenance 写出**:
- 行文中自然带:"... 该模式最早出现在 [[daily/2026/05/15.md]] 的实践中"
- **强制 typed predicate `derived_from::`** —— body 必须织入至少一条 `derived_from:: [[daily/...]]``[[resource/...]]`,纯散文形式不会被未来的 update / 守恒比对识别为边,下次 update 时会消失
- LLM 直接做语义守恒重写(只增不删) —— 不走"首版 append 起步"的过渡路径
### 4.3 F-invariants(演化的硬约束)
| # | 约束 | 含义 |
|---|---|---|
| **F-1** | **0 文件移动** | dream / split 都不移动现有文件;split 创建的是**新文件**,parent 原地 |
| **F-2** | **改正文限定 subject** | dream update 改 subject body;M split 改 parent body + 创建 children body;**没有任何操作改"其它节点正文"** |
| **F-3** | **maintainer 只做 split** | 没有 summarize / merge / re-edge / link / unify / dissolve |
| **F-4** | **一次一个候选** | M split 一次拆一个;dream 一次处理一个原子单元(N 候选 = N 次 dream) |
| **F-5** | **不确定时不动** | dream 拿不准 create 还是 update → 倾向 create;split 拿不准 cluster → 不拆 |
| **F-7** | **多归属合法** | 一个节点可被多个引用,也可指向多个;**没有"单父"约束** |
| **F-10** | **inbound 目标节点不动** | 所有 inbound 是裸链 `[[<parent-path>.md]]`(digest 不引入 anchor);split 时全部保持,parent 路径未变即天然有效 |
| **F-11** | **wikilink 是 body 的一部分** | 不存在"独立的边";reme 核心机械算子只感知字符层,语义责任在 LLM(prompt 自律);split 写入路径仍带机械 outbound 校验,dream update 当前是 prompt-only(详 §4.4) |
### 4.4 边守恒(E-1 / E-2 / E-3)
**前提**:wikilink 是 body 的一部分(F-11)。"边"不是独立抽象 —— body 一变,边就跟着变。reme 核心**没有"修边"算子**;边的所有变化都是 body 文本编辑的副作用。语义层守恒由两条腿承担:**prompt 自律**(LLM 在 update 时被反复要求 only-add, not-delete)+ **必要时的机械校验**(下文区分了哪些保留、哪些已移除)。
| # | 类别 | 规则 | 谁负责 |
|---|---|---|---|
| **E-1** | dream update 节点出边(subject 自身) | **强守恒**:新 body 出边 ⊇ 原 body 出边(`(target, predicate)` 二元组,predicate 一并守住) | **当前实现:LLM(prompt)自律** —— canonical `edit` 不做机械 outbound diff,prompt 反复强调"never drop wikilinks the old span contained" |
| **E-2** | split parent 出边(parent 拆解) | `(parent_new children_outbound) ⊇ parent_old` | LLM(split prompt)+ 机械(由 maintainer 在 split 写入路径上实施,见 `auto_consolidate_design.md`) |
| **E-3** | inbound wikilink `[[<parent-path>.md]]` | split 时**不动** —— 仍指 parent;后续 dream 进入若 LLM 觉得 child 粒度更合适,直接加新边到 child(F-10) | 不动 |
**E-1 实现取舍**:早期版本有专用 `digest_edit_step` 子类,在写入前对 body 做 outbound diff 比较,违反守恒时返回 `REJECT_CONSERVATION` 让 LLM 重试。在切到 canonical `edit` 工具(放弃 digest 子类)后,这道机械校验被移除 —— 守恒退化为 prompt-only 自律。trade-off:
- **失**:LLM 偶尔会在 REFINE / CORRECT 时无意丢弃 `derived_from::` 链;系统不再自动拒写
- **得**:Phase 2 工具与系统其它写入路径完全一致(write / edit 是 canonical job),没有 dream-private 写入语义;prompt 复杂度下降,工具表面更小
- **后续**:若 prompt-only 守恒在生产中被证伪(掉链率高),可在 canonical `edit` 上挂一个可选的 conservation 校验 hook(不再走子类化路径),由 dreamer 在调用前后各 read 一次做 diff;但当前不做
**强守恒(集合包含)而非等价**:`new ⊇ old` = 允许加新边(新关联),不允许减边(老内容不能丢);`new == old` 会拒绝任何新出边 → update 失去意义。
**predicate 守住** —— `[[A]]``is_a:: [[A]]` 视为不同 key,升降级走显式 audit 路径,不走默认。重排 / 改 alias / 加新边都不被拦下(集合相同或只增)。
**provenance 不单列** —— 节点反指上游 daily/resource 的 wikilink 是 body 正文的一部分,跟其它 wikilink 走同一套 E-1 / E-2;reme 核心没有 provenance 专用算子。
**inbound anchor 这一类不存在** —— digest 不引入 anchor,所有 inbound 都是裸链,走 E-3 即可,无需机械 retarget 子流程。
---
## 5. 与其它层
| 上下游 | 关系 |
|---|---|
| ← **auto-memory**(daily) | dream 读 daily 作为入流;daily 写完即对 dream 可见 |
| ← **resource** | dream 读 resource 作为入流(只读,不写) |
**关键边界**:dream 不写 daily / resource(I-2 / I-3);只写 digest 节点 body(自身 subject)。dream 不感知下游 —— split / 链接增强 / 索引刷新 / rename 等由 `auto_consolidate_design.md` / `auto_cognition_design.md` / `update_store_index_loop` 各自负责。
---
## 6. 下一步
本文档覆盖 dream 模型(桶 / 节点 / 边 / 演化)。组织端实现清单(M split / D 检测 / CAS 框架)见 `auto_consolidate_design.md` §10。
- ✅ **dream step 实现** —— Phase 1 extract(识别抽象 + 分配 bucket)+ Phase 2 integrate(per sub-unit,**bucket-specific prompt 分发**;`reme/steps/evolve/dream.py` + `dream.yaml`,与 `auto_memory` 同级同形)
- ✅ **三桶 hard-coded** —— `procedure / personal / wiki`,`BUCKETS` 常量在 `dream.py` 顶部,Phase 1 通过 `MemoryUnit.bucket: Literal[...]` 由 Pydantic 强制约束
- ✅ **provenance prompt 规范** —— `derived_from:: [[daily/...]]` / `[[resource/...]]` 强制(三桶 prompt 各自重申)
- ❌ ~~**边守恒校验工具**~~ —— 早期 `digest_edit` 子类的 outbound diff 校验已随子类一并移除(切到 canonical `edit`);E-1 现由 prompt 自律,详 §4.4
- ❌ ~~**bucket 集合配置外置**~~ —— 撤销:三桶是 dream 模型本身的一部分,不做配置参数(`workspace.yaml` 不再承载 `digest.buckets`,`_buckets.md` 视图也不再生成)
- 🆕 **Phase 2 召回拆 dedup / synapse**(2026-06-02 沉淀,详 §4.2.2)—— 当前 prompt 共用一次 `search(limit=5)`,既不够 dedup 精度也不够 synapse 覆盖;落地:`dream.yaml` 6 处(en + zh × 3 buckets)Recall 段改写,加 synapse 模式说明 + 写入即定型纪律
- 🆕 **`file_store.default.embedding_model` 启用**(blocker)—— `default.yaml` 当前 `""`,synapse recall 用 vector_weight=1.0 模式必须开启;否则 `search` 退化为纯 BM25,dedup 也劣化
- 🆕 **reinforce 并入立场写入**(详 §4.2.2)—— 与 `auto_consolidate_design.md` §4 标作废同步;`hierarchical_summary.md` §13.2 Q4 标解决
实现进入 `reme/steps/evolve/` 时,本文档与 `auto_memory_design.md` / `auto_consolidate_design.md` / `auto_cognition_design.md` 共同作为契约依据。

View file

@ -1,197 +0,0 @@
# auto-memory 设计(实时事件拆分 / 写入 daily)
> 本文档记录 reme 中 **auto-memory** 的设计讨论 —— 把 agent 连续的对话 / 任务流切成离散的 daily 事件原子,inline 落到 `daily/` 层。
>
> 配套阅读:
> - `structure.md` §2.1-2.2(daily 层定位)/ §3.4(sync 动作语义)/ §7.1(synchronizer 模块)
> - `auto_dream_design.md`:auto-memory 产物如何被 dream 消化(dream 读 daily 作为入流之一)
> - `auto_consolidate_design.md`:digest 的组织端 / CAS 写入协议;auto-memory 不直接复用,但事件级"拆"与节点级 split 在概念上同构(都把过载粒度切小)
> - `auto_cognition_design.md`:auto-cognition 三阶段顶层思想(写入 / 巩固 / 检索);daily 节点是 cognition 图视图的一部分(承载 `derived_from::` 反指),但不参与 Stage 2 巩固改造
>
> **服务全景**:reme 服务两条主线 —— **auto-memory**(本文档,入流端 / daily 写入)与 **auto-cognition**(顶层思想:写入 = auto-dream,巩固 = auto-consolidate,检索 = auto-recall)。auto-memory 把 agent 实时事件流切成 daily 事件原子;它的产物是 dream(cognition Stage 1)消化的两路输入之一(另一路是 resource)。
>
> **核心立场**:auto-memory 是 `structure.md` §3.4 `sync` 动作的实现侧 —— 强调 **inline 实时**与**事件边界检测**。是不是改名 sync → auto-memory 留给上层文档对齐,本文档聚焦机制。
---
## 0. 问题陈述
agent 的对话与任务过程是连续事件流(用户回合、工具调用、上下文切换、中断恢复),但记忆系统需要离散的、可独立检索的事件单元。auto-memory 解决这个切分问题。
| 输入 | 输出 |
|---|---|
| agent 当前事件流(对话回合 / 工具调用 / 任务切换信号);可选 `notify` 候选作为 cue | `daily/<date>/<event-slug>/<note>.md` 事件原子;`daily/<date>.md` 主索引 |
**设计目标**:
1. **事件边界尽量与 agent 语义意图一致** —— 同一个意图(同一个任务 / 同一段思路)→ 同一个事件;意图切换 → 新事件
2. **inline 实时写入** —— 不滞后,不批处理;agent 一边工作,记忆一边落地
3. **保持 daily 写权契约** —— I-2 单作者(同 folder 不并发改);folder 名 = summary note 名(I-3 可移动单元)
**显式排除**(不属于 auto-memory 职责):
- ❌ 蒸馏 / 沉淀:那是 auto-dream(`auto_dream_design.md`)的事
- ❌ 实体识别 / wikilink 自动补全:cognition 三阶段不在写入后做"事后补 wikilink"(详 `auto_cognition_design.md` §1.1);所有 wikilink 由 dream 在写入瞬间产出
- ❌ 改写 resource / digest:auto-memory 只写 daily(I-1 / I-3)
---
## 1. 已对齐决策
### 1.1 物理布局:与 `structure.md` §2.2 对齐
| 项 | 决策 |
|---|---|
| **主轴** | 时间 + 任务:`daily/<date>/<event-slug>/` |
| **event-slug** | LLM 抽取的事件短名(snake_case / dash-case;不强制 schema),同 `<date>` 下唯一 |
| **folder 内** | 一个事件可有 N 个 note(`progress.md` / `decision.md` / `references.md` 等),由消费层 schema 决定;最少含一个 summary note,与 folder 同名 |
| **主索引** | `daily/<date>.md`:当天事件列表(机械写入,wikilink 指向各 event folder)|
| **跨日索引** | 不强制;dream 消费时按 `<date>` 范围拉取即可 |
**为什么不是单文件 event**(report §5.1 一种简化方向):
- 单文件 event = `daily/<date>/<event-slug>.md` 比 folder 模型简单,但失去"一个事件可包含多个视角 note"的灵活度
- 现行 `structure.md` 已定 folder 单位模型;auto-memory 沿用,不破坏既有 I-2 / I-3
- 若后续 dogfooding 验证单事件普遍只有一份 note,可演进为 folder 内只放一份 summary,机械上等价于单文件方案 —— 演进路径平滑,不需要现在选
### 1.2 事件边界:语义意图切换驱动
事件边界由 LLM 在 inline 写入时判:**当前回合的意图是否仍属上一个 event**。
| 维度 | 决策 |
|---|---|
| **决策时机** | 每个 agent 回合写入前 inline 判 |
| **决策依据** | 上一个 active event 的 summary + 当前回合内容;LLM 输出 `{continue: bool, new_event_slug?: str, summary_patch?: str}` |
| **continue=true** | append 当前回合到 active event(append-only 或 LLM 重写 summary,详 §1.3) |
| **continue=false** | 关闭 active event(写最终 summary)+ 开新 event folder(slug 由 LLM 给)|
| **同时 active 多事件** | 不允许(I-2 单作者)—— 一时刻只一个 active event;真要并行任务,agent 自己 sync 切换 |
**已排除**:
- 时间窗口切分(N 分钟无活动则切)—— 对话节奏因任务而异,时间窗口噪声大
- 关键词切分(出现"切换 / 现在做 X"等触发词)—— 假阳性高,且不所有切换都明显说出
- 后置 batch 切分 —— inline 写入要求 event 必须当下可决定归属,不能等
### 1.3 事件内写入模型
active event 内,每个回合的内容写到 event folder 下,有两种模式可选(消费层 schema 决定):
| 模式 | 形态 | 适用 |
|---|---|---|
| **append-only** | 一份 `<event-slug>.md`,新回合 append 到末尾(章节 / 时间戳 / 等)| 实现最简;事件短(< 几十回合)时可读性 OK |
| **多 note 重写** | summary note(folder 同名)+ 各视角 note(`progress.md` / `decision.md`);LLM 把新内容融到对应 note,summary note 重写为当下概览 | 事件长 / 多视角时可读性高;LLM 成本高 |
**默认 opinionated default**:append-only(最简启动)。消费层可改 prompt + schema 走多 note。
**与 E-1 守恒的关系**:daily 不强制 E-1 守恒(它是工作记录,允许 LLM 删旧加新);只在 multi-note 重写模式下,可选启用类似守恒(保留所有 wikilink),具体由消费层决定。
### 1.4 主索引 `daily/<date>.md`
当天事件 list 视图,机械维护(无需 LLM):
| 触发 | 操作 |
|---|---|
| 新建 event folder | 主索引 append 一行 `[[daily/<date>/<event-slug>/<event-slug>.md|<event-slug>]]` |
| 事件关闭(被切下一个 event) | 主索引该行 append 最终 summary 摘要(可选,LLM 写最终 summary 时附带写入) |
| 索引文件不存在 | 写入第一个 event 时创建 |
主索引**仅承担当天浏览锚点**:文件系统 `ls daily/<date>/` 也能看见,但有主索引人/agent 可直接 `read daily/2026/05/28.md` 拿到 list 视图 + summary 一览。
不维护跨日索引(`daily/2026/05.md``daily.md`):dream 消费时按时间范围拉取即可;`list daily/<date>/` 已经覆盖浏览需求。
### 1.5 与 notify 的协作
`notify` 是 reme → agent 的虚边推送(`structure.md` §3.3),把"有新 resource 值得看"传递给 agent。auto-memory 在以下两点与 notify 协作:
| 维度 | 协作方式 |
|---|---|
| **新事件 cue** | agent 收到 notify 后,如果决定响应(开始处理这个候选),通常会触发**新 event** —— auto-memory 把 notify payload 作为 hint(候选 resource 路径)写入新 event 的 summary,顺手用 wikilink 引上 |
| **acknowledge 派生** | event note 里出现指向 `[[resource/...]]` 的 wikilink → L1 watcher 将该 resource 推送状态置 `acknowledged`(`structure.md` §3.3 / §6.2);auto-memory 自身不调任何 ack API |
**关键约束**:auto-memory **不强制** agent 用 wikilink 引 notify 候选 —— agent 可能略过、也可能不通过 wikilink 而是直接读 resource。ack 是 daily → resource wikilink 的副产品,不是 auto-memory 显式负责的事。
---
## 2. 待对齐边界点
### 2.1 LLM 决策频率与成本
inline 边界检测的最朴素形态是每回合调一次 LLM。在长对话 + 高频回合下成本可观。可选优化:
- **continue 假设默认**:大多数回合是 continue(同一意图内),LLM 可能只在"看似切换"启发(token 跨度大 / 工具种类突变 / 用户显式说"接下来")时跑;否则默认 continue 不调 LLM
- **批回合**:每 N 回合批一次,延迟切分(代价:active event 边界滞后,首版可接受)
首版默认每回合调一次(最简,正确率高),M1+ 视成本优化。
### 2.2 中断恢复 / 跨进程 active event
agent 进程重启 / Service 重启后,如何识别"还有 active event"?
候选方案:
- **L2 自治状态**:L1 watcher 派生 `daily/<date>/<event-slug>/` 中最新 mtime 的 event 为 active(默认 N 分钟内有写入)
- **状态文件**:`.daily-active` 维护 active event slug,Service 启动时读
- **每次重建**:agent 进程重启视为新 event,旧的关闭(切到 §1.2 continue=false 路径)—— 最简但会增加事件数
倾向 §1.2 自然路径(进程重启 = LLM 下次判 continue=false 概率高)+ 不维护状态文件,详细 worker recovery 留给 Service 实现。
### 2.3 多 agent 同 workspace 的 active event 隔离
I-2 daily 单作者契约在多 agent 场景下需细化。候选:
- per-agent date subfolder:`daily/<date>/<agent-id>/<event-slug>/`
- 单 agent 模式 + agent ID 进 event-slug:`<date>/<agent-id>_<event-slug>/`
第二种破坏 slug 短名习惯;第一种引入额外层级。倾向后者作为消费层契约,reme 核心不固化。
### 2.4 事件粒度的 prompt 引导
边界检测的 prompt 决定切分粒度。粗 = event 大 / dream 看每个 event 时容易 overflow;细 = event 数爆炸 / 主索引拥挤。
**opinionated default prompt 倾向**:
- 一个意图 = 一个事件(用户提了 X 问题 / agent 开了 Y 任务 → 直到这个意图收尾)
- 跨意图的"附带工作"(查资料 / 算个数)归入当前意图,不开新 event
- 真新意图("好,现在我们做下一件事")才切
详细 prompt 落 `reme/steps/jobs/protocol.md` 或 synchronizer 的 prompt 模板。
### 2.5 与 resource ingest 的时序
如果 ingest 与 auto-memory 同时活跃(External push 推 resource 进来 + agent 在 sync),且 agent 想响应这个新 resource:
- ingest 写完 resource → L1 watcher 派生 L2 → notifier 决策推送(`structure.md` §5.3)→ Service MCP 推给 agent
- agent 在当前回合或下一回合响应 → auto-memory 判 continue=false 开新 event,wikilink 引上 resource
整条链 sub-second 到 seconds(notify 节奏);auto-memory 不直接知道 ingest,只在 agent 决定响应时被动接收 notify payload。
### 2.6 跨日任务延续
event 物理路径含日期(`daily/<date>/<event-slug>/`),同一意图跨日的任务无法用同一 event folder 承载。候选模型:
| 模式 | 形态 | 适用 |
|---|---|---|
| **每日新 event,wikilink 反指前日** | new day 起新 folder;summary note frontmatter 加 `inherits: [[daily/<prev-date>/<prev-slug>/<prev-slug>.md]]`;新 event body 不复制旧内容,仅引用 | event-slug 短,日切口干净;查 backlinks 拼出整条任务链 |
| **同 event 重复写不同日** | 不允许(I-2 single author + event folder date 在路径上,跨日写违反路径不可变) | × |
| **任务 ID 跨 daily 抽象** | 引入 `task-id` 维度,daily event 只是某 task 的某一日切片;额外维护 task index | 复杂度高,M0 不引入 |
**倾向**:第一种(`inherits` frontmatter wikilink)—— 与 §1.4 主索引一致(机械维护),实现侧 LLM 在 §1.2 boundary 判定时若发现意图与最近 N 天某个 active 任务一致,直接写入 inherits 即可。详细 boundary prompt 落 §2.4。
INHERIT 行为细节(扫描窗口、predecessor 是否关闭、Plan/Objective 是否拷贝)归消费层 schema 决定;reme 核心只承认 `inherits:` frontmatter wikilink 作为跨日链路载体。
---
## 3. 与其它层的协作
| 上下游 | 关系 |
|---|---|
| ← **notify** | 接收 notify payload 作为新 event cue;不强制响应,不强制 wikilink 引 |
| ← **resource** | 只读(通过 wikilink 引);不写 |
| → **daily** | **唯一写者**(I-2);写 event folder + 主索引 |
| → **auto-dream** | dream 读 daily 作为入流(`auto_dream_design.md` §4.2 dream scope);auto-memory 写完即对 dream 可见(走 L2 索引,有 eventual 窗口) |
| → **auto-cognition (三阶段)** | daily 节点是 cognition 图视图的一部分;dream(Stage 1)读 daily 作为入流;consolidate(Stage 2)只对 digest 节点跑 dups / community / decay,**不改 daily**;recall(Stage 3)三层并行召回时 daily 也参与命中 |
**关键边界**:auto-memory 是 daily 写入端的**唯一**入口;cognition 三阶段没有任何子阶段会**事后改写 daily**(无写回路径)。daily 一旦由 auto-memory 写完,就只被读不被改(I-2 / I-3 仍守);后续 dream / consolidate / recall 都是只读消费。
---
## 4. 下一步
1. **synchronizer step 实现**:event 边界检测 prompt + active event 状态管理 + inline 写入(append-only 默认)
2. **主索引维护**:`daily/<date>.md` 机械维护(新 event 时 append、关闭时附 summary)—— 走 crud/daily 基础工具
3. **notify ack 派生验证**:L1 watcher 派生 acknowledged 状态(`structure.md` §6.2),与 auto-memory 的 wikilink 写入端到端跑通
4. **多 agent 隔离 schema**(M1+):若实际有并发 agent,确定 daily 子目录 / slug 命名约定
5. **粗 / 细粒度 prompt 调参**:dogfooding 后看实际 event 数 / dream 消化效率,调 boundary prompt
实现进入 `reme/steps/jobs/``reme/file_graph/` 时,本文档与 `auto_dream_design.md` / `auto_cognition_design.md` 共同作为契约依据。

View file

@ -1,323 +0,0 @@
# auto-recall 设计(Stage 3 检索:信号融合 + 召回增强)
> 本文档:reme 中 **auto-cognition 三阶段****Stage 3 — 检索阶段** 实现。覆盖 query 到来时如何把 workspace 一等公民信号(wikilink 图 / frontmatter)与维护阶段产出信号(centrality / community / recency / archived)融合,生成最终召回。
>
> 配套阅读:
> - `auto_cognition_design.md`:三阶段顶层思想(本文档是 Stage 3)
> - `auto_dream_design.md`:Stage 1 写入 / 节点 + 边模型
> - `auto_consolidate_design.md`:Stage 2 维护 —— **本文档消费它产出的所有 `meta/*.json`**
> - `structure.md` §4(retrieve 三种问法)/ §7.4(为什么没有 retriever 模块)
> - `reme/steps/index/search.py` / `traverse.py`:现有原子实现
>
> **核心立场**:
> - retrieve **不引入新 L4 模块**(`structure.md` ✗-15)—— 三种问法各自由 L3 原子工具(`list_step` / `search_step` / `traverse_step`)直接覆盖
> - 本文档增强**集中在 `search_step` 内部**:把维护信号融入打分 / 排序 / 过滤;`traverse_step` 仅做小幅参数扩展
> - retrieve **只读 workspace,不写 body / 不写 frontmatter**;唯一写入是 `meta/access_log.json`(命中计数,供下次 recency 计算)
---
## 0. 问题陈述
`structure.md` §4 已规定 retrieve 三种问法(state / semantic / topological)正交分立(R-1)。本文档**只增强 semantic 问法**;state 问法已被 `list_step` 覆盖,topological 问法已被 `traverse_step` 覆盖。
semantic 问法当前在 `reme/steps/index/search.py` 实现:
| 已就绪 | 缺口 |
|---|---|
| ✅ vector + keyword 并行召回 | ❌ 节点中心性加权(高权威节点不被 boost) |
| ✅ RRF fusion(vector_weight=0.7) | ❌ 同社区 boost(`meta/communities.json` 未消费) |
| ✅ 一跳 expand_links(向前向后,max=10) | ❌ 时效衰减 / 冷藏过滤(`meta/access_log.json``meta/archived.json` 未消费) |
| ✅ min_score 过滤 + limit 截断 | ❌ 同 file 多 chunk 冗余(top-K 可全来自同节点) |
| ✅ chunk-level 命中(start_line / end_line) | ❌ 节点级 surface(frontmatter `name + description` 未与 chunk 命中合并展示) |
| ✅ 二跳 traverse 作为独立工具 | ❌ search 内 multi-hop expand(只一跳,跨术语关系到不了) |
| | ❌ query rewrite / multi-query(单一表达式漏召) |
**本文档的工作 = 设计这些缺口怎么填**,在 `search_step` / `traverse_step` 现有形态上增量。
---
## 1. 三种问法分立(继承 R-1)
```
┌─────────────┐ state 问 ──────► list_step + frontmatter filter
│ agent │ semantic 问 ──► search_step (本文档主要增强)
└─────────────┘ topological 问 ► traverse_step (小幅参数扩展)
```
| 问法 | 原子工具 | 本文档涉及 | 备注 |
|---|---|---|---|
| **state** | `list_step` / `daily_list_step` / `frontmatter_read_step` | 不涉及 | frontmatter 过滤无需维护信号 |
| **semantic** | `search_step` | **主战场**(§3-§7) | RRF fusion + 信号加权 + multi-hop + query rewrite |
| **topological** | `traverse_step` | 小幅(§8) | 起点选择可借助维护信号 |
**关键约束**(继承 `structure.md` ✗-8):**绝不合并三种问法成单一 read verb**。本文档增强 search_step,但不把 list / traverse 揉进 search;agent 按需各自调用。
---
## 2. 维护信号契约消费总览
`auto_consolidate_design.md` §11 列出维护产出。retrieve 端按以下方式读:
| 信号 | 来源 | 加载时机 | 缺失行为(降级) |
|---|---|---|---|
| **centrality** | `file_graph` 反向索引(实时) | search_step init 时引用 file_store | 总在线(file_graph 是核心组件) |
| **community** | `meta/communities.json` | search_step 启动 lazy load(LRU 缓存,文件 mtime 失效) | 缺失 → 不做同社区 boost |
| **recency** | `meta/access_log.json` | 同上 | 缺失 → recency_factor = 1.0 |
| **archived** | `meta/archived.json` | 同上 | 缺失 → 不过滤,所有节点参与 |
| **wikilink 图** | workspace 自身(file_graph) | 实时 | 总在线 |
| **frontmatter** | workspace 自身(`name` / `description`) | chunk 已带 metadata | 总在线 |
**version 校验**:`meta/*.json` 加载时检查 `version` 字段,与本文档约定的 schema 版本不匹配 → 走"该信号缺失"降级,日志告警(不崩)。
**新鲜度**:每个信号文件的 `computed_at` 暴露给调用者(metadata 中带 `signals_freshness`),调用方知道当前权重基于多久前的快照。超过阈值(默认 14 days)→ logger.warning + 仍使用(避免维护偶尔失效就拒绝服务)。
---
## 3. semantic 问法增强:打分公式
**目标**:把维护信号融入 fused chunk 的最终 score,让排序兼顾"文本相关 + 节点权威 + 同社区 + 时效"。
### 3.1 当前打分(基线)
```
score = RRF_fused(vector_rank, keyword_rank, vector_weight=0.7)
```
仅文本相似度。
### 3.2 新打分公式
```
final_score = base_score
× centrality_factor(path)
× community_factor(path, query_seed_paths)
× recency_factor(path)
```
| 因子 | 公式 | 默认参数 | 来源 |
|---|---|---|---|
| **base_score** | RRF 融合分(现状) | vector_weight=0.7 | search.py |
| **centrality_factor** | `1 + α · log(1 + inbound_count)` | α = 0.15 | file_graph 实时 |
| **community_factor** | 同 community 命中节点 → ×β,否则 1.0 | β = 1.20 | `meta/communities.json` |
| **recency_factor** | `exp(-Δt / τ)`,Δt = 距 last_hit_or_update | τ = 60 days | `meta/access_log.json` |
**为什么乘法而非加法**:
- 各因子量级不同(base_score ≤ 0.02,centrality 与 query 无关),加法需大量 normalization;乘法天然处理量级差
- 任一因子接近 0(极冷藏 / 极孤立)→ 整体压低,符合"弱信号一票否决"直觉
- 默认 α/β/τ 让 factor 落在 [0.5, 2.0] 区间,不会让 base_score 完全失声
**已排除**:LLM rerank。它是 query-time 多调一次 LLM,成本高,M0 不引入;留 M1+ 视 dogfooding 决定。
### 3.3 query_seed_paths 的角色
community_factor 需要"query 主关注的节点是哪些"才能判断同/异社区。做法:
1. RRF 融合后取 top-N(N=3)的 fused chunk 的 path 作 seed
2. 后续每个候选 chunk 的 path → 查它和任一 seed 是否同社区 → boost
3. 不需要 query 自身被映射到 community(query 是字符串,不在图里)
**边界**:N=3 是经验起点;N 太大会让"同社区"几乎等于"全召回"失去区分度。dogfooding 后调。
---
## 4. semantic 增强:节点级合并(unique_paths)
**问题(gap 5)**:fused 列表里 top-5 可能是同 file 的 5 个 chunk,信噪比退化。
**当前**:`expand_links` 已用 `unique_paths = list(dict.fromkeys(c.path for c in fused))`,但 fused 本身没去重,limit=5 仍可全是同节点。
**新方案**(节点级 dedupe + 节点级 surface):
```
fused (chunk-level) → group by path → 每组保留 top_chunks_per_path 个
→ 每组追加节点 frontmatter (name + description) 作"节点级 surface"
→ 再按节点 best_score 排序 → limit
```
| 参数 | 默认 | 含义 |
|---|---|---|
| `top_chunks_per_path` | 2 | 同节点最多保留多少 chunk |
| `surface_node` | true | 是否在每组前追加 frontmatter `name + description` |
**为什么**:
- 节点是 retrieve 的语义单位(`auto_dream_design.md` §2 路径即 ID),chunk 只是"展示窗口"
- frontmatter 是节点级摘要(name + description)—— 已是 dream 写入时认证过的信号,不召它浪费
- 同节点多 chunk 时,frontmatter + top-2 chunk 比 5 个 chunk 信息密度高
### 4.1 答案展示形态
```
========== digest/auth/jwt-rotation.md ==========
[node] JWT Key Rotation
Process for rotating JWT signing keys without downtime.
[score=0.0241 centrality=2.1 community=1.2 recency=0.91]
---------- chunk @5-23 ----------
<chunk text>
---------- chunk @45-60 ----------
<chunk text>
[expansion] 1 inbound, 2 outbound (...)
```
**对照旧形态**:每个 chunk 独立成块,无节点级 surface,scores 散在 chunk 头。新形态以**节点为视觉单位**,人 / agent 看到的第一眼是"哪个节点中了",而非"哪段文字中了"。
---
## 5. semantic 增强:multi-hop expand
**问题(gap 4)**:当前 expand_links 只展一跳,跨术语关系("分布式锁" → 一跳到"租约机制",再一跳才到"心跳协议")到不了。
**新方案**:expand_links 支持 `depth` 参数;默认仍 1(保守),agent / 配置可调到 2。
| 参数 | 默认 | 限制 |
|---|---|---|
| `expand_depth` | 1 | 最大 3(避免组合爆炸) |
| `max_links_per_direction` | 10(现状)| 每跳每方向上限,深度不展开时限到当跳总数 |
| `expand_path_budget` | 30 | 总扩展节点数硬上限,优先深度优先(深度浅但条数少) |
**为什么默认仍 1**:
- 二跳延迟不可忽略(N × 10 × 10 = 100 候选 IO)
- agent 需要"再深一层"时显式调 `traverse_step(depth=2)` —— 三种问法分立(R-1)
- 默认深拉会让"语义召回"变成"图召回",违背 R-1
**何时调 2**:dogfooding 发现 workspace 节点平均出度低 / 跨术语关系频繁 → 调到 2(改 search_step 配置,不改协议)。
---
## 6. semantic 增强:query rewrite / multi-query
**问题(gap 6)**:用户 query "JWT 怎么轮换" 可能错过 body 写"密钥定期更换"的节点(术语不同)。
**方案矩阵**:
| 方案 | 成本 | 效果 |
|---|---|---|
| **(a) 不做** | 0 | 漏召部分跨术语 |
| **(b) embedding 多 query**(用同 LLM 生成 N 个表述) | LLM 调用 1 次(query → N 表述)+ N 次 vector_search | 中等 |
| **(c) BM25 同义词扩展**(用静态词表 / 嵌入式词表) | 0(若有词表) | 弱(中文场景词表缺) |
| **(d) HyDE**(LLM 生成假设答案 → 嵌入这个答案而非 query) | LLM 1 次 | 高,文献证实 |
**首版决策**:**(a) 不做**。理由:
- workspace 本身规模 M0 不大,推断增加召回但增 LLM cost 不划算
- 维护阶段的 community 聚类已部分弥补"跨术语关系"(同社区 boost)
- 真要做,优先 (d) HyDE,延 M1+ 再启,实施只需加一层 query 预处理
**契约预留**:search_step kwargs 加 `query_rewrite: str | None`(默认 None;非 None 则用此重写代替原 query 做 vector_search,keyword_search 仍用原 query)。SDK 层可调用 LLM 生成重写后传入,reme 核心不强加 LLM 依赖。
---
## 7. semantic 增强:archived 过滤
**问题**:长期未访问的旧节点应该默认排除。
**方案**:search_step kwargs 加 `include_archived: bool`,默认 false。
```
fused → drop where path in archived_set → 后续打分 / unique_paths
```
**何时绕过**:
- agent 显式 `include_archived=true`(找历史 / debug)
- query 命中节点本身在 archived → boost 推回(冷节点突然被命中,说明不是真冷)
- **首版不做**,过滤即过滤;如有需要,M1+ 加"intent override"机制
**冷启动**(`meta/archived.json` 缺失)→ 不过滤,等同 `include_archived=true`
---
## 8. topological 问法的小增强
`traverse_step` 当前完整:BFS / 多 seed / direction / depth / per-edge 输出。本文档不重构,仅:
### 8.1 起点选择借助维护信号(可选 hint)
agent 调用 traverse 时往往不知道"哪个节点是该主题的中心";维护阶段产出的 centrality 可作 hint:
| 用例 | 做法 |
|---|---|
| traverse 给定 seed | 不变,直接 BFS |
| traverse 给定主题字符串(SDK 上层语法糖) | 先 search_step 找 top-1 → 用其作 seed → traverse depth=2 |
**位置**:这个组合在 SDK 上层做,不进 traverse_step;reme 核心保留 traverse 原子形态。
### 8.2 traverse 输出消费 archived
traverse_step 当前不知道 archived 信号。改造:加 `exclude_archived: bool` kwarg 默认 false(traverse 默认不过滤,因为它是图问法,过滤会破坏图视角)。SDK / agent 可显式开启。
---
## 9. retrieve 写访问日志(唯一对外写入)
**问题**:`meta/access_log.json``last_read` / `last_hit_count_30d` 谁写?
**约定**:retrieve 命中节点 → 异步 append 到访问日志缓冲区;由 maintain daily batch 聚合写入 `meta/access_log.json`
| 路径 | 实现 |
|---|---|
| **同步写**(每 query) | retrieve 把命中 path 写入内存 ring buffer(进程级)|
| **异步落盘** | 进程退出 / 维护 daily batch / 周期 flush(默认 10 min)|
| **聚合** | maintain 在 daily access_log 重算时:读 ring buffer + 上一份 access_log → 合并写新版 |
**幂等**:同 query 多次重读同节点不应放大 last_hit_count;ring buffer 按 (path, day) 去重,每天每节点最多记一次"被读"。
**降级**:ring buffer 写失败 / flush 失败 → 不影响 retrieve 返回,只是日志少一条;recency 信号略迟。
---
## 10. 不变量 / 边界
| # | 约束 | 含义 |
|---|---|---|
| **R-1**(继承)| 三种问法分立 | 不合并 list / search / traverse 成单一 verb |
| **R-2**(继承)| 默认 `digest > daily > resource`,可覆盖 | search_step 通过 `search_filter` 支持限层 |
| **R-3**(继承)| 拓扑问与层无关 | traverse 跨三层(I-4) |
| **R-4**(继承)| Provenance 默认 lazy | retrieve 不自动 traverse(R-4);expand_links 是性能优化非语义展开 |
| **Re-1**(本文档)| retrieve 不引入 L4 模块 | 增强限定在原子 step 内部 |
| **Re-2**(本文档)| retrieve 只读 workspace | 不改 body / frontmatter / 文件位置 |
| **Re-3**(本文档)| retrieve 唯一对外写入是 `meta/access_log.json` | 通过 ring buffer + maintain 聚合,不直接写 |
| **Re-4**(本文档)| 任一维护信号缺失 → 降级不崩 | `meta/*.json` 缺 → 跳过对应因子,系统始终可用 |
| **Re-5**(本文档)| version 不兼容 → 降级 + warning | 不阻断 retrieve |
---
## 11. 与其它文档的引用关系
| 引用 | 来源 |
|---|---|
| 三种问法 / R-1..R-5 | `structure.md` §4 |
| 没有 retriever 模块 | `structure.md` §7.4 |
| 节点 / 边 / wikilink 模型 | `auto_dream_design.md` §2 / §3 |
| 维护信号契约 | `auto_consolidate_design.md` §11 |
| centrality / community / recency / archived 输出 | `auto_consolidate_design.md` §3-§5 |
| 路径即 ID | `auto_dream_design.md` §2 |
---
## 12. 下一步
实现进入 `reme/steps/index/` 时,本文档与 `auto_cognition_design.md`(顶层)/ `auto_dream_design.md` / `auto_consolidate_design.md` 共同作为契约依据。
**search_step 增强(§3-§7)**:
- ⏳ **打分公式**:加 centrality_factor / community_factor / recency_factor;config 化 α / β / τ(§3)
- ⏳ **节点级合并 + surface**:group-by-path + frontmatter surface + top_chunks_per_path(§4)
- ⏳ **multi-hop expand**:`expand_links` 支持 depth 参数,加 `expand_path_budget` 硬上限(§5)
- ⏳ **query_rewrite kwarg**:契约预留,reme 核心不强加 LLM(§6)
- ⏳ **archived 过滤**:`include_archived` kwarg,默认 false(§7)
**traverse_step 增强(§8)**:
- ⏳ **`exclude_archived` kwarg**(默认 false)
**信号加载基础设施(§2)**:
- ⏳ **`meta/*.json` lazy loader + LRU 缓存 + mtime 失效**
- ⏳ **version 校验 + 降级路径 + warning logger**
- ⏳ **signals_freshness metadata 暴露**
**access log 写入路径(§9)**:
- ⏳ **进程级 ring buffer**(命中 path 异步 append)
- ⏳ **周期 flush + (path, day) 幂等**
- ⏳ **maintain daily 聚合接口**(读 ring → 合并旧 access_log → 写新版)
**性能与回归**:
- ⏳ **基准测试**:打分公式启用前后的 召回 P@5 / MRR(用合成 workspace + ground-truth query)
- ⏳ **延迟监控**:维护信号读取 + multi-hop expand 的 p50 / p95

View file

@ -1,166 +0,0 @@
ReMe新版本V4
@jinli
新版reme是一个自管理的个人知识库。
- **记忆分层:** → 记忆按"原始 → 加工"两层组织:`resource/`(原始素材)、`daily/`(日记事件)是只增不删的流水帐;`digest/` 是加工层,下分 `personal/`(个性化)、`knowledge/`(主题知识)、`procedural/`Agent 任务经验)、`proactive/`(主动洞察)四个固定子目录,写入策略和检索权重各有差异。
- **记忆的载体还是 Markdown** → 所有记忆都是 Obsidian 兼容的 .md 文件——YAML front matter、四种 wikilink`[[X]]` / `[[X#anchor]]` / `[[X|alias]]` / `![[X]]`、Dataview 风格 `predicate:: [[X]]` 语义关系全部沿用社区约定。用户可读、可备份、可迁移,对抗黑盒。
- **自我管理进化** → 不需要用户手工整理Agent 在后台自动对于原始素材进行整理和融合按照记忆的类型个性化、程序化、知识类进行分类整理并更新现有逻辑同时自动Build link让笔记自己长出结构。这一点把 ReMe 同时与"手动建图的 Obsidian"和"扁平存储的Mem0"拉开。
- **渐进式检索** → 自我管理进化的产出物不是一堆扁平笔记,而是一张可被**渐进式检索**消费的图:向量 + 关键词 + 图谱三路 RRF 融合,返回时通过 1-hop 邻居 meta 让 Agent"先看目录、再决定要不要展开正文",不像传统 RAG 那样一次性把 top-K 切片塞进上下文。
- **被集成而非内置(分发形态)** → ReMe 不做独立 Agent 产品,而是作为**能力**被任意 Harness 调用SDK 深度集成qwenpaw / AgentScope、MCP Tool + skill.md、CLI + skill.md 三条路径并行,记忆跟着用户走,不绑定任何上层框架。
1. 目标: 构建个人知识库集成qwenpaw等harness框架中实现知识/记忆的自进化和自管理结合graph高效搜索。
2. 新的特性:
- 支持多种记忆类型,包括个性化记忆、程序化记忆、知识类记忆
- [❌ 待补充] 当前 reme 中只有统一的 `FileNode/FileChunk` 抽象(`reme/schema/file_node.py``reme/schema/file_chunk.py`),尚未在代码层区分"个性化/程序化/知识类"三类记忆,需要在 schema 与 store 中扩展类型字段或子类。
- 支持memory-self-evolving
- [❌ 待补充] 没有发现自进化相关的 step/job 实现,目前只有基础的 search/reindex 等 common steps`reme/steps/common/`)。需要新增 auto-memory/auto-dream 等 step。
- 支持markdown之间的链接构建graph更好的渐进式展开
- [✅ 已实现 → `reme/components/file_chunker/markdown_file_chunker.py`wikilink 解析 + Dataview 谓词)、`reme/components/file_graph/`local/nx/neo4j 三种 graph 后端)]
- [✅ 已实现 → `reme/steps/common/search.py:109` `_expand_links``reme/config/default.yaml:86` `expand_links` 参数(搜索结果可附 outlinks/inlinks 邻居元数据)]
3. 工程实现:
1. components
- 支持backend切换
- [✅ 已实现 → `reme/components/component_registry.py``R.register(name)` 装饰器 + `R.get(ctype, backend)` 查找);`reme/application.py:51` 通过 `config.components` 中的 `backend` 字段动态构造]
- 生命周期管理 start/close
- [✅ 已实现 → `reme/components/base_component.py:151` `start()` / `:162` `close()` / `:172` `restart()`,含 `is_started` 幂等保护与 `asyncio.Lock`]
- components之间相互调用支持前序依赖还是啥
- [✅ 已实现 → `reme/components/base_component.py:78` `BaseComponent.bind()` 声明依赖(含 `optional``default_factory``:98` `_resolve_bindings()` 自动注入;`reme/application.py:80` `_topological_order()` Kahn 算法做拓扑排序、检测循环依赖]
2. job/step借鉴自github action
- step是最小的执行单元可以自由使用components不需要管理生命周期
- [✅ 已实现 → `reme/steps/base_step.py``reme/steps/common/`demo/health_check/help/reindex/search/version/stream_demo 等内置 step]
- job是steps的集合可以自由组合支持step复用
- [✅ 已实现 → `reme/components/job/base_job.py`(顺序执行 step`reme/components/job/stream_job.py`(流式 job`reme/config/default.yaml:5` 通过 yaml 声明 job→steps 组合]
- 对外job可以封装cli命令mcp_toolhttp服务接口等
- [✅ 已实现HTTP / MCP / CLI client`reme/components/service/http_service.py:35` `_add_job` 把 job 注册成 POST 端点;`reme/components/service/mcp_service.py``reme/components/client/http_client.py``reme/components/client/mcp_client.py``reme/reme.py:27` `main()` 通过 CLI 子命令 `start` / `find_reme` / `<job_name>` 调用 client]
3. application
- components的生命周期管理通过前序依赖构建拓扑图启动应用
- [✅ 已实现 → `reme/application.py:115` `_start()` 按拓扑顺序启动所有 component`:133` `_close()` 反序关闭]
- 集成run_job
- [✅ 已实现 → `reme/application.py:148` `run_job()` / `:154` `run_stream_job()`]
- 集成Service能力对外提供能力
- [✅ 已实现 → `reme/application.py:170` `run_app()` 调用 `service.run_app(app=self)``reme/components/service/base_service.py`]
4. 对外接口:
- skill.md + cli方案通用方案支持集成到各种harness框架中
- [⚠️ 部分实现] CLI 调用通道已具备(`reme/reme.py:17` `call_server()` 通过 `http_client` / `mcp_client` 调任意已注册 job但 [❌ 待补充] 仓库内未发现 `skill.md` 文件,需要为 Claude Code / 其它 harness 编写 skill 描述文件。
- 可以选择agent来启动reme服务后台
- [❌ 待补充] 未见"由 agent 自动拉起后台 reme 服务"的脚本/约定,需要补充进程托管或 launchctl/systemd 集成方案。
- skill.md + mcp-tool方案通用方案
- [⚠️ 部分实现] MCP 服务通道存在(`reme/components/service/mcp_service.py``reme/components/client/mcp_client.py`),但 [❌ 待补充] 同样缺 `skill.md` 模板。
- 需要手动启动mcp服务
- [✅ 已实现 → `reme service` 模式可通过 `reme/config/default.yaml:1` `service.backend: mcp` 切换,`reme/reme.py` `start` 子命令拉起]
- sdk集成qwenpaw集成
- [❌ 待补充] reme 内未见 qwenpaw / agentscope 相关适配代码(仅 `reme/``reme_ai/` 旧版有部分逻辑,但已废弃,按记忆 [[feedback_deprecated_directories]] 不应改动)。需要新建 `reme/integrations/qwenpaw/` 之类的模块。
- str + 封装AgentscopeTools
- [❌ 待补充] 没有 `AgentscopeTools` 包装层。
- 集成auto-memory、auto-dream、auto-memory-search的能力
- [❌ 待补充] 三个能力均未实现。
4. 记忆存储方案:
- resource原始对话日志上传的文件原始的html文件等
- [❌ 待补充] `reme/application.py:20` 仅创建 `metadata_dir` / `daily_dir` / `knowledge_dir`,未见 `resource_dir` 概念;需要在 `ApplicationConfig` 中加入并落地相应目录与抓取/上传逻辑。
- daily
- daily/YYYYMMDD.md主Agent调用write/edit工具修改兼容上一版同时承担了当天其他md的索引
- [⚠️ 部分实现] `reme/application.py:23` 已建 `daily_dir`,但目录内 markdown 的"主索引"约定与 write/edit 兼容协议无显式实现,主要靠主 agent 自身行为。需要文档化 + 校验。
- daily/YYYYMMDD/{event}.md auto-memory 针对上下文对话拆分成不同的事件存储同时在YYYYMMDD.md构建好索引可以链接过来
- [❌ 待补充] auto-memory 拆事件的 step / job 不存在。
- knowledge:
- knowledge/{topic:-personal/agent/financial/work...}/{xxx}.md 在空闲时间整理记忆,按照主题和事件进行分类存储
- [⚠️ 部分实现] `knowledge_dir` 已建(`reme/application.py:24`),但"按主题/事件整理"的后台任务、topic 枚举均缺失。
- proactive:
- proactive/YYYYMMDD.md 待定。如果存在给用户主动推送的能力这里可以记录每一天agent给用户推荐的分析和心路历程。
- [❌ 待补充] 主动推送/proactive 目录与逻辑均未实现。
5. Markdown 格式 & Build Graph
1. obsidian格式的Markdown文件格式
- front matter格式
- [✅ 已实现 → `reme/components/file_chunker/markdown_file_chunker.py:313` `frontmatter.loads(...)``reme/schema/file_front_matter.py`]
- file link格式 4种格式
- [⚠️ 部分实现] `markdown_file_chunker.py:88` `_WIKILINK_RE` 已支持 `[[target]]` / `[[target#anchor]]` / `[[target|alias]]` / `![[target]]`(嵌入),并支持 Dataview `predicate:: [[X]]` 与 inline `[predicate:: [[X]]]`。但 [❌ 待补充] 标准 Markdown `[text](url.md)` 链接尚未被解析为 graph 边。
2. 更好的文件chunking机制
- 旧版 类似rag 带overlap的chunking机制
- [📌 历史] V3 旧逻辑,对照说明用,无需在 reme 中实现。
- 解析 Markdown Ast
- [✅ 已实现 → `markdown_file_chunker.py:308` 使用 `mistletoe``Document`/`MarkdownRenderer``:335` `_build_tree` 把扁平 children 折叠成 section 嵌套树(`MdNode`]
- 每一个chunk都带全部标题
- [✅ 已实现 → `markdown_file_chunker.py:381` `_chunk_node``before` 累积已经过的标题、`after` 拼剩余 desc_toc`:712` `_make_chunk``_toc_join(before, content, after)` 把全文目录骨架前后包裹]
3. 通过link构建graph索引同时构建反向link索引
- [✅ 已实现 → `reme/components/file_graph/base_file_graph.py``reme/components/file_graph/local_file_graph.py`(含 `get_outlinks``get_inlinks` 双向索引nx/neo4j 后端同 API`reme/steps/common/search.py:114-129` 使用双向 link]
4. link的生成有两种一种是主agent在生成link另一种是通过后台任务自动构建文档之间的link
- 介绍如何auto-link
- [⚠️ 部分实现] 主 agent 显式写 `[[link]]` 已经会被 parser 抓为边(`markdown_file_chunker.py:152` `_extract_links`)。但 [❌ 待补充] "后台任务自动补 link" 的实现(实体抽取 / 候选文档相似度匹配 / link 写回 markdown尚不存在需要单独的 step/job。
6. 如何做memory自进化
Auto-memory
auto-dream
- [❌ 待补充] reme 没有 auto-memory / auto-dream 任何代码。需要:
- 新增 step`reme/steps/auto_memory.py``reme/steps/auto_dream.py`),基于现有 `BaseStep` + LLM component
- 设计触发机制job 调度、空闲检测);
- 与上面的 daily/knowledge 目录约定打通。
7. 更好的检索:
- 渐进式展开的检索
- [⚠️ 部分实现] `reme/steps/common/search.py:14` `SearchStep` 已做 vector + keyword 的 RRF 融合,并支持 `expand_links` 一跳展开outlinks/inlinks + 邻居 meta。但 [❌ 待补充] "多跳渐进展开"、"按需要由 agent 主动展开下一层"的交互式 API 尚未实现。
8. 结合外部的Agent工具
ReMe更加专注于知识加工而不是知识获取
- 结合qwenpaw
- sdk集成qwenpaw集成
- [❌ 待补充] 见 §3.4。
- str + 封装AgentscopeTools
- [❌ 待补充] 同上。
- 集成auto-memory、auto-dream、auto-memory-search的能力
- [❌ 待补充] 同上。
- 结合其他的Agent框架
- skill.md + cli方案通用方案支持集成到各种harness框架中
- 可以选择agent来启动reme服务后台
- [❌ 待补充] 同 §3.4。
- skill.md + mcp-tool方案通用方案
- 需要手动启动mcp服务
- [⚠️ 部分实现] MCP 服务可启动,但 skill.md 缺失。
## 更好的性能,更稳定和兼容
V4更加高效的底层记忆索引
- V3版本基于sqlite/chroma等本地数据库
- 在qwenpaw等低版本linux & win系统存在兼容性问题会存在core dump等问题
- 不支持关键词检索这里需要Keyword倒排索引对中文的支持较差
- [📌 历史] 描述 V3 痛点,不需要代码。
- V4版本我们重写了file parserfile storefile graphfile watcher手写了支持增量更新倒排索引
- file parser → [✅ `reme/components/file_chunker/`base/default/chunked/linked 四种)]
- file store → [✅ `reme/components/file_store/local_file_store.py`]
- file graph → [✅ `reme/components/file_graph/`local/nx/neo4j]
- file watcher → [✅ `reme/components/file_watcher/lite_file_watcher.py` 基于 watchfiles awatch`base_file_watcher.py` 抽象接口]
- 增量倒排索引 → [✅ `reme/components/keyword_index/bm25_index.py`(增量 BM25`reme/components/tokenizer/`regex / jieba 两种 tokenizerjieba 含 stopwords 子目录)]
- 未来可以使用rust/c++重写,高性能本地知识引擎
- [📌 规划]
## 知识库应用场景(重点)
### 金融
产业链
- [❌ 待补充] 没有领域 schema / 产业链知识图谱样例,需要写 demo 数据集 + topic 配置。
### 自己的工作&生活
xxxx
- [❌ 待补充] 文档本身就是占位,需要补充具体场景描述与对应的 daily/knowledge 目录样例。
---
## 标注小结
### ✅ 已经在 `reme/` 中实现的能力
1. **组件框架**backend 注册(`component_registry.py`)、生命周期(`base_component.py`)、依赖声明 + 拓扑启动(`application.py:80`)。
2. **Job/Step 体系**`components/job/base_job.py``components/job/stream_job.py``steps/base_step.py``steps/common/*`
3. **服务/客户端**HTTP`service/http_service.py` + `client/http_client.py`、MCP`service/mcp_service.py` + `client/mcp_client.py`CLI 入口 `reme.py:main`
4. **Markdown 解析**`file_chunker/markdown_file_chunker.py`,含 frontmatter、wikilink + Dataview 谓词、AST 树、带全标题骨架的 chunking。
5. **Graph**`file_graph/{local,nx,neo4j}_file_graph.py`,双向链接索引。
6. **存储 / 索引**`file_store/local_file_store.py` + `keyword_index/bm25_index.py`(增量 BM25+ `tokenizer/{regex,jieba}_tokenizer.py`
7. **文件监听**`file_watcher/lite_file_watcher.py`watchfiles 轮询)。
8. **混合检索 + 一跳展开**`steps/common/search.py`vector + keyword RRF 融合,可附 outlinks/inlinks
9. **Embedding / LLM 适配壳**`components/embedding/openai_embedding_model.py``components/as_llm/``components/as_llm_formatter/``components/as_token_counter/`
### ❌ 需要额外补充的能力
1. **记忆类型分层**:个性化 / 程序化 / 知识类的 schema 与路由。
2. **memory-self-evolving**auto-memory拆事件→ daily/YYYYMMDD/{event}.md、auto-dream空闲整理→ knowledge/{topic}/)、对应触发器与调度。
3. **存储目录约定**`resource/``proactive/` 目录、daily 主索引协议、knowledge topic 枚举均未落地。
4. **auto-link 后台任务**:自动从正文挖出实体并写回 wikilink。
5. **多跳渐进展开检索 API**:当前只能一跳。
6. **标准 Markdown `[text](url.md)` 链接**:尚未纳入 graph 边解析。
7. **skill.md 模板**CLI 与 MCP 两种集成方式都缺 skill 描述文件。
8. **Agent 拉起后台 reme 服务**:缺脚本/约定。
9. **qwenpaw / AgentScope SDK 集成**:包括 `AgentscopeTools` 包装层与 auto-memory/dream/search 暴露。
10. **应用场景样例**:金融产业链、个人工作&生活的 demo 数据 + topic 配置。

View file

@ -1,192 +0,0 @@
# 快速测试
```bash
# 终端 A启动服务
reme start
# 终端 B调用 version 验证服务可用
reme version
# 预期输出:✅ ReMe v{__version__}
```
# 基础Job
@jinli
入口:`reme/reme.py::main()``parse_args(*sys.argv[1:])` 解析首个位置参数为 `action`,后续 `key=value` 解析为 kwargs支持
`service.port=8080` 的 dot notation自动剥离 `--` / `-` 前缀;值会做 bool / int / float / JSON 转换)。
调用模式:
- `start`:本地启动 `ReMe(Application)` 服务(不经过 client
- `find_reme`:本地探测正在运行的 reme不调用服务
- `list`:在 client 端拦截,不转发到服务端,直接返回 action 目录
- 其他 action通过 `call_server(action, **kwargs)``R.get(ComponentEnum.CLIENT, backend)` 实例化客户端并流式打印(任意未列出的
step register name 都按本规则透传)
通用可选参数 `backend:str=http`(取值 `http` / `mcp`,对应 `reme/components/client/{http_client,mcp_client}.py`
`@R.register` 注册名);服务端默认 host/port 见 `reme/constants.py`,可由 `start` 端通过 `service.host=` / `service.port=`
覆盖。
说明:📥 输入参数 📤 输出 ⭐ 必填 🎚️ 默认值 🛠️ 内部行为 📊 metadata
| 分类 | 指令 (register name) | 入口 | 参数 & 行为 |
|------------|--------------------------------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 🚀 本地 | 🟢 `start` | `reme.py:30``ReMe(**kwargs).run_app()` | 📥 可选 `config=<name\|path>`(默认加载 `reme/config/default.yaml``.yaml/.yml/.json` 都支持,含 `${ENV:-default}` 占位符)| 可选 `service.host=` / `service.port=` 等任意 dot-notation 覆盖 🛠️ 流程:`load_env()``resolve_app_config(**kwargs)` deep merge → `precheck_start(svc)``utils/service_utils.py:72`:目标 host:port 已有 reme → 打印 `reme already running ...` 直接返回;端口被其他进程占用 → stderr 提示 `port {port} occupied. Start on another port: reme start service.port=<other_port>``sys.exit(1)`)→ 启动服务 |
| 🚀 本地 | 🧭 `find_reme` | `reme.py:36``utils/service_utils.py:89` | 📥 无 📤 发现服务则 stdout 打印 `HOST={host} PORT={port} PID={pid or 'unknown'}`;未发现则 stderr 提示 `reme not started. Try: reme start``sys.exit(1)` 🛠️ 流程:先探 `REME_DEFAULT_HOST:REME_DEFAULT_PORT``health_check` 命中算 `reme`),再 `pgrep -af "reme.* start"` 扫描其他端口 |
| 🛰️ 客户端 | 📜 `list` | `components/client/base_client.py:36` | 📥 无 📤 服务端可用 action 目录JSON`indent=2 ensure_ascii=False` 🛠️ 在 `BaseClient.__call__` 中拦截,不进入 `_execute`,直接调用 `list_actions()`HTTP/MCP backend 各自实现) |
| 🌐 通用 step | 🆘 `help` (`help_step`) | `call_server("help")` | 📥 无 📤 `answer` 一行一个 job`🛠️ \`{name}\` — {description} 📥 {params}`,参数渲染为 `name:type*`(必填) / `name:type={default}` / `name:type` 📊 `metadata.job_count` 🛠️ 自动跳过名为 `help` 的 job |
| 🌐 通用 step | 🩺 `health_check` (`health_check_step`) | `call_server("health_check")` | 📥 无 📤 `answer = "✅/❌ ReMe v{version} - healthy/unhealthy"` 📊 `metadata.health = {version, healthy, components}` 🧩 覆盖组件:`embedding_model`(🟢 is_started/is_healthy/model_name/dimensions/cache_size/memory) · `file_graph`(🕸️ n_nodes/n_edges/n_virtual\|n_pending/memory) · `file_store`(📦 n_chunks/n_chunks_with_embedding/memory) · `file_watcher`(👀 background_running/watch_paths) · `keyword_index`(🔤 n_docs/vocab_size/memory) 🛠️ deep sizeof含 numpy.nbytes未启动 / 后台未跑 / embedding 不健康 → ❌ |
| 🌐 通用 step | 🏷️ `version` (`version_step`) | `call_server("version")` | 📥 无 📤 `answer = reme.__version__` 📊 `metadata.version` |
| 🌐 通用 step | 🔄 `reindex` (`reindex_step`) | `call_server("reindex")` | 📥 无 📤 `answer = "🔄 Reindexed {added} file(s)"` 📊 `metadata.counts = {added, ...}` 🛠️ 流程:`file_watcher.close()``file_store.clear()``file_watcher.update_store()``file_watcher.start()`finally 保证重启) |
| 🔎 search | 🔍 `search` (`search_step`) | `call_server("search", query=…, …)` | 📥 `query:str` 🎚️ `limit:int=5`(>0) 🎚️ `min_score:float=0.0` ⚖️ `vector_weight:float=0.7` ∈[0,1]keyword 权 = 1-vw 🔀 `candidate_multiplier:float=3.0`candidates = min(200, limit×mult) 🔗 `expand_links:bool=True` 🔢 `max_links_per_direction:int=10` 🎚️ `search_filter:dict={}` 📤 `answer` 每命中一行 `path:start-end [score=… vector=… keyword=…] text` + 缩进的 `→ outlinks (n)` / `← inlinks (n)` + `via predicate=… anchor=#…` 📊 `metadata.results` / `metadata.link_expansion` / `metadata.counts={vector,keyword,returned,hybrid}` 🛠️ 并行 `vector_search` + `keyword_search` → RRF 融合K=60按 chunk.id 合并)→ `min_score` 过滤 → `limit` 截断 → 邻居 meta 注入 |
| 🧪 demo | 🪄 `demo_echo` (`demo_echo_step1` + `step2`) | `call_server("demo_echo", query=…, min_score=…)` | 📥 `query:str=""` 🎚️ `min_score:float=0.5` 🛠️ step1`processed_query = query.strip().lower()``adjusted_min_score = min_score * 0.9`,写回 context 📤 step2`answer = "echo: {processed_query} (min_score={adjusted_min_score})"` 📊 `metadata = {step, query, min_score, processed_query, adjusted_min_score}` |
| 🌊 demo | 🌊 `stream_demo` (`stream_demo_step1` + `step2`) | `call_server("stream_demo", query=…, repeat=…, interval=…)` | 📥 `query:str=""` 🎚️ `repeat:int=10` 🎚️ `interval:float=0.1`(秒/字符)| 🛠️ step1`stream_text = query * repeat` 写回 context 📤 step2按字符 `add_stream_string(ch, ChunkEnum.CONTENT)` 流式输出,`asyncio.sleep(interval)` 节流 |
| 📂 crud | 📖 `read` (`read_step`) | `call_server("read", path=…, …)` | 📥 `path:str` ⭐(**完整相对路径**,相对于 workspace绝对路径会被拒绝`.md` 后缀拒绝)| 🎚️ `start_line:int=null`1-based, 含端点)| 🎚️ `end_line:int=null`1-based, 含端点)| 🎚️ `max_bytes:int=51200`(截断阈值)| 📤 `answer = 选中的行内容`,超过 `max_bytes` 时附加 `--- TRUNCATED ---` 续读指引(`start_line=…` 📊 `metadata.path` / `metadata.total_lines`(出错路径才会附带)| 🛠️ 流程:`BaseStep.resolve_path(raw, require_md=True)``aiofiles.os.stat``read_file_safe`utf-8-sig BOM 容忍、UnicodeDecodeError fallback `errors=ignore`)→ `split("\n")` 切片 `[s-1:e]``truncate_text_output` 按字节截断保行 |
使用示例:
```bash
# 启动(默认 default.yaml
reme start
# 指定 config 与服务端口
reme start config=paw.yaml service.port=8181
# 查找在跑的 reme
reme find_reme
# HOST=127.0.0.1 PORT=8000 PID=12345
# 列出所有可用 actionclient 端处理,不转服务端)
reme list
# 转发到服务端的 step所有 key=value 透传为 step kwargs
reme help
reme health_check
reme version
reme reindex
reme search query="latency 问题" limit=10 min_score=0.2 vector_weight=0.6
# 读取 workspace 下的 markdown完整相对路径无后缀自动补 .md可按行切片或限制字节
reme read path=Templates/Recipe.md
reme read path=Notes start_line=1 end_line=20
reme read path=Big.md max_bytes=4096
# 通过 MCP backend 调用
reme search query="..." backend=mcp
```
@sen
| file | upload/download/move/delete/stat/list | 文件操作CRUD |
| property | read/update/delete | frontmatter CRUD | |
| graph | traverse/retarget | path="My Note" directtion=forward/backward depth=1 predicat=xxx |
@wangce
| crud | write | path="New Note" name="xxx" description="xxx" metadata={}, content="# Hello" (4 字段都必填frontmatter 只写 name/description) |
| crud | read | path="Templates/Recipe.md" |
| crud | edit | path="Templates/Recipe.md" old="xxx" new="xxx" |
| crud | append | path="My Note" content="New line" |
| crud | delete | path="My Note
| daily_crud | daily_xxx | 与 crud 参数保持一致 |
- daily_resolve name=xxxx (符合一定规范 win下要求)
- daily_list date=xxxx 返回path
- daily_index
frontmatter read path
frontmatter update path metadata={}
frontmatter delete path keys=[]
delete path
download path=xxx内部相对路径download_path=(外部绝对路径,可选)
upload path=xxx外部绝对路径description="xxx" metadata=xxx 返回内部相对路径 加metadata
stat path
list path
mv path=xxx new_path=xxx
traverse path=xxx direction=xxx depth=xxx
# 日记类型
| 类型 | 路径 | 说明 |
|-----------|-----------------------------------------------|-----------------------------|
| daily | {daily}/xxxx-mm-dd.md + xxxx-mm-dd/{event}.md | 按日期归档的原始信息记录 |
| topic | topic/{topic:-personal(agent)}/{xxxx}.md | 按主题聚类的二次加工内容 |
| proactive | todo | 基于 daily / topic 思考后主动推送的消息 |
# 生成Job
| 任务 | 输入 | 输出 | 触发时机 | 说明 |
|-------------------------|---------------|-----------------------------------------------|-----------------------------|------------------------------------------------------|
| 日记summary @sen @wangce | msg | {daily}/xxxx-mm-dd.md + xxxx-mm-dd/{event}.md | freq (every_n_turn、compact) | 把 msg 的信息写入 daily 目录 |
| 主题dream + 生成链接 @sen | daily/xxx | knowledge/xxx | /dream | 把 daily 目录的内容按主题聚类合并到 topic 目录, 主动在文档中建立 [[link]] 关联 |
| 主动proactive @wangce | daily / topic | proactive_query | pre_query | 思考 daily / topic 信息,主动决定推送给用户的消息 |
2. file_chunker
a. 抽象基类 parse: @jinli
. 输入是path相对路径
ⅱ. 输出是FileMetadata & list[FileChunks] & list[FileEdge]
b. default parser 兼容老方案 @jinli
. 带overlap的chunking策略 不输出FileEdge
c. markdown parser @sen
. 根据markdown ast做chunk不需要overlap
ⅱ. 增加一个索引的chunk chunk_type @锦鲤 file_chunk_type content/index
ⅲ. 增加link的正则解析predicate:: [[path#anchor]]
3. file_store @sen
a. 抽象存储:
. filenode = file + path + st_mtime + metadata + list[FileEdge]
ⅱ. graph=dict[str, filenode] 内存+json
ⅲ. list[FileChunk] 存db
b. 抽象基类
. graphfellow dict的操作 update/get/set
ⅱ. chunks dict[str, list[chunk]]
1. delete_chunks_by_path
2. update_chunks_by_path
3. list_chunks_by_path
4. vector_search/keyword_search
ⅲ. 手写一个bm25检索
ⅳ. 【核心】检索机制 vector bm25 graph 如何进行融合
4. file_watcher @jinli
a. 抽象基类
. on_start:
1. file_store 的start 在前加载graphfile_watcher在后递归扫描目录
a. 通过ms_time对比graphon_change 进行改动
ⅱ. on_change:
1. 更新/增加:
a. delete_chunks_by_path 更新数据库
b. upate_chunks_by_path 更新数据库
c. 更新graph
2. 删除
a. delete_chunks_by_path 更新数据库
MemorySchema
1. markdown文件结构 @sen
a. formatter
. name
ⅱ. desc
2. memory文件结构目录
a. MEMORY.md
b. msg/files -> daily/YYYYMMDD/YYYYMMDD.md + xxxx.md
. YYYYMMDD.md
1. xxx -> xxxx.md
2. xxx -> xxxd.md
ⅱ.
c. daily -> topic/topic_l1/topic_l1.md + xxx.md + topic_l2
d. proactive
steps:
1. 治理(算法+LLM
a. 节点关联P0现有的链接做补充挖掘新的LLM的link
. /Users/yuli/workspace/ReMe/reme2/component/edge_extractor/llm_edge_extractor.py
ⅱ. 移动到steps
b. 节点整合/节点拆分/节点归档
c. 健康度检查
2. retrieve 调用store的检索
3. 原子stepsreme edit
4. 组合steps总结
a. - freq (every_n_turn、compact) -> daily_summarizer
b. topic (/dream ) -> topic_summarizer(daily_xx -> topic_xx)
c. proactive -> proactive_summarizer(personal_xxx -> proactive_query - pre_query

View file

@ -1,486 +0,0 @@
# ReMe 设计文档
> 本文按 `reme/` 目录最新代码整理,重点描述当前实现,而不是历史设想。
## 整体定位
一句话总结:**面向 Agent 的、文件优先的自进化记忆系统**。
ReMe 把记忆落在一个可读、可编辑、可复制的 workspace 目录里,用 Markdown、front matter、wikilink、BM25 倒排索引和后台 Agent 管线,把原始材料逐步沉淀为可检索、可追溯、可演化的长期记忆。
核心原则:
- **文件即记忆**:长期状态主要是 workspace 下的文件和 `reme_metadata/` 中的索引快照。
- **Agent 可操作**:所有能力通过 Job 暴露Agent 可以用 HTTP、MCP 或 Python 直接调用。
- **渐进加工**:对话和资源先进入 `daily/`,再由 `auto_dream` 提炼到 `digest/`
- **Obsidian 兼容**Markdown、YAML front matter、`[[wikilink]]`、Dataview 风格属性都按文本文件保存。
## 1. Workspace 与记忆分层
默认目录来自 `ApplicationConfig`
```text
<workspace_dir>/
reme_metadata/ # ReMe 索引、图谱、catalog 等持久状态
reme_session/ # Agent session 与原始对话
dialog/
<session_id>.jsonl # auto_memory 保存的对话消息
agentscope/ # AgentScope wrapper session
claude_code/ # Claude Code wrapper session
resource/ # 外部原始材料
YYYY-MM-DD/
<resource>.<ext>
daily/ # 浅加工记忆
YYYY-MM-DD.md # 当天索引页
YYYY-MM-DD/
<session_id>.md # 对话或资源加工后的 daily note
interests.yaml # auto_dream 产出的主动兴趣主题
digest/ # 深加工记忆
personal/
procedure/
wiki/
```
分层含义:
| 层级 | 内容 | 主要写入方 | 说明 |
| --- | --- | --- | --- |
| `resource/` | 原始文本材料 | 手动、外部同步 | 当前 `auto_resource` 支持文本类资源读取:`md/txt/json/jsonl/csv/yaml/html` |
| `reme_session/dialog/` | 原始对话 JSONL | `auto_memory` | 对话消息按 `session_id` 去重、合并、持久化,并在 daily note front matter 中溯源 |
| `daily/` | 日记、资源解读、当天索引、兴趣主题 | `daily_create``auto_memory``auto_resource``auto_dream` | 浅加工层,保留当天发生的事实和材料 |
| `digest/personal/` | 用户画像、偏好、长期个人事实 | `auto_dream` | 深加工记忆桶之一 |
| `digest/procedure/` | 方法论、流程、操作经验 | `auto_dream` | 深加工记忆桶之一 |
| `digest/wiki/` | 通用知识、概念、决策先例 | `auto_dream` | 深加工记忆桶之一 |
启动时 `Application` 会确保 workspace 根目录和上述主要子目录存在。
## 2. Markdown 与图谱格式
### 2.1 Front Matter
Markdown 文件可带 YAML front matter
```markdown
---
name: 光伏产业链研究
description: 从硅料到组件的全链条梳理
tags: [新能源, 光伏, 产业链]
---
```
当前 `FileFrontMatter` 约定 `name``description` 等字段;写入类 Job 会保留并合并 metadata。索引时front matter 会进入 `FileNode.front_matter`,供 `node_search`、图展开和 Agent 判断使用。
### 2.2 Wikilink
`WikilinkHandler` 是系统唯一的 wikilink 解析和改写入口。支持:
| 写法 | 示例 | 含义 |
| --- | --- | --- |
| 标准链接 | `[[digest/wiki/光伏.md]]` | 指向 workspace-relative 目标 |
| 锚点链接 | `[[digest/wiki/钴.md#应用]]` | 指向目标章节 |
| 别名链接 | `[[digest/wiki/宁德时代.md\|宁德]]` | 显示别名,目标不变 |
| 嵌入引用 | `![[resource/2026-06-01/report.md]]` | 作为 wikilink 记录边 |
| 行级属性 | `industry:: [[digest/wiki/新能源.md]]` | 提取 predicate |
| 内联属性 | `[competitor:: [[digest/wiki/比亚迪.md]]]` | 提取 predicate |
当前实现采取**字面路径语义**`[[X]]` 的 target 就是 `X`,不会自动补 `.md`,不会做 basename 搜索,也不会做 folder note 解析。推荐使用带扩展名的 workspace-relative 路径。
### 2.3 图谱边
Markdown chunker 会从正文提取 `FileLink`
```text
source_path # 源文件
target_path # wikilink 里的字面目标
target_anchor # # 后的锚点,可为空
predicate # Dataview 风格关系名,可为空
```
`file_graph` 维护:
- 节点:`FileNode(path, st_mtime, links, chunk_ids, front_matter)`
- 正向边:文件里的 outlinks
- 反向边:谁指向当前节点
- pending 边:目标文件暂不存在时先保留为 virtual link目标出现后自动提升为 real link
`move` 默认会调用 `WikilinkHandler.retarget_links`,把入边来源文件中的 `[[src]]` 字面链接改写为 `[[dst]]``delete` 会返回仍然存在的入边,提示调用方清理引用。
## 3. 语义分块与索引
### 3.1 Markdown AST 分块
`MarkdownFileChunker` 使用 `mistletoe` 构建 Markdown AST再按标题层级折叠成树
```text
Document AST
-> MdNode root
-> section H1
-> body paragraph/list/table/code
-> section H2
```
分块策略:
- 按 H1/H2/H3 等章节递归分块。
- 每个 chunk 默认包含完整标题骨架,检索命中后能看到片段在文档中的位置。
- 表格拆分时重复表头和分隔行。
- 代码块拆分时重复 fence opener/closer。
- 列表按 item 打包。
- 过长叶子节点按行或内部单元拆分,并加 `[Part X/N]`
- `chunk_chars` 默认 10000`embed_toc` 默认开启。
`DefaultFileChunker` 用于非 Markdown 的默认文本切块,默认配置中主要覆盖 `jsonl`
### 3.2 FileStore 组合
`LocalFileStore` 是当前默认文件索引协调层,组合:
| 子组件 | 默认后端 | 功能 |
| --- | --- | --- |
| `file_graph` | `local` | 节点、wikilink 正反向图谱 |
| `keyword_index` | `bm25` | BM25 全文检索 |
默认 `reme/config/default.yaml` 中:
```yaml
file_store:
default:
backend: local
keyword_index: default
file_graph: default
```
因此最新默认行为是:**BM25 + 图谱**。
### 3.3 BM25 Index
`BM25Index` 是 numpy 实现的倒排索引:
- tokenizer 默认是 `regex`
- 文档级 lazy delete更新时先退休旧 doc slot再追加新 slot。
- 持久化到 `reme_metadata/keyword_index/bm25_<name>_<tokenizer>_<fingerprint>_v1.pkl`
- tokenizer 配置和 stopwords 指纹进入索引文件名,避免不同分词配置复用错误索引。
### 3.4 Search
`search` Job 当前实现:
1. 读取 query、limit、min_score、search_filter。
2. 默认配置下执行 `keyword_search`,返回 BM25 命中的 chunk。
3. 按 `min_score` 过滤并截断到 limit。
4. 对命中的唯一 path 做 link expansion默认每个方向最多 10 条。
5. 返回 chunk 正文、行号、分数和出入链目录。
### 3.5 Node Search
`node_search` 是给 `auto_dream` Phase 2 使用的专用召回:
- 只返回 `digest/` 下节点。
- 以 path 聚合 chunk 结果,一篇 digest 只返回一行。
- 返回 path、score、front matter 中的 name/description。
- 不返回正文,不做 link expansion。
- 供集成 Agent 判断是 CREATE、CORROBORATE、REFINE 还是 CORRECT。
外部问答 Agent 应使用 `search`dream 集成应使用 `node_search`
## 4. 自进化管线
### 4.1 Auto Memory
`auto_memory` 输入对话 messages 和可选 `session_id`
1. 把 messages 标准化为 AgentScope `Msg`
2. 如有 `session_id`,保存到 `reme_session/dialog/<session_id>.jsonl`
3. 调用 `daily_create` 创建或复用 `daily/<date>/<session_id>.md`,空 session 时使用 `daily/<date>.md`
4. 通过 `agent_wrapper` 调用 LLM Agent工具集为 `read``edit``frontmatter_update``write`
5. 如果有 `session_id`,在 note front matter 写入 `source_conversation: [[reme_session/dialog/<session_id>.jsonl]]`
6. 刷新当天索引页 `daily/<date>.md`
保存对话时会去掉 base64 数据块,并截断超长 tool result避免 session JSONL 过大。
### 4.2 Auto Resource
`auto_resource` 处理 `resource/` 下的变更批次。默认后台 `resource_watch_loop` 监听:
```yaml
watch_dirs: [resource_dir]
watch_suffixes: [md, txt, json, jsonl, csv, yaml, html]
```
资源路径约定为:
```text
resource/YYYY-MM-DD/<filename>
```
处理逻辑:
- `added/modified`:读取原始资源文本,创建或更新 `daily/YYYY-MM-DD/<resource_stem>.md`,再由 Agent 解读资源内容并写入 daily note。
- `deleted`:删除对应 daily note更新 file_store并刷新当天索引页。
- Agent session id 使用资源路径的 UUID5保证同一资源重复处理时会话稳定。
### 4.3 Auto Dream
`auto_dream` 是最新代码中的四步 Job
```yaml
auto_dream:
steps:
- dream_extract_step
- dream_integrate_step
- dream_topics_step
- dream_finish_step
```
它的目标是扫描某天 daily 输入,把值得长期保留的抽象记忆写入 `digest/`,同时生成当天的 `interests.yaml`
#### Phase 1: Extract
`dream_extract_step`
- 刷新当天索引页。
- 扫描 `daily/<date>.md``daily/<date>/` 下文件,但排除 `interests.yaml`
- 用 `file_catalog:dream` 对比 mtime只处理 changed paths。
- 如果没有变化,直接结束。
- 调用 Agent 读取 changed material输出
- `units`: 需要进入 digest 的抽象记忆单元。
- `topics`: 主动兴趣主题候选。
- unit bucket 限定为 `procedure``personal``wiki`,未知 bucket 会路由到 `wiki`
#### Phase 2: Integrate
`dream_integrate_step` 对每个 unit 独立调用 Agent
- Agent 可用工具:`node_search``read``frontmatter_read``write``edit``frontmatter_update`
- 先召回 digest 中可能相同或相关的节点。
- 决策结果是结构化 `IntegrateOutcome`
| action | 含义 |
| --- | --- |
| `CREATE` | 新建 digest 节点 |
| `CORROBORATE` | 给已有节点追加佐证 |
| `REFINE` | 补充更精确的表述 |
| `CORRECT` | 修正旧记忆中的矛盾或过时内容 |
失败 unit 会记录到 `failed_units``failed_paths`,不会被 checkpoint后续运行会重试。
#### Phase 3: Topics
`dream_topics_step` 写入:
```text
daily/<date>/interests.yaml
```
默认最多保留 3 个 topic并参考过去 7 天的 `interests.yaml` 做去重,避免每天重复推送同类兴趣。若 LLM 不可用,会退化为本地去重选择。
#### Phase 4: Finish
`dream_finish_step`
- 把成功处理的 changed paths、`interests.yaml` 和当天索引页写入 `file_catalog:dream`
- 删除 catalog 中已经不存在的 daily 输入。
- 持久化 catalog 到 `reme_metadata/file_catalog/dream.jsonl.zst`
- 返回本次扫描、抽取、集成、topic 和 checkpoint 的摘要。
### 4.4 Proactive
`proactive` 读取当天或指定日期的:
```text
daily/<date>/interests.yaml
```
返回 topics 和可选 YAML 原文,供调用方读取当天兴趣主题。
## 5. Job、Step 与组件架构
### 5.1 分层
```text
Service 层
HTTP / MCP把 Job 暴露为外部接口
Application 层
加载配置,初始化 service、component、job按依赖拓扑启动组件
Job 层
BaseJob / StreamJob / BackgroundJob / CronJob按 YAML 顺序执行 Step
Step 层
默认 Job 使用的原子业务操作file_io / index / evolve / common
Component 层
可插拔基础设施store、graph、index、catalog、LLM、agent wrapper、tokenizer
```
### 5.2 Registry 与依赖注入
所有后端通过全局注册表 `R` 注册:
```python
@R.register("local")
class LocalFileStore(BaseFileStore):
...
```
配置中的 `backend` 会通过 `(ComponentEnum, backend)` 找到类。组件依赖通过 `BaseComponent.bind(name, BaseClass)` 声明,`Application` 会按依赖拓扑顺序启动组件,并在关闭时反序关闭。
### 5.3 Job 类型
| Job 后端 | 类 | 行为 |
| --- | --- | --- |
| `base` | `BaseJob` | 请求触发,按步骤顺序执行,返回 `Response` |
| `stream` | `StreamJob` | SSE/流式输出 chunk |
| `background` | `BackgroundJob` | 应用启动后后台运行,失败时可 supervisor 重启 |
| `cron` | `CronJob` | 按 cron 表达式定时执行步骤 |
后台 Job 强制 `enable_serve=False`,不会暴露成 HTTP endpoint 或 MCP tool。
### 5.4 默认 Job 列表
默认配置中的主要 Job
| 类别 | Job | 说明 |
| --- | --- | --- |
| 后台索引 | `index_update_loop` | 监听 `daily/``digest/` 的 Markdown 变更,增量更新 file_store |
| 后台资源 | `resource_watch_loop` | 监听 `resource/` 文本资源,更新 resource catalog 并触发 `auto_resource_step` |
| 后台 catalog | `digest_watch_loop` | 监听 `daily/``digest/`,更新 digest catalog 并记录变更 |
| 系统 | `version` | 返回包版本 |
| 系统 | `health_check` | 返回组件健康快照 |
| 系统 | `help` | 列出已注册 Job |
| 检索 | `search` | chunk 级 BM25 检索和 link expansion |
| 检索 | `node_search` | digest 节点级召回,供 dream 集成使用 |
| 图谱 | `traverse` | 从指定 path 遍历 wikilink 图 |
| 索引维护 | `reindex` | 清空 file_store 并从文件重新建索引 |
| 日记 | `daily_create` | 幂等创建当天 day-level 或 session-level note |
| 日记 | `daily_list` | 列出某天 daily notes |
| 日记 | `daily_reindex` | 重建当天索引页 |
| 文件读写 | `read` | 读取 workspace 内 Markdown 文件,可指定行号 |
| 文件读写 | `read_image` | 读取图片为 base64默认上限 5MB |
| 文件读写 | `write` | 写 Markdown 文件和 front matter |
| 文件读写 | `edit` | 全量 find-and-replace |
| 文件读写 | `delete` | 删除文件或目录,返回残留入边 |
| 文件读写 | `move` | 移动或重命名文件,默认改写入边 wikilink |
| 文件读写 | `list` | 列目录 |
| 文件读写 | `stat` | 返回路径元信息 |
| Front Matter | `frontmatter_read` | 读取 front matter |
| Front Matter | `frontmatter_update` | 合并更新 front matter |
| Front Matter | `frontmatter_delete` | 删除 front matter 字段 |
| 自进化 | `auto_memory` | 对话写入 daily note |
| 自进化 | `auto_resource` | 资源文件解读为 daily note |
| 自进化 | `auto_dream` | daily -> digest + interests.yaml |
| 主动记忆 | `proactive` | 读取 `interests.yaml` |
## 6. 服务、客户端与 CLI
### 6.1 HTTP Service
`HttpService` 使用 FastAPI
- 非 stream Job 注册为 `POST /<job.name>`,请求体是 `Request`,响应是 `Response`
- StreamJob 注册为 `POST /<job.name>`,返回 `text/event-stream`
- CORS 默认开放。
- lifespan 中启动/关闭整个 `Application`
### 6.2 MCP Service
`MCPService` 使用 FastMCP
- 非 stream Job 注册为 MCP tool。
- 支持 `stdio``sse``streamable-http` 等 transport。
- StreamJob 当前不注册为 MCP tool。
### 6.3 Client 与 CLI
入口是:
```bash
reme start
reme find_reme
reme <job_name> key=value ...
```
行为:
- `reme start`:加载 `.env`,解析配置,启动服务。
- `reme find_reme`:从环境或默认地址探活。
- 其他 action通过 client 调用已运行服务,默认 HTTP也可指定 `backend=mcp`
配置解析支持:
- 默认加载 `reme/config/default.yaml`
- `config=<name-or-path>` 指定配置文件。
- dot notation 覆盖,如 `service.port=8090`
- `${ENV_VAR:-default}` 环境变量展开。
服务启动后会把地址写到环境变量 `REME_SERVICE_INFO`HTTP client 会优先使用显式 host/port其次使用该环境变量最后回落到默认 host/port。
## 7. 默认组件后端
默认配置中的组件:
| ComponentEnum | 名称 | 后端 | 说明 |
| --- | --- | --- | --- |
| `service` | - | `http` | 默认服务协议 |
| `tokenizer` | `default` | `regex` | BM25 分词 |
| `as_llm` | `default` | `${LLM_BACKEND:-openai}` | OpenAI 兼容 LLM默认模型 `qwen3.7-plus` |
| `agent_wrapper` | `default` | `agentscope` | AgentScope ReAct wrapper |
| `agent_wrapper` | `claude_code` | `claude_code` | Claude Code wrapper |
| `file_graph` | `default` | `local` | 纯 Python 图谱 |
| `file_catalog` | `default/resource/digest/dream` | `local` | JSONL.zst catalog |
| `file_chunker` | `markdown` | `markdown` | Markdown AST chunker |
| `file_chunker` | `default` | `default` | 默认文本 chunker |
| `keyword_index` | `default` | `bm25` | numpy BM25 |
| `file_store` | `default` | `local` | graph + keyword |
## 8. 持久化状态
除 workspace 正文文件外ReMe 会在 `reme_metadata/` 下保存组件状态:
| 组件 | 持久化内容 |
| --- | --- |
| `file_store` | `file_chunks_<name>_v1.jsonl.zst`,保存 chunk 元数据 |
| `file_graph` | `<name>.jsonl.zst`,保存 `FileNode` 和 links |
| `keyword_index` | `bm25_*.pkl`,保存 vocab、posting list、doc meta |
| `file_catalog` | `<catalog_name>.jsonl.zst`,保存已处理文件 mtime checkpoint |
`Application.close()` 会反序关闭组件,`LocalFileStore.close()` 会触发 chunk、keyword index、file graph dump。后台 catalog/dream finish 也会按需 dump catalog。
## 9. 关键数据模型
```text
Response
success: bool
answer: str
metadata: dict
FileNode
path: str
st_mtime: float
links: list[FileLink]
chunk_ids: list[str]
front_matter: FileFrontMatter
FileChunk
id: str # hash(path, start_line, end_line, text)
path: str
start_line: int
end_line: int
text: str
metadata: dict
scores: dict[str, float]
FileLink
source_path: str
target_path: str
target_anchor: str | None
predicate: str | None
DreamState
date / changed_paths / unchanged_paths / deleted_paths
units / topics
integrate_results / failed_units / failed_paths
interests_path / topics_written
checkpoint_paths / errors / summary
```

View file

@ -1,211 +0,0 @@
# reme 代码模块索引
> 本文档梳理 `reme/` 下各能力模块、核心类和代码路径,便于快速定位与扩展。
> 所有路径相对仓库根目录 `/Users/yuli/workspace/ReMe/`
## 1. 顶层入口与运行流程
| 文件 | 作用 |
| --- | --- |
| `reme/reme.py` | CLI 入口(`main()``start` 启动应用;`find_reme` 探活;其他动作转发到 client。 |
| `reme/application.py` | `Application` 基类:解析 config → 注册 service / components / jobs → 拓扑排序启动 → `run_job` / `run_stream_job` / `run_app`。 |
| `reme/constants.py` | 服务发现常量:`REME_SERVICE_INFO`、默认 host/port (`127.0.0.1:2333`)。 |
| `reme/__init__.py` | 包入口。 |
启动流程:`reme.main()``parse_args``resolve_app_config``precheck_start``ReMe(...).run_app()``service.run_app(app)``app.start()`(按拓扑序启动 components 与 jobs
## 2. 配置与枚举
| 文件 | 作用 |
| --- | --- |
| `reme/config/default.yaml` | 默认配置service / jobs / components 全套样例。 |
| `reme/config/config_parser.py` | `parse_args``resolve_app_config`、env 变量展开、点号配置覆盖、YAML/JSON 加载。 |
| `reme/enumeration/component_enum.py` | `ComponentEnum`所有组件类型枚举service/client/job/step/file_*/embedding/keyword_index/tokenizer/as_*)。 |
| `reme/enumeration/chunk_enum.py` | `ChunkEnum`:流式分块类型 (THINK/CONTENT/TOOL_*/USAGE/ERROR/DONE)。 |
## 3. SchemaPydantic 数据模型)
代码:`reme/schema/`
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `ApplicationConfig` / `ComponentConfig` / `JobConfig` | `application_config.py` | 顶层配置模型;包含 service/jobs/components/workspace_dir 等字段。 |
| `EmbNode` | `emb_node.py` | 文本+embedding 节点基类,`np.ndarray` 序列化为列表存储。 |
| `FileChunk` | `file_chunk.py` | 文件切片(继承 `EmbNode``path/start_line/end_line/scores`,含 `set_hash_id()`。 |
| `FileNode` | `file_node.py` | 文件级图节点:`path/st_mtime/links/chunk_ids/front_matter`。 |
| `FileLink` | `file_link.py` | 文件间 wikilink 边:`source_path → target_path`,可选 `target_anchor` / `predicate`。 |
| `FileFrontMatter` | `file_front_matter.py` | YAML 头:`name/description``extra="allow"` 保留未知键。 |
| `Request` / `Response` | `request.py` / `response.py` | 服务端请求/响应封装。 |
| `StreamChunk` | `stream_chunk.py` | 流式分块:`chunk_type/chunk/done/metadata`。 |
## 4. Components核心能力组件
> 所有组件继承 `BaseComponent``reme/components/base_component.py`),提供:
> - `start/close/restart` 生命周期;
> - `bind(name, base_cls, default_factory, optional)` 声明依赖(启动时通过拓扑排序解析);
> - `workspace_path` / `working_metadata_path` 工作目录;
> - `dump/load` 持久化钩子。
>
> 组件通过 `ComponentRegistry``R``reme/components/component_registry.py`)按 `(ComponentEnum, name)` 注册和查找;上下文容器为 `ApplicationContext``application_context.py`),运行期上下文为 `RuntimeContext``runtime_context.py`)。
### 4.1 Tokenizer — `reme/components/tokenizer/`
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseTokenizer` | `base_tokenizer.py` | 抽象基类,启动时加载 `stopwords` 文件。 |
| `RegexTokenizer` (`@R "regex"`) | `regex_tokenizer.py` | 正则切词;中文按字符切分,非中文按词切分。 |
| `JiebaTokenizer` (`@R "jieba"`) | `jieba_tokenizer.py` | 基于 jieba 的中文分词。 |
### 4.2 Keyword Index — `reme/components/keyword_index/`
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseKeywordIndex` | `base_keyword_index.py` | 抽象基类:`add_docs/delete_docs/retrieve/clear/optimize_index`,依赖 tokenizer。 |
| `BM25Index` (`@R "bm25"`) | `bm25_index.py` | 自实现 Okapi BM25 倒排索引:`vocab` / `inverted_index` / `doc_meta`pickle 持久化,支持增量更新与 `optimize_index` 紧凑化。 |
### 4.3 Embedding — `reme/components/embedding/`
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseEmbeddingModel` | `base_embedding_model.py` | LRU 缓存 + npz 磁盘持久化、批量、重试、健康检查(`is_healthy`);提供 `get_embedding/get_embeddings/get_node_embeddings`。 |
| `OpenAIEmbeddingModel` (`@R "openai"`) | `openai_embedding_model.py` | OpenAI 兼容协议dashscope/qwen 等),`AsyncOpenAI` 客户端。 |
### 4.4 File Graph — `reme/components/file_graph/`
存储 `FileNode` 节点与 `FileLink` 边,支持「虚节点」(被指但尚未导入的目标占位)。
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseFileGraph` | `base_file_graph.py` | 抽象接口:`upsert_nodes/delete_nodes/get_nodes/rebuild_links/clear/get_outlinks/get_inlinks`。 |
| `LocalFileGraph` (`@R "local"`) | `local_file_graph.py` | 纯 dict 实现 + JSONL 持久化;维护 `_nodes`/`_inverse`/`_pending`。 |
| `NxFileGraph` (`@R "nx"`) | `nx_file_graph.py` | networkx `MultiDiGraph` + pickle 持久化,虚节点用「无 node 属性」标识。 |
| `Neo4jFileGraph` (`@R "neo4j"`) | `neo4j_file_graph.py` | Neo4j 后端bolt 驱动),`(:File)-[:LINKS]->(:File)`,支持升降级虚节点、`rebuild_links` 修复重建。 |
### 4.5 File Chunker — `reme/components/file_chunker/`
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseFileChunker` | `base_file_chunker.py` | 抽象接口:`parse(path) -> (FileNode, list[FileChunk])`,提供 `_get_relative_path`。 |
| `DefaultFileChunker` (`@R "default"`) | `default_file_chunker.py` | 字节级带 overlap 切片 + YAML front matter + wikilink 抽取(含 Dataview `predicate::`)。 |
| `MarkdownFileChunker` (`@R "markdown"`) | `markdown_file_chunker.py` | Markdown 专用mistletoe AST → MdNode 树 → 章节递归分块;每个 chunk 携带完整 heading skeletonTOCwikilink 解析支持隐式 `.md`、folder-note、短路径歧义扇出需注入 `file_graph` 解析目标。 |
### 4.6 File Store — `reme/components/file_store/`
聚合 `embedding_model` + `keyword_index` + `file_graph`,统一 chunk 写入与混合检索。
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseFileStore` | `base_file_store.py` | 抽象基类:`upsert_file/delete_by_path/clear/vector_search/keyword_search/rebuild_links/get_nodes/get_outlinks/get_inlinks`;启动时探活 embedding失败则降级为纯关键字检索。 |
| `LocalFileStore` (`@R "local"`) | `local_file_store.py` | 内存 chunk 字典 + JSONL 持久化upsert 时复用旧 chunk 的 embedding按 chunk.id 命中);`vector_search``batch_cosine_similarity``keyword_search` 委托给 keyword_index。 |
### 4.7 File Watcher — `reme/components/file_watcher/`
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseFileWatcher` | `base_file_watcher.py` | 抽象接口:`watch_loop/update_store/on_added/on_modified/on_deleted`;启动后台任务先做一次全量同步再进入监听循环。 |
| `LiteFileWatcher` (`@R "lite"`) | `lite_file_watcher.py` | 基于 `watchfiles.awatch` 的轮询监听;变更分类后调用 file_chunker 解析、写 file_store`update_store` 通过 mtime 对比做增量。 |
### 4.8 Job — `reme/components/job/`
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseJob` (`@R "base"`) | `base_job.py` | 顺序执行 `steps`:每个 step 共享 `RuntimeContext`,最终返回 `Response`;启动时把 step config 实例化为 `BaseStep`。 |
| `StreamJob` (`@R "stream"`) | `stream_job.py` | 流式执行:异常包装为 ERROR chunk结束时 emit DONE 终止流。 |
### 4.9 Service — `reme/components/service/`
把 jobs 暴露给外部协议。
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseService` | `base_service.py` | 抽象接口:`build_service/add_job/start_service``run_app` 串起来。 |
| `HttpService` (`@R "http"`) | `http_service.py` | FastAPI + uvicorn普通 job → POST JSON 端点stream job → SSE 流CORS 全开。 |
| `MCPService` (`@R "mcp"`) | `mcp_service.py` | FastMCP把 job 注册为 MCP `FunctionTool`StreamJob 跳过transport 支持 sse/stdio/streamable-http。 |
### 4.10 Client — `reme/components/client/`
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseClient` | `base_client.py` | 抽象接口:`__call__` 分发 `list`/`_execute``list_actions` 列出 server 能力。 |
| `HttpClient` (`@R "http"`) | `http_client.py` | httpx 异步流式:根据 `Content-Type` 自适应 JSON/SSE`/openapi.json` 列出 actionsCLI 友好格式化。 |
| `MCPClient` (`@R "mcp"`) | `mcp_client.py` | fastmcp Client 包装transport=`sse/stdio/streamable-http``list_tools` 列出工具。 |
### 4.11 AgentScope 适配as_*`reme/components/as_*/`
把 AgentScope 的 LLM / Formatter / TokenCounter 包成 ReMe 组件,供 step 通过 `step.as_llm` / `step.as_llm_formatter` / `step.as_token_counter` 访问。
| 类 | 文件 | 说明 |
| --- | --- | --- |
| `BaseAsLLM` / `OpenAIAsLLM` (`openai`) / `AnthropicAsLLM` (`anthropic`) | `as_llm/__init__.py` | 包装 `agentscope.model.OpenAIChatModel / AnthropicChatModel`,启动时实例化 `self.model`。 |
| `BaseAsLLMFormatter` / `AsOpenAIChatFormatter` (`openai`) / `AsAnthropicChatFormatter` (`anthropic`) | `as_llm_formatter/__init__.py` | 包装 AgentScope formatterOpenAI 版用 `ReMeOpenAIChatFormatter` 扩展 |
| `ReMeOpenAIChatFormatter` | `as_llm_formatter/reme_openai_chat_formatter.py` | OpenAI formatter 扩展tool_result 中的 image 提升为 user 消息thinking 块合并为 `reasoning_content`;新增 video block 支持。 |
| `BaseAsTokenCounter` / `EstimatedAsTokenCounter` (`estimated`) | `as_token_counter/__init__.py` | 字符级估算 token 计数器(`encoded_byte_len / divisor`)。 |
| `EstimatedTokenCounter` | `as_token_counter/estimate_token_counter.py` | 实现类。 |
### 4.12 Prompt Handler — `reme/components/prompt_handler.py`
`PromptHandler`YAML/JSON 加载或类同名文件加载;多语言后缀(`key_zh/key_en``prompt_format` 支持 `[flag]` 行级条件、`{var}` 参数校验。
## 5. Steps最小执行单元
代码:`reme/steps/`
| 类 | 注册名 | 文件 | 作用 |
| --- | --- | --- | --- |
| `BaseStep` | — | `base_step.py` | 抽象基类:`execute()` + `RuntimeContext` 注入 + `input/output_mapping` + 通过 `_resolve` 自动取组件(`as_llm/as_llm_formatter/as_token_counter/file_chunker/file_store/embedding/file_watcher``add_as_tool(toolkit, job_name)` 把 job 包成 AgentScope tool。 |
| `DemoEchoStep1/2` | `demo_echo_step1` / `demo_echo_step2` | `common/demo.py` | 烟雾测试query 处理 + 应答。 |
| `HealthCheckStep` | `health_check_step` | `common/health_check.py` | 各组件健康/规模快照embedding/file_graph/file_store/file_watcher/keyword_index+ 内存深度估算。 |
| `HelpStep` | `help_step` | `common/help.py` | 一行式列出全部 job 元信息(含参数 schema。 |
| `ReindexStep` | `reindex_step` | `common/reindex.py` | 全量重建:停 watcher → clear store → `update_store` → 重启 watcher。 |
| `SearchStep` | `search_step` | `common/search.py` | 混合检索vector_search + keyword_search 并发 → RRF 融合 → 阈值过滤 → 截断 → 可选 outlinks/inlinks 邻居展开(含元数据)。 |
| `StreamDemoStep1/2` | `stream_demo_step1` / `stream_demo_step2` | `common/stream_demo.py` | 流式烟雾测试:逐字符 emit CONTENT。 |
| `VersionStep` | `version_step` | `common/version.py` | 输出 `reme.__version__`。 |
## 6. Utils — `reme/utils/`
| 文件 | 主要导出 |
| --- | --- |
| `common_utils.py` | `hash_text`(SHA-256)、`execute_stream_task`(SSE 流转发)、`mock_reme_server`(子进程启动测试服务器)、`call_action` / `call_and_check`(HTTP 调用与断言)。 |
| `service_utils.py` | `find_reme` / `locate_reme` / `precheck_start` / `cli_find_reme`:服务发现,`lsof` + `pgrep` 扫描运行实例,端口冲突预检。 |
| `env_utils.py` | `load_env`:加载 `.env`。 |
| `logger_utils.py` | `get_logger`loguru 日志(控制台 + 文件)。 |
| `logo_utils.py` | `print_logo`:启动 ASCII logo。 |
| `similarity_utils.py` | `cosine_similarity` / `batch_cosine_similarity`numpy 向量相似度。 |
## 7. 内置 Jobs`reme/config/default.yaml`
| Job | Backend | 步骤 | 说明 |
| --- | --- | --- | --- |
| `demo` | `base` | `demo_echo_step1``demo_echo_step2` | 端到端 demo。 |
| `version` | `base` | `version_step` | 返回包版本。 |
| `health_check` | `base` | `health_check_step` | 组件健康快照。 |
| `help` | `base` | `help_step` | 列出全部 job。 |
| `reindex` | `base` | `reindex_step` | 全量重建索引。 |
| `search` | `base` | `search_step` | 混合检索vector+keyword RRF可展开邻居。 |
| `stream_demo` | `stream` | `stream_demo_step1``stream_demo_step2` | 流式 demo。 |
## 8. 默认依赖关系(来自 `default.yaml`
```
tokenizer (regex) ──┐
embedding_model (openai) ──┤── file_store (local) ── file_watcher (lite)
file_graph (local) ──┤ (持有 embedding/keyword_index/file_graph)
file_chunker (default) ──┘ │
keyword_index (bm25) ── tokenizer ──────────────┘ │
file_chunker ──┘
```
启动时由 `Application._topological_order()`Kahn 算法)按依赖拓扑序启动;关闭时反向。
## 9. 扩展点速查
| 需求 | 入口 |
| --- | --- |
| 新增检索后端 | 实现 `BaseFileStore` 子类,`@R.register("xxx")` |
| 新增图后端 | 实现 `BaseFileGraph` 子类(参考 `Neo4jFileGraph` 处理虚节点) |
| 新增分词器 | 实现 `BaseTokenizer.tokenize` |
| 新增解析器 | 实现 `BaseFileChunker.parse`(返回 `(FileNode, list[FileChunk])` |
| 新增 Job | 在 `default.yaml`(或自定义 yaml`jobs:` 段声明 + 写步骤实现 |
| 新增 Step | 继承 `BaseStep`,实现 `execute()``@R.register("xxx_step")` |
| 暴露新协议 | 实现 `BaseService`(参考 `HttpService` / `MCPService` |
| 接入新 LLM | 实现 `BaseAsLLM` 子类(`agentscope.model` 适配) |

View file

@ -1,971 +0,0 @@
# ReMe把本地 Markdown 自进化成知识图谱的个人记忆引擎
> 面向 Leader / 决策者的能力报告
> 关键词:个人记忆 · 记忆自进化 · 多模检索 · Agent 接入 · 本地优先
---
## 一、引言:为什么要做新版本
### 1.1 ReMe 的一句话定位
> **ReMe 是一个把本地 Markdown 自进化成知识图谱的个人记忆引擎。**
- **记忆分层(形态的物化)** → 记忆按"原始 → 加工"两层组织:`resource/`(原始素材)、`daily/`(日记事件)是只增不删的流水帐;`digest/` 是加工层,下分 `personal/`(个性化)、`knowledge/`(主题知识)、`procedural/`Agent 任务经验)、`proactive/`(主动洞察)四个固定子目录,写入策略和检索权重各有差异。
- **本地 Markdown载体** → 所有记忆都是 Obsidian 兼容的 .md 文件——YAML front matter、四种 wikilink`[[X]]` / `[[X#anchor]]` / `[[X|alias]]` / `![[X]]`、Dataview 风格 `predicate:: [[X]]` 语义关系全部沿用社区约定。用户可读、可备份、可迁移,对抗黑盒。
- **自进化(机制)** → 不需要用户手工整理Agent 在后台让笔记自己长出结构。这一点把 ReMe 同时与"手动建图的 Obsidian"和"扁平存储的 Mem0"拉开。【event/trace】
- **知识图谱(结果)** → 自进化的产出物不是一堆扁平笔记,而是一张可被**多模 + 渐进式检索**消费的图:向量 + 关键词(中文 BM25+ 图谱三路 RRF 融合,返回时通过 1-hop 邻居 meta 让 Agent"先看目录、再决定要不要展开正文",不像传统 RAG 那样一次性把 top-K 切片塞进上下文。
- **被集成而非内置(分发形态)** → ReMe 不做独立 Agent 产品,而是作为**能力**被任意 Harness 调用SDK 深度集成qwenpaw / AgentScope、MCP ToolClaude Code / Cursor / Cherry Studio、CLI + skill.md 三条路径并行,记忆跟着用户走,不绑定任何上层框架。
支撑这一切的是**自研轻量索引内核**——纯 Python(后期可以使用rust重写索引内核) + 文件持久化,无 sqlite / chroma
等原生扩展依赖,老旧 Linux/Win 也能稳跑,这是 ReMe 能"被部署到大量异构用户机器"的工程前提。
---
## 二、产品全景图
### 2.1 一张图看 ReMe
```
┌─────────────────────────────────────────────────────────┐
│ 外部 Agent / Harness │
│ qwenpaw · Claude Code · Cursor · 其它 │
└──────────┬──────────────┬───────────────┬───────────────┘
│ SDK │ MCP Tool │ CLI / skill.md
┌──────────▼──────────────▼───────────────▼───────────────┐
│ ReMe Service Layer │
│ HTTP / MCP / CLI · 服务发现 · 进程托管 │
├─────────────────────────────────────────────────────────┤
│ ReMe Job/Step 编排 │
│ search · auto_memory · auto_dream · auto_link … │
├─────────────────────────────────────────────────────────┤
│ Markdown 知识内核(本地文件即数据库) │
│ FileChunker · FileStore · FileGraph · FileWatcher │
│ BM25 倒排 · 向量索引 · Wiki Link 图谱 │
├─────────────────────────────────────────────────────────┤
│ 文件目录约定 │
│ resource/ · daily/ · digest/{personal,knowledge, │
│ procedural,proactive}/ │
└─────────────────────────────────────────────────────────┘
```
四层结构从上到下:
- **接入层**:让任何 Agent 框架都能用。
- **服务层**HTTP / MCP / CLI 三种协议同时暴露,按 Harness 需求选用。
- **编排层**:把能力拆成 Job/Step可组合、可流式。
- **内核层**Markdown 解析、存储、图谱、监听一体化。
- **目录层**:用户最直观看到的文件夹结构,本身就是 ReMe 的"产品形态"。
### 2.2 三个最直观的故事场景
**场景一:金融分析师的产业链知识库**
盘后,分析师和 Agent 对话讨论今天看到的几条新能源新闻。第二天打开知识库,发现昨天的对话已经被自动拆分成「钴价波动」「下游电池厂动向」「上游矿企并购」三条事件笔记,分别归档到
`digest/knowledge/financial/产业链/` 下相应主题;笔记之间通过 `[[钴]]` `[[宁德时代]]` 这样的 wikilink 互相串联。下周再问"钴的下游应用"ReMe
沿着图谱渐进展开,从一个节点跳到相关的全部上下文。
**场景二:个人工作 & 生活第二大脑**
日常对话、会议讨论、学习笔记都被主 Agent 实时写入 daily 笔记。夜晚 Agent 空闲时ReMe 在后台把零散的 daily 内容按"
客户/项目/学习/生活"主题重新整理到 knowledge 库,并自动补全笔记之间的链接。三个月后,用户拥有一份完全属于自己的、可视化的"
第二大脑",可以用 Obsidian 直接打开浏览。
**场景三Agent 框架开箱接入**
开发者在 qwenpaw 或 Claude Code 中安装 ReMe不需要改 Agent 一行代码 —— Agent 立刻拥有"长期记忆 + 个人知识检索 +
自动整理"三项能力。SDK 集成是无感的:每次对话自动落入 daily每次检索自动走多模融合每天空闲自动整理归档。
---
## 三、记忆模型ReMe 把什么存下来
### 3.1 两层记忆结构:原始素材 + 加工记忆
ReMe 不把对话一股脑塞进数据库,而是按"原始 → 加工"分两层组织:
| 层次 | 目录 | 存什么 | 典型场景 |
|----------|-------------|----------------------------------|-------------------------------|
| **原始素材** | `resource/` | 上传文件、抓取网页、PDF 研报、邮件附件 | 溯源 / 审计 / 二次加工 |
| **日记流水** | `daily/` | 每天的事件性记忆,主 Agent 实时写入 | "我今天和谁聊了什么"、"今天工作内容" |
| **加工记忆** | `digest/` | 经 Auto-Dream 整理后的长期记忆,下分四类(见 3.2 | "光伏产业链"、"webpack 排查路径"、"早间洞察" |
`resource/``daily/` 是只增不删的"流水帐"——前者保留原始事实、后者保留事件级现场;`digest/` 才是被反复消费的精华层,也是 Auto-Dream / Auto-Link 持续打磨的主要产物。
### 3.2 digest 下的四种记忆
`digest/` 固定划分四个子目录,正交覆盖"用户 / 知识 / Agent / 主动"四个维度:
| 子目录 | 内容性质 | 写入触发 | 检索权重 | 典型例子 |
|------------------------|---------------------|----------------------|-------------|---------------------------------------|
| **digest/personal/** | 个性化(用户偏好、习惯、人物档案) | 用户纠正 / 偏好表达 | 全场景常驻 | "用户不爱写注释"、"用户喜欢 pnpm" |
| **digest/knowledge/** | 知识类(客观知识、领域参考) | 主题对话 / Auto-Dream 归档 | 主题相关性匹配 | "光伏产业链"、"React Server Components" |
| **digest/procedural/** | 程序化Agent 任务经验) | 任务完成后归纳 | 任务相似度高时唤起 | "webpack 卡死的排查路径" |
| **digest/proactive/** | 主动推送Agent 输出的分析) | 定时 / 触发式生成 | 时效衰减 | 早间洞察、周复盘、热点跟踪 |
四类的"形状"刻意不同:
- `digest/knowledge/` 由用户自定义二级分类(如 `work/``financial/``life/`),下面层级随意展开。
- `digest/personal/``digest/proactive/` 保持扁平,便于全量加载或时序浏览。
- `digest/procedural/` 软链到 Harness Agent 的 skill 目录P0让 Agent 沉淀的"经验"直接成为可复用的 skill。
### 3.3 目录约定(用户可读、可备份、可迁移)
skills 建议使用index 看 whole picture~
```
~/reme_workspace/
├── resource/ # 原始素材(按日期归档)
│ └── 20260518/
│ ├── 1430_xueqiu_comment.html # 雪球评论抓取
│ └── 1620_research_report.pdf # 研报原件
├── daily/
│ ├── 20260518.md # 当天主索引(兼容 write/edit
│ └── 20260518/
│ ├── meeting-with-alice.md
│ ├── debug-login.md
│ └── reading-paper.md
└── digest/ # 固定四个子目录personal / knowledge / procedural / proactive
├── personal/ # 个性化记忆:偏好、习惯、个人事件
.change_log.md difference
_moc.md
│ └── 用户偏好.md
├── knowledge/ # 知识类记忆用户自定义二级目录work / financial / ...
│ ├── work/
│ ├── financial/
│ │ ├── 光伏产业链.md
│ │ └── 钴.md
│ └── ...
├── procedural/ # 程序化记忆:软链到 harness agent 的 skill 目录P0
│ └── xxxx.md # Agent 完成任务沉淀的经验
└── proactive/ # 主动推送:各家协议不同
└── 20260518.md # Agent 主动产出的建议
```
> `digest/` 下固定为 **personal / knowledge / procedural / proactive** 四个子目录;其中 `knowledge/` 内部由用户自行扩展二级分类(如 `work/``financial/`),其余三类保持扁平结构。
**所有记忆都是普通 Markdown 文件**,用户随时可以:
- 用 Obsidian / Typora / VSCode 打开浏览编辑
- 用 Git / iCloud / 网盘做版本控制和跨设备同步
- 迁移到任何机器,复制目录即可
- **没有黑盒数据库,没有产品锁定**
这一点对 Leader 视角尤其重要:用户对自己数据的掌控感,是所有"个人记忆"产品的信任基础。
## 四、Markdown 内核:把文件当数据库
### 4.1 Obsidian 兼容的 Markdown 格式
ReMe 没有发明新格式,而是完全复用 Obsidian 生态的约定:
- **YAML front matter**:标题、标签、描述、自定义字段。
```markdown
---
title: 光伏产业链研究
description: 从硅料到组件的全链条梳理
tags: [新能源, 光伏, 产业链]
parent: 新能源
author: 张三
updated。: 2026-05-19
---
# 正文从这里开始
`title` / `description` / `tags` 是约定字段(参见 `reme/schema/file_front_matter.py`),其余键值对作为 extras
全部保留,可被检索和图索引消费。
```
- **4 种 wikilink 写法**
- `[[X]]`:标准链接
- `[[X#anchor]]`:链接到文件中的章节
- `[[X|alias]]`:自定义显示文本
- `![[X]]`:嵌入引用
- **Dataview 风格语义关系**`predicate:: [[X]]`,例如 `parent:: [[新能源]]``founder:: [[张三]]`,把 link 升级为带类型的"
边"。
- 标准 `[text](xxx.md)` 链接也会被识别为图边。
**意义**:用户的知识库可以直接用 Obsidian 打开做可视化浏览,可以用 Obsidian 插件做扩展。ReMe 不是替代 Obsidian而是**给
Obsidian 加上一个会自己写笔记的 Agent**
### 4.2 比 RAG 更聪明的切片
传统 RAG 用固定 token 长度 + overlap 切片经常切坏文档结构。ReMe 用 Markdown AST 切片:
- 解析为章节嵌套树(按 H1/H2/H3 分层)。
- 按章节边界递归切分,保留语义完整性。
- **每个 chunk 自带完整的标题骨架TOC**:检索回来的片段一眼就能看出"这段在哪个章节、什么主题下"。
```
某 chunk 实际内容长这样:
─────────────────────
# 光伏产业链
## 上游:硅料
### 多晶硅工艺
[chunk 正文]
## 中游:硅片
## 下游:组件
─────────────────────
```````
Agent 拿到这个 chunk立刻知道层级位置不会断章取义。
### 4.3 Graph 索引:双向链接
定位句里"自进化成**知识图谱**"的物理形态,就落在这一节——每个文件参与两套索引:
- **正向outlinks**A → BA 引用了 B
- **反向inlinks**B ← {A, C, D}(谁引用了 B
**反向链接**是知识库可用性的关键 —— 让你站在任意一个概念上,看到"还有哪些地方提到过我"。
ReMe 提供三种 graph backend按规模和需求切换
- **本地 dict + JSONL**:轻量、零依赖、适合个人规模。
- **NetworkX + pickle**:方便做图算法分析。
- **Neo4j**企业规模、Cypher 查询、可视化丰富。
切换只需配置一行。
## 五、记忆的自进化(核心差异化)
> 这是 ReMe 最重要的能力,也是和市面所有「记忆即数据库」产品的根本分野。
>
> **ReMe 的记忆不是被动存的,是主动长成知识图谱的。**
定位句中"自进化成知识图谱"的具体路径,由下面三件套共同承担:**auto-memory** 在前线把对话拆成事件,**auto-dream**
在空闲时把事件归档成主题,**auto-link** 把这一切用 wikilink 串成图。三者协作daily 流水最终被织成一张越用越密的个人知识图谱。
### 5.1 Auto-Memory实时拆事件
主对话进行时ReMe 在后台把上下文按"事件"自动拆分:
- 用户和 Agent 的连续对话,被识别为若干个独立事件(一次会议、一次 debug、一次学习
- 每个事件成为一个独立的 `daily/YYYYMMDD/{event}.md` 笔记。
- 同时在 `daily/YYYYMMDD.md` 维护主索引,所有事件可被反向追溯。
**用户体验**
:不需要手动整理。打开当天主索引,事件已经分章节列好,每条都能跳转到独立笔记。这就像有一个秘书在你说话的同时帮你做"
会议纪要的分章节"。
### 5.2 Auto-Dream空闲整理
借鉴人在睡眠中"记忆巩固"的机制:
- Agent 检测到空闲(夜晚、用户离开、长时间无交互)时触发。
- 把若干天的 daily 笔记按主题、实体重新组织到 `digest/knowledge/{domain}/` 下;同时把对话里反复出现的偏好沉淀到 `digest/personal/`,把 Agent 完成任务的经验固化到 `digest/procedural/`
- 抽取共性、合并重复、生成总结。
**用户体验**:第二天打开 `digest/`,会发现昨天散落在不同对话里的内容已经按"客户/项目/学习"自动归档到 `digest/knowledge/`,关键概念被抽成独立的主题笔记。
这是 ReMe 区别于"对话历史搜索"的关键 —— **它会自己整理**
### 5.3 Auto-Link自动建图
后台任务自动从正文里识别实体、候选链接,把隐式关系写回 wikilink
- 在「光伏产业链」笔记里提到「隆基」ReMe 自动补 `[[隆基]]` 链接到对应主题笔记。
- 在 daily 事件里提到「Alice」自动链到 `[[Alice]]` 个人档案。
- 生成的 link 是可见的、可编辑的(写在 Markdown 文件里),用户随时可以修正。
**用户体验**:知识库随时间自然"越长越密"。浏览时可以从任意一处跳转到相关全部上下文,类似于在自己的脑子里"联想"。
### 5.4 三者协同:从对话到知识图谱的自然演化
```
[实时] [离线] [持续]
原始对话 ─Auto-Memory─► daily 事件 ─Auto-Dream─► digest/{personal,knowledge,procedural}
Auto-Link
知识图谱
```
整个过程**不需要用户操心**。用户只需要正常和 Agent
对话,三个月后回头看,就有了一张按主题组织、互相关联、可视化浏览的个人知识图谱——这就是一句话定位里"自进化成知识图谱"的物理产物。
## 六、检索体验:多模检索 + 渐进式展开
### 6.1 三路融合的混合检索
ReMe 同时跑三种检索通路,结果通过 RRFReciprocal Rank Fusion排序融合
- **向量检索** —— 捕捉语义相似度("钴" ≈ "锂电正极原料"
- **关键词检索BM25** —— 精确匹配,对中文友好("宁德时代" 一定要命中)
- **图谱检索** —— 通过 wikilink 邻居展开(找到"钴" → 自动带上"刚果(金)"、"嘉能可"
单一通路都有盲区:
- 纯向量 → 名词术语容易错配。
- 纯关键词 → 同义改写抓不到。
- 纯图谱 → 起点选错就全盘错。
三路融合让检索像"三个人各自查一遍再开会确认",结果鲁棒得多。
### 6.2 渐进式展开
传统 RAG 是一次性把 top-K 切片塞进上下文token 利用率低而且经常带进不相关的噪音。ReMe 的检索(
`reme/steps/common/search.py`)是**分跳**的,且每一跳的"信息密度"刻意不同:
- **第一跳:直接命中的切片**——返回 chunk 全文 + 章节骨架。
- **第二跳1-hop 邻居**——只返回邻居的 path + metaname/description+ 边的语义predicate/anchor**不展开正文**。
- **第 N 跳Agent 主动追问**——基于二跳的"目录",挑出真正相关的邻居,再发起新一次 search 拿正文。
**一个具体例子:分析师查询"钴的下游应用"**
第一跳直接命中 `digest/knowledge/financial/产业链/钴.md` 的某一段切片answer 里这一段长这样:
```
========== digest/knowledge/financial/产业链/钴.md:42-78 [score=0.0234 vector=0.0123 keyword=0.0111] ==========
# 钴
## 应用
钴是锂电正极材料的关键原料,主要用于动力电池、消费电子和储能……
→ outlinks (3):
→ digest/knowledge/financial/矿产/刚果(金).md name="刚果(金) - 钴矿主产区"
via predicate=producer, anchor=#钴矿带
→ digest/knowledge/financial/公司/嘉能可.md name="嘉能可 Glencore"
via plain
→ digest/knowledge/financial/产品/三元正极.md name="三元正极材料"
via predicate=downstream
← inlinks (2):
← digest/knowledge/financial/产业链/锂电产业链.md name="锂电产业链总览"
via predicate=upstream
← daily/20260318/宁德调研纪要.md name="宁德时代调研纪要"
via plain
```
注意第二跳的信息只有"路径 + 名称 + 边的 predicate/anchor"**没有邻居正文**。这是关键设计:
- 一次检索就让 Agent 看到"这个主题周围长什么样"——上游是刚果(金)、嘉能可,下游是三元正极,被锂电产业链当作 upstream 引用,最近还在
3 月 18 日的宁德调研里被提到。
- Agent 可以基于这份"目录"判断哪个邻居才是用户真正想要的,再调一次 search 拉对应文件的正文(比如挑 `三元正极.md` 的细节)。
**为什么不一次把邻居正文也带回来**
如果第二跳直接返回正文,三跳网络很容易把上下文撑爆。当前实现里 `max_links_per_direction` 默认 10单跳最多吐出 10 个
outlink + 10 个 inlink 的 meta每条只占一行**整张二跳目录的成本不到一个 chunk 的 token**。
**工程层面的关键参数**
- `candidate_multiplier=3.0`:候选池预拉 `limit*3` 条(最多 200给 RRF 融合留余量。
- `min_score`:过低分切片直接丢弃,避免噪音。
- `expand_links=True`:开关二跳展开;关闭则退化为传统 RAG。
- `max_links_per_direction=10`:单方向(出/入)最多展示几个邻居,防爆。
**用户体验**:检索像"翻知识网络"——先看一眼周边目录,再决定要不要深入某一条线,而不是"拉一坨切片塞进上下文"。
**工程价值**上下文窗口永远只装最相关的部分token 成本可控Agent 也能更精确地解释"我为什么知道这个"——因为它能引用
predicate=upstream、anchor=#应用 这种带语义的边。
### 6.3 关键词索引的工程价值
很多人忽视:**做中文知识库,关键词检索比向量更重要**。
ReMe 自研增量 BM25 倒排索引,配合 jieba 中文分词:
- 增量更新:新增/删除文件无需重建全索引。
- 跨平台:纯 Python + 文件落盘,没有 sqlite/chroma 这类原生扩展。
- 这一点直接解决了老版本在 qwenpaw 等老旧 Linux/Win 系统上的 core dump 兼容问题。
---
## 七、工程架构:可扩展、可替换、可演进
### 7.1 Component 框架
ReMe 把所有能力封装为 Component
```
embedding · file_store · file_graph · file_chunker · file_watcher
tokenizer · keyword_index · LLM 适配 · service · client
```
每个 Component 都可以:
- **Backend 热切换**`local``nx``neo4j` 一行配置改完。
- **生命周期托管**start / close / restart 全自动,幂等保护。
- **依赖声明**:组件间相互调用,按依赖图拓扑排序自动启动。
- **持久化钩子**dump/load 标准接口。
这意味着 ReMe 有非常强的**可演进性** —— 当某个 backend 不够用了(比如个人 Neo4j 改用云上 Neo4j换的成本极低。
### 7.2 Job / Step 编排(借鉴 GitHub Actions
- **Step**:最小执行单元,做一件具体的事(如检索、解析、调 LLM
- **Job**steps 的有序组合,可复用、可流式。
- **对外**:每个 Job 同时暴露为 HTTP API / MCP Tool / CLI 命令,无需重复开发。
新增一个能力的标准动作是:
1. 写一个 Step继承 BaseStep实现 execute
2. 在配置里把它组合进 Job。
3. 自动获得 HTTP / MCP / CLI 三种调用方式。
### 7.3 配置即应用
一份 `default.yaml` 描述完整应用service / components / jobs。
```yaml
service:
backend: http
components:
file_store:
backend: local
file_graph:
backend: local
jobs:
search:
steps:
- search_step
```
替换 backend、增删 Job、调整依赖全部通过配置完成部署上线无需改代码。
---
## 八、生态接入ReMe 如何被使用
### 8.1 三种集成路径
| 路径 | 适用对象 | 体验 |
|-------------------------|-----------------------------------------------------|--------------------------------------------------------------------|
| **SDK 集成** | qwenpaw / AgentScope 等深度合作框架 | 直接调用 `AgentscopeTools`,无感拥有 auto-memory / auto-dream / auto-search |
| **MCP Tool + skill.md** | 任何支持 MCP 的客户端Claude Code / Cursor / Cherry Studio | 配 skill.md开箱即用 |
| **CLI + skill.md** | 通用方案,兜底所有 Harness | 一条命令调用shell 友好 |
三条路径的设计哲学是:**不强迫任何 Agent 框架做 ReMe-specific 的改造**。
- 对深度合作方,给最丝滑的 SDK。
- 对支持 MCP 的产品,靠 MCP 标准协议。
- 对什么都不支持的环境CLI + skill.md 兜底。
### 8.2 服务托管
- **按需拉起**Agent 检测到 ReMe 服务未运行时,可以自动后台拉起,用户无感知。
- **服务发现**`find_reme` 一键探活,避免端口冲突;多个 ReMe 实例共存时也能精准定位。
### 8.3 ReMe 的边界
> **ReMe 专注于知识加工,不做知识获取。**
- **数据采集** —— 网页抓取、邮件接入、Slack 同步、文件上传 —— 由上游 Agent 完成。
- **ReMe 负责** —— 把这些资料消化、整理、链接、检索、自进化。
这个边界划得清楚的好处:
- ReMe 不和上游的数据接入工具竞争。
- ReMe 不需要为每种数据源写适配,专注做记忆引擎本职。
- 让 ReMe 在"被集成"路线上更纯粹、更通用。
---
## 九、应用场景
### 9.1 金融场景:产业链知识库
**主角**:王分析师,新能源行业研究员,每天要处理 10+ 篇研报、数十条产业新闻、若干场公司调研。
**痛点**信息散落在飞书文档、PDF 研报、微信群消息、调研纪要里,"上次调研宁德时代时聊到的钴价话题"再也找不回来。
#### 一周内 ReMe 自动织出的产业链图谱
> **关键边界**Auto-Dream 只对**已存在的 daily 事实**做聚合,不会凭空梦出"产业链总览"这种结构性概念。总览级笔记的诞生依赖**用户主动 query**,下面会分两个阶段展示。
##### 阶段一Auto-Memory + Auto-Dream事实层聚合
**Day 1周一盘后**:王分析师把今天看到的 3 篇研报扔给 Agent又口述了对刚果(金)矿权变更的看法。
```
对话原文(片段)
> 今天嘉能可发了三季报,钴产量同比下滑 18%……
> 刚果(金)那边的政策变化,对洛阳钼业 KFM 矿的影响要重点跟……
> 下游三元正极厂商已经开始转向高镍低钴方案……
```
ReMe 当晚 Auto-Memory 拆事件:
```
daily/20260518/
├── 嘉能可三季报点评.md ← Auto-Memory 拆出的事件 1
├── 刚果金矿权政策跟踪.md ← 事件 2
└── 三元正极高镍化趋势.md ← 事件 3
```
**Day 2-3**王分析师又陆续聊了宁德调研、亿纬电话会、嘉能可后续公告daily 里「钴」「嘉能可」「三元正极」「宁德时代」反复出现。
**Day 3周三夜间 Auto-Dream**:把多天 daily 里**反复出现的实体**聚合成实体笔记——只做归并,不做总览。
```
digest/knowledge/financial/公司/
├── 嘉能可.md ← 新建:聚合 day1/day2 提到嘉能可的 4 个事件
├── 洛阳钼业.md ← 新建
└── 宁德时代.md ← 已有,本次新增「高镍化决策」一节
digest/knowledge/financial/原料/
└── 钴.md ← 新建:聚合 3 天里所有提到「钴」的内容
digest/knowledge/financial/产品/
└── 三元正极.md ← 新建:技术路线变化
```
注意:**Auto-Dream 没有生成「锂电产业链.md」**——产业链是结构性概括,不在 daily 事实里,凭空生成就是幻觉。
##### 阶段二:用户 query 触发检索 + 合成(结构层)
**Day 5周五**:王分析师准备组会要讲新能源板块,主动问 Agent
> **"分析锂电相关上下游"**
这一句 query 触发了**检索 → 合成 → 落盘**的完整闭环:
###### Step 1渐进式检索返回多节点 + 关系骨架
ReMe 走多模融合(向量 + BM25 + 图谱),命中 3 天来 Auto-Dream 已经聚合好的实体节点,并展开 1-hop 邻居 meta
```
========== 第一跳直接命中5 个节点)==========
digest/knowledge/financial/原料/钴.md:42-78 [score=0.0234]
# 钴 / ## 应用
钴是锂电正极材料的关键原料,主要用于动力电池……
→ outlinks (4):
→ digest/knowledge/financial/产品/三元正极.md via predicate=downstream
→ digest/knowledge/financial/公司/嘉能可.md via predicate=producer
→ digest/knowledge/financial/公司/洛阳钼业.md via predicate=producer
→ daily/20260518/三元正极高镍化趋势.md via plain
← inlinks (2):
← daily/20260318/宁德调研纪要.md via plain
← daily/20260512/亿纬电话会.md via plain
digest/knowledge/financial/产品/三元正极.md:15-44 [score=0.0211]
# 三元正极 / ## 高镍低钴路线
2025 年起主流厂商加速 8 系/9 系产品……
→ outlinks (2):
→ digest/knowledge/financial/公司/宁德时代.md via predicate=used_by
→ digest/knowledge/financial/原料/钴.md via predicate=upstream
digest/knowledge/financial/公司/宁德时代.md:88-120 [score=0.0193]
# 宁德时代 / ## 高镍化决策
本季度切换到 9 系三元为主……
digest/knowledge/financial/公司/嘉能可.md:5-30 [score=0.0167]
digest/knowledge/financial/公司/洛阳钼业.md:1-22 [score=0.0152]
========== 第二跳Agent 主动展开邻居 meta不取正文==========
共 9 个邻居节点,按预测相关度排序:
- digest/knowledge/financial/公司/亿纬锂能.md ← 三元正极 used_by 反链
- daily/20260512/亿纬电话会.md ← 宁德时代 inlinks
- daily/20260318/宁德调研纪要.md ← 钴 inlinks
...
```
Agent 不需要把这些邻居正文都拉回来——光看"路径 + name + predicate"就足够拼出上下游骨架。
###### Step 2Agent 基于检索结果合成总览,写回知识库
```
digest/knowledge/financial/产业链/
└── 锂电产业链.md ← 由 Day 5 query 触发合成
内容来源:上一步检索命中的 5 个节点 + 关系
不引入任何 daily 之外的"想象"
```
`锂电产业链.md` 正文:
```markdown
---
name: 锂电产业链总览
source: query-synthesized ← 标记来源是 query 合成
trigger_query: "分析锂电相关上下游"
generated_at: 2026-05-22
generated_from:
- [[钴]]
- [[嘉能可]]
- [[洛阳钼业]]
- [[三元正极]]
- [[宁德时代]]
---
## 上游 · 资源
- 钴矿:[[嘉能可]] / [[洛阳钼业]](刚果金为主产区,详见 [[钴]]
## 中游 · 材料
- 正极:[[三元正极]](高镍化趋势,详见同名笔记)
## 下游 · 电池厂
- [[宁德时代]][[daily/20260318/宁德调研纪要]] 中已确认 9 系切换)
- [[亿纬锂能]][[daily/20260512/亿纬电话会]] 中提到产能规划)
> 本笔记由 query 触发合成;下次再问"锂电上下游"会直接命中此文件,
> 后续 Auto-Link 会在新 daily 事件出现相关实体时增量补连接。
```
###### Step 3Agent 同步给出组会答复
Agent 拿这份合成结果,给王分析师的回复直接带**上下游骨架 + 公司归属 + 历史调研引用**
> "锂电产业链分三段:上游钴矿(嘉能可、洛阳钼业,刚果金集中)、中游三元正极(高镍化加速)、下游电池厂(宁德/亿纬)。这周您提到的事件分别落在:嘉能可三季报 → 上游产能;高镍化趋势 → 中游路线切换;宁德 9 系切换 → 下游产品验证。详细引用见 [[digest/knowledge/financial/产业链/锂电产业链]]。"
**关键差异**:传统 RAG 会一股脑塞 5 个文件正文进上下文ReMe 是"先看 5 个节点的目录骨架 → 拼出总览 → 落盘成可被反复消费的笔记"。下次再问"锂电下游有谁",直接命中这份总览,不用再走一遍合成。
##### Day 7图谱已经长出层次
```
┌─────────────┐
┌────────►│ 锂电产业链 │◄────────┐
│ └──────┬──────┘ ← Day 5 query 合成
│ upstream │ │ upstream
│ │ contains │
┌───────┴──────┐ ▼ ┌──────┴──────┐
│ 钴 │ ┌─────────┐ │ 锂 │
│ (刚果金产区) │◄──┤ 原料 ├────►│ (盐湖产区) │
└───────┬──────┘ └────┬────┘ └─────────────┘
│ producer │ downstream
▼ ▼
┌──────────────┐ ┌──────────────┐
│ 嘉能可 │ │ 三元正极 │◄── 高镍化趋势
│ 洛阳钼业 │ └──────┬───────┘
└──────────────┘ │ used_by
┌──────────────┐
│ 宁德时代 │ ← daily/0318 调研纪要
│ 亿纬锂能 │ ← daily/0512 电话会
└──────────────┘
【实体层 · Auto-Dream 聚合产生】 │
【结构层 · query 合成产生】
```
每条边都对应文件里的一句 `predicate:: [[X]]`,每个节点点开就是 Markdown 笔记,每段笔记都能反向追溯到原始 daily 事件——**没有任何节点是凭空"梦"出来的**。
#### proactive主动洞察推送
每天早上 9:00ReMe 在 `digest/proactive/20260519.md` 里写:
```markdown
---
name: 早间洞察 · 2026-05-19
---
## 与您近期关注主题相关的事件
- **嘉能可宣布刚果(金) Mutanda 矿复产** ← 关联 [[钴]] / [[嘉能可]]
上周您在 [[daily/20260518/嘉能可三季报点评]] 中标注「关注复产节奏」。
→ 复产对钴价的边际影响估计 -5% 到 -8%,可能影响 [[三元正极]] 成本。
- **宁德时代发布麒麟电池新版本** ← 关联 [[宁德时代]] / [[三元正极]]
上次调研([[daily/20260318/宁德调研纪要]])中提到的高镍方案已落地。
```
**这就是金融场景下 ReMe 的核心价值**:分析师只负责"看 + 说"知识图谱自己长出来当行业事件发生时ReMe 主动把"新事件 ↔ 旧上下文"的连线送到分析师面前。
---
### 9.2 个人工作 & 生活第二大脑
**主角**:李工,前端工程师 + 业余跑者 + 有娃奶爸。每天和 Agent 聊工作 bug、读论文、讨论小孩教育、规划周末徒步路线。
**目标**:让所有这些零散的对话沉淀成一份"自己的"知识库,三个月后能用 Obsidian 直接打开浏览。
#### 时间线:从空目录到第二大脑
```
Day 1 Day 7 Day 30 Day 90
│ │ │ │
▼ ▼ ▼ ▼
[空目录] [daily 流水开始堆积] [knowledge 主题浮现] [图谱密集成网]
──────────────────────── Auto-Memory ─────────────────────────────► │
──────────── Auto-Dream每晚 ──────────────────► │
────── Auto-Link持续 ─────────────► │
Obsidian Graph
打开是密集网状
```
#### Day 7daily 流水
```
daily/
├── 20260513.md
├── 20260513/
│ ├── 调试登录页面 CSS 问题.md ← 工作
│ ├── 读《深度工作》第三章.md ← 学习
│ └── 周末徒步路线讨论.md ← 生活
├── 20260514.md
├── 20260514/
│ ├── 团队周会决定切换到 pnpm.md ← 工作
│ ├── 给宝宝挑选英语启蒙绘本.md ← 育儿
│ └── 5km 配速训练记录.md ← 跑步
└── ……
```
打开 `daily/20260513.md`(主索引):
```markdown
---
name: 2026-05-13
---
## 今日事件
- 09:30 [[daily/20260513/调试登录页面 CSS 问题]] · #工作 #前端
- 14:20 [[daily/20260513/读《深度工作》第三章]] · #阅读
- 21:10 [[daily/20260513/周末徒步路线讨论]] · #生活 #徒步
```
#### Day 30Auto-Dream 已经把主题归档好了
```
digest/knowledge/
├── life/ ← 用户自定义二级分类:生活
│ ├── 跑步训练日志.md ← 把 1 个月的「配速训练」事件聚合
│ ├── 阅读笔记/
│ │ ├── 深度工作.md ← 全书要点(从多次 daily 阅读片段汇总)
│ │ └── 给孩子的诗.md
│ └── 徒步路线/
│ ├── 莫干山线.md
│ └── 千岛湖环湖线.md
├── work/ ← 用户自定义二级分类:工作
│ ├── 前端调试技巧.md ← 「调试登录页面 CSS」「修复 z-index」等事件聚合
│ ├── 包管理工具切换决策.md ← 「pnpm vs npm」讨论沉淀
│ └── 团队会议纪要/
└── parenting/ ← 用户自定义二级分类:育儿
├── 英语启蒙书单.md
└── 与孩子沟通技巧.md
```
李工没有手动建过任何一个 `digest/knowledge/` 下的文件——它们都是 Agent 在他睡觉时从 daily 里"梦出来"的。同时 Agent 在 `digest/personal/` 沉淀着对李工的画像("偏前端"、"早睡"、"周末徒步"),但这一层用户不会主动浏览。
#### Day 90Obsidian Graph View 打开是这样
```
[深度工作]
引用 │ 应用到
[跑步训练日志] ◄── 借鉴方法 ── [前端调试技巧] ──► [包管理工具切换决策]
│ ▲ ▲
│ 关联 │ │ 提到
▼ │ │
[徒步路线] [周会纪要] [团队成员]
│ │
│ │ mentions
▼ ▼
[莫干山线] ───── 同行 ────► [Alice] ◄── 育儿讨论 ── [给孩子的诗]
[英语启蒙书单]
```
**这张图是李工的"第二大脑"**——工作、跑步、阅读、育儿、社交关系全部交织在一起能从「Alice」一路联想到「莫干山徒步」再跳到「孩子的英语书单」因为某次徒步同行时聊到过这个话题。
#### 一次具体的"联想式回忆"
某天李工问:"**上次和 Alice 一起聊过的那本书叫什么?**"
```
========== 第一跳daily 命中 ==========
daily/20260420/与 Alice 周末聚餐.md
> ……Alice 推荐了一本讲注意力的书,标题里有「深度」两个字……
← inlinks:
← digest/knowledge/life/阅读笔记/深度工作.md via plain
→ outlinks:
→ digest/personal/Alice.md via mention
========== 第二跳Agent 顺藤摸瓜 ==========
digest/knowledge/life/阅读笔记/深度工作.md
> 卡尔·纽波特2016 年出版……
```
Agent 回:"**《深度工作》,卡尔·纽波特著。** 您在 4/20 周末聚餐时 Alice 推荐的,您后来在 5/13 读了第三章并做了笔记。"
模糊回忆 → 精确召回 → 上下文重建——这是普通"对话历史搜索"做不到的,因为它只会按时间顺序往回翻,而 ReMe 沿着图谱"联想"。
---
### 9.3 Agent 长期陪伴:跨会话的程序化记忆
**主角**:张研发,长期使用 Claude Code 做日常开发。希望 Agent "越用越懂我"——记得我的代码风格偏好,记得过去踩过的坑,记得未完成的任务。
#### 跨会话的记忆生命周期
```
[第 1 次会话] [第 N 次会话N 周后]
│ │
│ 用户在编辑器报错 │ 用户遇到类似报错
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Agent 排查 │ │ Agent 检索 │
│ 试 A 方案 ❌│ ── ReMe ──► │ ReMe 召回 │
│ 试 B 方案 ✅│ │ 上次的 B 方案│
└──────┬──────┘ └──────┬──────┘
│ 写入 │ 直接套用
▼ ▼
digest/ 跳过踩坑1 步解决
├── procedural/
│ └── webpack 编译卡死.md ← Agent 任务经验
└── personal/
└── 代码风格.md ← 用户偏好画像
```
#### 程序化记忆的真实例子
**第 1 次会话2026-03-10**webpack 编译突然卡死。
```
对话过程(摘要)
- 用户:"npm run build 卡在 92% 不动了"
- Agent 试方案 A清缓存 → 没用 ❌
- Agent 试方案 B升级 terser-webpack-plugin → 没用 ❌
- Agent 试方案 C发现是 fork-ts-checker 的 OOM加 --max-old-space-size=8192 → ✅ 成功
```
ReMe 的 Auto-Dream 当晚把这次会话沉淀到:
```markdown
# digest/procedural/webpack 编译卡死.md
---
name: webpack 编译卡死的排查路径
type: programmatic
---
## 症状
build 卡在 92%chunk asset optimization 阶段)。
## 排查顺序(按命中率)
1. ✅ **检查 Node 内存**`NODE_OPTIONS=--max-old-space-size=8192`
→ fork-ts-checker 在大型 TS 项目里很容易 OOM
2. ❌ 清 .cache 缓存(多数情况下无效)
3. ❌ 升级 terser-webpack-plugin仅特定版本相关
## 关联
- 用户偏好:[[digest/personal/代码风格#TypeScript]] 启用了 strict 模式,
类型检查负担大,更易触发 OOM
- 历史事件:[[daily/20260310/webpack 卡死排查]]
```
**第 2 次会话2026-04-226 周后)**:用户在另一个项目又遇到类似问题。
```
用户:"vite build 也卡在打包阶段,是同一类问题吗?"
Agent 内部检索 ReMe
========== 命中digest/procedural/webpack 编译卡死.md ==========
关键词匹配编译卡死、build 阶段
向量相似vite build ≈ webpack build
Agent 回复:
"根据您 3/10 在另一个项目遇到的同类问题,建议优先检查 Node 内存。
vite 的 esbuild 阶段也吃内存,先试 NODE_OPTIONS=--max-old-space-size=8192。
(上次清缓存和升级 plugin 都没用,可以跳过)"
```
**节省的不是时间,是踩坑路径**——这就是程序化记忆的价值。
#### 用户偏好的"自我画像"
`digest/personal/` 下随时间长出的画像:
```markdown
# digest/personal/代码风格.md
---
type: personalization
---
## 命名
- 倾向:函数 camelCase、类型 PascalCase、常量 SCREAMING_SNAKE
- 来源:[[daily/20260215]] 多次纠正 Agent 的命名建议
## 注释
- 倾向:**不写无意义注释**,只在 WHY 不显然时写
- 来源:[[daily/20260301]] 用户原话:"don't comment what the code already says"
## 错误处理
- 倾向:边界处校验、内部代码相信调用方
- 来源:[[daily/20260408]] 用户拒绝在内部函数加 try/catch 时的解释
## 测试组织
- 倾向tests4/unittest 按基类组织(来自项目 CLAUDE.md
```
**意义**:这不是 Agent 在 system prompt 里写死的"用户喜欢简洁",而是**从用户实际行为里被动观察到的、可追溯到具体对话的偏好画像**。每条偏好都有 `[[daily/...]]` 反向链接,用户可以审视、可以修正。
#### 三类记忆在 Agent 陪伴里的分工
回到 [3.2](#32-digest-下的四种记忆) 中 `digest/` 的四个子目录本场景主要由其中三类共同支撑proactive 已在 9.1 主动推送场景演示):
| digest 子目录 | 写入触发 | 检索权重 | 实际表现 |
|----------------------------|----------------|----------|---------------------------------------|
| **digest/personal/** | 用户纠正 / 偏好表达 | 全场景常驻 | "我懂你不爱写注释" |
| **digest/procedural/** | 任务完成后归纳成功/失败路径 | 任务相似度高时高 | "上次这类 bug 你这样解决过" |
| **digest/knowledge/** | 学习对话、文档阅读 | 主题相关时高 | "你之前学过的 React Server Components" |
三类共同织成一个"懂用户 + 会做事 + 有知识"的长期陪伴 Agent——**差异化体验来自 ReMe 维护的个人记忆,而不是模型本身**。换言之,同一个 Claude / Qwen 模型,套上不同用户的 ReMe会变成完全不同的 Agent。
---
## 十、性能与稳定性
### 10.1 自研轻量内核
新版本重写了记忆引擎的核心模块:
- **file chunker** —— Markdown AST + 章节切片 + wikilink 抽取
- **file store** —— 内存 chunk 字典 + JSONL 持久化
- **file graph** —— 双向链接索引,多 backend
- **file watcher** —— 基于 watchfiles 的轻量监听
- **keyword index** —— 自研增量 BM25 倒排,原生支持中文
整体**纯 Python + 文件持久化**,无 sqlite/chroma 等三方原生依赖。
### 10.2 跨平台稳定性
老版本在 qwenpaw 等低版本 Linux/Win 环境会出现 sqlite 段错误、chroma core dump这些问题在新版本完全规避
- 没有 native 扩展依赖。
- 老旧 glibc / 老旧 Python 版本也能跑。
- 安装简单,不需要 cmake、build-essential。
这对一个**要被部署到大量异构用户机器**的产品至关重要。
### 10.3 未来Rust / C++ 高性能内核
- 当前 Python 版本已能覆盖个人规模知识库(万级文件)。
- 规划用 Rust / C++ 重写关键路径BM25 索引、文件解析、向量计算),支撑:
- 更大规模(十万级文件)
- 更低延迟(亚秒级冷启动)
- 更小内存
- 上层 API 不变,对用户和 Agent 接入方完全透明。
---
## 十一、Roadmap
| 阶段 | 关键里程碑 |
|-----------|--------------------------------------------------------------------------------------------------------|
| **Now** | 组件框架、Job/Step、Markdown 内核、混合检索(向量+BM25+图谱、HTTP / MCP / CLI 三协议服务 |
| **Next** | auto-memory / auto-dream / auto-link 全套自进化能力记忆类型分层resource / proactive 目录skill.md 模板qwenpaw SDK 集成 |
| **Later** | 多跳渐进检索 API、领域 demo金融产业链、个人场景模板包、Rust 高性能内核、可视化管理面板 |
每个阶段都有清晰的对外可演示成果:
- Now → 可以现场演示 ReMe 检索 + Agent 集成。
- Next → 可以演示"今天聊的内容明天自动整理好"。
- Later → 可以演示十万级知识库下的亚秒检索 + 主动推送闭环。
---
## 十二、结语ReMe 想成为什么
> ReMe 不止是「记忆库」。
>
> 它的目标是:**让每个用户拥有一张由本地 Markdown 自进化而成、可携带、可被任意 Agent 调用的个人知识图谱。**
>
> 当 Agent 时代真正到来时,差异化的不是模型,而是「这个 Agent 是不是了解我」。
>
> ReMe 想做的就是这份「了解」的载体——一张属于用户自己、Agent 可读可写、会自己生长的图谱。
**三个判断**
1. 个人记忆是 Agent 时代必然出现的基础设施 —— 不是 ReMe 不做就没人做,而是早做的人有先发优势。
2. **本地 Markdown + 自进化 + 知识图谱**(叠加被集成路线)—— 这套组合在当下市场是空缺的。
3. ReMe 的工程内核已经就位,剩下是**自进化能力 + 生态集成 + 场景模板**的三件套加固,路径明确。

View file

@ -1,55 +0,0 @@
- 增加agent 的component
- 增加全局 时区time_zone全局作用
数据结构
- resource
- YYYYMMDD
- xxxx.html
- xxxx.txt
- xxxx.md
- dialog
- YYYYMMDD
- session_{session_id}.jsonl msg->dict格式
- daily
- YYYYMMDD.md 索引
- YYYYMMDD
- session_{session_id}.md 日志本
- resource_{resource_id}.md
- digest
- personal 个性化信息
- xxx.md
- procedural 程序化记忆
- xxx.md
- wiki 知识化记忆
- xxx.md
监控任务【后台】:
- 构建bm25+emb的index【5s】
- 目录daily+digest 的 所有md使用markdown的ast解析
- 可选jsonl要求保存的时候对工具结果截断使用rag方案解析
- daily md监控【1min】
- 暂无
- digest md监控【1min】
- 暂无
- resource 监控【间隔5min】
- 针对每一个文件生成一个hashid作为session_id
- 生成一个agent解读文件读前1MB内容防止上下文炸了
- 把抽取的内容写到daily/YYYYMMDD/resource_{resource_id}.md
- 调用推送工具:
- qwenpaw推送收件箱/agent
- cc可以直接推送agent @sen
hook任务
- auto-memory在上下文满/每隔多少轮/session_end
- qwenpaw直接传message session_id date直接append session_agent_{session_id}.jsonl @jinli
- cc给出新的path对比我们保存的session_{session_id}.jsonl看到增量msg接着解析path的内容保存到session_{session_id}.jsonl @sen
- 注意保存的时候截断工具调用结构,防止太长
定时任务:
- auto-dream每天夜晚触发
- 记忆整理按照session/resource_id去做for循环整理把YYYYMMDD.md + YYYYMMDD/* 消化更新到 digest下的personal/procedural/wiki
- 记忆linkmarkdown之间linkdigest内部链接可以链接到外面。

View file

@ -1,782 +0,0 @@
# reme 系统架构 — 设计文档
## 文档定位
本文档定义 reme 的**架构设计**:概念边界、数据流契约、职责划分。
- 不涉及代码路径 / 实现进度 / API 具体形态
- **执行栈与架构角色**(分层、模块切分、职责划分)在第 6-7 节;源码映射与落地状态见 `docs4/reme_report.md` 与源码
- 不规定怎么做,只规定**是什么、谁负责、输入输出**
> 阅读顺序:**第 1 节**给出完整的架构总览(数据视角 + 运行时视角 + 核心机制 + 不变量 + 导航);**第 2-5 节**逐层展开三层存储 / 6 类 L4 动作语义 / 反向回流 / 触发节奏;**第 6 节**描述底层执行栈(L0→L5);**第 7 节**把 6 类 Action 落到 L4 实现模块;**第 8 节**讲跨切面 schema 契约;**第 9 节**列出明确不属于本架构的反例。
---
## 1. 架构总览
本章给出 reme 完整的设计骨架,后续 §2-§9 逐项展开细节。
### 1.1 解决什么问题
reme 是 agent 的**长期记忆系统**。它把 agent 的工作过程沉淀为可检索、可演化的知识结构。
设计要解耦两件事:
| 关注点 | 由谁负责 |
|---|---|
| **agent 写什么 / 读什么** | agent 的工作流自决 |
| **workspace 自身如何健康演化** | reme 自治,agent 不感知 |
实现方式:三层存储拓扑为"两路并行写入(原始资料 / 任务过程) → 双源合流到沉淀知识层",reme 提供这三层的容器、动作语义、反向检索与自治维护。
### 1.2 数据视角:并行起点 + 双源合流 + 反向回流
数据有**两个并行起点** —— **External source**(webhook/upload/pull)与 **Agent**(外部主体,自身任务驱动)。两条独立通道各自落地到**并行的材料层**:External 经 `ingest` 沉到 `resource/`,Agent 经 `sync` 写到 `daily/`。两层材料**合流**到 `digest/`,由 reme 通过 `digest` 动作完成"消化"。`digest/` 自身由 `maintain` 做 in-place 重组。Agent 通过 `retrieve` 从 resource + daily + digest **三层并行**回流。`notify` 是 reme 跨过 workspace 直接提醒 Agent 的**虚边**(控制信号,不写任何文件)。每段路径都对应一个 L4 动作语义(完整动作详见 §5.2 / §7):
| 路径 | L4 动作 | 说明 |
|---|---|---|
| External source → resource | **ingest** | 外部信源落到 workspace |
| External source ╌╌► Agent | **notify** | reme 推送通知(虚边,只走 L2 推送队列,不写文件) |
| Agent → daily | **sync** | Agent 写 daily(响应 notify 或自身任务驱动) |
| resource + daily → digest | **digest** | reme 内部 LLM 抽取沉淀(双源合流) |
| digest → digest | **maintain** | reme 内部 LLM 折叠重组(in-place, fold-only) |
| resource + daily + digest → Agent | **retrieve** | 三层并行回流(state / semantic / topological 三种正交问法) |
```
notify(虚边,控制信号)
External source ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌► AGENT
(webhook/upload/pull) (外部主体/自身任务)
│ │ ▲
│ ingest │ │ retrieve
│ ┌────── sync ────────────────────-┘ │ (state /
▼ ▼ │ semantic /
┌──────────┐ ┌──────────┐ │ topological)
│resource/ │ │ daily/ │ │
│ 原始资料 │ │任务工作区 │───────── retrieve ─────────────┤
│ 不可变 │ │ 半可变 │ │
└───┬──┬───┘ └────┬─────┘ │
│ │ │ │
│ │ digest digest │ │
│ └────────┐ ┌────┘ │
│ ▼ ▼ │
│ ┌────────────────────┐ │
│ │ digest/ │ ◄──╮ │
│ │ 沉淀知识 │ │ maintain │
│ │ 可重组(语义索引) │ ───╯ (in-place, fold-only) │
│ └──────────┬─────────┘ │
│ │ retrieve │
│ └─────────────────────────────────────-─┤
│ │
│ retrieve │
└──────────────────────────────────────────────────────────┘
```
**模型要点**:
- **两个起点平行,不存在主从** —— External 与 Agent 各自独立驱动;Agent 既可响应 `notify` 也可由自身任务直接 `sync`
- **两层材料平行,不存在传递** —— resource 与 daily 是**两条独立的写入通道**,不互相穿越:Agent 不写 resource,ingester 不写 daily。
- **digest 是双源合流的产物** —— `digest` 动作的输入是 resource + daily 的组合(不是仅 daily);相应地,digest 节点的 provenance 可同时指向 resource 与 daily。
- **digest 自循环** —— `maintain` 在 digest 内部做密度折叠,不与上游材料层交互。
- **notify 是虚边** —— reme 用它提醒 Agent "有新 resource 值得看",但不落任何文件;Agent 的响应通过 `sync` 落 daily(并可选地用 wikilink 引 resource)。
retrieve 三种问法正交:
| 问法 | 工具 | 主要看哪层 |
|---|---|---|
| **state**(谁在 / 是什么状态) | `list` / `frontmatter` | 各层平等 |
| **semantic**(我想到一个意思) | `search` | digest > daily > resource(默认权重) |
| **topological**(从一个点向外摸) | `traverse` | 沿 wikilink 跨层平等 |
### 1.3 运行时视角:六层执行栈 + 双进程
reme 的功能不是堆在一层,而是从文件系统底层往上栈式堆叠。顶层 Service 与 Runtime 是同一套 workspace 上的两个进程角色,共享 L0-L4 全栈(详见 §5.3 / §6)。
```
┌─────────────────────┐ ┌─────────────────────┐
│ L5 Service │ │ L5 Runtime │
│ (HTTP / MCP) │ │ (scheduler 自治) │
└──────────┬───────────┘ └──────────┬──────────┘
│ │
└─────────────┬────────────────┘
┌──────────────────────────────────────────────────┐
│ L4 6 类 Action(动作语义) │
│ ingest notify sync retrieve digest maintain│
└──────────────────────┬───────────────────────────┘
┌──────────────────────────────────────────────────┐
│ L3 原子工具 │
│ ┌─────────────────────┐ ┌──────────────────┐ │
│ │ 基础工具 │ │ 高级工具 │ │
│ │ create/append/edit/ │ │ search │ │
│ │ read/write/move/ │ │ traverse │ │
│ │ delete/list/stat │ │ frontmatter │ │
│ └──────────┬──────────┘ └────────┬─────────┘ │
└─────────────│──────────────────────│─────────────┘
│ 直读 / 直写 │ 走索引读
│ (eventual,有滞后) │
│ ▼
│ ┌────────────────────────────┐
│ │ L2 文件状态 │
│ │ · file_store(chunk+vec) │
│ │ · file_graph(node+link) │
│ │ · 自治状态(scheduler 用): │
│ │ - resource: 入流批次/ │
│ │ 未消化(orphan) │
│ │ - daily: 任务索引 │
│ │ (进行中/stale/完成) │
│ │ - digest: 密度水位/ │
│ │ 断链(broken wikilink) │
│ │ · 推送队列(notify): │
│ │ pending/notified/ │
│ │ acknowledged │
│ └─────────────▲──────────────┘
│ │ 派生 / 更新
│ ┌─────────────┴──────────────┐
│ │ L1 file_watcher │
│ │ fs event → state delta │
│ │ (唯一 fs→state 桥) │
│ └─────────────▲──────────────┘
│ │ 监听
▼ │
┌──────────────────────────────────────────────────┐
│ L0 workspace 文件系统 │
│ resource/ daily/ digest/ │
└──────────────────────────────────────────────────┘
```
Service 与 Runtime 是同一份 workspace 上的两个进程角色:
| 进程 | 触发源 | 时延敏感 | 典型动作 |
|---|---|---|---|
| **Service** | 外部 push / 外部 pull / agent 同步请求 / **MCP 推送通道** | 是 | ingest / sync / retrieve / **notify-out(MCP)** |
| **Runtime** | scheduler 周期 + L2 自治状态阈值 | 否(eventual) | **notify 决策** / digest / maintain |
### 1.4 核心机制总览
| 机制 | 一句话 | 详见 |
|---|---|---|
| 三层存储 | resource(冷) / daily(温) / digest(冷,组织化) | §2 |
| 6 类 L4 动作 | ingest / notify / sync / retrieve / digest / maintain | §1.2 / §3 |
| notify+sync 链 | reme 主动从 L2 资源自治状态选候选,经 MCP 推给 agent;agent sync 落 daily | §3.3-3.4 / §7.1 |
| 反向 retrieval | state / semantic / topological 三种正交问法 | §4 |
| 触发四源 | 外部 push / 外部 pull / agent on-demand / reme 后台 | §5.1-§5.2 |
| Service + Runtime | 双进程角色,共享 L0-L4,职责按时延分 | §5.3 |
| 执行栈(L0-L5) | filesystem → file_watcher → 文件状态 → 原子工具 → Action → Service/Runtime | §6 |
| 原子工具:基础 vs 高级 | 基础直 fs;高级走 L2 索引(eventual) | §6.4 / §5.5 |
| Action 模块映射 | 6 类 Action 由 5 个模块实现(retrieve 直走原子工具) | §7 |
| Schema 跨切面 | name+description 是核心强约束,其余 opinionated default 可重载 | §8 |
### 1.5 核心不变量速览
写入拓扑(架构脊梁,来自 §2.3):两路并行写入(External→resource、Agent→daily)→ 双源合流到 digest;resource 与 daily 之间互不写入;任何一层都不能反向改写它的上游。
| 不变量 | 内容 | 来源 |
|---|---|---|
| **I-1** | agent 不直接写 digest(digest 写权只属 dreamer / maintainer) | §2.4 |
| **I-2** | daily folder 单作者(同 folder 不并发改) | §2.4 |
| **I-3** | resource 内容不可变,只允许 metadata appendable | §2.4 |
| **I-4** | 三层共用同一套 wikilink 索引,跨层引用全靠 wikilink | §2.4 |
| **R-1** | retrieve 三种问法分立,不合并为单一 read verb | §4.3 |
| **M-1** | Maintainer 只做一件事:密度折叠(把碎片叶子折叠到新的中间节点下) | §7.3 |
| **F-1** | L1 `file_watcher` 是 L0→L2 的唯一派生桥 | §6.5 |
| **F-2** | L3 基础工具直接读写 L0;高级工具只走 L2 | §6.5 |
| **F-5** | L5 Service / Runtime 共享 L0-L4,不直接通信 | §6.5 |
| **F-6** | L0↔L2 存在 eventual 窗口,agent 上下文承担近期信息 | §5.5 / §6.5 |
### 1.6 文档导航
| 想了解… | 看 |
|---|---|
| 三层各自的定位、不变量 | §2 |
| 6 类 L4 动作语义(notify / sync / digest / maintain 的输入产出不变量) | §3 |
| Retrieval 的三种问法与跨层语义 | §4 |
| 谁来触发、什么节奏、为什么分两个进程 | §5 |
| 系统从文件系统到 Service 的分层(底层基础) | §6 |
| L4 五个模块的对称结构与 Maintainer 折叠设计 | §7 |
| Schema 协议与重载机制 | §8 |
| 哪些设计不属于本架构(反例与边界) | §9 |
| 术语回查 | 附录 |
---
## 2. 三层存储
### 2.1 一句话定位
| 层 | 一句话 |
|---|---|
| **resource/** | 外部原始资料的**不可变快照**。reme 是容器,不是作者。 |
| **daily/** | agent 的**任务工作区**。folder 是单位,以"日 + 任务"为索引。 |
| **digest/** | 跨任务沉淀的**有组织知识**。以语义(概念/实体/方法)为索引,与时间无关。 |
### 2.2 五维度对照
| 维度 | resource/ | daily/ | digest/ |
|---|---|---|---|
| **组织主轴** | 时间(`<date>/<name>`) | 时间 + 任务(`<date>/<slug>/`) | 语义(`<slug>/<subslug>/...`,任意嵌套) |
| **写权归属** | 入流通道唯一(webhook / upload / pull) | agent(写入任务过程) | dreamer / maintainer(无 agent 直写) |
| **可变性** | 不可变,只追加新文件 | folder 内可反复更新 | 单节点可演化,可被合并/拆分/移动 |
| **不变量** | 写入即冻结,原文永不变 | folder 名 = summary note 名(可移动单元);同 slug 同日只一份 | slug 全局唯一;每 folder 有 canonical entry;wikilink 全路径 |
| **谁在用** | agent(查原文)、dreamer(双源输入之一) | agent(自己的工作记录)、dreamer(双源输入之一) | agent(召回主目标)、maintainer(自维护对象) |
### 2.3 写入纪律:并行写入 + 双源合流
```
External source Agent
│ │
│ ingest │ sync
▼ ▼
┌──────────┐ ┌──────────┐
│resource/ │ │ daily/ │
│ 不可变 │ │ 半可变 │
│(ingester)│ │ (agent) │
└─────┬────┘ └─────┬────┘
│ │
│ digest digest │
└──────────────┐ ┌─────────────┘
▼ ▼
┌──────────────┐ ◄──╮
│ digest/ │ │ maintain
│ 可重组 │ ────╯ (in-place,
│ (dreamer + │ fold-only)
│ maintainer) │
└──────────────┘
```
写权按这个**两层并行 → 单层合流**的拓扑分配:resource 写权专属 ingester(外部入流通道),daily 写权专属 agent(sync 落入,可响应 notify 或自身任务驱动),digest 写权专属 dreamer + maintainer。**resource 与 daily 之间互不写入**(agent 不动 resource,ingester 不动 daily);任何一层都不能反向改写它的上游。这是整个架构的脊梁。
### 2.4 不变量(永远成立)
| # | 不变量 | 否则后果 |
|---|---|---|
| **I-1** | agent 不直接写 digest | digest 的"有组织"性失守,沉淀质量退化 |
| **I-2** | daily folder 单作者(同 folder 不并发改) | 任务边界模糊,sync/digest 竞态 |
| **I-3** | resource content immutable,只允许 metadata appendable | 原文可能消失/被覆写,citation 不可信 |
| **I-4** | 三层共用同一套 wikilink 索引,跨层引用全靠 wikilink | 引入第二套引用机制 → 索引重建复杂 / 跨层关系不可达 |
---
## 3. L4 动作语义详解
§1.2 给出了 6 个 L4 动作在数据视角下的整体形态。本节按动作逐个展开输入 / 产出 / 不变量 / 反例。`ingest`(外部→resource,机械)和 `retrieve`(三层并行回流,只读)分别在 §5/§7.4 与 §4 详述,本节聚焦四个**写动作**:`notify` / `sync` / `digest` / `maintain`
### 3.1 统一原则
四个写动作都遵守:
| 原则 | 内容 |
|---|---|
| **Monotonic content** | 上游内容不可变,下游只能新建节点或加链接,不能改写上游 |
| **Provenance 必须可达** | 任何下游节点必须能通过 wikilink 反查到上游来源 |
| **Wikilink 是新结构的唯一载体** | 跨层关系靠 wikilink,不靠内容拷贝 |
它们都不是"数据搬家",而是"在下游新生成有引用关系的节点"。
### 3.2 四个写动作的本质对照
| 动作 | 上游 → 下游 | 性质 | 上游变化 | 下游变化 |
|---|---|---|---|---|
| **notify** | resource → Agent | **Attention**(推送注意力) | 不变 | 不写 workspace;仅入 L2 推送队列 |
| **sync** | Agent → daily | **Reference**(引用落地) | 不变 | daily 中新增工作记录 + 对 resource 的 wikilink |
| **digest** | resource + daily → digest | **Crystallize**(双源合流结晶) | 不变 | digest 新增节点,wikilink 反指上游来源(daily 与/或 resource) |
| **maintain** | digest → digest | **Reorganize**(重组) | 结构变,内容守恒 | fold-only:引入子中间节点搬叶子,改变拓扑 |
> `notify``sync` 共同实现"resource 中的候选被 Agent 看见并织入 daily"这条**Reference 链**;它们是两个独立的 L4 动作,主体不同(notify 由 Reme 自治触发,sync 由 Agent 触发)。
### 3.3 notify:reme → Agent 推送候选
| 维度 | 内容 |
|---|---|
| 主体 | Reme Runtime(`notifier` 模块) |
| 输入 | L2 资源自治状态:orphan(无 inbound wikilink)/ 入流批次 / 未消化老于 N |
| 产出 | L2 推送队列条目;通过 Service MCP **server-initiated notification** 推到 Agent;**不写任何 workspace 文件** |
| 不变量 | resource 原文 0 修改;**完全单向**,不维护任何反向元数据;`notify` 决策在 Runtime,Service 只作 MCP transport |
| Acknowledge 机制 | L1 watcher 检测到 daily→resource 新 wikilink → L2 推送状态 `notified``acknowledged`,避免重复推送 |
| 反例 | (a) Service 自决推什么 notify(✗-17);(b) notify 写入 workspace(✗-16);(c) Agent 主动调 notify(✗-18) |
### 3.4 sync:Agent → daily 落地
| 维度 | 内容 |
|---|---|
| 主体 | Agent(`synchronizer` 模块在 Service 内编排) |
| 输入 | Agent 当前事件流(响应 `notify` 的候选,**或**自身任务直接驱动) |
| 产出 | daily folder 内的工作叙事;可选地用全路径 wikilink 引 resource(agent 自决,reme 不强制) |
| 不变量 | resource 原文 0 修改;daily 单作者(I-2);folder 名 = summary note 名(可移动单元) |
| Provenance | daily → resource 可达(通过 daily body 中的 wikilink) |
| 反例 | "agent 把 resource 内容拷进 daily" —— 不允许,daily 只持有引用 + 自己的工作记录 |
### 3.5 digest:resource + daily → digest 双源合流结晶
| 维度 | 内容 |
|---|---|
| 主体 | Reme Runtime(`dreamer` 模块,LLM-driven) |
| 输入 | 一组待蒸馏的 daily folder + 相关 resource(双源合流;通常以 daily 任务为线索,顺着 wikilink / 同主题搜索拉入相关 resource 原文) |
| 产出 | digest 中 0~N 个新节点 或 已有节点的更新;新节点必须用 wikilink 反指至少一个上游来源 |
| 不变量 | resource / daily 正文 0 修改;digest 新节点必须 wikilink 反指上游(provenance);digest 节点遵守第 2.4 节列的不变量 |
| Provenance | digest → daily / resource 双源链条可达(资料源是 resource 时直接反指,任务过程是 daily 时反指 daily 进而可达 resource) |
| 反例 | dreamer 改写 resource;dreamer 改写 daily 正文 |
### 3.6 maintain:digest → digest 折叠
| 维度 | 内容 |
|---|---|
| 主体 | Reme Runtime(`maintainer` 模块,LLM-driven,**fold-only**) |
| 输入 | digest/ 当前整体状态 |
| 产出 | 同一 digest/ 树的**密度折叠**(fold):某中间节点下叶子过多时,引入子中间节点把相关叶子归簇 + 写"高密度摘要" |
| 不变量 | 树**只向下生长**(从不反向);叶子内容 0 修改,只被搬位置;新中间节点 = 一个高密度摘要文件;任何节点移动**原子重写所有入边**(retarget);slug 全局唯一在折叠后仍成立 |
| Provenance | digest → daily 的反指链接在折叠后仍有效(retarget 保证) |
| 反例 | merge / move / promote / demote 等改写既有拓扑的操作;改写既有叶子内容 |
> 折叠操作的承诺与决策点见 §7.3。
### 3.7 链接重定向例外
`maintain` 的 retarget 会改写其它节点中指向被移动节点的 wikilink。从字面看,这违反了"上游内容不可变"。
实际上这是 wikilink 系统的**机械性副作用**,不算下游写上游:
| 字面 | 实质 |
|---|---|
| daily 里的 `[[digest/old.md]]` 被改成 `[[digest/new.md]]` | 作者意图("我引用了 X 这个 digest 节点")没变,只是 X 的物理位置变了 |
只要 retarget 保持 wikilink 的**目标语义不变**,就允许它作为机械维护副作用穿越层界。这是这条规则的唯一例外。
---
## 4. Retrieval 反向回流
Retrieval 是把 §3 几条正向写动作反着读:agent 站在结果端,沿 wikilink 反查源头。
### 4.1 三种问法
按 agent 意图分,有三类完全不同的读需求,**正交**,各自独立:
| 问法 | 例子 | 本质 |
|---|---|---|
| **状态问** (State) | "我有哪些 in-progress 的任务?""哪些 resource 还没被引用?" | 在某层做 list + frontmatter 过滤 |
| **语义问** (Semantic) | "关于 auth 重构我知道什么?" | 跨层全文/向量检索 |
| **拓扑问** (Topological) | "auth 概念周围都连了什么?" | 从某节点沿 wikilink 走 |
### 4.2 三层 × 三问法 矩阵
| 问法 | resource/ | daily/ | digest/ |
|---|---|---|---|
| **状态问** | "未处理 resource 清单" | "active / pending-digest 清单" | "孤儿节点 / canonical 缺失 清单"(给 maintain 用) |
| **语义问** | 兜底(原文,信噪比低) | 次优(最新,但未沉淀) | **首选**(沉淀过,信噪比高) |
| **拓扑问** | 通常是叶子(被指向) | daily → resource / digest | digest 内部连接最密 |
### 4.3 设计原则
| # | 原则 | 含义 |
|---|---|---|
| **R-1** | 三种问法分立,不合并为单一 "read" verb | 不同问法的索引、过滤、排序逻辑完全不同 |
| **R-2** | 语义问的默认权重 `digest > daily > resource`,**可被显式覆盖** | 默认体现"沉淀质量",但 agent 可指定单层或调权 |
| **R-3** | 拓扑问与层无关 | traverse 沿 wikilink 走,天然跨三层(I-4) |
| **R-4** | Provenance expansion 默认 lazy,eager 是上层便利封装 | 原子 retrieval 不自动展开;agent 需要时再 traverse |
| **R-5** | Cold start 不是新的 retrieval mode | 只是状态问 + 语义问的组合,reme 不为它单设 verb |
### 4.4 在主干图里的位置
Retrieval 不引入新存储,不引入新层。它是 **agent 与三层存储之间的读视图**,通过三种正交问法暴露,共享同一套 wikilink 索引(I-4)。
---
## 5. 节奏与触发
锁定"谁推动每个动作发生"。这一步定 reme 是纯被动 service 还是带后台 runtime。
### 5.1 触发源四分类
| 触发源 | 性质 | 例子 |
|---|---|---|
| **External push** | 外部事件主动推 | webhook / 用户 upload |
| **External pull** | reme 主动去外部拉 | scheduled fetcher(RSS / 邮件 / API 轮询) |
| **Agent on-demand** | agent 在请求里显式调用 | "sync 我的对话" / "搜 X" |
| **Reme background** | reme 自己的 watcher / scheduler | file_watcher / cron-like |
### 5.2 六个动作的触发归属
| 动作 | 主触发 | 备用触发 | 备注 |
|---|---|---|---|
| **ingest** | External push / pull | — | 外部→resource,机械 |
| **notify** | **Reme background**(cron + L2 资源自治状态阈值) | — | Runtime 决策,Service MCP 推送 |
| **sync** | Agent on-demand | — | agent→daily;notify 的响应也走这里 |
| **digest** | **Reme background** | Agent 显式(后门) | resource + daily 双源合流到 digest |
| **maintain** | **Reme background**(cron + threshold) | Agent / 人工 显式(后门) | digest 内部折叠 |
| **retrieve** | Agent on-demand | — | 三层只读 |
**关键定性**:`notify` / `digest` / `maintain` 三个 reme 自治动作的主控制权**在 reme,不在 agent**。Agent 只负责"响应 notify + 写 daily(响应或自身任务驱动)+ 主动读";不需要记得"该看哪些 resource""该蒸了""该整理了"。
### 5.3 Service + Runtime 双进程结构
把 5.2 的归属直接推出 reme 的基本架构。两进程共享 L0-L4 全栈,只在 L5(进程入口)分叉:
```
┌──────────────────────────────────────────────────────────┐
│ Reme System │
│ │
│ ┌────────────────────┐ ┌────────────────────────┐ │
│ │ L5 Service │ │ L5 Runtime │ │
│ │ (HTTP / MCP) │ │ (scheduler 自治) │ │
│ │ 服务 agent 请求: │ │ 服务 workspace 健康: │ │
│ │ · ingest │ │ · notify(决策) │ │
│ │ · sync │ │ · digest │ │
│ │ · retrieve │ │ · maintain │ │
│ │ · notify(MCP 推送)│ │ │ │
│ └─────────┬──────────┘ └───────────┬────────────┘ │
│ │ │ │
│ └──────────────┬───────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ L4 Action / L3 原子工具 │ │
│ │ Action 编排 → 基础工具 + 高级工具 │ │
│ └──────────────────────┬───────────────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ L2 文件状态(file_store + file_graph + 自治) │ │
│ └──────────────────────▲───────────────────────────┘ │
│ │ 派生 │
│ ┌──────────────────────┴───────────────────────────┐ │
│ │ L1 file_watcher(fs → state 的唯一桥) │ │
│ └──────────────────────▲───────────────────────────┘ │
│ │ 监听 │
│ ┌──────────────────────┴───────────────────────────┐ │
│ │ L0 workspace filesystem │ │
│ │ resource/ daily/ digest/ │ │
│ └──────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
两进程职责正交、共享 L0-L4 基础设施(详见 §6):
| 维度 | L5 Service | L5 Runtime |
|---|---|---|
| 触发方式 | 请求-响应 + MCP server-initiated 推送 | 周期 + L2 自治状态阈值 |
| 服务对象 | agent | workspace 自身 |
| 暴露给 agent | 是 | 否(agent 不感知) |
| 主要动作 | ingest / sync / retrieve / **notify 推送通道**(MCP) | **notify 决策** / digest / maintain |
| 与对端的耦合 | 通过 L2 推送队列读 notifier 产出 | 通过 L2 推送队列写,**不直接调 Service** |
### 5.4 节奏(latency tolerance)
| 动作 | 节奏 | latency 容忍 |
|---|---|---|
| retrieve | request-driven | sub-second |
| ingest | event-driven | seconds |
| sync | agent on-demand | seconds |
| **notify** | reactive(L2 资源状态变化后) | seconds ~ minutes |
| digest | reactive(状态变化后) | minutes ~ hours(eventual consistency) |
| maintain | periodic | days(无紧迫) |
实时性需求差三个数量级。这是 digest / maintain 必须放后台异步的根本原因 —— 不能阻塞 agent 的 retrieve / sync 请求。
### 5.5 排序约束与一致性模型
部分动作对**不能并发**,background runtime 内部要保证排序:
| 约束 | 原因 |
|---|---|
| **sync(同一 daily)→ digest(同一 daily)** | digest 不能看到 sync 半成品 |
| **digest(同一 scope)→ maintain(同一 scope)** | maintain 重组的拓扑不应被 digest 中途插入 |
ingest / retrieve 跟所有动作都可并发(纯入流 + 纯读)。
**一致性模型 = Eventual consistency on digest/maintain**。Agent 不能依赖"我刚写完 daily 就能查到对应 digest"。digest / maintain 都是后台异步,有可见的延迟窗口。
**watcher 滞后契约(L0 ↔ L2)**:基础工具直接写 L0 文件系统,L2 文件状态由 L1 file_watcher 派生,二者之间存在 eventual 窗口 —— 写完一份 daily 后,search / traverse 这类走 L2 索引的高级工具不一定立刻能看到。这是设计意图,不是 bug:agent 本身有上下文窗口,近期信息靠 agent 自带的对话上下文承接,不依赖 reme 索引立即可见。需要"写后立刻可读"的场景请用基础工具(read 直接读 fs)。
---
## 6. 执行栈:六层结构
L3 原子工具、L4 Action、L5 进程都不直接操作文件系统。它们坐在 L0-L2 的**底层基础**上 —— 这套基础是 reme 的"动力源",决定了为什么上层能解耦成 Service + Runtime 两进程,且两者既正交又共享状态。
### 6.1 概念分层(L0 → L5)
```
┌──────────────────────────────────────────────────────────┐
│ L5 Service ‖ Runtime │
│ 进程入口:Service 服务 agent;Runtime 自治维护 │
├──────────────────────────────────────────────────────────┤
│ L4 Action(6 类动作语义) │
│ ingest / notify / sync / retrieve / digest / maintain │
├──────────────────────────────────────────────────────────┤
│ L3 原子工具 │
│ 基础工具(直接 fs) + 高级工具(走 L2 索引) │
├──────────────────────────────────────────────────────────┤
│ L2 文件状态 │
│ file_store + file_graph + 自治状态(scheduler 用) │
├──────────────────────────────────────────────────────────┤
│ L1 file_watcher │
│ fs event → state delta(唯一 fs→state 桥) │
├──────────────────────────────────────────────────────────┤
│ L0 workspace filesystem │
│ resource/ + daily/ + digest/ │
└──────────────────────────────────────────────────────────┘
数据流(主要关系):
· L3 基础工具 ──写──► L0
· L3 基础工具 ──读──► L0(无需经 L2)
· L0 变化 ──► L1 监听到 ──派生──► L2 state delta
· L3 高级工具 ──读──► L2(走索引)
· L4 Action ──编排──► L3 工具组合
· L5 进程 ──触发──► L4 Action
```
| 层 | 角色 | 关键约束 |
|---|---|---|
| L0 | workspace 文件系统 | 唯一真相源;任何 L2 状态都可由 reindex 从 L0 重建 |
| L1 | `file_watcher` | **唯一**与 fs 事件直接耦合的组件;fs→state 的唯一派生桥 |
| L2 | 文件状态(`file_store` + `file_graph` + 自治状态) | 高级工具的读视图;由 L1 单向更新,L3+ 只读不写 |
| L3 | 原子工具(基础 / 高级) | 基础直读写 L0;高级只走 L2 |
| L4 | Action(6 类语义动作) | N:M 编排 L3 工具;不直接碰 L0 / L2 |
| L5 | Service / Runtime 进程 | 共享 L0-L4 全栈,**不直接通信**,只通过 L0 / L2 状态间接耦合 |
### 6.2 L1 file_watcher:fs → state 的唯一桥
`file_watcher` 是 reme 唯一与 OS filesystem 事件直接耦合的组件。它把 fs 变化翻译为 L2 文件状态的 delta,承担**双重职责**:
```
filesystem events (create / modify / move / delete)
file_watcher ─┬─► 索引同步:写完文件,L2 file_store/file_graph 自动更新
│ (L3 基础工具不需要显式调用"入索引")
└─► 自治状态派生:维护 scheduler 用的可推导状态
· resource: 入流批次 / 未消化(orphan) /
推送状态(pending/notified/acknowledged)
· daily: 任务索引(进行中 / stale / 完成)
· digest: 密度水位 / 断链(broken wikilink)
```
**关键设计**:可派生的状态由 watcher 在外部索引中维护,**不写回 frontmatter**。L3 工具只管写内容文件,状态由 watcher 独立派生。这是 ✗-14 反例(L3 写 `status` 字段)成立的基础。
**Acknowledge 派生例**:`notify` 的"推送状态"由 watcher 维护 —— 当 watcher 检测到一条新 wikilink 从 daily 指向某 resource,即把该 resource 的推送状态从 `notified` 改为 `acknowledged`。notifier / Service 都不需要显式 ack。
### 6.3 L2 文件状态
| 组件 | 职责 | 由谁更新 |
|---|---|---|
| `file_store` | chunk 分块 + 向量持久化,提供 search / read API | L1 watcher 派生 |
| `file_graph` | wikilink 有向图,提供 upsert / traverse(双向)API | L1 watcher 派生 |
| **自治状态** | scheduler 自治决策的输入(入流批次 / 任务索引 / 密度水位 / 断链) | L1 watcher 派生 |
| **推送队列** | `notify` 的待推送 / 已推送 / 已确认条目 | notifier 写 pending;Service 推送后置 notified;L1 watcher 检测到 ack 后置 acknowledged |
L2 只关心"workspace 当前是什么样",**无业务语义** —— 不知道 daily / digest / 动作语义的存在。L3+ 只读 L2,不写(**例外**:notifier 写推送队列,这是 Runtime 与 Service 之间唯一的间接耦合通道,见 F-5)。
> **现状提示**:当前实现中 file_store / file_graph 之外的"自治状态"和"推送队列"尚不完整,这是 L1 watcher 与 notifier 待补齐的能力。完整化后 scheduler 才能从"周期扫描"切换为"事件驱动",`notify` 才能从隐式变为显式。
### 6.4 L3 原子工具:基础 vs 高级
两组工具的切分依据只有一条:**是否必须经过 L2 索引**。
| 组别 | 工具 | 数据通路 | 一致性 |
|---|---|---|---|
| **基础工具** | create / append / edit / read / write / move / delete / list / stat | 直接对接 L0 | 写后立即可读(同一工具) |
| **高级工具** | search / traverse / frontmatter | 必须走 L2 索引 | 受 watcher 滞后影响(eventual) |
**写路径全部走基础工具**(L4 Action 编排基础工具完成写入)。高级工具是**只读**的索引查询入口。
**eventual 窗口**:基础工具写 L0 后,L2 索引由 L1 watcher 异步追平。在窗口内,高级工具看到的是滞后的视图。详见 §5.5"watcher 滞后契约"。
### 6.5 设计含义
| # | 不变量 | 推论 |
|---|---|---|
| **F-1** | L1 `file_watcher` 是 L0 → L2 的**唯一**派生桥 | 状态一致性是 L1 的事;L3 工具不要"自己更新索引" |
| **F-2** | L3 基础工具直接读写 L0;L3 高级工具只走 L2 | 写路径无需"先 reindex";读路径接受 eventual |
| **F-3** | L0 是唯一真相源 | 任何 L2 状态都可由 reindex 从 L0 重建,L2 是缓存而非数据库 |
| **F-4** | L4 Action 与 L3 工具是 N:M 编排关系 | Action 不直接碰 L0 / L2 |
| **F-5** | L5 Service 与 Runtime 共享 L0-L4 全栈,**不直接通信** | 只通过 L0 / L2 状态间接耦合;一边崩了不影响另一边的读 |
| **F-6** | L0 与 L2 之间存在 eventual 窗口 | agent 上下文承担近期信息,不依赖 L2 立即可见(详见 §5.5) |
---
## 7. L4 Action 模块映射
第 5 节列了 6 类 Action 及其触发源,本节把这些 Action 落到 **L4 实现模块**(架构角色,不指代源码路径);触发机制(on-demand 路径与 background 路径)见 §5.3。
### 7.1 五个 L4 模块
| 模块 | 实现动作 | 触发 | LLM-driven | 单一职责 |
|---|---|---|---|---|
| **ingester** | ingest | External push / pull | × | 原样落 resource + 抽 frontmatter + 入索引 |
| **notifier** | notify | Reme background(cron + L2 资源自治状态阈值) | × | 从 L2 资源自治状态选候选 → 写 L2 推送队列;Service MCP 拿走 |
| **synchronizer** | sync | Agent on-demand | ✓ | 把当下事件织入 daily 工作叙事 |
| **dreamer** | digest | Reme background | ✓ | resource + daily 双源合流成 digest 长期条目 |
| **maintainer** | maintain | Reme background | ✓ | digest topic tree 的**密度折叠**(fold-only) |
`retrieve` 不构成独立 L4 模块,理由见 §7.4。
**三个 reme 自治模块**:notifier(机械)、dreamer(LLM)、maintainer(LLM)。三者都由 scheduler 触发,都消费 L2 自治状态,但只有 notifier 是机械的 —— 候选选择不需要 LLM,LLM 决策在 agent 侧的 sync。
### 7.2 对称结构
```
跨表征层翻译 结构性纪律
(LLM-driven) (机械)
Inbound: ingester
Attention: notifier
Working: synchronizer
Sink: dreamer
Organization: maintainer (fold-only)
```
五类不同方向的"翻译":
| 模块 | 翻译方向 |
|---|---|
| ingester | 外部异构格式 → workspace 统一文件 |
| notifier | L2 资源自治状态 → agent 注意力(`notify` 推送) |
| synchronizer | agent 事件流 → 工作过程叙事(写 hot) |
| dreamer | 工作过程 + 原始资料 → 长期知识(双源合流,写 cold) |
| maintainer | 散乱叶子 → 有层次的 topic tree(组织 cold) |
ingester 和 notifier 是机械(确定性阈值/流水线);其它三个是 LLM 决策模块,各自跨越一层语义鸿沟。
### 7.3 Maintainer:Topic Tree 密度折叠
`digest/` 整体视为一颗 **topic tree**:文件夹 = 中间节点,文件 = 叶子。Maintainer 唯一职责:随写入持续,某中间节点下叶子过密时,**折叠**为新的子中间节点 + 高密度摘要。
```
触发前:某中间节点叶子过多 / 太碎
digest/infra/
├── logging.md
├── tracing.md
├── metrics.md
├── alerting.md
├── dashboards.md
└── slo.md
折叠后:LLM 判断聚类,引入子中间节点 + 摘要
digest/infra/
├── observability/ ← 新中间节点
│ ├── _index.md ← 新生成的高密度摘要
│ ├── logging.md ← 内容不变,只搬位置
│ ├── tracing.md
│ ├── metrics.md
│ ├── alerting.md
│ ├── dashboards.md
│ └── slo.md
└── ...(未被折叠的叶子原位)
```
**设计承诺**(在 `maintain` 通用不变量之上进一步收紧):
| # | 承诺 | 含义 |
|---|---|---|
| **M-1** | **Fold-only**,无 merge / move / promote / demote / introduce | 树只向下生长,从不反向 |
| **M-2** | 叶子内容 0 修改,只被搬位置 | 与 `maintain` 内容守恒一致 |
| **M-3** | 新中间节点带一个高密度摘要文件,读摘要就能决定要不要深入 | 折叠后可读性不降反升 |
| **M-4** | 每次只处理一个候选节点 | 最小化变更面 |
| **M-5** | 不能聚类时,**不动**(默认保守) | 宁可不折,不要错折 |
LLM 唯一的决策点:
1. 这些叶子能不能聚类(if not → 不动)
2. 新中间节点叫什么、摘要怎么写
其它都机械:阈值判断(L1 file_watcher 派生 L2 自治状态提供信号)、移动文件(crud)、wikilink 重定向(graph/retarget)。
### 7.4 为什么没有 retriever 模块
L4 模块的存在条件 = "有跨原子编排 / 需要 LLM 决策"。Retrieve 不满足:
- 三种问法(state / semantic / topological)各自被 **L3 原子工具**直接覆盖(list+filter / search / traverse)
- 没有跨原子状态、没有 LLM 决策点
- Agent 直接调用 L3 原子即可
---
## 8. 跨切面:Schema
Schema(资料的 frontmatter / wikilink / 章节约定)是横跨三层、各写动作的共同契约。reme 的核心立场:
| 立场 | 说明 |
|---|---|
| **reme 核心只保留 `name` / `description` 两个字段** | 其它都是 opinionated convention,服务消费层可以替换 |
| **Schema 是"协议"不是"代码"** | 用 markdown 文字描述,LLM agent 自我约束;不内嵌 schema validator |
| **三层共用同一套 wikilink 协议** | 全路径引用,无 short-link / no-ext 解析 |
### 8.1 协议文档(opinionated default)
| 内容 | 谁规定 |
|---|---|
| 目录结构(三层 + folder 单位) | 第 2 节本文档 |
| 动作语义契约(notify / sync / digest / maintain 的输入产出不变量) | 第 3 节本文档 |
| Frontmatter 推荐字段(4 轴等) | `reme/steps/jobs/protocol.md` (opinionated) |
| 章节约定(Objective/Plan/Progress/...)| sync / digest 各自的 prompt(opinionated) |
### 8.2 重载入口
服务消费层(plugin / 自定义 caller)无需 fork reme,可通过以下方式替换 schema:
| 入口 | 适用场景 |
|---|---|
| 替换 protocol 文档 | 改 frontmatter / wikilink / 章节约定 |
| 替换 prompt 模板 | 改 sync / digest 的决策流程 |
| 替换 toolkit | 改 ReAct agent 可见的工具集 |
---
## 9. 反例:不属于本架构的设计
明确画出**不允许**的设计,免得后续讨论或扩展时滑回去:
| # | 反例 | 违反的不变量 |
|---|---|---|
| ✗-1 | Agent 通过任意 verb 直接写 digest | I-1(digest 写权只属 dreamer / maintainer) |
| ✗-2 | 多 agent 并发改同一个 daily folder | I-2(daily 单作者) |
| ✗-3 | 任何动作改写 resource 的原文 | I-3(resource immutable) |
| ✗-4 | 跨层引用引入第二套机制(hash-id / external ref / SQL) | I-4(wikilink 是唯一跨层载体) |
| ✗-5 | dreamer 改写 daily 正文 | `digest` 不变量(§3.5) |
| ✗-6 | maintain 改写 daily / resource 的语义内容 | `maintain` 不变量(§3.6) |
| ✗-7 | `notify` 维护 resource 上的 `referenced_by` 反指 | `notify` 完全单向(§3.3) |
| ✗-8 | 把 state / semantic / topological 合并成单一 read verb | R-1 |
| ✗-9 | Retrieve 自动 eager-expand provenance | R-4 |
| ✗-10 | digest / maintain 同步阻塞 agent 请求 | 5.4 节奏分级 |
| ✗-11 | digest / maintain 强一致(agent 写完 daily 立即可查 digest) | 5.5 eventual consistency |
| ✗-12 | maintainer 做 merge / move / promote / demote 等"通用重组" | M-1(fold-only) |
| ✗-13 | maintainer 改写既有叶子的内容(不只是搬位置) | M-2(叶子内容 0 修改) |
| ✗-14 | L4 模块在 frontmatter 里写 `status` / `pending` 等可派生状态字段 | 状态由 L1 file_watcher 派生到 L2 自治状态,L4 不重复 |
| ✗-15 | 为 retrieve 单设 L4 模块或聚合 verb | §7.4(L3 原子已足够) |
| ✗-16 | notify 写入 workspace(在 resource 上加 `notified` frontmatter 或新建 daily 占位) | notify 只写 L2 推送队列,**不落任何文件**;ack 由 L1 watcher 检测 wikilink 派生 |
| ✗-17 | Service 自决推什么 notify 候选 | notify 决策在 Runtime(notifier);Service 只是 MCP transport,从 L2 推送队列读取(F-5) |
| ✗-18 | agent 主动调用 `notify` 想"标记这个 resource 我要看" | notify 是 reme→agent 单向,反向是 agent 用 sync 写 wikilink(自然 ack) |
---
## 附录:术语索引
| 术语 | 定义 |
|---|---|
| **resource/** | 不可变原始资料层 |
| **daily/** | agent 任务工作区层 |
| **digest/** | 沉淀知识层 |
| **State 问** | 在某层做 list + 过滤的状态查询 |
| **Semantic 问** | 跨层全文/向量检索 |
| **Topological 问** | 沿 wikilink 走的拓扑查询 |
| **Provenance** | 下游节点反查到上游来源的能力 |
| **Retarget** | 节点移动时对所有入向 wikilink 的原子重写 |
| **L5 Service** | 服务 agent 请求的进程(HTTP / MCP);执行栈最上层;也是 notify 的 MCP transport |
| **L5 Runtime** | 自治维护 workspace 的进程;scheduler 在其中按 L2 自治状态阈值触发 background Action |
| **L4 Action** | 6 类动作语义:ingest / notify / sync / retrieve / digest / maintain |
| **L4 模块** | 实现 Action 的架构角色;五个:ingester / notifier / synchronizer / dreamer / maintainer(retrieve 不构成独立模块) |
| **ingester** | L4 模块,机械:外部源原样落 resource + 抽 frontmatter + 入索引 |
| **notifier** | L4 模块,机械:从 L2 资源自治状态选 notify 候选 → 写 L2 推送队列;Service MCP 拿走推给 agent |
| **synchronizer** | L4 模块,LLM-driven:agent 事件织入 daily 工作叙事;响应 notify 的也走这里 |
| **dreamer** | L4 模块,LLM-driven:resource + daily 双源合流为 digest 长期条目 |
| **maintainer** | L4 模块,LLM-driven,**fold-only**:digest topic tree 的密度折叠 |
| **scheduler** | L5 Runtime 内部触发器:按 cron + L2 自治状态阈值拉起 background L4 模块(notifier / dreamer / maintainer) |
| **Topic tree** | digest/ 的心智模型:文件夹 = 中间节点,文件 = 叶子 |
| **Fold(密度折叠)** | maintainer 唯一操作:把过密叶子归簇到新子中间节点 + 写高密度摘要 |
| **L3 原子工具** | 基础(create/append/edit/read/write/move/delete/list/stat,直 fs)+ 高级(search/traverse/frontmatter,走 L2)两组 |
| **L2 文件状态** | `file_store` + `file_graph` + 自治状态(resource 入流批次/orphan、daily 任务索引、digest 密度水位/断链)+ 推送队列;由 L1 派生(推送队列由 notifier 写) |
| **L2 推送队列** | `notify` 的 L2 状态条目;notifier 写 pending,Service MCP 推送后置 notified,L1 watcher 检测到 daily→resource wikilink 后置 acknowledged |
| **L1 file_watcher** | fs event → L2 state delta 的唯一派生桥;承担索引同步 + 自治状态派生 + `notify` ack 派生 |
| **L0 workspace filesystem** | 物理目录:resource/ + daily/ + digest/;唯一真相源 |
| **Eventual consistency** | digest / maintain 异步处理,有可见延迟窗口;L0↔L2 之间 watcher 滞后窗口同理 |
| **Opinionated default** | reme 提供的参考实现,服务层可替换 |

View file

@ -1,38 +0,0 @@
- reme_session/
- agentscope|claude_code / # 使用内置的agent wrappersession会保存在这里
{session_id}.jsonl UUID格式要求 # /Users/yuli/workspace/ReMe/reme/components/agent_wrapper
- dialog/
{session_id}.jsonl # auto memory保存 可以监控可以被检索【可选】
- resource/
- YYYY-MM-DD/
- {channel}_{xxxx}.html
- {channel}_{xxxx}.md
- daily/【日记,浅加工】
- YYYY-MM-DD.md
- YYYY-MM-DD/
- {session_id}.md
- {和resource同名}.md
- digest/
- personal/
- procedure/
- wiki/
函数接口:
- auto_memory
- message 应该会 会保存到 reme_session/dialog/{session_id}.jsonl
- 通过 message 更新 daily/YYYY-MM-DD/{session_id}.md
- auto-resource
- 会保存到 daily/YYYY-MM-DD/{resource_stem}.md
- auto-dream
- 读取所有的md
- 会生成link auto-link
- 会生成topic
- proactive
- 会读取topic
- search
后台任务:
- index_update_loop 索引监控
- resource_watch_loop 资源监控
- digest_watch_loop 应该是闲置?

View file

@ -1,68 +0,0 @@
# Jupyter Book settings — Chinese docs (built as a standalone book, served at /zh/).
# Learn more at https://jupyterbook.org/customize/config.html
project: "ReMe"
title: "<div style='text-align:center'>
<span style='font-weight:700;color:#2196f3;'>AgentScope</span><br>
<span style='font-weight:900;color:#ff5722;'>ReMe</span>
</div>"
author: Alibaba Tongyi Lab
logo: ../figure/reme_logo.png
copyright: "2025, Tongyi Lab, Alibaba Inc."
only_build_toc_files: true
execute:
execute_notebooks: off
parse:
myst_enable_extensions:
- colon_fence
- deflist
- attrs_inline
- dollarmath
sphinx:
extra_extensions:
- sphinx_design
- sphinxcontrib.mermaid
config:
# Render ```mermaid fences as diagrams; generate heading anchors for in-page links.
myst_fence_as_directive:
- mermaid
myst_heading_anchors: 4
# Theme
html_theme: furo
pygments_style: "friendly"
html_show_sphinx: false
html_last_updated_fmt: "%Y-%m-%d"
html_copy_source: false
html_show_sourcelink: false
# Shared assets live in docs/_static (custom.css + the language switcher).
html_static_path:
- "../_static"
html_css_files:
- custom.css
html_js_files:
- switcher.js
use_multitoc_numbering: false
html_theme_options:
sidebar_hide_name: false
source_repository: "https://github.com/agentscope-ai/ReMe"
source_branch: "main"
source_directory: "docs/zh/"
footer_icons:
- name: GitHub
url: "https://github.com/agentscope-ai/ReMe"
html: |
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
</svg>
class: ""
light_css_variables:
color-brand-primary: "#2196f3"
color-brand-content: "#2196f3"
color-admonition-background: "#f8f9fa"
dark_css_variables:
color-brand-primary: "#64b5f6"
color-brand-content: "#64b5f6"

View file

@ -1,24 +0,0 @@
format: jb-book
root: index
parts:
- caption: 入门
chapters:
- file: quick_start
- caption: 核心概念
chapters:
- file: memory_as_file
- file: framework
- caption: 记忆
chapters:
- file: auto_memory
- file: auto_resource
- file: auto_dream
- file: auto_link
- caption: 检索与主动
chapters:
- file: memory_search
- file: proactive
- caption: 社区
chapters:
- file: contributing

View file

@ -1,95 +0,0 @@
# 概览
<p align="center"><em>Remember Me, Refine Me —— 面向 AI Agent 的记忆管理工具箱</em></p>
<p align="center">
<img src="../figure/design-philosophy.svg" alt="ReMe 设计哲学" width="92%">
</p>
ReMe 把对话和资源转化为**可读、可写、可检索的文件化长期记忆**:长期记忆不再藏在黑盒数据库里,
而是落在 workspace 目录中的 Markdown 文件里,用户和 Agent 都能直接读写、移动、删除。
## ✨ 核心理念
::::{grid} 1 1 2 2
:gutter: 3
:::{grid-item-card} 📄 文件即记忆
Markdown 文件 + frontmatter + wikilink 作为记忆节点,用户和 Agent 都能直接编辑。
:::
:::{grid-item-card} 🌱 自进化知识库
Auto Memory / Resource / Dream 把对话与资源逐步沉淀为长期记忆,并自动织入 wikilink 关系。
:::
:::{grid-item-card} 🔎 渐进式混合检索
wikilink + BM25 + 向量召回,融合关键词匹配、语义召回与关系展开。
:::
:::{grid-item-card} 🤝 Agent 友好集成
`SKILL.md` + CLI 集成,让不同 Agent 都能读、写、维护和复用记忆。
:::
::::
## 🔄 记忆流水线
ReMe 的能力沿一条 **写入 → 沉淀 → 读取** 的流水线组织:
- **写入** —— [Auto Memory](auto_memory.md) 把对话沉淀为 daily 卡片,
[Auto Resource](auto_resource.md) 解读资源文件。
- **沉淀** —— [Auto Dream](auto_dream.md) 把 daily 抽取整合为长期 `digest/`
[Auto Link](auto_link.md) 在此过程中织入来源与关联 wikilink。
- **读取** —— [Memory Search](memory_search.md) 做混合检索与链接展开,
[Proactive](proactive.md) 暴露“今天值得主动关注什么”。
底层的文件模型与运行时分别见 [Memory as File](memory_as_file.md) 与 [代码框架](framework.md)。
## 📚 开始阅读
::::{grid} 1 2 2 3
:gutter: 3
:::{grid-item-card} 🚀 快速开始
:link: quick_start
:link-type: doc
安装、启动,完成第一次写入、索引与检索。
:::
:::{grid-item-card} 📄 Memory as File
:link: memory_as_file
:link-type: doc
文件化记忆模型分层、frontmatter、wikilink、chunking。
:::
:::{grid-item-card} 🏗️ 代码框架
:link: framework
:link-type: doc
Application / Service / Job / Step 运行时与依赖注入。
:::
:::{grid-item-card} 🧠 Auto Memory
:link: auto_memory
:link-type: doc
对话如何沉淀为 daily 记忆卡片并保留出处。
:::
:::{grid-item-card} 🔎 Memory Search
:link: memory_search
:link-type: doc
索引构建、混合召回与渐进式链接展开。
:::
:::{grid-item-card} ✨ Proactive
:link: proactive
:link-type: doc
读取当天兴趣主题,驱动主动提醒与洞察。
:::
::::

View file

@ -43,7 +43,7 @@ resource/
├── cobalt-policy.md
└── cathode-trend.md
reme_session/
session/
└── dialog/
└── 2026-05-18-close.jsonl
@ -59,7 +59,7 @@ daily/
对应链路:
- `auto_memory` 保存原始对话到 `reme_session/dialog/<session_id>.jsonl`,再让 Agent 把重要事实写入 `daily/<date>/<session_id>.md`
- `auto_memory` 保存原始对话到 `session/dialog/<session_id>.jsonl`,再让 Agent 把重要事实写入 `daily/<date>/<session_id>.md`
- `resource_watch_loop` 监听 `resource/` 文本文件变化,并触发 `auto_resource_step` 写同名 daily note。
- `daily_create` 会维护 `daily/<date>.md` 当天索引页。
@ -269,7 +269,7 @@ Agent 排查过程:
`auto_memory` 写入:
```text
reme_session/dialog/build-oom-2026-03-10.jsonl
session/dialog/build-oom-2026-03-10.jsonl
daily/2026-03-10/build-oom-2026-03-10.md
```
@ -358,7 +358,7 @@ Agent 回复可以直接跳过低价值路径:
- `digest/procedure/` 保存“怎么做”和“哪些路径无效”,让 Agent 复用排查经验。
- `digest/personal/` 保存用户偏好,让 Agent 跨会话遵守同一工程风格。
- 原始对话仍在 `reme_session/dialog/`daily 记录可追溯digest 只是长期提炼结果。
- 原始对话仍在 `session/dialog/`daily 记录可追溯digest 只是长期提炼结果。
## 场景三:个人第二大脑