我用 Docker 自托管了 AI 记忆系统,踩了 5 个坑全记录

背景:AI Agent 的"失忆症"

最近在用 AI Agent(比如 Claude、GPT 这类)帮我写代码,发现一个很烦的问题------每次开新对话,它完全不记得我之前是谁、做什么项目、用什么技术栈。每次都要重新自我介绍一遍,效率极低。

市面上的方案要么贵(按月付费),要么数据不在自己手里(云端存储)。我想找个自托管、免费、数据本地、支持多 Agent 共享的记忆系统。

调研了一圈,选了 Honcho------一个用 Python + FastAPI 写的自托管记忆服务,支持多 Agent、向量检索、方言推理。刚好我手头有 WSL2 + Docker Desktop,LLM 用的是 DeepSeek(便宜)。

下面是我从头搭建到跑通的完整过程,重点是我踩的 5 个坑


整体架构

css 复制代码
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  Hermes     │    │  Claude     │    │  其他 Agent  │
│  (你)       │    │  Code       │    │             │
└──────┬──────┘    └──────┬──────┘    └──────┬──────┘
       │                  │                  │
       └──────────────────┼──────────────────┘
                          │
                   ┌──────▼──────┐
                   │   Honcho    │  ← 自托管 Docker
                   │   API :8000 │
                   └──────┬──────┘
                          │
          ┌───────────────┼───────────────┐
          │               │               │
    ┌─────▼─────┐  ┌──────▼──────┐  ┌─────▼─────┐
    │ Deriver   │  │  Embedding  │  │ Postgres  │
    │ (DeepSeek)│  │  (jina-v2)  │  │ +pgvector │
    └───────────┘  └─────────────┘  └───────────┘

三个核心组件:

  • Honcho API:接收消息、管理会话
  • Deriver:用 LLM 从对话中提取关键信息
  • Embedding 服务:把文本转成向量,支持语义搜索

环境

  • Windows 11 + WSL2(Ubuntu)
  • Docker Desktop(WSL2 集成模式)
  • DeepSeek API(deepseek-chat 模型)
  • 本地 embedding 服务(jina-embeddings-v2-base-zh,768 维)

坑 1:Docker 镜像拉不下来

第一个命令就跑不通:

bash 复制代码
git clone https://github.com/plastic-labs/honcho.git
cd honcho
docker compose up -d   # ❌ 卡住不动

Docker Hub 在国内基本不可达。解决:在 Docker Desktop → Settings → Docker Engine 里加上镜像源:

json 复制代码
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.xuanyuan.me"
  ]
}

改完记得 wsl --shutdown 重启 WSL,否则不生效。

另外如果开了代理(比如 clash-verge,本地端口 10808),还可以在 Docker Desktop Settings → Resources → Proxies 里配上 HTTP/HTTPS 代理,双保险。


坑 2:DeepSeek 当 LLM + Embedding 的"分裂"配置

Honcho 默认用 OpenAI,但我要用 DeepSeek。.env 配置如下:

bash 复制代码
# LLM 配置
LLM_MODEL_CONFIG__TRANSPORT=deepseek
LLM_MODEL_CONFIG__MODEL=deepseek-chat
LLM_MODEL_CONFIG__API_KEY=sk-xxxxxxxx
LLM_MODEL_CONFIG__BASE_URL=https://api.deepseek.com

# 关键:DeepSeek 没有 embedding API!
# 必须显式配置 embedding provider,否则会走 OpenAI 的 text-embedding-3-small
EMBEDDING_MODEL_CONFIG__TRANSPORT=openai
EMBEDDING_MODEL_CONFIG__MODEL=jina-embeddings-v2-base-zh
EMBEDDING_MODEL_CONFIG__API_KEY=not-needed
EMBEDDING_MODEL_CONFIG__BASE_URL=http://localhost:8080/v1

核心教训:DeepSeek 有 Chat API 但没有 Embedding API 。如果不显式配 EMBEDDING_MODEL_CONFIG,Honcho 会默认走 OpenAI,但又没有 OpenAI key,直接挂掉。

我选的是 jina-embeddings-v2-base-zh,用 sentence-transformers 在本机 8080 端口起了一个兼容 OpenAI 格式的 embedding 服务。768 维,中文友好,单条 51ms,内存占用 ~1.2GB。


坑 3:pgvector 维度不匹配------最隐蔽的坑

Honcho 默认用 PostgreSQL + pgvector 存向量,默认维度是 1536(OpenAI text-embedding-3-small 的输出维度)。

但 jina-v2 输出的是 768 维

直接写入会报错:

yaml 复制代码
ERROR: expected 1536 dimensions, not 768

解决分两步:

第一步:改数据库

sql 复制代码
-- 连接数据库(注意数据库名是 postgres,不是 honcho)
docker exec honcho-database-1 psql -U postgres -d postgres

-- 改两表的向量列
ALTER TABLE documents ALTER COLUMN embedding TYPE vector(768);
ALTER TABLE message_embeddings ALTER COLUMN embedding TYPE vector(768);

-- 重建 HNSW 索引
DROP INDEX IF EXISTS documents_embedding_idx;
CREATE INDEX documents_embedding_idx ON documents USING hnsw (embedding vector_cosine_ops);

DROP INDEX IF EXISTS message_embeddings_embedding_idx;
CREATE INDEX message_embeddings_embedding_idx ON message_embeddings USING hnsw (embedding vector_cosine_ops);

第二步:改源码

Honcho 有个向量迁移策略:schema 里的 Vector(1536) 是硬编码的,并且有个 MIGRATED 环境变量控制是否走新代码路径。但代码里用的是 or not MIGRATED,导致 MIGRATED=false 时永远走旧路径。

需要把 6 个文件里的 or not MIGRATED 改成 and not MIGRATED

python 复制代码
# 改前
if not MIGRATED or not migrated:
# 改后
if not MIGRATED and not migrated:

涉及文件:

  • src/config.py
  • src/crud/message.py
  • src/crud/document.py
  • src/search.py
  • src/sync_vectors.py

改完重建镜像:

bash 复制代码
docker compose build --no-cache api deriver
docker compose up -d api deriver

坑 4:DeepSeek json_object 兼容性------deriver 直接罢工

最坑的一个。

Honcho 的 deriver 组件负责用 LLM 从对话中提取关键信息(观察)。它会调用 DeepSeek API,设置 response_format: json_object

但 DeepSeek 有一条奇葩要求:prompt 里必须包含单词 "json",否则 400 错误

vbnet 复制代码
ERROR - Error code: 400 - "Prompt must contain the word 'json' in some form 
to use 'response_format' of type 'json_object'."

Honcho deriver 的系统提示词是 "Analyze messages from {peer_id} to extract explicit atomic facts..."------你仔细看,全篇没有一个 "json" 单词

deriver 重试 3 次后直接放弃,队列里堆了 49 条消息没人处理,整个推理功能不可用。

解决:src/llm/backends/openai.py 两处注入 "Respond in JSON."

python 复制代码
# 位置 1:_build_params() 中 json_mode 分支
if extra_params.get("json_mode"):
    params["response_format"] = {"type": "json_object"}
    # 注入这一行
    system_msg["content"] += "\nRespond in JSON."

# 位置 2:_create_structured_response() 中 json_schema 回退路径
# 类似地,在设置 json_object 后向消息追加 "\nRespond in JSON."

改完同样的 docker compose build --no-cache api deriver && docker compose up -d api deriver


坑 5:FLUSH_ENABLED------短消息会永久卡在队列

Honcho 有一个消息 flush 机制:新消息会先进队列,等待攒够一定量后再由 deriver 批量处理。但如果你发了一条很短的消息(比如 "你好"),可能永远凑不够批量阈值,消息就一直卡着。

加上这行到 .env

bash 复制代码
FLUSH_ENABLED=true

这样每条消息都会触发即时处理,不再等待攒批。

代价是多消耗一点 LLM token(每次都调一次 API),但对个人使用来说完全可忽略。


端到端验证:别信容器状态

容器全部 healthy 不代表功能正常。我总结了一套三步验证法:

bash 复制代码
# 1. 写入测试
curl -X POST http://localhost:8000/v3/workspaces/hermes/sessions/test/messages \
  -H "Content-Type: application/json" \
  -d '{"content": "用户用 Python 写后端,喜欢 FastAPI", "peer_name": "sanlin"}'

# 2. 搜索验证(等 30 秒让 deriver 处理)
curl http://localhost:8000/v3/workspaces/hermes/peers/sanlin/search \
  -d '{"query": "Python"}'

# 3. 推理验证
# 使用 honcho CLI 或 API 调用推理接口

三步全通过才算"正常运行"。


成本

项目 费用
DeepSeek API ~0.1 元/天(个人使用,对话量不大)
jina-v2 embedding 免费(本地跑,1.2GB 内存)
Honcho 服务 免费(自托管)
Docker Desktop 免费(个人版)

每月花销不到 3 块钱。


总结

五个坑按隐蔽程度排序:

  1. ⭐⭐⭐⭐⭐ pgvector 维度不匹配------既要改数据库,又要改源码
  2. ⭐⭐⭐⭐ json_object 兼容性------DeepSeek 特有要求,报错信息明确但不明显
  3. ⭐⭐⭐ Embedding 配置分离------DeepSeek 无 embedding API,必须显式配
  4. ⭐⭐ Docker 镜像拉取------国内通用问题,有标准解法
  5. FLUSH_ENABLED------文档有提但不醒目

如果你也想自托管 Honcho + DeepSeek,照着这五个坑提前填好,应该能少走很多弯路。


最后安利一下 Honcho 的 Peer 模型设计:同一个用户画像(sanlin)可以被多个 Agent(Hermes、Claude Code、自写脚本)共享,但每个 Agent 的行为和记忆又是隔离的。这比简单的"全局记忆池"灵活太多。

相关推荐
无心水1 小时前
【Hermes:安全、权限与生产环境】39、智能体也会犯错?Hermes 纠错、回滚与遗忘机制全指南 —— 让 AI 的错误像 Git 一样可逆可控
人工智能·git·安全·mcp协议·openclaw·hermes·honcho
小白编程锤炼1 小时前
深入解析:质量门禁
人工智能·算法·架构·vibe-coding
Ares-Wang1 小时前
AI》》 监督学习,无监督学习,半监督学习、强化学习 、深度学习 统计学的常用方法
人工智能·深度学习·学习
江瀚视野1 小时前
DeepWay深向盈利拐点趋近意味着什么?
大数据·人工智能
爱学习的张大1 小时前
KG与LLM:大模型时代的智能规划
人工智能
三维重建-光栅投影1 小时前
线性代数之超定方程使用最小二乘求解
人工智能·线性代数
老码观察2 小时前
数环通iPaaS知识库选型实践:从技术评估到RAGFlow深度调优
人工智能·agent·知识库
从零开始的奋豆2 小时前
从零构建 ClaudeCode 风格的 AI 编程助手:Code Agent 完整架构解析
人工智能·架构
多年小白2 小时前
【行情复盘】2026年5月12日(周二)
人工智能·科技·机器学习·ai·金融