Multi-Modal Fusion Search: Für jede Query den richtigen Retriever wählen
> 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 wietraceback→ exact_match (0,85–0,90) - ein
CamelCase- odersnake_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
Warum wir unsere Code-Suche auf voyage-4-large upgegradet haben_
Wir haben unsere Code-Embeddings auf voyage-4-large umgestellt — aktuell die Nummer eins im öffentlichen RTEB-Code-Retrieval-Leaderboard. Die ehrliche Version: der Trade-off, den wir eingehen, was wir tatsächlich indizieren, und warum wir für Premium-Embeddings bezahlen.
Language Recursive Self-Improvement: Code Intelligence über ~280 Sprachen hinweg grinden_
Wir unterstützen Code Intelligence für ~280 Sprachen. Das kann kein Mensch von Hand auditieren. Also haben wir eine Language-Recursive-Self-Improvement-Loop gebaut — Stichprobe, LLM-as-Judge, eine Sache reparieren, erneut validieren — und lassen sie mit einer Flotte isolierter Agenten laufen, bis die Extraktion tatsächlich stimmt, nicht nur grün ist.
Agent-Observability: Hooks, Alloy und Grafana_
Wir haben Claude Code und Codex mit OpenTelemetry und Alloy in einen gemeinsamen Grafana-Stack eingebunden und dann mit Traces und Logs Probleme im Agent-Verhalten direkt an der Quelle gefunden und behoben.