158 lines
5.3 KiB
Markdown
158 lines
5.3 KiB
Markdown
# TASK RESULT
|
||
|
||
## Research Notes
|
||
|
||
1. **当前最适合 pin 的 QMD 版本**
|
||
- 选择 `v1.0.7`(`@tobilu/qmd@1.0.7`),是截至 2026-03-07 的最新非预发布 stable release(发布时间 2026-02-18)。
|
||
|
||
2. **是否已有官方 compose 参考**
|
||
- 在 `tobi/qmd` 的 `v1.0.7` 源码树中未找到 `Dockerfile` / `docker-compose.yml` 参考,需要自行实现。
|
||
|
||
3. **QMD HTTP MCP 启动与健康检查方式**
|
||
- 启动:`qmd mcp --http`(默认端口 8181)
|
||
- 端点:`POST /mcp`、`GET /health`
|
||
|
||
4. **是否需要覆盖默认模型**
|
||
- 第一版不覆盖,直接沿用源码默认模型(embeddinggemma / qwen3-reranker / qmd-query-expansion)。
|
||
|
||
5. **Node 与 Bun 在容器中选型**
|
||
- 选 Node(`node:22-bookworm-slim`)。理由:
|
||
- 上游 package `engines.node >=22`
|
||
- `npm install -g @tobilu/qmd@1.0.7` 路径直接、可复现
|
||
- 官方生态和镜像稳定性更高,长期维护成本更低
|
||
|
||
6. **缓存目录、索引目录、知识库目录挂载策略**
|
||
- `XDG_CACHE_HOME=/var/lib/qmd/cache`(模型缓存 + 默认 sqlite 索引)
|
||
- `XDG_CONFIG_HOME=/var/lib/qmd/config`(collection YAML 配置)
|
||
- 业务知识库挂载到 `/data/knowledge`
|
||
- 测试数据挂载到 `/data/testdata`
|
||
|
||
7. **smoke test 最小闭环覆盖步骤**
|
||
- compose 启动服务
|
||
- `/health` 检查通过
|
||
- 添加 collections(notes/docs/meetings)
|
||
- `qmd update` + `qmd embed`
|
||
- 至少一次 `qmd search`
|
||
- 至少一次 `qmd query`(deep search 等价能力)
|
||
|
||
## Implemented Files
|
||
|
||
```text
|
||
qmd-docker-http-mcp/
|
||
├─ Dockerfile
|
||
├─ docker-compose.yml
|
||
├─ .dockerignore
|
||
├─ README.md
|
||
├─ TASK-RESULT.md
|
||
├─ scripts/
|
||
│ ├─ entrypoint.sh
|
||
│ ├─ warmup.sh
|
||
│ └─ smoke-test.sh
|
||
├─ knowledge/
|
||
└─ testdata/
|
||
├─ notes/
|
||
├─ docs/
|
||
└─ meetings/
|
||
```
|
||
|
||
## Commands Executed (Real)
|
||
|
||
```bash
|
||
# Research
|
||
curl -fsSL https://api.github.com/repos/tobi/qmd/releases?per_page=5 | jq ...
|
||
curl -fsSL https://api.github.com/repos/tobi/qmd/git/trees/v1.0.7?recursive=1 | jq -r '.tree[].path' | rg 'docker|compose|Dockerfile|docker-compose' || true
|
||
curl -fsSL https://raw.githubusercontent.com/tobi/qmd/v1.0.7/README.md
|
||
curl -fsSL https://raw.githubusercontent.com/tobi/qmd/v1.0.7/src/llm.ts
|
||
|
||
# Build / Run
|
||
cd qmd-docker-http-mcp
|
||
docker build -t hotwa/qmd:latest .
|
||
docker compose up -d
|
||
docker compose logs --no-color --tail=120 qmd
|
||
curl -fsS http://127.0.0.1:8181/health
|
||
|
||
# Warmup / Smoke
|
||
./scripts/warmup.sh
|
||
./scripts/smoke-test.sh
|
||
|
||
# Extra MCP endpoint check
|
||
curl -X POST http://127.0.0.1:8181/mcp -H 'content-type: application/json' -d '{}'
|
||
```
|
||
|
||
## Build Result
|
||
|
||
- Image built successfully: `hotwa/qmd:latest`
|
||
- Image inspect summary:
|
||
- `hotwa/qmd:latest b5c811d89722 1.99GB`
|
||
|
||
## Compose Startup Result
|
||
|
||
- `docker compose up -d` 成功
|
||
- `docker compose ps` 结果:
|
||
- `qmd-http-mcp ... Up ... (healthy) ... 0.0.0.0:8181->8181/tcp`
|
||
|
||
## Healthcheck Result
|
||
|
||
- `GET /health` 返回成功:
|
||
|
||
```json
|
||
{"status":"ok","uptime":244}
|
||
```
|
||
|
||
- `POST /mcp` 路由可达(示例请求返回协议校验错误而非 404):
|
||
- HTTP `406`
|
||
- `Not Acceptable: Client must accept both application/json and text/event-stream`
|
||
|
||
## Warmup Result
|
||
|
||
- 成功创建并索引 3 个 collection:`notes` / `docs` / `meetings`
|
||
- 成功执行 `qmd update`
|
||
- 成功执行 `qmd embed`
|
||
- 首次运行完成 embedding 模型下载并生成向量
|
||
|
||
## Smoke Test Result
|
||
|
||
`scripts/smoke-test.sh` 真实执行通过,覆盖:
|
||
|
||
- 服务启动与 `/health` 成功
|
||
- collection 检查通过(3/3)
|
||
- `qmd search "incident runbook" --json -n 5` 返回命中(含 `docs/incident-runbook.md`)
|
||
- `qmd query "what is the RTO target for disaster recovery" --json -n 5` 返回命中(`docs/disaster-recovery.md` 得分最高)
|
||
- 脚本最终输出:`[smoke] Smoke test passed`
|
||
|
||
## Problems Found and Fixes
|
||
|
||
1. **问题:容器外访问 8181 失败(连接被重置)**
|
||
- 根因:QMD `v1.0.7` 的 HTTP MCP 在上游实现中绑定 `localhost`。
|
||
- 修复:在 `entrypoint.sh` 引入 `socat` 转发,将容器 `0.0.0.0:8181` 转发到容器内 QMD 监听端口。
|
||
|
||
2. **问题:初版转发到 `127.0.0.1:8182` 仍失败**
|
||
- 根因:QMD 在容器内实际监听 `::1`(IPv6 localhost),`127.0.0.1` 不通。
|
||
- 修复:改为 `socat ... TCP6:[::1]:8182`。
|
||
|
||
3. **观察项:首次 query/embed 有 node-llama-cpp 的 CUDA 构建回退告警**
|
||
- 现象:日志提示 `git/cmake not found`,随后回退并继续 CPU 路径,流程最终成功。
|
||
- 结论:当前不阻塞功能闭环,但会增加首次请求噪声与时延。
|
||
|
||
## Final Acceptance
|
||
|
||
验收条件逐项结果:
|
||
|
||
- [x] 成功构建 `hotwa/qmd:latest`
|
||
- [x] `docker compose up -d` 后服务启动
|
||
- [x] `/health` 返回成功
|
||
- [x] 至少一组测试数据被索引
|
||
- [x] 至少一次关键词搜索成功
|
||
- [x] 至少一次深检索/混合检索成功
|
||
- [x] README 可指导复现
|
||
- [x] 本文件记录真实测试过程(无伪造)
|
||
|
||
## Sources
|
||
|
||
- QMD releases: https://api.github.com/repos/tobi/qmd/releases
|
||
- QMD v1.0.7 README: https://raw.githubusercontent.com/tobi/qmd/v1.0.7/README.md
|
||
- QMD v1.0.7 llm.ts: https://raw.githubusercontent.com/tobi/qmd/v1.0.7/src/llm.ts
|
||
- QMD v1.0.7 mcp.ts: https://raw.githubusercontent.com/tobi/qmd/v1.0.7/src/mcp.ts
|
||
- Codex MCP docs: https://developers.openai.com/codex/mcp/
|
||
- Claude Code MCP docs: https://docs.anthropic.com/en/docs/claude-code/mcp
|