Зачем вообще это нужно? Проблема тупого квантования
Берешь модель в 20 миллиардов параметров, запускаешь стандартное INT4 квантование через mlx-lm и ждешь чуда. А получаешь модель, которая путает Париж с перитонитом. Знакомая история? Стандартные методы квантования обращаются со всеми слоями нейросети одинаково — как солянкой в столовой. Льют один и тот же соус и на чувствительные слои внимания, и на простые линейные проекции. Результат — катастрофическая деградация качества, о которой мы уже писали.
На Mac с M4 или M5 это особенно больно. Unified Memory не безгранична, а запускать полноразмерную Qwen3-30B в FP16 — все равно что отапливать улицу. Нужно сжимать. Но как сжать умно?
oQ: инструмент, который слышит вашу модель
oQ (optimal Quantization) — это не очередной скрипт для конвертации весов. Это data-driven система, которая решает, какие слои квантовать сильно, а какие оставить в относительно высоком precision. Она не гадает. Она анализирует.
Как это работает? Магия на калибровочных данных
Инструмент берет вашу модель в FP16 и прогоняет через нее калибровочный датасет (например, 128 случайных текстовых промптов). Он не просто измеряет активации. Он оценивает чувствительность каждого слоя к квантованию. Слой, выход которого резко меняется при округлении весов, получает больше бит (например, Q6_K). Слой, который терпимо относится к сжатию, ужимается до Q2_K. На выходе — гибридная модель со смешанной точностью.
Ставим и запускаем за пять минут
Никакого шаманства с компиляцией LLVM. Все через pip и Python 3.11+.
pip install oq-quant
pip install mlx-lm>=0.9.0Проверяем, что установилось:
python -c "import oq; print(oq.__version__)"Если видите 2.1.0 или выше — можно работать.
Сердце процесса: калибровка и квантование
Вот где oQ показывает свою силу. Процесс делится на два этапа: сбор чувствительности и само квантование.
1Сбор метрик чувствительности
Создаем простой Python-скрипт. Не нужно городить конфиги в YAML.
from oq import SensitivityAnalyzer
from transformers import AutoTokenizer
import mlx.core as mx
# Загружаем модель и токенизатор
model_id = "Qwen/Qwen3-14B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
# Инициализируем анализатор с целевым размером (например, 8GB)
analyzer = SensitivityAnalyzer(model_id, target_size_gb=8.0)
# Загружаем или генерируем калибровочные данные
calibration_data = ["Explain quantum computing", "Write a python function", ...] # 128 промптов
# Запускаем анализ
sensitivity_report = analyzer.analyze(calibration_data, tokenizer)
# Сохраняем отчет
sensitivity_report.save("qwen14b_sensitivity.json")Инструмент сам определит, какие слои важны для ваших данных. Если калибровать на кодек, он будет бережнее относиться к слоям, отвечающим за логику. Если на поэзию — к тем, что работают с семантикой.
2Запуск mixed-precision квантования
Теперь, с отчетом в руках, квантуем.
oq quantize \
--model qwen3-14b-instruct \
--sensitivity-report qwen14b_sensitivity.json \
--output qwen3-14b-oq-mixed \
--bits-config "{ 'default': 4, 'sensitive_layers': [6, 8] }" \
--calibrateФлаг --calibrate говорит oQ использовать сохраненные данные для точной настройки квантовых масштабов. Без него вы получите простое равномерное квантование — а зачем тогда все это?
Не путайте калибровку для анализа чувствительности и калибровку для масштабов! Первая — для выбора битности, вторая — для точного расчета параметров квантования. oQ делает и то, и другое, если передать оба флага.
Что в сухом остатке? Сравниваем с аналогами
На бумаге все инструменты решают одну задачу. На практике разница — как между скальпелем и топором.
| Инструмент / Метод | Подход | Качество (vs FP16) | Скорость инференса на M4 Pro | Главная боль |
|---|---|---|---|---|
| oQ (data-driven mixed) | Анализ чувствительности слоев + калибровка | 98-99% | ~45 токенов/с (Qwen3-14B) | Требует времени на анализ |
| Стандартное mlx-lm INT4 | Равномерное квантование всех весов | 92-95% | ~55 токенов/с | Деградация на сложных задачах |
| Unsloth Dynamic 2.0 | Эвристический выбор слоев для квантования | 96-97% | ~50 токенов/с | Меньшая гибкость под данные |
| NanoQuant (экстремальное сжатие) | Агрессивное квантование с низкой битностью | 85-90% | ~65 токенов/с | Качество падает на рассуждениях |
Видите тренд? Самые быстрые методы жертвуют качеством. oQ жертвует скоростью подготовки, но сохраняет разум модели. В итоге вы получаете модель, которая не превращается в овощ после квантования.
Кому oQ подойдет идеально, а кому — нет
Это не серебряная пуля. Инструмент требует понимания процесса и немного времени.
- Идеально для: исследователей, которые тестируют модели на Mac перед развертыванием; разработчиков, которым нужно запустить конкретную LLM для своих данных (код, документация, медицинские тексты) с минимальными потерями; всех, кто устал от сюрпризов после квантования и хочет контролируемый процесс.
- Не подойдет: тем, кому нужно сжать модель за пять секунд и запустить; тем, кто работает исключительно с моделями < 7B параметров (там проще равномерное квантование); фанатам экстремальной скорости, готовым жертвовать осмысленностью ответов.
Если вы выбираете оптимальную локальную LLM для Mac, то с oQ вы сможете выжать из нее максимум памяти без превращения в бесполезный скрипт.
Финал: что делать после квантования?
Запустили модель. Получили приемлемую скорость и качество. Не останавливайтесь на этом. Обязательно прогнать ее на релевантных бенчмарках — не только на общих, но и на тех, что отражают вашу задачу. oQ позволяет перекалибровать модель под новые данные. Собрали корпус юридических документов? Запустите анализ чувствительности на них и переквантуйте. Модель станет лучше понимать конкретный домен.
И последний совет, который редко дают: не бойтесь оставлять некоторые слои в FP16. Да, это съедает память. Но если слой отвечает за критически важные операции (например, механизм внешней памяти в архитектуре RAG), его квантование до Q2_K может развалить всю систему. oQ как раз помогает найти эти точки уязвимости. Используйте эту информацию, даже если не будете применять сам инструмент.