内容
# 共享内存
[](https://github.com/fazerluga-creator/shared-memory/actions/workflows/ci.yml)
[](LICENSE)

一个可移植的、自托管的 **LLM 代理的语义内存层**,通过 [模型上下文协议](https://modelcontextprotocol.io) (MCP) 暴露。
将任意数量的代理 — Claude Code、其他 MCP 客户端或您自己的脚本 — 指向一个共享的向量存储,并让它们通过含义而不是 grep 文件来回忆过去的决策、笔记和对话。
- **默认本地运行。** 嵌入式在设备上通过 [fastembed](https://github.com/qdrant/fastembed) 运行;除非您选择加入远程 API,否则不会离开主机。
- **一个存储,多个代理。** 每个区块都带有 `agent` 和 `source` 标签,因此搜索可以是全局的或限定在单个代理上。
- **三个 MCP 工具。** `memory_search`、`memory_add`、`memory_stats` — 就是整个界面。
- **自带内容。** 配备通用 markdown 索引器;编写聊天日志、票证或文档的适配器是一个简短的脚本。
## 为什么
代理在会话之间是无状态的。常见的解决方案是加载一个简短的“始终加载”的内存文件,但它无法扩展 — 您不能将曾经做出的所有决定都粘贴到每个提示中。
shared-memory 是 **第二层**:一个无界限的存储,您可以按需搜索。
- **层 A** — 一个简短的、手动策划的内存文件,加载到每个提示中(您已经为此使用了现有的文件)。
- **层 B(此项目)** — 无界限,通过语义搜索。 “我们决定了什么关于 X?” 返回相关的过去区块,而不是文件转储。
## 架构
```
┌────────────────┐
agent A ─┐ │ MCP 服务器 │ memory_search
agent B ─┼──▶ │ (FastMCP) │ memory_add ──▶ ChromaDB(持久)
scripts ─┘ │ │ memory_stats + 本地嵌入
└────────────────┘
▲
│ 索引器/适配器
您的内容(markdown、会话、文档、…)
```
```
shared-memory/
├── lib/
│ ├── embedder.py # 提供程序感知的嵌入(本地 fastembed | OpenAI 兼容)
│ └── store.py # ChromaDB 持久客户端助手
├── mcp-server/
│ └── server.py # FastMCP 服务器:memory_search、memory_add、memory_stats
├── examples/
│ └── index_markdown.py # 通用适配器:索引一个文件夹的 *.md
├── embedding.env.example # 复制到 embedding.env 以自定义(可选)
└── requirements.txt
```
## 安装
需要 Python 3.10+。
```bash
git clone https://github.com/fazerluga-creator/shared-memory.git
cd shared-memory
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
```
可选地复制配置文件并调整它(默认值一开始就很好):
```bash
cp embedding.env.example embedding.env
```
第一次运行会下载本地嵌入模型(几百 MB)。
## 快速开始
索引一些 markdown 并搜索它:
```bash
# 1. 摄入一个文件夹的笔记
python examples/index_markdown.py ./notes --agent notes
# 2. 运行 MCP 服务器(stdio 传输)
python mcp-server/server.py
```
或者直接使用库:
```python
from lib.embedder import Embedder
from lib.store import get_client, get_collection
col = get_collection(get_client())
emb = Embedder()
col.add(
ids=["note::1"],
embeddings=[emb.embed_document_one("在星期五发布测试版,功能标志新的 UI。")],
documents=["在星期五发布测试版,功能标志新的 UI。"],
metadatas=[{"agent": "notes", "source": "manual"}],
)
res = col.query(query_embeddings=[emb.embed_one("测试版什么时候发布?")], n_results=3)
print(res["documents"])
```
## MCP 工具
| 工具 | 签名 | 返回 |
| --- | --- | --- |
| `memory_search` | `(query, top_k=5, agent_filter=None, source_filter=None, since=None)` | `[{text, metadata, score}, ...]` 按相关性排序 |
| `memory_add` | `(text, metadata=None)` | 添加块的 ID |
| `memory_stats` | `()` | `{total, by_agent, by_source, collection}` |
过滤器:
- `agent_filter` — 限制为单个 `metadata.agent` 值。
- `source_filter` — 限制为 `metadata.source` 值(例如 `markdown`、`sessions`)。
- `since` — `metadata.timestamp` 的 ISO 时间戳下限。
### 连接到 Claude Code / 任意 MCP 客户端
将服务器添加到您的客户端配置中(路径是示例):
```json
{
"mcpServers": {
"shared-memory": {
"command": "/path/to/shared-memory/.venv/bin/python",
"args": ["/path/to/shared-memory/mcp-server/server.py"]
}
}
}
```
## 配置
所有设置都从 `embedding.env` 读取(参见 `embedding.env.example`)。路径可以通过环境变量覆盖:
| 变量 | 默认值 | 目的 |
| --- | --- | --- |
| `SHARED_MEMORY_ENV` | `./embedding.env` | 环境文件的路径 |
| `SHARED_MEMORY_DATA_DIR` | `./chroma_data` | ChromaDB 持久性目录 |
| `EMBEDDING_PROVIDER` | `local` | `local`(fastembed)或 `openai_compatible` |
| `EMBEDDING_MODEL` | MiniLM 多语言 | 嵌入模型 ID |
| `EMBEDDING_COLLECTION` | `shared_memory` | Chroma 集合名称 |
要通过远程 OpenAI 兼容的 `/v1/embeddings` 端点路由嵌入,请设置 `EMBEDDING_PROVIDER=openai_compatible` 并填写 `EMBEDDING_BASE_URL` / `EMBEDDING_API_KEY`。
## 编写您自己的索引器
`examples/index_markdown.py` 是模板。适配器需要:
1. 发现源项,
2. 将每个项转换为 `(text, metadata)` 块 — 始终设置 `agent` 和 `source`,以及一个 ISO `timestamp`(如果您想要 `since` 过滤),
3. 调用 `add_chunks(collection, embedder, ids, texts, metadatas, upsert=True)`。
使用稳定、确定的 ID 方案,以便重新运行 upsert 而不是重复。
## 设计笔记
- **嵌入由我们计算,而不是由 Chroma 计算。** 向量在 `add`/`query` 上显式传递,因此存储与嵌入可用性分离。
- **分块(markdown):** 按 `##` 标题拆分;回退到段落;软上限 8000 字符。
- **时间戳** 是整个 ISO-UTC 字符串(ISO 按字典序排列,这是 `since` 过滤器依赖的)。
- **搜索时卫生:** 结果按内容哈希去重,并删除短的已知错误字符串。
## 路线图
- [ ] 高容量源的 TTL / 遗忘策略。
- [ ] 索引时可选的 PII 过滤器。
- [ ] 会话结束钩子以自动索引新内容。
- [ ] 更多示例适配器(聊天日志、问题跟踪器)。
## 贡献
问题和 PR 欢迎 — 请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。新的索引适配器(聊天日志、问题跟踪器、文档)是一个很好的起点。
## 许可证
[MIT](LICENSE)。