Tenho lido muito sobre LLMs locais. As pessoas parecem bastante animadas com isso. Decidi experimentar.
Uma reflexão sobre LLMs
Se você gosta de IA, provavelmente sabe o que é um LLM. Em uma explicação bem superficial, é um algoritmo que produz uma saída a partir de um prompt. Ele processa sua resposta conforme um enorme conjunto de dados no qual foi treinado. As capacidades de um LLM geralmente dependem de seus dados de treinamento.
Alguns populares são ChatGPT, Claude e Gemini. Em geral, você interage com esses LLMs por meio de uma aplicação ou site desenvolvido por seu fornecedor.
Mas acessar o LLM pelo site do fornecedor é apenas uma das formas de acessá-lo. Você pode usar qualquer outra interface de chat, frequentemente chamada de harness, que suporte APIs compatíveis com LLMs e “conversar” com LLMs da mesma maneira. De modo semelhante, também pode fornecer ferramentas ao LLM para fluxos de trabalho agênticos. A única diferença é que você não tem a UX do fornecedor. Você recebe a resposta bruta do LLM com todas as suas capacidades.
Conectar-se a um LLM por uma API ou qualquer tipo de interface pressupõe que ele esteja em execução em algum lugar nos datacenters do fornecedor. Portanto, tudo que você digita vai para os servidores deles e é processado pelo LLM. Em geral isso é aceitável, mas vimos o preço por token disparar ultimamente. Leia um de meus posts recentes para ter uma ideia. Além disso, empresas como OpenAI e Meta não são exatamente o que eu chamaria de confiáveis para armazenar meus dados pessoais. E, convenhamos, alguns de nós tiveram conversas pessoais com LLMs em algum momento.
Além de preço e privacidade, algumas tarefas podem ser simples demais para LLMs com trilhões de parâmetros. Para evitar um exemplo bobo como “quantos Rs há em strawberry”, vejamos um exemplo simples, mas comum, para desenvolvedores: explorar uma codebase e explicar sua estrutura ou encontrar certo ponto do código onde uma lógica específica acontece. Esses casos poderiam usar LLMs bem pequenos, potencialmente locais.
O que são LLMs locais?
Da mesma forma que um LLM roda em algum servidor, ele também pode rodar na sua máquina, com certas limitações.
Um LLM com centenas de bilhões de parâmetros exige muita computação de GPU: mais do que uma pessoa comum conseguiria comprar em toda a vida. Veja as notícias sobre os bilhões de dólares gastos nisso para ter uma ideia.
Para um ser humano comum sem acesso a bilhões de dólares, a solução é reduzir os LLMs até que caibam em hardware comum. Por hardware comum, quero dizer algumas GPUs domésticas poderosas, como a RTX 5090. É claro que esse hardware é caro, especialmente considerando o aumento nos preços de memória devido à demanda da infraestrutura de IA. Ainda assim, é acessível para usuários domésticos.
Além disso, CPUs de Mac após Apple Silicon compartilham memória com a GPU. Portanto, se você tem 48 GB de RAM, pode executar alguns modelos locais bastante decentes. Os resultados da minha pesquisa foram feitos em GPUs de Mac, também conhecidas como Metal, em duas máquinas diferentes com 16 GB e 48 GB de RAM.
Mas executar LLMs localmente traz uma limitação: você só pode executar modelos até certa escala e, em geral, quanto menor o LLM, menos capaz e inteligente ele é.
Porém, dependendo da tarefa, um LLM local pode funcionar muito bem. Só é difícil medir. Qual quantidade de parâmetros é melhor? Qual fornecedor? Devo escolher open source ou closed source?
Essas são perguntas que quero começar a responder neste post.
Como medir isso?
Alguém poderia dizer: “Bem, você só precisa verificar um benchmark e encontrar um LLM inteligente o suficiente e pequeno o suficiente para você, e pronto!”
O problema é que benchmarks gerais não preveem desempenho em tarefas. Se você testa um modelo em MMLU ou HumanEval, aprenderá algo sobre o modelo, mas nada sobre se ele consegue realmente resolver seus problemas.
Então, para este post introdutório, projetei um teste mais prático: pequenos LLMs locais conseguem refatorar código real?
O design do teste
Tenho um componente React que renderiza uma lista de itens selecionáveis. Ele tem uma prop para habilitar a ordenação dos itens por seleção. Itens selecionados ficam no começo da lista caso essa prop seja verdadeira.
Criei dois testes totalmente não científicos, enviesados e completamente opinativos com base nisso.
Teste 1: remoção da prop de ordenação
Remova a prop de ordenação do componente React e toda a lógica subjacente ligada a ela. Simples no papel, mas isso testa:
- O modelo entende escopo? (remover apenas props não usadas)
- Ele acompanha dependências? (se uma prop é usada em algum lugar, deve ficar)
- Ele consegue simplificar código sem quebrá-lo?
O objetivo é ter um componente que renderize a lista como está, independentemente da seleção, com o código mais limpo possível.
Teste 2: inverso: adicionar a prop de volta
Partindo de um componente React sem a prop e a lógica de ordenação, adicione a mesma prop de volta com a lógica de ordenação. Isso testa:
- Ele consegue implementar uma funcionalidade a partir de requisitos?
- Ele lê instruções cuidadosamente? (ordenar pelo campo
selected, não porselectedItemId, por exemplo) - Ele produz código limpo e idiomático?
O objetivo é ter o mesmo componente original com lógica de ordenação, o mais limpo possível.
A configuração do teste
Para cada teste, medi cinco coisas:
- Correção — Compila? Resolve o problema?
- Velocidade — Tokens por segundo (quanto tempo leva?)
- Qualidade — O código é limpo ou cheio de padrões desnecessários?
- Tokens — Quantos tokens consome?
- Raciocínio — Se o modelo suporta thinking, quanto tempo leva?
Estou usando LM Studio para baixar e executar os modelos. Cada execução começa de um contexto completamente limpo, sem ferramentas, skills ou MCPs habilitados. Cada modelo recebe 8192 tokens de contexto. Todos usam exatamente o mesmo prompt.
O que encontrei
Os resultados foram surpreendentes. O tamanho do modelo quase não previu nada.
| Modelo | Tamanho | Tokens | TPS | Tempo de raciocínio | Remoção | Inverso | Veredito |
|---|---|---|---|---|---|---|---|
| Phi-4 Mini | 3.8B | ~42.000 | 52 | 20m+ | ✗ FALHOU | ✗ FALHOU | Desqualificado por alucinação |
| Mistral 7B | 7B | 2.690 | 38 | Nenhum | ✗ FALHOU | ✗ FALHOU | Qualidade e velocidade ruins |
| Qwen 2.5 Coder 7B | 7B | 2.365 | 22 | Nenhum | ✓ PASSOU | ✓ PASSOU | O primeiro bom |
| Qwen 3.5 9B (thinking OFF) | 9B | 2.454 | 33 | Nenhum | ✗ FALHOU | — | Qualidade ruim |
| Qwen 3.5 9B (thinking ON) | 9B | 22.792 | 26 | 12m47s | ✗ FALHOU | — | 12m pensando? Qual é! |
| Gemma-4-e4b | 9B | 3.186 | 35 | 7s | ✓ PASSOU | ✓ PASSOU | Surpreendentemente bom! |
| GPT-oss 20B | 20B | 2.493 | 50 | 9s (médio) | ✓ PASSOU | ✗ FALHOU | Tamanho e qualidade decentes |
| Qwen Coder 30B | 30B | 1.930 | 55 | Nenhum | ✓ PASSOU | ✗ FALHOU | Grande demais para a qualidade entregue |
| Deepseek Coder 33B | 33B | 3.369 | 9 | Nenhum | ✓ FALHOU | - | Desqualificado por velocidade e qualidade de código ruins |
Observações principais:
Deepseek Coder 33B, o maior e supostamente mais capaz, foi o mais lento (9 tokens/s) e produziu código com bugs. Ele estava rodando em hardware decente, então a máquina não é a culpada.
Qwen 2.5 Coder 7B, com um quinto do tamanho, foi 6x mais rápido e correto.
Phi-4 alucinou já no processo de raciocínio e acabou explodindo a cota de tokens.
Mais interessante: prompts melhores ajudaram alguns modelos, mas não outros. Instruções mais claras melhoraram a qualidade do código em modelos pequenos, mas não corrigiram mal-entendidos fundamentais. Todos os modelos de 20B ou mais erraram o teste inverso da mesma forma: confundiram “ordenar pelo campo selected” com “ordenar pelo ID do item selecionado”. Essa é uma lacuna de compreensão, não de prompt.
O experimento de loop
Aqui foi onde ficou interessante. Venho lendo sobre loops agênticos ultimamente. Decidi experimentar.
Quando dei ao Qwen 3.5 9B feedback explícito sobre o que deu errado — “Você removeu a prop errada, mantenha keepLabel porque ela é usada em mapItemToEntry” — ele corrigiu o bug na segunda tentativa.
Tentativa 1 (prompt mínimo): falhou. Removeu a prop errada da interface.
Feedback inserido: “Regra crítica: remova apenas props que não são usadas em nenhuma parte do corpo da função. Se uma prop aparece em qualquer linha de código, ela deve permanecer na interface.”
Tentativa 2: passou. Manteve corretamente keepLabel e removeu apenas sortItems.
Isso é bem legal. Um modelo super barato que falha sozinho, mas tem sucesso com feedback, é exatamente o que você precisa para trabalho agêntico. Talvez você não precise de um modelo de um trilhão de parâmetros que acerte na primeira tentativa.
O que isso significa
Três coisas se destacam:
1. Modelos pequenos funcionam se você os guiar.
Qwen 2.5 Coder 7B (7B) acertou ambos os testes na primeira tentativa com o prompt correto. Gemma-4-e4b (9B) produziu código com qualidade de produção. Você não precisa de 30B+ parâmetros para tarefas de refatoração.
2. O tamanho do modelo não é a métrica.
Deepseek 33B teve o pior desempenho. Velocidade e correção vieram da qualidade do treinamento e do alinhamento à tarefa, não da contagem bruta de parâmetros. A narrativa de que “o maior modelo vence” está errada.
3. Loops de feedback importam.
Modelos falham de maneiras previsíveis, mas aprendem com correção explícita. Um modelo que erra sozinho, mas acerta com feedback, não é um fracasso, e sim a base de um sistema agêntico.
Mas não são só flores
É claro que, de “adicionar uma prop a este componente” até o mundo louco de desenvolvimento agêntico que vemos hoje, há um salto enorme.
Um modelo pequeno que se sai bem numa tarefa tão simples não garante que será excelente em um ambiente mais pesado.
Isso abre caminho para testes futuros. E tenho algumas ideias em mente.
As próximas perguntas
Tenho algumas perguntas em aberto que vou colocar à prova nos próximos dias:
- Se modelos locais conseguem refatorar código com feedback, o que mais conseguem fazer?
- Como construir um sistema que usa iteração local barata + verificação inteligente para superar APIs de nuvem caras?
- Qwen 2.5 Coder 7B provou ser bom com código, mas não suporta ferramentas. Para um sistema agêntico, poderíamos combinar vários modelos aproveitando o que cada um faz melhor?
Talvez não precisemos de Claude Fable 5 no raciocínio máximo para resolver a maioria dos problemas, afinal.
Sabemos que o Qwen 2.5 Coder 7B pode ser o ponto ideal para programação. Mas preciso encontrar o melhor para usar ferramentas. Provavelmente Gemma 4 e4b é um bom começo, já que teve bom desempenho neste teste.
Fiquem por aqui para ver os próximos experimentos.
Todos os testes foram executados em uma máquina de 16 GB ou 48 GB com LM Studio usando quantização Q4_K_M. Resultados completos e metodologia de teste disponíveis mediante solicitação.