Avançado
llama.cpp e GGUF
O engine de inferência de arquivo único e o contêiner autodescritivo por trás dele: como o GGUF empacota o artefato de texto Q4_K_M fixado do Qwen3.8-27B em 17,1 GB (15,93 GiB), o que a escada de quants troca e quais máquinas de fato rodam o artefato.
Atualizada em
01 · Conceito
Conceito
Você baixou um arquivo. Tem exatamente 17.106.773.984 bytes na versão fixada, o nome termina em Q4_K_M.gguf, e ele afirma ser o Qwen3.8-27B. A lição 7.12 disse qual degrau da escada de quantization é esse; esta lição abre a caixa. O que há dentro de um GGUF, por que esse arquivo fixado tem 17,1 GB em vez da estimativa ingênua de 13,5 GB, e o que precisa ser verdade sobre a sua máquina antes de o arquivo valer o download?
Comece pelo engine, porque o formato existe para servi-lo. O llama.cpp é um runtime de inferência escrito em C e C++, sem dependência de runtime Python, construído sobre a biblioteca de tensors ggml. Sua restrição definidora é que um modelo precisa ser um artefato e um binário, executável numa CPU de laptop, numa GPU da Apple via Metal, numa GPU NVIDIA via CUDA ou num caminho multi-fornecedor via Vulkan, com o mesmo arquivo em todos os casos. Essa restrição produziu o GGUF.
Um arquivo GGUF é um contêiner, e o mal-entendido mais comum de todos é tratá-lo como método de compressão. Ele não é. O layout é um header de metadados chave-valor tipados, seguido de um diretório de tensors, seguido dos bytes dos tensors. Os metadados nomeiam a arquitetura, os hiperparâmetros de que um runtime precisa para montar o grafo de computação, o tokenizer completo incluindo merges e special tokens, e o chat template. O diretório de tensors dá a cada tensor um nome, um shape, um offset e — esta é a parte importante — o seu próprio tipo de quantization. Um GGUF é, portanto, autodescritivo e mapeável em memória: o runtime mapeia o arquivo, lê o manifesto, decide antes de alocar qualquer coisa se consegue montar este grafo, e pagina os pesos do disco em vez de copiá-los através de um loader.
A compressão vive nesses tipos por tensor, e eles formam uma escada. Q8_0 é um esquema de blocos de 8 bits direto, praticamente sem perdas na prática e com cerca de metade do tamanho em bf16. Os k-quants — Q6_K, Q5_K_M, Q4_K_M, Q4_K_S, Q3_K_M, até Q2_K — usam uma estrutura de super-bloco em que pequenos blocos de pesos compartilham uma escala e as próprias escalas são quantizadas contra uma escala de nível de bloco, que é como eles compram precisão em taxas baixas de bits. A letra final é uma política de mistura e não uma largura de bits: uma variante M mantém em um tipo mais alto os tensors que o conversor considera sensíveis, mais do que a variante S faz. É por isso que a aritmética da lição 7.10 fecha. Nominalmente 4 bits sobre 27 bilhões de parâmetros dão GB; as escalas, os metadados de super-bloco e os tensors deliberadamente preservados acrescentam bytes, e o artefato fixado chega a 17,1 GB (15,93 GiB). O rótulo arredondado 27B não fornece denominador suficiente para uma alegação exata de bits efetivos. A diferença não é desperdício. É a razão de o arquivo ainda ser utilizável.
Abaixo dos k-quants existe uma segunda família, os i-quants — IQ1_S, de IQ2_XXS até IQ4_XS e IQ4_NL. Eles reconstroem os pesos a partir de um codebook em vez de um inteiro escalado simples, o que lhes permite permanecer coerentes em taxas de bits onde um k-quant se desfaz. Duas coisas com que são rotineiramente confundidos, ambas dignas de ficar claras antes de você baixar um. A importance matrix é separável do formato: muitos arquivos Q4_K_M bem avaliados são calibrados por imatrix, e nem todo tipo IQ precisa de uma — o llama.cpp recusa nos seus degraus mais baixos (as famílias IQ1 e IQ2, os tipos IQ3 menores e o Q2_K_S), avisando que o resultado seria lixo, enquanto IQ4_XS e IQ4_NL são construídos sem problema. A verificação é por tensor e depende do tipo de destino, então o conjunto preciso muda entre releases. E menor não é automaticamente melhor custo-benefício, porque consultas a codebook custam tempo de decode que um k-quant não paga. Recorra a um i-quant quando a memória for a restrição vinculante, não como upgrade geral. A lição 7.13 compara esses artefatos direito.
Não repita o orçamento de memória do modelo apenas a partir do tamanho do artefato. A lição 7.2 é dona da derivação específica de KV cache e estado recorrente do modelo, e a lição 9.3 é dona do orçamento completo do acelerador depois da reserva de runtime. O estado Gated DeltaNet da implementação de referência ocupa cerca de 144 MiB por sequência quando armazenado em fp32, constante no comprimento do contexto; o llama.cpp pode usar outro dtype ou layout, e seus buffers de compute e workspace do grafo dependem do build e do backend exatos. Tanto num device de 24 GB quanto num da classe 16 GiB, carregue o GGUF exato, inspecione a alocação realizada e o offload informados pelo llama-server e valide o contexto e a concorrência pretendidos em vez de declarar que cabe a partir do teto nominal de VRAM.
llama-server -m Qwen3.8-27B-Q4_K_M.gguf -ngl 99 -c 8192 \
--temp 0.7 --top-p 0.80 --top-k 20
Se a alocação medida exigir offload parcial, o alerta de performance continua real. O decode é limitado por banda — cada token lê essencialmente todos os bytes de pesos residentes —, portanto camadas deixadas no host rodam na velocidade da memória de sistema e suas ativações atravessam o PCIe durante cada token. Uma configuração com noventa por cento das camadas na GPU não implica noventa por cento do throughput com offload completo; meça a divisão exata. A decisão honesta fica entre um artefato menor com perda de qualidade medida e o throughput medido do offload para CPU, não entre números de capacidade inferidos do nome do arquivo.
A ideia durável é separação de responsabilidades. O quantizador decidiu quantos bits cada tensor merece; o contêiner registrou essas decisões num manifesto que um runtime consegue ler antes de comprometer memória; o engine monta um grafo se reconhece a arquitetura e recusa se não reconhece. Tudo a jusante nesta track — os runners de conveniência da lição 8.8 e a comparação com o caminho próprio da Apple na lição 8.9 — está construído sobre aquele único arquivo e aquele único manifesto.
02 · Analogia
Analogia
Um contêiner de carga não é um jeito de deixar a carga menor. É uma caixa padronizada com um manifesto parafusado na porta: o que há dentro, em que unidades, embalado por quem e quais guindastes conseguem erguê-lo. Qualquer porto que leia o manifesto consegue descarregá-lo sem abrir a caixa antes. O GGUF é esse contêiner para pesos de modelo — a compressão aconteceu antes do empacotamento, e o manifesto é o que permite a um runtime recusar um load que ele não consegue honrar em vez de falhar no meio do caminho.
03 · Explique de volta
Explique de volta
Explique o que o GGUF realmente é, distinga-o de um método de quantization e explique como você validaria um deployment do Qwen3.8-27B Q4_K_M numa GPU de 24 GB e numa GPU de 16 GB.
Comparar com uma resposta-modelo
GGUF é um formato de contêiner, não um algoritmo de compressão: um arquivo guarda metadados tipados e dados de tensors, e cada tensor carrega o próprio tipo de quantization. Os esquemas k-quant fazem a compressão, e um arquivo pode misturar tipos para preservar tensors sensíveis em precisão mais alta. O artefato comunitário Q4_K_M fixado do modelo de texto tem 17.106.773.984 bytes: 17,1 GB, ou 15,93 GiB. Não infira um valor exato de bits efetivos por peso do rótulo arredondado 27B, pois o arquivo mistura tipos de tensor e o denominador exato precisa vir dos tensors contidos nele. Saber se ele cabe numa GPU de 24 GB ou de 16 GB é uma medição de runtime, não o tamanho do artefato subtraído da VRAM de catálogo: a lição 7.2 é dona da derivação de cache e estado recorrente, incluindo cerca de 144 MiB por sequência para o estado DeltaNet em fp32 da referência, enquanto a lição 9.3 é dona do orçamento completo do device. O llama.cpp pode usar outro dtype ou layout de estado. Carregue o artefato e o build exatos, inspecione as alocações realizadas e trate qualquer offload parcial necessário para CPU como um caminho de banda a medir, não como desaceleração percentual graciosa.
04 · Teste seu entendimento
Teste seu entendimento
Conclua o teach-back e acerte o quiz para finalizar a aula.
◎ · Marcador de evidência
Fontes
- Georgi Gerganov e contribuidores (2023). llama.cpp.
- Qwen Team (2026). Qwen3.8-27B Model Card.