Browse Source

spec: FLARE as a first-class engine (engine=flare, deploy=native)

Design for running FLARE packages from recipes the way dgpp does: a [flare]
recipe block (package/revision/name/http_port/serve_flags), the publisher key in
the private config only, preflight (agents paired on every launch node), package
provisioning on the controller with a rev stamp, orbit run/stop, /health then
/v1/models readiness, follow and log attach. Written after the gb10 package
(511 GB, 4 Sparks, c16, DSpark5 + adaptive verification) made a first-class
driver worth it.
Alexander Korolev 16 giờ trước cách đây
mục cha
commit
1a6126581a
1 tập tin đã thay đổi với 80 bổ sung và 0 xóa
  1. 80 0
      specs/tech-architecture/flare-engine-driver.md

+ 80 - 0
specs/tech-architecture/flare-engine-driver.md

@@ -0,0 +1,80 @@
+# FLARE как движок рецепта (`engine = "flare"`, `deploy = "native"`)
+
+Цель: запускать FLARE-пакеты из наших рецептов тем же путём, что `dgpp`:
+рецепт описывает *что* подать, кластер — *где*, а лаунчер делает preflight,
+провижининг, запуск, ожидание готовности, follow и stop. Никаких ручных
+`flare orbit …` в истории смен.
+
+## Блок рецепта
+
+```toml
+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'е):
+
+```toml
+[flare]
+accept_key        = "3748701d…"        # --dangerously-approve-key (пакет подписан)
+accept_publisher  = "local-development"
+binary            = "flare"            # если не в PATH
+orbit_cluster     = "sparks"           # имя `[cluster.<...>]` в orbit.toml
+```
+
+## Что делает драйвер (`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` + пересборка обеих сторон.