Представьте себе ситуацию: в основной ветке библиотеки, которой пользуются тысячи разработчиков, скрывается баг. Он не вызывает аварийного завершения программы, не выдает ошибок компиляции и даже не ломает базовую функциональность. Модель просто начинает «видеть» то, чего быть не должно. В случае с архитектурой T5 это означало, что декодер во время обучения мог заглянуть в будущее, подглядывая в ответ, который ему только предстояло предсказать. Этот баг пролежал в коде почти два месяца, пока его не обнаружили случайно при воспроизведении истории коммитов на процессоре. История с UMT5 стала поворотным моментом для команды Hugging Face, заставившим пересмотреть подход к тестированию сложных нейросетевых архитектур.
Библиотека Transformers поддерживает более 750 типов моделей, и объем тестирования здесь огромен: только в основной ветке выполняется более 88 000 тестов на CPU и 200 000 тестов на GPU ежедневно. Однако запускать полные интеграционные тесты с реальными весами моделей на каждом pull request (PR) физически невозможно — это потребовало бы непрерывной загрузки GPU-кластеров. В результате регрессии часто обнаруживаются постфактум, когда код уже попал в основную ветку. Чтобы решить эту проблему, команда разработала новую систему: Model Integration Contracts (MIC), или Контракты интеграции моделей.
В этой статье мы подробно разберем, как работает эта система, почему обычные тесты оказались бессильны перед багом в механизме внимания (attention), как создаются «мини-модели» для тестирования и что это значит для разработчиков, использующих Transformers. Мы рассмотрим технические детали, примеры кода и стратегию, которая позволяет находить тонкие ошибки до того, как они повлияют на работу пользователей.
01Почему баги просачиваются в основную ветку (main)
Чтобы понять масштаб проблемы, нужно взглянуть на архитектуру тестирования Transformers. Тестовый набор включает не только проверку самих моделей, но и пайплайны, обучение, распределенное выполнение, квантование и ядра внимания. Интеграционные тесты загружают реальные чекпоинты (сохраненные веса моделей) и проверяют их API на реальном оборудовании. Это самый надежный способ убедиться, что модель работает так, как задумано, но и самый ресурсоемкий.
Запуск всех этих тестов на каждом изменении кода (PR) означал бы, что GPU-инстансы заняты весь день. Это непрактично с точки зрения затрат и времени. Поэтому команда полагается на периодические запланированные запуски. Но между моментом внесения изменений и моментом проверки может пройти время. Если регрессия возникает, она уже может оказаться в основной ветке (main), прежде чем система успеет её обнаружить.
Классический пример — внедрение масштабированного скалярного произведения внимания (Scaled Dot-Product Attention, SDPA) для модели T5 30 июля 2026 года. Это изменение улучшило производительность, но имело побочный эффект: декодер UMT5 получил возможность обращаться к будущим токенам. Во время обучения модель могла «подглядывать» в ответ. Ничего не упало, ошибки не было, и баг оставался в main почти два месяца. Лишь когда команда начала воспроизводить историю коммитов для отладки, небольшая модель UMT5, запущенная на CPU, начала сигнализировать об аномалиях в каждом коммите. Этот инцидент стал катализатором для создания новой системы тестирования.
02Подход через уменьшение модели: создание фикстур
Стратегия, которую выбрала команда Hugging Face, заключается не в упрощении тестов, а в упрощении модели. Идея состоит в том, чтобы создать «фикстуру» (fixture) — уменьшенную версию реальной модели, которая сохраняет все ключевые архитектурные особенности оригинала, но требует значительно меньше вычислительных ресурсов.
Фикстура строится на основе конфигурации реального чекпоинта. В ней сохраняется меньше слоев, а сами слои делаются уже (меньше размерность скрытых состояний), но сохраняются все типы слоев, присутствующие в оригинале. Токенизатор и процессор остаются неизменными, чтобы тестировать полный конвейер обработки данных. Такая фикстура публикуется один раз и затем многократно переиспользуется. Это позволяет запускать «быстрые интеграционные тесты» на дешевых CPU-инстансах, что делает проверку каждого PR возможной.
Например, в исследовании на CPU экспериментальная фикстура UMT5 занимала всего 66 МБ весов, в то время как исходный чекпоинт весил 1 227 МБ. Этот подход также работает для очень больших моделей, которые физически не помещаются на стандартных GPU-инстансах для тестирования, но их фикстуры легко запускаются на CPU. Важно отметить, что разработчики моделей уже создавали крошечные тестовые модели (так называемые tiny-random-* чекпоинты), но не было единого стандарта. MIC вводит этот стандарт, добавляя проверки, выходящие за рамки простой загрузки и прямого прохода (forward pass). В случае с UMT5 баг прошел бы обычный forward pass без ошибок, так как архитектура была корректной, но логика внимания была нарушена.
03Введение контрактов интеграции моделей (MIC)
Model Integration Contract (MIC) — это предложенный стандарт упаковки тестов для фикстур. Контракт состоит из трех ключевых частей:
- Фикстура (Fixture): Уменьшенная модель, описанная выше. Она публикуется один раз и фиксируется (pinning), чтобы обеспечить воспроизводимость.
- Путь использования (Usage Path): Выполняемый пример на Markdown, демонстрирующий типичное использование модели. Это может быть генерация текста, шаг обучения или другое действие.
- Базовые показатели (Baselines): Записанные выходные данные при запуске этого примера, которые были проверены и одобрены человеком.
Контракт считается выполненным, если запуск пути использования на фикстуре по-прежнему дает результаты, совпадающие с базовыми показателями. Важно понимать, что контракт охватывает архитектуру и путь использования, а не один конкретный чекпоинт. Совместимые чекпоинты могут делить одну фикстуру, но каждый сохраняет свои ожидаемые результаты. Эти контракты публикуются в репозитории huggingface-mic.
Рассмотрим пример контракта для SmolLM. Он генерирует текст по таким подсказкам, как «Столица Франции —», и сравнивает идентификаторы токенов с записанным ответом. После загрузки модели и токенизатора код генерации (упрощенный для одного запроса) выглядит следующим образом:
inputs = tokenizer(
"The capital of France is",
return_tensors="pt"
)
outputs = model.generate(**inputs, max_new_tokens=10, do_sample=False)
new_tokens = outputs[:, inputs["input_ids"].shape[1]:]
print(tokenizer.batch_decode(new_tokens, skip_special_tokens=True))Но MIC делает больше, чем просто сравнение токенов. Он также сравнивает потери при обучении (training loss), проверяет, что градиенты конечны, и verifies, что шаг оптимизатора изменяет веса. Это обеспечивает глубокую проверку корректности модели. Пакетный репозиторий на Hugging Face Hub фиксирует каждый MIC к замороженной ревизии, а также к версиям пакетов, использованным для записи базовых показателей. Каждый запуск CI записывает ревизию пакета, которую он использовал, чтобы обеспечить возможность воспроизведения результатов в будущем.
04Регрессия UMT5: как MIC обнаружил ошибку
Чтобы проверить эффективность новой системы, команда воспроизвела замороженные MIC за пять месяцев истории коммитов Transformers. Маленькая фикстура UMT5 успешно выявила регрессию с момента её появления 30 июля 2026 года до исправления 28 сентября. Логарифмические вероятности (log-probabilities) отличались от проверенной базовой линии на 1.22, а потери при обучении — примерно на 0.20.
Одна деталь имела решающее значение: контракт использовал SDPA, путь внимания по умолчанию. Запуск только варианта внимания eager (жадного) пропустил бы эту ошибку. Фикстура помогает только в том случае, если она проходит через тот же код, что и реальный чекпоинт. Это подчеркивает важность точного соответствия путей выполнения кода.
Затем команда отменила исправление в доказательной ветке в CI Transformers. Проверка дала сбой с теми же различиями, а шаг выполнения выбранного контракта T5 занял всего 13.4 секунды на CPU, без учета настройки. Это демонстрирует высокую эффективность системы: быстрая проверка, которая находит серьезные логические ошибки.
05Как модели уменьшаются: рецепт создания фикстур
Первоначальный рецепт был простым: сделать размерности меньше и оставить меньше слоев. Но этого оказалось недостаточно для смешанных архитектур. Если оставить два слоя, это бесполезно, если оба используют скользящее внимание (sliding attention), а слои с полным вниманием исчезают. Теперь рецепт состоит из четырех шагов:
- Уменьшение конфигурации. Начните с реального чекпоинта и уменьшите размеры скрытых состояний, головы внимания и глубину. Сохраните разные типы слоев, включая смеси скользящего и полного внимания или плотные и MoE (Mixture of Experts) слои. Некоторые архитектуры требуют дополнительных правил для совместимости компонентов. Также смотрят на собственные тесты модели в Transformers:
ModelTesterв файлеtest_modeling_уже вручную выбирает маленькую конфигурацию, поэтому берутся её размеры для любой ширины, которую общее правило не знает по имени..py - Сохранение предобработки. Сохраняйте словарь, специальные токены и входные размеры, копируйте файлы токенизатора и процессора побайтово. Загрузка и предобработка — это часть того, что мы хотим протестировать.
- Построение и валидация весов. Попробуйте случайные веса с фиксированным сидом и измените входы, чтобы проверить, реагирует ли модель. Если нет, попробуйте обучить её на небольшом наборе примеров из контракта. Перезагрузите сохраненную модель и проверьте, что выходные данные, потери и градиенты конечны. Отклоняйте неудачные сборки.
- Заморозка и запись. Сохраните принятые веса и измерьте воспроизводимые выходные данные на известной хорошей сборке Transformers. Проверьте базовые показатели для каждой поддерживаемой платформы и точности, затем опубликуйте зафиксированный снимок. CI переиспользует его; он не перестраивает фикстуру для каждого PR.
Мы также сохраняем исходный формат файла весов. В противном случае мы бы пропустили код конвертации, который запускается, когда пользователь загружает реальный чекпоинт. Полный рецепт содержит больше деталей. Отчет по уменьшению Llama 4 Scout показывает, как это выглядит на большой модели: 108.6 миллиарда параметров становятся 44.7 миллионами. Визуальный стек уменьшается с 34 слоев до 2, а языковой стек — с 48 до 4, сохраняя проверенные типы слоев и стиль маршрутизации MoE.
06Построение MIC с помощью агентов
Команда разработала CLI-инструмент tmic, который создает контракт и строит фикстуру. Для новой модели LLM (Large Language Model) черновиком выступает код использования и манифест, а запуски на CPU и GPU измеряют кандидатные базовые показатели. LLM чернует, но не утверждает. Измененные ожидания требуют проверки человеком.
Чтобы попробовать это на своей машине, используйте свой исходный чекпоинт вместо org/model:
pip install "transformers-mic[runtime]" "hf-doc-builder @ git+https://github.com/huggingface/doc-builder.git"
hf auth login
tmic run org/model --local-only --fixtures-only --no-history --bill-to ''Эта команда черновик контракта, строит фикстуру и записывает её базовые показатели на вашей машине, спрашивая вас о проверке каждого шага, и останавливается перед загрузкой чего-либо. Для новой модели черновик создается LLM через Inference Providers, оплачиваемый с вашего собственного аккаунта (--bill-to ''). Документация CLI охватывает отдельные шаги. Команда использовала агентов для создания MIC across model families. Когда они сталкивались с крайним случаем, они исправляли сам рецепт, а не одну фикстуру, с помощью экспертов по моделям. Опубликованные модели и оставшиеся пробелы находятся в пространстве покрытия (coverage space).
07Случайные веса против переобучения (Overfit)
Случайные веса не всегда обеспечивают достаточную чувствительность. Например, с случайными весами фикстура Whisper едва реагировала на изменения в аудио. Она работала, но была плохим тестом для аудио-пути. Поэтому её обучили на нескольких тонах, сопоставленных со словами, такими как «красный» и «зеленый». Мы не учили её распознаванию речи, а просто делали изменения аудио видимыми в её выводах.
В исследовании инициализации весов случайные фикстуры Whisper поймали 18 из 24 внедренных сбоев. Переобученные фикстуры поймали все 24. Это дает два способа построения весов:
- Начните со случайных весов и фиксированного сидa.
- Переобучитесь на нескольких примерах, например, «Столица Франции —» => «Париж».
Результат Whisper не устанавливает, какой из них лучше. Это были синтетические сбои, и мы не нашли реальной регрессии, пойманной только версией с переобучением. Обе версии пропустили ошибку вспомогательного декодирования, которую выявил реальный чекпоинт Whisper. Поэтому мы сохраняем случайные веса, когда они проходят проверки, и переобучаемся, когда нам нужна лучшая чувствительность или читаемые ответы. Обучение занимает секунды, но это еще один шаг, который может не сойтись, и еще одна вещь, которую нужно поддерживать. Сравнение содержит результаты для обоих вариантов.
08Открытые вопросы и будущее
По состоянию на 1 ноября 2026 года задача MIC в CI Transformers сообщает об ошибках, но не блокирует PR. Блокировка зависит от вещей, которые мы еще не измерили: сколько реальных ошибок она ловит на PR, а не только в воспроизведениях? Как часто она заставляет нас гоняться за ложными срабатываниями? Сколько работы занимает проверка базовых показателей? Мы также не знаем, сколько ошибок, таких как ошибка вспомогательного декодирования Whisper, проявляются только с реальными весами, или ловит ли переобучение реальные ошибки, которые пропускают случайные веса.
Покрытие все еще частичное, по семействам моделей и API, которые используют люди. Когда регрессия проскальзывает, мы можем добавить недостающий путь использования и воспроизвести его на сломанной и исправленной версиях. Мы будем сохранять существующие тесты, пока их покрытие не будет учтено. Наконец, мы хотели бы связать оригинальные страницы моделей Hub с их MIC, чтобы разработчик или агент, использующий чекпоинт, мог начать с примера, протестированного на этом чекпоинте, в его среде и с ожидаемыми выводами.
09Что это значит на практике
Для разработчиков, использующих Hugging Face Transformers, внедрение Model Integration Contracts означает более стабильную и надежную библиотеку. Хотя вы не будете напрямую взаимодействовать с MIC каждый день, вы получите выгоду от более тщательного тестирования новых функций и архитектур. Если вы разрабатываете новую модель или вносите изменения в существующую, рекомендуется:
- Использовать фикстуры для локального тестирования. Создайте уменьшенную версию вашей модели, чтобы быстро проверять изменения без загрузки огромных весов.
- Проверять разные пути внимания. Убедитесь, что ваши тесты покрывают как SDPA, так и eager attention, чтобы избежать ошибок, подобных UMT5.
- Воспроизводимость. Фиксируйте версии пакетов и окружения, чтобы обеспечить воспроизводимость результатов, как это делает система MIC.
- Участие в сообществе. Если вы видите модель, которая не покрыта MIC, попробуйте создать контракт с помощью
tmicи внесите вклад в улучшение покрытия библиотеки.
Система MIC — это не просто техническое улучшение, это сдвиг в культуре тестирования. Она показывает, что даже самые сложные модели можно эффективно тестировать, если правильно подойти к выбору инструментов и методов. И хотя система еще находится в стадии развития, её потенциал для предотвращения будущих инцидентов огромен.
huggingface-mic и документацией CLI, чтобы быть в курсе новых возможностей и улучшенных рецептов создания фикстур.В заключение, история с UMT5 и последующее внедрение MIC демонстрируют зрелость подхода Hugging Face к обеспечению качества. Вместо того чтобы полагаться на удачу или ресурсоемкие тесты, они создали элегантное решение, которое балансирует между скоростью, точностью и масштабируемостью. Для всех, кто работает с большими языковыми моделями, это важный шаг в сторону более надежного и предсказуемого машинного обучения.
Источник: Hugging Face ↗