一个给 AI 用的长期情绪记忆系统。基于 Russell 效价/唤醒度坐标打标,Obsidian 做存储层,MCP 接入,带遗忘曲线和向量语义检索。
A long-term emotional memory system for AI assistants. Tags memories using Russell's valence/arousal coordinates, stores them as Obsidian-compatible Markdown, connects via MCP, with forgetting curve and vector semantic search.
本项目 fork 自 P0luz/Ombre-Brain(原作者),已获授权开源。
核心记忆机制(衰减公式 / 做梦 / feel / 记忆桶 / 情感权重)与原作者完全一致、未改动。 我在其上做的是:① 全套新前端体验 ② 一批便利功能 ③ 检索/排序的命中精度优化(尤其中文场景)。改了哪些、为什么,全部透明列在 CHANGES.md。
如果你不需要这些前端/便利功能,请直接支持原作者的版本。
📋 CHANGES.md 改了什么 · 🚀 DEPLOY.md 云部署+备份 · 🔄 MIGRATION.md 从上游迁移
💡 第一次接触 Ombre-Brain?记忆模型 / 衰减 / 做梦这些核心概念建议先读原作者的 README,讲得很完整;本仓的概念说明沿用其设计。
对大多数人(尤其不太折腾技术的)这是最简单的方式 —— 不用装 Docker、不用碰命令行,填几个环境变量就跑起来。 (想本地跑 / 自己改代码?跳到下面「从源码部署」。)
用 GitHub 账号登录 Render → 按提示部署。它会自动读本仓的 render.yaml,已经帮你配好了持久磁盘(数据重启不丢)。
Render 给你的是一个公开 URL,所以 OB 有全局鉴权:除了静态网页和
/health,所有/api/*和/mcp都必须带X-Admin-Tokenheader,否则任何拿到 URL 的人都能读/删你的 全部记忆(含私密日记)、改提示词、换 LLM 地址截走数据。好消息:Render 会自动帮你生成这个 token(
render.yaml里generateValue: true)—— 默认就是安全的,你啥都不用填。只有当你要用网页 dashboard 或接 claude.ai 时才需要它:到 Render → 你的服务 → Environment → 复制
OMBRE_ADMIN_TOKEN的值。第一次打开网页会弹窗让你粘贴,存浏览器后 就不用再输;claude.ai 等连接器配成X-Admin-Tokenheader(见 DEPLOY.md)。(Docker / 手动部署没有自动生成 —— 必须自己设
OMBRE_ADMIN_TOKEN,否则公网模式拒绝启动; 确知在私网/反代已鉴权才裸跑可设OMBRE_ALLOW_NO_AUTH=1。)
部署后到 Render → 你的服务 → Environment,填三个:
OMBRE_API_KEY— 你的 LLM API key(DeepSeek / Gemini / Claude 等任意 OpenAI 兼容的都行)OMBRE_BASE_URL— 例https://api.deepseek.com/v1OMBRE_MODEL— 例deepseek-chat
免费 key:DeepSeek 或 Google AI Studio。
持久盘能扛住"重启",但盘本身万一损坏 / 误删 / 平台出事,数据就全没了 —— 此类丢失确有先例(曾因持久盘问题丢失约一周记忆)。所以请务必加上 off-site 自动备份(把记忆推到你自己的一个私有 git 仓),几分钟搞定,是唯一靠得住的"第二层"。
完整步骤见 DEPLOY.md「自动备份配置」。 配完一定要去 GitHub Actions 手动触发一次确认它真的跑通,否则很容易"以为配好了、其实一次都没备份"。
部署完成后:
- 主网页:
https://你的服务.onrender.com/v2/ - 手机端:
https://你的服务.onrender.com/v2/mobile/(可在手机浏览器"添加到主屏幕"当 App 用;首次访问同样会弹窗让你粘贴 token,存浏览器后免输) - 接入 Claude Desktop / Claude.ai:见下方「接入 Claude」章节,MCP 地址填
https://你的服务.onrender.com/mcp
适合想自己改代码、或者不想用预构建镜像的用户。
前置条件: 电脑上装了 Docker Desktop,并且已经打开。
第一步:拉取代码
git clone https://github.com/ceshihaox-dotcom/OmbreBrain-folio.git
cd OmbreBrain-folio第二步:创建 .env 文件
在项目目录下新建一个叫 .env 的文件(注意有个点),内容填:
OMBRE_API_KEY=你的API密钥
🔑 推荐免费方案:Google AI Studio
- 打开 aistudio.google.com/apikey,登录 Google 账号
- 点击「Create API key」生成一个 key
- 把 key 填入
.env文件的OMBRE_API_KEY=后面- 免费额度(请以官网实时信息为准):
- 脱水/打标模型(
gemini-2.5-flash-lite):免费层 30 req/min- 向量化模型(
gemini-embedding-001):免费层 1500 req/day,3072 维- 在
config.yaml中dehydration.base_url设为https://generativelanguage.googleapis.com/v1beta/openai也支持 DeepSeek、Ollama、LM Studio、vLLM 等任意 OpenAI 兼容 API。
Recommended free option: Google AI Studio
- Go to aistudio.google.com/apikey and create an API key
- Free tier (check official site for current limits):
- Dehydration model (
gemini-2.5-flash-lite): 30 req/min free- Embedding model (
gemini-embedding-001): 1500 req/day free, 3072 dims- Set
dehydration.base_urltohttps://generativelanguage.googleapis.com/v1beta/openaiinconfig.yamlAlso supports DeepSeek, Ollama, LM Studio, vLLM, or any OpenAI-compatible API.
没有 API key 则脱水压缩和自动打标功能不可用(会报错),但记忆的读写和检索仍正常工作。如果暂时不用脱水功能,可以留空:
OMBRE_API_KEY=
第三步:配置 docker-compose.yml(指向你的 Obsidian Vault)
用文本编辑器打开 docker-compose.yml,找到这一行:
- ./buckets:/data改成你的 Obsidian Vault 里 Ombre Brain 文件夹的路径,例如:
- /Users/你的用户名/Documents/Obsidian Vault/Ombre Brain:/data不知道路径?在 Obsidian 里右键那个文件夹 → 「在访达中显示」,然后把地址栏的路径复制过来。 不想挂载 Obsidian 也行,保持
./buckets:/data不动,数据会存在项目目录的buckets/文件夹里。
第四步:启动
docker compose up -d等它跑完,看到 Started 就好了。
验证是否正常运行:
docker logs ombre-brain看到 Uvicorn running on http://0.0.0.0:8000 说明成功了。
浏览器打开前端 Dashboard:**http://localhost:18001/v2/**(`docker-compose.yml` 默认端口映射 18001:8000)
接入 Claude.ai(远程访问)
需要额外配置 Cloudflare Tunnel,把服务暴露到公网。参考下面「接入 Claude.ai (远程)」章节。
接入 Claude Desktop(本地)
不需要 Docker,直接用 Python 本地跑。参考下面「安装 / Setup」章节。
Claude 没有跨对话记忆。每次对话结束,之前聊过的所有东西都会消失。
Ombre Brain 给了它一套持久记忆——不是那种冷冰冰的键值存储,而是带情感坐标的、会自然衰减的、像人类记忆一样会遗忘和浮现的系统。
Claude has no cross-conversation memory. Everything from a previous chat vanishes once it ends.
Ombre Brain gives it persistent memory — not cold key-value storage, but a system with emotional coordinates, natural decay, and forgetting/surfacing mechanics that loosely mimic how human memory works.
核心特点 / Key features:
-
情感坐标打标 / Emotional tagging: 每条记忆用 Russell 环形情感模型的 valence(效价)和 arousal(唤醒度)两个连续维度标记。不是"开心/难过"这种离散标签。 Each memory is tagged with two continuous dimensions from Russell's circumplex model: valence and arousal. Not discrete labels like "happy/sad".
-
双通道检索 / Dual-channel search: 关键词模糊匹配 + 向量语义相似度并联检索。关键词通道用 rapidfuzz 做模糊匹配;语义通道用 embedding(默认
gemini-embedding-001,3072 维)计算 cosine similarity,能在"今天很累"这种没有精确关键词的查询里找到"身体不适"、"睡眠问题"等语义相关记忆。两个通道去重合并,token 预算截断。 Keyword fuzzy matching + vector semantic similarity in parallel. Keyword channel uses rapidfuzz; semantic channel uses embeddings (defaultgemini-embedding-001, 3072 dims) with cosine similarity — finds semantically related memories even without exact keyword matches (e.g. "feeling tired" → "health issues", "sleep problems"). Results are deduplicated and truncated by token budget. -
自然遗忘 / Natural forgetting: 改进版艾宾浩斯遗忘曲线。不活跃的记忆自动衰减归档,高情绪强度的记忆衰减更慢。 Modified Ebbinghaus forgetting curve. Inactive memories naturally decay and archive. High-arousal memories decay slower.
-
权重池浮现 / Weight pool surfacing: 记忆不是被动检索的,它们会主动浮现——未解决的、情绪强烈的记忆权重更高,会在对话开头自动推送。 Memories aren't just passively retrieved — they actively surface. Unresolved, emotionally intense memories carry higher weight and get pushed at conversation start.
-
记忆重构 / Memory reconstruction: 检索时根据当前情绪状态微调记忆的 valence 展示值(±0.1),模拟人类"此刻的心情影响对过去的回忆"的认知偏差。 During retrieval, memory valence display is subtly shifted (±0.1) based on current mood, simulating the human cognitive bias of "current mood colors past memories".
-
Obsidian 原生 / Obsidian-native: 每个记忆桶就是一个 Markdown 文件,YAML frontmatter 存元数据。可以直接在 Obsidian 里浏览、编辑、搜索。自动注入
[[双链]]。 Each memory bucket is a Markdown file with YAML frontmatter. Browse, edit, and search directly in Obsidian. Wikilinks are auto-injected. -
API 脱水 + 缓存 / API dehydration + cache: 脱水压缩和自动打标通过 LLM API(DeepSeek / Gemini 等)完成,结果缓存到本地 SQLite(
dehydration_cache.db),相同内容不重复调用 API。向量检索不可用时降级到 fuzzy matching。 Dehydration and auto-tagging are done via LLM API (DeepSeek / Gemini etc.), with results cached locally in SQLite (dehydration_cache.db) to avoid redundant API calls. Embedding search degrades to fuzzy matching when unavailable. -
历史对话导入 / Conversation history import: 将过去与 Claude / ChatGPT / DeepSeek 等的对话批量导入为记忆桶。支持 Claude JSON 导出、ChatGPT 导出、Markdown、纯文本等格式,分块处理带断点续传,通过 Dashboard「导入」Tab 操作。 Batch-import past conversations (Claude / ChatGPT / DeepSeek etc.) as memory buckets. Supports Claude JSON export, ChatGPT export, Markdown, and plain text. Chunked processing with resume support, via the Dashboard "Import" tab.
官方记忆功能已经在做身份层的事了——你是谁,你有什么偏好,你们的关系是什么。那一层交给它,Ombre Brain不打算造重复的轮子。
Ombre Brain 的边界是时间里发生的事,不是你是谁。它记住的是:你们聊过什么,经历了什么,哪些事情还悬在那里没有解决。两层配合用,才是完整的。
每次新对话,Claude 从零开始——但它能从 Ombre Brain 里找回跟你有关的一切。不是重建,是接续。
Official memory already handles the identity layer — who you are, what you prefer, what your relationship is. That layer belongs there. Ombre Brain isn't trying to duplicate it.
Ombre Brain's boundary is what happened in time, not who you are. It holds conversations, experiences, unresolved things. The two layers together are what make it feel complete.
Each new conversation starts fresh — but Claude can reach back through Ombre Brain and find everything that happened between you. Not a rebuild. A continuation.
Claude ←→ MCP Protocol ←→ server.py
│
┌───────────────┼───────────────┐
│ │ │
bucket_manager dehydrator decay_engine
(CRUD + 搜索) (压缩 + 打标) (遗忘曲线)
│ │
Obsidian Vault embedding_engine
(Markdown files) (向量语义检索)
│
embeddings.db
(SQLite, 3072-dim)
breath(query="今天很累")
│
┌────┴────┐
│ │
Channel 1 Channel 2
关键词匹配 向量语义
(rapidfuzz) (cosine similarity)
│ │
└────┬────┘
│
去重 + 合并
token 预算截断
│
[语义关联] 标注 vector 来源
│
返回 ≤20 条结果
6 个 MCP 工具 / 6 MCP tools:
| 工具 Tool | 作用 Purpose |
|---|---|
breath |
浮现或检索记忆。无参数=推送未解决记忆;有参数=关键词+向量语义双通道检索。支持 domain/valence/arousal 过滤 / Surface or search memories. No args = surface unresolved; with query = keyword + vector dual-channel search. Supports domain/valence/arousal filters |
hold |
存储单条记忆,自动打标+合并相似桶+生成 embedding。feel=True 写模型自己的感受 / Store a single memory with auto-tagging, merging, and embedding. feel=True for model's own reflections |
grow |
日记归档,自动拆分长内容为多个记忆桶,每个桶自动生成 embedding / Diary digest, auto-split into multiple buckets with embeddings |
trace |
修改元数据、标记已解决、删除 / Modify metadata, mark resolved, delete |
pulse |
系统状态 + 所有记忆桶列表 / System status + bucket listing |
dream |
对话开头自省消化——读最近记忆,有沉淀写 feel,能放下就 resolve / Self-reflection at conversation start |
- Python 3.11+
- 一个 Obsidian Vault(可选,不用也行,会在项目目录下自建
buckets/) An Obsidian vault (optional — without one, it uses a localbuckets/directory)
git clone https://github.com/ceshihaox-dotcom/OmbreBrain-folio.git
cd OmbreBrain-folio
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt复制配置文件并按需修改 / Copy config and edit as needed:
cp config.example.yaml config.yaml如果你要用 API 做脱水压缩和自动打标(推荐,效果好很多),设置环境变量: If you want API-powered dehydration and tagging (recommended, much better quality):
export OMBRE_API_KEY="your-api-key"支持任何 OpenAI 兼容 API。在 config.yaml 里改 base_url 和 model 就行。
Supports any OpenAI-compatible API. Just change base_url and model in config.yaml.
💡 向量化检索(Embedding) Ombre Brain 内置双通道检索:关键词匹配 + 向量语义搜索。每次
hold/grow存入记忆时自动生成 embedding 并存入embeddings.db(SQLite)。 推荐:Google AI Studio 的gemini-embedding-001(免费,1500 次/天,3072 维向量)。在config.yaml的embedding部分配置。 不配置 embedding 也能用,系统会降级到纯 fuzzy matching 模式。已有存量桶需要补生成 embedding:运行
backfill_embeddings.py:OMBRE_API_KEY="your-key" python backfill_embeddings.py --batch-size 20Docker 用户:
docker exec -e OMBRE_BUCKETS_DIR=/data ombre-brain python3 backfill_embeddings.py --batch-size 20Embedding support: Built-in dual-channel search: keyword + vector semantic. Embeddings are auto-generated on each
hold/growand stored inembeddings.db(SQLite). Recommended: Google AI Studiogemini-embedding-001(free, 1500 req/day, 3072-dim). Configure inconfig.yamlunderembedding. Without it, falls back to fuzzy matching. For existing buckets, runbackfill_embeddings.py.
在 Claude Desktop 配置文件中添加(macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):
Add to your Claude Desktop config:
{
"mcpServers": {
"ombre-brain": {
"command": "python",
"args": ["/path/to/Ombre-Brain/server.py"],
"env": {
"OMBRE_API_KEY": "your-api-key"
}
}
}
}上面是本地同机直跑(stdio 传输)的配置,不需要 token。配置文件位置:macOS
~/Library/Application Support/Claude/claude_desktop_config.json,Windows%APPDATA%\Claude\claude_desktop_config.json。 The block above is local same-machine (stdio) — no token needed. Config file: macOS~/Library/Application Support/Claude/claude_desktop_config.json, Windows%APPDATA%\Claude\claude_desktop_config.json.
如果 OB 部署在远程、且设了 OMBRE_ADMIN_TOKEN,Claude Desktop 不能直接填 URL —— 它需要一个 stdio↔HTTP 的桥。用 mcp-remote,并带上鉴权 header:
If OB runs remotely with OMBRE_ADMIN_TOKEN set, Claude Desktop can't take a bare URL — it needs a stdio↔HTTP bridge. Use mcp-remote with the auth header:
{
"mcpServers": {
"ombre-brain": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://<你的域名>/mcp",
"--header", "X-Admin-Token:<你的 OMBRE_ADMIN_TOKEN>"
]
}
}
}<你的 OMBRE_ADMIN_TOKEN>:部署平台环境变量里那个值,原样粘贴,冒号后不要加空格。Paste the value from your deploy platform's env vars; no space after the colon.- 前置:本机需装 Node.js(
mcp-remote通过npx运行)。改完配置后彻底退出并重开 Claude Desktop(托盘里 Quit,不是关窗口)。Requires Node.js (run vianpx); fully quit & reopen Claude Desktop after editing. - 不要用
cmd /c curl ... /mcp之类的写法:curl是单向 HTTP,承载不了 MCP 的双向 JSON-RPC,必然Server disconnected。Don't wrap the endpoint incmd /c curl ... /mcp—curlis one-way HTTP and can't carry MCP's bidirectional JSON-RPC, so it always fails withServer disconnected.
需要 HTTP 传输 + 隧道。可以用 Docker: Requires HTTP transport + tunnel. Docker setup:
echo "OMBRE_API_KEY=your-api-key" > .env
docker-compose up -ddocker-compose.yml 里配好了 Cloudflare Tunnel。你需要自己在 ~/.cloudflared/ 下放凭证和路由配置。
The docker-compose.yml includes Cloudflare Tunnel. You'll need your own credentials under ~/.cloudflared/.
在 config.yaml 里设置 buckets_dir:
Set buckets_dir in config.yaml:
buckets_dir: "/path/to/your/Obsidian Vault/Ombre Brain"不设的话,默认用项目目录下的 buckets/。
If not set, defaults to buckets/ in the project directory.
所有参数在 config.yaml(从 config.example.yaml 复制)。关键的几个:
All parameters in config.yaml (copy from config.example.yaml). Key ones:
| 参数 Parameter | 说明 Description | 默认 Default |
|---|---|---|
transport |
stdio(本地)/ streamable-http(远程) |
stdio |
buckets_dir |
记忆桶存储路径 / Bucket storage path | ./buckets/ |
dehydration.model |
脱水用的 LLM 模型 / LLM model for dehydration | deepseek-chat |
dehydration.base_url |
API 地址 / API endpoint | https://api.deepseek.com/v1 |
embedding.enabled |
启用向量语义检索 / Enable embedding search | true |
embedding.model |
Embedding 模型 / Embedding model | gemini-embedding-001 |
decay.lambda |
衰减速率,越大越快忘 / Decay rate | 0.05 |
decay.threshold |
归档阈值 / Archive threshold | 0.3 |
merge_threshold |
合并相似度阈值 (0-100) / Merge similarity | 75 |
敏感配置用环境变量: Sensitive config via env vars:
OMBRE_API_KEY— LLM API 密钥OMBRE_TRANSPORT— 覆盖传输方式OMBRE_BUCKETS_DIR— 覆盖存储路径
系统对记忆的权重计算采用分段策略,模拟人类记忆的时效特征: The system uses a segmented weighting strategy that mimics how human memory prioritizes:
| 阶段 Phase | 时间范围 | 权重分配 | 直觉解释 |
|---|---|---|---|
| 短期 Short-term | ≤ 3 天 | 时间 70% + 情感 30% | 刚发生的事,鲜活度最重要 |
| 长期 Long-term | > 3 天 | 情感 70% + 时间 30% | 时间淡了,情感强度决定能记多久 |
连续指数衰减,无跳变: Continuous exponential decay, no discontinuities:
| 距存入时间 Time since creation | 新鲜度乘数 Multiplier |
|---|---|
| 刚存入 (t=0) | ×2.0 |
| 约 25 小时 | ×1.5 |
| 约 50 小时 | ×1.25 |
| 72 小时 (3天) | ×1.14 |
| 1 周+ | ≈ ×1.0 |
t 为小时,36 为衰减常数。老记忆不被惩罚(下限 ×1.0),新记忆获得额外加成。
- 默认
base=1.0,arousal_boost=0.8 - arousal=0.3(平静)→ 1.24;arousal=0.9(激动)→ 1.72
| 状态 State | 修正因子 Factor | 说明 |
|---|---|---|
| 未解决 Unresolved | ×1.0 | 正常权重 |
| 已解决 Resolved | ×0.05 | 沉底,等关键词唤醒 |
| 已解决+已消化 Resolved+Digested | ×0.02 | 加速淡化,归档为无限小 |
| 高唤醒+未解决 Urgent | ×1.5 | arousal>0.7 的未解决记忆额外加权 |
| 钉选 Pinned | 999.0 | 不衰减、不合并、importance=10 |
| Feel | 50.0 | 固定分数,不参与衰减 |
importance: 1-10,记忆重要性 / memory importanceactivation_count: 被检索的次数,越常被想起衰减越慢 / retrieval count; more recalls = slower decaydays: 距上次激活的天数 / days since last activationarousal: 唤醒度,越强烈的记忆越难忘 / arousal; intense memories are harder to forgetλ(decay_lambda): 衰减速率,默认 0.05 / decay rate, default 0.05
每次新对话开始时,Claude 会自动执行 dream()——读取最近的记忆桶,用第一人称思考:哪些事还有重量?哪些可以放下了?
At the start of each conversation, Claude runs dream() — reads recent memory buckets and reflects in first person: what still carries weight? What can be let go?
- 值得放下的 →
trace(resolved=1)让它沉底 - 有沉淀的 → 写
feel,记录模型自己的感受 - 没有沉淀就不写,不强迫产出
Feel 不是事件记录,是模型带走的东西——一句感受、一个未解答的问题、一个观察到的变化。
Feel is not an event log — it's what the model carries away: a feeling, an unanswered question, a noticed change.
hold(content="...", feel=True, source_bucket="源记忆ID", valence=模型自己的感受)valence是模型的感受,不是事件情绪。同一段争吵,事件 V0.2,但模型可能 V0.4(「我从中看到了成长」)source_bucket指向被消化的记忆,会被标记为「已消化」→ 加速淡化到无限小,但不会被删除- Feel 不参与普通浮现、不衰减、不参与 dreaming
- 用
breath(domain="feel")读取之前的 feel
1. breath() — 睁眼,看有什么浮上来
2. dream() — 消化最近记忆,有沉淀写 feel
3. breath(domain="feel") — 读之前的 feel
4. 开始和用户说话
CLAUDE_PROMPT.md 是写给 AI 看的使用说明——教它何时用哪个工具、"权重池"怎么回事、dream/feel 怎么做。
⚠️ 要知道:AI 默认看不到这份说明。它默认只能看到 MCP 工具的简短描述(+ 若装了 SessionStart hook,会有 breath/dream 的输出)。所以这份指南需要你主动喂给它——给多少,按你的 token 预算自己定:
| 怎么给 | 效果 | 代价 |
|---|---|---|
把 CLAUDE_PROMPT.md 全文放进 system prompt / custom instructions |
AI 最会用 OB(该 hold 就存、该 resolved 就放下、pulse 不乱调) |
每次会话多占一段 token |
| 放精简版(自己删到核心几条) | 折中 | 中等 |
| 不放,只靠工具描述 | 最省 token | AI 用得糙(可能乱调 pulse、少用 hold) |
这是给你的信息和选择,不是规定——OB 不会自动往 AI 的 prompt 里塞东西(省得给 token 紧张的人加负担)。
English: CLAUDE_PROMPT.md is the usage guide for the AI. Note it is not auto-injected — by default the AI only sees the brief MCP tool descriptions. Paste as much of it into your system prompt as your token budget allows: full = the AI uses OB best (more tokens/session); partial = middle ground; none = cheapest but the AI uses the tools crudely.
| 脚本 Script | 用途 Purpose |
|---|---|
embedding_engine.py |
向量化引擎,管理 embedding 的生成、存储、相似度搜索 / Embedding engine: generate, store, and search embeddings |
backfill_embeddings.py |
为存量桶批量生成 embedding / Batch-generate embeddings for existing buckets |
write_memory.py |
手动写入记忆,绕过 MCP / Manually write memories, bypass MCP |
migrate_to_domains.py |
迁移平铺文件到域子目录 / Migrate flat files to domain subdirs |
migrate_from_upstream.py |
从上游迁入:老字段→新字段升级 / Migrate from upstream (field upgrade) |
reverse_compat_migrate.py |
切回上游前:新字段→老字段回填 / Back-fill to upstream-compatible fields |
reclassify_api.py |
用 API 重打标未分类桶 / Re-tag uncategorized buckets via API |
reclassify_domains.py |
按关键词规则重分类 domain 并搬目录 / Reclassify domains by keyword rules |
test_tools.py |
MCP 工具集成测试(6 步:5 工具 + 清理) / MCP tool integration tests |
test_smoke.py |
冒烟测试 / Smoke test |
⚠️ 免费层不可用:Render 免费层不支持持久化磁盘,服务重启后记忆数据会丢失,且会在无流量时休眠。必须使用 Starter($7/mo)或以上才能正常使用。 Free tier won't work: Render free tier has no persistent disk — all memory data is lost on restart. It also sleeps on inactivity. Starter plan ($7/mo) or above is required.
项目根目录已包含 render.yaml,点击按钮后:
- (写入记忆必需)设置
OMBRE_API_KEY:任何 OpenAI 兼容 API 的 key;不填则 hold / grow / dream 报错(只检索已有记忆不受影响) - (可选)设置
OMBRE_BASE_URL:API 地址,支持任意 OpenAI 化地址,如https://api.deepseek.com/v1/http://123.1.1.1:7689/v1/http://your-ollama:11434/v1 - Render 自动挂载持久化磁盘到
/opt/render/project/src/buckets - Dashboard:
https://<你的服务名>.onrender.com/v2/ - 部署后 MCP URL:
https://<你的服务名>.onrender.com/mcp
render.yaml is included. After clicking the button:
- (Required for writing)
OMBRE_API_KEY: any OpenAI-compatible key; without it hold / grow / dream will error (searching existing memories still works) - (Optional)
OMBRE_BASE_URL: any OpenAI-compatible endpoint, e.g.https://api.deepseek.com/v1,http://123.1.1.1:7689/v1,http://your-ollama:11434/v1 - Persistent disk auto-mounts at
/opt/render/project/src/buckets - Dashboard:
https://<your-service>.onrender.com/v2/ - MCP URL after deploy:
https://<your-service>.onrender.com/mcp
💡 Zeabur 的定价模式:Zeabur 是「买 VPS + 平台托管」,你先购买一台服务器(最低腾讯云新加坡 $2/mo、火山引擎 $3/mo),Volume 直接挂在该服务器上,数据天然持久化,无丢失问题。另需订阅 Zeabur 管理方案(Developer $5/mo),总计约 $7-8/mo 起。 Zeabur pricing model: You buy a VPS first (cheapest: Tencent Cloud Singapore ~$2/mo, Volcano Engine ~$3/mo), then add Zeabur's Developer plan ($5/mo) for management. Volumes mount directly on your server — data is always persistent, no cold-start data loss. Total ~$7-8/mo minimum.
步骤 / Steps:
-
创建项目 / Create project
- 打开 zeabur.com → 购买一台服务器 → New Project → Deploy from GitHub
- 先 Fork 本仓库到自己 GitHub 账号,然后在 Zeabur 选择
你的用户名/OmbreBrain-folio - Zeabur 会自动检测到根目录的
Dockerfile并使用 Docker 方式构建 - Go to zeabur.com → buy a server → New Project → Deploy from GitHub
- Fork this repo first, then select
your-username/OmbreBrain-folioin Zeabur - Zeabur auto-detects the
Dockerfilein root and builds via Docker
-
设置环境变量 / Set environment variables(服务页面 → Variables 标签页)
OMBRE_API_KEY(写入记忆必需)— LLM API 密钥,不填则 hold / grow / dream 报错(检索不受影响)OMBRE_BASE_URL(可选)— API 地址,如https://api.deepseek.com/v1
⚠️ 不需要手动设置OMBRE_TRANSPORT和OMBRE_BUCKETS_DIR,Dockerfile 里已经设好了默认值。Zeabur 对单阶段 Dockerfile 会自动注入控制台设置的环境变量。 You do NOT need to setOMBRE_TRANSPORTorOMBRE_BUCKETS_DIR— defaults are baked into the Dockerfile. Zeabur auto-injects dashboard env vars for single-stage Dockerfiles. -
挂载持久存储 / Mount persistent volume(服务页面 → Volumes 标签页)
- Volume ID:填
ombre-buckets(或任意名) - 挂载路径 / Path:
/app/buckets ⚠️ 不挂载的话,每次重新部署记忆数据会丢失⚠️ Without this, memory data is lost on every redeploy
- Volume ID:填
-
配置端口 / Configure port(服务页面 → Networking 标签页)
- Port Name:
web(或任意名) - Port:
8000 - Port Type:
HTTP - 然后点 Generate Domain 生成一个
xxx.zeabur.app域名 - Then click Generate Domain to get a
xxx.zeabur.appdomain
- Port Name:
-
验证 / Verify
- 访问
https://<你的域名>.zeabur.app/health,应返回 JSON - Visit
https://<your-domain>.zeabur.app/health— should return JSON - Dashboard:
https://<你的域名>.zeabur.app/v2/ - 最终 MCP 地址 / MCP URL:
https://<你的域名>.zeabur.app/mcp
- 访问
常见问题 / Troubleshooting:
| 现象 Symptom | 原因 Cause | 解决 Fix |
|---|---|---|
| 域名无法访问 / Domain unreachable | 没配端口 / Port not configured | Networking 标签页加 port 8000 (HTTP) |
| 域名无法访问 / Domain unreachable | OMBRE_TRANSPORT 未设置,服务以 stdio 模式启动,不监听任何端口 / Service started in stdio mode — no port is listened |
Variables 标签页确认设置 OMBRE_TRANSPORT=streamable-http,然后重新部署 |
| 构建失败 / Build failed | Dockerfile 未被识别 / Dockerfile not detected | 确认仓库根目录有 Dockerfile(大小写敏感) |
| 服务启动后立刻退出 | OMBRE_TRANSPORT 被覆盖为 stdio |
检查 Variables 里有没有多余的 OMBRE_TRANSPORT=stdio,删掉即可 |
| 启动即退出 + 日志「REFUSING TO START / 拒绝启动」 | HTTP 模式下没设 OMBRE_ADMIN_TOKEN(全局鉴权必需) |
Variables 里加 OMBRE_ADMIN_TOKEN=强随机值后重启(确知私网/反代已鉴权才用 OMBRE_ALLOW_NO_AUTH=1 豁免) |
网页能打开但 /api 全 401 / 一直弹 token 框 |
输入的 token 跟 OMBRE_ADMIN_TOKEN 不一致 |
确认浏览器输入的值 == 服务端 env 的值(清掉 localStorage 重输) |
| 重启后记忆丢失 / Data lost on restart | Volume 未挂载 | Volumes 标签页挂载到 /app/buckets |
ℹ️ HTTP 模式下 server.py 自动启用 CORS + 全局鉴权中间件。CORS 默认仅同源 (claude.ai / MCP 客户端是服务端调用,不走浏览器 CORS,不受影响);只有从另一个域名的 网页 JS 直接打
/api才需要在OMBRE_ALLOWED_ORIGINS里加该 origin。 Since HTTP mode, server.py enables CORS + global auth. CORS is same-origin by default; setOMBRE_ALLOWED_ORIGINSonly if browser JS on another domain calls/apidirectly.
使用隧道连接时,确保以下条件满足: When connecting via tunnel, ensure:
-
服务器必须运行在 HTTP 模式 / Server must use HTTP transport
OMBRE_TRANSPORT=streamable-http python server.py
或 Docker:
docker-compose up -d
-
在 Claude.ai 网页版添加 MCP 服务器 / Adding to Claude.ai web
- URL 格式 / URL format:
https://<tunnel-subdomain>.trycloudflare.com/mcp - 或 ngrok / or ngrok:
https://<xxxx>.ngrok-free.app/mcp - ⚠ 鉴权限制:公网部署设了
OMBRE_ADMIN_TOKEN后,/mcp要求X-Admin-Tokenheader。 但 claude.ai 网页版的自定义连接器不支持自定义 header(只有 URL + OAuth),所以 网页版无法直接连带鉴权的 OB。要在客户端直连,请用 Claude Desktop +mcp-remote:npx -y mcp-remote https://<your-host>/mcp --header "X-Admin-Token:${OMBRE_TOKEN}"(${OMBRE_TOKEN}需你的 shell / 环境支持变量展开才会被替换;不确定就直接填 token 字面值,否则会把字面串发出去 → 401)。 Claude Code 更省事:直接在~/.claude.json的mcpServers里给该 server 配"headers": {"X-Admin-Token": "<token>"},不用 mcp-remote 桥。 或在本机用 stdio 模式(无需 token)。 / claude.ai web custom connectors don't support custom headers, so they can't reach an authed OB — use Claude Desktop +mcp-remote --header, or run locally in stdio mode. - 💡 可选 · 想用 claude.ai 网页版直连:设独立 env
OMBRE_MCP_URL_KEY(URL 安全随机串, 别跟OMBRE_ADMIN_TOKEN同值),连接器 URL 二选一:https://<host>/<KEY>/mcp(推荐,密钥在 路径里最稳)或https://<host>/mcp?key=<KEY>。这条口子只开/mcp(读写删记忆)、打不开/api/*,密钥在 URL 里比 header 弱、可单独轮换;默认不设 = 关闭。详见 DEPLOY.md Option ①。 / Optional: to connect from claude.ai web, set a separateOMBRE_MCP_URL_KEYand usehttps://<host>/<KEY>/mcp(recommended) orhttps://<host>/mcp?key=<KEY>(opens/mcponly, weaker than header — see DEPLOY.md). - 先访问
/health验证连接 / Verify first:https://<your-tunnel>/healthshould return{"status":"ok",...}(/health不需要 token / no token needed)
- URL 格式 / URL format:
-
已知限制 / Known limitations
- Cloudflare Tunnel 免费版有空闲超时(约 10 分钟),系统内置保活 ping 可缓解但不能完全消除
- Free Cloudflare Tunnel has idle timeout (~10 min); built-in keepalive pings mitigate but can't fully prevent it
- ngrok 免费版有请求速率限制 / ngrok free tier has rate limits
- 如果连接仍失败,检查隧道是否正在运行、服务是否以
streamable-http模式启动 - If connection still fails, verify the tunnel is running and the server started in
streamable-httpmode
| 现象 Symptom | 原因 Cause | 解决 Fix |
|---|---|---|
| 网页版无法连接隧道 URL / Web can't connect to tunnel URL | 服务以 stdio 模式运行 / Server in stdio mode | 设置 OMBRE_TRANSPORT=streamable-http 后重启 |
| 网页版无法连接隧道 URL / Web can't connect to tunnel URL | 旧版 server.py 缺少 CORS 头 / Missing CORS headers | 拉取最新代码,CORS 已内置 / Pull latest — CORS is now built-in |
/health 返回 200 但 MCP 连不上 / /health 200 but MCP fails |
路径错误 / Wrong path | MCP URL 末尾必须是 /mcp 而非 / |
| 隧道连接偶尔断开 / Tunnel disconnects intermittently | Cloudflare Tunnel 空闲超时 / Idle timeout | 保活 ping 已内置,若仍断开可缩短隧道超时配置 |
部署后,如果你使用 Claude Code,可以在项目内激活自动浮现 hook:
.claude/settings.json 已配置好 SessionStart hook,每次新会话或恢复会话时自动触发 breath,把最高权重未解决记忆推入上下文。
仅在远程 HTTP 模式下有效(OMBRE_TRANSPORT=streamable-http)。本地 stdio 模式下 hook 会安静退出,不影响正常使用。
可以通过 OMBRE_HOOK_URL 环境变量指定服务器地址(默认 http://localhost:8000),或者设置 OMBRE_HOOK_SKIP=1 临时禁用。
If using Claude Code, .claude/settings.json configures a SessionStart hook that auto-calls breath on each new or resumed session, surfacing your highest-weight unresolved memories as context. Only active in remote HTTP mode. Set OMBRE_HOOK_SKIP=1 to disable temporarily.
不同部署方式的更新方法。
Different update procedures depending on your deployment method.
cd OmbreBrain-folio
# 拉取最新代码
git pull origin main
# 重新构建并重启
docker compose down
docker compose build
docker compose up -d
docker compose build会重新构建镜像。volume 挂载的记忆数据不受影响。docker compose buildrebuilds the image. Volume-mounted memory data is unaffected.
cd OmbreBrain-folio
# 拉取最新代码
git pull origin main
# 更新依赖(如有新增)
pip install -r requirements.txt
# 重启服务
# Ctrl+C 停止旧进程,然后:
python server.pyRender 连接了你的 GitHub 仓库,自动部署:
- 如果你 Fork 了仓库 → 在 GitHub 上同步上游更新(Sync fork),Render 会自动重新部署
- 或者手动:Render Dashboard → 你的服务 → Manual Deploy → Deploy latest commit
持久化磁盘(
/opt/render/project/src/buckets)上的记忆数据在重新部署时保留。 Persistent disk data at/opt/render/project/src/bucketsis preserved across deploys.
Zeabur 也连接了你的 GitHub 仓库:
- 在 GitHub 上同步 Fork 的最新代码 → Zeabur 自动触发重新构建部署
- 或者手动:Zeabur Dashboard → 你的服务 → Redeploy
Volume 挂载在
/app/buckets,重新部署时数据保留。 Volume mounted at/app/buckets— data persists across redeploys.
cd OmbreBrain-folio
# 拉取最新代码
git pull origin main
# 方式 A:Docker 部署
docker compose down
docker compose build
docker compose up -d
# 方式 B:直接 Python 运行
pip install -r requirements.txt
# 重启你的进程管理器(systemd / supervisord / pm2 等)
sudo systemctl restart ombre-brain # 示例通用注意事项 / General notes:
- 更新不会影响你的记忆数据(存在 volume 或 buckets 目录里)
- 如果
requirements.txt有变化,Docker 用户重新 build 即可自动处理;非 Docker 用户需手动pip install -r requirements.txt- 更新后访问
/health验证服务正常- Updates never affect your memory data (stored in volumes or buckets directory)
- If
requirements.txtchanged, Docker rebuild handles it automatically; non-Docker users needpip install -r requirements.txt- After updating, visit
/healthto verify the service is running
这是 P0luz/Ombre-Brain 的一个优化分支版本。核心记忆机制(衰减公式 / 做梦 / feel / 记忆桶 / 情感权重)与原作者完全一致、未改动;我主要做了前端体验、便利功能,以及检索/排序的命中精度优化(尤其中文)。改了哪些、为什么,全部透明列在 CHANGES.md。已获得原作者授权开源。
This is an optimized fork of the upstream. The core memory mechanism (decay / dreaming / feel / bucket model / emotion weighting) is identical to upstream and unchanged — my changes are the frontend experience, convenience features, and retrieval/ranking precision tuning (especially for Chinese). Every change is transparently listed in CHANGES.md. Open-sourced with the original author's permission.
本 fork 特有文档 / Fork-specific docs:
- 📋 CHANGES.md — 完整功能清单 + 跟上游的差异说明 (透明披露所有改动)
- 🚀 DEPLOY.md — 一键部署到 Render + 自动备份配置
- 🔄 MIGRATION.md — 从上游版本迁移过来的操作指南 + 兼容工具
一键部署到 Render / One-click deploy:
MIT