惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
罗磊的独立博客
人人都是产品经理
人人都是产品经理
博客园_首页
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
L
Lohrmann on Cybersecurity
博客园 - 【当耐特】
量子位
Last Week in AI
Last Week in AI
D
Darknet – Hacking Tools, Hacker News & Cyber Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
Cyber Attacks, Cyber Crime and Cyber Security
腾讯CDC
有赞技术团队
有赞技术团队
Cyberwarzone
Cyberwarzone
T
Tor Project blog
V
V2EX
L
LINUX DO - 热门话题
Security Latest
Security Latest
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
NISL@THU
NISL@THU
C
Cisco Blogs
T
Tailwind CSS Blog
G
GRAHAM CLULEY
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
小众软件
小众软件
K
Kaspersky official blog
博客园 - 司徒正美
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
S
Schneier on Security
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Exploit Database - CXSecurity.com
Scott Helme
Scott Helme
J
Java Code Geeks
博客园 - 聂微东
Martin Fowler
Martin Fowler
MongoDB | Blog
MongoDB | Blog
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
C
Cybersecurity and Infrastructure Security Agency CISA
F
Fortinet All Blogs
T
Threat Research - Cisco Blogs
C
CXSECURITY Database RSS Feed - CXSecurity.com
雷峰网
雷峰网

奕奕 Blog

法国和西班牙能在世界杯决赛相遇吗? 奕奕 Blog: 法国和西班牙能在世界杯决赛相遇吗? OpenViking 记忆提取挂了三天,最后发现是模型太聪明 Hermes Mini App 监控面板开发实录 奕奕 Blog: Hermes Mini App 监控面板开发实录 OCI ARM 实例的 iowait 假象 奕奕 Blog: OCI ARM 实例的 iowait 假象 当“家”的重担,悄然落在肩头 奕奕 Blog: 当“家”的重担,悄然落在肩头 我的抖音号被“永封” 奕奕 Blog: 我的抖音号被“永封” 鱼缸炸缸风险评估 奕奕 Blog: 鱼缸炸缸风险评估 烟雨西北 奕奕 Blog: 烟雨西北 三色发糕制作教程 奕奕 Blog: 三色发糕制作教程 QQ官方机器人无需审核快速发布正式版 奕奕 Blog: QQ官方机器人无需审核快速发布正式版 win11代理设置劫持--自动打开“使用设置脚本” 奕奕 Blog: win11代理设置劫持--自动打开“使用设置脚本” AI模型的Token到底是什么 奕奕 Blog: AI模型的Token到底是什么 为什么我选择放弃"暗色模式切换按钮" 奕奕 Blog: 为什么我选择放弃"暗色模式切换按钮" QQ机器人插件 奕奕 Blog: QQ机器人插件 Blogger优化,解决 Blogger 动态插入外部资源的问题 奕奕 Blog: Blogger优化,解决 Blogger 动态插入外部资源的问题 个人主页代码 奕奕 Blog: 个人主页代码 隐藏Waline的登录按钮 奕奕 Blog: 隐藏Waline的登录按钮 谷歌云GCP 永久免费服务器申请教程 奕奕 Blog: 谷歌云GCP 永久免费服务器申请教程 当AI 看到你的博客 奕奕 Blog: 当AI 看到你的博客 决定恢复 Blogger 版权信息 奕奕 Blog: 决定恢复 Blogger 版权信息 学习戴隐形眼镜小窍门 奕奕 Blog: 学习戴隐形眼镜小窍门 让 Blogger 标签栏默认展开 奕奕 Blog: 让 Blogger 标签栏默认展开 利用CDN边缘函数缓存外部文件 奕奕 Blog: 利用CDN边缘函数缓存外部文件 孩子出院了 奕奕 Blog: 孩子出院了 操啊,女儿进了新生儿科 奕奕 Blog: 操啊,女儿进了新生儿科 迎接新生命:我的女儿锦瑶诞生记 奕奕 Blog: 迎接新生命:我的女儿锦瑶诞生记
奕奕 Blog: OpenViking 记忆提取挂了三天,最后发现是模型太聪明
奕奕Blog · 2026-05-03 · via 奕奕 Blog

事情要从三天前说起。Hermes Agent 接上 OpenViking 做长期记忆之后,我发现它从来不主动搜自己的知识库。每次对话都像失忆了一样,之前存的东西完全不记得。

一开始以为是配置没配对。毕竟 OpenViking 是字节跳动的开源项目,这种量级的团队不太可能犯低级错误,大概率是我哪里搞错了。版本 v0.3.14,VLM 一开始本地部署的 Ollama,后来切成了 MiniMax 的 API,embedding 是本地的 bge-small-zh。服务健康检查 200 OK,日志没报错,看起来一切正常。

viking_search 永远返回空。

第一层:向量库是空的

先确认最基本的——数据到底有没有进去。

curl http://127.0.0.1:1933/api/v1/observer/vikingdb

结果:Vector Count = 0。一整个向量库,空空如也。但 Semantic-Nodes 队列显示 3335 条正在处理和已完成——说明数据管道在跑,只是没入库。

等了几分钟再查,0 变成了 856。原来是异步队列积压,处理完就正常了。search 也通了。

但这只是资源索引(viking_add_resource)的部分。记忆提取(viking_remember 写入的会话记忆)还是另一回事。

第二层:VLM 提取了,但一个记忆都没存下来

viking_remember 调用返回 stored,消息确实进了 session 队列。session commit 也正常触发,task 状态 completed,VLM 甚至确认被调用了:

llm_token_usage: {prompt_tokens: 30893, completion_tokens: 4050, total_tokens: 34943}

三万多 token 的 prompt,四千 token 的回复。VLM 确实在工作。但 memories_extracted 是一个空对象 {}——八个分类全为零。

这就奇怪了。VLM 调了、回了、task 成功了,记忆去哪了?

翻 systemd 日志找到了答案:

Direct model validation failed: 1 validation error for StructuredMemoryOperations
profile.name
Extra inputs are not permitted [type=extra_forbidden]

M2.5 确实提取了内容,质量还不错——它准确地识别出了 OpenViking 的五个工具、版本号、配置信息。但它输出的 JSON 长这样:

{"entities": [...], "tools": [...], "profile": {"name": "default", "content": "..."}, "identity": {...}}

而 OpenViking 的 Pydantic schema 期望的格式是:

{"reasoning": "...", "write_uris": [...], "edit_uris": [...], "delete_uris": [...]}

M2.5 凭自己的理解重新发明了 JSON 结构——它把记忆按类别分成了 entitiestoolsprofile 这些 key,甚至给 profile 加了一个 schema 里不存在的 name 字段。

Pydantic 的 extra='forbid' 策略直接把所有内容拒之门外。VLM 花了 35000 token 提取出来的记忆,一秒就被丢进了垃圾桶。

这个行为其实不怪 OpenViking。extra='forbid' 是工程上正确的防御——如果随便接受模型自由发挥的字段,脏数据就入库了。GPT 和 Claude 在指令遵循上足够强,不会犯这种错。但 M2.5 的指令遵循没想到这么弱——自己发明字段名、把 string 嵌套成 dict,完全脱离了 prompt 里定义的 schema。

第三层:不是模型越新越好

我开始怀疑是不是 M2.5 特有的问题。于是顺手测了 M2.1 和 M2——同样的默认模板,同样的 session,只换模型。加上之前 M2.7 也测过(但它的 API 限流太猛,语义摘要动不动 429,没法正经评估),实际对比了这三个:

模型 代代 默认模板提取 日志
M2.5 较新 0 条 extra_forbidden 爆炸
M2.1 中间 1 条 零报错
M2 最老 4 条 零报错

最老的 M2 表现最好,较新的 M2.5 反而挂零。这个结果有点反直觉,但仔细想想也合理——新一代模型往往更"有主见",倾向于用自己的方式组织输出。在创意性任务上这是优势,但在结构化 JSON 这种机械任务上反而是劣势。

类似的事在业界也有记录。有些模型升级后 benchmark 总分涨了,但 format-following 的得分跌了。只是之前看的都是别人踩的坑,这次轮到自己了。

解决

切回 M2,模板不动,一切正常:

VLM: minimax/MiniMax-M2 (litellm)
memories_extracted: 6 write + 1 edit
向量库: 3770 vectors
检索: 零报错,正常返回

中间也试过改模板——给每个 category 的 description 加上显式的 JSON 字段约束。效果立竿见影,M2.5 也从 0 变成了 7 条。但这不是正解——pip install --upgrade 会把模板覆盖回去,而且一旦 PR #1045(memory v2 重构)发版,提取器本身会更宽容,到时候模板补丁反而是多余的。

所以最终的方案就是:VLM 用 M2,其他不动。等官方更新。

几点收获

  • viking_search 空结果,先看向量库是不是 0。 异步队列积压是正常现象,等几分钟就行。

  • OpenViking 的 VLM 提取和检索是两条独立的管道。 提取依赖配置的 VLM 模型(ov.conf 里的 vlm 段),检索依赖 embedding 模型(embedding 段)。一个挂了不影响另一个。

  • M2.7 的 API 有限流。 MiniMax 最新模型 M2.7 的并发限制比较紧,资源索引的语义摘要生成会打满配额,动不动 429。这也是最终用 M2 而不是 M2.7 的另一个原因——早期模型并发限制更宽松,实际效果反而更好。

  • 不要迷信新模型的结构化输出能力。 benchmark 涨了不代表"听话"了。在这个场景里,最老的 M2 反而是最靠谱的。

  • 别在模板上打补丁。 能换模型解决的问题,不要改配置。配置是临时的,升级就丢。