# 多模態融合搜尋：為每個查詢挑選正確的檢索方式

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

> 像「parseConfig 定義在哪裡」這樣的查詢，需要的搜尋方式和「auth 是如何運作的」截然不同。Maguyva 會先分類查詢意圖，據此為四種檢索模式加權，再以加權版的 Reciprocal Rank Fusion（倒數排名融合）演算法整合結果。

> 歷史設計說明：這篇 2026 年 4 月的文章描述的是當時的路由設計，並非目前的預設行為。下方 9 月的更正僅針對一項測量聲明。關於目前的路由、預設組態與明確的檢索模態控制，請參閱[運作原理](https://maguyva.ai/zh-hant/docs/how-it-works)。

搜尋查詢從來不是單一種東西。

「`parseConfig` 定義在哪裡」想要的是精確的符號——一個精準的位置，而且要快。「authentication 是如何運作的」想要的是意義——是能解釋一個概念的相關程式碼分佈全貌。「如果我修改這個函式會壞掉什麼」想要的是依賴關係圖。「找出字串 `ECONNREFUSED`」想要的是字面比對，不需要耍任何花招。

Grep 在字面比對上表現優異，對某些參照搜尋也很有用，但它不是依賴關係圖，也不理解意義。嵌入模型涵蓋了語意層面，但對精確字串比對與影響分析來說，卻是用錯了工具。多數程式碼搜尋工具只會選定一種引擎，讓每個查詢都得將就這個選擇。Maguyva 不做這種取捨，而是先判斷你提出的是哪一類問題，再依該問題應得的比例，混合四種檢索方式。

## 四種模式

在底層，有四種各自獨立的方式可以找到程式碼：

- **語意（semantic）** — 對 Voyage 二元嵌入向量進行向量搜尋，依意義找出程式碼。
- **文字（text）** — 三字元片段（trigram）比對，找出字面值、錯誤字串、精確識別碼。
- **結構（structural）** — AST 查詢，找出定義、簽章與語言結構。
- **圖譜（graph）** — 依賴關係圖，找出呼叫端、被呼叫端與影響範圍。

每一種模式各擅長不同類型的問題，關鍵在於：針對眼前這個查詢，該給予每一種多少信任。

## 意圖分類

在任何檢索執行之前，一個輕量分類器會先將查詢歸入六種意圖之一，並附上信心分數。這個分類器刻意做得很精簡——依序套用啟發式規則，第一個命中者勝出——因為它運作在關鍵路徑上，只能增加一兩毫秒的延遲：

- 以 `def `、`class `、`func `、`import `⋯⋯ 開頭 → **find_definition**（信心 0.95）
- 「who calls」「usages of」「references to」→ **find_references**（0.90）
- 「impact」「blast radius」「what depends on」→ **impact_analysis**（0.90）
- 加了引號的 `"string"` 或像 `traceback` 這樣的錯誤相關詞彙 → **exact_match**（0.85–0.90）
- 一個 `CamelCase` 或 `snake_case` 形式的識別碼 → **find_definition**（0.60–0.80）
- 「how」「why」「explain」「architecture」→ **understand_code**（0.75）
- 都不符合 → **understand_code**，低信心（0.40）

每種意圖在四種模式上都有各自的權重設定，以下是實際數值：

| 意圖 | 語意 | 文字 | 結構（AST） | 圖譜 |
|---|---|---|---|---|
| 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 |

因此「`parseConfig` 定義在哪裡」會大幅偏重 AST（0.6）；「auth 是如何運作的」會偏重語意向量（0.5）；「什麼依賴這個」幾乎完全倚重圖譜（0.7）；「找出 `ECONNREFUSED`」則幾乎完全倚重三字元片段比對（0.9），並完全關閉嵌入模型——因為對精確字串來說，語意相似度正是用錯了工具。

## 快速路徑，以及融合路徑

當分類器信心足夠——分數 ≥ 0.85——且查詢屬於一般情形時，Maguyva 會完全跳過融合，直接路由到單一主導模式。「X 定義在哪裡」不需要四種檢索器，它現在就需要的是 AST 索引。這條直達路徑會回報為 `fusion_strategy: "direct"`。

其餘一切模糊不清的查詢，都會經過融合程序。四種（或在預設集下為三種）模式會並行執行，各自回傳自己的排名清單，再由我們加以整合。

## 加權版 Reciprocal Rank Fusion

融合異質的檢索器，比聽起來還要困難：0.82 的餘弦相似度、137 的三字元片段分數，以及 0.004 的圖譜中心性，彼此並不在同一個量尺上，因此不能直接相加。Reciprocal Rank Fusion（倒數排名融合）繞過了這個問題——捨棄原始分數，只保留每個引擎所給出的**排名**。某項結果來自某一種模式的貢獻值為：

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

其中 `rank` 是它在該模式清單中的位置，`k` 則是一個平滑常數。若某項結果被一種以上的引擎找到，各模式的貢獻值就會加總——檢索器之間的共識，自然會浮上頂端。我們在預設集中使用 **k = 40**，在 `thorough` 中則使用 60（`quick` 僅執行語意搜尋，因此融合機制在那裡從不啟動）。RRF 原始研究對一般用途檢索採用 k = 60；我們的預設值更偏重前列結果，讓多種模式都排在前列的結果獲得稍高的權重——而我們不建議手動調整這個數值。

除此之外，結果還會帶有一項**圖譜重要性加成**。一個樞紐節點——整個程式碼庫都仰賴的函式——即使在相同的文字相關性下，也應該排在不起眼的葉節點之前，因此我們會將每項貢獻值乘以：

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

中心性數值來自管線預先計算好的 PageRank／度數指標，且此加成上限鎖定在 1.5 倍，避免一個熱門函式完全蓋過另一個相關性更高、卻較不起眼的函式。最後，我們會將來自 vendor、build 與 archive 路徑的結果降權，並針對每個檔案去除重複，只保留最佳片段。

## 仍不完美之處

意圖分類器是一組正規表示式，而不是經過訓練的模型。它以啟發式方法處理常見的查詢形式，遇到模糊的查詢時，會退回 `understand_code` 與偏重語意的混合檢索。本文的早期版本曾將無結果查詢比例從約 15% 降至低於 5% 描述為已實現的改善。實際上，2025 年 12 月的提案列出的是估計基準與目標，並未提供支持此結果的查詢集或測量紀錄。我們撤回這項已實現改善的聲明；參見[來源證據與更正（英文）](https://maguyva.ai/evidence/search-quality.md)。我們尚未以訓練過的模型取代這個分類器，因為低成本版本對於預定的路由用途而言夠快、也夠好，而且一個自信卻錯誤的分類器，比一個坦誠的備援方案更糟。這些權重是手動選定的先驗值，並非從我們沒有收集的點擊資料中學習而來。

## 問問題，而不是選工具

代理不該需要自己判斷該用 grep、嵌入模型還是呼叫圖——它應該用直白的方式提出問題，並得到正確的答案。多模態融合，正是讓 `find_symbol`、語意搜尋與依賴分析，能共同藏身於單一查詢介面之後的原因：系統會讀懂問題的形狀，靜靜地為它組出正確的檢索方式。負責為嵌入向量評分的模型固然重要，但知道*何時不該*使用它們同樣重要。為每個查詢挑選正確的工具，本身就是一種品質，而這正是我們寧可自己扛下、也不願丟給呼叫端處理的事。

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