Eu Implementei um Paper de Pesquisa do Google como uma Biblioteca JS Open-Source
Tudo começou com um vídeo no YouTube.
Eu estava assistindo ao canal do Lucas Montano quando ele detalhou um paper do Google Research — TurboQuant: Online Vector Quantization, aceito no ICLR 2026. Ele comparou com o Pied Piper de Silicon Valley: compressão sem perda que realmente funciona, só que dessa vez é real e foi projetada para a era da IA. O tweet do Google sobre o paper bateu 19 milhões de views. Ações da Micron e SanDisk caíram com a notícia — se o TurboQuant entregar o que promete, a demanda por hardware de memória em infraestrutura de IA pode cair drasticamente.
Mas o que mais chamou minha atenção foi o Lucas mostrando a própria implementação. Ele construiu o TurboQuant dentro do Perssua, o SaaS de assistentes de IA dele, para resolver um problema concreto: usuários fazem upload de pastas inteiras de documentos para criar bases de conhecimento pros seus assistentes, e os vector embeddings desses documentos estavam consumindo toda a memória do client. A solução dele foi comprimir os índices de embedding usando TurboQuant e armazenar tudo no IndexedDB — sem servidor, sem cloud, tudo client-side. Depois de indexar mais de 400 roteiros de vídeo, o consumo de memória ficou estável.
Foi aí que tive o insight: se resolveu um problema real no produto dele, poderia resolver pra muitos outros devs também. As implementações existentes, até então, dependiam de WASM ou binários nativos. Não tinha nada que você pudesse simplesmente dar npm install e usar em TypeScript puro.
Então pensei: por que não construir como uma biblioteca open-source?
Venho sendo consumidor assíduo de open source durante toda minha carreira — npm install e pip install pra todo lado, mas nunca tinha estado do outro lado. Nunca tinha publicado algo que outros desenvolvedores pudessem usar. Então porque não tentar com este insight?
turboquant-js é o resultado: uma implementação em TypeScript puro do algoritmo TurboQuant. Zero dependências, funciona no Node.js e em browsers, ~15 KB no bundle.
npm install turboquant-jsOu veja em ação: Demo — Semantic Search Client-Side
Primeiro, o que são vector embeddings?
Se você já trabalhou com full-text search (Elasticsearch, PostgreSQL tsvector), sabe como funciona: você busca por keywords. Pesquise "voos baratos para Paris" e vai encontrar documentos contendo essas palavras.
Vector embeddings são o próximo passo. Em vez de buscar keywords, um modelo de IA converte texto (ou imagens, áudio, etc.) em um array de números — tipicamente 384 ou 768 floats. Esses arrays capturam significado, não apenas palavras. Duas frases com palavras completamente diferentes mas significado similar terão arrays similares.
// Um embedding é isso — um array comum de números
const embedding = [0.023, -0.041, 0.089, ..., 0.017]; // 384 floatsPara buscar por significado, você compara esses arrays usando matemática (cosine similarity ou dot product). Quanto mais próximos dois arrays, mais similar o significado.
É isso que alimenta features como "produtos similares", "artigos relacionados", barras de semantic search e, cada vez mais, RAG (Retrieval-Augmented Generation) — onde um LLM busca contexto relevante antes de responder uma pergunta.
O problema: embeddings são caros para armazenar
Cada embedding é apenas um Float64Array, mas eles se acumulam rápido:
| Documentos | Dimensões | Tamanho bruto |
|---|---|---|
| 1.000 | 384 | 3 MB |
| 100.000 | 384 | 300 MB |
| 1.000.000 | 384 | 3 GB |
Se você está rodando um servidor, 3 GB é administrável. Mas e se você quiser rodar isso no browser? Para uma feature de busca privacy-first, um app offline, ou uma browser extension? 3 GB no client é inviável.
Esse é exatamente o problema que o Lucas enfrentou no Persua: centenas de documentos convertidos em vetores, todos armazenados client-side, sem espaço para a memória crescer linearmente. E é o mesmo problema que você vai encontrar se estiver construindo qualquer feature de IA client-side que trabalha com embeddings.
A solução típica é usar um vector database server-side (Pinecone, Qdrant, Weaviate) ou uma biblioteca compilada em WASM como o FAISS. Mas essas opções têm trade-offs:
- Databases server-side significam que seus dados saem do client — ruim para casos de uso sensíveis à privacidade
- FAISS-WASM é um blob binário de ~2 MB com um processo de build complexo
- Product Quantization (PQ), a técnica de compressão padrão, requer uma etapa de treinamento — você precisa de um dataset representativo para "ensinar" o compressor como são seus dados antes de poder usá-lo
E se você pudesse comprimir esses 3 GB para ~150 MB sem servidor, sem WASM, sem etapa de treinamento — apenas npm install e algumas linhas de TypeScript?
O que o TurboQuant faz de diferente
Pense nisso como compressão de imagem. Um JPEG comprime uma foto descartando detalhes visuais que seus olhos não vão notar. O TurboQuant faz algo similar para arrays de números: ele comprime cada float para 2-4 bits preservando as relações matemáticas entre os vetores.
A propriedade crítica — e é isso que empolgou o Lucas no vídeo dele — é que quando você compara dois vetores comprimidos, o score de similaridade que você obtém não é sistematicamente errado. Pode ter um pequeno ruído aleatório (como qualquer compressão), mas não desvia consistentemente para uma direção. O paper prova isso matematicamente. Como o Lucas disse, referenciando Silicon Valley: "o que o Richard Hendricks tentou fazer em seis temporadas, o Google fez de verdade — e funciona."
Com quantização de 3-bit, você consegue 20.8x de compressão:
| Formato | Tamanho por 1M docs | Compressão |
|---|---|---|
| float64 (bruto) | 3 GB | 1x |
| quantizado 4-bit | 192 MB | 15.7x |
| quantizado 3-bit | 144 MB | 20.8x |
| quantizado 2-bit | 98 MB | 30.7x |
Essa é a diferença entre "impossível no browser" e "totalmente viável".
Como funciona (sem precisar de PhD)
O algoritmo combina três técnicas — e o Lucas na verdade passou pelas três no vídeo dele, o que me ajudou a entendê-las antes de mergulhar no paper:
Passo 1: Rotação aleatória. Antes de comprimir, o TurboQuant rotaciona aleatoriamente o vetor usando uma rotação ortogonal. Pense nisso como embaralhar os números para que nenhuma coordenada individual seja mais importante que as outras. Isso simplifica a geometria e torna a compressão por coordenada quase ótima.
Passo 2: Quantização escalar. Uma vez rotacionado, cada número segue uma distribuição previsível, e você pode arredondá-lo para um pequeno conjunto de valores (o "codebook") que são pré-computados para minimizar o erro. Sem treinamento necessário — o codebook é determinado puramente por matemática.
Passo 3: Correção de erro QJL. Arredondar introduz erro, e esse erro tornaria as comparações de similaridade levemente enviesadas — como uma balança que consistentemente marca 0,5 kg a mais. O TurboQuant corrige isso com um termo de correção de 1 bit baseado na projeção Quantized Johnson-Lindenstrauss. Como o Lucas explicou: "te custa um bit extra, mas o resultado é precisão quase perfeita no cálculo de attention score." O resultado: scores de similaridade em vetores comprimidos são estimativas não-enviesadas dos scores verdadeiros.
Você não precisa entender a matemática para usar a biblioteca. Mas se tiver curiosidade, tem um THEORY.md detalhado mapeando a implementação ao paper.
Construindo: vibe coding um paper de pesquisa
Aqui vai um detalhe que conecta minha história com a do Lucas: ele também usou IA para implementar o TurboQuant. No vídeo, ele mencionou que alimentou o Claude Code com os papers do Google e a ferramenta implementou o algoritmo pro Persua. Eu fiz a mesma coisa — construí a turboquant-js quase inteiramente via vibe coding.
Estamos em um momento onde toda empresa está correndo para integrar IA nos seus workflows, e eu queria testar como é construir um projeto não-trivial do zero com IA como co-piloto. Não um app de todo list ou uma API CRUD — uma implementação real de um paper de pesquisa com matemática de verdade, operações bit a bit e requisitos de precisão numérica.
O processo foi genuinamente surpreendente. Coisas como a Randomized Hadamard Transform, geração de codebook Lloyd-Max com quadratura adaptativa de Simpson, e bit-packing em buffers Uint8Array — são o tipo de tarefa onde você normalmente gastaria dias lendo livros e debugando erros de off-by-one. Com assistência de IA, eu pude focar em entender o quê o algoritmo precisava fazer e deixar o tooling lidar com a tradução mecânica para TypeScript funcional.
Dito isso, não foi apenas "dar prompt e fazer deploy." Eu precisei entender o paper suficiente para validar o output, escrever testes significativos (196 deles, incluindo z-tests estatísticos para não-enviesamento), e tomar decisões arquiteturais que a IA não podia tomar por mim — como escolher a Randomized Hadamard Transform em vez de decomposição QR densa para o passo de rotação, o que reduziu a complexidade de O(d³) para O(d log d).
A conclusão: vibe coding funciona surpreendentemente bem para implementar algoritmos bem definidos. O paper era a spec, a matemática era o test oracle, e a IA era o tradutor entre os dois. Não é mágica — você ainda precisa entender o que está construindo — mas reduz dramaticamente a barreira para transformar um paper de pesquisa em software funcional.
Usando na prática
A biblioteca expõe duas APIs de alto nível. Se você já usou algum ORM ou search client, o padrão vai parecer familiar.
Vector search index
import { VectorIndex } from 'turboquant-js';
// Criar um index — como criar uma tabela
const index = new VectorIndex({ dimension: 384, bits: 3, metric: 'cosine' });
// Adicionar vetores — como inserir linhas
index.add('doc1', embedding1);
index.add('doc2', embedding2);
index.add('doc3', embedding3);
// Buscar — como uma query, mas por significado em vez de keywords
const results = index.search(queryEmbedding, 10);
// => [{ id: 'doc2', score: 0.93 }, { id: 'doc1', score: 0.87 }, ...]
// Verificar quanta memória você economizou
console.log(index.memoryUsage);
// => { compressionRatio: 20.8, actualBytes: 7200 }
// Salvar em disco / IndexedDB / enviar pela rede
const buffer = index.toBuffer();
// Depois: restaurar
const restored = VectorIndex.fromBuffer(buffer, { dimension: 384 });KV cache compression (para aplicações com LLM)
Se você está trabalhando com LLMs no browser (usando Transformers.js ou WebLLM), o KV cache é um grande gargalo de memória — é a memória de curto prazo que cresce a cada token que o modelo gera. É exatamente o problema que o paper do Google ataca, e que o Lucas demonstrou com o Gemma 3 12B indo de 6 GB para menos de 5 GB de uso de RAM:
import { KVCacheCompressor } from 'turboquant-js';
const compressor = new KVCacheCompressor({
keyDim: 128, valueDim: 128,
keyBits: 3, // attention scores não-enviesados
valueBits: 2, // reconstrução de valores com baixo erro
});
compressor.append(keys, values);
const scores = compressor.attentionScores(queryVector);Benchmarks
Números reais do npm run bench:
| Dimensão | Bits | Erro médio (MSE) | Viés | Compressão |
|---|---|---|---|---|
| 384 | 2 | 0.0012 | ~0 | 30.7x |
| 384 | 3 | 0.00074 | ~0 | 20.8x |
| 384 | 4 | 0.0006 | ~0 | 15.7x |
Para colocar o erro em perspectiva: um MSE de 0.00074 significa que o erro médio por coordenada é cerca de 0.027. Para um vetor de 384 dimensões, isso é desprezível — os resultados de busca são praticamente idênticos aos de uma busca sem compressão.
A demo mostra isso concretamente: com quantização de 3-bit, 3 de 5 resultados do top geralmente coincidem com a busca exata por força bruta.
Live Demo
A melhor forma de entender o que isso possibilita é experimentar você mesmo. A demo roda um pipeline completo de semantic search no seu browser:
- Baixa um modelo de embedding pequeno (~30 MB) via Transformers.js
- Converte 50 artigos em vetores de 384 dimensões
- Comprime com turboquant-js (3-bit por padrão — compressão de 20.8x)
- Permite buscar por significado, não por keywords
Tudo roda client-side. Sem servidor, sem chamadas de API, sem dados saindo do seu browser. Você pode alternar entre quantização de 2, 3 e 4-bit e ver o trade-off qualidade/compressão em tempo real. A demo mostra resultados lado a lado comparando a busca quantizada com a busca exata por força bruta.
Como se compara
| turboquant-js | FAISS-WASM | Pinecone / Qdrant | |
|---|---|---|---|
| Runtime | TypeScript puro | Binário WASM | Server-side |
| Setup | npm install |
Build complexo | API key + infra |
| Treinamento | Nenhum | Sim (PQ) | N/A |
| Scores não-enviesados | Sim (provado) | Não | N/A |
| Bundle size | ~15 KB | ~2 MB | N/A |
| Privacidade | Dados ficam no client | Dados ficam no client | Dados vão para o servidor |
Quando você usaria isso?
- Assistentes de IA com bases de conhecimento — Exatamente o que o Lucas construiu no Persua: deixar usuários fazerem upload de pastas de documentos, gerar embeddings, comprimir os índices e buscar por significado — tudo no browser, armazenado no IndexedDB.
- Browser extensions — Indexar bookmarks, histórico ou notas para semantic search local. Dados nunca saem do dispositivo.
- Apps offline — Construir features de busca ou RAG que funcionam sem internet. Combine com Transformers.js para o modelo de embedding.
- Features privacy-first — "Documentos similares" ou "busca inteligente" onde dados do usuário devem ficar client-side (LGPD, saúde, jurídico).
- Edge functions — Cloudflare Workers e Vercel Edge rodam JS mas não WASM. turboquant-js funciona nesses ambientes (~15 KB).
- Prototipagem — Precisa de vector search em um side project? Pule os containers Docker e API keys.
npm install, três linhas de código, pronto.
De consumidor a contribuidor
Construir a turboquant-js foi um marco pra mim. Depois de anos sendo o lado receptor do open source — usando bibliotecas de outras pessoas, lendo código de outras pessoas — eu finalmente publiquei algo meu.
O Lucas disse algo no vídeo dele que ficou comigo: ele ficou chocado que ninguém estava realmente falando sobre o TurboQuant, apesar do potencial. Eu senti a mesma coisa — e em vez de apenas falar sobre, decidi tornar acessível. A um único npm install de distância de qualquer pessoa que precise.
Se você tem pensado em fazer sua primeira contribuição open-source mas não sabe por onde começar, aqui vai o que aprendi: encontre um paper, uma técnica ou uma ferramenta que resolve um problema real, e torne acessível. O mundo não precisa de mais um framework. Precisa de mais pontes entre pesquisa e prática.
Experimente
npm install turboquant-js- GitHub: github.com/danilodevhub/turboquant-js
- npm: npmjs.com/package/turboquant-js
- Demo: danilodevhub.github.io/turboquant-js-examples
- Paper: arxiv.org/abs/2504.19874
A biblioteca é MIT-licensed e contribuições são bem-vindas. Se você está construindo algo com vector embeddings em JavaScript, adoraria saber como você usa — abra uma issue ou entre em contato.
turboquant-js é baseado no paper "TurboQuant: Online Vector Quantization" de Zandieh, Daliri, Hadian e Mirrokni (ICLR 2026).