mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-08-28 05:25:04 +00:00
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:
parent
b1c9bf67bf
commit
6a2dd02e48
30 changed files with 741 additions and 5397 deletions
155
AGENTS.md
Normal file
155
AGENTS.md
Normal 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
1
CLAUDE.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
AGENTS.md
|
||||
15
README.md
15
README.md
|
|
@ -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
|
||||
|
||||
[](https://www.star-history.com/#agentscope-ai/ReMe&Date)
|
||||
|
|
|
|||
11
README_ZH.md
11
README_ZH.md
|
|
@ -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 历史
|
||||
|
||||
[](https://www.star-history.com/#agentscope-ai/ReMe&Date)
|
||||
|
|
|
|||
23
docs/README.md
Normal file
23
docs/README.md
Normal 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/` 中维护对应副本。
|
||||
- 网页文档、导航、版本和部署在统一文档仓库中维护。
|
||||
|
|
@ -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>
|
||||
78
docs/_static/custom.css
vendored
78
docs/_static/custom.css
vendored
|
|
@ -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);
|
||||
}
|
||||
|
||||
54
docs/_static/switcher.js
vendored
54
docs/_static/switcher.js
vendored
|
|
@ -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
85
docs/doc.md
Normal 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 严格校验。
|
||||
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
106
docs/en/index.md
106
docs/en/index.md
|
|
@ -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
465
docs/en/reme_scene.md
Normal 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.
|
||||
|
|
@ -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 健康面板
|
||||
|
||||
各阶段实现进度详见各自文档的"下一步"章节。
|
||||
|
|
@ -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 类型加权)
|
||||
|
|
@ -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` 共同作为契约依据。
|
||||
|
|
@ -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` 共同作为契约依据。
|
||||
|
|
@ -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
|
||||
|
|
@ -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_tool,http服务接口等
|
||||
- [✅ 已实现(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 parser,file store,file graph,file 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 两种 tokenizer,jieba 含 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 配置。
|
||||
|
|
@ -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
|
||||
|
||||
# 列出所有可用 action(client 端处理,不转服务端)
|
||||
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. 抽象基类
|
||||
ⅰ. graph:fellow 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 在前,加载graph,file_watcher在后,递归扫描目录
|
||||
a. 通过ms_time对比graph,on_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. 原子steps:reme 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
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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. Schema(Pydantic 数据模型)
|
||||
|
||||
代码:`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 skeleton(TOC);wikilink 解析支持隐式 `.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` 列出 actions;CLI 友好格式化。 |
|
||||
| `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 formatter;OpenAI 版用 `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` 适配) |
|
||||
|
|
@ -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 Tool(Claude 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 → B(A 引用了 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 同时跑三种检索通路,结果通过 RRF(Reciprocal Rank Fusion)排序融合:
|
||||
|
||||
- **向量检索** —— 捕捉语义相似度("钴" ≈ "锂电正极原料")
|
||||
- **关键词检索(BM25)** —— 精确匹配,对中文友好("宁德时代" 一定要命中)
|
||||
- **图谱检索** —— 通过 wikilink 邻居展开(找到"钴" → 自动带上"刚果(金)"、"嘉能可")
|
||||
|
||||
单一通路都有盲区:
|
||||
|
||||
- 纯向量 → 名词术语容易错配。
|
||||
- 纯关键词 → 同义改写抓不到。
|
||||
- 纯图谱 → 起点选错就全盘错。
|
||||
|
||||
三路融合让检索像"三个人各自查一遍再开会确认",结果鲁棒得多。
|
||||
|
||||
### 6.2 渐进式展开
|
||||
|
||||
传统 RAG 是一次性把 top-K 切片塞进上下文,token 利用率低,而且经常带进不相关的噪音。ReMe 的检索(
|
||||
`reme/steps/common/search.py`)是**分跳**的,且每一跳的"信息密度"刻意不同:
|
||||
|
||||
- **第一跳:直接命中的切片**——返回 chunk 全文 + 章节骨架。
|
||||
- **第二跳:1-hop 邻居**——只返回邻居的 path + meta(name/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 2:Agent 基于检索结果合成总览,写回知识库
|
||||
|
||||
```
|
||||
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 3:Agent 同步给出组会答复
|
||||
|
||||
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:00,ReMe 在 `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 7:daily 流水
|
||||
|
||||
```
|
||||
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 30:Auto-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 90:Obsidian 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-22,6 周后)**:用户在另一个项目又遇到类似问题。
|
||||
|
||||
```
|
||||
用户:"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 的工程内核已经就位,剩下是**自进化能力 + 生态集成 + 场景模板**的三件套加固,路径明确。
|
||||
|
|
@ -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
|
||||
- 记忆link:markdown之间link,digest内部链接,可以链接到外面。
|
||||
|
|
@ -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 提供的参考实现,服务层可替换 |
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
- reme_session/
|
||||
- agentscope|claude_code / # 使用内置的agent wrapper,session会保存在这里
|
||||
{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 应该是闲置?
|
||||
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
读取当天兴趣主题,驱动主动提醒与洞察。
|
||||
:::
|
||||
|
||||
::::
|
||||
|
|
@ -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 只是长期提炼结果。
|
||||
|
||||
## 场景三:个人第二大脑
|
||||
|
||||
Loading…
Add table
Reference in a new issue