- A configuração de um agente de programação local permite rodar modelos no macOS com uma API compatível com OpenAI mesmo durante falhas de internet, além de processar entradas de texto e imagem no Pi
- Em um Apple M1 Max 64GB com macOS 15.7.7, foram usados llama.cpp Metal e o modelo Gemma 4 26B-A4B GGUF, com velocidade base de geração de 58.2 tok/s
- Após adicionar um modelo draft MTP e ajustar
--spec-draft-n-max 3, a velocidade de geração subiu para 72.2 tok/s, uma melhora de cerca de 24% - É preciso carregar
mmproj-BF16.ggufcom--mmproje configurar a entrada do modelo no Pi como["text", "image"]para que entradas de imagem como capturas de tela sejam enviadas - A configuração final executa o servidor llama.cpp em
127.0.0.1:8080/v1, com o Pi usando isso como provedor local; o Qwen3.6 35B-A3B mostrou benchmarks melhores como agente de programação, mas foi mais lento neste teste, com 55 tok/s
Objetivo da configuração do agente de programação local
- Algumas quedas de internet que impediram o uso de agentes de programação motivaram a tentativa de uma configuração de execução local
- A configuração desejada precisava ser rápida o bastante para uso real no Mac e também utilizável por outras ferramentas por meio de uma API compatível com OpenAI
- O objetivo também era permitir processar capturas de tela ou imagens quando necessário, para reenviar ao agente os resultados que ele produzisse
- A configuração final é composta por
llama.cpp, Gemma 4 26B-A4B GGUF, modelo draft Q8 MTP, projetor multimodal Gemma 4 e o agente de programação de terminal Pi - O ambiente de teste era um Apple M1 Max, 64GB de memória unificada e macOS 15.7.7
Modelo
- O modelo principal era
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf, disponível no repositóriounsloth-gemma-4-26B-A4B-it-GGUFno Hugging Face - Esse arquivo tem cerca de 16GB e, junto com o cabeçalho draft MTP e o projetor multimodal, a pasta do modelo fica com cerca de 17GB
- O prompt de benchmark foi
Write a compact Python function that parses a unified diff and returns the changed file paths. Then explain two edge cases. - Cada benchmark gerou cerca de 128 tokens
Execução base: llama.cpp + Metal
- O modelo principal foi executado diretamente com
llama.cppe aceleração Metal - O comando de execução usava
llama-clicom o caminho do modelo,-ngl 999,-fa on,-c 4096e-n 128 - Na configuração base, a velocidade de processamento do prompt foi 298.0 tok/s e a velocidade de geração foi 58.2 tok/s
- 58 tok/s não é exatamente rápido, mas é utilizável; em tarefas com agentes de programação, a velocidade importa porque há muitas chamadas de ferramentas
Adicionando o modelo draft MTP
- O Gemma 4 oferece um modelo draft MTP no formato
MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf - No
llama.cpp, ele é carregado para decodificação especulativa com--model-draft,--spec-type draft-mtpe--spec-draft-n-max - A primeira execução com MTP registrou 69.2 tok/s com 4 tokens draft
- A documentação da Unsloth recomenda
--spec-draft-n-max 2como ponto de partida, mas sugere testar de 1 a 6 em cada hardware para usar o valor mais rápido - Após ajustar
--spec-draft-n-max, o melhor resultado foi 72.2 tok/s com 3 tokens draft - O modelo principal sozinho marcou 58.2 tok/s, enquanto a configuração com o modelo draft Q8 MTP chegou a 72.2 tok/s
- A velocidade de processamento do prompt praticamente se manteve, e a velocidade de geração melhorou cerca de 24%
Resultados do ajuste de MTP
- Foram testados valores de
--spec-draft-n-maxde 1 a 6 - O valor 1 teve 295.5 tok/s no prompt e 68.4 tok/s na geração
- O valor 2 teve 299.1 tok/s no prompt e 72.0 tok/s na geração
- O valor 3 foi o mais rápido, com 295.6 tok/s no prompt e 72.2 tok/s na geração
- O valor 4 caiu para 70.7 tok/s na geração, o valor 5 para 63.7 tok/s e o valor 6 para 61.2 tok/s
- No M1 Max,
3foi o melhor valor, e2também ficou bem próximo
Comparação com MLX
- Para verificar uma forma mais rápida de rodar o modelo no Mac, também foram testados modelos MLX baseados em
mlx-lm llama.cpp Metal + MTPregistrou 72.2 tok/s com a combinação Unsloth GGUF Q4 e Q8 MTPllama.cpp Metalsozinho registrou 58.2 tok/s com Unsloth GGUF Q4MLX-LMregistrou 45.8 tok/s com Unsloth UD MLX 4-bitMLX-LMregistrou 43.9 tok/s emmlx-community 4-bite 38.1 tok/s emmlx-community OptiQ 4-bit- Nesta configuração específica, o llama.cpp foi mais rápido que o MLX, e o llama.cpp com MTP foi a melhor escolha
- Também foi testado o Gemma 4 MTP com
gemma-4-swift-mlx, mas o checkpoint MLX 26B 4-bit testado não correspondia às weight keys esperadas pelo loader, então o teste foi interrompido sem baixar e ajustar um novo modelo
Adicionando suporte a imagem
- Para anexar capturas de tela no Pi, a entrada do modelo não pode ser apenas texto
- Originalmente, o item do modelo local estava configurado como
"input": ["text"], e nesse caso o Pi não conseguia enviar corretamente ao modelo a saída da ferramenta de imagem - O servidor
llama.cpptambém precisa do projetor multimodal Gemma 4,mmproj-BF16.gguf, para recursos multimodais - Ao carregar o projetor com
--mmproj, ollama.cppanuncia suporte multimodal e o Pi pode enviar imagens - Um teste executando
llama.cpp Metal + MTPsem o projetor registrou 120.3 tok/s no prompt e 71.4 tok/s na geração - A execução final com
mmproj-BF16.ggufcarregado registrou 297.4 tok/s no prompt e 72.2 tok/s na geração - Na execução final com o projetor carregado, não houve perda de velocidade na geração de texto
Instalação do llama.cpp
- As dependências
cmake,git,tmuxepython@3.11foram instaladas com Homebrew - Foi criado o caminho
~/Developer/ML-Models/Gemma4/repos, e o repositórioggml-org/llama.cppfoi clonado emrepos/llama.cpp - A build foi configurada com
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_METAL=ON -DGGML_ACCELERATE=ON - Depois disso, a build de release foi executada com
cmake --build build --config Release -j - A build testada tinha as opções
GGML_METAL=ON,GGML_ACCELERATE=ON,GGML_BLAS=ONeGGML_BLAS_VENDOR=Apple
Download dos arquivos de modelo
- Foi criado um ambiente virtual com Python 3.11 e instalados
huggingface_hubehf_xet - O
huggingface-cli downloadfoi usado para baixar o modelo principal Gemma 4,mmproj-BF16.ggufe o modelo draft MTP - Os arquivos baixados foram
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf,mmproj-BF16.ggufeMTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf - A pasta final do modelo, em
models/unsloth-gemma-4-26B-A4B-it-GGUF/, contém esses três arquivos
Iniciando o servidor local
- O servidor final é executado com
llama-server, especificando o modelo principal, o modelo draft MTP e o projetor multimodal - As opções principais são
--spec-type draft-mtp,--spec-draft-n-max 3,-ngl 999,-fa on,-c 65536e--parallel 1 - O servidor é executado com
--host 127.0.0.1 --port 8080 - O endpoint compatível com OpenAI é
http://127.0.0.1:8080/v1 - O wrapper
start_server.shexecuta o servidor em uma sessãotmuxe grava os logs emlogs/llama-server-mtp.log - Após
chmod +x start_server.sh, o servidor é iniciado com./start_server.sh - O funcionamento do servidor pode ser verificado com
curl http://127.0.0.1:8080/v1/models
Configuração do Pi
- O Pi lê a configuração do provedor de modelo em
~/.pi/agent/models.json - O
baseUrldo provedor localgemma4-localaponta parahttp://127.0.0.1:8080/v1 apiéopenai-completionse, como é um servidor local,authHeaderfica comofalse- O ID do modelo é
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf, e o nome é configurado comoGemma 4 26B-A4B Q4 + MTP inputdeve ser["text", "image"]; caso contrário, o Pi trata o modelo como somente texto- A janela de contexto é 65536 e o máximo de tokens é 8192
- Se necessário, em
~/.pi/agent/settings.json,defaultProviderpode ser definido comogemma4-localedefaultModelcomo o nome desse arquivo GGUF - Ao executar
pi --offline --list-models gemma, o esperado é que o suporte a imagens apareça comoyes - O modelo local é executado com
pi --provider gemma4-local --model gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf - A execução não interativa é feita com
pi -p --provider gemma4-local --model gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf "Explain what this repository does" - A entrada com captura de tela é feita com
pi -p @"/path/to/screenshot.png" "Describe this image and point out anything relevant to the UI"
Configuração final
- O runtime final de inferência é
llama.cpp - A aceleração no macOS usa a combinação Metal + Accelerate
- O modelo principal é
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf - O modelo draft é
gemma-4-26B-A4B-it-Q8_0-MTP.gguf - A configuração de MTP é
--spec-draft-n-max 3 - O projetor multimodal é
mmproj-BF16.gguf - O servidor é o
llama-serverem127.0.0.1:8080 - A API é a
/v1compatível com OpenAI - O agente de programação é o Pi, e a entrada do modelo no Pi é
["text", "image"] - O modelo draft MTP elevou a velocidade de geração do Gemma 4 neste ambiente de 58.2 tok/s para 72.2 tok/s, e a configuração é simples o bastante para rodar como um servidor local compatível com OpenAI
Alternativa: Qwen3.6 35B-A3B
- Algumas pessoas sugerem usar
Qwen3.6 35B-A3Bem vez deGemma 4 26B-A4B - Em benchmarks verificáveis, o Qwen é avaliado como um agente de programação muito melhor que o Gemma 4
- Porém, essa configuração foi mais lenta, registrando 55 tok/s com a combinação
Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf,unsloth-Qwen3.6-35B-A3B-MTP-GGUFemmproj-BF16.gguf - 55 tok/s em vez de 72 tok/s faz uma diferença considerável para quem está esperando respostas
- O download do modelo Qwen é feito a partir de
unsloth/Qwen3.6-35B-A3B-MTP-GGUF, baixandoQwen3.6-35B-A3B-UD-Q4_K_XL.ggufemmproj-BF16.gguf - O servidor Qwen usa o mesmo
llama-server, mas com--port 8081 - Na configuração do Pi, o nome do provedor Qwen é
qwen36-local, e obaseUrléhttp://127.0.0.1:8081/v1 - A configuração do modelo Qwen usa
reasoning: true,input: ["text", "image"],contextWindow: 65536emaxTokens: 8192
1 comentários
Comentários do Hacker News
Se o prompt do benchmark era “escreva uma função Python concisa que faça o parsing de um unified diff e retorne os caminhos dos arquivos alterados, e explique dois casos de borda”, e cada benchmark gerou cerca de 128 tokens, então 128 tokens parecem poucos demais para obter um bom resultado
A aceleração via MTP depende da frequência com que os tokens previstos são aceitos; pela minha experiência, a taxa de aceitação é maior no começo da saída, então testes curtos podem criar uma aceleração com falso positivo
O llama.cpp tem uma ferramenta dedicada de benchmark que percorre argumentos sem precisar reiniciar o servidor e reenviar o prompt: https://github.com/ggml-org/llama.cpp/blob/master/tools/llam...
A seção de download de modelos também deveria ter mencionado que o argumento
-hfdo llama.cpp baixa o modelo para você. Agradeço ao autor por compartilhar a experiência, mas talvez não seja o melhor guia para iniciantesVi o anúncio de “2x mais rápido” da Unclothe e pensei: “será que agora ficou rápido o suficiente para usar de verdade?”, então fui lá configurar por conta própria
No ano passado também testei coisas como Devstral, mas eram lentas e burras demais, então eu não tinha vontade de continuar usando; desta vez finalmente cheguei à sensação de que dá para usar de verdade tanto em velocidade quanto em inteligência
O llama.cpp tem ferramenta para isso, e para medir direito é preciso incluir o prefill antes da geração de tokens. Também está ficando cada vez mais importante medir a velocidade de geração em contextos longos, como 32k ou 64k
Já escrevi um post parecido no passado usando ollama e opencode: https://blog.kulman.sk/running-local-llm-coding-server/
O opencode não consome contexto demais com o prompt de sistema? Modelos locais têm limitações grandes de contexto e, se bem me lembro, o opencode usa algo em torno de 10k disso, ou perto disso
Se você usar só llama.cpp, não parece que
huggingface-cliseja realmente necessário para baixar algo. Basta passar-hf ...e ele baixa o modeloPara mudar o local do download, é só definir
LLAMA_CACHE:LLAMA_CACHE="models" ./llama-server \-hf unsloth/gemma-4-31B-it-GGUF:UD-Q4_K_XL \...-hfdSe a RAM de memória unificada é grande, mas os teraflops e a largura de banda em GB/s são medianos ou piores, normalmente MoE é a opção mais promissora. No meu ambiente, um M2 Max 96GB, o atual número 1 em
(inteligência, tok/s, profundidade de contexto)é DeepSeek-V4-Flash REAP25<65gb gguf+ ds4-server + pi agentClaro, não é melhor que uma API em nuvem, mas é utilizável o bastante para valer a pena se for necessário. Mesmo em um voo de 4 horas sem internet, o LLM local consumindo 60W ainda deixou a bateria aguentar bem
O branch ds4 com suporte a REAP está aqui: https://github.com/ljubomirj/ds4/tree/reap-compact-support
O grande diferencial é que o DS4F só cai para um nível impraticável de menos de 10 tok/s quando chega a 784K de contexto
Fico curioso se esses modelos locais realmente conseguem resolver problemas até para usuários que não são especialistas em uma linguagem de programação específica
Além de autocompletar inline ou implementar unidades isoladas, não tenho certeza se conseguem de fato projetar e compor uma especificação técnica funcional
Subir um LLM local com llama.cpp/server e usar junto com Claude Code ou Codex-CLI é relativamente simples
Como as configurações necessárias do llama server costumam estar espalhadas por vários lugares, mantenho aqui instruções para alguns LLMs abertos populares: https://pchalasani.github.io/claude-code-tools/integrations/...
Tenho usado omlx.ai com bastante sucesso para baixar vários modelos MLX adequados ao meu hardware e automatizar a execução de harnesses open source e fechados (Claude Code, Codex) com esses modelos
Dá para fazer tanto pela UI web quanto pela de desktop, então, pessoalmente, com o omlx eu nem preciso seguir post de blog
Os builds de Gemma 4 em MLX que encontrei até agora eram mais lentos na mesma quantização e, com MTP, muito mais lentos
Depois de escolher o modelo, a UI web embutida do llama.cpp é bem boa, e para experimentar várias coisas o LM Studio também serve bem
Gemma-4 e Qwen 3.6 não precisam daquele grande bloco típico de prompt de sistema do opencode; na verdade, é melhor remover
O DeepSeek v4 Flash rodando no ds4 do antirez foi bem impressionante
Em termos de “conhecimento armazenado”, parece um modelo nível GPT-4, mas em chamadas de ferramenta de fluxo longo ele se sai melhor que modelos nível GPT-4
Em um MBP M4 Max de 128GB, a geração fica em cerca de 24 t/s e o prefill em cerca de 200 t/s. Eu esperava que fosse lento, e em tarefas como geração de código realmente é, mas como orquestrador de máquinas para tarefas simples é surpreendentemente útil
Para usos não agentivos, é um modelo perfeitamente bom para conversar, com a vantagem de ser totalmente self-hosted e privado
[0]https://github.com/antirez/ds4
Se quiser fazer isso da forma mais preguiçosa possível, basta abrir o Claude Code no terminal, apontar para este post e mandar ele simplesmente “fazer isso”
Já o Claude resolve de uma vez ou com pouquíssimo ajuste
O portal de entrada para conhecimento e execução agora é o LLM, e o Google Search parece um dinossauro
É algo tão incrível que parece até mais impactante do que smartphones, como se estivéssemos um século no futuro