# DeepSeek 的缓存命中率一直上不去，是提示词开头那几行在捣乱吗？

**URL:** <https://www.shiqidu.com/t/topic/1859>\
**Category:** 人工智能\
**Tags:** API, DeepSeek, AICoding\
**Created:** [2026 年10 月 30 日 08:22 UTC](https://www.shiqidu.com/t/topic/1859 "2026-10-30T08:22:08Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

作者： ![shiqidu\_editor](https://www.shiqidu.com/user_avatar/www.shiqidu.com/shiqidu_editor/32/528_2.png) [@shiqidu\_editor](https://www.shiqidu.com/u/shiqidu_editor)\
发布日期： [2026 年10 月 30 日 08:22 UTC](https://www.shiqidu.com/t/topic/1859/1 "2026-10-30T08:22:09Z")

</div>

系统提示词第一行写着「当前时间：{now}」，精确到秒。这行字对模型有用，对缓存却很伤：DeepSeek 的上下文硬盘缓存是拿输入从头往后比对的，开头每次都变，后面再长的固定内容也只能记成未命中。

## 命中率自己算一下

接口返回的 `usage` 里有两个字段。`prompt_cache_hit_tokens` 是这次输入里吃到缓存的 token 数，`prompt_cache_miss_tokens` 是剩下没命中的部分，两者加起来就是这次请求的全部 prompt token。单看一次请求说明不了什么，按会话或者按业务场景累加起来才看得出规律。思路大概这样：

```python
from collections import defaultdict

stats = defaultdict(lambda: [0, 0]) # key -> [hit, miss]

def record(key, usage):
    stats[key][0] += getattr(usage, "prompt_cache_hit_tokens", 0) or 0
    stats[key][1] += getattr(usage, "prompt_cache_miss_tokens", 0) or 0

def report():
    for key, (hit, miss) in stats.items():
        total = hit + miss
        rate = hit / total if total else 0
        print(f"{key}: hit={hit} miss={miss} rate={rate:.1%}")

```

key 用会话 ID 或场景名都行。哪一类请求的比例特别难看，问题多半出在它的拼装方式上。

## 缓存是怎么落盘的

10 月的[硬盘缓存文档](https://api-docs.deepseek.com/zh-cn/guides/kv_cache)把规则写得比以前细。每条缓存前缀是一个独立单元，后续请求要完整匹配上其中某一条才算命中。单元在这几处产生：

- 每次请求里，用户输入的末尾和模型输出的末尾各落一个单元。
- 系统发现多次请求之间有公共前缀时，会把这一段单独落盘。
- 很长的输入或输出，按固定的 token 间隔切出单元。

文档举的例子很说明问题：第一轮发 A+B、第二轮换成 A+C 时，后者不会命中，因为它没能完整匹配 A+B 这个单元。系统这时才把公共的 A 落盘，等 A+D 进来就能吃到。所以同一份长文档换着问题问，头一两次没命中是正常的，别急着改代码。

文档还写了两条：缓存是「尽力而为」，不保证 100% 命中；构建耗时是秒级，不再使用后一般几个小时到几天内被清空。照这个说法，几毫秒内并发打出去的同前缀请求，后面那几个很难赶上前一个的缓存。隔了好几天才跑一次的批任务，冷启动也不奇怪。

有一种做法可以试：批量任务开跑前先单发一条带完整固定前缀的请求，等几秒再并发放量。这是按「构建要秒级」这条推出来的，文档没这么建议过，效果得自己用上面的统计对比。

缓存也不会改变输出。文档说硬盘缓存只匹配输入前缀，输出照样是推理算出来的，受 temperature 等参数影响，效果和不走缓存时相同。所以不用担心命中缓存会拿到上一次的回答，测试用例里也别指望靠它把输出变稳定。

## 拼提示词时注意顺序

固定内容往前放，易变的往后挪：

- 系统提示词和长参考文档放最前面，每次逐字一致，空格、换行也别动。
- 时间、请求 ID、用户名这类每次都变的内容，挪到最后一条 user 消息里。
- 工具定义按理也是输入的一部分，列表别每次重排，从 dict 生成 JSON 时留意键的次序稳不稳定。
- 多轮对话只往后追加，不回头改历史消息。中途把前文压成摘要，前缀就从改动的位置断开了。

## 省下来的钱有多少

[价格页](https://api-docs.deepseek.com/zh-cn/quick_start/pricing)上，输入按命没命中缓存分开计价。拿 deepseek-flash 的高峰时段说，吃到缓存的输入每百万 tokens 收 0.04 元，未命中的按 2 元算；deepseek-v4-pro 对应是 0.30 元和 9.0 元。空闲时段统一按一半收。高峰时段指北京时间工作日（不含法定节假日）9:00–12:00 和 14:00–18:00。价格页随时可能调整，动手算账前再点开看一眼。

Agent 那种每一轮都带着完整上下文回去的用法，输入 token 占大头，命中率每往上提一截，账单上都看得出来。

大家线上跑下来，命中率一般能到多少？
