Мы добавляем поддержку эффективного запуска моделей GGUF в transformers, чтобы вы могли использовать чекпоинты, размер которых подходит под объем памяти вашего ноутбука, через привычные API transformers. Выберите GGUF на Hub, загрузите его с помощью from_pretrained и начните генерацию на собственном устройстве.
Запуск моделей ИИ на ноутбуке стал намного проще, и llama.cpp сыграла в этом большую роль. Ее движок инференса обеспечивает работу таких локальных ИИ-инструментов, как Ollama, LM Studio и Jan. Наряду с такими проектами, как MLX, она помогла сделать локальный инференс практичным выбором для повседневного использования.
Недавний пример того, как ощущается локальный ИИ:
Вот где мы находимся прямо сейчас. И я не буду врать, это выглядит довольно волшебно 🧙♀️ Qwen3.6 27B работает внутри агента кодирования Pi через Llama.cpp на MacBook Pro. Для нетривиальных задач в кодовых базах @huggingface это очень, очень близко к тому, чтобы догнать последнюю версию Opus в Claude… pic.twitter.com/lsIxLoUneU — Жюльен Шомон (@julien_c) 24 апреля 2026 г.
Вот где мы находимся прямо сейчас. И я не буду врать, это выглядит довольно волшебно 🧙♀️
Qwen3.6 27B работает внутри агента кодирования Pi через Llama.cpp на MacBook Pro
Для нетривиальных задач в кодовых базах @huggingface это очень, очень близко к тому, чтобы догнать последнюю версию Opus в Claude… pic.twitter.com/lsIxLoUneU
GGUF, разработанный командой llama.cpp, — это широко используемый формат для локального инференса. Команда также публикует квантованные чекпоинты под учетной записью ggml-org на Hub. Издатели, такие как Unsloth, LM Studio Community и bartowski, также предоставляют готовые к использованию чекпоинты GGUF с различной степенью квантования, чтобы пользователи могли выбрать версию, подходящую для их машины. Модели GGUF были скачаны миллионы раз.
Мы хотим сделать запуск таких моделей локально с помощью transformers еще проще. Совместимость полезна только тогда, когда модель приятно запускать. Чтобы приблизить производительность к llama.cpp, мы используем ее базовые ядра ggml через библиотеку kernels и снижаем накладные расходы в generate. Наша первоначальная цель — локальный инференс на Apple Silicon, начиная с архитектуры Qwen3.5.
Что такое формат файла GGUF?
GGUF упаковывает веса модели и метаданные, включая информацию о токенизаторе и опциональный шаблон чата, в один файл. Он поддерживает различные уровни квантования, позволяя пожертвовать частью точности ради меньшего объема памяти. Такие варианты, как Q4_K_M, смешивают точность тензоров, используя в основном 4-битные веса, сохраняя при этом критически важные тензоры в более высокой точности.
Вот как квантование влияет на размер файла Qwen3.5-4B от Unsloth:
Мы рекомендуем начать с Q4_K_M, а затем попробовать Q5_K_M или Q6_K, если у вас больше доступной памяти. Более агрессивное квантование может помочь уместить более крупные модели, но компромисс в качестве зависит от модели и задачи. Оцените его на той работе, которую вы действительно хотите выполнять с помощью модели. В документации GGUF на Hub описаны доступные типы квантования.
Загрузка GGUF с помощью transformers
Для начала вам понадобится:
- Mac на базе Apple Silicon.
- Версия PyTorch, поддерживаемая опубликованными сборками ядров ggml-quantization (обычно два последних релиза PyTorch).
- Самая свежая версия transformers (на данный момент ветка main до следующего релиза) и совместимая версия kernels.
Чтобы загрузить модель GGUF, передайте ее model_id на Hub и имя файла в качестве параметра gguf_file в from_pretrained.
Никакой дополнительной настройки не требуется: когда веса остаются упакованными на Metal, transformers автоматически загружает совместимые ядра слоя ggml/Metal и использует ggml-org/ggml-attn в качестве реализации внимания. Если это ядро не удается получить, модель возвращается к «sdpa» с выдачей предупреждения, и вы всегда можете принудительно выбрать «sdpa», явно передав attn_implementation="sdpa". Дополнительные параметры загрузки см. в документации GGUF.
Это единственный шаг, специфичный для GGUF. Все остальное — это стандартный API transformers:
Без совместимого ядра квантования загрузчик выполняет деквантование модели, что приводит к увеличению потребления памяти.
Без совместимого ядра квантования загрузчик выполняет деквантование модели, что приводит к увеличению потребления памяти.
Обслуживание GGUF с использованием предпочитаемого интерфейса
Вы также можете использовать тот же чекпоинт с помощью transformers serve, который предоставляет API, совместимый с OpenAI:
Аргумент модели использует формат <model_id>:<filename>.gguf: до двоеточия указан репозиторий Hub (unsloth/Qwen3.5-4B-GGUF), а после него — загружаемый файл (Qwen3.5-4B-Q4_K_M.gguf). Это позволяет выбрать конкретное квантование из репозитория, который может содержать несколько вариантов.
Для моделей, чей шаблон чата поддерживает режим размышлений (thinking), добавьте --reasoning off, чтобы отключить его, или --reasoning on, чтобы включить. Значение по умолчанию --reasoning auto следует настройкам шаблона чата по умолчанию. Подробности см. в разделе параметров рассуждений.
Вы можете подключить такой клиент, как Jan или Pi, добавив пользовательского провайдера, совместимого с OpenAI, со следующими настройками:
transformers запускает модель на вашем Mac, в то время как клиент предоставляет интерфейс для общения. Эту же конечную точку могут использовать и другие клиенты, поддерживающие данный API.
Тестирование производительности по сравнению с llama.cpp
Нашим эталоном производительности локального инференса является llama.cpp. Приведенное ниже сравнение сосредоточено на трех чекпоинтах GGUF: небольшой плотной модели, более крупной плотной модели и модели типа «месье экспертов» (Mixture-of-Experts).
Столбцы llama.cpp получены с помощью утилиты llama-bench (сборка 5f55650a7, релиз b10200, бэкенд Metal из ggml 0.18.0), запущенной как llama-bench -m <file> -p 0 -n 128 -r 3, которая сообщает tg128: скорость генерации токенов по 128 декодированным токенам, усредненную по трем повторениям, исключая обработку промпта. Столбец transformers представляет собой generate, генерирующий те же 128 токенов из 12-токенового промпта (лучший результат из трех разогретых запусков), и включает префилл (prefill).
Измерения проводились на MacBook Pro M2 Max, 32 ГБ объединенной памяти, macOS 26.6, PyTorch 2.12.1, kernels 0.17.0, при подключении к сети питания.
Для остальных столбцов:
Transformers близка к llama.cpp для всех трех чекпоинтов. На графике используются те же измерения, что описаны выше; он не подразумевает идентичных условий бенчмарка, поскольку измерение Transformers включает префилл, в то время как llama-bench сообщает пропускную способность только для декодирования.
transformers и llama.cpp
Когда GGML и llama.cpp присоединились к Hugging Face, мы описали их взаимодополняющие роли: llama.cpp обеспечивает основу для локального инференса, в то время как transformers предоставляет основу для определения моделей. Поддержка GGUF сближает эти два направления.
llama.cpp остается нашим рекомендуемым движком, когда вашим приоритетом является эффективный локальный инференс. Его специализированная среда выполнения, управление памятью и широкая аппаратная поддержка созданы именно для этой цели. Эта интеграция предоставляет разработчикам удобный способ работы с теми же чекпоинтами GGUF внутри transformers:
- Экспериментируйте с GGUF в Python и PyTorch. Исследуйте промежуточные активации с помощью хуков (hooks), изменяйте проход модели вперед (forward pass) или создавайте прототипы пользовательских слоев с помощью привычных инструментов PyTorch.
- Оценивайте модели GGUF. Используйте существующие рабочие процессы оценки transformers для измерения качества квантованных чекпоинтов.
- Проверяйте конвертацию GGUF. Для нас как разработчиков загрузка оригинального чекпоинта и его конвертированной версии GGUF в transformers упрощает проверку корректности конвертации весов с учетом ошибки квантования.
- Попробуйте новые идеи декодирования. Используйте пользовательские процессоры логитов и критерии остановки с помощью generate или напишите собственный цикл генерации на Python.
- Выполните дообучение на основе чекпоинта GGUF. Расквантуйте веса и продолжите стандартный рабочий процесс обучения в transformers.
Для последнего случая используйте GgufConfig(dequantize=True):
За пределами GGUF: ядра ggml для большего числа моделей
Более масштабная возможность — перенести производительность ggml на модели, которые не поддерживаются llama.cpp.
Библиотека transformers уже предоставляет реализации этих архитектур на PyTorch. Благодаря ядрам ggml и схемам квантования, доступным в PyTorch, мы можем работать над ускорением поддерживаемых ими операций без предварительной реализации всей модели в llama.cpp. Это особенно полезно для новых архитектур, исследовательских моделей и пользовательских вариантов, для которых никогда не появятся специализированные реализации в llama.cpp.
Эта возможность выходит за рамки самого формата GGUF. Ядро работает с тензорами; ему не нужно, чтобы вся модель поступала из файла GGUF. Те же строительные блоки можно интегрировать в другие модели transformers и рабочие процессы загрузки. Это также открывает путь к другим модальностям: модели компьютерного зрения, аудиомодели и мультимодальные модели могут повторно использовать совместимые ядра внимания, нормализации и матричного умножения без предварительной полной реализации в llama.cpp. Каждая архитектура по-прежнему требует интеграции и валидации; представленные здесь первые примеры GGUF охватывают генерацию текста.
Быстрый локальный инференс с помощью Python и PyTorch
Мы также хотели показать, каких результатов можно добиться, сохраняя модель и цикл генерации на Python. При наличии правильных ядер и эффективного цикла генерации Python и PyTorch способны обеспечить высокую производительность локального инференса. Ядра берут на себя тяжелые вычисления, в то время как цикл генерации загружает GPU работой, избегая ненужной синхронизации.
Наша цель заключалась в том, чтобы сделать отложенное (eager) выполнение быстрым без использования torch.compile. Для интерактивного использования нам требовался быстрый старт и непрерывный поток токенов без пауз на компиляцию или рекомпиляцию при изменении формы входных данных. Две основные составляющие этой работы — сами ядра и функция generate.
Повторное использование ядер Metal от ggml
Ядро — это небольшая программа, выполняющая операцию на GPU. PyTorch предоставляет реализации общего назначения; специализированное ядро может выполнять меньше работы, объединять несколько операций или считывать квантованные веса непосредственно в их сохраненном формате.
Библиотека ядер позволяет нам распространять совместимые сборки ядер Metal от ggml на Hub и вызывать их из transformers. Это привносит функционал ggml в модель PyTorch без замены модели отдельной средой выполнения инференса.
Первые четыре пакета созданы на основе ядер ggml; ядро top-k решает отдельную проблему узкого места в маршрутизации MoE. Вместе они снижают нагрузку на GPU, необходимую для генерации каждого токена.
Чтобы продемонстрировать вклад ядер слоев, мы сравниваем одни и те же упакованные чекпоинты GGUF с ними и без них. Ядро квантования остается включенным в обеих конфигурациях: его отключение также изменило бы представление весов и привело бы к оценке другого компромисса.
Совместная работа CPU и GPU
Более быстрые ядра помогают только тогда, когда у GPU есть работа. Во время генерации CPU планирует операции для GPU и управляет циклом, который производит следующий токен. Чтение результата обратно с GPU может заставить CPU ждать завершения поставленных в очередь операций. Повторение даже небольшого ожидания для каждого токена может заметно снизить пропускную способность.
Два изменения решают эту проблему в generate, что приводит к улучшению для всех моделей transformers (а не только при запущенных файлах GGUF):
- Раннее удаление ненужной маски внимания (#48814). Когда поддерживаемый вход только с декодером не имеет заполнения (padding), его маску заполнения, состоящую из одних единиц, можно удалить в начале генерации. Последующий код внимания больше не должен многократно проверять эту маску, чтобы определить, можно ли ее пропустить. Причинное (causal) внимание при этом сохраняется.
- Отсрочка проверки условия остановки (#47975). На поддерживаемых путях generate асинхронно копирует решение об остановке и использует его на следующем шаге. CPU может продолжать планирование работы, пока работает GPU. Потоковая передача токенов использует тот же подход, а любой лишний шаг после условия остановки удаляется из результата.
Эти изменения улучшают цикл генерации вокруг модели, поэтому их полезность выходит за рамки GGUF. Они дополняют работу над ядрами: ядра снижают стоимость операции, в то время как меньшее количество точек синхронизации позволяет совместить планирование на CPU и выполнение на GPU.
Эти измерения выполняются при включенных ядрах всех слоев; столбцы на графике изолируют изменения в цикле генерации.
Текущие ограничения и следующие шаги
Первоначальная цель — один интерактивный диалог на Apple Silicon. Следует учитывать несколько ограничений:
- Путь упакованного инференса на данный момент работает только с MPS. Импорт GGUF посредством деквантования остается отдельной опцией; поддержка формата файла не означает, что упакованные ядра доступны на каждом устройстве.
- Заполнение (padding) и батчинг все еще требуют доработки. Неупакованные входы выигрывают от описанной выше оптимизации масок. Заполненные батчи не могут использовать тот же короткий путь и могут иметь более низкую производительность. Мы хотим распространить эту работу на generate_batch на MPS.
- Покрытие архитектур ограничено. Упакованный загрузчик в настоящее время охватывает плотные архитектуры и архитектуры MoE Qwen3.5, включая совместимые чекпоинты Qwen3.8. Добавление поддержки других архитектур относительно просто, и мы будем постепенно расширять покрытие.
Если у вас есть модель GGUF, которую вы хотели бы использовать в transformers, откройте issue с указанием чекпоинта и вашего варианта использования. Это поможет нам расставить приоритеты поддержки моделей, которые пользователи запускают локально.
Благодарности
Мы хотели бы поблагодарить Артура Цукера (Arthur Zucker) за инициализацию этой работы и рецензирование всех моих PR, а также Сирила Валле (Cyril Vallez) за PR, связанные с generate. Мы признательны Саяку Полу (Sayak Paul), команде llama.cpp и Бертрану Шевалье (Bertrand Chevalier) за их помощь в интеграции ядер. Мы также благодарим Аритру Рой Гостипати (Aritra Roy Gosthipaty) и Педро Куэнку (Pedro Cuenca) за рецензирование этого поста в блоге, а Лисандра Дебю (Lysandre Debut) за общее руководство проектом.