Escolher o modelo de embedding: dimensão, idioma e custo
A escolha do modelo de embedding define a qualidade da busca, o tamanho do índice e o custo de reprocessar tudo quando você mudar de ideia. Vale decidir com dado, não por ranking.
Equipe EasyOps Cloud · · 8 min de leitura
Todo projeto de busca semântica passa por essa escolha cedo, e ela costuma ser feita pelo caminho errado: pegando o primeiro colocado de algum ranking público.
O problema é que esses rankings medem desempenho médio em conjuntos de teste em inglês, sobre tarefas genéricas. A sua busca é em português, sobre o seu domínio, com as perguntas dos seus usuários — e a correlação entre uma coisa e outra é menor do que parece.
A escolha importa porque ela define três coisas de uma vez: qualidade da busca, tamanho do índice e custo de mudar de ideia depois.
O que um embedding faz
Ele converte texto em uma lista de números que posiciona aquele trecho num espaço. Textos com significado próximo ficam próximos nesse espaço, o que permite buscar por sentido em vez de por palavra.
A consequência prática que decide tudo: a busca só é boa se o modelo posicionar bem o seu tipo de conteúdo. Um modelo treinado majoritariamente em inglês aproxima mal termos técnicos em português; um treinado em texto genérico não distingue nuances de um domínio específico.
Dimensão: a variável mais subestimada
Modelos produzem vetores de tamanhos diferentes — 384, 768, 1024, 1536, 3072. Mais dimensões significam mais capacidade de representar nuance, e custo proporcional em tudo.
| Dimensões | 1 milhão de vetores | Uso indicado |
|---|---|---|
| 384 | ~1,5 GB | Base pequena, busca simples |
| 768 | ~3 GB | Bom equilíbrio |
| 1536 | ~6 GB | Padrão de muitas APIs |
| 3072 | ~12 GB | Só com ganho comprovado |
Some 30% a 50% para o índice, e lembre que ele precisa caber na RAM — assunto do artigo sobre banco vetorial.
O ponto que costuma surpreender: a diferença de qualidade entre 768 e 1536 dimensões é, em muitos casos práticos, pequena — enquanto a diferença de custo de memória é o dobro. Vale medir antes de assumir que maior é melhor.
Alguns modelos recentes permitem truncar o vetor, mantendo a maior parte da qualidade com menos dimensões. Se o seu permitir, isso dá uma alavanca de custo sem trocar de modelo.
Português importa mais do que se supõe
Modelo multilíngue não significa igualmente bom em todos os idiomas. Termos técnicos, gíria regional, abreviação de domínio e concordância aparecem com qualidade bem variável.
Um teste rápido revela muito. Pegue pares que deveriam ser próximos no seu domínio, e pares que deveriam ser distantes, e confira se o modelo concorda:
pares_proximos = [
("cancelar assinatura", "quero encerrar meu plano"),
("nota fiscal", "NF-e"),
("prazo de entrega", "quando chega meu pedido"),
]
pares_distantes = [
("cancelar assinatura", "assinar contrato"),
("segunda via de boleto", "boleto vencido"),
]Um modelo que não aproxima "cancelar assinatura" de "quero encerrar meu plano" vai falhar na sua busca, independentemente de posição em ranking.
Esse teste leva vinte minutos e vale mais que qualquer comparativo publicado, porque usa o seu vocabulário.
Avaliar com o seu conteúdo
O método honesto exige um conjunto pequeno de perguntas com o documento correto anotado:
[
{"pergunta": "qual o prazo para cancelar sem multa?",
"doc_correto": "politica-cancelamento-v3"},
{"pergunta": "como emitir segunda via?",
"doc_correto": "faq-financeiro-boletos"}
]Trinta perguntas bastam para diferenciar modelos. Com elas, a métrica é direta: em quantas o documento correto apareceu entre os cinco primeiros resultados?
def avaliar(modelo, indice, casos, k=5):
acertos = 0
for c in casos:
r = indice.buscar(modelo.embed(c["pergunta"]), k=k)
if c["doc_correto"] in [d.id for d in r]:
acertos += 1
return acertos / len(casos)Compare dois ou três candidatos com o mesmo conjunto. A diferença costuma ser clara — e às vezes o modelo menor e mais barato vence, o que só se descobre medindo.
Repare que essa métrica é sobre recuperação, não sobre a resposta final. É a separação defendida no artigo sobre avaliação: se o trecho certo não é recuperado, nenhum modelo de linguagem compensa.
Local ou API
Embedding é uma das tarefas de IA mais viáveis localmente. Os modelos são pequenos — frequentemente algumas centenas de megabytes — e rodam bem em CPU.
Local faz sentido quando o volume de indexação é alto, quando o conteúdo não pode sair, ou quando você quer estabilidade: o modelo não muda sem você mandar.
API faz sentido para começar, para volume baixo, e quando você quer os modelos maiores sem infraestrutura.
Há um risco específico da API que vale conhecer: se o fornecedor atualizar o modelo, os vetores novos podem não ser comparáveis com os antigos. Todo o índice precisa ser recalculado, e isso costuma ser descoberto quando a busca começa a devolver resultado estranho. Fixe a versão do modelo sempre que a API permitir.
O custo de trocar depois
Aqui está a razão de a escolha merecer cuidado: trocar de modelo exige reindexar tudo. Vetores de modelos diferentes não são comparáveis, nem que tenham a mesma dimensão.
Para cem mil trechos, reindexar leva horas e custa dinheiro. Para milhões, vira projeto com janela de manutenção.
Três medidas reduzem esse custo antes de ele existir:
- Guarde o texto original junto com o vetor. Reindexar a partir do texto é possível; a partir do vetor, não.
- Registre qual modelo e qual versão gerou cada vetor. Sem isso, uma base com vetores de duas gerações misturados produz busca silenciosamente ruim.
- Isole a geração de embedding atrás de uma interface no seu código, para que a troca toque um arquivo.
E vale planejar a migração como transição: gerar os vetores novos em paralelo, comparar a qualidade com o conjunto de avaliação, e só então trocar a busca. Assim a troca não é aposta.
Fragmentar bem vale mais que o modelo
Uma constatação que economiza tempo: em boa parte dos casos, a qualidade da busca é mais afetada por como o texto foi dividido que por qual modelo gerou os vetores.
Trecho grande demais dilui o significado — o vetor representa a média de vários assuntos e não fica próximo de nenhum. Trecho pequeno demais perde contexto e vira ambíguo.
O que costuma funcionar: dividir por seção lógica do documento, com algumas centenas de palavras por trecho, mantendo o título da seção junto do conteúdo em cada fragmento. Assim o vetor carrega o contexto do que aquele trecho é.
Se a busca está ruim, vale testar mudanças de fragmentação antes de trocar de modelo — é mais barato, mais rápido, e frequentemente resolve. O tema completo está no artigo sobre infraestrutura para RAG.
Um roteiro de decisão
- Monte trinta perguntas com o documento correto anotado.
- Teste dois ou três modelos com o mesmo conjunto e a mesma fragmentação.
- Compare qualidade, dimensão e custo — nessa ordem, e considerando o custo de memória do índice.
- Escolha a menor dimensão que entregue qualidade aceitável.
- Fixe a versão e registre-a junto de cada vetor.
- Guarde o texto original, sempre.
O que emerge com frequência desse processo é que um modelo multilíngue de 768 dimensões, rodando localmente, atende bem uma base corporativa em português — com custo de infraestrutura modesto e sem dependência externa. Nem sempre é a conclusão, mas é comum o suficiente para valer o teste antes de assumir que o maior é necessário.
Um detalhe que muda o resultado
Vale conhecer uma característica que passa despercebida e afeta bastante a qualidade: alguns modelos são treinados esperando um prefixo diferente para o documento e para a pergunta.
A ideia é que "o que estou procurando" e "o que está guardado" são papéis distintos, e o modelo representa cada um de um jeito. Usar o mesmo tratamento para os dois degrada a busca de forma silenciosa — tudo funciona, os resultados só são piores do que poderiam ser.
# Indexação
vetor_doc = modelo.embed("passage: " + texto_do_trecho)
# Consulta
vetor_consulta = modelo.embed("query: " + pergunta_do_usuario)Os prefixos variam por modelo, e a documentação diz quais usar. Se ela mencionar instrução ou prefixo, aplique — a diferença costuma ser perceptível no conjunto de avaliação.
E se você trocar de modelo, revise isso junto: aplicar o prefixo de um modelo em outro que não o espera também piora o resultado. É o tipo de detalhe que não aparece em erro nenhum e explica por que uma implementação funciona melhor que outra aparentemente igual.
O caso de não usar embedding
Vale fechar com a possibilidade que raramente é considerada: talvez a sua busca não precise de vetores.
Se as consultas dos usuários são majoritariamente por termo exato — código de produto, número de documento, nome próprio —, a busca textual tradicional resolve melhor, mais rápido e sem infraestrutura adicional. Vetor é bom para significado aproximado, e ruim para correspondência exata.
Se a base é pequena — algumas centenas de documentos —, uma busca textual bem feita com sinônimos costuma entregar resultado equivalente, sem índice para manter nem modelo para escolher.
E se a estrutura do conteúdo é forte, com categorias e metadados bem definidos, boa parte das buscas se resolve com filtro em vez de similaridade.
A abordagem híbrida descrita no artigo sobre banco vetorial é quase sempre superior a qualquer uma isolada — e começar pela busca textual, acrescentando vetores onde ela falha, costuma dar um resultado melhor por menos esforço que o caminho contrário.