Перейти к содержанию

Llm On Mac

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

Мы рассмотрим два бэкенда: | Бэкенд | Установка | Лучше всего в | Формат | |---|---|---|---| | llama.cpp | brew install llama.cpp | Быстрейшее время до первого токена, квантованный KV-кэш для экономии памяти | GGUF | | omlx | omlx.ai | Быстрейшая генерация токенов, нативная оптимизация Metal | MLX (safetensors) |

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

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


Выбор модели

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

Вариант Размер на диске Требуется RAM (контекст 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-ускорения «из коробки».

Установка

[code] brew install llama.cpp

[/code]

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

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

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

[code] brew install huggingface-cli

[/code]

Затем скачайте:

[code] huggingface-cli download unsloth/Qwen3.5-9B-GGUF Qwen3.5-9B-Q4_K_M.gguf --local-dir ~/models

[/code]

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

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

[code] 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

[/code]

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

Флаг Назначение
-ngl 99 Выгрузить все слои на GPU (Metal). Используйте большое число, чтобы ничего не осталось на CPU.
-c 131072 Размер окна контекста (128K токенов). Уменьшите, если мало памяти.
-np 1 Количество параллельных слотов. Оставьте 1 для одного пользователя — больше слотов уменьшает бюджет памяти.
-fa on Flash 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, если не нужен сетевой доступ.

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

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

[/code]

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

Флаги --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 и уменьшите контекст до -c 32768 (32K). На 16 ГБ можно комфортно работать с контекстом 128K. На 32+ ГБ можно запускать модели побольше или несколько параллельных слотов.

Если памяти всё ещё не хватает, сначала уменьшите размер контекста (-c), затем попробуйте меньшую квантизацию (Q3_K_M вместо Q4_K_M).

Проверка

[code] 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": "Hello!"}], "max_tokens": 50 }' | jq .choices[0].message.content

[/code]

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

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

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

[/code]


Вариант 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, если доступно.

Проверка

[code] 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": "Hello!"}], "max_tokens": 50 }' | jq .choices[0].message.content

[/code]

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

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

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

[/code]


Бенчмарки: llama.cpp vs 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

Подключение к Hermes

Когда ваш локальный сервер запущен:

[code] hermes model

[/code]

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


Тайм-ауты

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

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

[code] # В вашем .env — увеличить со 120 с по умолчанию до 30 минут HERMES_STREAM_READ_TIMEOUT=1800

[/code]

Тайм-аут По умолчанию Локальная автонастройка Переопределение через env-переменную
Чтение стрима (уровень сокета) 120 с Увеличен до 1800 с HERMES_STREAM_READ_TIMEOUT
Обнаружение устаревшего стрима 180 с Полностью отключён HERMES_STREAM_STALE_TIMEOUT
API-вызов (нестриминг) 1800 с Не требуется изменений HERMES_API_TIMEOUT

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