ds4 от antirez: локальный coding agent на DeepSeek V4 Flash, который работает на MacBook

Создатель Redis за две недели написал инференс-движок только для одной модели — DeepSeek V4 Flash. 1M контекст, 26 t/s на M3 Max, KV-кэш на диске. Как это запустить и подключить к Claude Code.

ds4 — локальный инференс-движок DeepSeek V4 Flash на Apple Metal

Garry Tan и Bindu Reddy 9 мая 2026 одновременно расшарили одну и ту же новость: создатель Redis Salvatore Sanfilippo (antirez) выложил ds4 — инференс-движок на C+Metal, который запускает DeepSeek V4 Flash (284B MoE, 1M контекста) на ноутбуке. Не «технически возможно», а «работает с coding-агентами на 26 t/s». Я разобрался, что под капотом, и как использовать это как локальный backend для Claude Code.


1. Что произошло за две недели

24 апреля 2026 DeepSeek выпустил серию V4. V4 Flash — efficiency-модель: 284 миллиарда параметров суммарно, 13 миллиардов активных (MoE), контекст 1 миллион токенов. Раньше модели такого размера жили только в облаке.

Antirez посмотрел на это и сделал ставку, которую универсальные раннеры сделать не могут. Он форкнул llama.cpp, две недели возился внутри него, понял геометрию V4 Flash, выкинул всё лишнее и написал с нуля движок на 4 файлах: ds4.c (~ инференс), ds4_metal.m (Metal kernels), ds4_server.c (HTTP-сервер), ds4_cli.c (REPL). Снаружи всё это говорит на двух протоколах одновременно: OpenAI Chat Completions (/v1/chat/completions) и Anthropic Messages (/v1/messages). То есть подключается к любому агенту, который умеет один из них.

Результаты, которые автор замерил сам:

МашинаКвантПромптPrefillGeneration
MacBook Pro M3 Max, 128 GBq2короткий58.52 t/s26.68 t/s
MacBook Pro M3 Max, 128 GBq211709 токенов250.11 t/s21.47 t/s
Mac Studio M3 Ultra, 512 GBq2короткий84.43 t/s36.86 t/s
Mac Studio M3 Ultra, 512 GBq412018 токенов448.82 t/s26.62 t/s

26 токенов в секунду генерации — это не «можно посмотреть», это рабочая скорость для coding-агента, который пишет, читает файлы, вызывает инструменты. На длинном промпте генерация падает до 21 t/s, но за счёт KV-кэша на диске это окупается уже на третьем запросе той же сессии.


2. Три инженерных трюка, которые делают это возможным

Я внимательно прочитал README и AGENT.md репозитория, и ниже — самое существенное, без чего ds4 не работал бы.

2.1. Асимметричное 2-битное квантование

Стандартный подход к 2-битному кванту — давить всё подряд до 2 бит, и тогда модель начинает галлюцинировать в tool calling, путать аргументы и забывать схему. Antirez сделал иначе: квантованы только MoE-эксперты на routed-пути (up/gate в IQ2_XXS, down в Q2_K) — потому что они занимают большую часть веса (модель — 284B, и почти всё это — эксперты). Shared-эксперты, проекции, роутинг — остаются в Q8. Это компоненты, в которых потеря точности дорого стоит.

Эффект: 2-битный квант весит 81 GB и помещается в 128 GB унифицированной памяти MacBook Pro M3 Max, при этом надёжно работает в coding-агентах (что валидируется тестами против официальных логитов API DeepSeek).

2.2. KV-кэш как first-class disk citizen

Главная боль stateless API-протоколов вроде Chat Completions: клиент каждый раз присылает всю историю, и сервер обязан пре-фильнуть её с нуля. Claude Code, например, на старте шлёт ~25K токенов системного промпта. На локальном железе это десятки секунд до первого токена.

Ds4 решает это лобово: после успешного prefill стейт сессии (KV-чекпоинт) сериализуется в файл, ключ — SHA1 от token IDs. Когда приходит следующий запрос с тем же префиксом, сервер берёт чекпоинт с диска и пропускает prefill. Из README:

The KV cache is actually a first class disk citizen. <…> Modern MacBooks have fast SSDs and compressed KV caches like the one of DeepSeek v4.

На практике это означает разницу между «4 секунды до первого токена при повторном вызове» и «60 секунд». Диск тут — не своп под давлением, а логичное хранилище: SSD достаточно быстрые, KV у DeepSeek V4 хорошо сжимается, а характеристика «один и тот же системный промпт + меняющийся хвост» точно описывает работу coding-агента.

2.3. Metal-only и одна модель за раз

Никакого CUDA, никакого CPU-фоллбэка для прода (CPU-путь существует только для correctness-чеков и сейчас падает на уровне ядра macOS из-за бага в VM — antirez об этом честно пишет). Никакой попытки сделать «универсальный раннер». Только Apple Silicon, только эта одна модель, и так до тех пор, пока не появится новая версия V4 Flash или сильно лучшая модель того же класса.

Цена — narrow bet. Выгода — тебе не нужно поддерживать матрицу (модель × железо × квант), и ты можешь оптимизировать Metal-ядра под точную геометрию слоёв этой конкретной модели.


3. Что мне понадобится: железо, модель, час времени

Я планирую разворачивать это на MacBook Pro M3 Max, 128 GB (минимально жизнеспособная конфигурация по README). У меня его пока нет, и в этом разделе — честный план, что я буду делать, когда железо приедет; цифры взяты из бенчмарков antirez’а, но я хочу их перепроверить на своём экземпляре.

Минимальные требования по моим прикидкам:

  • macOS на актуальной версии (там же баг VM в CPU-пути, но Metal-путь не задет).
  • Apple Silicon с 128 GB+ унифицированной памяти. M3 Max или M3 Ultra.
  • ~100 GB свободного места: 81 GB сама модель Q2 + место под KV-кэш на диске. Под Q4-квант — 256 GB+ RAM и ~150 GB на диске.
  • Xcode Command Line Tools (для clang/Metal headers).
  • ~30–60 минут на скачивание модели (зависит от канала).

То, чего может не хватить начинающим: 128 GB unified memory — это уровень MBP M3 Max в топовой комплектации или Mac Studio. На 64-гиговом Mac Q2 не заработает: модель просто не влезет в RAM. Это не «медленно», это «никак».


4. Установка пошагово

Команды ниже — то, что я сделаю в первый же день, опираясь на инструкции README. Где описание скучает за конкретикой — я добавил собственные комментарии.

4.1. Сборка

# 1. Склонировать репозиторий
git clone https://github.com/antirez/ds4.git
cd ds4

# 2. Скачать 2-битный квант (81 GB; для 128 GB MBP)
./download_model.sh q2

# Скрипт качает с huggingface.co/antirez/deepseek-v4-gguf,
# поддерживает резюм через curl -C - — можно прервать и продолжить.
# Если нужен 4-битный квант (для Mac Studio 256+ GB), используй ./download_model.sh q4.

# 3. Собрать
make

# Проверить, что собралось:
./ds4 --help
./ds4-server --help

Сборка — обычный make, никаких CMake, никаких pkg-config. Это намеренно: зависимостей за пределами Apple SDK у проекта нет.

4.2. Первый запуск в REPL

./ds4 -p "Объясни Redis streams в одном абзаце."

Без -p запускается интерактивная сессия с командами /help, /think, /think-max, /nothink, /ctx N, /read FILE, /quit. Это хорошо для проверки, что движок жив, и для сравнения скорости генерации против заявленных 26 t/s.

4.3. Запуск как HTTP-сервер

Это режим, в котором ds4 становится локальным backend’ом для агентов:

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

Параметры:

  • --ctx 100000 — контекстное окно в 100K токенов. Полный 1M-контекст ест ~26 GB только на индексер; на 128 GB Mac, где 81 GB уже занято моделью, это не оставит места для KV-кэша. 100–300K — разумный компромисс.
  • --kv-disk-dir /tmp/ds4-kv — каталог для disk KV-кэша. Я бы вынес его на быстрый SSD (внешний или встроенный — оба ок).
  • --kv-disk-space-mb 8192 — лимит на размер кэша. 8 GB для одного-двух активных проектов хватит; для сессий побольше — увеличивай.

Сервер слушает 127.0.0.1:8000. Эндпоинты:

EndpointПротокол
POST /v1/chat/completionsOpenAI Chat Completions (+ tools)
POST /v1/completionsOpenAI legacy completions
POST /v1/messagesAnthropic Messages (для Claude Code)
GET /v1/modelsсписок моделей

Аутентификация по статичному API-ключу (по умолчанию принимается любой; в README рекомендуется dsv4-local).


5. Подключение как coding agent

Это та часть, ради которой я вообще копал тему. Все три приведённых ниже способа работают одновременно — каждый агент ходит в один и тот же ds4-server.

5.1. Claude Code → Anthropic-совместимый эндпоинт

Claude Code умеет говорить с любым backend’ом, который выставляет Anthropic Messages API. Создаём обёртку ~/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"

# Подменяем все алиасы Sonnet/Haiku/Opus на локальную модель —
# чтобы /model в Claude Code не дёрнул облачный fallback.
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"

# Отключаем телеметрию и не-стриминговый fallback.
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" "$@"

chmod +x ~/bin/claude-ds4 — и запускаешь Claude Code как claude-ds4 вместо claude. Все запросы пойдут на локальный ds4-сервер. Тонкость, на которую обращает внимание сам antirez:

Claude Code may send a large initial prompt, often around 25k tokens, before it starts doing useful work. Keep --kv-disk-dir enabled.

Без disk KV-кэша запуск Claude Code на холодную будет занимать минуту и больше; с кэшем — после первого старта последующие будут восстанавливаться с диска.

5.2. opencode

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
    }
  }
}

limit.context: 100000 обязательно совпадает с --ctx, с которым стартует ds4-server — иначе сервер обрежет, а opencode об этом не узнает и пошлёт следующее сообщение, ожидая нерабочую длину.

5.3. Pi (мини-агент antirez’а)

Если используешь 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",
        "thinkingFormat": "deepseek",
        "requiresReasoningContentOnAssistantMessages": true
      },
      "models": [
        {
          "id": "deepseek-v4-flash",
          "name": "DeepSeek V4 Flash (ds4.c local)",
          "reasoning": true,
          "contextWindow": 100000,
          "maxTokens": 384000,
          "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
        }
      ]
    }
  }
}

cost: 0 — это не маркетинг, это правда. Каждый запрос обходится в электричество и износ SSD, не в токены.


6. Где это сломается (важные грабли)

Реальные ограничения, на которые я наткнусь, и то, как их обходить.

Окно контекста должно быть согласовано везде. Стартуешь сервер с --ctx 100000, ставишь в opencode limit.context: 100000, в Claude Code не лезешь в системный промпт сверх этого. Если у Claude Code init-prompt ~25K, то на проект остаётся 75K — реально хватает на средний codebase, но не на огромные репозитории.

Disk KV-кэш «привязан» к точному префиксу. Любая правка в системном промпте, в CLAUDE.md, в первых сообщениях — инвалидирует чекпоинт. Это не баг, это by design: матчинг идёт по SHA1 от token IDs. Если ты часто редактируешь CLAUDE.md, ожидай холодные старты. Решение — закоммитить системный контракт и не править его в каждой сессии.

MTP/спекулятивное декодирование пока не даёт большого выигрыша. В README прямо написано: «currently provides at most a slight speedup». Не закладывайся на удвоение скорости от MTP — текущая реализация correctness-gated и на сложных промптах часто триггерит партиал-аксепт.

Один live KV-кэш в памяти. Сервер сейчас не батчит независимые запросы. Если два агента ходят одновременно — второй ждёт первого. Это нормальный trade-off для локального single-user setup, но если ты хочешь параллельный multi-tenancy на одном Mac — ds4 пока не для этого.

CPU-режим падает на свежих macOS. Это про debug-путь, не про прод (Metal-only — основной таргет), но если по привычке захочешь сравнить инференс на CPU — не делай этого: kernel-panic, надо ребутиться.


7. Что это значит: vertical inference engines как тренд

Главное — не ds4 сам по себе, а паттерн, который antirez формализовал.

Локальный inference сейчас выглядит как «универсальный раннер + тысяча моделей в GGUF + обёртки разной свежести». Это работает, но движётся со скоростью наименее популярной модели: ускорять Llama 3.1 в llama.cpp проще, чем добавить эффективную поддержку DeepSeek V4 — потому что в первом случае структура слоёв совпадает с двадцатью другими моделями, а во втором — appears once.

Antirez показывает противоположный путь. Один движок — одна модель — один сценарий (coding agent). Дальше нужно три вещи, и все три — в продукте:

  1. Inference engine с HTTP API.
  2. GGUF, специально подготовленный под этот движок и его допущения.
  3. Тесты и валидация на сцепке с конкретными агент-клиентами.

Если эта ставка работает (и бенчмарки говорят, что да), будущее локального inference — не «ещё одна абстракция поверх абстракции», а «у каждой важной модели — свой ds4-подобный проект». Когда выходит V4.1 или V5, кто-то из community делает новый движок, новый GGUF, новые тесты, и через две недели у пользователей уже работающая локальная установка. Старые движки уходят на покой вместе со старыми моделями.

И второе. В README antirez явно пишет:

This software is developed with strong assistance from GPT 5.5 and with humans leading the ideas, testing, and debugging.

Две недели от форка llama.cpp до production-ready узкого движка с серверным API — без AI это не сделать, и antirez это прямо говорит. Вот это переключение — «один человек + AI = инфраструктура для целой модели за две недели» — на мой взгляд интереснее, чем сами цифры t/s.


Итог

ds4 от antirez — это не «ещё один локальный инференс». Это узкая ставка: один движок, одна модель (DeepSeek V4 Flash), одна архитектура железа (Apple Silicon с Metal), один сценарий (coding agent). За счёт асимметричного 2-битного кванта 284B-модель влезает в 128 GB MacBook, за счёт disk KV-кэша работает с агентами, которые гоняют 25K-токенные системные промпты, за счёт OpenAI/Anthropic-совместимости подключается к Claude Code, opencode и Pi из коробки.

Если у вас есть Mac с 128 GB+ — это рабочий локальный backend для серьёзной коммерческой работы с приватным кодом. Если нет — ждать DDR5 и unified memory на Linux/CUDA, или смотреть, кто следующий повторит этот паттерн под свою связку «модель + железо».

В любом случае стоит наблюдать. Я ставлю на то, что через год так будут собирать половину серьёзных локальных установок.


Источники:

FAQ

Зачем отдельный движок под одну модель, если есть llama.cpp?

Универсальные раннеры обязаны абстрагироваться: один и тот же код должен загрузить Llama, Qwen, DeepSeek, Mistral. Абстракция = компромисс. ds4 знает геометрию DeepSeek V4 Flash на уровне Metal-ядер, делает асимметричную 2-битную квантизацию (квантуются только MoE-эксперты, остальное в Q8), и валидирует логиты против официального API. Цена — узкая ставка на одну модель: появится V4.1 или V5 — нужно переписывать. Но для текущего поколения это даёт быстрый прирост, который универсальному раннеру технически недоступен.

Какой Mac реально нужен?

Минимум — 128 GB унифицированной памяти и Apple Silicon (M3 Max или старше). На таком железе работают 2-битные кванты Q2 (вес ~81 GB), 32K контекст, 26 t/s генерации. Для 4-битных квантов и больших контекстов нужен M3 Ultra с 256 GB+ (комфортно — 512 GB Mac Studio). На 64 GB MacBook ничего не запустится: модель не влезет в RAM.

Можно ли запустить на Linux/CUDA?

Сейчас — нет. Проект Metal-only, и автор честно пишет: «возможно, добавлю CUDA, но обещаний не даю». CPU-путь существует только как correctness-чек и в текущих macOS падает на уровне ядра из-за бага виртуальной памяти. Если у вас не Mac — ds4 не для вас, смотрите на vLLM/llama.cpp с DeepSeek V4 Flash GGUF.

Что такое asymmetric quantization и почему 2 бита не убивают качество?

В обычной 2-битной квантизации все веса сжимаются до 2 бит — модель теряет точность и часто перестаёт надёжно вызывать tools. ds4 делает иначе: 2-битно квантуются только MoE up/gate (IQ2_XXS) и down (Q2_K), которые занимают большую часть веса. Shared-эксперты, проекции и роутинг остаются в Q8 — это чувствительные части, где потеря точности дороже. На практике 2-битный Q2 надёжно работает с coding-агентами, что и подтверждается в тестах против официальных логитов API.

Disk KV cache — это просто свопинг?

Нет. Стейт inference-сессии (KV-чекпоинт) сериализуется в файл с SHA1 от token IDs в качестве ключа. Когда агент-клиент присылает следующий запрос с тем же префиксом (а Claude Code типично шлёт ~25K токенов системного промпта каждый раз), сервер не делает пре-фил с нуля — он восстанавливает чекпоинт с диска. Это разница между «4 секунды до первого токена» и «60 секунд до первого токена» на длинном промпте.

Чем это лучше OpenAI/Anthropic API?

Не лучше — а другое. Облачный API всегда быстрее, надёжнее, и модели поверх него умнее (текущая фронтир-планка — Sonnet 4.6, Opus 4.6, GPT 5.5). ds4 на DeepSeek V4 Flash — это «квази-фронтир» с тремя выгодами: ноль рублей за токены, полный контроль данных, оффлайн-работа. Подходит для приватных проектов, экспериментов с агентами и работы в самолёте. Не подходит, если вам нужна максимальная точность или работа с контекстом, который не влезет в ваш Mac.