Spring til indhold
cd /blog

Multimodal fusionssøgning: Sådan vælges den rette retriever til hver forespørgsel

[Søgning] [Arkitektur]

> 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.

Note om det historiske design: Denne artikel fra april 2026 beskriver routingdesignet på det tidspunkt, ikke den nuværende standardadfærd. Rettelsen fra september nedenfor vedrører kun en påstand om en måling. Se Sådan virker det for aktuel routing, forudindstillinger og eksplicit styring af søgemodaliteter.

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 låser sig ikke til én motor. 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 blast radius.

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 ofte benyttede eksekveringssti 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 streng i anførselstegn som "string" eller et fejltoken som traceback → exact_match (0.85–0.90)
  • en CamelCase- eller snake_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 har en almindelig form, 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 træder aldrig i kraft der). Det oprindelige RRF-arbejde landede på k = 60 til almenformåls-retrieval; vores standardindstilling giver lidt mere vægt til resultater, som flere modaliteter placerer højt — 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 en mindre kendt bladnode, 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, men mindre kendt funktion. Til sidst nedgraderer vi resultater fra vendor-, build- og arkivstier og fjerner dubletter til det bedste chunk pr. fil.

Hvad der stadig er ufuldkomment

Intent-klassifikatoren er en samling regulære udtryk, ikke en trænet model. Den håndterer almindelige forespørgselsmønstre med heuristikker, og en tvetydig forespørgsel falder tilbage på understand_code og en blanding med vægt på semantik. En tidligere version af dette indlæg beskrev et fald i andelen af søgninger uden resultater fra cirka 15 % til under 5 % som opnået. Forslaget fra december 2025 angav faktisk en anslået udgangsværdi og et mål; der er ikke fremlagt et understøttende forespørgselssæt eller en målerapport. Vi trækker påstanden om en opnået forbedring tilbage; se kildeevidens og rettelse. Vi har ikke erstattet klassifikatoren med en trænet model, fordi den billige version er hurtig og god nok til sin tiltænkte routingopgave, og fordi en klassifikator, der tager fejl med stor sikkerhed, er værre end et ærligt fallback. Selve vægtene er håndvalgte forhåndsantagelser, ikke lært fra klikdata, som vi ikke indsamler.

Stil spørgsmålet uden at vælge værktøj

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 ét fælles forespørgselsinterface: 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