缓存命中率99%!深挖Reasonix源码,吃透DeepSeek前缀缓存最佳实践
文章目录前言DeepSeek 的缓存机制一个无情的字符串比较器Reasonix 的记忆约束不动前缀动尾巴XML 拼接把变化赶到 prompt 的尾巴上协议层防 cache missDeepSeek 的 thinking 模式陷阱工程纪律命中率 99% 不是写出来的是管出来的第一缓存诊断第二CI 里的 cache-guard第三写进项目记忆的 PR 规则独立 session 历史双模型协作不打架请求结构上半段稳定下半段蹦迪写在最后P.S. 无意间发现了一个巨牛的人工智能教程非常通俗易懂对AI感兴趣的朋友强烈推荐去看看传送门https://blog.csdn.net/HHX_01前言我的项目默认接的是 DeepSeek。最近有个事特别闹心——DS 的缓存命中率低得离谱有时候只有 20% 到 30%。你们知道 DeepSeek 的 prefix caching 命中的部分价格有多便宜吗便宜到让我怀疑人生。但命中率这么低API 费用直接起飞。每个月账单看得我想把显卡卖了换硬币结果发现硬币更保值。我在 L 站、B 站 AI 区经常看到一个叫Reasonix的 agent harness 被吹爆。人家用 DS 跑缓存命中率一般能达到 99%。同样是用 DeepSeek为什么我的项目命中率这么拉这就好比你和学霸用同一支笔人家考满分你考及格。问题不在笔在你。于是我决定扒了它的源码。别问问就是开源精神——开源的代码就是我的代码。我抄代码的速度比抄作业还快。而且抄得理直气壮毕竟 LICENSE 都写着 MIT 呢。DeepSeek 的缓存机制一个无情的字符串比较器DeepSeek 的 prompt caching 是服务端自动的不用像 Anthropic 那样手动打cache_control标记。只要多次请求的 prompt 前缀完全一致命中部分就按缓存价计费。规则简单粗暴从 prompt 的第一个 token 开始逐个往下比。中间任何一个 token 不一样从这个位置起后面全部 miss。这就像你排队买奶茶前面 99 个人都一模一样第 100 个人突然要加珍珠。对不起从第 100 个人开始后面所有人重新排队。DeepSeek 的缓存策略本质上就是一个有强迫症的字符串比较器。它不在乎你后面变没变它只在乎前面有没有一个字不一样。这就像你女朋友问你刚才那句话什么意思你说没什么意思然后她就开始从第一句话逐字分析。DeepSeek 也是这个德行而且比女朋友还绝情——女朋友至少会给你解释的机会DeepSeek 直接 miss钱照扣。所以想让命中率高核心思路就一个让 prompt 的前缀部分在每一轮请求里纹丝不动有变化的部分全部塞到 prompt 的末尾去。听起来简单对吧但很多人直接把记忆更新、状态切换往 system prompt 里一塞缓存当场去世。这就像你装修房子为了换一盏灯把整栋楼拆了重建。物业都看傻了邻居都报警了DeepSeek 的账单直接把你送走。Reasonix 的记忆约束不动前缀动尾巴Reasonix 在项目记忆文件REASONIX.md里写着一条铁律Cache-first: the system-prompt prefix (base prompt tools memory) must stay byte-stable across turns so DeepSeek’s automatic prefix cache stays warm. Never mutate it mid-session.翻译成人话系统提示词前缀基础提示词 工具 记忆在多轮对话中必须保持字节级稳定确保 DeepSeek 的自动前缀缓存一直热着。中途千万别动它。这就像你家里的 WiFi 密码一旦设好了全家都别改。谁改谁负责重新教所有设备连网。我上次改了个密码我妈三天没理我智能音箱也不会说话了扫地机器人在客厅转了三圈找不到回家的路。看 Reasonix 的internal/boot/boot.go里的Build()函数前缀的组装顺序是这样的// boot.gosysPrompt,err:cfg.ResolveSystemPromptForRoot(root)// output style 折叠进 base prompt只组装一次进入 cache-stable prefixifst,ok:outputstyle.Resolve(cfg.Agent.OutputStyle,outputstyle.Dirs());ok{sysPromptoutputstyle.Apply(sysPrompt,st)}sysPrompt\n\nconfig.LanguagePolicy// 持久记忆在这里折叠进系统提示一次mem:memory.Load(memory.Options{CWD:root,UserDir:config.MemoryUserDir()})sysPromptmemory.Compose(sysPrompt,mem)// skill 只放索引名字描述正文按需加载不进 prefixskills:skillStore.List()if!tokenEconomy{sysPromptskill.ApplyIndex(sysPrompt,skills)}base prompt 放最前面这个正常来讲不会变。即使记忆跨 session 变了base prompt 仍然是一个合法的缓存前缀。skill 只塞名字和描述进前缀正文用到的时候才加载不进 prefix。这个应该是常识了但常识往往是最容易忘的。就像你知道要早睡但你依然在凌晨两点刷手机。常识和做到之间隔着一整个银河系还有我的黑眼圈。这个sysPrompt组装完之后传给agent.NewSession变成Session.Messages[0]。之后在这个 session 里它就不会再动了。工具 schema 也一样启动时注册进*tool.Registrysession 内不变。连 plan 模式这种功能切换都不改工具列表。进入 plan 模式不会从 schema 里删掉写工具而是在执行时进行拦截让模型看到错误自己适应。这就是细节啊。就像你进餐厅服务员不会为了让你减肥直接把菜单上的红烧肉涂掉而是等你点了之后告诉你“不好意思今天卖完了。” 模型一脸懵逼但缓存稳如老狗。DeepSeek 看着模型自己纠错内心 OS“这届 AI 挺自觉。”为了顺应开源精神我决定 OpenMMV 直接把这个方案给抄过来。抄代码不丢人抄了还说自己是原创才丢人。我抄得光明正大README 里还写了 “Inspired by Reasonix”——虽然 “Inspired” 这个词用在这里约等于 “CtrlC CtrlV”。XML 拼接把变化赶到 prompt 的尾巴上问题来了。如果用户在会话中途改了计划模式、临时加了条记忆模型必须知道这些变化吧肯定不能直接写进 system prompt不然前缀变了缓存命中直接 gg。这就像你正在直播突然换了个背景布观众全跑了。DeepSeek 的缓存比观众还绝情——观众跑了还能回来缓存 miss 了钱就没了。Reasonix 的解法是所有中途会变化的都作为 XML 块拼到当前 user 消息的最前面。源码在internal/control/input.go的Compose()里。这段代码我第一眼看到的时候脑子里只有一个念头这帮人是不是 XML 成精了// input.go —— Composefunc(c*Controller)Compose(textstring)string{plan:c.planMode notes:c.pendingMemory goal,goalStatus,goalResearchMode:c.goals.snapshot()// active goal 块拼在 user turn 前面ifstrings.TrimSpace(goal)!goalStatusGoalStatusRunning{textactiveGoalBlock(goal,goalResearchMode)\n\ntext}// plan mode 标记拼在 user turn 前面ifplan{textPlanModeMarker\n\ntext}// 推理语言块瞬时 user-turn 上下文textagent.WithReasoningLanguage(text,reasoningLanguage)// 中途加的记忆搭 turniflen(notes)0{varb strings.Builder b.WriteString(\n)b.WriteString(The following project-memory changes were just made and apply from now on:\n)for_,n:rangenotes{b.WriteString(- n\n)}b.WriteString(\n\n)textb.String()text}// 后台任务完成通知搭 turnifc.jobs!nil{ifnote:c.jobs.DrainCompletedNoteForSession(c.parentSessionID());note!{text\nnote\n\n\ntext}}returntext}这些、PlanModeMarker、、、块全部拼在最新 user 消息前面处于 prompt 的尾部。前缀部分是稳定的能命中缓存尾部是变化的。这就像你搬家不是把整栋楼推倒重建而是在门口贴个告示“新地址在隔壁请查收。” 快递小哥看了直呼内行。DeepSeek 看了也直呼内行“前缀没变好前面的我都知道了只看尾巴就行。”注释里写得很清楚Memory added mid-session rides the turn (never the cached system prefix), so it takes effect now without invalidating the prompt cache. It folds into the system prefix on the next session, where it costs nothing per turn.会话中途添加的记忆会附着在当前对话轮次中绝不触碰已缓存的系统前缀因此它不仅能立即生效还不会导致提示词缓存失效。在下一次全新的会话中它会被合并到系统前缀里届时由于缓存机制它在每一轮交互中都不会再产生额外成本。Reasonix 把会话状态和缓存前缀做了物理隔离。最新状态变化拼到 XML 里不会直接拼进 system prompt。这操作就像把垃圾扔到垃圾桶而不是扔到客厅——虽然都是扔但效果天差地别。我妈看了这段代码都说“这代码比我收拾房间还讲究。”协议层防 cache missDeepSeek 的 thinking 模式陷阱前面都是 harness 层的设计。在 provider 适配层Reasonix 还针对 DeepSeek 做了几个直接避免缓存失效和请求失败的处理。DeepSeek 的 thinking 模式有个巨坑当你要把历史里某条带工具调用的 AI 消息重新发给 DeepSeek 时必须把这条消息当初的思维链reasoning_content也一起发回去。不然 DeepSeek 直接返回 400。400 错误就像你女朋友说我没事——表面平静实则暴风雨前的宁静。DeepSeek 的 400 更直接直接告诉你“不行滚。” 连个解释的机会都不给比分手还干脆。Reasonix 在buildRequest里专门处理了// openai.go —— buildRequest// DeepSeek thinking mode 400s a tool_calls turn whose reasoning_content was// dropped on a cache-miss replay, so round it back — but only on the turn// that carries the tool calls.ifc.deepseekm.Roleprovider.RoleAssistantlen(m.ToolCalls)0{cm.ReasoningContentm.ReasoningContent}注意它只在带tool_calls的那一轮回传。这样既避免了 400又不把所有 reasoning 都塞回去——因为重新发送全部 reasoning 会有多余的花费。这就像你去饭店吃饭服务员不会因为你没点饮料就把你的筷子收走。细节决定成败也决定你的钱包厚度。多传一个 reasoning_content 可能就多花几毛钱积少成多一个月下来够买杯奶茶了。我算了算Reasonix 这个优化一年能省下的钱够我喝三百杯奶茶。三百杯这样看起来像是边边角角的逻辑判定其实就是缓存命中策略的细节。把这些容易踩坑的地方都填平了缓存命中率才会高上去。很多人写代码就像拼乐高只拼主体不拼边角。结果一碰就散架。Reasonix 是连说明书背面的小字都认真读了。我读代码的时候就在想这帮人是不是闲得慌后来发现闲得慌的人才能把缓存命中率做到 99%。工程纪律命中率 99% 不是写出来的是管出来的命中率要做到 99% 点几光代码里写好不够还得保证后续改动不退化。这一层是很多项目缺失的Reasonix 为此做了几个工程化的规矩。第一缓存诊断agent 的 run loop 里每一轮都取前缀快照跟上一轮对比把结果挂到 Usage 事件上。诊断信息里带了PrefixChanged、PrefixChangeReasons告诉你这一轮 miss 是因为 system 变了、工具变了、还是 log 被压缩重写了。Reasonix 让你能看到为什么这一轮 miss 了。因为看不见就管不住嘛。而且它用的是会话级的累计命中率不是单轮的比率。压缩时也不重置累计值所以压缩不会让显示的命中率突然暴跌。这就像你减肥每天称体重但只看趋势不看单日波动。某天多吃了一块蛋糕曲线不会断崖式下跌你也不会 panic 到把秤砸了。虽然我很想砸。第二CI 里的 cache-guard它有两个脚本。一个跑TestReleaseCacheHitGuard测试这是发版前缓存命中率不能退化的检测脚本。另一个脚本的作用是当一个 PR 改了缓存敏感文件比如internal/boot、internal/tool、internal/provider这些就强制要求 PR body 里写明Cache-impact:和Cache-guard:两行。值用n/a、none、todo这种敷衍词会被直接拒绝。这就像你公司的报销制度不写清楚用途直接打回。没人喜欢填表但大家都喜欢钱不被乱花。Reasonix 的 CI 比 HR 还严格敷衍它门都没有。我怀疑它的 CI 脚本是用 DeepSeek 写的因为 DeepSeek 也不接受敷衍。第三写进项目记忆的 PR 规则REASONIX.md把这套规范固化成对所有贡献者的约束。也就是说这个改动会不会影响 DeepSeek 缓存命中率是每个 PR 必须显式回答的问题。这就像你结婚前要签婚前协议——虽然麻烦但能避免以后扯皮。Reasonix 的缓存命中率能长期维持 99% 点几靠的不是某一行神代码而是这一整套工程纪律。代码可以抄但工程纪律抄不来。就像你可以抄学霸的笔记但抄不来学霸每天六点起床的习惯。我抄过真的抄不来。我六点起床的唯一原因是尿憋的。独立 session 历史双模型协作不打架Reasonix 支持双模型协作planner 计划 executor 执行。这是一个很容易缓存崩坏的场景。如果在同一个会话里切模型system、tools、历史的格式全变缓存直接清零。这就像你刚把冰箱温度调好有人把冰箱门拆了。你问谁拆的planner 和 executor 互相甩锅。最后发现是合租的锅而合租的锅永远甩不清。Reasonix 的做法是让 planner 和 executor 各自独立 session不共享历史。planner 用自己的 session 产出计划计划作为结构化文本交给 executorexecutor 在自己独立的 session 执行。The sessions never mix, so neither model’s prefix is disturbed by the other’s turns.各个会话完全独立所以两个模型的提示词前缀互不交织各自的对话轮次也不会互相打扰。不共享历史两个 session 各自的缓存前缀是稳定增长的。这就像合租最好的关系是各用各的卫生间。共用那只会带来灾难。我大学室友共用洗发水三个月后瓶子里的液体颜色都变了。到现在我都不知道那瓶子里到底是什么。Reasonix 显然吸取了教训各用各的 session各缓存各的谁也不打扰谁。请求结构上半段稳定下半段蹦迪把前面这几层串起来一次发给 DeepSeek 的请求prompt 大概是这个结构上半段是缓存命中区逐字节稳定整个 session 不变base prompt、output style、language、memory、skill 索引加上所有工具 schema再加上 append-only 增长的历史。下半段是缓存未命中区每轮新增只是尾部一小段那些、、、块加上 Plan mode 标记最后才是用户真正输入的文本。DeepSeek 从头匹配上面整块前缀和上一轮是一样的会大面积命中只有最底下这轮新拼的尾巴是 cache miss。这就像你去 KTV上半段是固定的歌单下半段是现场点歌。点歌的人换来换去但歌单本身不会变。除非有人把歌单撕了那缓存就真 miss 了。我有一次在 KTV 把歌单撕了不是因为缓存是因为有人点了《学猫叫》十遍。写在最后有时候我在想为什么 OpenMMV 的缓存命中率这么小。分析了一下因为 OpenMMV 的 AI 消息的 token 量太少了前缀本身就很小加之每轮的新增消息占比比较大缓存命中率自然不会太大。前缀占比越大命中率就越逼近 100%。Reasonix 的长会话里 system 加 tools 加历史可能有几万甚至几十万 token而尾巴那一小段只有几百到几千 token这样缓存命中率就比较大。这就像你请客吃饭请的人越多人均越便宜。缓存也是这个理——前缀越大尾巴的占比越小miss 的成本就越低。我请三个人吃饭人均 100请三十个人人均 30。DeepSeek 的缓存账单也是这个算法而且 DeepSeek 不会跟你 AA。高缓存命中率不是某一行代码的技巧而是从项目记忆到 CI 脚本一以贯之的工程纪律。如果你觉得这篇文章有帮助点赞关注点点赞~毕竟我扒源码的时候咖啡都喝了三杯。现在心跳比缓存命中率还高。如果这篇文章的缓存命中率也能到 99%那我下次写文就不用喝咖啡了——直接喝缓存命中率的喜悦。P.S. 无意间发现了一个巨牛的人工智能教程非常通俗易懂对AI感兴趣的朋友强烈推荐去看看传送门https://blog.csdn.net/HHX_01

相关新闻

Rive渲染器实战:解决跨平台高性能动画渲染难题

Rive渲染器实战:解决跨平台高性能动画渲染难题

Rive渲染器实战:解决跨平台高性能动画渲染难题 【免费下载链接】rive-renderer Low-level C Rive runtime and renderer 项目地址: https://gitcode.com/GitHub_Trending/ri/rive-renderer 在当今跨平台应用开发中,开发者面临一个核心挑战&#x…

2026/7/7 1:32:48阅读更多 →
基于SpringBoot+Vue3的海洋生态监测系统

基于SpringBoot+Vue3的海洋生态监测系统

一、项目介绍 1.1 项目背景 随着全球海洋生态环境问题日益突出,海洋污染、生物多样性下降、水质恶化等问题对海洋生态系统造成了严重威胁。传统的海洋生态监测工作依赖人工记录与纸质档案管理,存在数据采集效率低、信息共享困难、预警响应滞后等问题&…

2026/7/7 1:32:48阅读更多 →
从游戏存档到安装程序:Universal Extractor 2的完整文件解包工作流

从游戏存档到安装程序:Universal Extractor 2的完整文件解包工作流

从游戏存档到安装程序:Universal Extractor 2的完整文件解包工作流 【免费下载链接】UniExtract2 Universal Extractor 2 is a tool to extract files from any type of archive or installer. 项目地址: https://gitcode.com/gh_mirrors/un/UniExtract2 当你…

2026/7/7 1:27:48阅读更多 →
国产吉他品牌技术发展与市场格局分析

国产吉他品牌技术发展与市场格局分析

本文从技术参数、产业演进、市场格局三个维度,对国产吉他品牌的发展现状进行梳理分析。数据来源为公开行业资料及品牌官方参数,供行业从业者和消费者参考。一、产业背景:代工积累与技术外溢中国吉他制造业的规模化发展始于20世纪90年代。随着…

2026/7/7 2:42:55阅读更多 →
Universal x86 Tuning Utility:解锁电脑隐藏性能的终极指南

Universal x86 Tuning Utility:解锁电脑隐藏性能的终极指南

Universal x86 Tuning Utility:解锁电脑隐藏性能的终极指南 【免费下载链接】Universal-x86-Tuning-Utility Your Hardware. Your Rules. Open. Powerful. Unrestricted Tuning. 项目地址: https://gitcode.com/gh_mirrors/un/Universal-x86-Tuning-Utility …

2026/7/7 2:42:55阅读更多 →
新能源工程师培训哪家好?2026 光伏储能入行避坑深度解析

新能源工程师培训哪家好?2026 光伏储能入行避坑深度解析

近两年新能源行业迎来高速发展,户用光伏、工商业储能、分布式绿电、大型储能电站项目在全国遍地开花,市场对于持证新能源工程师的需求量持续暴涨,各大平台每天都有水电工、装修师傅、机房运维、应届毕业生提问新能源工程师培训哪家好&#xf…

2026/7/7 2:42:55阅读更多 →
百变互动-数字展厅沉浸式体验与视觉效果全解析

百变互动-数字展厅沉浸式体验与视觉效果全解析

在策划数字展厅项目时,我们常常陷入一个误区:过度关注屏幕的大小和数量,却忽视了内容本身的交互逻辑与呈现质感。很多数字展厅乍看之下科技感十足,但观众走马观花一圈后,留下的印象却寥寥无几。百变互动认为&#xff0…

2026/7/7 2:42:55阅读更多 →
竞争存在论:存在的投影法则——三连续统框架下的认知与本质

竞争存在论:存在的投影法则——三连续统框架下的认知与本质

存在的投影法则:三连续统框架下的认知与本质——从光子到暗物质的认识论转向摘要:基于竞争存在论的三连续统框架,本文提出“存在的投影法则”:任何一个纯粹维度的存在,都必须通过其“抑制项”——即它“不是”的那两个…

2026/7/7 2:42:55阅读更多 →
复杂遮挡环境轨迹还原技术,Trajectory Tensor张量推演在视频孪生中的应用

复杂遮挡环境轨迹还原技术,Trajectory Tensor张量推演在视频孪生中的应用

复杂遮挡环境轨迹还原技术,Trajectory Tensor张量推演在视频孪生中的应用一、技术总览本方案由镜像视界浙江科技有限公司联合镜像视界浙江普陀时空大数据应用技术联合研究院自主研发,纳入国家十四五时空感知重点课题攻关成果,经河南省电检院完…

2026/7/7 2:37:54阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/6 4:26:20阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/6 2:48:33阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/7 1:03:28阅读更多 →
Acunetix v24.8 深度解析:DAST漏洞扫描器核心原理与DevSecOps实践

Acunetix v24.8 深度解析:DAST漏洞扫描器核心原理与DevSecOps实践

1. 项目概述:Acunetix v24.8 高级版漏洞扫描器深度解析作为一名在网络安全领域摸爬滚打多年的老兵,我深知一款趁手的“兵器”对于安全测试工作意味着什么。今天要聊的,就是Web应用安全测试领域里一个响当当的名字——Acunetix。特别是其v24.8…

2026/7/7 0:02:41阅读更多 →
国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot)

国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot)

国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot) 🌐 演示地址:http://ruoyioffice.com | 📦 源码1GitHub:ruoyi-office | 📦 源码2GitCode:ruoyi-o…

2026/7/7 0:02:41阅读更多 →
CentOS 7/8 SSH 连接失败:5步系统性排错流程与决策树

CentOS 7/8 SSH 连接失败:5步系统性排错流程与决策树

CentOS SSH连接故障排查:从基础检查到深度修复的完整指南引言当你尝试通过Xshell或其他SSH客户端连接CentOS服务器时,突然遭遇"Connection refused"或"Connection timed out"的错误提示,这种经历对任何运维人员或开发者来…

2026/7/7 0:02:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/6 4:45:01阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/6 4:45:01阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/6 4:45:03阅读更多 →