# Multimodal fusionssökning: att välja rätt hämtare för varje sökfråga

Canonical source: https://maguyva.ai/sv/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

> En sökfråga som 'var är parseConfig definierad' vill ha en annan typ av sökning än 'hur fungerar auth'. Maguyva klassificerar avsikten, viktar fyra hämtningslägen därefter, och slår samman resultaten med viktad Reciprocal Rank Fusion.

> Historisk designnot: den här artikeln från april 2026 beskriver dåtidens routningsdesign, inte dagens standardbeteende. Rättelsen från september nedan gäller endast ett mätpåstående. För aktuell routning, förval och uttrycklig styrning av modaliteter, se [Så fungerar det](https://maguyva.ai/sv/docs/how-it-works).

Sökfrågor kan vara av olika slag.

"var är `parseConfig` definierad" vill ha en exakt symbol — en precis plats, snabbt. "hur fungerar autentisering" vill ha mening — spridningen av relaterad kod som förklarar ett koncept. "vad går sönder om jag ändrar den här funktionen" vill ha beroendegrafen. "hitta strängen `ECONNREFUSED`" vill ha en bokstavlig träff, ingenting smart.

Grep är utmärkt för bokstavliga träffar och användbart för viss referensjakt, men det är ingen beroendegraf och det förstår inte mening. Inbäddningar täcker den semantiska sidan, men de är fel verktyg för exakta strängar och konsekvensanalys. De flesta kodsökverktyg väljer en motor och tvingar varje sökfråga att leva med det valet. Maguyva låser sig inte vid en enda motor. Det räknar ut vilken typ av fråga du ställde, och blandar sedan fyra hämtare i den proportion frågan förtjänar.

## Fyra hämtningslägen

Under huven finns fyra oberoende sätt att hitta kod:

- **semantisk** — vektorsökning över Voyage-binärinbäddningar; hittar kod efter mening.
- **text** — trigrammatchning; hittar bokstavliga strängar, felmeddelanden, exakta identifierare.
- **strukturell** — AST-queries; hittar definitioner, signaturer och språkkonstruktioner.
- **graf** — beroendegrafen; hittar anropare, anropade och påverkansradie.

Var och en är stark på en egen klass av frågor. Konsten ligger i att avgöra hur mycket man ska lita på var och en för sökfrågan framför sig.

## Avsiktsklassificering

Innan någon hämtning körs sorterar en lättviktig klassificerare sökfrågan i en av sex avsikter, med en konfidenspoäng. Den är medvetet billig — ordnad heuristik, första träff vinner — eftersom den körs i den tidskritiska kodvägen och bara lägger till en millisekund eller två:

- börjar med `def `, `class `, `func `, `import `… → **find_definition** (konfidens 0,95)
- "who calls", "usages of", "references to" (vem anropar, användningar av, referenser till) → **find_references** (0,90)
- "impact", "blast radius", "what depends on" (påverkan, påverkansradie, vad som är beroende av något) → **impact_analysis** (0,90)
- en citerad `"string"` eller ett felmeddelande-token som `traceback` → **exact_match** (0,85–0,90)
- en identifierare av typen `CamelCase` eller `snake_case` → **find_definition** (0,60–0,80)
- "how", "why", "explain", "architecture" (hur, varför, förklara, arkitektur) → **understand_code** (0,75)
- inget matchar → **understand_code**, låg konfidens (0,40)

Varje avsikt bär en viktprofil över de fyra hämtningslägena. Det här är de verkliga talen:

| Avsikt | semantisk | text | strukturell (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å "var är `parseConfig` definierad" lutar tungt mot AST (0,6). "hur fungerar auth" lutar mot semantiska vektorer (0,5). "vad beror på det här" är nästan helt graf (0,7). "hitta `ECONNREFUSED`" är nästan helt trigram (0,9), med inbäddningsmodellen helt avstängd — eftersom semantisk likhet är exakt fel verktyg för en exakt sträng.

## Den snabba vägen och den sammanslagna vägen

När klassificeraren är säker — poäng ≥ 0,85 — och sökfrågan är en normal sådan, hoppar Maguyva över fusion helt och dirigerar direkt till det enda dominerande hämtningsläget. "var är X definierad" behöver inte fyra hämtare; den behöver AST-indexet, direkt. Den direkta vägen rapporteras tillbaka som `fusion_strategy: "direct"`.

Allt tvetydigt går genom fusion. De fyra (eller tre, i standardinställningen) hämtningslägena körs parallellt, var och en returnerar sin egen rankade lista, och vi kombinerar dem.

## Viktad Reciprocal Rank Fusion

Att slå samman heterogena hämtare är svårare än det låter: en cosinuslikhet på 0,82 och en trigrampoäng på 137 och en grafcentralitet på 0,004 ligger inte på samma skala, så man kan inte bara addera dem. Reciprocal Rank Fusion kringgår problemet genom att kasta bort de råa poängen och bara behålla den **placering** varje motor tilldelade. Ett resultats bidrag från ett hämtningsläge är:

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

där `rank` är dess position i det hämtningslägets lista och `k` är en utjämningskonstant. Bidrag summeras över hämtningslägen för varje resultat som mer än en motor hittade — samstämmighet mellan hämtare flyter naturligt upp till toppen. Vi använder **k = 40** i standardinställningen och 60 för `thorough` (`quick` körs enbart semantiskt, så fusion aktiveras aldrig där). Det ursprungliga RRF-arbetet landade på k = 60 för generell hämtning; vårt standardvärde ger något större tyngd åt resultat som rankas högt i flera hämtningslägen — och vi rekommenderar inte att man finjusterar den för hand.

Utöver det bär resultaten en **grafviktighetsboost**. Ett nav — en funktion hela kodbasen lutar sig mot — bör rankas högre än en mindre känd lövnod även vid samma textuella relevans, så vi multiplicerar varje bidrag med:

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

Centralitet kommer från pipelinens förberäknade PageRank-/gradmått, och boosten är begränsad till 1,5× så att en populär funktion inte helt kan begrava en mer relevant men obskyr sådan. Slutligen degraderar vi resultat från vendor-, build- och arkivsökvägar, och tar bort dubbletter och behåller det bästa kodavsnittet per fil.

## Vad som fortfarande är ofullständigt

Avsiktsklassificeraren är en samling reguljära uttryck, inte en tränad modell. Den hanterar vanliga frågeformer med heuristiker, och en tvetydig sökfråga faller tillbaka på `understand_code` och en blandning med tonvikt på semantik. En tidigare version av det här inlägget beskrev en minskning av andelen sökningar utan resultat från cirka 15 % till under 5 % som uppnådd. Förslaget från december 2025 angav i själva verket ett uppskattat utgångsläge och ett mål; ingen underbyggande uppsättning sökfrågor eller mätdokumentation har tillhandahållits. Vi drar tillbaka påståendet om en uppnådd förbättring; se [källunderlaget och rättelsen (på engelska)](https://maguyva.ai/evidence/search-quality.md). Vi har inte ersatt klassificeraren med en tränad modell eftersom den billiga versionen är snabb och tillräckligt bra för sin avsedda routningsuppgift, och eftersom en felaktig men självsäker klassificerare är sämre än ett ärligt reservalternativ. Vikterna är handvalda apriorivärden, inte inlärda från klickdata som vi inte samlar in.

## Ställ frågan utan att välja verktyg

En agent ska inte behöva veta om den ska ta till grep eller inbäddningar eller anropsgrafen — den ska ställa sin fråga i vanliga ord och få rätt svar. Multimodal fusion är det som låter `find_symbol`, semantisk sökning och beroendeanalys ligga bakom en och samma sökyta: systemet läser frågans form och sätter tyst ihop rätt hämtare för den. Modellen som poängsätter inbäddningarna spelar roll, men det gör även att veta när man *inte* ska använda dem. Att välja rätt verktyg för varje sökfråga är sin egen sorts kvalitet, och det är en vi hellre äger själva än skjuter över på anroparen.

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