理解 KVC 哈希命名:DwarfStar 如何用 SHA1 前缀命中复用检查点
【免费下载链接】ds4DeepSeek 4 Flash and PRO local inference engine for Metal, CUDA and ROCm项目地址: https://gitcode.com/GitHub_Trending/ds4/ds4
DwarfStar(ds4)是一款面向 DeepSeek 4 Flash 与 PRO 的本地推理引擎,支持 Metal、CUDA 和 ROCm。这篇指南带你理解它的 KVC 磁盘缓存:检查点文件名由提示词字节前缀的 SHA1 哈希生成,命中即跳过重复 prefill,长会话与换回旧会话都能秒级恢复。
为什么检查点文件名是一个 40 位十六进制哈希
KVC 缓存文件遵循一个非常简单的命名规则:文件名 = 40 位 SHA1 十六进制摘要 +.kv后缀,总长 43 个字符。目录扫描时会直接校验这个形状,不符合的文件一律忽略(见 ds4_kvstore.c):
| 命名成分 | 内容 | 作用 |
|---|---|---|
| 前 40 个字符 | SHA1 摘要的十六进制 | 唯一定位一个检查点 |
| 后 3 个字符 | 固定后缀.kv | 区分缓存文件与其他文件 |
SHA1 摘要由 ds4_kvstore_sha1_bytes_hex 统一计算,服务端还内置了经典测试向量:sha1("abc")必须等于a9993e364706816aba3e25717850c26c9cd0d89d,保证摘要算法在任何平台编译后行为一致(见 ds4_server.c)。
为什么哈希字节前缀,而不是 token 序列
这是整套机制最关键的设计决策。源码注释写得很直白:文件名是缓存文本字节的 SHA1,而不是 token 序列的 SHA1(ds4_server.c)。
原因是:token 序列只有引擎自己读得懂,而客户端(CLI、HTTP 客户端、agent)重启后能复现的只有"渲染出来的文本"。用渲染文本的字节前缀做键,检查点在进程重启、会话切换后依然可以被再次命中——文件里的 KV 数据、token 数等元信息仍然由文件头承载,文件名只负责"选对检查点"。
一次 KVC 命中是如何发生的:SHA1 前缀校验三步走
缓存查找入口是 ds4_kvstore_find_text_prefix,整个流程可以概括为"输入 → 校验 → 命中"三段管道:
第一步:枚举候选。扫描缓存目录下所有合法的 43 位哈希文件名,逐条读文件头,先做廉价过滤:文本长度、最小 token 数(默认 512)、模型 ID、量化位宽(2/4)、上下文尺寸,任何一项不匹配直接跳过。
第二步:SHA1 前缀比对。对新提示词取"前 N 字节"再算 SHA1(N 为该候选检查点保存的文本长度),与文件名里的 40 位摘要逐字符比较。如果新提示词恰好从某个旧检查点继续生长,这里就能命中——这正是"前缀命中"的含义:不要求整段相等,只要求候选文本是新提示词的字节前缀。
第三步:落盘自检。真正加载时还会把文件里保存的文本重新算一次 SHA1,与文件名摘要核对,再做逐字节前缀匹配(ds4_kvstore.c)。任何一步失败——"cached text hash mismatch"、"cached text prefix mismatch"——该检查点会被标记无效甚至直接删除,绝不会拿错状态的 KV 去恢复会话。
写入侧同样讲究:新文件先写成<名称>.tmp.<pid>临时文件,全部落盘后再原子改名为最终哈希文件名,避免半截文件污染缓存目录(ds4_kvstore.c)。
三类命名策略:自动缓存、继续点与 Agent 会话
服务端自动缓存:前缀对齐 2048 token
服务端在冷提示词 prefill 到达"稳定边界"时保存检查点。默认会裁剪尾部 32 个 token 并对齐到 2048 token 边界(ds4_kvstore.c),这与后端 prefill 分块调度一致,保证压缩器行收尾与冷启动全量 prefill 完全相同。
继续点与锚点:淘汰时谁先走
磁盘超预算时按评分淘汰:命中数带半衰期衰减,cold / evict / shutdown 这类"锚点"检查点得分 ×2(ds4_kvstore.c)。判断一个新检查点是否覆盖某个旧的"continued"继续点,用的还是 SHA1 前缀技巧——取新文本的前旧长度字节算摘要,与旧文件名比对(ds4_kvstore.c)。
Agent 会话:SHA1(标题 ‖ 创建时间) 的稳定身份
ds4-agent的会话命名策略不同:会话 ID 取SHA1(title || created_at_le64)(ds4_agent.c)。标题取第一条用户消息,创建时间在多次保存间保持不变——因此反复保存同一会话时文件名稳定,而文件内的转录和 KV 载荷持续演化。系统提示词则固定存放在sysprompt.kv,因名称固定,加载前会比较文件内保存的文本是否一致,不一致就重建覆盖。
上手实践:查看、恢复与清理 KVC 检查点
会话文件统一存放在~/.ds4/kvcache(README.md)。在ds4-agent交互界面里,文件名中的哈希前缀就是会话句柄:
| 命令 | 作用 |
|---|---|
/list | 列出所有可用 SHA1 哈希会话 |
/switch <sha> | 按哈希前缀恢复会话,跳过 prompt 重建 |
/save | 保存当前会话为新的 KVC 检查点 |
/del <sha>//strip <sha> | 删除会话 / 剥离大体积 KV 载荷仅留文本 |
服务端的命中与淘汰会写入日志,例如kv cache hit ... key=token-text load=41.7 ms或kv cache evicted reason=disk-cache-full ... file=....kv,可以据此确认 SHA1 前缀缓存是否按预期工作。更多 HTTP 用法见 docs/SERVER.md。
小结
- KVC 文件名 = 40 位 SHA1 十六进制 +
.kv,目录扫描时按 43 字符形状严格过滤 - 哈希对象是渲染文本的字节前缀而非 token 序列,保证客户端可复现、跨进程可命中
- 命中需通过摘要比对 + 逐字节前缀复核 + 模型/量化/上下文三重校验,失败即弃用
- 写入走临时文件原子改名;淘汰按带半衰期的命中评分执行,锚点检查点享 2 倍生存加权
理解了这套"SHA1 前缀即身份"的命名方式,你就能预判哪些请求会命中检查点、哪些会触发 prefill,也让本地长会话推理的成本变得可预期。
【免费下载链接】ds4DeepSeek 4 Flash and PRO local inference engine for Metal, CUDA and ROCm项目地址: https://gitcode.com/GitHub_Trending/ds4/ds4
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考