# Multimodalt fusjonssøk: Velge riktig retriever for hvert søk

Canonical source: https://maguyva.ai/nb/blog/multi-modal-fusion-search

License: text under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); code samples under [MIT-0](https://opensource.org/license/mit-0); the Maguyva name, logos, brand assets and other code are not covered. Details: [maguyva.ai/license](https://maguyva.ai/license).

Date: 2026-04-15 · Author: Maguyva Team

> Et søk som «hvor er parseConfig definert» krever et annet søk enn «hvordan fungerer autentisering». Maguyva klassifiserer intensjonen, vekter fire retrieval-modaliteter deretter, og fusjonerer resultatene med vektet Reciprocal Rank Fusion.

> Merknad om historisk design: Denne artikkelen fra april 2026 beskriver rutingsdesignet på den tiden, ikke dagens standardatferd. Rettelsen fra september nedenfor gjelder bare en målepåstand. Se [Slik fungerer det](https://maguyva.ai/nb/docs/how-it-works) for gjeldende ruting, forhåndsinnstillinger og eksplisitte modalitetsvalg.

Et søk er ikke bare én ting.

«hvor er `parseConfig` definert» vil ha et eksakt symbol — ett presist sted, raskt. «hvordan fungerer autentisering» vil ha mening — spredningen av relatert kode som forklarer et konsept. «hva ryker hvis jeg endrer denne funksjonen» vil ha avhengighetsgrafen. «finn strengen `ECONNREFUSED`» vil ha et bokstavelig treff, ikke noe smart.

Grep er utmerket for bokstavelige treff og nyttig for enkelte referansejakter, men det er ikke en avhengighetsgraf, og det forstår ikke mening. Embeddinger dekker den semantiske siden, men de er feil verktøy for eksakte strenger og konsekvensanalyse. De fleste kodesøkverktøy velger én motor og lar hvert søk leve med det valget. Maguyva låser seg ikke til én motor. Det finner ut hva slags spørsmål du stilte, og blander deretter fire retrievere i den andelen spørsmålet fortjener.

## Fire modaliteter

Under panseret finnes det fire uavhengige måter å finne kode på:

- **semantisk** — vektorsøk over Voyage binære embeddinger; finner kode etter mening.
- **tekst** — trigram-matching; finner literaler, feilstrenger, eksakte identifikatorer.
- **strukturelt** — AST-spørringer; finner definisjoner, signaturer og språkkonstruksjoner.
- **graf** — avhengighetsgrafen; finner kallere, kalte, og påvirkningsradiusen.

Hver er sterk på en annen klasse spørsmål. Trikset er å avgjøre hvor mye man skal stole på hver enkelt for søket foran deg.

## Intensjonsklassifisering

Før noen retrieval kjører, sorterer en lettvekts-klassifiserer søket inn i én av seks intensjoner, med en konfidensscore. Den er bevisst billig — ordnede heuristikker, første treff vinner — fordi den kjører på den kritiske stien og bare legger til ett eller to millisekunder:

- 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 feiltoken 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)
- ingenting matcher → **understand_code**, lav konfidens (0,40)

Hver intensjon har en vektprofil på tvers av de fire modalitetene. Dette er de reelle tallene:

| Intensjon | semantisk | tekst | strukturelt (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` definert» lener seg tungt på AST (0,6). «hvordan fungerer autentisering» lener seg på semantiske vektorer (0,5). «hva avhenger av dette» er nesten bare graf (0,7). «finn `ECONNREFUSED`» er nesten bare trigram (0,9), med embedding-modellen helt slått av — fordi semantisk likhet er akkurat feil verktøy for en eksakt streng.

## Hurtigstien, og den fusjonerte stien

Når klassifiseringen er sikker — score ≥ 0,85 — og søket har en vanlig form, hopper Maguyva over fusjon helt og ruter rett til den ene dominerende modaliteten. «hvor er X definert» trenger ikke fire retrievere; det trenger AST-indeksen, nå. Den direkte stien rapporteres tilbake som `fusion_strategy: "direct"`.

Alt som er tvetydig går gjennom fusjon. De fire (eller tre, på standardoppsettet) modalitetene kjører parallelt, hver returnerer sin egen rangerte liste, og vi kombinerer dem.

## Vektet Reciprocal Rank Fusion

Å fusjonere heterogene retrievere er vanskeligere enn det høres ut som: en kosinuslikhet på 0,82 og en trigram-score på 137 og en graf-sentralitet på 0,004 er ikke på samme skala, så du kan ikke bare legge dem sammen. Reciprocal Rank Fusion omgår problemet ved å kaste bort de rå scorene og bare beholde **rangeringen** hver motor tildelte. Et resultats bidrag fra én modalitet er:

```text
contribution = weight × 1 / (k + rank + 1)
```

hvor `rank` er dets posisjon i den modalitetens liste, og `k` er en utjevningskonstant. Bidrag summeres på tvers av modaliteter for ethvert resultat som mer enn én motor fant — enighet mellom retrievere flyter naturlig til toppen. Vi bruker **k = 40** på standardoppsettet og 60 på `thorough` (`quick` kjører kun semantisk, så fusjon utløses aldri der). Det originale RRF-arbeidet landet på k = 60 for generell retrieval; standardverdien vår gir litt mer vekt til resultater som flere modaliteter plasserer høyt — og vi anbefaler ikke å håndjustere den.

I tillegg får resultater en **graf-viktighetsboost**. Et knutepunkt — en funksjon hele kodebasen lener seg på — bør rangere høyere enn en lite kjent bladnode selv ved samme tekstlige relevans, så vi multipliserer hvert bidrag med:

```text
boost = min(1 + 0.3 × ln(1 + centrality), 1.5)
```

Sentraliteten kommer fra pipelinens forhåndsberegnede PageRank/grad-metrikker, og boosten er begrenset til 1,5× slik at en populær funksjon ikke helt kan begrave en mer relevant, men lite kjent funksjon. Til slutt nedgraderer vi resultater fra vendor-, build- og arkivstier, og fjerner duplikater slik at kun det beste utdraget per fil beholdes.

## Hva som fortsatt er ufullkomment

Intensjonsklassifikatoren er en samling regex-er, ikke en trent modell. Den håndterer vanlige spørringsformer med heuristikker, og en tvetydig spørring faller tilbake til `understand_code` og en semantisk orientert blanding. En tidligere versjon av dette innlegget beskrev en reduksjon i andelen søk uten resultater fra omtrent 15 % til under 5 % som oppnådd. Forslaget fra desember 2025 oppga i virkeligheten et estimert utgangspunkt og et mål; det er ikke lagt frem noe støttende spørresett eller noen målerapport. Vi trekker tilbake påstanden om at denne forbedringen var oppnådd; se [kildedokumentasjonen og rettelsen](https://maguyva.ai/evidence/search-quality.md). Vi har ikke erstattet klassifikatoren med en trent modell fordi den billige versjonen er rask og god nok for den tiltenkte rutingsrollen, og fordi en selvsikker klassifikator som tar feil, er verre enn en ærlig fallback. Vektene er i seg selv manuelt valgte priorer, ikke lært fra klikkdata vi ikke samler inn.

## Still spørsmålet uten å velge verktøy

En agent burde ikke måtte vite om den skal gripe til grep eller embeddinger eller kallgrafen — den burde stille spørsmålet sitt med enkle ord og få riktig svar. Multimodal fusjon er det som lar `find_symbol`, semantisk søk og avhengighetsanalyse sitte bak ett søkegrensesnitt: systemet leser formen på spørsmålet og setter stille sammen riktig retriever for det. Modellen som scorer embeddingene betyr noe, men det gjør også det å vite når man *ikke* skal bruke dem. Å velge riktig verktøy for hvert søk er sin egen type kvalitet, og det er en vi heller vil eie selv enn å skyve over på den som kaller.

`// you bring the question. it brings the tools.`
