这个博客的每一处细节 —— 为什么用 Workers 不用 Pages、封面为什么是那张雪景、sticky 和 top 有什么区别 —— 都是一次次折腾出来的。

问题是:这些上下文只存在于对话里,不在项目里。

于是每次开新会话,我都得从头讲一遍。这次我决定给它配一个「记忆」。

结果折腾了一晚上、踩了四个坑才发现:我一开始选的方向,就是重的。


我想要的到底是什么

不是「让 AI 更聪明」,是一件很具体的事:

下次打开这个项目,它就已经知道:技术栈是什么、部署怎么走、
哪些写法是「看起来多余但删了就坏」的、域名卡在哪一步。

这个博客已经有四篇文章和一份很长的 README,但那些是给人看的。我要的是给 AI 看的:能按语义检索,还能在动手之前主动提醒「这里你以前踩过坑」。


第一版方案:云端记忆

我先上的是一个云端记忆插件。它按仓库分库,自动把会话内容抽成「记忆条目」,下次按语义召回。

听起来很顺。然后我在四个坑里各摔了一次。

坑 1:装好了,但没配密钥 —— 读写全部 401

插件装上了,我以为就能用。实际诊断信息是:

1
2
api_token_configured: false
api_token_in_use: false

所有调用都返回 401 Authentication failed: API key required。

最要命的是:它连「会话结束时自动留档」也会失败。也就是说,这一整晚的对话一条都存不进去,而界面上没有任何报错 —— 它只是安静地什么都没做。

这正是我这个博客反复出现的那个主题:不报错 ≠ 生效。

坑 2:切到本地守护模式,它又要一个 LLM 密钥

我不想依赖云端账号,就切成了本地守护模式。文档说改个配置就行。

改完之后诊断信息确实变了:

1
api_url: http://127.0.0.1:9077    ← 切到本地了

但调用仍然失败 —— 本地根本没有进程在监听。

去翻插件源码才发现,启动守护进程前要过三道检查:

1
2
3
4
5
6
7
8
9
function preflightDaemon(cfg, harness) {
if (!hasUvx()) { /* 需要 uv */ }
if (!hasRustToolchain()) { /* 仅 macOS */ }
if (!detectLlm()) {
// "daemon mode needs an LLM for fact extraction —
// set OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY
// 或 HINDSIGHT_API_LLM_PROVIDER"
}
}

「本地」不等于「什么都不用配」。 本地守护进程同样需要一个 LLM 密钥 —— 因为「把对话变成记忆」这个动作本身就要调模型。

装上 uv、配上密钥之后,它接着要别的东西。

坑 3:还要下载两个模型 —— 被代理软件拦了

守护进程起来了,然后卡在读模型上:

1
2
3
ERROR: We couldn't connect to 'https://huggingface.co' to load the files,
and couldn't find them in the cached files.
SSL: CERTIFICATE_VERIFY_FAILED ... unable to get local issuer certificate

它要下两个模型:BAAI/bge-small-en-v1.5(向量)和 cross-encoder/ms-marco-MiniLM-L-6-v2(重排)。

本机开着 Clash。我做了个对比测试,结论很干净:

测试 结果
系统 Python → hf-mirror.com ✅ 200
系统 Python → huggingface.co ❌ 502
Node → 云端 API ✅ 200

代理把 huggingface.co 走了代理并替换了证书,Python 的 CA 包不认这张证书。 所以不是网络不通,是证书链对不上 —— 一个很容易误判成「Python 环境坏了」的现象。

坑 4:守护进程不读我注入的环境变量

解决办法本来很简单:让它改用国内镜像(HF_ENDPOINT=https://hf-mirror.com)。我试了两条路:

  1. 启动时设进程环境变量 —— 无效,它起的是分离进程
  2. 写进它自己的 profile 配置文件 —— 也无效,实测它不读

所以这个坑我修不了。 要修得去动代理规则(让那个域名走直连,或者把代理的 CA 加进 Python 的信任库),那是另一件事了。


转折:先退回云端

最后我在云端和本地之间选了云端(Node 直连完全可达,一次就通),把攒下来的 8 份知识文档写了进去,然后做了三层验证:

验证层 方法 结果
入库确认 拉取文档列表 8 份,ID 逐一吻合
语义检索 让它复述这个项目 准确说出技术栈、踩过的坑、域名状态
计数核对 数一遍 9 个文档 + 1 个会话留档,一个不多不少

能用。但我不打算长期用它。

因为它需要:一个云端账号和额度、一个 Python 环境(约 4.7 GB)、两个模型、一个嵌入式 PostgreSQL。

为了存 88 KB 的笔记,这不划算。


换成本地记忆库

后来我换了一个本地记忆插件。它和上面那个的根本区别:

云端记忆 本地记忆库
存储位置 云端 API 本机
需要 LLM ✅ 需要(抽取事实) ❌ 不需要
索引方式 服务端异步抽取 本地:文档摘要 + 代码符号表
依赖 账号 / Python 环境 / 模型 零
维护成本 要管账号和额度 零

它主要做两件事:

  1. 索引项目和代码 —— 文档切块存摘要,代码只提符号表(函数/类名 + 行号),全程零 token
  2. 存「洞察」,并且带触发条件 —— 这条最有意思

最有意思的设计:把注入当成「准入问题」,而不是「检索问题」

大多数记忆系统是检索式的:每一步都找出最相关的那条塞进上下文。

问题是排序是个全函数 —— 永远存在「最相关」,所以噪声是结构性的。用久了你会开始无视它,那这套记忆就白配了。

这个插件反过来:默认沉默,只有「这一步即将跨过我踩过坑的边界」才出声。

我写了 9 条洞察,每条带一个触发条件:

洞察 什么时候自动提醒
不报错 ≠ 生效 每次提交代码之前
PowerShell 脚本必须纯 ASCII(中文会被按 GBK 解码) 要写 tools/*.ps1 之前
改文章前先停 dev server(否则文件被锁) 提到「改文章」时
置顶用 sticky 不是 top 提到「置顶」时
部署是 Workers 不是 Pages 提到「部署」时
域名委派要查 TLD 注册局(托管商的 DoH 会自己回答自己) 提到「域名 / DNS」时

它不是「我搜到了什么」,而是「你马上要做的事,我拦一下」。


配置时的三个发现

1. 记忆库必须按项目隔离

我的工作目录下并列放着 7 个互不相关的项目 —— 这个博客只是其中之一。

如果直接拿整个工作目录当项目根,7 个项目会混进同一个记忆库,互相污染。

它的根目录解析顺序是:显式指定 → 登记的根 → 最近的 .git / package.json 祖先 → 会话工作目录。

所以正确做法是在项目目录里启动,或者显式指定根。我还在工作区根放了一条「路标」:提到这个博客时,它会告诉模型真正的库在哪。

2. 记忆工具对子代理是硬性禁用的(源码级)

我一开始想省事,让一个子代理去把文档写进记忆。结果 8 份全部失败,报同一句话。

子代理很争气,直接把源码行找出来了:

1
2
3
4
function workspaceForAgent(agent) {
if (agent.session.header.origin === "subagent") return void 0; // ← 就是这行
return workspaceFor(workspaceRoot(agent));
}

它在读取任何内容之前就返回了 —— 所以派子代理去写记忆,必然 0 成功,重试多少次都一样。

3. 构建产物被误索引了

插件有一份内置的忽略名单:node_modules、dist、build、target、coverage……

但它没有 public —— 而 public 正是 Hexo / Hugo / Jekyll 的默认产物目录。

结果 38 个被索引的文件里有 10 个是构建产物的副本(主题 JS 之类)。不影响使用,只是噪音。而且配置里没有「忽略目录」这一项,我自己排不掉。

如果你也在用它,值得给作者提一句:默认忽略名单加上 public。


我又一次验证了那句话

搭这个博客的时候,我总结过 28 个坑,其中大半是同一类:不报错但没生效。

这次折腾记忆,我第一个栽的坑还是它:

插件装好了、界面正常、没有任何报错,我以为它能用了。
实际上它一条都没存进去,连「会话结束时自动留档」都是失败的。

所以这次我坚持了三层验证:入库确认 → 语义检索 → 计数核对。

只跑通第一层(「调用没报错」)是不够的 —— 这个项目里已经栽过太多次了。


现在的效果

给这个博客配好记忆之后:

  • 索引了 38 个文件(16 份文档 + 22 个代码符号表)
  • 存了 9 条洞察,每条都能在对应场景自动拦一下
  • 后台 30 秒轮询,改了文件会静默增量重索引
  • 整个库 220 KB,纯本地,零依赖

下次开新会话,它已经知道这个博客的一切。 我不用再从头讲一遍了。


这是建站记录的第 5 篇。前面几篇讲了:不买服务器怎么有博客、Hexo 的 front-matter 和标签插件怎么用、以及这个博客搭起来踩过的 28 个坑。