Вызов from_pretrained("google/gemma-3-4b-it") возвращает то, на что сейчас указывает ветка main в репозитории. Это движущаяся мишень. У Gemma она сдвигалась по причинам, которые напрямую меняют поведение модели: правки чат-шаблона, исправления токенизатора, перезалитые веса. Если не зафиксировать версию, однажды ваши оценки перестанут сходиться с прошлыми прогонами — без единой строчки изменений в вашем коде.
Что именно меняется, когда вы следите за main
Репозиторий модели на Hugging Face — это git-репозиторий. Ветка main здесь ничем не отличается от любой другой. Как только Google пушит коммит, все, кто тянет модель без указания revision, получают её при следующем холодном старте. И это не косметика:
| Файл | Что меняется | Чем это грозит |
|---|---|---|
| tokenizer_config.json | Чат-шаблон (chat template) | Меняется точный текст, который получает модель, — а значит, и её ответы |
| generation_config.json | Набор стоп-токенов | Меняется момент, когда генерация завершается |
| config.json | Архитектурные значения: sliding window, лимит позиций | Меняется контекстное окно и поведение при длинных входах |
| safetensors-шарды | Перезалитые веса | Меняются сами параметры модели — тихо, без предупреждения |
Ни одно из этих изменений само себя не объявляет. Результаты на бенчмарках плывут, эталонные ответы перестают совпадать, а дифф лежит в чужом репозитории. Пиннинг превращает это в осознанное решение.
Найдите коммит, на котором вы сейчас находитесь
Прежде чем закрепляться на «хорошей» ревизии, выясните, какую именно вы уже используете. Иначе вы рискуете не сохранить поведение, а изменить его. Репозитории Gemma закрыты, поэтому сначала авторизация:
hf auth login
Затем узнайте, на что сейчас указывает main:
from huggingface_hub import model_info; print(model_info("google/gemma-3-4b-it").sha)
Если модель уже лежит в локальном кеше, прочитайте хэш именно того коммита, который у вас есть, а не того, что сейчас на сервере. Они расходятся как раз тогда, когда это важно:
from huggingface_hub import scan_cache_dir; print([r.commit_hash for r in scan_cache_dir().repos if r.repo_id == "google/gemma-3-4b-it"])
Пиннуйте каждый загрузчик, а не только модель
Самая частая ошибка — закрепить веса и забыть про токенизатор. Получается худшая комбинация: параметры зафиксированы, а чат-шаблон плавает. Передавайте revision во все вызовы from_pretrained, которые касаются репозитория.
Вынесите хэш в одно место, а не в каждый вызов:
MODEL_ID = "google/gemma-3-4b-it"; REVISION = "0f1e2d3c4b5a69788796a5b4c3d2e1f0a9b8c7d6"
И грузите токенизатор, процессор (если чекпоинт мультимодальный) и модель по одной ревизии:
tok = AutoTokenizer.from_pretrained(MODEL_ID, revision=REVISION)
proc = AutoProcessor.from_pretrained(MODEL_ID, revision=REVISION)
model = AutoModelForCausalLM.from_pretrained(MODEL_ID, revision=REVISION)
Для контейнеров или air-gapped окружений скачивайте ревизию как единое целое на этапе сборки и указывайте рантайму на полученную директорию. В CI полезно запретить свободную загрузку: простой grep, который падает, если в from_pretrained нет revision, — этого достаточно, чтобы поймать вызов, который кто-то добавит через полгода.
Используйте полный 40-символьный SHA, а не тег. Теги — это тоже перемещаемые ссылки, они наследуют ту же проблему. Хэш привязан к содержимому, его нельзя переставить.
Рядом с пином модели должны стоять ещё два пина. Первый — библиотека: Gemma 3 требует достаточно свежий transformers, чтобы знать архитектуру. Слишком старый стек упадёт на загрузке — это хороший случай. Плохой — когда новая версия библиотеки меняет дефолты в процессоре или реализации внимания, и ваши закреплённые веса работают уже по-другому. Пиннуйте библиотеку вместе с ревизией.
Второй — сам процесс скачивания. Если делать его на этапе сборки образа, а не при старте контейнера, артефакт запекается, при старте нет сетевых запросов, а авария на хабе не остановит масштабирование. Заодно авторизация из-за лицензии происходит один раз в контролируемом месте, а не на каждой ноде.
Проверьте и запишите ваш пин
Хорошо добавить проверку при старте, чтобы неправильно настроенное окружение падало громко, а не молча обслуживало другую модель:
import hashlib; print(hashlib.sha256((tok.chat_template or "").encode()).hexdigest()[:16])
Логируйте хэш шаблона, список eos-токенов и максимальную позицию при каждом прогоне. Когда оценка поедет, вы за секунды поймёте, двигалась ли модель. Запишите ревизию и к лицензионным документам: условия привязаны к конкретному артефакту, и знать, какой именно артефакт вы использовали, — часть ответа на возможные вопросы.
Как обновлять пин осознанно
Пин — это не решение никогда не обновляться. Это решение, что обновление — событие с диффом. Цикл короткий:
- Сравните свой хэш с текущим main.
- Прочитайте историю коммитов репозитория. Изменение шаблона или generation_config требует полной оценки; правка README — нет.
- Прогоните оценочный набор на обеих ревизиях до переключения. Если токенизатор менялся, перемеряйте количество токенов.
- Обновите константу, деплойте, а в сообщении коммита оставьте предыдущий хэш, чтобы откат был правкой одной строки, а не расследованием.
Разумный ритм — проверять движение наверху по расписанию, а не реагировать на него. Еженедельная задача сравнивает ваш пин с main и открывает issue при расхождении. Так вы узнаёте о правке шаблона от джобы, а не от пользователя.
Та же дисциплина касается производных артефактов: квантованных версий, экспортов ONNX, дообученных адаптеров. Все они неявно зависят от базовой ревизии, но не записывают её. Пишите базовый хэш в метаданные или имя файла при сборке. Год спустя эта строка — разница между ответом за пять минут и потерянным днём.
Ничто из этого не специфично для Gemma. Каждая open-weight семья живёт в изменяемом репозитории, и дисциплина одна на всех. Просто у Gemma шаблон и конфигурация генерации уже правились наверху, так что цена отсутствия пина — конкретная, а не теоретическая. Одна привычка, которую стоит взять из этого текста: константа в начале модуля — id модели и полный хэш коммита в одном месте, и каждый загрузчик читает её.
Комментарии (0)
Войдите, чтобы комментировать.
Пока нет комментариев. Будьте первым.