flare-engine-driver.md 7.7 KB

FLARE как движок рецепта (engine = "flare", deploy = "native")

Цель: запускать FLARE-пакеты из наших рецептов тем же путём, что dgpp: рецепт описывает что подать, кластер — где, а лаунчер делает preflight, провижининг, запуск, ожидание готовности, follow и stop. Никаких ручных flare orbit … в истории смен.

Блок рецепта

engine = "flare"
deploy = "native"
model = "deepseek-ai/DeepSeek-V4.1-Flash-1017"   # для отчёта/медалей
docker_image = "flare-inference"                  # не используется (нет докера)

[flare]
package   = "local-inference-lab/DeepSeek-V4.1-Flash-1017-FLARE"  # HF-репо пакета
revision  = "gb10"                # ветка/ревизия пакета (gb10 = под 4 Spark)
name      = "deepseek1017"        # имя группы в orbit (--name)
http_port = 8000                  # API на контроллере, /health + /v1/models
serve_flags = [                   # verbatim в `flare orbit run`
  "--max-concurrency", "16",
  "--mtp-draft-tokens", "5", "--mtp-adaptive-verification",
  "--embedding-table-storage", "disk",
  "--embedding-table-resident-scales",
  "--embedding-table-cache-size", "1GiB",
]
# необязательное: пин агентского пакета + ключ издателя проверяются в config,
# не в рецепте (репозиторий рецептов публичный)

Конфиг (приватный, на аддоне/Mac'е):

[flare]
accept_key        = "3748701d…"        # --dangerously-approve-key (пакет подписан)
accept_publisher  = "local-development"
binary            = "flare"            # если не в PATH
orbit_cluster     = "sparks"           # имя `[cluster.<...>]` в orbit.toml
# наши имена нод → имена в orbit (по порядку рангов). Пусто = совпадают.
orbit_nodes       = ["spark1", "spark2", "spark3", "spark4"]

Реализация: src/native/flare.rs (+ [flare] в config/recipe.rs и config/types.rs), диспетчеризация в native::{serve,stop}, logs → flare orbit attach, готовность через readiness::wait_engine на [flare].http_port. Тесты: cargo test flare (6 штук). Dry-run:

sm121 -d serve --recipe dsv41-flash-1017-4x-flare-gb10 --cluster dgx58-switch

Что делает драйвер (src/engine/drivers.rs, как у dgpp)

  1. Preflight (все ноды запуска): flare --version, сервис агента (systemctl --user is-active flare-agent), flare orbit status --cluster <orbit_cluster> — все ноды кластера на месте и в нужном порядке рангов. Не выполнено → отказ до любого запуска (класс ошибок «publisher not approved»/«peer not paired» нам уже знаком по bring-up).
  2. Провижининг пакета (только контроллер = rank 0): flare download <package> --revision <revision> (идемпотентно — кэш переиспользуется), путь сохраняется в <dir>/.sm121-flare-package; повторный serve с тем же package@revision пропускает проверку подписи и лицензии (штамп .sm121-flare-rev, аналог dgpp .sm121-dgpp-rev).
  3. Запуск: flare orbit run "<node>:<package_path>" --cluster <orbit_cluster> --name <name> --host 0.0.0.0 --port <http_port> --detach --dangerously-approve-key <ключ> --dangerously-accept-publisher … <serve_flags> на rank 0 (агенты сами раздают рангам их срезы). Лог — через flare orbit attach <name> пишется в <dir>/log/.
  4. Готовность: поллинг GET http://<rank0>:<http_port>/health, затем /v1/models (30 мин, --no-wait пропускает) — как у остальных движков.
  5. Follow: HTTP-проба раз в 30 с; 2 промаха → падение (как в docker-пути).
  6. Stop: flare orbit stop <name> --cluster <orbit_cluster>, затем проверка, что /health недоступен; ledger закрывается только после успешной остановки (как у docker stop).
  7. Логи: sm121 logs → flare orbit attach (tail) на контроллере.

Открытые вопросы

  • Ключ издателя: хранить в config ([flare].accept_key), в репозиторий рецептов не пускать; validate ругается, если ключ попал в рецепт.
  • --max-concurrency 16 упаковочный: у нас исторически 4 seqs на vLLM — для FLARE это его собственный prepared capacity, не наш KV-бюджет.
  • Порт: у FLARE API фиксирован (8000 в их примере, но задаётся), это освобождение от правила «порт 30000» — как у gr8/dgpp (takes_host_port() == false).
  • A/B с текущими лейнами: мерить теми же бенчами (sm121 bench), сравнение с прод-SGLang (47.8–50.7 c1 / 64.2–68.3 c2, pp 2.8–3.1k) и нашим прошлым FLARE-bring-up (19.2 / 29.6, pp 1430–1700).
  • Обновления FLARE: перед экспериментом — scripts/flare-upstream-watch.sh (пин flare-upstream.pin), git pull + пересборка обеих сторон.

Откуда берём flare: APT-срез против сборки из исходников

Замер 2026-10-23 21:17 UTC: в APT-репозитории один пакет flare-inference 0.1.0~git20261022193508.f2822dc3-1 (arm64 + amd64, 6.28 MB), собранный из коммита f2822dc3 2026-10-22 19:35:08 UTC; Release-файл датирован 19:38 — публикация через три минуты после сборки (это CI-задержка, не свежесть). То есть пакету ~сутки: APT — суточный срез, а не per-commit. Наш прежний пин исходников 3b9e86a (2026-10-22 15:48) даже старше пакета.

Правила:

  1. Базовый путь — APT с явным пином версии (apt-get install -y flare-inference=0.1.0~git20261022193508.f2822dc3-1); версия пишется в манифест прогона рядом с checksum образа, поэтому A/B атрибутируем.
  2. Дерево исходников (~/flare-src, 8.3 GB) живёт только на build-хосте (dgx5) — для head-сборок, когда нужен фикс, которого ещё нет в пакете (в сутки у них проходит много коммитов: вотчер видел 17 за 14 ч). Бинарь копируется остальным нодам, версия штампом — как с образами, без тулчейна на четырёх нодах.
  3. Вотчер следит за двумя источниками: Version: из dists/noble/main/binary-arm64/Packages (= что реально установится) и upstream HEAD (= что можно собрать). Расхождение > суток или появление нужного фикса — повод собрать head на dgx5.