Skip to content

缓存实验室

缓存实验室会告诉你提示词为什么未命中模型的缓存,并测量这件事在每一轮对话中让你付出了多少代价。

侧边栏位置: 缓存实验室(在协议观察台上方) 路由: /cache-lab加入版本: v0.6.0(2026 年 9 月) 需要: Ollama 0.33.3 或更新版本

这有什么意义?

本地模型不会在每一轮都重读你的整个提示词。它会保留一份已处理 token 的 KV 缓存并复用 —— 但只有在提示词从第一个 token 起仍然完全一致时才会复用。

「从第一个 token 起」就是全部关键。缓存依赖的是共享的前缀。一旦有一个 token 不同,它之后的所有内容都会被丢弃并重新计算,无论那部分有多么一模一样。

所以系统提示词顶部的一个时间戳,会让整段系统提示词在每一轮都重新计算。在真实的守护进程上、用同一个 324 token 的提示词实测:

时间戳的位置提示词 token从缓存复用预填充耗时
开头324464.6 ms
结尾32429018.6 ms

同样的模型。同样的文字。同样的 token 数量。预填充耗时相差 3.5 倍,差别只在于一个值放在了哪里。

这一点在其他工具中都看不到,而它是影响本地模型响应快慢的最大杠杆之一。

使用这个页面

  1. 选择一个模型。
  2. 粘贴你每一轮真正会发送的系统提示词。
  3. 点击测量

这个页面做三件事。

诊断

在测量之前,实验室会先扫描你的提示词,找出逐轮变化的值 —— 时间戳、日期、时间、会话 ID、长数字 —— 并以标签形式列出。

然后它会用三种颜色渲染你的提示词:

  • 绿色 —— 缓存可以保留的前缀。
  • 红色 —— 第一个发生变化的值。
  • 灰色 —— 仅仅因为排在那个值之后而全部失效的内容。

灰色区域才是重点。它通常占了提示词的绝大部分,而且那部分内容本身通常毫无问题。

测量

实验室会发送两种排布,每种各发送两次

  1. 你写的原始提示词。
  2. 同样的提示词,但把变化的值移到了末尾。

每种排布的第二次发送都带着不同的值 —— 新的时间戳、新的 ID —— 因为真实请求就是这样的。被测量的是第二次发送。测量第一次只能说明一个提示词和它自己有多匹配,而这对任何排布都接近 100%,什么也说明不了。

你会得到一张表格,显示守护进程实际保留了多少:提示词 token 数、复用数、实际计算数、预填充耗时,以及复用百分比。

结论

最后是一句直白的结论:改写每轮省下多少 token、省下多少毫秒,以及加速了多少倍。

页面上的每一个数字都来自你自己的守护进程。没有任何估算。

如何解读结果

复用接近 100% —— 这个排布表现很好,缓存承载了几乎整个提示词。

复用接近 0% 且有一个值在开头 —— 这是最常见、也最值得修的情况。把变化的值移到系统提示词的末尾,或者移到用户消息里,上方的主体部分就能保持在缓存中。

「未报告」 —— 你的守护进程早于 Ollama 0.33.3,不会报告缓存复用情况。实验室不会因此显示 0%,因为「守护进程没说」和「什么都没缓存」是两种不同的说法,而只有后者才是问题。

负的节省值 —— 改写让情况变差了。这是有可能的;既然是实测出来的,就相信实测,而不是相信理论。

该怎么办

解决办法几乎总是结构性的,而且几乎总是不花什么代价:

  • 把系统提示词中稳定的部分放在最前面:角色、规则、风格、示例。
  • 每轮都会变的内容放在最后:当前时间、用户 ID、会话 ID、检索到的片段。
  • 保持检索上下文的顺序稳定。 在两轮之间重新排序片段,会从第一个位置发生变化的片段开始让缓存失效。
  • 不要用一个会重新序列化字典的模板来拼接系统提示词 —— 键的顺序可能在你不知情时发生改变。

这些都不会改变告诉模型的内容,只会改变告诉它的位置,而这是免费的。

说明与限制

  • 实验室把生成限制为一个 token。它测量的是预填充,解码在这里只是噪音。
  • 它所测量的改写是机械的:把检测到的片段移到末尾,其余原封不动。这是一次测量,而不是推荐你直接采用的最终提示词 —— 采用前请自己读一遍。
  • 用于模拟「下一轮」的变异值只保留形状,不保留含义。日期可能变成一个不存在的日期。这没有关系:缓存只在意这个值变了,不在意它的含义。
  • 一切都在 localhost 上运行。无云端,无 API key,无需注册。

Released under the Apache 2.0 License.