Каноническая спецификация исполнения
«Та же модель» не означает «тот же результат». Два честных майнера могут загрузить одинаковые веса, правильно ответить на один промпт и всё равно выдать результаты, различающиеся в последних битах. Проверка обязана отличать это от майнера, который втихую подсунул модель поменьше. Каноническая спецификация исполнения как раз и убирает все источники разброса, которые протокол в силах убрать, чтобы оставшийся разброс был понятным и ограниченным.
Почему сравнивают именно логиты
На каждом шаге генерации языковая модель выдаёт распределение вероятностей по всему словарю. Выпавший токен случаен, поэтому текст у двух майнеров часто различается. Стоящее за ним распределение не случайно: при одном входе и одинаковых настройках оно одно и то же.
На этом свойстве проверка и держится. Два честных майнера с моделью на 405B вернут одинаковые верхние вероятности, даже если один сэмплировал «4», а другой «четыре». Майнер, подменивший её на 8B, вернёт заметно другие вероятности, и расстояние между векторами сразу выдаёт подмену. Сравнение текстов не доказало бы ничего, сравнение распределений доказывает, какая модель реально работала.
Что меняется даже при правильных весах
Квантование, движок инференса, непрерывный батчинг, спекулятивное декодирование и маршрутизация MoE - всё это меняет логиты, полученные из одного набора весов. Системный промпт тоже. Часть различий мала, и малость здесь как раз проблема: по замерам друг против друга распространённые числовые форматы расходятся примерно настолько же, насколько разошлась бы дообученная подменная модель.
Допуск, достаточно широкий, чтобы принять незафиксированный dtype, достаточно широк и для того, чтобы принять подменённую модель. Лечится это не расширением допуска, а фиксацией окружения.
Что фиксирует спецификация
У каждой задачи есть каноническая спецификация, которую при проверке обязан воспроизвести каждый обслуживающий её майнер:
| Поле | Что фиксирует |
|---|---|
model_hash | Точные веса, по хэшу |
dtype | Числовой формат весов и активаций (bf16, fp16, fp32, int8, fp8, nvfp4, mxfp4) |
attention_impl | Реализация внимания (SDPA, FlashAttention 2, cuDNN) |
gpu_arch | Семейство архитектуры GPU, обязательно для уровня A и опционально для уровня B |
compile_mode | Режим компиляции Torch (eager, reduce-overhead, max-autotune) |
seed | Сид для любой случайности в прогоне |
Конфигурация задачи вокруг неё добавляет остальные канонические условия: размер батча 1 во время проверки, спекулятивное декодирование выключено, детерминированная маршрутизация для MoE-моделей и хэш канонического системного промпта, если он есть. Реальных пользователей майнер волен обслуживать как угодно: с непрерывным батчингом, спекулятивным декодированием и полным KV-кэшем. Канонический режим относится к проходу пересчёта, а не к продакшен-трафику.
Реализация внимания заслуживает отдельного предупреждения, потому что выглядит косметикой, а на деле не косметика. На одном GPU с одним dtype SDPA и eager-внимание дали совершенно разные хэши, ни один зонд не совпал. Тот же GPU, те же веса, та же точность, ноль совпадений. Валидатор и проверяемый майнер обязаны использовать побитово одинаковые стратегии, иначе сравнение развалится по причине, никак не связанной с честностью.
Поведение между архитектурами
Внутри одной архитектуры результаты воспроизводимы бит в бит. Между архитектурами - нет, и никакой настройкой это не чинится.
В замерах между двумя поколениями NVIDIA на одинаковых промптах не совпал ни один хэш, и это одинаково верно для bf16, fp16 и fp32. Численно результаты эквивалентны, различия по логиту далеко за пределами того, что заметит пользователь, но тензорные ядра двух поколений используют разный порядок редукции и разное расписание накопления, поэтому биты расходятся, а вместе с ними и хэши.
Та же картина на переходе через ещё одну границу поколений, и там дело зашло дальше битов: не совпали ни хэши, ни лидирующие токены. То есть расхождения хватило, чтобы поменять порядок победивших токенов, а не только слегка сдвинуть их вероятности. Прогоны шли ещё и на разных версиях PyTorch и CUDA, поэтому зазор смешивает эффекты железа и софта и не должен читаться как чисто аппаратное число.
Отсюда два вывода. Переход через границу архитектуры ломает побитовое сравнение как общее правило, а не как причуду одного поколения одного вендора. И внутри архитектуры детерминизм держится, поэтому задачу на одной архитектуре можно проверять точным хэшем. На этом и построены два уровня проверки; чем отличаются уровень A и уровень B, разобрано в статье Гетерогенный майнинг.
Как dtype принуждается эталонными зондами
Спецификация объявляет dtype, но само по себе объявление не мешает майнеру заявить fp16 и считать в bf16 ради экономии памяти. Эту щель закрывают эталонные зонды.
При создании задачи владелец считает эталонные логиты в каноническом окружении: фиксированный набор из 10 промптов, каноническая спецификация задачи, размер батча 1. В цепь идут только хэши, это 10 хэшей по 32 байта.
- Майнер, регистрирующийся на задачу, получает те же промпты и считает логиты на своём железе в каноническом режиме.
- Отправляет по хэшу на промпт.
- Рантайм сравнивает с эталоном. Совпадение допускает майнера, расхождение отклоняет.
- Периодически протокол берёт 3 промпта из 10 и требует воспроизвести их снова, что стоит 3 прямых прохода и 96 байт в цепи.
Проверка сделана сравнением хэшей, а не расстоянием, и это намеренно. Хэш даёт двоичный ответ без порога, который надо подкручивать, и без серой зоны: правильный dtype с правильными весами совпадает, всё остальное нет. Правильный dtype на двух разных GPU одной архитектуры воспроизвёл зонды в точности, так что точное совпадение - реалистичное требование, а не ловушка для честных.
Периодическая перепроверка закрывает и случай, когда майнер честно зарегистрировался, а потом сменил dtype или модель.
Квантование - часть спецификации
Квантование не деталь реализации на усмотрение майнера. Это часть отпечатка задачи, потому что каждый формат даёт собственный детерминированный вывод.
Ряд форматов признан пригодным для канона, то есть каждый из них побитово одинаков при повторных прогонах на одном GPU. Набор покрывает стандартные типы с плавающей точкой, распространённые целочисленные и 4-битные схемы квантования и более новые микромасштабированные форматы. Части самых свежих нужны железо класса Blackwell и свежая сборка PyTorch, поэтому их выбор сужает круг майнеров, способных обслуживать задачу. Что именно задача вправе объявить, определяет рантайм.
Большое расстояние L2 между квантованным форматом и базой bf16 отражает потери дискретизации, а не нестабильность. Формат может лежать далеко от bf16 и при этом сам по себе быть идеально детерминированным. Поскольку эталонные зонды считаются для объявленного формата, майнер, который считает не в том формате, что объявлен, зонды не пройдёт.
Одно семейство исключено: AWQ для проверки использовать нельзя. Повторные прогоны AWQ на одном GPU дают разные хэши, а недетерминизм живёт в его ядре деквантования, а не в железе, поэтому никакая архитектура его не спасает. Обслуживать пользователей на AWQ майнер может, но проход пересчёта обязан идти в каноническом формате.
Покрытие разных типов моделей
Спецификация не привязана к генерации текста. Что именно фиксируется, зависит от типа модели:
| Тип модели | Что фиксирует спецификация |
|---|---|
| LLM (генерация текста) | Квантование, движок, хэш системного промпта, батч 1 |
| Диффузия | Сид, число шагов, масштаб CFG, шедулер |
| Энкодер / эмбеддинги | Квантование (модели маленькие, накладные расходы минимальны) |
| Агент (многошаговый) | Хэш системного промпта, хэш конфигурации инструментов |
| MoE | Детерминированная маршрутизация, квантование, батч 1 |
| Аудио (класс Whisper) | Квантование, язык, задача (транскрипция или перевод) |
Артефакт проверки несёт хэш контекста, покрывающий системный промпт, историю диалога и сообщение пользователя, рядом с хэшем модели и параметрами генерации. Проверяющий сверяет этот хэш до всякого пересчёта: если контекст не совпал, сравнение падает сразу и вычисления не тратятся.
Куда это встраивается
Каноническая спецификация - то, что делает перепроверку осмысленной. Без неё расхождение могло бы означать и мошенничество, и просто другой бэкенд внимания, а различить это сеть бы не смогла. Как проходит перепроверка, описано в статье Проверка инференса, про два уровня читайте в Гетерогенном майнинге, а как владелец задаёт эти значения - в Конфигурации задачи.