Çok Modlu Füzyon Arama: Her Sorgu için Doğru Getiriciyi Seçmek
> 'parseConfig nerede tanımlanmış' gibi bir sorgu, 'kimlik doğrulama nasıl çalışıyor' sorgusundan farklı bir arama ister. Maguyva niyeti sınıflandırır, dört getirim modalitesini buna göre ağırlıklandırır ve sonuçları ağırlıklı Reciprocal Rank Fusion ile birleştirir.
Bir arama sorgusu tek bir şey değildir.
“parseConfig nerede tanımlanmış” tam bir sembol ister — tek, kesin bir konum, hızlıca. “kimlik doğrulama nasıl çalışıyor” anlam ister — bir kavramı açıklayan ilgili kodun yayılımı. “bu fonksiyonu değiştirirsem ne bozulur” bağımlılık grafiğini ister. “ECONNREFUSED dizesini bul” tam bir eşleşme ister, hiçbir zekice yaklaşım değil.
Grep, tam eşleşmeler için mükemmeldir ve bazı referans aramaları için yararlıdır, ama bir bağımlılık grafiği değildir ve anlamı anlamaz. Gömme (embedding) vektörleri semantik tarafı kapsar, ama tam dizeler ve etki analizi için yanlış araçtır. Çoğu kod arama aracı tek bir motor seçer ve her sorguyu bu seçimle yaşamaya zorlar. Maguyva seçmez. Sorulan sorunun türünü çözer, sonra dört getiriciyi o sorunun hak ettiği oranda harmanlar.
Dört modalite
Kaputun altında kod bulmanın dört bağımsız yolu vardır:
- semantic — Voyage ikili gömmeleri üzerinden vektör araması; kodu anlamıyla bulur.
- text — trigram eşleştirme; tam dizeleri, hata mesajlarını, tam tanımlayıcıları bulur.
- structural — AST sorguları; tanımları, imzaları ve dil yapılarını bulur.
- graph — bağımlılık grafiği; çağıranları, çağrılanları ve etki yarıçapını bulur.
Her biri farklı bir soru sınıfında güçlüdür. Zor olan kısım, karşınızdaki sorgu için her birine ne kadar güveneceğinize karar vermektir.
Niyet sınıflandırması
Herhangi bir getirim çalışmadan önce, hafif bir sınıflandırıcı sorguyu bir güven puanıyla birlikte altı niyetten birine ayırır. Kasıtlı olarak ucuzdur — sıralı sezgisel yöntemler, ilk eşleşme kazanır — çünkü yoğun yolda çalışır ve sadece bir iki milisaniye ekler:
def,class,func,importile başlar… → find_definition (güven 0.95)- “who calls”, “usages of”, “references to” → find_references (0.90)
- “impact”, “blast radius”, “what depends on” → impact_analysis (0.90)
- tırnaklı bir
"string"veyatracebackgibi bir hata belirteci → exact_match (0.85–0.90) - bir
CamelCaseveyasnake_casetanımlayıcısı → find_definition (0.60–0.80) - “how”, “why”, “explain”, “architecture” → understand_code (0.75)
- hiçbiri eşleşmez → understand_code, düşük güven (0.40)
Her niyet, dört modalite genelinde bir ağırlık profili taşır. Bunlar gerçek sayılardır:
| 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 |
Yani “parseConfig nerede tanımlanmış” AST’ye ağır bir şekilde dayanır (0.6). “kimlik doğrulama nasıl çalışıyor” semantik vektörlere dayanır (0.5). “buna ne bağımlı” neredeyse tamamen graf’tır (0.7). “ECONNREFUSED bul” neredeyse tamamen trigram’dır (0.9), gömme modeli tamamen devre dışı bırakılmış olarak — çünkü semantik benzerlik, tam bir dize için tam olarak yanlış araçtır.
Hızlı yol ve füzyon edilmiş yol
Sınıflandırıcı emin olduğunda — puan ≥ 0.85 — ve sorgu normal bir sorguysa, Maguyva füzyonu tamamen atlar ve doğrudan baskın tek modaliteye yönlendirir. “X nerede tanımlanmış”, dört getiriciye ihtiyaç duymaz; şu anda AST indeksine ihtiyaç duyar. Bu doğrudan yol fusion_strategy: "direct" olarak geri raporlanır.
Belirsiz olan her şey füzyondan geçer. Dört (veya varsayılan ön ayarda üç) modalite paralel çalışır, her biri kendi sıralı listesini döndürür ve biz bunları birleştiririz.
Ağırlıklı Reciprocal Rank Fusion
Heterojen getiricileri birleştirmek göründüğünden zordur: 0,82’lik bir kosinüs benzerliği, 137’lik bir trigram puanı ve 0,004’lük bir graf merkeziliği aynı ölçekte değildir, bu yüzden bunları toplayamazsınız. Reciprocal Rank Fusion, ham puanları atıp yalnızca her motorun atadığı sıralamayı tutarak sorunu bertaraf eder. Bir sonucun tek bir modaliteden gelen katkısı şudur:
contribution = weight × 1 / (k + rank + 1)
burada rank o modalitenin listesindeki konumudur ve k bir yumuşatma sabitidir. Katkılar, birden fazla motorun bulduğu herhangi bir sonuç için modaliteler arasında toplanır — getiriciler arasındaki anlaşma doğal olarak üste yüzer. Varsayılan ön ayarda k = 40, thorough’te ise 60 kullanırız (quick yalnızca semantik çalışır, bu yüzden füzyon orada hiç devreye girmez). Orijinal RRF çalışması genel amaçlı getirim için k = 60’ta karar kıldı; biz varsayılan olarak biraz daha keskin bir değer kullanırız, bu da modaliteler arasındaki en üst sıralı anlaşmaya biraz daha fazla ağırlık verir — ve bunu elle ayarlamanızı önermiyoruz.
Bunun üzerine, sonuçlar bir graf önem artışı taşır. Bir merkez (hub) — tüm kod tabanının dayandığı bir fonksiyon — aynı metinsel alaka düzeyinde bile belirsiz bir yaprağı geride bırakmalıdır, bu yüzden her katkıyı şununla çarparız:
boost = min(1 + 0.3 × ln(1 + centrality), 1.5)
Merkezilik, hattın önceden hesaplanmış PageRank/derece metriklerinden gelir ve artış 1,5 kat ile sınırlandırılmıştır, böylece popüler bir fonksiyon daha alakalı ama belirsiz bir fonksiyonu tamamen gömemez. Son olarak, vendor, build ve arşiv yollarından gelen sonuçları geriye düşürürüz ve dosya başına en iyi parçaya göre tekilleştiririz.
Hâlâ kusurlu olan
Niyet sınıflandırıcı, öğrenilmiş bir model değil, bir düzenli ifade (regex) yığınıdır. Bir sorgunun yaygın biçimlerini iyi kapsar — onu tanıtan karar, sıfır sonuç oranının kabaca %15’ten %5’in altına düştüğünü kaydetti — ama sezgiseldir ve gerçekten belirsiz bir sorgu understand_code’e ve semantik ağırlıklı bir karışıma düşer. Bu güvenli bir varsayılandır, zekice bir varsayılan değil. Bunu eğitilmiş bir sınıflandırıcıyla değiştirmedik çünkü ucuz sürüm yeterince hızlı ve yeterince iyi, ve çünkü yanlış ama kendinden emin bir sınıflandırıcı, dürüst bir yedekten daha kötüdür. Ağırlıkların kendisi, toplamadığımız tıklama verisinden öğrenilmiş değil, elle seçilmiş önsel değerlerdir.
Aracı Değil, Soruyu Sorun
Bir ajanın grep’e mi, gömmelere mi, yoksa çağrı grafiğine mi başvuracağını bilmesi gerekmemeli — sorusunu düz bir dille sormalı ve doğru yanıtı almalı. Çok modlu füzyon, find_symbol’in, semantik aramanın ve bağımlılık analizinin tek bir sorgu yüzeyinin arkasında oturmasını sağlayan şeydir: sistem sorunun biçimini okur ve sessizce onun için doğru getiriciyi bir araya getirir. Gömmeleri puanlayan model önemlidir, ama onları ne zaman kullanmayacağını bilmek de önemlidir. Her sorgu için doğru aracı seçmek kendi başına bir kalite türüdür ve bunu çağırana devretmek yerine sahiplenmeyi tercih ederiz.
// you bring the question. it brings the tools.
İlgili okumalar
Maguyva yapım günlüğünden daha fazlası
Kod Aramasını voyage-4-large'a Neden Yükselttik_
Kod gömmelerimizi voyage-4-large'a taşıdık — şu anda herkese açık RTEB kod getirim liderlik tablosunun zirvesinde. Dürüst versiyon: yaptığımız ödünleşim, gerçekte neyi indekslediğimiz ve neden premium gömmelere ödeme yaptığımız.
Dilde Özyinelemeli Öz-İyileştirme: ~280 Dilde Kod Zekâsını İnceden İnceye Cilalamak_
~280 dil için kod zekâsı desteği sunuyoruz. Hiçbir insan bunu elle denetleyemez. Bu yüzden bir dilde özyinelemeli öz-iyileştirme döngüsü kurduk — nokta kontrolü, hakem olarak LLM, tek bir şeyi düzelt, yeniden doğrula — ve çıkarım sadece yeşil değil gerçekten doğru olana kadar bunu izole ajanlardan oluşan bir filoyla çalıştırıyoruz.
Ajan Gözlemlenebilirliği: Hook'lar, Alloy ve Grafana_
Claude Code ve Codex'i OpenTelemetry ve Alloy ile tek bir Grafana yığınına bağladık, ardından ajan davranış sorunlarını kaynağında bulup düzeltmek için izleri (trace) ve günlükleri kullandık.