Перейти к основному содержимому

Запуск локальных LLM на Mac

Это руководство проведёт вас через запуск локального LLM-сервера на macOS с OpenAI-совместимым API. Вы получите полную конфиденциальность, нулевые затраты на API и удивительно хорошую производительность на Apple Silicon.

Мы рассматриваем два бэкенда:

БэкендУстановкаЛучше всего вФормат
llama.cppbrew install llama.cppСамое быстрое время до первого токена, квантованный KV-кэш для низкого потребления памятиGGUF
omlxomlx.aiСамая быстрая генерация токенов, нативная оптимизация MetalMLX (safetensors)

Оба предоставляют OpenAI-совместимую конечную точку /v1/chat/completions. VibeOS работает с любым из них — просто укажите http://localhost:8080 или http://localhost:8000.

Только Apple Silicon

Это руководство предназначено для Mac с Apple Silicon (M1 и новее). Intel Mac будут работать с llama.cpp, но без ускорения GPU — ожидайте значительно более низкой производительности.


Выбор модели​

Для начала мы рекомендуем Qwen3.5-9B — это сильная модель рассуждений, которая комфортно помещается в 8 ГБ+ унифицированной памяти с квантизацией.

ВариантРазмер на дискеТребуется ОЗУ (контекст 128K)Бэкенд
Qwen3.5-9B-Q4_K_M (GGUF)5,3 ГБ~10 ГБ с квантованным KV-кэшемllama.cpp
Qwen3.5-9B-mlx-lm-mxfp4 (MLX)~5 ГБ~12 ГБomlx

Эмпирическое правило памяти: размер модели + KV-кэш. Модель 9B Q4 занимает ~5 ГБ. KV-кэш при контексте 128K с квантизацией Q4 добавляет ~4-5 ГБ. При стандартном (f16) KV-кэше это раздувается до ~16 ГБ. Флаги квантованного KV-кэша в llama.cpp — ключевой трюк для систем с ограниченной памятью.

Для более крупных моделей (27B, 35B) потребуется 32 ГБ+ унифицированной памяти. Модель 9B — оптимальный выбор для машин с 8-16 ГБ.


Вариант A: llama.cpp​

llama.cpp — это наиболее портативная среда выполнения локальных LLM. На macOS она использует Metal для ускорения GPU «из коробки».

Установка​

brew install llama.cpp

Это даёт вам глобальную команду llama-server.

Загрузка модели​

Вам понадобится модель в формате GGUF. Проще всего загрузить её с Hugging Face через huggingface-cli:

brew install huggingface-cli

Затем загрузите:

huggingface-cli download unsloth/Qwen3.5-9B-GGUF Qwen3.5-9B-Q4_K_M.gguf --local-dir ~/models
Ограниченные модели

Некоторые модели на Hugging Face требуют аутентификации. Если вы получаете ошибку 401 или 404, сначала выполните huggingface-cli login.

Запуск сервера​

llama-server -m ~/models/Qwen3.5-9B-Q4_K_M.gguf \
-ngl 99 \
-c 131072 \
-np 1 \
-fa on \
--cache-type-k q4_0 \
--cache-type-v q4_0 \
--host 0.0.0.0

Вот что означает каждый флаг:

ФлагНазначение
-ngl 99Выгрузить все слои на GPU (Metal). Используйте большое число, чтобы ничего не оставалось на CPU.
-c 131072Размер окна контекста (128K токенов). Уменьшите, если не хватает памяти.
-np 1Количество параллельных слотов. Оставьте 1 для одного пользователя — больше слотов разделяет бюджет памяти.
-fa onFlash attention. Уменьшает использование памяти и ускоряет инференс с длинным контекстом.
--cache-type-k q4_0Квантовать кэш ключей до 4 бит. Это главный экономитель памяти.
--cache-type-v q4_0Квантовать кэш значений до 4 бит. Вместе с предыдущим сокращает память KV-кэша на ~75% по сравнению с f16.
--host 0.0.0.0Слушать на всех интерфейсах. Используйте 127.0.0.1, если не нужен сетевой доступ.

Сервер готов, когда вы видите:

main: server is listening on http://0.0.0.0:8080
srv update_slots: all slots are idle

Оптимизация памяти для систем с ограничениями​

Флаги --cache-type-k q4_0 --cache-type-v q4_0 — самая важная оптимизация для систем с ограниченной памятью. Вот влияние при контексте 128K:

Тип KV-кэшаПамять KV-кэша (контекст 128K, модель 9B)
f16 (по умолчанию)~16 ГБ
q8_0~8 ГБ
q4_0~4 ГБ

На Mac с 8 ГБ используйте KV-кэш q4_0 и выберите модель поменьше, которая всё ещё поддерживает минимальный контекст VibeOS в 64K. На 16 ГБ вы можете комфортно работать с контекстом 128K. На 32 ГБ+ можно запускать более крупные модели или несколько параллельных слотов.

Если памяти всё равно не хватает, уменьшите контекст, но не ниже минимальных 64K VibeOS; в противном случае переключитесь на модель поменьше или более низкую квантизацию (Q3_K_M вместо Q4_K_M).

Проверка​

curl -s http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen3.5-9B-Q4_K_M.gguf",
"messages": [{"role": "user", "content": "Привет!"}],
"max_tokens": 50
}' | jq .choices[0].message.content

Получение имени модели​

Если вы забыли имя модели, запросите конечную точку моделей:

curl -s http://localhost:8080/v1/models | jq '.data[].id'

Вариант B: MLX через omlx​

omlx — это нативное приложение для macOS, которое управляет и обслуживает MLX-модели. MLX — это собственный фреймворк машинного обучения Apple, оптимизированный специально для архитектуры унифицированной памяти Apple Silicon.

Установка​

Скачайте и установите с omlx.ai. Приложение предоставляет графический интерфейс для управления моделями и встроенный сервер.

Загрузка модели​

Используйте приложение omlx для просмотра и загрузки моделей. Найдите Qwen3.5-9B-mlx-lm-mxfp4 и скачайте её. Модели хранятся локально (обычно в ~/.omlx/models/).

Запуск сервера​

omlx по умолчанию обслуживает модели на http://127.0.0.1:8000. Запустите обслуживание из интерфейса приложения или через CLI, если доступно.

Проверка​

curl -s http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen3.5-9B-mlx-lm-mxfp4",
"messages": [{"role": "user", "content": "Привет!"}],
"max_tokens": 50
}' | jq .choices[0].message.content

Список доступных моделей​

omlx может обслуживать несколько моделей одновременно:

curl -s http://127.0.0.1:8000/v1/models | jq '.data[].id'

Бенчмарки: llama.cpp против MLX​

Оба бэкенда протестированы на одной машине (Apple M5 Max, 128 ГБ унифицированной памяти) с одной и той же моделью (Qwen3.5-9B) на сопоставимых уровнях квантизации (Q4_K_M для GGUF, mxfp4 для MLX). Пять различных промптов, по три запуска каждого, бэкенды тестировались последовательно во избежание конкуренции за ресурсы.

Результаты​

Метрикаllama.cpp (Q4_K_M)MLX (mxfp4)Победитель
TTFT (среднее)67 мс289 мсllama.cpp (в 4,3 раза быстрее)
TTFT (p50)66 мс286 мсllama.cpp (в 4,3 раза быстрее)
Генерация (среднее)70 ток/с96 ток/сMLX (на 37% быстрее)
Генерация (p50)70 ток/с96 ток/сMLX (на 37% быстрее)
Общее время (512 токенов)7,3 с5,5 сMLX (на 25% быстрее)

Что это значит​

  • llama.cpp превосходно обрабатывает промпты — его конвейер flash attention + квантованный KV-кэш выдаёт первый токен за ~66 мс. Если вы создаёте интерактивные приложения, где важна воспринимаемая отзывчивость (чат-боты, автодополнение), это значительное преимущество.

  • MLX генерирует токены на ~37% быстрее после запуска. Для пакетных нагрузок, длительной генерации или любых задач, где важнее общее время завершения, а не начальная задержка, MLX справляется быстрее.

  • Оба бэкенда чрезвычайно стабильны — разброс между запусками был незначительным. На эти цифры можно положиться.

Какой выбрать?​

Сценарий использованияРекомендация
Интерактивный чат, инструменты с низкой задержкойllama.cpp
Длительная генерация, пакетная обработкаMLX (omlx)
Ограниченная память (8-16 ГБ)llama.cpp (квантованный KV-кэш не имеет аналогов)
Обслуживание нескольких моделей одновременноomlx (встроенная поддержка нескольких моделей)
Максимальная совместимость (включая Linux)llama.cpp

Подключение к VibeOS​

После запуска локального сервера:

vibeos model

Выберите Custom endpoint и следуйте инструкциям. Вас попросят указать базовый URL и имя модели — используйте значения из выбранного вами бэкенда.


Тайм-ауты​

VibeOS автоматически определяет локальные конечные точки (localhost, LAN-адреса) и смягчает тайм-ауты стриминга. Для большинства конфигураций настройка не требуется.

Если вы всё же сталкиваетесь с ошибками тайм-аута (например, при очень больших контекстах на медленном оборудовании), вы можете переопределить тайм-аут чтения стрима:

# В вашем .env — увеличьте с 120 с по умолчанию до 30 минут
VIBEOS_STREAM_READ_TIMEOUT=1800
Тайм-аутПо умолчаниюАвтонастройка для локальныхПереопределение через env
Чтение стрима (уровень сокета)120 сУвеличивается до 1800 сVIBEOS_STREAM_READ_TIMEOUT
Обнаружение устаревшего стрима180 сПолностью отключаетсяVIBEOS_STREAM_STALE_TIMEOUT
API-вызов (без стриминга)1800 сИзменения не требуютсяVIBEOS_API_TIMEOUT

Тайм-аут чтения стрима — наиболее вероятная причина проблем: это дедлайн на уровне сокета для получения следующего фрагмента данных. Во время префилла на больших контекстах локальные модели могут не выдавать вывод в течение нескольких минут, пока обрабатывается промпт. Автоопределение обрабатывает это прозрачно.