我用 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 的行为和记忆又是隔离的。这比简单的"全局记忆池"灵活太多。

相关推荐
阿里云大数据AI技术7 小时前
从算力到智能体,面向 Agentic AI 的基础设施演进
人工智能·agent
hangyuekejiGEO7 小时前
GEO技术服务选型指南
大数据·人工智能·python
阿里云大数据AI技术8 小时前
EMR Serverless Spark AI Function 的双维降本实践
人工智能·sql·spark
维基框架8 小时前
GitHub源码处理提速 一趟扫描反而更慢
人工智能·github
冬奇Lab8 小时前
代码库知识库系列(05):向量检索 vs 知识图谱——加了调用图并没有变更好
人工智能
AKAMAI8 小时前
你的源服务器可能是你做出的最昂贵决定
运维·人工智能·云计算
冬奇Lab8 小时前
【无标题】
人工智能·开源
专业贴准9 小时前
苏州SMT供料器设备选型分析:本地主流自动化企业技术特点与行业趋势
人工智能·自动化·制造
cxr8289 小时前
Synapse Mind (三维智能认知图谱) 全景深度工程
人工智能·交互·智能体·认知框架