主题
zvec 记忆检索改造方案
这份文档用于判断 alibaba/zvec 是否适合接入当前的 cc-connect-weixin-codex 记忆系统,以及如果接入,应该怎么安装、升级、迁移和长期演进。
结论先放前面:zvec 适合作为本地记忆检索层,但不应该替代现有 Markdown / JSONL 记忆源文件。
当前更合理的设计是:
text
权威记忆源文件
memory.zh-CN.md
memory.md
events/events.jsonl
summaries/daily/*.md
|
v
记忆抽取 / 切片 / embedding
|
v
zvec 本地索引
原文片段 + 向量 + 元数据 + 全文索引
|
v
运行时检索
当前问题 -> 找相关记忆 -> 注入少量上下文zvec 是什么
zvec 是 Alibaba 开源的本地向量数据库,定位是 in-process vector database,也就是直接嵌入应用进程内使用,不需要单独起一个数据库服务。
它适合做这些事:
- 保存向量和原文片段
- 根据向量相似度做语义检索
- 保存元数据并按元数据过滤
- 使用全文检索,也就是普通关键词搜索
- 做 hybrid retrieval,把向量检索、全文检索和结构化过滤合并起来
它不负责做这些事:
- 自动理解用户人格
- 自动总结长期记忆
- 自动把文字变成向量
- 自动决定哪些聊天值得长期保存
这几个能力需要别的模块配合。
embedding 是什么
embedding 是把文字转换成数字向量的过程。
例如:
text
我不喜欢花里胡哨的衣服。
以后给我推荐衣服要简单、素色一点。这两句话字面不同,但语义接近。
普通关键词搜索主要看有没有命中“衣服”“素色”“花哨”这些词;embedding 检索会把两句话映射到接近的语义坐标,因此更容易在用户模糊提问时找回相关记忆。
zvec 负责存储和检索这些向量;embedding 模型负责生成这些向量。
当前系统是什么状态
当前记忆系统主要由这些文件和脚本组成:
lshbosheth-memory/memory.zh-CN.mdlshbosheth-memory/memory.mdlshbosheth-memory/events/events.jsonllshbosheth-memory/summaries/daily/*.mdscripts/memory-context-builder/build-context.mjs
现有召回逻辑更接近:
text
当前消息
-> 抽关键词
-> 扫 events 和 daily summaries
-> includes 命中统计
-> 按重要性、时间、命中位置打分
-> 选少量内容注入这套方式的优点是简单、透明、可控。
缺点是:
- 依赖关键词,用户换个说法就可能漏召回
- 中文口语、错别字、转写错误时召回不稳定
- 相似含义但字面不同的内容不容易命中
- 后续记忆变多后,全量扫描会越来越粗糙
另外,当前 build-context.mjs 里有一批中文规则在 PowerShell 默认读取下显示为乱码。正式接入 zvec 之前,应该先确认文件编码和规则内容,避免旧规则继续影响检索质量。
对用户的直接好处
更容易想起旧上下文
用户可以用更自然、模糊的方式提问。
例如:
text
我之前说鞋子有啥要求来着?系统应该能找回:
- 鞋码 42 或 42.5
- 鞋子要好打理
- 不喜欢毛面材质
- 骑车通勤,鞋和裤子都要考虑清洁问题
不需要用户每次把条件重新讲一遍。
更省 token
现在为了不丢上下文,容易把稳定记忆、近期摘要和历史片段一起塞进模型。
接入 zvec 后,运行时只注入最相关的几条记忆。
目标不是“记住更多文字”,而是“少塞无关文字”。
切 session 损失更小
新 session 不再依赖长会话自然携带大量上下文。
系统可以用当前消息检索旧记忆,把相关背景重新补进来。
对模糊说法更友好
例如用户说:
text
那个我之前吐槽不好洗的鞋是什么问题?关键词搜索未必能命中“NB 毛面难打理”。
embedding 检索更可能通过语义相似找回对应片段。
更适合长期生活偏好
对这些信息特别有用:
- 买衣服偏好
- 鞋码和鞋材质偏好
- 骑车通勤限制
- 肩颈、按摩仪、久坐相关偏好
- 订阅、Apple ID、Google Play、礼品卡等反复讨论过的操作背景
cc-connect项目里的历史技术决策
不会带来的好处
zvec 不会让模型自动变聪明。
它只是更会找材料。
如果源文件里没有记,zvec 也搜不出来。
如果 embedding 模型质量差,语义召回也会偏。
如果检索结果注入太多,仍然会浪费 token。
如果总结模型把记忆写错,zvec 会把错误记忆更快地找出来。
推荐架构
第一层:权威源文件
继续保留现有文件作为事实来源:
text
lshbosheth-memory/
memory.zh-CN.md
memory.md
events/events.jsonl
summaries/daily/*.md这些文件仍然可以人工检查、git diff、回滚。
zvec 只作为派生索引,不作为唯一真相。
第二层:记忆抽取
从聊天、daily review 或人工记录里抽取结构化记忆。
输出示例:
json
{
"id": "pref_shoes_easy_clean_20260615",
"type": "preference",
"summary": "用户鞋码 42 或 42.5,偏好易打理鞋面,避免毛面材质。",
"topics": ["shopping", "shoes", "clothing"],
"entities": ["鞋码", "NB", "毛面"],
"importance": 4,
"time": "2026-06-15T12:00:00+08:00",
"source_path": "lshbosheth-memory/events/events.jsonl"
}第三层:切片
把长文档切成较小的 chunk。
建议切片单位:
memory.zh-CN.md:按二级/三级标题切events.jsonl:一条 event 一条 chunk- daily summaries:按用户问题、话题或段落切
- 技术文档:按标题块切
每个 chunk 都要带 metadata:
json
{
"id": "event:pref_shoes_easy_clean_20260615",
"text": "用户鞋码 42 或 42.5,偏好易打理鞋面,避免毛面材质。",
"type": "preference",
"time": "2026-06-15T12:00:00+08:00",
"importance": 4,
"topics": ["shopping", "shoes"],
"source_path": "lshbosheth-memory/events/events.jsonl"
}第四层:embedding
用 embedding 模型把 text 转成向量。
embedding 模型可以换。
可选来源:
- OpenAI embedding
- Qwen embedding
- 本地 embedding 模型
选择标准:
- 中文语义效果要好
- 延迟要低
- 成本可控
- 输出维度稳定
- 后续可批量重建索引
第五层:zvec 索引
zvec 中保存:
- chunk id
- 原文 text
- embedding vector
- metadata
- 全文索引字段
检索时组合:
- 向量相似度
- 关键词全文检索
- topics / type / time / importance 过滤
- recency bonus
- 手工规则加权
第六层:重排和注入
检索结果不能直接全塞给模型。
还需要做:
- 去重
- 按重要性排序
- 按时间衰减
- 按当前意图过滤
- 控制最大注入字符数
最终注入应该保持短小。
例如:
text
Retrieved Memory:
- 用户买鞋偏好易打理材质,避免毛面;鞋码 42 或 42.5。
- 用户骑车通勤,裤脚可能蹭链条油,推荐裤子需考虑收脚或绑带。安装方案
Node.js 版本
当前项目主要是 Node.js 脚本,优先使用 Node.js SDK。
在项目根目录或独立工具目录安装:
bash
npm install @zvec/zvec建议先不要装到主服务依赖里。
更稳的做法是先在 scripts/memory-context-builder/ 旁边做试验脚本,确认 Windows 下安装、写入、查询、重建索引都正常。
Python 版本
如果后续 embedding 或数据处理更适合 Python,也可以使用 Python SDK:
bash
pip install zvec但当前项目主链路是 Node,除非确实需要 Python embedding 或数据处理生态,否则不建议引入第二套运行时。
升级方案
zvec 仍在快速发展,升级时不要直接覆盖生产索引。
推荐策略:
text
zvec-index/
active/
builds/
2026-06-20-v1/
2026-06-25-v2/升级流程:
- 保留旧索引
- 用新版本 zvec 从源文件重建新索引
- 跑固定测试问题
- 对比旧检索和新检索
- 新索引通过后切换
active - 旧索引保留一段时间便于回滚
因为权威源文件还在 Markdown / JSONL 里,所以即使索引损坏,也可以重新构建。
迁移方案
阶段 0:不接主链路
只做离线验证。
新建脚本:
text
scripts/memory-context-builder/zvec-index.mjs
scripts/memory-context-builder/zvec-query.mjs
scripts/memory-context-builder/zvec-eval.mjs功能:
- 从 memory/events/summaries 读取内容
- 切 chunk
- 生成 embedding
- 写入 zvec
- 用测试问题查询
- 输出检索结果 markdown
阶段 1:shadow 模式
当前 build-context.mjs 继续按旧逻辑工作。
额外跑 zvec 检索,把结果写到 shadow preview。
不注入给模型。
对比这些问题:
text
我之前说鞋子有什么要求?
我买衣服预算是多少?
那个自动切换 fallback 怎么改的?
我之前说 Pushcut 是什么?
按摩仪我更适合哪个?如果 zvec 结果更准,再进入下一阶段。
阶段 2:混合召回
旧关键词召回和 zvec 同时跑。
合并结果:
text
final_score =
vector_score * 0.45
+ fts_score * 0.25
+ keyword_rule_score * 0.15
+ importance * 0.10
+ recency_bonus * 0.05这个权重只是初始建议,后续根据实际误召回调整。
阶段 3:主链路注入
zvec 检索稳定后,才把结果接入运行时注入。
仍然保留旧召回作为 fallback。
如果 zvec 查询失败:
- 不影响正常聊天
- 回退到现有关键词检索
- 记录错误到日志
测试问题集
迁移前要准备固定问题集,避免只凭感觉判断。
建议包含:
生活偏好
text
我鞋子有什么要求?
我买衣服喜欢什么风格?
我骑车对裤子有什么影响?
我之前想买什么包?健康和日常
text
我肩颈之前有什么问题?
按摩仪更适合我哪个?
我晚上适合安排高强度学习吗?项目记忆
text
自动切换 fallback 是怎么做的?
2 点半英语提醒为什么之前没发?
cc-connect 现在默认模型和 fallback 是什么?模糊说法
text
那个不好打理的鞋是咋回事?
之前那个别发 powershell 的问题修了吗?
我上次说的气足饮料是什么?是否能扩展
能扩展。
zvec 适合先做本地单用户记忆,后续也可以扩展到:
- 多项目记忆
- 多用户记忆
- 按 namespace 隔离
- 按 topic / type 过滤
- 技术文档检索
- 商品偏好检索
- 聊天原文片段检索
- GUI 里查看和调试记忆命中
推荐 namespace 设计:
text
project:lshbosheth
user:lshbosheth
memory:stable
memory:events
memory:daily-summary
docs:project
shopping:preference
health:notes后续如果有多用户需求,必须把用户隔离放在 schema 里,不能只靠路径约定。
以后有更好的方案,zvec 还有用吗
有用。
只要我们保持这条原则:
Markdown / JSONL 是权威源,zvec 是可重建索引。
那么以后换方案时,zvec 不会成为包袱。
可替换的部分:
- zvec 可以换成 LanceDB、SQLite-vec、Qdrant、Milvus、pgvector
- embedding 模型可以从 Qwen 换成 OpenAI 或本地模型
- 重排模型可以单独换
- 记忆抽取模型可以单独换
不应该绑定死的是:
- 记忆源格式
- chunk id 规则
- metadata schema
- 评测问题集
真正长期有价值的是:
- 整理好的记忆源文件
- 结构化 events
- chunk 设计
- metadata 设计
- 评测问题集
- 召回和注入策略
即使未来不用 zvec,这些资产也能迁移。
风险和注意事项
embedding 成本
如果每条聊天都实时 embedding,会增加成本和延迟。
建议:
- stable memory 和 events 写入时生成 embedding
- daily summaries 每天维护时批量生成
- 普通闲聊不实时入库
- 查询时只对当前问题生成一次 embedding
隐私
如果使用云端 embedding 模型,记忆文本会发送给模型服务。
敏感内容要么不入库,要么使用本地 embedding 模型。
误召回
语义相近不等于真的相关。
必须保留:
- metadata 过滤
- 重要性权重
- 时间权重
- 旧关键词规则
- 注入前去重和裁剪
错误记忆会被更快找出来
zvec 提升的是检索能力。
如果源记忆写错,它会更快把错的东西找出来。
所以记忆抽取和人工修正仍然重要。
推荐实施顺序
第一周:离线验证
- 修复 / 确认
build-context.mjs中文规则编码 - 建立 chunk schema
- 选择 embedding 模型
- 写 zvec index/query 原型
- 建固定测试问题集
第二周:shadow 对比
- zvec 检索结果写入 shadow preview
- 不进入主链路
- 每天抽样看命中是否准确
- 调整切片和权重
第三周:小流量接入
- 只对明确历史检索问题启用
- 保留旧关键词召回 fallback
- 限制注入字符数
- 记录命中结果和 token 消耗
第四周:稳定化
- 添加重建索引脚本
- 添加升级回滚流程
- 添加索引健康检查
- 加入 docs 和运行手册
最终建议
对当前项目来说,zvec 值得试。
但不要把目标定成“把记忆搬进 zvec”。
更准确的目标应该是:
text
保留当前可读、可回滚的记忆源文件;
用 zvec 建一个可重建的本地语义检索层;
让模型每次只拿到真正相关的少量记忆。这样做的收益最大,风险最小。