Multi-Modal Fusion Search: Memilih Retriever yang Tepat untuk Setiap Kueri
> Kueri seperti 'di mana parseConfig didefinisikan' menginginkan pencarian yang berbeda dari 'bagaimana auth bekerja'. Maguyva mengklasifikasikan intent, memberi bobot pada empat modalitas retrieval sesuai kebutuhannya, lalu menggabungkan hasilnya dengan weighted Reciprocal Rank Fusion.
Sebuah kueri pencarian bukanlah satu hal.
“di mana parseConfig didefinisikan” menginginkan sebuah simbol persis — satu lokasi yang tepat, cepat. “bagaimana autentikasi bekerja” menginginkan makna — sebaran kode terkait yang menjelaskan sebuah konsep. “apa yang rusak jika saya mengubah fungsi ini” menginginkan graf dependensi. “cari string ECONNREFUSED” menginginkan kecocokan literal, tidak lebih.
Grep sangat baik untuk kecocokan literal dan berguna untuk sebagian pencarian referensi, tetapi ia bukan graf dependensi dan tidak memahami makna. Embedding mencakup sisi semantik, tetapi mereka adalah tool yang salah untuk string persis dan analisis dampak. Sebagian besar tool pencarian kode memilih satu engine dan memaksa setiap kueri hidup dengan pilihan itu. Maguyva tidak memilih. Ia mencari tahu jenis pertanyaan apa yang Anda ajukan, lalu memadukan empat retriever dalam proporsi yang layak untuk pertanyaan itu.
Empat modalitas
Di baliknya ada empat cara independen untuk menemukan kode:
- semantik — pencarian vektor atas Voyage binary embedding; menemukan kode berdasarkan makna.
- teks — pencocokan trigram; menemukan literal, string error, identifier persis.
- struktural — kueri AST; menemukan definisi, signature, dan konstruk bahasa.
- graf — graf dependensi; menemukan pemanggil, yang dipanggil, dan radius dampak.
Masing-masing kuat pada kelas pertanyaan yang berbeda. Triknya adalah memutuskan seberapa besar mempercayai masing-masing untuk kueri yang ada di depan Anda.
Klasifikasi intent
Sebelum retrieval apa pun berjalan, sebuah classifier ringan mengurutkan kueri ke dalam salah satu dari enam intent, dengan skor kepercayaan diri. Ini sengaja dibuat murah — heuristik berurutan, kecocokan pertama menang — karena berjalan di hot path dan hanya menambah satu-dua milidetik:
- dimulai dengan
def,class,func,import… → find_definition (kepercayaan 0,95) - “siapa yang memanggil”, “penggunaan dari”, “referensi ke” → find_references (0,90)
- “dampak”, “radius dampak”, “apa yang bergantung pada” → impact_analysis (0,90)
- sebuah
"string"berkutip atau token error sepertitraceback→ exact_match (0,85–0,90) - sebuah identifier
CamelCaseatausnake_case→ find_definition (0,60–0,80) - “bagaimana”, “mengapa”, “jelaskan”, “arsitektur” → understand_code (0,75)
- tidak ada yang cocok → understand_code, kepercayaan rendah (0,40)
Setiap intent membawa profil bobot di seluruh empat modalitas. Berikut angka-angka sesungguhnya:
| Intent | semantik | teks | struktural (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 |
Jadi “di mana parseConfig didefinisikan” bersandar berat pada AST (0,6). “bagaimana auth bekerja” bersandar pada vektor semantik (0,5). “apa yang bergantung pada ini” hampir sepenuhnya graf (0,7). “cari ECONNREFUSED” hampir sepenuhnya trigram (0,9), dengan model embedding dimatikan sepenuhnya — karena kemiripan semantik justru tool yang salah untuk sebuah string persis.
Jalur cepat, dan jalur terfusi
Ketika classifier percaya diri — skor ≥ 0,85 — dan kuerinya normal, Maguyva melewati fusi sepenuhnya dan langsung merutekan ke satu modalitas dominan. “di mana X didefinisikan” tidak butuh empat retriever; ia butuh indeks AST, sekarang juga. Jalur langsung itu dilaporkan kembali sebagai fusion_strategy: "direct".
Semua yang ambigu melewati fusi. Empat (atau tiga, pada preset default) modalitas berjalan paralel, masing-masing mengembalikan daftar peringkatnya sendiri, dan kami menggabungkannya.
Weighted Reciprocal Rank Fusion
Memfusikan retriever yang heterogen lebih sulit dari kedengarannya: sebuah cosine similarity 0,82 dan sebuah skor trigram 137 dan sebuah graph centrality 0,004 tidak berada pada skala yang sama, jadi Anda tidak bisa sekadar menjumlahkannya. Reciprocal Rank Fusion menghindari masalah ini dengan membuang skor mentah dan hanya mempertahankan rank yang diberikan setiap engine. Kontribusi sebuah hasil dari satu modalitas adalah:
contribution = weight × 1 / (k + rank + 1)
di mana rank adalah posisinya dalam daftar modalitas tersebut dan k adalah konstanta smoothing. Kontribusi dijumlahkan lintas modalitas untuk hasil apa pun yang ditemukan oleh lebih dari satu engine — kesepakatan antar retriever secara alami mengapung ke atas. Kami menggunakan k = 40 pada preset default dan 60 pada thorough (quick berjalan semantic-only, sehingga fusi tidak pernah aktif di sana). Karya RRF asli mendarat pada k = 60 untuk retrieval umum; kami menggunakan default yang sedikit lebih tajam, yang memberi kesepakatan peringkat-teratas antar modalitas sedikit bobot lebih besar — dan kami tidak menganjurkan menyetelnya secara manual.
Di atas itu, hasil membawa boost graph-importance. Sebuah hub — sebuah fungsi yang menjadi sandaran seluruh basis kode — seharusnya mengungguli sebuah leaf yang jarang disentuh bahkan pada relevansi tekstual yang sama, jadi kami mengalikan setiap kontribusi dengan:
boost = min(1 + 0.3 × ln(1 + centrality), 1.5)
Centrality berasal dari metrik PageRank/degree yang telah dihitung sebelumnya oleh pipeline, dan boost-nya dibatasi pada 1,5× sehingga sebuah fungsi populer tidak bisa sepenuhnya mengubur fungsi yang lebih relevan tapi jarang disentuh. Terakhir kami menurunkan peringkat hasil dari path vendor, build, dan archive, lalu melakukan dedup ke chunk terbaik per file.
Apa yang masih belum sempurna
Intent classifier-nya adalah tumpukan regex, bukan model yang dipelajari. Ia mencakup bentuk-bentuk umum sebuah kueri dengan baik — decision yang memperkenalkannya mencatat tingkat zero-result turun dari sekitar 15% menjadi di bawah 5% — tetapi ia heuristik, dan sebuah kueri yang sungguh-sungguh ambigu jatuh ke understand_code dan sebuah campuran yang condong ke semantik. Itu default yang aman, bukan yang cerdas. Kami belum menggantinya dengan classifier terlatih karena versi murahnya sudah cepat dan cukup baik, dan karena sebuah classifier yang salah-tapi-percaya-diri lebih buruk daripada fallback yang jujur. Bobot-bobotnya sendiri adalah prior yang dipilih tangan, bukan dipelajari dari data klik yang tidak kami kumpulkan.
Tanyakan Pertanyaannya, Bukan Tool-nya
Seorang agen seharusnya tidak perlu tahu apakah harus meraih grep atau embedding atau call graph — ia seharusnya mengajukan pertanyaannya dengan bahasa sederhana dan mendapat jawaban yang tepat. Multi-modal fusion adalah yang memungkinkan find_symbol, pencarian semantik, dan analisis dependensi berada di balik satu permukaan kueri: sistem membaca bentuk pertanyaannya dan diam-diam merakit retriever yang tepat untuknya. Model yang menilai embedding itu penting, tetapi begitu juga mengetahui kapan tidak menggunakannya. Memilih tool yang tepat untuk setiap kueri adalah jenis kualitasnya sendiri, dan itu jenis yang lebih kami pilih untuk kami tangani sendiri ketimbang dilemparkan ke pemanggil.
// you bring the question. it brings the tools.
Bacaan terkait
Lebih banyak dari build log Maguyva
Mengapa Kami Meningkatkan Pencarian Kode ke voyage-4-large_
Kami memindahkan embedding kode kami ke voyage-4-large — saat ini teratas di papan peringkat retrieval kode RTEB publik. Versi jujurnya: trade-off yang kami ambil, apa yang sebenarnya kami indeks, dan mengapa kami membayar untuk embedding premium.
Language Recursive Self-Improvement: Menggrind Kecerdasan Kode di ~280 Bahasa_
Kami mendukung kecerdasan kode untuk ~280 bahasa. Tidak ada manusia yang bisa mengaudit itu secara manual. Jadi kami membangun loop language recursive self-improvement — spot-check, LLM-as-judge, perbaiki satu hal, validasi ulang — dan menjalankannya dengan sepasukan agen terisolasi sampai ekstraksinya benar-benar tepat, bukan sekadar hijau.
Observabilitas Agen: Hooks, Alloy, dan Grafana_
Kami menghubungkan Claude Code dan Codex ke satu stack Grafana yang sama dengan OpenTelemetry dan Alloy, lalu menggunakan trace dan log untuk menemukan dan memperbaiki masalah perilaku agen langsung di sumbernya.