Zum Inhalt springen
cd /blog

Multi-Modal Fusion Search: Für jede Query den richtigen Retriever wählen

[Suche][Architektur]

> Eine Query wie 'wo ist parseConfig definiert' braucht eine andere Suche als 'wie funktioniert Auth'. Maguyva klassifiziert die Intention, gewichtet vier Retrieval-Modalitäten entsprechend und fusioniert die Ergebnisse mit gewichteter Reciprocal Rank Fusion.

Eine Suchanfrage ist nicht eine einzige Sache.

„wo ist parseConfig definiert“ will ein exaktes Symbol — einen präzisen Ort, schnell. „wie funktioniert Authentifizierung“ will Bedeutung — die Streuung an verwandtem Code, die ein Konzept erklärt. „was bricht, wenn ich diese Funktion ändere“ will den Dependency-Graph. „finde den String ECONNREFUSED“ will einen literalen Treffer, nichts Cleveres.

Grep ist hervorragend für literale Treffer und nützlich für manche Referenzsuchen, aber es ist kein Dependency-Graph und versteht keine Bedeutung. Embeddings decken die semantische Seite ab, sind aber das falsche Werkzeug für exakte Strings und Impact-Analyse. Die meisten Code-Search-Tools wählen eine Engine und zwingen jede Query, mit dieser Wahl zu leben. Maguyva wählt nicht. Es findet heraus, welche Art von Frage du gestellt hast, und mischt dann vier Retriever in der Gewichtung, die diese Frage verdient.

Vier Modalitäten

Unter der Haube gibt es vier unabhängige Wege, Code zu finden:

  • semantic — Vektorsuche über binäre Voyage-Embeddings; findet Code nach Bedeutung.
  • text — Trigram-Matching; findet Literale, Fehler-Strings, exakte Identifier.
  • structural — AST-Queries; findet Definitionen, Signaturen und Sprachkonstrukte.
  • graph — der Dependency-Graph; findet Aufrufer, Aufgerufene und den Auswirkungsradius.

Jede ist stark bei einer anderen Klasse von Frage. Der Trick ist zu entscheiden, wie sehr man jeder für die vorliegende Query vertraut.

Intent-Klassifizierung

Bevor überhaupt ein Retrieval läuft, sortiert ein leichtgewichtiger Klassifizierer die Query in eine von sechs Intentionen, mit einem Konfidenzwert. Das ist bewusst billig gehalten — geordnete Heuristiken, der erste Treffer gewinnt — weil es auf dem Hot Path läuft und nur ein bis zwei Millisekunden hinzufügt:

  • beginnt mit def , class , func , import … → find_definition (Konfidenz 0,95)
  • „wer ruft auf“, „Verwendungen von“, „Referenzen auf“ → find_references (0,90)
  • „Impact“, „Auswirkungsradius“, „was hängt davon ab“ → impact_analysis (0,90)
  • ein zitiertes "string" oder ein Fehler-Token wie tracebackexact_match (0,85–0,90)
  • ein CamelCase- oder snake_case-Identifier → find_definition (0,60–0,80)
  • „wie“, „warum“, „erkläre“, „Architektur“ → understand_code (0,75)
  • nichts passt → understand_code, niedrige Konfidenz (0,40)

Jede Intention trägt ein Gewichtungsprofil über die vier Modalitäten. Das sind die echten Zahlen:

Intent 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

Also stützt sich „wo ist parseConfig definiert“ stark auf AST (0,6). „wie funktioniert Auth“ stützt sich auf semantische Vektoren (0,5). „was hängt davon ab“ ist fast ausschließlich Graph (0,7). „finde ECONNREFUSED“ ist fast ausschließlich Trigram (0,9), wobei das Embedding-Modell komplett ausgeschaltet ist — weil semantische Ähnlichkeit genau das falsche Werkzeug für einen exakten String ist.

Der schnelle Pfad und der fusionierte Pfad

Wenn der Klassifizierer sicher ist — Score ≥ 0,85 — und die Query normal ist, überspringt Maguyva die Fusion komplett und routet direkt zur einzelnen dominanten Modalität. „wo ist X definiert“ braucht keine vier Retriever; es braucht sofort den AST-Index. Dieser direkte Pfad wird als fusion_strategy: "direct" zurückgemeldet.

Alles Mehrdeutige durchläuft die Fusion. Die vier (oder drei, im Standard-Preset) Modalitäten laufen parallel, jede liefert ihre eigene Rangliste zurück, und wir kombinieren sie.

Gewichtete Reciprocal Rank Fusion

Heterogene Retriever zu fusionieren ist schwieriger, als es klingt: Eine Cosine-Similarity von 0,82, ein Trigram-Score von 137 und eine Graph-Zentralität von 0,004 liegen nicht auf derselben Skala, du kannst sie also nicht einfach addieren. Reciprocal Rank Fusion umgeht das Problem, indem es die Rohwerte verwirft und nur den Rang behält, den jede Engine vergeben hat. Der Beitrag eines Ergebnisses aus einer Modalität ist:

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

wobei rank seine Position in der Rangliste dieser Modalität ist und k eine Glättungskonstante. Beiträge werden über Modalitäten hinweg summiert für jedes Ergebnis, das mehr als eine Engine gefunden hat — Übereinstimmung zwischen Retrievern schwimmt natürlich nach oben. Wir verwenden k = 40 im Standard-Preset und 60 bei thorough (quick läuft nur semantisch, sodass Fusion dort nie greift). Die ursprüngliche RRF-Arbeit landete bei k = 60 für allgemeines Retrieval; wir setzen den Standard etwas schärfer, was Top-Rang-Übereinstimmung zwischen Modalitäten etwas mehr Gewicht gibt — und wir empfehlen nicht, von Hand daran zu drehen.

Zusätzlich erhalten Ergebnisse eine Graph-Relevanzgewichtung. Ein Hub — eine Funktion, auf die sich die gesamte Codebase stützt — sollte selbst bei gleicher textueller Relevanz ein obskures Blatt überholen, also multiplizieren wir jeden Beitrag mit:

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

Die Zentralität kommt aus den vorberechneten PageRank-/Degree-Metriken der Pipeline, und der Boost ist bei 1,5× gedeckelt, damit eine populäre Funktion eine relevantere, obskure nicht komplett begraben kann. Schließlich degradieren wir Ergebnisse aus Vendor-, Build- und Archiv-Pfaden und dedupen auf den besten Chunk pro Datei.

Was noch unperfekt ist

Der Intent-Klassifizierer ist ein Stapel Regexes, kein gelerntes Modell. Er deckt die gängigen Formen einer Query gut ab — die Decision, die ihn eingeführt hat, hielt fest, dass die Zero-Result-Rate von rund 15 % auf unter 5 % gefallen ist — aber er ist heuristisch, und eine wirklich mehrdeutige Query fällt durch zu understand_code und einer semantisch geneigten Mischung. Das ist ein sicherer Standard, kein cleverer. Wir haben ihn nicht durch einen trainierten Klassifizierer ersetzt, weil die billige Version schnell und gut genug ist, und weil ein falscher, aber selbstbewusster Klassifizierer schlimmer ist als ein ehrlicher Fallback. Die Gewichte selbst sind handgewählte Priors, nicht aus Klickdaten gelernt, die wir nicht sammeln.

Stell die Frage, nicht das Werkzeug

Ein Agent sollte nicht wissen müssen, ob er zu grep, Embeddings oder dem Call-Graph greifen soll — er sollte seine Frage in einfachen Worten stellen und die richtige Antwort bekommen. Multi-Modal Fusion ist das, was find_symbol, semantische Suche und Abhängigkeitsanalyse hinter einer einzigen Query-Oberfläche vereint: Das System liest die Form der Frage und stellt still den richtigen Retriever dafür zusammen. Das Modell, das die Embeddings bewertet, zählt, aber genauso zählt es, zu wissen, wann man sie nicht verwenden sollte. Für jede Query das richtige Werkzeug zu wählen, ist eine eigene Art von Qualität — und eine, die wir lieber selbst verantworten, als sie an den Aufrufer abzuschieben.

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

Weiterführende Artikel

Mehr aus dem Maguyva-Buildlog