0人正在访问博客
2026-10-31 · LLM · SELF-HOSTED

自托管记忆引擎大检修 - 9 模型大战、僵尸定时任务,与“上限只是保险”哲学

TL;DR

  • 我花了三天对自托管记忆引擎(Honcho)的召回回路(dialectic)做全面翻修:9 模型实测大战 → 僵尸定时任务事故 → 配置哲学之争
  • 最终架构:记录用 glm-5.3-flash(包月免费),日常召回用 haiku-5.5(实测 $0.0135/次),深度研究(max)单独换成 glm-5.3+thinking MAX(免费,实测 178 秒)
  • 上限(轮数、输出 Token)不是省钱工具,而是防发散的保险 -- 统一设为服务器允许的最大值才是正解
  • 最大的教训:源码默认值里藏着"每个等级用不同模型"的隐含假设。 一旦打破这个假设,默认值就变成毒药

背景:赢下基准测试只是前一半

在上一篇文章里,haiku-5.5 赢下了 6 路召回后端实测。但基准夺冠只完成了一半。落地生产 → 扛过事故 → 确立配置原则,自己管服务器就是这么回事。本文是后半场的记录。

9 模型大战的完整记分板

用同一协议(3 事实召回 × 10 次)打真实的 dialectic 管线:

实验 模型 结果 判定
EXP3 recursive/flint-v1.0:free 准确率 71% 免费的代价 - 不推荐
EXP3b mistral-nemo ($0.03/M) 事实准确率 0%(合成失败) 弃用
EXP3c nemotron-3-ultra-550b(本地网关) 9 次中 5 次 120 秒超时 单次调用稳定性在多次调用放大下崩塌
EXP3d qwen3.5-flash 因诚实的"无信息"拒绝在筛选出局 → 触发 haiku 复测:带上上下文一切都不同
EXP3e haiku-5.5 20.9s · 事实 30/30 · $0.0135/次 👑 夺冠
EXP3f haiku + Anthropic 原生缓存 缓存无效 cache_control 标记只挂在 system 上,覆盖不到主体
EXP3g gpt-6-luna 13.7s 破纪录,成本仅 18% 质量不达标 - 速度冠军毫无意义
EXP3h haiku + thinking off 13.1s 但准确率 100→62% 实证 thinking 是合成质量的核心

最令人印象深刻的是 EXP3e 的元诚实:它在召回回答里主动识别出"F1 0.92 这个数字来自 Honcho 实验提示词原文",并与我的原话区分开。在筛选阶段让它出局的那种诚实拒绝,在挂上真实记忆上下文后升华为准确性。

贯穿全部实验的教训:单发筛选 ≠ 管线性能。 单发 3.8s 的免费模型在 16K 上下文的 dialectic 上平均 86 秒、超时率 20%。选型必须用真实负载跑 10 次端到端。

僵尸定时任务:自动化倒转了自己的配置

整个战役中最毛骨悚然的一幕。为实验监督搭的 n8n 门控早已草草收场,但它内部的5 分钟定时任务还活着,晚上 9 点 20 分自己复活,把进行中的实验的 .env"恢复"(=回滚)了。正在复现的实验被一个本不该存在的配置杀掉。

对策就是源头切断:

  1. 停掉 n8n + 清扫所有僵尸执行
  2. 给 .env 上 chattr +i(不可变)- 文件级防火墙
  3. 基准设施从 n8n 迁到 Windmill(Postgres 持久队列、步骤级并行)

教训:自动化监督者必须有寿命。 一次性任务的门控以永久定时任务的形式存活下来,早晚会咬主人一口。

落地阶段的两个坑

  1. API Key 路径:MODEL_CONFIG__API_KEY_ENV 会被静默忽略 - 必须写 OVERRIDES__API_KEY_ENV。症状(401)离病因(配置位置错误)十万八千里,排查花了很久
  2. thinking 上限:关掉 thinking,haiku 崩到 62%(见表)。"默认最优"已写进注释刻死

验证工具本身的坑

  • docker exec -e VAR=x 覆盖测试不生效 - 应用启动时执行 load_dotenv(override=True),挂载的 /app/.env 永远赢。要确认生效值只能在容器内直接内省 settings
  • 在 env 里写 MAX_OUTPUT_TOKENS=null(想要全局回退)会因未设置 env_parse_none_str 而验证崩溃、服务器拒绝启动。写同值显式覆盖才是正解

源码默认值的隐含假设:被倒转的轮数阶梯

Honcho dialectic 各等级(minimal–max)的源码默认轮数是 1/5/2/4/10 - 一个 low 比 medium 高 2.5 倍的非单调阶梯。翻出引入提交后发现:

# TODO: Fill in appropriate values for each reasoning level

作者本人留下的注释承认这些是手工调的临时值。而这些值的前提是每个等级不同的模型+thinking(最初 low = 用便宜快模型搜 5 次的档位)。当我统一模型后,等级只剩下轮数差异 - 阶梯当场倒转。"等级越高越好"的预期在配置层面不再成立。

上限哲学:保险就该放在模型极限附近

在此我确立了自己的原则:上限不是省钱工具,是防发散的保险。

  • 压低输出 Token 上限省不了钱 - 计费按实际生成为准,一旦截断,input+推理费用照付、可见回答为零。OpenAI、Anthropic、Gemini 官方文档都在警告这一点;Gemini 更是直说"别压 max_output_tokens,去降 thinking 档位"
  • haiku-5.5 官方最大输出 128K,但 Honcho 配置校验上限 le=100000 → 全等级统一 100000(设 128000 服务器会拒绝启动)
  • 轮数同理:校验上限 le=50(工具循环硬上限 100)→ 全等级统一 50。现代模型会自适应地在 1–3 轮内自己收尾,实际开销不变,50 纯粹是最坏情况的天花板

出发点是这个信念:现代模型自己就能选好合适的推理量和轮数。 既然如此,上限不该是调教模型的工具,而应该只在真正发散时兜底的保险网。

effort 默认值是有官方明文的(但是……)

我一直知道"haiku 用默认 thinking 最优",但默认到底是多少?官方文档回答:haiku-5.5(和 opus 5.5)默认 effort 为 medium - 其他模型默认 high。thinking 永远开启(adaptive)。

有趣的是这个实测矛盾:官方声称"设为默认值与省略完全相同",但 dialectic 实测中显式 medium 96.8s vs 省略 20.9s - 差了 4.5 倍。我的推测:adaptive 的本质是连"要不要思考"都由模型自掸,显式指定 effort 会把这个掸子固定住。无论如何,保持不指定的结论被双重确认了。

最终架构与成本

角色 模型 成本 实测
记录(deriver/summary/dream) glm-5.3-flash + thinking max 包月免费 常驻
日常召回(low) haiku-5.5(不指定 thinking) $0.0135/次 15–21s
深度研究(max) glm-5.3 + thinking MAX 免费(包月) 178s
搜索嵌入 qwen3-embedding:4b 本地 Ollama 免费 -

日常召回便宜又快,"真往深了挖"的请求走免费慢速档。轮数 50 / 输出 100000 是全链路共用的保险。

遗留事项

  • 每轮自动注入(perTurn)关闭的 2 周实验 - 11 月 13 日前后复评
  • Honcho v3.0.3 → v3.0.9(145 commits)升级 - 因构建/迁移问题继续搁置

通用化的要点

  1. 模型基准要用真实管线负载跑 10 次端到端。 单发筛选只会给出错误答案
  2. 给自动化管线设寿命。 活下来的定时任务早晚会回滚你的配置
  3. 源码默认值里藏着假设。 打破这些假设的部署(例如统一模型)值得重新审查默认值
  4. 上限是保险。 算好保费(所需 Token),把它设在模型极限附近 - 而不是低得危险
  5. 验证要看应用的生效值。 env 变量覆盖在 dotenv override=True 面前毫无还手之力
评论 (0)
COUNTER
001065
TOTAL VIEWS
0007
TODAY