Metal 上的 DeepSeek V4 Flash 本地推理引擎

Hacker News Top 工具

摘要

ds4 是一款专为 Apple Silicon 优化的 DeepSeek V4 Flash 本地原生推理引擎,支持基于磁盘的 KV 缓存持久化和 Metal 加速。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/05/08 08:30

antirez/ds4 源码: https://github.com/antirez/ds4 # ds4.c ds4.c 是一个专为 DeepSeek V4 Flash 设计的小型原生推理引擎。它的定位非常狭窄:既不是通用的 GGUF 运行器,也不是其他运行时环境的封装,更不是开发框架。其核心路径是一个针对 DeepSeek V4 Flash 特定的 Metal 图执行器,包含了 DS4 特有的模型加载、提示词渲染、KV 状态管理以及服务器 API 接口粘合代码。

如果没有 llama.cpp 和 GGML,这个项目根本不会存在,请务必阅读致谢部分,特别感谢 Georgi Gerganov 以及所有其他贡献者。

现在回到本项目。为什么我们认为 DeepSeek v4 Flash 是一款非常特别、值得拥有独立引擎的模型?因为在将其与强大的小型稠密模型进行比较后,我们可以报告以下几点:

  1. 由于激活参数更少,DeepSeek v4 Flash 速度更快。
  2. 在思考模式下,如果你避免使用 最大思考(max thinking),它生成的思考部分长度远短于其他模型,在许多情况下仅为其他模型的 1/5,而且至关重要的一点是,思考部分的长度与问题复杂度成正比。这使得 DeepSeek v4 Flash 在启用思考模式时依然可用,而其他模型在相同条件下几乎无法使用。
  3. 该模型具备 100 万 token 的上下文窗口。
  4. 由于体量巨大,在知识边缘进行采样时,它知道更多事物。例如,询问关于意大利节目或政治的问题时,很快就能发现 2840 亿参数确实比 270 亿或 350 亿参数强大得多。
  5. 它的英语和意大利语写作能力更强。它感觉像是一个准前沿模型。
  6. 其 KV 缓存具有极高的压缩率,允许在本地计算机上进行长上下文推理,并支持磁盘 KV 缓存持久化
  7. 它在进行特殊量化(后文详述)时能很好地支持 2-bit 量化。这使得它可以在配备 128GB RAM 的 MacBook 上运行。
  8. 我们预计 DeepSeek 未来会发布更新的 v4 Flash 版本,会比当前版本更好。

话说回来,关于这个项目有几个重要的事项:

  • 本地推理领域包含许多优秀的项目,但新模型不断发布,注意力立即会被下一个需要实现的模型所吸引。这个项目采取了刻意狭窄的赌注:一次专注一个模型,进行官方向量验证(使用官方实现获得的 logits),进行长上下文测试,并进行足够的智能体(agent)集成以确认其是否真正有效。具体的模型可能会随着环境变化而改变,但约束条件保持不变:在高端个人机器或 Mac Studio(至少 128GB 内存)上实现可信的本地推理。
  • 本软件在 GPT 5.5 的强力辅助下开发,由人类主导思路、测试和调试。我们公开说明这一点,因为它塑造了项目的构建方式。如果你不喜欢 AI 开发的代码,这款软件不适合你。下面的致谢同样重要:没有 llama.cpp 和 GGML( largely 手工编写),这一切都不可能存在。
  • 本实现基于这样一个理念:像 DeepSeek v4 这样的压缩 KV 缓存以及现代 MacBook 的快速 SSD 磁盘,应该改变我们认为 KV 缓存属于 RAM 的观念。KV 缓存实际上是一等公民级的磁盘居民
  • 我们的愿景是,本地推理应该是三件事开箱即用、良好协作的结合体:A) 带有 HTTP API 的推理引擎 + B) 专门为在给定引擎和假设下良好运行而定制的 GGUF + C) 通过编码智能体实现进行测试和验证。该推理引擎仅与提供的 GGUF 文件配合运行。它针对在不同上下文大小下官方获得的 logits 进行测试。这个项目的存在是因为我们希望让一个本地模型从头到尾感觉是完整的,而不仅仅是可运行的。然而,这仍然是 alpha 质量的代码,所以我们可能尚未达到完美。
  • 这是仅限 Metal 的实现,未来可能会实现 CUDA 支持?也许,但也仅此而已。CPU 路径仅用于正确性检查,但警告:当前 macOS 版本在虚拟内存实现中存在 bug,如果尝试运行 CPU 代码将导致内核崩溃。记得吗?软件很糟糕。我未能修复 CPU 推理以避免崩溃,因为每次都需要重启电脑,这并不好笑。如果你有能力,请帮助我们。

致谢 llama.cpp 和 GGML

ds4.c 并不链接 GGML,但它得益于 llama.cpp 项目开辟的道路、内核、量化格式、GGUF 生态系统以及在那里开发的来之不易的工程知识。我们感谢并感激 llama.cpp (https://github.com/ggml-org/llama.cpp) 及其贡献者。他们的实现、内核、测试和设计选择在构建此 DeepSeek V4 Flash 专用推理路径时是重要的参考。在 MIT 许可下,此处保留或改编了一些源代码级别的组件:GGUF 量化布局和表格、CPU 量化/点积逻辑以及某些 Metal 内核。出于这个原因,并且因为我们 genuinely 感激,我们在 LICENSE 文件中保留了 GGML 作者的版权声明。

模型权重

此实现仅适用于为本项目发布的 DeepSeek V4 Flash GGUF 文件。它不是通用的 GGUF 加载器,任意的 DeepSeek/GGUF 文件将不具备引擎所期望的张量布局、量化混合、元数据或可选的 MTP 状态。

这里提供的 2-bit 量化并非玩笑:它们表现良好,在编码智能体下工作可靠,并能可靠地调用工具。2-bit 量化使用非常不对称的量化:仅对路由的 MoE 专家进行量化,up/gate 为 IQ2_XXS,down 为 Q2_K。它们占模型空间的绝大多数:其他组件(共享专家、投影、路由)保持不变以保证质量。

下载一个主模型:

./download_model.sh q2 # 128 GB RAM 机器
./download_model.sh q4 # >= 256 GB RAM 机器

该脚本从 https://huggingface.co/antirez/deepseek-v4-gguf 下载,将文件存储在 ./gguf/ 下,使用 curl -C - 恢复部分下载,并更新 ./ds4flash.gguf 指向所选的 q2/q4 模型。公共下载无需认证,但如果存在 --token TOKENHF_TOKEN 或本地 Hugging Face 令牌缓存,则使用它们。

./download_model.sh mtp 获取可选的投机解码(speculative decoding)支持 GGUF。它可与 q2 和 q4 一起使用,但必须使用 --mtp 显式启用。当前的 MTP/投机解码路径仍处于实验阶段:它受正确性门控(correctness-gated),目前最多提供轻微的速度提升,而非显著的生成速度优势。

然后构建:

make

./ds4flash.gguf 是两者二进制文件使用的默认模型路径。传递 -m 以从 ./gguf/ 中选择另一个支持的 GGUF。运行 ./ds4 --help./ds4-server --help 查看完整的标志列表。

速度

以下是使用 --ctx 32768--nothink、贪心解码(greedy decoding)和 -n 256 的单次运行 Metal CLI 数据。短提示是一个普通的意大利小故事提示。长提示测试分块预填充(chunked prefill)加长上下文解码。由于 Q4 需要更大内存的机器类别,因此 M3 Max Q4 的数据为 N/A

机器量化提示词预填充 (Prefill)生成 (Generation)
MacBook Pro M3 Max, 128 GBq258.52 t/s26.68 t/s
MacBook Pro M3 Max, 128 GBq211709 tokens250.11 t/s21.47 t/s
MacBook Pro M3 Max, 128 GBq4N/AN/A
MacBook Pro M3 Max, 128 GBq4N/AN/A
Mac Studio M3 Ultra, 512 GBq284.43 t/s36.86 t/s
Mac Studio M3 Ultra, 512 GBq211709 tokens468.03 t/s27.39 t/s
Mac Studio M3 Ultra, 512 GBq478.95 t/s35.50 t/s
Mac Studio M3 Ultra, 512 GBq412018 tokens448.82 t/s26.62 t/s

CLI

单次提示:

./ds4 -p "Explain Redis streams in one paragraph."

不带 -p 启动交互式提示:

./ds4
ds4>

交互式 CLI 是真正的多轮 DS4 聊天。它保留渲染的聊天记录和实时 Metal KV 检查点,因此每轮对话都延申之前的会话。有用命令包括 /help/think/think-max/nothink/ctx N/read FILE/quit。Ctrl+C 中断当前生成并返回到 ds4>

CLI 默认为思考模式。使用 /nothink--nothink 获取直接答案。--mtp MTP.gguf --mtp-draft 2 启用可选的 MTP 投机路径;它仅对贪心解码有用,目前使用置信度门控(--mtp-margin)以避免缓慢的部分接受,应被视为实验性的轻微加速路径。

服务器

启动一个兼容 OpenAI/Anthropic 的本地服务器:

./ds4-server --ctx 100000 --kv-disk-dir /tmp/ds4-kv --kv-disk-space-mb 8192

服务器仅限 Metal。它在内存中保留一个可变图/KV 检查点,因此无状态客户端如果重新发送同一提示词的更长版本,可以复用共享前缀,而不是从头预填充。请求解析和套接字在客户端线程中运行,但推理本身通过单个 Metal 工作者序列化。当前服务器不将多个独立请求合并批次;并发请求在单个实时图/会话上等待轮到它们。

支持的端点:

  • GET /v1/models
  • GET /v1/models/deepseek-v4-flash
  • POST /v1/chat/completions
  • POST /v1/completions
  • POST /v1/messages

/v1/chat/completions 接受通常的 OpenAI 风格 messagesmax_tokens/max_completion_tokenstemperaturetop_ptop_kmin_pseedstreamstream_options.include_usagetoolstool_choice。工具模式被渲染为 DeepSeek 的 DSML 工具格式,生成的 DSML 工具调用映射回 OpenAI 工具调用。

/v1/messages 是 Claude Code 风格客户端使用的 Anthropic 兼容端点。它接受 systemmessagestoolstool_choicemax_tokenstemperaturetop_ptop_kstreamstop_sequences 和思考控制。工具使用以 Anthropic tool_use 块形式返回。

两个 API 都支持 SSE 流式传输。在思考模式下,推理以原生 API 形状流式传输,而不是混合到最终文本中。

最小 OpenAI 示例:

curl http://127.0.0.1:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model":"deepseek-v4-flash",
    "messages":[{"role":"user","content":"List three Redis design principles."}],
    "stream":true
  }'

智能体客户端用法

ds4-server 可被支持 OpenAI 兼容聊天完成的本地编码智能体使用。首先启动服务器,并将客户端上下文限制设置得不高于你启动服务器时使用的 --ctx 值:

./ds4-server --ctx 100000 --kv-disk-dir /tmp/ds4-kv --kv-disk-space-mb 8192

如果你愿意,可以使用更大的上下文和更大的缓存。完整的 100 万 token 上下文将使用大约 26GB 内存(仅压缩索引器就约为 22GB),因此请配置适合你系统的上下文。使用 128GB RAM 时,你会运行 2-bit 量化版本,其本身已占用 81GB,26GB 可能会太多,因此 100k~300k token 的上下文窗口更明智。下面的 384000 输出限制避免了 token 上限,否则模型能够生成非常长的回复(高达 384k token)。服务器在配置的上下文窗口满时仍然会停止。

对于 opencode,在 ~/.config/opencode/opencode.json 中添加提供者和智能体条目:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ds4": {
      "name": "ds4.c (local)",
      "npm": "@ai-sdk/openai-compatible",
      "options": {
        "baseURL": "http://127.0.0.1:8000/v1",
        "apiKey": "dsv4-local"
      },
      "models": {
        "deepseek-v4-flash": {
          "name": "DeepSeek V4 Flash (ds4.c local)",
          "limit": {
            "context": 100000,
            "output": 384000
          }
        }
      }
    }
  },
  "agent": {
    "ds4": {
      "description": "DeepSeek V4 Flash served by local ds4-server",
      "model": "ds4/deepseek-v4-flash",
      "temperature": 0
    }
  }
}

对于 Pi,在 ~/.pi/agent/models.json 中添加提供者:

{
  "providers": {
    "ds4": {
      "name": "ds4.c local",
      "baseUrl": "http://127.0.0.1:8000/v1",
      "api": "openai-completions",
      "apiKey": "dsv4-local",
      "compat": {
        "supportsStore": false,
        "supportsDeveloperRole": false,
        "supportsReasoningEffort": true,
        "supportsUsageInStreaming": true,
        "maxTokensField": "max_tokens",
        "supportsStrictMode": false,
        "thinkingFormat": "deepseek",
        "requiresReasoningContentOnAssistantMessages": true
      },
      "models": [
        {
          "id": "deepseek-v4-flash",
          "name": "DeepSeek V4 Flash (ds4.c local)",
          "reasoning": true,
          "thinkingLevelMap": {
            "off": null,
            "minimal": "low",
            "low": "low",
            "medium": "medium",
            "high": "high",
            "xhigh": "xhigh"
          },
          "input": ["text"],
          "contextWindow": 100000,
          "maxTokens": 384000,
          "cost": {
            "input": 0,
            "output": 0,
            "cacheRead": 0,
            "cacheWrite": 0
          }
        }
      ]
    }
  }
}

可选地在 ~/.pi/agent/settings.json 中将其设为默认 Pi 模型:

{
  "defaultProvider": "ds4",
  "defaultModel": "deepseek-v4-flash"
}

对于 Claude Code,使用 Anthropic 兼容端点。像这样的包装器匹配本地 ~/bin/claude-ds4 设置:

#!/bin/sh
unset ANTHROPIC_API_KEY
export ANTHROPIC_BASE_URL="${DS4_ANTHROPIC_BASE_URL:-http://127.0.0.1:8000}"
export ANTHROPIC_AUTH_TOKEN="${DS4_API_KEY:-dsv4-local}"
export ANTHROPIC_MODEL="deepseek-v4-flash"
export ANTHROPIC_CUSTOM_MODEL_OPTION="deepseek-v4-flash"
export ANTHROPIC_CUSTOM_MODEL_OPTION_NAME="DeepSeek V4 Flash local ds4"
export ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION="ds4.c local GGUF"
export ANTHROPIC_DEFAULT_SONNET_MODEL="deepseek-v4-flash"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="deepseek-v4-flash"
export ANTHROPIC_DEFAULT_OPUS_MODEL="deepseek-v4-flash"
export CLAUDE_CODE_SUBAGENT_MODEL="deepseek-v4-flash"
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
export CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1
export CLAUDE_STREAM_IDLE_TIMEOUT_MS=600000
exec "$HOME/.local/bin/claude" "$@"

Claude Code 可能会在开始执行有用工作之前发送一个大的初始提示,通常约为 25k token。保持启用 --kv-disk-dir:在第一次昂贵的预填充后,磁盘 KV 缓存允许后续的延续或重启的会话复用保存的前缀,而不是再次处理整个提示。

思考模式

DeepSeek V4 Flash 具有不同的非思考、思考和 Think Max 模式。服务器默认为思考模式。reasoning_effort=max 请求 Think Max,但它仅在上下文大小足够大以符合模型卡片推荐时应用;较小的上下文回退到普通思考。OpenAI reasoning_effort=xhigh 仍然映射到普通思考,而非 Think Max。对于直接回复,使用 thinking: {"type":"disabled"}think:false 或非思考模型别名如 deepseek-chat

磁盘 KV 缓存

聊天/补全 API 是无状态的:智能体客户端通常在每个请求中重新发送整个对话。ds4-server 通过比较渲染的 token 流与缓存的 token 前缀来处理此问题。内存中的实时检查点覆盖当前会话;磁盘 KV 缓存使有用的前缀在会话切换和服务器重启后得以保留。

出于内存原因,目前内存中只有一个实时 KV 缓存。当新的无关会话替换它时,旧检查点只有在写入磁盘 KV 缓存的情况下才能在不重新处理的情况下恢复。换句话说,内存缓存处理活跃会话;磁盘缓存是不同会话的恢复机制。

使用以下命令启用:

./ds4-server --kv-disk-dir /tmp/ds4-kv --kv-disk-space-mb 8192

缓存键是精确 token ID 的 SHA1,而非原始文本。每个 token ID 作为小端 32 位整数进行哈希,文件命名为 .kv。文件故意使用普通的 read/write I/O 写入,而非 mmap,因此恢复缓存条目不会为已经映射模型的进程添加更多 VM 映射。

在磁盘上,缓存文件结构为:

KVC 固定头部,48 字节
u32 rendered_text_bytes
rendered_text_bytes 字节的 UTF-8-ish token 文本
DS4 会话负载,来自 KVC 头的 payload_bytes

相似文章

DeepSeek-V4-Flash 284B 在 5.3GB 内存上运行

Reddit r/LocalLLaMA

一位开发者展示了 Mference,这是一个新的推理引擎,通过从 SSD 流式加载专家,仅用约 5.3GB 内存即可运行 MoE 模型(如 DeepSeek-V4-Flash),并配有原生 Mac 应用和兼容 OpenAI 的服务器。

DS4

Reddit r/LocalLLaMA

Salvatore Sanfilippo 发布了 DS4 项目,使 DeepSeek V3(文中称为 V4)Flash 能够在 Mac Metal 硬件上运行 100 万(1M)上下文窗口,并有望支持 DGX 和 AMD 芯片。