Um modelo de embeddings roda 100% local via WebAssembly. Calculamos similaridade do cosseno entre a sua pergunta e cada documento — sem enviar nada para um servidor.
Faça uma busca para ver o vetor real gerado pelo modelo.
Faça uma busca para ver o cálculo real.
Interceptamos window.fetch ao carregar a página e contamos toda chamada de rede. A única rede usada é o download único do modelo (~50MB, cacheado pelo navegador — recarregue e veja). Abra o DevTools → Network e confira você mesmo enquanto digita uma busca: nenhuma requisição sai.
Aguarde o modelo terminar de baixar para o contador "após modelo carregar" começar.
// 1) Load the model once (download cached in the browser)
const extractor = await pipeline(
"feature-extraction",
"Xenova/paraphrase-multilingual-MiniLM-L12-v2",
{ quantized: true },
);
// 2) Each text becomes a 384-dim vector, already normalized (L2 = 1)
async function embed(text) {
const out = await extractor(text, { pooling: "mean", normalize: true });
return out.data; // Float32Array(384)
}
// 3) Since vectors are normalized, cosine == dot product
function cosine(a, b) {
let s = 0;
for (let i = 0; i < a.length; i++) s += a[i] * b[i];
return s; // ∈ [-1, 1] — higher means more similar
}Esse é o trecho real que produziu o vetor e o score acima — veja src/lib/semantic-search.ts no repositório.
O sistema procura as palavras "dinheiro", "graça", "celular" nos textos. Nenhum documento contém todas essas palavras juntas — o card do Pix (que é exatamente a resposta) fica enterrado ou nem aparece.
O modelo entende que "mandar dinheiro de graça na hora pelo celular" significa transferência instantânea gratuita — e o card do Pix sobe para o 1º lugar. Sem reescrever a query, sem sinônimos manuais.
Cada documento do corpus vira um vetor (embedding) de 384 dimensões. Acontece uma vez ao abrir a página.
Sua pergunta é convertida pelo mesmo modelo num vetor que captura significado — não só palavras.
Calculamos o cosseno entre o vetor da pergunta e cada vetor do corpus. Quanto maior, mais relacionado.
Ordenamos por score. O melhor resultado fica no topo, mesmo sem nenhuma palavra em comum.