Daniel Garcia
llamafile no Windows: o que aprendi ao usar os mesmos GGUF no Ollama
English version →Um executável, um modelo e a promessa de simplificar a IA local foram suficientes para despertar a curiosidade. Passei uma manhã e parte da tarde a experimentar o llamafile, a comparar respostas com o Ollama e a descobrir que alguns dos problemas mais instrutivos estavam no PowerShell e no código gerado.

Neste artigo
- Parte I — A experiência: motivação, ferramentas e condições do ensaio.
- Conversação com Qwen3: thinking, tempos e limites da comparação.
- Programação com Qwen2.5 Coder: respostas plausíveis e verificações concretas.
- Parte II — Como repetir o procedimento: pastas, executável e modelos.
- Executar o llamafile no browser ou numa chamada de terminal.
- Importar os GGUF no Ollama, sem confundir o Modelfile com comandos PowerShell.
- Recolher resultados e resolver dificuldades: CPU, métricas, continuação de comandos e cópia de texto.
Parte I — A experiência
Porque quis experimentar o llamafile
Encontrei o llamafile na coleção Open Tools da Mozilla.ai e fiquei interessado na proposta: simplificar a execução de modelos de linguagem locais, incluindo a possibilidade de distribuir o modelo e o programa que o executa num único ficheiro.
A Mozilla disponibiliza exemplos e recomendações de modelos para começar a utilizar o llamafile. Mas decidimos não seguir esse caminho. Afinal, se nos limitássemos a executar os modelos sugeridos, qual era a piada nisso? ;)
Preferimos escolher dois modelos por nossa conta, com características e objetivos diferentes: o Qwen3 1.7B, para conversação e tarefas gerais, e o Qwen2.5 Coder 3B, orientado para programação. A intenção era verificar se conseguíamos executar modelos GGUF escolhidos por nós, tanto no llamafile como no Ollama, sem depender dos exemplos preparados pelos autores da ferramenta.
Como já utilizava o Ollama e estava familiarizado com o seu funcionamento, pareceu-me uma boa referência para esta experiência. Mais do que comparar desempenhos, queria perceber até que ponto o llamafile era simples de configurar e prático de utilizar no dia a dia.
Devido a uma avaria, o meu Homelab Linux estava indisponível, pelo que não pude replicar esta experiência noutro sistema que não fosse Windows.
Para quem está a chegar agora à IA local, o artigo «IA local: quando faz sentido correr um modelo no nosso próprio computador?» enquadra as escolhas de hardware e de modelo. Aqui vou concentrar-me no que fiz com estas duas ferramentas.
Conceitos essenciais para compreender a experiência
O modelo é o conjunto de parâmetros que foi treinado para realizar determinadas tarefas. Neste caso, usei modelos das famílias Qwen3 e Qwen2.5 Coder.
GGUF (GPT-Generated Unified Format) é o formato de ficheiro binário desenvolvido no ecossistema do llama.cpp, concebido para armazenar modelos de inteligência artificial e facilitar a sua execução local. Um ficheiro .gguf contém os pesos do modelo, a sua arquitetura e outros metadados necessários à interpretação e execução, incluindo informações relacionadas com a tokenização. Uma das suas principais vantagens é o suporte a diferentes níveis de quantização, permitindo reduzir o tamanho dos modelos e os requisitos de memória, com possíveis compromissos na qualidade das respostas. Neste teste, utilizámos ficheiros GGUF para executar os mesmos modelos no Ollama e no llamafile, sem necessidade de os converter entre as duas ferramentas.
A designação Q5_K_M identifica um método de quantização que reduz a precisão utilizada para armazenar os pesos do modelo, diminuindo o tamanho do ficheiro e os requisitos de memória. Esta redução pode afetar a qualidade das respostas, dependendo do modelo e da quantização aplicada.
O llama.cpp é o projeto de inferência que está na base de várias destas soluções. O llamafile combina essa base com Cosmopolitan Libc e ferramentas próprias para facilitar a distribuição e execução. A apresentação técnica do projeto descreve essa combinação.
O Ollama oferece um fluxo de gestão e execução de modelos, com nomes locais, comandos e uma API. Também permite importar um GGUF já existente, que foi precisamente o caminho usado nesta experiência.
Há ainda duas maneiras de utilizar llamafile: um executável que já inclui o modelo ou um executável independente que abre um GGUF separado. Usei a segunda opção. O teste não demonstrou a distribuição de tudo num único ficheiro nem o transporte entre vários computadores.
O que ficou igual e o que ficou por controlar
As duas ferramentas usaram CPU, com contexto configurado para 4096 tokens. Um token é uma unidade de texto processada pelo modelo; não corresponde necessariamente a uma palavra. A janela de contexto limita o texto que pode ser considerado numa interação, incluindo o histórico relevante.
No llamafile, usei -ngl 0. No Ollama, ollama ps confirmou 100% CPU, contexto 4096 e o runner llamacpp.
Os ficheiros registados localmente foram:
| Utilização | Modelo e ficheiro GGUF | Tamanho observado |
|---|---|---|
| Conversação | Qwen3 1.7B — Qwen3-1.7B-Q5_K_M.gguf |
1 257 880 032 bytes, cerca de 1,26 GB |
| Programação | Qwen2.5 Coder 3B Instruct — qwen2.5-coder-3b-instruct-q4_k_m.gguf |
2 104 932 800 bytes, cerca de 2,10 GB |
Estes são tamanhos dos ficheiros, não medições de memória ocupada durante a execução.
As versões identificadas foram llamafile 0.10.6 (visível na captura de ecrã) e Ollama v0.40.6 (informada posteriormente). Não registei todos os parâmetros de geração, e o histórico e a cache não ficaram rigorosamente uniformizados. Também não medi RAM, temperatura, consumo elétrico ou tempo até ao primeiro token. Por isso, os números seguintes descrevem ensaios exploratórios naquele computador, sem estabelecer um benchmark controlado.
Qwen3: três frases podem demorar mais do que parece
Comecei com uma pergunta simples:
Responde em português de Portugal: explica em três frases a diferença entre memória RAM e armazenamento SSD.
Com o modo de raciocínio, ou thinking, ativo, o modelo podia gerar bastante texto antes da resposta final. Em duas execuções do llamafile ficaram registados 394 e 424 tokens, com tempos apresentados de 31 e 36 segundos. No Ollama, uma execução apresentou 368 tokens gerados e cerca de 22,5 segundos totais.
Pedir três frases não significa, portanto, que só essas frases participem na geração. O controlo de thinking também depende do modelo e da ferramenta, como explica a documentação do Ollama.
Passei depois a ensaios sem thinking. Na série final, com três repetições por ferramenta, registei:
| Ferramenta | Repetição | Tokens gerados | Tempo apresentado, em segundos | Geração, em tokens/s |
|---|---|---|---|---|
| llamafile | 1 | 149 | 11 | 13,32 |
| llamafile | 2 | 139 | 10 | 12,96 |
| llamafile | 3 | 149 | 13 | 11,46 |
| Ollama | 1 | 136 | 8,736 | 17,92 |
| Ollama | 2 | 106 | 6,041 | 18,53 |
| Ollama | 3 | 120 | 6,636 | 18,27 |
Os tempos do Ollama foram arredondados para três casas decimais nesta tabela. As médias aritméticas das velocidades apresentadas são 12,58 tokens/s no llamafile e 18,24 tokens/s no Ollama: cerca de 45% acima no Ollama, relativamente ao llamafile, neste conjunto.
Esse resultado não permite afirmar que o Ollama será sempre 45% mais rápido. As respostas tinham comprimentos diferentes; houve diferenças de histórico e cache; e os tempos apresentados podem incluir fases distintas. Mesmo a utilização do mesmo GGUF não uniformiza o template que formata a conversa nem os parâmetros que influenciam a geração.
Também apareceram respostas com português mais próximo da variante brasileira e, numa saída do Ollama, a afirmação incorreta de que SSD era mais lento do que HDD. Registei o erro daquela resposta, sem o transformar num diagnóstico geral da ferramenta.
Qwen2.5 Coder: o código precisa de passar no teste
Para programação, comecei por pedir uma função calcularDesconto(preco, percentagem) que devolvesse o preço final arredondado a duas casas decimais. Devia rejeitar números não finitos, preços negativos e percentagens fora do intervalo de 0 a 100.
Na resposta obtida através do llamafile apareceu uma condição com preco <= 0. Isso rejeitava o preço zero, embora o enunciado apenas excluísse preços negativos. O teste que revela a diferença é pequeno:
calcularDesconto(0, 50); // Resultado esperado: 0
A resposta obtida através do Ollama permitia esse caso e correspondeu melhor aos requisitos funcionais. Ainda assim, os prompts deste primeiro teste não foram exatamente iguais e houve desvios ao pedido de apresentar apenas código. Não seria correto tirar daqui uma classificação geral de qualidade.
No segundo exercício, pedi a correção de uma função com erros deliberados. O cálculo devia aplicar o desconto ao subtotal e, depois, um IVA de 23% sobre o valor já descontado. A taxa era uma condição do exercício.
Este era o código de partida:
function calcularTotal(preco, quantidade, desconto) {
if (preco < 0 && quantidade < 0) {
throw new Error('Valores inválidos');
}
const subtotal = preco + quantidade;
const valorDesconto = desconto / 100;
const total = subtotal + valorDesconto * 1.23;
return Math.round(total * 100) / 10;
}
O enunciado exigia ainda números finitos, preço e quantidade maiores que zero, desconto entre 0 e 100, manutenção do nome e dos três parâmetros e arredondamento a duas casas decimais.
Ambas as respostas corrigiram partes do problema, mas ambas falharam o cálculo final. Com calcularTotal(100, 2, 10), conseguimos verificar:
| Implementação | Resultado |
|---|---|
Referência: 200 × 0,9 × 1,23 |
221,40 |
| Resposta obtida no llamafile | 2046,00 |
| Resposta obtida no Ollama | 184,60 |
No llamafile, a resposta manteve a divisão por 10 no arredondamento, não validou o desconto e usou uma base incorreta para o IVA. No Ollama, o arredondamento foi corrigido, mas o IVA foi calculado sobre o desconto, e a validação aceitava casos que deviam ser rejeitados.
Aqui importa distinguir isNaN() de Number.isFinite(): o primeiro pode converter valores antes de os avaliar; o segundo exige um número finito. A referência de JavaScript da MDN explica a diferença.
Nesta execução de correção de código, as velocidades apresentadas foram 10,20 tokens/s no llamafile e 10,72 no Ollama. São valores próximos, mas resultam de uma só resposta por ferramenta, com comprimentos diferentes. No primeiro exercício de programação, não ficou um registo fiável de duração do llamafile, pelo que não o comparo em velocidade.
A lição mais útil foi a verificação: uma resposta pode corrigir linhas, explicar com confiança o que fez e continuar errada. Dois valores de entrada conhecidos podem esclarecer mais do que um parágrafo convincente.
O que me convenceu na utilização
Consegui carregar GGUF externos e trabalhar com o llamafile sem depender de um modelo pré-empacotado. A interface Web também foi útil para copiar respostas, depois de algumas dificuldades com a seleção de texto no terminal.
O Ollama continuou a oferecer o fluxo a que já estava habituado: importar, atribuir um nome e executar. O interesse do llamafile ficou sobretudo na forma de organizar a experiência à volta de um executável e dos ficheiros de modelo.
Não testei a portabilidade entre sistemas. E o facto de uma ferramenta simplificar a distribuição não elimina os limites de memória, CPU, drivers ou backend. O resultado foi uma forma adicional de usar IA local, com vantagens práticas que não dependem de ganhar todas as medições de velocidade.
Parte II — Como repetir o procedimento no Windows
1. Preparar os ficheiros e registar as versões
Os exemplos seguintes usam PowerShell e uma pasta neutra em D:\AI-Tests. Adaptar a unidade, se necessário. Os comandos criam ficheiros de exemplo; escolher pastas novas se já existir trabalho que pretendemos preservar.
New-Item -ItemType Directory -Force -Path 'D:\AI-Tests\llamafile', 'D:\AI-Tests\models', 'D:\AI-Tests\ollama\qwen3', 'D:\AI-Tests\ollama\qwen25', 'D:\AI-Tests\results'
O Ollama já estava instalado durante a experiência. Para preparar outro computador, seguir a documentação de instalação em Windows.
Obter o executável independente na página oficial de releases do llamafile. Na revisão de 18/10/2026, a release mais recente era a 0.10.6, com o asset llamafile-0.10.6. Guardá-lo como D:\AI-Tests\llamafile\llamafile.exe, acrescentando a extensão ao nome. A versão 0.10.6 também ficou identificada numa captura de ecrã realizada durante a experiência.
A documentação de arranque explica o uso de pesos externos, incluindo a limitação de executáveis com mais de 4 GB no Windows. Essa limitação do executável não deve ser confundida com um limite de 4 GB para qualquer GGUF externo.
Para os modelos, há um cuidado de proveniência:
- O Qwen2.5 Coder 3B Instruct Q4_K_M da Qwen tem o nome e o tamanho registados no ensaio.
- Uma opção atualmente disponível para Qwen3 1.7B Q5_K_M é a distribuição da Unsloth. Porém, o ficheiro consultado tem 1 257 880 128 bytes, 96 bytes mais do que o registo original. É uma alternativa para repetir o procedimento, não uma identificação comprovada do ficheiro usado nas medições.
Guardar os GGUF em models, com os nomes usados nos comandos abaixo. Utilizar o mesmo ficheiro local nas duas ferramentas, sem trocar a quantização a meio. O nome e o tamanho ajudam a identificar um ficheiro; um hash permite verificar melhor a sua identidade.
Get-ChildItem 'D:\AI-Tests\models\*.gguf' | Select-Object Name, Length
Get-FileHash -Path 'D:\AI-Tests\models\*.gguf' -Algorithm SHA256
ollama --version
& 'D:\AI-Tests\llamafile\llamafile.exe' --version
Registar estas saídas com os resultados. As versões identificadas nesta experiência foram llamafile 0.10.6 e Ollama v0.40.6; numa nova sessão, convém confirmar e registar as versões efetivamente usadas.
2. Executar o llamafile e abrir o browser
Para tornar explícito o uso do servidor apenas no próprio computador:
Set-Location 'D:\AI-Tests\llamafile'
.\llamafile.exe --server --host 127.0.0.1 --port 8080 -m 'D:\AI-Tests\models\Qwen3-1.7B-Q5_K_M.gguf' -c 4096 -ngl 0 --gpu disable
-m seleciona o GGUF, -c 4096 define o contexto e -ngl 0 evita descarregar camadas para GPU. Acrescentei --gpu disable ao exemplo para explicitar a escolha de CPU. --server seleciona o modo Web, --host 127.0.0.1 limita a escuta à máquina local e --port escolhe a porta.
Estas opções estão descritas na referência de argumentos do llamafile 0.10.6. No ensaio também usei o modo combinado, que abre conversação no terminal e servidor Web; o exemplo acima escolhe apenas o servidor para tornar os passos mais claros.
Abrir http://localhost:8080 e enviar uma pergunta simples. Ver a página não basta: confirmar que o modelo produz uma resposta.
Para experimentar o modelo de programação, terminar o processo anterior com Ctrl+C e usar:
.\llamafile.exe --server --host 127.0.0.1 --port 8080 -m 'D:\AI-Tests\models\qwen2.5-coder-3b-instruct-q4_k_m.gguf' -c 4096 -ngl 0 --gpu disable
Se a porta estiver ocupada, escolher outra, por exemplo --port 8081, e abrir o endereço correspondente. Terminar o servidor quando acabar a sessão.
3. Desativar thinking no modo adequado
No llamafile 0.10.6, --nothink está documentado para modo CLI. Não o acrescentar indiscriminadamente a uma linha de arranque do servidor Web. Para uma pergunta independente, com Qwen3:
.\llamafile.exe --cli --nothink -m 'D:\AI-Tests\models\Qwen3-1.7B-Q5_K_M.gguf' -c 4096 -ngl 0 --gpu disable -p 'Responde em português de Portugal: explica em três frases a diferença entre memória RAM e armazenamento SSD.'
Este exemplo usa uma chamada de terminal com um prompt. Não reproduz automaticamente o estado das conversas anteriores. Para outras versões ou modos, consultar primeiro a ajuda:
.\llamafile.exe --help
.\llamafile.exe --cli --help
.\llamafile.exe --server --help
4. Importar os mesmos GGUF no Ollama
O ficheiro Modelfile é uma receita de configuração, não um comando para escrever diretamente no PowerShell. FROM indica qual é o modelo; PARAMETER define opções.
Para conservar as duas receitas, vamos usar uma pasta por modelo. No PowerShell, copiar o bloco completo:
Set-Location 'D:\AI-Tests\ollama\qwen3'
@"
FROM D:\AI-Tests\models\Qwen3-1.7B-Q5_K_M.gguf
PARAMETER num_ctx 4096
PARAMETER num_gpu 0
"@ | Set-Content -LiteralPath .\Modelfile -Encoding ascii
Get-Content -LiteralPath .\Modelfile
ollama create teste-qwen3 -f .\Modelfile
O bloco entre @" e "@ é uma here-string: uma string que ocupa várias linhas. Deve ser introduzido como uma construção única. A linha que fecha a string começa por "@, sem espaços antes. A documentação do PowerShell explica esta sintaxe.
O ficheiro chama-se Modelfile, sem .txt. Set-Content substitui o conteúdo desse ficheiro de exemplo. A codificação ASCII é suficiente para estas linhas, que usam caminhos sem acentos.
No registo original, a receita fixava num_ctx. No guia acrescentei num_gpu 0 para pedir execução em CPU. O parâmetro existe no código da versão Ollama v0.40.6 consultada; a confirmação prática continua a ser feita com ollama ps durante uma execução.
Para o segundo modelo:
Set-Location 'D:\AI-Tests\ollama\qwen25'
@"
FROM D:\AI-Tests\models\qwen2.5-coder-3b-instruct-q4_k_m.gguf
PARAMETER num_ctx 4096
PARAMETER num_gpu 0
"@ | Set-Content -LiteralPath .\Modelfile -Encoding ascii
Get-Content -LiteralPath .\Modelfile
ollama create teste-qwen25 -f .\Modelfile
A referência de Modelfile documenta a diretiva FROM, os caminhos e o contexto. As três linhas do ficheiro configuram o carregamento; não uniformizam todos os parâmetros de geração das duas ferramentas.
5. Conversar e confirmar o uso de CPU
No PowerShell:
ollama run teste-qwen3 --verbose
Dentro da conversa do Ollama, para desativar thinking, usar:
/set nothink
Este é um comando da conversa, não do PowerShell. A sintaxe foi confirmada no código do modo interativo do Ollama v0.40.6. Depende de suporte no modelo; ocultar a apresentação de thinking não deve ser confundido com desativá-lo.
Enviar depois o mesmo prompt de três frases. Para o modelo de programação, abrir ollama run teste-qwen25 --verbose e usar os enunciados da primeira parte.
Enquanto o modelo está carregado, num segundo PowerShell:
ollama list
ollama ps
Confirmar 100% CPU e contexto 4096. Se aparecer GPU ou uma distribuição mista, a execução não corresponde ao cenário descrito. A FAQ do Ollama explica a coluna PROCESSOR.
Sair da conversa com /bye. Antes de testar a outra ferramenta, podemos descarregar o modelo do Ollama:
ollama stop teste-qwen3
ollama stop teste-qwen25
Parar modelos que não estamos a usar evita que continuem carregados durante a experiência seguinte. A referência CLI documenta estes comandos.
6. Recolher resultados sem confundir as métricas
No Ollama, --verbose apresenta contagens e tempos. Avaliar o prompt é processar a entrada; gerar a resposta é produzir os tokens seguintes. Uma taxa elevada de avaliação do prompt não é a velocidade de escrita da resposta.
No llamafile, usei os contadores e as estatísticas disponíveis na interface, incluindo /stats no ambiente do ensaio. Consultar /help no modo interativo instalado para confirmar os comandos disponíveis.
Para uma nova experiência, guardar o prompt completo, a resposta em texto, o modelo, o hash, as versões, o contexto e o estado de thinking. Usar conversas novas para evitar histórico acumulado e registar se o modelo já estava carregado. Isso melhora a comparação, mas não a transforma automaticamente num estudo controlado.
Não calcular tokens/s dividindo cegamente os tokens pelo tempo total: esse tempo pode incluir carregamento e processamento da entrada. Na tabela anterior, mantive as velocidades apresentadas pelas ferramentas.
7. As dificuldades que realmente apareceram
Uma das primeiras confusões foi tratar a abertura e o fecho da here-string como comandos separados. Outra foi encontrar os sinais >> gravados no próprio Modelfile.
Quando aparece no início da linha do terminal, >> pode ser o prompt de continuação do PowerShell: está à espera de que terminemos uma construção. Esse indicador não deve ser copiado para o ficheiro. No meio de um comando, os mesmos símbolos também podem ter uma função de redirecionamento; o contexto importa.
O Modelfile deve começar pela diretiva FROM, sem >> à frente. Se o conteúdo estiver errado, recriar o bloco e confirmar com Get-Content antes de voltar a executar ollama create. Para verificar o caminho do modelo:
Test-Path 'D:\AI-Tests\models\qwen2.5-coder-3b-instruct-q4_k_m.gguf'
O resultado esperado é True. Se for False, corrigir o caminho ou o nome do ficheiro. Se o terminal estiver preso numa instrução incompleta, Ctrl+C permite cancelar essa entrada e começar novamente.
Também tive dificuldade em selecionar texto com o rato no terminal usado com llamafile. Encontrei uma opção de exportação e acabei por aproveitar o browser em localhost, onde copiar as respostas era mais simples. Essa dificuldade descreve o meu ambiente, não todos os terminais.
A passagem de uma imagem para texto chegou a separar visualmente || em | |. Não atribuí esse aparente erro de sintaxe ao modelo: havia incerteza na transcrição. Para analisar código, guardar texto exportado é preferível a tentar reconstruí-lo a partir de uma imagem.
Uma função de referência para conferir o cálculo
Esta implementação foi preparada como referência de verificação; não é uma resposta atribuída a nenhum dos modelos:
function calcularTotal(preco, quantidade, desconto) {
if (!Number.isFinite(preco) || preco <= 0 ||
!Number.isFinite(quantidade) || quantidade <= 0) {
throw new Error('Preço ou quantidade inválidos');
}
if (!Number.isFinite(desconto) || desconto < 0 || desconto > 100) {
throw new Error('Desconto inválido');
}
const subtotal = preco * quantidade;
const totalComDesconto = subtotal * (1 - desconto / 100);
const totalComIVA = totalComDesconto * 1.23;
return Math.round(totalComIVA * 100) / 100;
}
calcularTotal(100, 2, 10); // 221.4, ou 221,40 quando formatado
O exemplo ajuda a verificar os requisitos usuais do exercício. Valores monetários em produção podem exigir uma estratégia decimal ou em cêntimos, devido à representação binária dos números JavaScript; isto não é uma biblioteca de faturação.
O que fica desta experiência
O llamafile cumpriu o que mais me interessava experimentar: consegui executá-lo no Windows, carregar modelos GGUF externos e conversar com eles. O Ollama serviu de referência familiar e apresentou melhores velocidades na pequena série de Qwen3 que registei, sem que isso encerre a comparação entre ferramentas.
O ganho mais duradouro foi perceber melhor o procedimento: separar programa e modelo, confirmar CPU e contexto, importar o mesmo ficheiro e verificar as respostas com casos conhecidos.
Uma ferramenta prática poupa passos. Uma boa experiência ensina-nos também a desconfiar do resultado quando ele parece demasiado convincente. Nesta manhã e parte da tarde, houve espaço para as duas coisas.
