A fórmula: cos(θ) = (A · B) / (||A|| × ||B||), onde A · B é o produto escalar e ||A||, ||B|| são as magnitudes (comprimentos) dos vetores. Ao dividir pelas magnitudes, a similaridade de cosseno mede apenas a direção — um vetor [1, 2, 3] é idêntico em similaridade de cosseno a [2, 4, 6] porque apontam na mesma direção. Essa normalização é o motivo pelo qual o cosseno funciona bem para embeddings: a direção codifica o significado, enquanto a magnitude pode variar com base no comprimento do texto ou peculiaridades do modelo.
Se os embeddings já estão normalizados para comprimento unitário (magnitude 1), a similaridade de cosseno é igual ao produto escalar — e o produto escalar é mais rápido de computar (sem divisão). A maioria dos modelos de embedding gera vetores normalizados exatamente por isso. Ao usar um banco de dados vetorial, verifique se seus embeddings são normalizados: se sim, use produto escalar (mais rápido). Se não, use similaridade de cosseno (correto independentemente da normalização).
A similaridade de cosseno trata todas as dimensões igualmente, mas algumas dimensões de embedding podem ser mais importantes que outras. Ela também mede a similaridade geral de direção, o que pode perder diferenças sutis. Duas frases sobre "programação Python" e "Python a cobra" podem ter similaridade de cosseno moderadamente alta porque compartilham o conceito "Python". Medidas de similaridade mais sofisticadas (métricas aprendidas, re-ranking com cross-encoder) podem capturar distinções mais finas a um custo computacional maior.