TurboQuant: 7,9× Menos RAM em Embeddings — Roda 8× Mais Docs na Mesma GPU
Embeddings de texto consomem até 80% da memória GPU em sistemas RAG de escala. Para 1 milhão de documentos com embeddings de dimensão 384, são necessários 1,5 GB em float32. Com 10 milhões de documentos, isso escala para 15 GB, exigindo sharding complexo ou offloading para CPU com latência elevada.
Implementei uma biblioteca Python com os quatro principais métodos do TurboQuant (Google Research, 2025) usando apenas NumPy. Os experimentos utilizam um corpus real de 591 documentos técnicos do Redis, indexados com o modelo BAAI/bge-small-en-v1.5.
Repositório completo com benchmarks
Resultados Principais
TurboQuantMSE 4-bit atinge 7,9× de compressão (192 MB vs 1,5 GB baseline) com recall@10 de 0.925 (-1 pp vs float32). Em 2-bit, alcança 15,7× de compressão (96 MB) mantendo o mesmo recall.
A latência de busca HNSW/FAISS permanece inalterada, pois a desquantização é vetorizada e ocorre durante a busca.
Comparação Detalhada
| Método | Memória (1M docs) | Compressão | Recall@10 | Degradação |
|---|---|---|---|---|
| float32 | 1,5 GB | 1× | 0.935 | — |
| TurboQuantMSE 4-bit | 192 MB | 7,9× | 0.925 | -1 pp |
| TurboQuantMSE 2-bit | 96 MB | 15,7× | 0.925 | -1 pp |
| Uniform 2-bit | 96 MB | 15,7× | 0.425 | -51 pp |
| Product Quantization | 192 MB | 7,9× | 0.892 | -4,3 pp |
Validação em Pipeline RAG
Query de teste: "Como o Redis lida com falta de memória?"
Resposta float32 (top 5 documentos):
1. "Redis usa eviction policies LRU/LFU quando maxmemory é atingida"
2. "Configuração maxmemory-policy allkeys-lru é padrão"
3. "Memória OOM protegida por políticas de eviction"
Resposta TurboQuantMSE 4-bit (7,9× menos RAM):
[Idêntica à float32 - mesma ordem de documentos]
Resposta Uniform 2-bit:
[Documentos irrelevantes sobre NestJS e autenticação]
Métodos Implementados
1. TurboQuantMSE (Método Principal)
Inovação central: Rotação ortogonal aleatória antes da quantização escalar.
Pipeline matemático:
1. R ← matriz ortogonal aleatória d×d
2. y = embeddings × Rᵀ (rotação)
3. ŷ ← LloydMax(y, b bits) (quantização por dimensão)
4. x̂ = ŷ × R (des-rotação)
Por que funciona: Embeddings têm covariância não-isotrópica. A rotação uniformiza a variância entre dimensões, permitindo quantização escalar independente com MSE ótimo.
2. TurboQuantProd (Para Similaridade Cosseno)
TurboQuantMSE + correção de bias no produto interno.
Aplica quantização 1-bit no erro residual para estimativas não viesadas:
similarity_corrigida = <q̂, k̂> + correção_residuo(||q - q̂||, ||k - k̂||)
Preserva 99,8% da similaridade cosseno vs float32.
3. Comparações Baseline
- Uniform Quantization: Divisão equiespaçada por dimensão
- Lloyd-Max puro: Codebook ótimo sem rotação
Vantagens vs Product Quantization
- Indexação em tempo zero (sem k-means pesado)
- 11× menor MSE na mesma taxa de bits
- Totalmente vetorizável em GPU/CPU
- Recall superior em baixas taxas de bits
Como Aplicar no Seu Projeto
# Quantize seus embeddings
python compress_embeddings.py \
--input your_embeddings.npy \
--method turboquant_mse \
--bits 4 \
--output embeddings_4bit.npz
# Indexe no FAISS
python index_embeddings.py \
--embeddings embeddings_4bit.npz \
--index_type HNSW
Paper original: TurboQuant: Online Vector Quantization with Near-optimal Distortion Rate
Teste no seu ambiente e compartilhe os resultados!