Documentação oficial desta página · v0.20.6
LLMs Locais no Mac
Este guia mostra passo a passo como rodar um servidor de LLM local no macOS com uma API compatível com a da OpenAI. Você ganha privacidade total, custo zero de API e um desempenho surpreendentemente bom no Apple Silicon.
Cobrimos dois backends:
| Backend | Instalação | Melhor em | Formato |
|---|---|---|---|
| llama.cpp | brew install llama.cpp | Menor tempo até o primeiro token, cache KV quantizado para pouca memória | GGUF |
| omlx | omlx.ai | Geração de tokens mais rápida, otimização nativa para Metal | MLX (safetensors) |
Os dois expõem um endpoint /v1/chat/completions compatível com a OpenAI. O Hermes funciona com qualquer um dos dois — basta apontá-lo para http://localhost:8080 ou http://localhost:8000.
Este guia é voltado para Macs com Apple Silicon (M1 e posteriores). Macs Intel funcionam com o llama.cpp, mas sem aceleração por GPU — espere um desempenho bem mais lento.
Como escolher um modelo
Para começar, recomendamos o Qwen3.5-9B — é um modelo forte de raciocínio que cabe folgado em 8 GB ou mais de memória unificada com quantização.
| Variante | Tamanho em disco | RAM necessária (contexto de 128K) | Backend |
|---|---|---|---|
| Qwen3.5-9B-Q4_K_M (GGUF) | 5,3 GB | ~10 GB com cache KV quantizado | llama.cpp |
| Qwen3.5-9B-mlx-lm-mxfp4 (MLX) | ~5 GB | ~12 GB | omlx |
Regra de bolso para memória: tamanho do modelo + cache KV. Um modelo 9B Q4 tem cerca de 5 GB. O cache KV com contexto de 128K e quantização Q4 acrescenta uns 4 a 5 GB. Com o cache KV padrão (f16), isso infla para cerca de 16 GB. As flags de cache KV quantizado do llama.cpp são o truque decisivo em sistemas com pouca memória.
Para modelos maiores (27B, 35B), você vai precisar de 32 GB ou mais de memória unificada. O 9B é o ponto ideal para máquinas de 8 a 16 GB.
Opção A: llama.cpp
O llama.cpp é o runtime de LLM local mais portátil. No macOS ele usa Metal para aceleração por GPU sem precisar de configuração.
Instale
brew install llama.cpp
Isso te dá o comando llama-server globalmente.
Baixe o modelo
Você precisa de um modelo em formato GGUF. A fonte mais fácil é o Hugging Face pela huggingface-cli:
brew install huggingface-cli
Depois baixe:
huggingface-cli download unsloth/Qwen3.5-9B-GGUF Qwen3.5-9B-Q4_K_M.gguf --local-dir ~/models
Alguns modelos no Hugging Face exigem autenticação. Rode huggingface-cli login antes, se você receber um erro 401 ou 404.
Suba o servidor
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
O que cada flag faz:
| Flag | Para que serve |
|---|---|
-ngl 99 | Joga todas as camadas para a GPU (Metal). Use um número alto para garantir que nada fique na CPU. |
-c 131072 | Tamanho da janela de contexto (128K tokens). Reduza se você estiver com pouca memória. |
-np 1 | Número de slots paralelos. Mantenha em 1 para uso individual — mais slots dividem o seu orçamento de memória. |
-fa on | Flash attention. Reduz o uso de memória e acelera a inferência de contexto longo. |
--cache-type-k q4_0 | Quantiza o cache de chaves em 4 bits. É aqui que a memória é mais economizada. |
--cache-type-v q4_0 | Quantiza o cache de valores em 4 bits. Junto com a opção acima, corta cerca de 75% da memória do cache KV em relação ao f16. |
--host 0.0.0.0 | Escuta em todas as interfaces. Use 127.0.0.1 se você não precisa de acesso pela rede. |
O servidor está pronto quando aparece:
main: server is listening on http://0.0.0.0:8080
srv update_slots: all slots are idle
Otimização de memória em sistemas apertados
As flags --cache-type-k q4_0 --cache-type-v q4_0 são a otimização mais importante em sistemas com memória limitada. Veja o impacto com contexto de 128K:
| Tipo de cache KV | Memória do cache KV (ctx 128K, modelo 9B) |
|---|---|
| f16 (padrão) | ~16 GB |
| q8_0 | ~8 GB |
| q4_0 | ~4 GB |
Em um Mac de 8 GB, use cache KV q4_0 e escolha um modelo menor que ainda caiba no contexto mínimo de 64K exigido pelo Hermes. Com 16 GB, você consegue usar contexto de 128K com tranquilidade. Com 32 GB ou mais, você pode rodar modelos maiores ou vários slots paralelos.
Se ainda estiver faltando memória, reduza o contexto apenas até o mínimo de 64K do Hermes; abaixo disso, troque para um modelo menor ou uma quantização menor (Q3_K_M em vez de Q4_K_M).
Teste
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": "Olá!"}],
"max_tokens": 50
}' | jq .choices[0].message.content
Descubra o nome do modelo
Se você esquecer o nome do modelo, consulte o endpoint de modelos:
curl -s http://localhost:8080/v1/models | jq '.data[].id'
Opção B: MLX pelo omlx
O omlx é um aplicativo nativo do macOS que administra e serve modelos MLX. O MLX é o framework de aprendizado de máquina da própria Apple, otimizado especificamente para a arquitetura de memória unificada do Apple Silicon.
Instale
Baixe e instale em omlx.ai. Ele oferece uma interface gráfica para administrar modelos e um servidor embutido.
Baixe o modelo
Use o aplicativo omlx para navegar e baixar modelos. Busque por Qwen3.5-9B-mlx-lm-mxfp4 e baixe. Os modelos ficam guardados localmente (normalmente em ~/.omlx/models/).
Suba o servidor
Por padrão, o omlx serve modelos em http://127.0.0.1:8000. Comece a servir pela interface do aplicativo, ou use a CLI se ela estiver disponível.
Teste
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": "Olá!"}],
"max_tokens": 50
}' | jq .choices[0].message.content
Liste os modelos disponíveis
O omlx consegue servir vários modelos ao mesmo tempo:
curl -s http://127.0.0.1:8000/v1/models | jq '.data[].id'
Benchmarks: llama.cpp x MLX
Os dois backends foram testados na mesma máquina (Apple M5 Max, 128 GB de memória unificada) rodando o mesmo modelo (Qwen3.5-9B) em níveis de quantização comparáveis (Q4_K_M para GGUF, mxfp4 para MLX). Cinco prompts variados, três execuções cada, backends testados em sequência para evitar disputa por recursos.
Resultados
| Métrica | llama.cpp (Q4_K_M) | MLX (mxfp4) | Vencedor |
|---|---|---|---|
| TTFT (média) | 67 ms | 289 ms | llama.cpp (4,3x mais rápido) |
| TTFT (p50) | 66 ms | 286 ms | llama.cpp (4,3x mais rápido) |
| Geração (média) | 70 tok/s | 96 tok/s | MLX (37% mais rápido) |
| Geração (p50) | 70 tok/s | 96 tok/s | MLX (37% mais rápido) |
| Tempo total (512 tokens) | 7,3s | 5,5s | MLX (25% mais rápido) |
O que isso significa
-
O llama.cpp se destaca no processamento do prompt — o pipeline de flash attention + cache KV quantizado entrega o primeiro token em cerca de 66 ms. Se você está construindo aplicações interativas em que a sensação de resposta imediata importa (chatbots, autocompletar), essa é uma vantagem relevante.
-
O MLX gera tokens cerca de 37% mais rápido depois que engata. Para cargas em lote, geração de texto longo ou qualquer tarefa em que o tempo total de conclusão importa mais que a latência inicial, o MLX termina antes.
-
Os dois backends são extremamente consistentes — a variação entre execuções foi desprezível. Você pode confiar nesses números.
Qual deles escolher?
| Caso de uso | Recomendação |
|---|---|
| Chat interativo, ferramentas de baixa latência | llama.cpp |
| Geração de texto longo, processamento em massa | MLX (omlx) |
| Memória apertada (8 a 16 GB) | llama.cpp (o cache KV quantizado não tem rival) |
| Servir vários modelos ao mesmo tempo | omlx (suporte embutido a múltiplos modelos) |
| Máxima compatibilidade (inclusive Linux) | llama.cpp |
Conecte ao Hermes
Com o seu servidor local rodando:
hermes model
Selecione Custom endpoint e siga as perguntas. Ele vai pedir a URL base e o nome do modelo — use os valores do backend que você configurou acima.
Timeouts
O Hermes detecta automaticamente endpoints locais (localhost, IPs de rede local) e relaxa os seus timeouts de streaming. Na maioria das configurações, não é preciso configurar nada.
Se você ainda topar com erros de timeout (por exemplo, contextos muito grandes em hardware lento), pode sobrescrever o timeout de leitura do stream:
# No seu .env — sobe dos 120s padrão para 30 minutos
HERMES_STREAM_READ_TIMEOUT=1800
| Timeout | Padrão | Ajuste automático local | Sobrescrita por variável de ambiente |
|---|---|---|---|
| Leitura do stream (nível de socket) | 120s | Sobe para 1800s | HERMES_STREAM_READ_TIMEOUT |
| Detecção de stream travado | 180s | Desligada por completo | HERMES_STREAM_STALE_TIMEOUT |
| Chamada de API (sem streaming) | 1800s | Não precisa mudar | HERMES_API_TIMEOUT |
O timeout de leitura do stream é o que mais tende a causar problema — é o prazo, no nível do socket, para receber o próximo pedaço de dados. Durante o prefill de contextos grandes, modelos locais podem ficar minutos sem produzir saída enquanto processam o prompt. A detecção automática lida com isso de forma transparente.
O Hermes envia o prompt de sistema e os esquemas de ferramentas em toda chamada, então, em hardware mais lento, o primeiro turno pode ter minutos de silêncio enquanto o modelo processa esse prompt antes de gerar qualquer coisa. Isso é o prefill trabalhando, não uma sessão travada. Veja Primeira resposta lenta (prefill) no guia do Ollama para mitigações como manter o modelo carregado e enxugar o prompt fixo com hermes prompt-size.