9.0 KiB
9.0 KiB
Git 一致性优先的共享记忆检索系统
本项目在现有 QMD 基础上增加 memory-gateway,目标是让多 Agent 查询具备“查询前强制同步”的一致性,而不是只依赖后台轮询同步。
1. 项目背景
在多 Agent 协作里,若“同步”和“查询”解耦为两个松散后台动作,会出现:
- Agent A 读到旧记忆
- Agent B 读到新记忆
- 对任务目标、恢复点、执行上下文理解分叉
本项目的核心设计:
- Git 是 source of truth
- QMD 只做索引和检索
- memory-gateway 负责查询前同步与一致性协调
2. 架构与一致性事务
flowchart LR
C[Remote Client\nCodex/Claude/OpenClaw] --> G[memory-gateway\nHTTP :8787]
G --> S[Sync Transaction\nfetch -> workspace sync -> qmd update/embed]
S --> Q[qmd search/query\nper-workspace index]
Q --> G
G --> C
G --> M[/data/git-mirror/repo.git]
G --> W1[/data/workspaces/main]
G --> W2[/data/workspaces/memory-2026-03]
G --> W3[/data/workspaces/task-TASK-001]
/query 的主链路:
- 解析
branch / memory_profile / query_type / query - 获取 workspace 锁(同 workspace 串行,不同 workspace 并行)
git fetch+ workspace 对齐到目标 branch 最新 commitqmd update(需要时embed)- 执行检索
- 返回结果 +
branch/commit_hash/synced_at/workspace
3. 服务职责
qmd
- 提供 MCP/HTTP 能力(
8181) - 持久化 cache/config
- 作为底层检索引擎,不作为远程客户端唯一入口
memory-gateway
- 远程唯一入口(
8787) - 提供
GET /health、POST /query、POST /sync、GET /status - 强制执行查询前同步
warmup(可选)
- 定时轻量请求,降低冷启动抖动
- 仅优化项,不提供一致性保证
4. 目录与关键路径
仓库目录(Host)
.
├─ docker-compose.yml
├─ .env.example
├─ AGENTS.md
├─ README.md
├─ gateway/
│ ├─ app/
│ ├─ tests/
│ ├─ requirements.txt
│ └─ Dockerfile
├─ scripts/
│ ├─ qmd-entrypoint.sh
│ ├─ bootstrap.sh
│ ├─ warmup.sh
│ └─ smoke-test.sh
└─ data/
├─ git-mirror/
├─ workspaces/
├─ qmd-cache/
├─ qmd-config/
└─ remote-memory.git/ # bootstrap 生成的本地 demo remote
容器内路径
- Git mirror:
/data/git-mirror/repo.git - Workspace 根目录:
/data/workspaces - QMD cache:
/var/lib/qmd/cache(qmd 容器)//data/qmd-cache(gateway 调 CLI) - QMD config:
/var/lib/qmd/config(qmd 容器)//data/qmd-config(gateway 调 CLI)
查询返回路径映射(项目相对路径)
为方便你直接在项目目录定位,/query 与 /sync 返回的 resolved_workspace 使用项目相对路径,而不是容器绝对路径。
main->data/workspaces/mainmemory/2026-03->data/workspaces/memory-2026-03task/TASK-001->data/workspaces/task-TASK-001
内部容器路径仍是 /data/workspaces/...,网关会在响应时转换为相对路径表示。
5. 分支与 profile 规则
优先级:branch > memory_profile > main
stable->mainmonthly-YYYY-MM->memory/YYYY-MMtask-<task-id>->task/<task-id>
建议分层:
- 长期稳定:
main - 月度滚动:
memory/YYYY-MM - 任务临时:
task/<task-id>
6. 环境变量(关键配置)
必填
GIT_REMOTE_URL:Git 真相源地址(ssh/https/file/path)
常用
DEFAULT_BRANCH:默认分支(默认main)QMD_TIMEOUT_SECONDS:gateway 调 qmd CLI 超时秒数(默认300)QMD_INDEX_PREFIX:per-workspace 索引名前缀(默认ws)QMD_UPDATE_ON_LATEST_QUERY:require_latest=true时是否强制qmd update(默认true)QMD_EMBED_ON_CHANGE:HEAD 变化时是否尝试 embed(默认true,可按性能改false)
GPU(qmd 容器)
CUDA_DEVICECUDA_VISIBLE_DEVICESNVIDIA_VISIBLE_DEVICES
模型覆盖(可选)
QMD_EMBED_MODEL_URIQMD_RERANK_MODEL_URIQMD_GENERATE_MODEL_URI
示例:见 [.env.example](/home/lingyuzeng/project/qmd-local/qmd-docker-http-mcp/.env.example)。
7. 快速开始
7.1 初始化 demo remote 与目录
cd /home/lingyuzeng/project/qmd-local/qmd-docker-http-mcp
./scripts/bootstrap.sh
7.2 启动
docker compose build
docker compose up -d
7.3 健康检查
curl http://127.0.0.1:8181/health
curl http://127.0.0.1:8787/health
8. API 使用
GET /health
curl -fsS http://127.0.0.1:8787/health
POST /sync
curl -fsS -X POST http://127.0.0.1:8787/sync \
-H 'content-type: application/json' \
-d '{"branch":"main","require_latest":true}'
POST /query(主入口)
curl -fsS -X POST http://127.0.0.1:8787/query \
-H 'content-type: application/json' \
-d '{
"branch":"main",
"query_type":"search",
"query":"recovery strategy",
"require_latest":true,
"debug":true
}'
返回字段核心:
okbranchresolved_workspace(项目相对路径,例如data/workspaces/main)commit_hashsynced_atquery_typeresultsqmd_collectiondebug(可选)
GET /status
curl -fsS http://127.0.0.1:8787/status
9. 查询策略说明
当前最小兼容实现中:
query_type=search->qmd searchquery_type=vsearch->qmd vsearchquery_type=query/deep_search-> 为保证稳定与时延上界,默认走qmd search(响应debug.qmd_command可追踪)
10. 测试与验收
自动化测试
python3 -m venv .venv
. .venv/bin/activate
pip install -r gateway/requirements.txt pytest httpx
PYTHONPATH=./gateway pytest -q gateway/tests
手工验收(建议)
- 构建与启动
- 服务健康
- 基础查询
- 修改远端后立即查询(验证查询前同步)
- 分支隔离
- 默认分支
- 并发查询
- 重启恢复
11. 常见问题
首次请求慢
首次模型/索引准备、或首次分支激活会慢。可用:
QMD_EMBED_ON_CHANGE=false(降低请求阻塞)- warmup profile 预热
本地路径 remote 被 git safe.directory 拦截
gateway 已对本地 GIT_REMOTE_URL 自动添加 safe.directory。
12. 客户端接入建议
- 远程客户端只访问
memory-gateway,不要直连 qmd - 每次请求尽量显式传
branch或memory_profile - 记录响应中的
branch + commit_hash用于审计与回放
13. 关键文件
- 网关入口:gateway/app/main.py
- 同步事务:gateway/app/sync_service.py
- Git 管理:gateway/app/git_manager.py
- QMD 调用:gateway/app/qmd_client.py
- Compose 编排:docker-compose.yml
14. 多 Agent 记忆仓库最佳实践
14.1 子记忆仓库怎么放
建议把“记忆系统仓库”单独管理,并在本项目中通过 .gitignore 忽略运行态 clone/mirror/workspace。
- 推荐:独立 memory repo(独立 push/pull 生命周期)
- 不推荐主方案:submodule(多 agent 高频写入时维护成本高、冲突处理复杂)
14.2 推荐目录结构(memory repo 内)
memory-repo/
├─ shared/
│ ├─ announcements/
│ └─ sop/
├─ agents/
│ ├─ agent-a/
│ │ ├─ AGENT-CARD.md
│ │ ├─ MEMORY-LOG.md
│ │ ├─ PROMPT-RULES.md
│ │ ├─ inbox/
│ │ ├─ working/
│ │ ├─ handoff/
│ │ └─ checkpoints/
├─ tasks/
│ └─ TASK-001/
└─ policies/
└─ WRITE-PERMISSIONS.yaml
14.3 每个子 Agent 的脚手架
本仓库提供脚手架脚本:scripts/scaffold-agent-memory.sh
示例:
./scripts/scaffold-agent-memory.sh \
--repo /path/to/memory-repo \
--agent agent-a \
--default-branch main
作用:
- 生成
agents/<agent-id>/标准目录 - 生成
AGENT-CARD.md(身份与可写路径声明) - 生成
PROMPT-RULES.md(写前 pull、冲突处理规则) - 生成
policies/WRITE-PERMISSIONS.yaml
14.4 多 Agent 同步与冲突最小化策略
- 写入前固定执行:
git pull --rebase origin <branch> - 尽量 append-only,减少多人改同一行
- 原子小提交(按一次记忆动作提交)
- 推送失败先 rebase,再自动合并一次;仍冲突则人工解决
- 共享目录写权限建议通过 gateway 或服务端 hook 校验,避免越权路径写入
14.5 与 QMD/gateway 的关系
- Git 仓库负责“真相源”和版本历史
- gateway 负责查询前同步和分支/工作区隔离
- qmd 负责本地索引与检索
这样可以同时满足:
- 多 agent 共享记忆
- 查询一致性
- 冲突可控
- 结果可追溯(branch + commit)