Busca com Fusão Multimodal: Escolhendo o Retriever Certo Para Cada Consulta
> Uma consulta como 'onde parseConfig é definido' quer um tipo de busca diferente de 'como funciona a autenticação'. O Maguyva classifica a intenção, pondera quatro modalidades de retrieval de acordo, e funde os resultados com Reciprocal Rank Fusion ponderada.
Uma consulta de busca não é uma coisa só.
“onde parseConfig é definido” quer um símbolo exato — um local preciso, rápido. “como funciona a autenticação” quer significado — o conjunto espalhado de código relacionado que explica um conceito. “o que quebra se eu mudar esta função” quer o grafo de dependências. “encontre a string ECONNREFUSED” quer uma correspondência literal, nada sofisticado.
O grep é excelente para correspondências literais e útil para algumas caças a referências, mas não é um grafo de dependências e não entende significado. Embeddings cobrem o lado semântico, mas são a ferramenta errada para strings exatas e análise de impacto. A maioria das ferramentas de busca de código escolhe um único motor e faz toda consulta conviver com essa escolha. O Maguyva não escolhe. Ele descobre que tipo de pergunta você fez, e então combina quatro retrievers na proporção que essa pergunta merece.
Quatro modalidades
Por baixo dos panos, existem quatro formas independentes de encontrar código:
- semantic — busca vetorial sobre embeddings binários da Voyage; encontra código por significado.
- text — correspondência de trigramas; encontra literais, strings de erro, identificadores exatos.
- structural — queries de AST; encontra definições, assinaturas e construções da linguagem.
- graph — o grafo de dependências; encontra chamadores, chamados e raio de impacto.
Cada um é forte em uma classe diferente de pergunta. O truque é decidir o quanto confiar em cada um para a consulta que está na sua frente.
Classificação de intenção
Antes de qualquer retrieval rodar, um classificador leve ordena a consulta em uma de seis intenções, com uma pontuação de confiança. É deliberadamente barato — heurísticas ordenadas, a primeira correspondência vence — porque roda no caminho crítico e adiciona apenas um ou dois milissegundos:
- começa com
def,class,func,import… → find_definition (confiança 0,95) - “quem chama”, “usos de”, “referências a” → find_references (0,90)
- “impacto”, “raio de impacto”, “o que depende de” → impact_analysis (0,90)
- um
"string"entre aspas ou um token de erro comotraceback→ exact_match (0,85–0,90) - um identificador
CamelCaseousnake_case→ find_definition (0,60–0,80) - “como”, “por que”, “explique”, “arquitetura” → understand_code (0,75)
- nada corresponde → understand_code, baixa confiança (0,40)
Cada intenção carrega um perfil de peso entre as quatro modalidades. Estes são os números reais:
| Intenção | semantic | text | structural (AST) | graph |
|---|---|---|---|---|
| find_definition | 0,2 | 0,1 | 0,6 | 0,1 |
| find_references | 0,1 | 0,2 | 0,2 | 0,5 |
| understand_code | 0,5 | 0,2 | 0,2 | 0,1 |
| find_similar | 0,4 | 0,3 | 0,2 | 0,1 |
| impact_analysis | 0,1 | 0,1 | 0,1 | 0,7 |
| exact_match | 0,0 | 0,9 | 0,1 | 0,0 |
Então “onde parseConfig é definido” se apoia fortemente em AST (0,6). “como funciona a autenticação” se apoia em vetores semânticos (0,5). “o que depende disso” é quase todo graph (0,7). “encontre ECONNREFUSED” é quase todo trigrama (0,9), com o modelo de embedding completamente desligado — porque similaridade semântica é exatamente a ferramenta errada para uma string exata.
O caminho rápido, e o caminho fundido
Quando o classificador está confiante — pontuação ≥ 0,85 — e a consulta é normal, o Maguyva pula a fusão por completo e roteia direto para a única modalidade dominante. “onde X é definido” não precisa de quatro retrievers; precisa do índice de AST, agora. Esse caminho direto é reportado de volta como fusion_strategy: "direct".
Tudo que é ambíguo passa pela fusão. As quatro (ou três, no preset padrão) modalidades rodam em paralelo, cada uma retornando sua própria lista ranqueada, e nós as combinamos.
Reciprocal Rank Fusion Ponderada
Fundir retrievers heterogêneos é mais difícil do que parece: uma similaridade de cosseno de 0,82, uma pontuação de trigrama de 137 e uma centralidade de grafo de 0,004 não estão na mesma escala, então você não pode simplesmente somá-las. O Reciprocal Rank Fusion contorna o problema descartando as pontuações brutas e mantendo apenas o rank que cada motor atribuiu. A contribuição de um resultado vinda de uma modalidade é:
contribution = weight × 1 / (k + rank + 1)
onde rank é a posição dele na lista daquela modalidade e k é uma constante de suavização. As contribuições são somadas entre modalidades para qualquer resultado que mais de um motor encontrou — a concordância entre retrievers naturalmente sobe ao topo. Usamos k = 40 no preset padrão e 60 em thorough (quick roda apenas com semantic, então a fusão nunca entra em ação ali). O trabalho original de RRF chegou a k = 60 para retrieval de propósito geral; nosso padrão é ligeiramente mais afiado, o que dá um pouco mais de peso à concordância entre modalidades bem ranqueadas — e não recomendamos ajustá-lo manualmente.
Além disso, os resultados carregam um boost de importância de grafo. Um hub — uma função em que todo o codebase se apoia — deve superar em ranking uma folha obscura mesmo com a mesma relevância textual, então multiplicamos cada contribuição por:
boost = min(1 + 0.3 × ln(1 + centrality), 1.5)
A centralidade vem das métricas pré-computadas de PageRank/grau do pipeline, e o boost é limitado a 1,5× para que uma função popular não consiga sepultar completamente uma obscura mais relevante. Por fim, rebaixamos resultados de caminhos de vendor, build e arquivo, e removemos duplicatas mantendo o melhor chunk por arquivo.
O que ainda é imperfeito
O classificador de intenção é uma pilha de regexes, não um modelo aprendido. Ele cobre bem os formatos comuns de consulta — a decisão que o introduziu registrou a taxa de resultado zero caindo de aproximadamente 15% para menos de 5% — mas é heurístico, e uma consulta genuinamente ambígua cai em understand_code e uma combinação inclinada ao semantic. Esse é um padrão seguro, não um esperto. Não o substituímos por um classificador treinado porque a versão barata é rápida e boa o suficiente, e porque um classificador errado-mas-confiante é pior do que um fallback honesto. Os próprios pesos são priors escolhidos à mão, não aprendidos a partir de dados de clique que não coletamos.
Faça a Pergunta, Não a Ferramenta
Um agente não deveria precisar saber se deve recorrer ao grep, a embeddings ou ao call graph — ele deveria fazer a sua pergunta em termos simples e obter a resposta certa. A fusão multimodal é o que permite que find_symbol, busca semântica e análise de dependências fiquem por trás de uma única superfície de consulta: o sistema lê o formato da pergunta e silenciosamente monta o retriever certo para ela. O modelo que pontua os embeddings importa, mas também importa saber quando não usá-los. Escolher a ferramenta certa para cada consulta é um tipo de qualidade em si, e é algo que preferimos assumir a empurrar para quem chama.
// you bring the question. it brings the tools.
Leituras relacionadas
Mais do log de build do Maguyva
Por Que Atualizamos a Busca de Código para o voyage-4-large_
Migramos nossos embeddings de código para o voyage-4-large — atualmente no topo do ranking público RTEB de retrieval de código. A versão honesta: o trade-off que fazemos, o que realmente indexamos, e por que pagamos por embeddings premium.
Autoaperfeiçoamento Recursivo de Linguagens: Aprimorando a Inteligência de Código em ~280 Linguagens_
Damos suporte a inteligência de código para ~280 linguagens. Nenhum humano consegue auditar isso manualmente. Por isso construímos um loop de autoaperfeiçoamento recursivo de linguagens — verificação pontual, LLM como juiz, corrigir uma coisa, revalidar — e o rodamos com uma frota de agentes isolados até que a extração esteja realmente correta, não apenas verde.
Observabilidade de Agentes: Hooks, Alloy e Grafana_
Conectamos o Claude Code e o Codex a uma única stack do Grafana com OpenTelemetry e Alloy, e depois usamos traces e logs para encontrar e corrigir problemas de comportamento dos agentes na origem.