Multimodal fusionssøgning: Sådan vælges den rette retriever til hver forespørgsel
> En forespørgsel som 'hvor er parseConfig defineret' vil have en anden søgning end 'hvordan fungerer auth'. Maguyva klassificerer intentionen, vægter fire retrieval-modaliteter derefter og fusionerer resultaterne med vægtet Reciprocal Rank Fusion.
En søgeforespørgsel er ikke bare én ting.
“hvor er parseConfig defineret” ønsker et eksakt symbol — ét præcist sted, hurtigt. “hvordan fungerer autentificering” ønsker mening — spredningen af relateret kode, der forklarer et koncept. “hvad går i stykker, hvis jeg ændrer denne funktion” ønsker afhængighedsgrafen. “find strengen ECONNREFUSED” ønsker et bogstaveligt match, intet klogt.
Grep er fremragende til bogstavelige matches og nyttigt til nogle referencejagter, men det er ikke en afhængighedsgraf, og det forstår ikke mening. Embeddings dækker den semantiske side, men de er det forkerte værktøj til eksakte strenge og konsekvensanalyse. De fleste kodesøgningsværktøjer vælger én motor og lader enhver forespørgsel leve med det valg. Maguyva vælger ikke. Det udreder, hvilken slags spørgsmål du stillede, og blander derefter fire retrievere i det forhold, spørgsmålet fortjener.
Fire modaliteter
Under motorhjelmen er der fire uafhængige måder at finde kode på:
- semantisk — vektorsøgning over Voyage binære embeddings; finder kode ud fra mening.
- tekst — trigram-matching; finder literals, fejlstrenge, eksakte identifikatorer.
- strukturel — AST-forespørgsler; finder definitioner, signaturer og sprogkonstruktioner.
- graf — afhængighedsgrafen; finder kaldere, kaldte og eksplosionsradius.
Hver er stærk på en anden klasse af spørgsmål. Kunsten er at afgøre, hvor meget man skal stole på hver enkelt for den forespørgsel, der ligger foran én.
Intentionsklassificering
Før nogen retrieval kører, sorterer en letvægtsklassifikator forespørgslen i en af seks intentioner med en konfidensscore. Den er bevidst billig — ordnede heuristikker, første match vinder — fordi den kører på den varme sti og kun tilføjer et millisekund eller to:
- starter med
def,class,func,import… → find_definition (konfidens 0.95) - “who calls”, “usages of”, “references to” → find_references (0.90)
- “impact”, “blast radius”, “what depends on” → impact_analysis (0.90)
- en citeret
"string"eller en fejltoken somtraceback→ exact_match (0.85–0.90) - en
CamelCase- ellersnake_case-identifikator → find_definition (0.60–0.80) - “how”, “why”, “explain”, “architecture” → understand_code (0.75)
- intet matcher → understand_code, lav konfidens (0.40)
Hver intention bærer en vægtprofil på tværs af de fire modaliteter. Dette er de reelle tal:
| Intention | semantisk | tekst | strukturel (AST) | graf |
|---|---|---|---|---|
| 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 |
Så “hvor er parseConfig defineret” læner sig kraftigt op ad AST (0.6). “hvordan fungerer auth” læner sig op ad semantiske vektorer (0.5). “hvad afhænger af dette” er næsten udelukkende graf (0.7). “find ECONNREFUSED” er næsten udelukkende trigram (0.9), hvor embedding-modellen er slået helt fra — fordi semantisk lighed er præcis det forkerte værktøj til en eksakt streng.
Den hurtige sti og den fusionerede sti
Når klassifikatoren er sikker — score ≥ 0.85 — og forespørgslen er en normal en, springer Maguyva fusion helt over og dirigerer direkte til den ene dominerende modalitet. “hvor er X defineret” har ikke brug for fire retrievere; det har brug for AST-indekset, nu. Den direkte sti rapporteres tilbage som fusion_strategy: "direct".
Alt tvetydigt går gennem fusion. De fire (eller tre, i standardpresettet) modaliteter kører parallelt, hver returnerer sin egen rangerede liste, og vi kombinerer dem.
Vægtet Reciprocal Rank Fusion
At fusionere heterogene retrievere er sværere, end det lyder: en kosinuslighed på 0.82 og en trigram-score på 137 og en graf-centralitet på 0.004 er ikke på samme skala, så man kan ikke bare lægge dem sammen. Reciprocal Rank Fusion omgår problemet ved at smide de rå scorer væk og kun beholde den rang, hver motor tildelte. Et resultats bidrag fra én modalitet er:
contribution = weight × 1 / (k + rank + 1)
hvor rank er dets position på den pågældende modalitets liste, og k er en udjævningskonstant. Bidrag summeres på tværs af modaliteter for ethvert resultat, som mere end én motor fandt — enighed mellem retrievere flyder naturligt til tops. Vi bruger k = 40 i standardpresettet og 60 på thorough (quick kører kun semantisk, så fusion aldrig træder i kraft der). Det oprindelige RRF-arbejde landede på k = 60 til almenformåls-retrieval; vi har som standard en lidt skarpere indstilling, hvilket giver topplaceret enighed mellem modaliteter lidt mere vægt — og vi anbefaler ikke at finjustere den manuelt.
Oven i det bærer resultater et graf-vigtigheds-boost. Et knudepunkt — en funktion, hele kodebasen læner sig op ad — bør rangere højere end et obskurt blad, selv ved samme tekstlige relevans, så vi ganger hvert bidrag med:
boost = min(1 + 0.3 × ln(1 + centrality), 1.5)
Centralitet kommer fra pipelinens forudberegnede PageRank/degree-metrikker, og boostet er begrænset til 1.5×, så en populær funktion ikke helt kan begrave en mere relevant, obskur en. Til sidst nedgraderer vi resultater fra vendor-, build- og arkivstier og fjerner dubletter til det bedste chunk pr. fil.
Hvad der stadig er ufuldkomment
Intentionsklassifikatoren er en stak af regexes, ikke en trænet model. Den dækker de almindelige former af en forespørgsel godt — beslutningen, der introducerede den, registrerede, at nul-resultat-raten faldt fra omkring 15% til under 5% — men den er heuristisk, og en genuint tvetydig forespørgsel falder igennem til understand_code og en semantisk-orienteret blanding. Det er et sikkert standardvalg, ikke et smart et. Vi har ikke erstattet den med en trænet klassifikator, fordi den billige version er hurtig og god nok, og fordi en forkert-men-selvsikker klassifikator er værre end et ærligt fallback. Vægtene selv er håndvalgte priors, ikke lært fra klikdata, vi ikke indsamler.
Stil spørgsmålet, ikke værktøjet
En agent burde ikke behøve at vide, om den skal ty til grep eller embeddings eller kaldegrafen — den bør stille sit spørgsmål i almindelige vendinger og få det rigtige svar. Multimodal fusion er det, der lader find_symbol, semantisk søgning og afhængighedsanalyse sidde bag én forespørgselsflade: systemet aflæser spørgsmålets form og samler stille og roligt den rette retriever til det. Den model, der scorer embeddings, betyder noget, men det gør det også at vide, hvornår man ikke skal bruge dem. At vælge det rette værktøj til hver forespørgsel er sin egen slags kvalitet, og det er en, vi hellere selv vil eje end skubbe over på den kaldende part.
// you bring the question. it brings the tools.
Relateret læsning
Mere fra Maguyva-byggeloggen
Hvorfor vi opgraderede kodesøgning til voyage-4-large_
Vi flyttede vores kode-embeddings til voyage-4-large — i øjeblikket øverst på den offentlige RTEB-rangliste for kode-retrieval. Den ærlige version: det kompromis, vi indgår, hvad vi rent faktisk indekserer, og hvorfor vi betaler for premium-embeddings.
Sprogets rekursive selvforbedring: Sådan sliber vi Code Intelligence på tværs af ~280 sprog_
Vi understøtter code intelligence for ~280 sprog. Intet menneske kan håndrevidere det. Så vi byggede en rekursiv selvforbedringsløkke for sprog — stikprøvekontrol, LLM som dommer, ret én ting, gen-validér — og kører den med en flåde af isolerede agenter, indtil udtrækket rent faktisk er korrekt, ikke bare grønt.
Agent-observability: Hooks, Alloy og Grafana_
Vi koblede Claude Code og Codex sammen i én Grafana-stak med OpenTelemetry og Alloy, og brugte derefter traces og logs til at finde og rette agentadfærdsproblemer ved kilden.