开发记录:ChatterCatcher——我给家庭群做了个记忆机器人

npm:ChatterCatcher
适合:技术用户自部署 + 飞书/Lark 家庭群

写在前面

最近,飞书新增了很多和AI有关的能力,因此我决定把家庭群迁移到飞书上,不光是为了日后接入AI,也更方便我现在就进行开发。我们家的通知都是我妈转发的,体检时间、学校通知、取餐码、活动改期、各种文件和截图……但是他们最后全都混在几百条闲聊里。每次要找的时候,总得有人去翻聊天记录。

因此,我妈总是红温。

于是,ChatterCatcher 诞生了——一个本地优先证据驱动的飞书家庭群 RAG 记忆机器人。说人话就是:把它拉进群,它自动记下所有消息和文件,之后你 @ 它问「上次体检几点」,它不光回答你,还会告诉你「是谁在什么时候说的」。

而且他和OpenClaw这些不一样的是,他的上下文不是暴力堆叠的,省Token啊!

调研 & 需求文档

VibeCoding 第一步永远是把问题说清楚。我给自己列的:

  • 干什么:做一个飞书/Lark 家庭群的「记忆层」——群里正常聊天,机器人静默记下来,需要时 @ 它提问,它先从本地检索证据再回答。

  • 为什么:家庭群的重要信息不是以「文档」形式出现的,而是碎片化地散在聊天里。传统做法是人工翻,又慢又烦。市面上的聊天机器人大多是「万能 AI 助理」,但我不需要万能,我只需要它记住群里说过什么

  • 怎么做:飞书群发消息 → 本地 Gateway 接收 → 消息/文件/图片入库 → 切块 + 索引 → 用户 @ 机器人提问 → 混合检索本地证据 → LLM 基于证据生成回答 → 回复到群里。整个闭环跑在你自己机器上。

  • 技术栈:Node.js + TypeScript、SQLite(FTS5 + embedding 向量)、飞书 SDK、OpenAI-compatible LLM/Embedding。选 SQLite 而不是 LanceDB 之类的外部向量库,因为安装成功率比性能重要——我不想让用户卡在 npm install 就劝退了。

开发过程

这次我没有用那种全自动 /dev 的方式,而是把工具换成了Claude Code+GPT-5.5,然后用了superpowers这个插件,能够有brainstorm等明确的流程,并且会落成Sepc文档Plan文档。 通过最近最Superpower的使用,我也掌握了一些新的概念,如worktree

不得不说,Github拿来开发是真的方便啊,之前不会用branch啥的属实是我蠢了。

整个开发大概分了十几个阶段,挑几个有意思的说。

最纠结的决定:不用外部向量库

一开始用了 LanceDB,功能是跑通了,但这个服务最终是要部署在我爸的古老Intel芯片的Mac上的,而LanceDB没有原生的npm包在这个平台上。纠结了半天,决定把所有 embedding 向量直接存 SQLite,检索时在 Node.js 侧算余弦相似度。

确实没有专用向量库快,但家庭群又不是企业知识库,几千条消息完全够用。更关键的是——npm 全局安装一把过,不用看平台脸色。对 MVP 来说,这个选择是对的。

最惊险的 Bug:工具标记泄露出去了

有一次我发现机器人回复里出现了类似 <tool_call>...</tool_call> 的 XML。吓得我赶紧排查——原来有些 OpenAI-compatible provider 不会按标准 tool_calls 字段返回,而是把 DSML 伪工具调用直接塞进 content

如果你只检查标准字段,这坨内部标记就原样发到家庭群了。完全看不懂啊

修法是两层防线:第一层在模型适配层把 DSML 解析成内部 tool calls,第二层在飞书发送层兜底——检测到原始工具标记直接拦截。宁可这次回答失败,也别把内部实现细节糊到群里。

最绕的链路:图片记忆

家庭群里的图片不是保存就完了,用户后面可能会问:

  • 「那个取餐码是哪张?」
  • 「上次发的二维码图片叫什么?」
  • 「定时提醒的时候把那张图发出来」

所以我搞了一个链路:飞书下载图片 → 多模态模型描述图片 → 描述文本入库 → 强制保留文件名 → episode summary 也保留文件名 → 定时任务引用已入库文件名 → 发送时由代码解析到本地目录。

简单说就是:模型理解图片内容,人用文件名找回图片,系统守好安全边界。模型只能给文件名,不能给任意路径——这个边界我想了很久才定下来。

最容易被忽略的:时间

群里消息大量是「明天」「今晚」「下周」这种相对时间。如果你不处理,三天后机器人就会说「体检是明天」——用户一看日历,明天是周三,但体检明明是周六啊😮‍💨

所以我在 episode summary、RAG 检索、最终回答的每个 LLM 路径里都传入了当前时间,并且强制提醒模型:「请结合证据中的消息时间戳,推导出具体日期,不要照搬相对表达」。

这东西实现不复杂,但少了这一步,机器人的回答会非常搞笑。

其他值得一提的

  • 自动获取 bot open id:没配置的情况下不会误触发响应,减少手动填错的可能。
  • episode memory summary:家庭群聊天是碎片化的,单条消息经常语义不完整,所以按时间窗口把一段聊天整理成 episode summary 再参与检索。
  • 定时任务:群内自然语言创建提醒(「每天早上8点提醒我吃药」),支持发送已入库的图片。限制在当前群聊,不能跨群操作。
  • Web UI:本地看板,能看到 Gateway 状态、最近消息、QA logs、cron jobs。不花哨,但排障够用。
  • 导出/恢复:数据都在本地 SQLite,支持导出和恢复。

当前状态

截止 0.1.28,ChatterCatcher 已经是可用 MVP——安装、配置、接入飞书、沉淀消息、检索回答、引用来源、处理文件图片、定时提醒,完整闭环都跑通了。

但它不是一个「一键安装全家都能用」的消费级产品,目前更适合愿意自己部署的技术用户试用。

下一步不是继续堆功能,而是找真实家庭群场景来打磨:什么信息值得记、什么回答最有用、哪些错误最不能忍。

一句话总结:

ChatterCatcher 的价值不在于「又做了一个聊天机器人」,而在于把家庭群里分散、随口说出的重要信息,变成一个本地、可检索、可追溯、可以被提问的记忆系统

欢迎使用,如果你觉得好的话也麻烦给我点个Star:[ChatterCatcher Github仓库](GitHub - FlashingChen2024/chattercatcher · GitHub)


PS:如果你也觉得家庭群消息太难找了,欢迎试试 ChatterCatcher。撞到 Bug 直接提 Issue,我改!


开发记录:ChatterCatcher——我给家庭群做了个记忆机器人
https://blog.chenyuxia.com/archives/chattercatcher-dev-log
作者
老陈爱刷机
发布于
2026年05月16日
许可协议