丘丘
多模态长记忆桌宠
跟一个 AI 聊完一轮,关掉再打开,它什么都不记得——这不是模型的问题,是上下文窗口一关就没了。市面上的「记忆」多半是把聊天记录整段塞回提示词,塞到装不下为止。
丘丘是一只常驻 macOS 桌面的 AI 桌宠,底下压着一层长期记忆中间件:每一轮对话拆成一条条事实存下来,下一次提问先去捞。整条链路是敞开的——记了什么、没记什么、这次答案参考了哪几条,全在界面上。
不记的那一半更重要
「我下周五去上海出差」会被拆成事实写进去。「嗯……那个……我看看啊」不会。
压缩这一步抽不出事实的句子,整句进丢弃列表,这一轮不写库。界面上照样给你看:那条管线走到「新颖度过滤」就熄了,右栏标着「冗余,丢掉」。
一个只会往里塞的记忆系统,用一周就被废话淹了。所以能看见它拒绝了什么,比看见它记住了什么更能建立信任。
三路并行检索,热冷两层
召回同时走三条:按意思(向量)、按字面(BM25)、按标签(实体)。三路取并集去重,再按 token 预算截断——先给摘要,不够再展开,预算内为止。
存储分热冷两层:热的常驻随时可取,冷的归档、按需回热。向量库用 LanceDB(Rust 原生,不用起服务),事实和会话在 SQLite。
删一条记忆只是让它失效,历史行不删除——记忆系统最怕的就是「它到底为什么这么答」查不回去。
画面上亮的每一格都来自后端事件
顶上那条管线不是动画脚本。前端只订阅后端发的事件流,哪一段发生了哪一段才亮,没发生的不亮。同一轮的每一步挂在同一个 trace id 上,右栏能逐条展开。
这是刻意立的一条约束(契约 AD-14):可见性的唯一来源是事件。否则演示时好看,真出问题时界面照样一片祥和。
表情不经过模型
32 个表情,两个方向都跟模型断开:发出去的 prompt 里没有任何表情信息,模型也没有输出表情标记的口子,它写的括号旁白在后端就滤掉了。
回复全文回来之后,由本地两张规则表(关键词 + 记忆事件)判出该演哪个表情。这样模型换一家、换个版本,脸上的调度不会跟着飘。
还有
端到端实时语音通话(说话时可以打断)、发图片走 Vision 转描述再进记忆、人格四个滑块加相处久了自己沉淀的习惯、鼠标穿透的桌宠窗口和跟着光标转的眼睛。
工程上是契约先行:docs/CONTRACTS.md 里的约定由测试直接解析校验,改了契约不改实现,测试会红。
在线 demo 跑在 Render 免费实例上,15 分钟没人访问会休眠,冷启动约 50 秒——仓库里挂了一条 GitHub Actions 每 5 分钟敲一次健康检查,正常情况下点开是热的。



- 上线
- 2026
- 我的角色
- 独立开发
- 技术栈
- ElectronReactTypeScriptFastAPILanceDBSQLiteDeepSeek豆包实时语音