Контракты интеграции моделей в Transformers

Источник: Hugging Face•

Контракты интеграции моделей в Transformers

Мы стремимся развивать и демократизировать искусственный интеллект с помощью открытого исходного кода и открытой науки.

30 июля 2026 года в Transformers было включено масштабированное точечное внимание PyTorch (SDPA) для T5. В качестве побочного эффекта декодер UMT5 получил возможность обращаться к будущим токенам. Во время обучения модель могла подсматривать ответ, который должна была предсказать. Ничего не упало, и баг оставался в ветке main почти два месяца.

Когда позже мы воспроизвели эти коммиты, небольшая модель UMT5, работающая на CPU, выявила проблему в каждом из них. Эта статья посвящена той модели и тестам, созданным вокруг нее.

Почему баги попадают в main

Transformers поддерживает более 750 типов моделей, и набор тестов велик: более 88 000 тестов для CPU в ветке main плюс более 200 000 тестов для GPU при ежедневном запуске. Тесты моделей — это лишь часть: мы также тестируем пайплайны, обучение, распределенное выполнение, квантование и ядра внимания.

Интеграционные тесты загружают реальные чекпоинты и проверяют API модели на «железе». Запуск всего этого при каждом PR потребовал бы постоянной загрузки множества GPU, что непрактично. К тому времени, когда плановый запуск обнаружит регрессию, она уже может оказаться в main.

Наш подход заключается в уменьшении модели. Мы создаем фикстуру: небольшую модель на основе конфигурации реального чекпоинта, с меньшим количеством и меньшей шириной слоев, но включающую каждый их тип, а также неизменные файлы токенизатора и процессора. Она публикуется один раз, а затем используется повторно. Мы запускаем для нее «быстрые интеграционные тесты» на недорогом раннере CPU. В нашем исследовании CPU экспериментальная фикстура UMT5 весила 66 МБ по весам, тогда как исходный чекпоинт — 1227 МБ.

Это также охватывает очень большие модели: некоторые из них не помещаются на наших стандартных раннерах GPU, но их фикстуры запускаются на CPU.

Интеграторы моделей уже создают крошечные тестовые модели (чекпоинты tiny-random-* в Transformers). Мы хотели получить общий рецепт и проверки, которые выходят за рамки простой загрузки модели и прямого прогона (forward pass). Баг в UMT5 успешно прошел бы прямой прогон.

Фикстуры не заменят полноценные интеграционные тесты, но в PR они дают нам шанс обнаружить баги до того, как они попадут в main.

Представляем контракты интеграции моделей

transformers-mic — это предлагаемый стандарт для упаковки таких тестов. Контракт интеграции модели (MIC) состоит из трех частей:

  • фикстура: описанная выше уменьшенная модель, опубликованная один раз и зафиксированная (pinned)
  • путь использования (usage path): исполняемый пример на Markdown, показывающий типовые сценарии работы с моделью, такие как генерация текста или шаг обучения
  • базовые показатели (baselines): результаты, записанные при выполнении этого примера и проверенные человеком

Контракт считается выполненным, если запуск пути использования на фикстуре по-прежнему дает базовые показатели.

Контракт охватывает архитектуру и путь использования, а не отдельный чекпоинт: совместимые чекпоинты могут использовать общую фикстуру, сохраняя при этом собственные ожидаемые результаты. Мы публикуем их в huggingface-mic.

Например, контракт SmolLM генерирует текст по промптам вроде «Столица Франции —» и сравнивает свои ID токенов с записанным ответом. После загрузки модели и токенизатора код генерации (упрощенный до одного промпта) выглядит так:

Он также сравнивает потери при обучении (training loss), проверяет конечным ли является градиент и подтверждает, что шаг оптимизатора изменяет веса. Смотрите полный usage.md.

Датасет флота (fleet dataset) на Hub привязывает каждый MIC к замороженной ревизии вместе с версиями пакетов, использованных для записи его базовых показателей. Каждый запуск CI записывает ревизию флота, которая использовалась, чтобы мы могли воспроизвести ее позже.

В PR мы выбираем MIC на основе файлов, измененных в патче.

Регрессия в UMT5

Мы воспроизвели замороженные MIC на пяти месяцах коммитов Transformers. Маленькая фикстура UMT5 выявляла регрессию с момента ее появления в July 30, 2026 и до исправления в September 28. Логарифмы вероятностей меток (log-probabilities) отличались от проверенного базового значения на 1.22, а потери при обучении — примерно на 0.20.

Одна деталь имела значение: в контракте использовалось SDPA — путь внимания по умолчанию. Запуск только варианта eager attention позволил бы пропустить баг. Фикстура помогает только тогда, когда она проходит через тот же код, что и реальный чекпоинт.

Затем мы откатили исправление в тестовой ветке (proof branch) в CI Transformers. Проверка завершилась ошибкой с теми же отклонениями, а шаг раннера для выбранного контракта T5 занял на CPU 13.4 секунды без учета настройки.

Результаты воспроизведения и демо CI содержат измерения и детали воспроизведения.

Как уменьшаются модели

Первый рецепт был прост: уменьшить размерности и сократить количество слоев. Этого оказалось недостаточно для смешанных архитектур. Оставлять два слоя бесполезно, если оба используют скользящее внимание (sliding attention), а слои с полным вниманием исчезают.

Теперь рецепт состоит из четырех шагов:

  • Уменьшить конфигурацию. Начните с реального чекпоинта и сократите скрытые размеры (hidden sizes), головы внимания и глубину. Сохраните различные типы слоев, включая комбинации скользящего и полного внимания или плотные (dense) слои и слои MoE. Некоторым архитектурам требуются дополнительные правила для сохранения совместимости компонентов. Мы также смотрим собственные тесты моделей в Transformers: ModelTester в test_modeling_<model>.py уже вручную выбирает небольшую конфигурацию, поэтому мы берем его размеры для любой ширины, которую наше общее правило не знает по имени.
  • Оставить предобработку неизменной. Сохраните словарь, специальные токены и размерности входных данных, а также побайтово скопируйте файлы токенизатора и процессора. Загрузка и предобработка — это часть того, что мы хотим протестировать.
  • Создать и проверить веса. Попробуйте использовать случайно инициализированные веса с фиксированным сидом (seeded random weights) и измените входные данные, чтобы проверить реакцию модели. Если она не реагирует, попробуйте обучить ее на небольшом батче примеров из контракта. Перезагрузите сохраненную модель и проверьте, являются ли выходные данные, потери и градиенты конечными. Отвергайте неудачные сборки.
  • Заморозить и записать. Сохраните принятые веса и измерьте воспроизводимые результаты на заведомо исправной сборке Transformers. Проверьте базовые показатели для каждой поддерживаемой платформы и точности, затем опубликуйте закрепленный снимок (pinned snapshot). CI использует его повторно; он не пересобирает фикстуру для каждого PR.

Мы также сохраняем исходный формат файла весов. В противном случае мы бы пропустили код конвертации, который запускается, когда пользователь загружает реальный чекпоинт. Полный рецепт содержит более подробную информацию.

Llama 4 Scout shrink report показывает, как это выглядит на большой модели. 108.6 миллиарда параметров превращаются в 44.7 миллиона. Визуальный стек сокращается с 34 слоев до 2, а языковой — с 48 до 4, сохраняя проверяемые типы слоев и стиль маршрутизации MoE.

Создание MIC с помощью агентов

Наш CLI, tmic, создает контракт и собирает фикстуру. Для новой модели LLM набрасывает код использования и манифест, а запуски на CPU и GPU измеряют базовые показатели-кандидаты. LLM делает черновик, но не утверждает его. Измененные ожидания требуют проверки человеком.

Чтобы протестировать это на своем компьютере, используйте исходный чекпоинт вместо org/model:

Он создает проект контракта, собирает фикстуру и записывает ее базовые показатели на вашем компьютере, прося вас проверять каждый шаг, и останавливается перед загрузкой чего-либо. Для новой модели черновик создается LLM через Inference Providers с оплатой с вашего собственного аккаунта (--bill-to ''). Документация по CLI описывает отдельные шаги.

Мы использовали агентов для создания MIC для различных семейств моделей. Когда они сталкивались с краевыми случаями, мы исправляли сам рецепт, а не отдельную фикстуру, при поддержке экспертов по моделям. Опубликованные модели и оставшиеся пробелы представлены в пространстве покрытия.

Случайные веса против переобучения (Random vs Overfit)

С со случайными весами наша тестовая конфигурация Whisper почти не реагировала на изменения в аудио. Она работала, но это делало ее плохим инструментом для проверки аудиотракта.

Поэтому мы обучили ее на нескольких тонах в паре со словами вроде «красный» и «зеленый». Мы не учили ее распознаванию речи, а лишь делали изменения в аудио заметными в ее выходных данных. В нашем исследовании инициализации весов случайные конфигурации Whisper обнаружили 18 из 24 внедренных сбоев. Переобученные (overfit) конфигурации обнаружили все 24.

Это дает нам два способа создания весов:

  • Начать со случайных весов и фиксированного начального числа (seed).
  • Переобучить на нескольких примерах, например «Столица Франции —» => «Париж».

Результат Whisper не дает однозначного ответа на вопрос, какой вариант лучше. Это были синтетические сбои, и мы пока не обнаружили реальной регрессии, которую поймала бы только переобученная версия. Обе версии пропустили баг с вспомогательным декодированием (assisted-decoding), который выявила настоящая контрольная точка (checkpoint) Whisper.

Поэтому мы используем случайные весы, когда они проходят проверки, и переобучение, когда нам нужна большая чувствительность или понятные ответы. Обучение занимает секунды, но это еще один шаг, который может не сойтись, и еще одна вещь, которую нужно обслуживать. В приведены результаты для обоих вариантов.

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

По состоянию на 1 ноября 2026 года задача MIC в CI Transformers сообщает о сбоях, не блокируя PR. Должна ли она блокировать PR, зависит от факторов, которые мы еще не измерили:

  • Сколько реальных багов она ловит в PR, а не только при повторном воспроизведении?
  • Как часто она заставляет нас гоняться за ложными тревогами?
  • Сколько усилий требуют проверки базовых показателей (baselines)?

Мы также не знаем, сколько багов, подобных багу со вспомогательным декодированием в Whisper, проявляются только с реальными весами, и способно ли переобучение поймать реальные баги, которые пропускают случайные весы.

Покрытие все еще частичное и охватывает не все семейства моделей и используемые людьми API. Когда регрессия проскальзывает, мы можем добавить недостающий путь использования и воспроизвести его на сломанной и исправленной версиях. Мы сохраним существующие тесты, пока их покрытие не будет учтено.

Наконец, мы хотели бы связать исходные страницы моделей на Hub с их MIC, чтобы разработчик или агент, использующий контрольную точку, мог начать с примера, протестированного на этой контрольной точке, ее окружении и ожидаемых выходных данных.

Хотите помочь? Выберите не покрытую тестами модель из области покрытия, попробуйте рабочий процесс tmic и внесите свой вклад, добавив путь использования или проверив сгенерированный контракт.

О чём эта статья

Ещё в разделе «AI и машинное обучение»

Все →

Ещё от Hugging Face