NexusQuant: compressão de memória para LLMs — guia prático
Neste guia vamos explorar os três presets de qualidade do NexusQuant em detalhe: quando usar cada um, o que esperar em termos de qualidade, e como o comportamento muda consoante o domínio do texto.
Instalação rápida
pip install "nexusquant-kv[hf]"
Os três presets explicados
high — Compressão conservadora (10x)
O preset high é o ponto de entrada seguro. Remove apenas os tokens de menor impacto e quantiza com margens confortáveis.
from nexusquant import nexusquant_evict
with nexusquant_evict(model, quality="high"):
output = model.generate(input_ids, max_new_tokens=512)
Quando usar:
- RAG com documentos técnicos ou legais onde a precisão importa
- Q&A sobre código-fonte
- Qualquer tarefa onde erros factuais têm custo real
- Primeiro deploy em produção (começa aqui, mede, depois sobe)
O que esperar:
- PPL +0.4% — praticamente imperceptível
- 10x compressão — 128K → 1.3M tokens em 80 GB
- Comportamento estável em contextos curtos e longos
balanced — O ponto ideal (17x)
with nexusquant_evict(model, quality="balanced"):
output = model.generate(input_ids, max_new_tokens=512)
Quando usar:
- Sumarização de documentos longos
- Chatbots com histórico de conversa longo
- Análise de código com contexto alargado
- A maioria dos casos de uso em produção
O que esperar:
- PPL +1.3% — ligeiro, normalmente não notável pelo utilizador final
- 17x compressão — 128K → 2.2M tokens em 80 GB
- Bom equilíbrio entre memória e qualidade
max — Compressão máxima (33x)
with nexusquant_evict(model, quality="max"):
output = model.generate(input_ids, max_new_tokens=512)
Quando usar:
- Processamento em batch onde throughput é mais importante que qualidade perfeita
- Exploração de documentos muito longos (busca, triagem)
- Investigação e benchmarking
- Contextos onde o utilizador tolera alguma degradação
O que esperar:
- PPL +2.6% — notável, especialmente em texto criativo
- 33x compressão — 128K → 4.2M tokens em 80 GB
- Pode haver omissões em detalhes específicos do contexto
Sensibilidade por domínio
O mesmo preset comporta-se de forma diferente consoante o tipo de texto. Em linhas gerais:
| Domínio | Sensibilidade | Preset recomendado |
|---|---|---|
| Código / técnico | Baixa |
balanced ou max
|
| Académico / científico | Baixa | balanced |
| Jornalístico / factual | Média |
high ou balanced
|
| Criativo / narrativo | Alta | high |
| Jurídico / contratual | Alta | high |
Texto estruturado (código, JSON, tabelas) é mais robusto ao eviction porque a estrutura local preserva o contexto. Texto narrativo depende mais de referências de longo alcance que podem ser evictadas.
Prefixes curtos: cuidado
O scorer de importância precisa de sinal suficiente para distinguir tokens relevantes de irrelevantes. Com menos de ~500 tokens, os resultados são menos fiáveis.
# Mau: prefix curto
input_ids = tok("O que é machine learning?", return_tensors="pt").input_ids
# ~6 tokens — o scorer não tem sinal suficiente
# Bom: context rico
long_prompt = document_text + "\n\nPergunta: O que é machine learning?"
input_ids = tok(long_prompt, return_tensors="pt").input_ids
# 800+ tokens — o scorer funciona bem
Detetar regressão no teu workload
Antes de fazer deploy, corre uma comparação rápida:
import math
from nexusquant import nexusquant_evict
def perplexity(model, tok, text, device="cpu"):
"""Calcula perplexidade de um texto."""
ids = tok(text, return_tensors="pt").input_ids.to(device)
with torch.no_grad():
loss = model(ids, labels=ids).loss
return math.exp(loss.item())
baseline_ppl = perplexity(model, tok, your_domain_text)
for preset in ["high", "balanced", "max"]:
with nexusquant_evict(model, quality=preset):
ppl = perplexity(model, tok, your_domain_text)
delta = (ppl - baseline_ppl) / baseline_ppl * 100
print(f"{preset}: PPL {ppl:.2f} ({delta:+.2f}%)")
Se o delta for aceitável para o teu caso de uso, avança com esse preset.
Exemplo completo: sumarização de documento longo
from transformers import AutoModelForCausalLM, AutoTokenizer
from nexusquant import nexusquant_evict
import torch
model = AutoModelForCausalLM.from_pretrained(
"TinyLlama/TinyLlama-1.1B-Chat-v1.0",
torch_dtype=torch.float16,
device_map="auto",
)
tok = AutoTokenizer.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0")
# Documento longo (substitui pelo teu)
document = open("relatorio_anual.txt").read()
prompt = document + "\n\nResumo executivo em 3 pontos:\n"
input_ids = tok(prompt, return_tensors="pt").input_ids.to(model.device)
print(f"Tokens no prompt: {input_ids.shape[1]}")
# Compressão 17x — ideal para sumarização
with nexusquant_evict(model, quality="balanced"):
output = model.generate(
input_ids,
max_new_tokens=200,
do_sample=False,
temperature=1.0,
)
resume = tok.decode(output[0][input_ids.shape[1]:], skip_special_tokens=True)
print(resume)
Notebook interativo no Colab
Podes correr todos estes exemplos no teu browser, sem GPU, em menos de 2 minutos:
github.com/jagmarques/nexusquant/blob/main/examples/nexusquant_demo.ipynb
Resumo
- Começa sempre com
quality="high"e mede no teu domínio -
balancedé o sweet spot para a maioria dos casos em produção -
maxé para quando o throughput importa mais que qualidade perfeita - Prefixes curtos degradam mais — dá contexto suficiente ao scorer
- Texto criativo/narrativo é mais sensível que texto técnico/estruturado
Cumprimentos, João Marques
Top comments (0)