在 Redis 创始人 Salvatore Sanfilippo(antirez)宣布淡出 Redis 维护之后,社区一直在等待他的下一个作品。2025 年底,他低调发布了 DwarfStar 4(后称 DS4),一个专为 DeepSeek V4 Flash 模型打造的本地推理引擎。这个项目并非又一款通用 GGUF 加载器,而是一个高度垂直化的系统:只服务于一个模型,在特定硬件上追求极致效率。阅读完 DS4 的源码与设计文档后,我认为它最值得关注的地方并非性能数字,而是 antirez 在 C 语言系统编程中展现出的工程哲学 —— 一种在约束下寻找优雅解法的思路。
设计起点:为什么只有一个模型
DS4 的第一个设计决策是极度收窄的 Scope。它不支持通用 GGUF 文件,不是一个包装另一个运行时的 wrapper,而是完全自包含的推理引擎。这个选择背后有一个明确的判断:当前本地推理领域的痛点不是「缺少通用 runner」,而是「缺少针对特定模型打磨到位的端到端体验」。通用的 GGUF loader 需要在正确性、易用性、性能之间做大量妥协,而 DS4 选择把所有的工程投入集中在一个模型上,换取这个模型在 MacBooks(Metal)和 DGX Spark(CUDA)上的可信体验。
从工程角度看,这种策略的好处是每个实现决策都可以针对模型的特定行为做优化。DeepSeek V4 Flash 有一个极为紧凑的 KV 缓存 —— 官方声称可以在本地计算机上实现长上下文推理,甚至支持 KV 缓存持久化到磁盘。DS4 把这个特性提升为架构的核心支柱,而不是事后添加的可选功能。这种「模型专用引擎」的思路在企业级推理系统中常见,但在开源社区的独立项目中相对少见。
KV 缓存:重新定义为一等磁盘公民
DS4 最重要的架构决策是将 KV 缓存从传统的内存概念中解放出来,把它视为磁盘的一等公民。在标准 LLM 推理管线中,KV 缓存被认为是消耗 RAM 的资源,磁盘只用作模型权重的持久化存储。DS4 反其道而行:利用 DeepSeek V4 Flash 的压缩 KV 缓存特性和现代 MacBooks 的高速 SSD,将大部分 KV 状态溢出到磁盘。
ds4-server 默认支持 --kv-disk-dir 参数来启用磁盘 KV 缓存。这个缓存不仅仅是冷启动优化,更是一个完整的会话恢复机制。当 agent 客户端发送一个包含长上下文的请求时,服务器首先检查磁盘上是否存在匹配的 KV 缓存。缓存的键是渲染后提示词的 SHA1 哈希,缓存文件包含完整的 DS4 会话负载 ——token ID 序列、logits 向量、压缩的注意力行等。这意味着即使服务器重启,同一个对话历史可以从磁盘恢复,无需重新 prefill 所有 token。
从实现细节来看,磁盘 KV 缓存格式被设计为可自描述的结构。文件以固定 48 字节的头部开始,包含魔数 "KVC"、版本号、量化位数、保存原因(cold/continued/evict/shutdown)、缓存 token 计数和创建时间戳。头部之后是渲染文本的 UTF-8 字节和 DS4 会话负载。值得注意的是,这个设计故意不使用 mmap,而是使用普通的 read/write I/O。antirez 在文档中解释了原因:映射模型文件后,进程已经有了大量 VM 映射,再增加 mmap 会增加内核的负担,普通的同步 I/O 在这个使用模式下反而更可控。
DSML 工具调用与精确回放
在 agent 场景中,工具调用(tool call)的处理是一个容易被忽视但实际极其棘手的问题。DeepSeek V4 Flash 通过 DSML(DeepSeek Markup Language)格式输出工具调用,这是一段包含工具名和参数的文本。问题在于:当 agent 客户端收到工具调用结果后,下一轮请求会以标准 JSON 格式把工具 ID 和参数发回服务器。如果服务器重新渲染这段 JSON,很可能会产生与原始 DSML 字节序列略有不同的输出 ——BPE tokenization 的边界差异会导致 KV 缓存失效。
DS4 用精确回放(exact replay)来解决这个问题。在工具调用发生时,服务器生成一个不可猜测的 API tool ID,将这个 ID 和模型采样的确切 DSML 文本存入内存映射。后续客户端用同一个 tool ID 发来 JSON 时,服务器直接使用原始采样的 DSML 字节,而不是重新渲染。更进一步,这个 tool ID 到 DSML 的映射可以持久化到 KV 缓存文件中的可选 KTM(tool-id map)节。这样即使服务器重启,精确回放依然有效。
当精确回放不可用时,DS4 会进行规范化渲染并比较结果。如果渲染后的字节前缀与缓存不匹配,系统会重写 live checkpoint,或者回退到更早的磁盘 KV 快照并只回放后缀部分。这个过程对调用方是透明的,确保了模型续接始终与无状态 API 的对话历史保持对齐。
还有一个值得注意的细节:在工具调用生成过程中,DS4 对协议结构部分(如 DSML 标签、参数头部、JSON 标点、关闭标记)强制使用 temperature=0 的贪婪解码。这保证了工具调用的语法部分是可确定的,不会因为采样随机性产生格式错误。参数 payload(JSON 字符串值、文件内容等)则使用请求指定的正常采样设置 —— 这个区分很关键,因为对长代码或文件内容使用贪婪解码会造成重复文本。
C 语言实现:单文件与依赖最小化
DS4 的 C 语言实现延续了 antirez 一贯的风格:单文件核心(ds4.c 可能超过两万行)、最小化外部依赖、自包含的工具链。这个项目依赖于 llama.cpp 和 GGML 的量化内核、布局格式和部分 CPU 路径,但主要的推理逻辑是独立实现的。
从项目结构来看,DS4 提供了几个独立的二进制文件:ds4 是交互式 CLI,ds4-server 是 HTTP 服务端,ds4-bench 是性能基准测试工具,ds4_test 是回归测试。这些工具都构建在同一套核心库之上,共享 KV 状态管理和图执行逻辑。构建系统支持多个后端:macOS Metal(默认)、NVIDIA CUDA(区分 DGX Spark 和通用构建)、AMD ROCm(社区维护的独立分支),以及仅用于诊断的 CPU 路径。
antirez 在 README 中坦承,这个项目的开发「在 GPT 5.5 的强力辅助下完成」,人类负责创意、测试和调试。这种人机协作的开发模式在 DS4 的代码中留下了清晰的印记:大量的断言和边界检查、清晰的错误路径处理、以及 --trace 参数提供的细粒度诊断输出。这种坦诚在开源项目中不常见,但也反映了一种务实的工程态度 —— 在 AI 辅助编程时代,工具就是工具,代码质量和设计决策依然需要人来把关。
性能与实用边界
DS4 给出的基准数据显示,在 MacBook Pro M3 Max(128 GB)上,使用 q2 量化并设置 11709 token 的长 prompt,prefill 速度可达 250 t/s,生成速度为 21 t/s。在 Mac Studio M3 Ultra(512 GB)上,q4 量化加上 12018 token 的长上下文,prefill 速度接近 449 t/s。DGX Spark GB10(128 GB)在 q2 量化下也有 343 t/s 的 prefill 速度。
这些数字需要放在上下文中理解。DS4 主要针对 96 GB 以上内存的机器,q2 量化(仅对 routed MoE experts 进行 IQ2_XXS 量化,其他组件保持原始精度)是 96/128 GB 机器的推荐配置。q4 量化需要 256 GB 以上内存。用户报告在 96 GB MacBooks 上使用 250k context window 也能运行 DS4,但需要关闭其他占用内存的进程。1M token 的完整上下文大约消耗 26 GB 内存,其中压缩索引器本身占约 22 GB。
与现有推理生态的关系
DS4 并不是要取代 llama.cpp 或其他通用 GGUF runner。它的定位更像是「针对特定场景的专用 ASIC」—— 在一个足够窄的领域中,用完全垂直的整合换取通用系统无法达到的完成度。llama.cpp 的价值在于广泛的模型支持和社区积累的量化技术;DS4 的价值在于对 DeepSeek V4 Flash 每一个细节的打磨,从 KV 缓存持久化到 DSML 协议处理的精确性。
对于在本地运行 coding agent 的开发者来说,DS4 提供了一个端到端可信的选项。它的 HTTP 服务器兼容 OpenAI 和 Anthropic 的 API 格式,可以直接作为 Claude Code、Codex CLI、opencode 等工具的后端,而 KV 缓存机制确保长时间 agent 会话的上下文不会因为服务器重启而丢失。这种「让本地模型感觉像完整产品」的思路,也许是 DS4 最有价值的贡献。
资料来源
- DS4 GitHub 仓库:https://github.com/antirez/ds4
内容声明:本文无广告投放、无付费植入。
如有事实性问题,欢迎发送勘误至 i@hotdrydog.com。