File size: 6,395 Bytes
05a051e 1cca670 05a051e 1cca670 05a051e 1cca670 b7b69ed 1cca670 b7b69ed 1cca670 b7b69ed 1cca670 9a9282d 1cca670 b7b69ed 1cca670 a76632b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | ---
title: 繁中維基語意搜尋 zh-TW Wiki Semantic Search
emoji: 🔍
colorFrom: indigo
colorTo: pink
sdk: gradio
sdk_version: 6.20.0
app_file: app.py
pinned: false
license: mit
short_description: bge-m3 + FAISS 語意搜尋 vs BM25(50k 繁中維基段落)
models:
- BAAI/bge-m3
datasets:
- steven0226/zhtw-wiki-semsearch-index
---
# 🔍 繁中維基語意搜尋引擎(bge-m3 × FAISS × Gradio)
對繁體中文維基百科隨機抽樣的 **50,000 個段落**建立語意索引,並排比較
**語意搜尋(bge-m3 + FAISS)** 與 **關鍵字搜尋(BM25 + jieba)**,
讓「同義改寫也搜得到」的差異一眼可見。
**🚀 線上 Demo:[Hugging Face Space](https://huggingface.co/spaces/steven0226/zhtw-wiki-semantic-search)**
(免費 ZeroGPU Space,app 為純 CPU 程式碼;冷啟動需幾分鐘)
## 為什麼做這個?
關鍵字搜尋只認得字面上的詞:搜「天空為什麼藍藍的」,BM25 只能比對
「天空」「藍」這些字,找不到用「瑞利散射」「大氣層」描述同一件事的段落。
語意搜尋把整句話變成 1024 維向量,「意思相近」的段落在向量空間裡自然靠近——
即使一個字都沒重疊。Demo 裡的橘色標記就是「語意找得到、關鍵字找不到」的結果。
## 架構
```
┌─────────────────┐ ┌──────────────────────┐ ┌─────────────────────┐
│ 本機 RTX 4090 │ │ HF Dataset repo │ │ HF Space(ZeroGPU) │
│ │ │ │ │ │
│ prepare_data.py │ │ index.faiss (205MB) │ │ app.py(Gradio) │
│ build_index.py ├─────▶│ metadata.parquet ├─────▶│ ・bge-m3 編碼查詢 │
│ (fp16 批次編碼) │ 上傳 │ (title/text/url) │ 啟動時 │ ・FAISS top-10 │
│ │ │ │ 下載 │ ・BM25 對照組 │
└─────────────────┘ └──────────────────────┘ └─────────────────────┘
```
重的 embedding 計算(50k 段 × bge-m3)在本機 GPU 做,Space 只負責:
把查詢句編碼成向量(CPU、約 1–3 秒)→ FAISS 內積搜尋(<1ms)→ 顯示結果。
## bge-m3 是什麼?
[BAAI/bge-m3](https://huggingface.co/BAAI/bge-m3) 是北京智源(BAAI)的多語言
embedding 模型,基於 XLM-RoBERTa-large(~568M 參數):
- **多語言**:100+ 語言共用同一個向量空間,中文查詢可以配對英文段落
- **Multi-Functionality**:同時支援 dense、sparse(lexical)、multi-vector
(ColBERT)三種檢索——本專案用 dense 向量(1024 維)
- **免 instruction prefix**:不像 bge-*-zh-v1.5 需要「為這個句子生成表示…」前綴
- 向量 L2-normalize 後用內積(= cosine 相似度)配 `faiss.IndexFlatIP` 做精確搜尋
(50k 規模不需要 IVF/HNSW 近似索引)
## 語意 vs 關鍵字:實際例子
| 口語查詢 | 語意搜尋找到 | BM25 的困境 |
|---|---|---|
| 天空為什麼藍藍的 | 瑞利散射、大氣光學條目 | 「藍藍的」比對不到「散射」 |
| 為什麼感冒好了比較不容易再中一次 | 免疫記憶、抗體條目 | 全句沒有「免疫」兩字 |
| 月亮為什麼有時候圓有時候只剩彎彎的一條 | 月相條目 | 「彎彎的一條」不在任何條目裡 |
(實際結果依 50k 隨機抽樣內容而定,歡迎在 Demo 裡自己試)
## 重現步驟
```powershell
# 0. 環境(Windows + NVIDIA GPU;Linux 把路徑分隔換掉即可)
uv venv .venv --python 3.12 --seed
.venv\Scripts\Activate.ps1
uv pip install -r requirements-local.txt --index-strategy unsafe-best-match
# 1. 資料:下載繁中維基(8.2GB)→ 清理 → 抽 50,000 段(seed=42,可重現)
python scripts/prepare_data.py
# 2. 索引:GPU fp16 批次編碼 + FAISS IndexFlatIP
python scripts/build_index.py
# 3. 上傳到 HF dataset repo(HF_TOKEN 放專案根目錄 .env)
python scripts/upload_index.py
# 4. 本機端到端測試(先本機檔案、再走真實下載路徑)
$env:DATA_DIR="data"; python app.py
Remove-Item Env:DATA_DIR; python app.py
# 5. 部署 Space
python scripts/deploy_space.py
```
## 設計筆記
- **HF 免費帳號政策(2026)**:新的 Gradio Space 只能建在 ZeroGPU 硬體
(cpu-basic 需 PRO 訂閱)。本 app 全程純 CPU 程式碼、不呼叫 GPU,
不消耗訪客的 ZeroGPU 配額;torch 必須 pin ZeroGPU 支援清單內的版本(2.8–2.11)
- **模型只載一次**:app.py 在 module top-level eager 載入(Space 的
Building/Starting 畫面天然就是 loading 提示),並先做一次暖身編碼
- **BM25 基線**:rank_bm25 + jieba 斷詞,啟動時對同一批 50k 段落現場建索引,
與語意側用完全相同的語料對照才公平
- **CJK 路徑陷阱**:faiss 的 `write_index`/`read_index` 用窄字元 fopen,
在含中文的 Windows 路徑會失敗——全程改用
`serialize_index`/`deserialize_index` + Python byte I/O
## 效能數據
| 項目 | 數值 |
|---|---|
| 50k 段落 GPU 編碼(4090, fp16, batch 128) | 52.2 秒(約 958 句/秒),見 [build_stats.json](https://huggingface.co/datasets/steven0226/zhtw-wiki-semsearch-index/blob/main/build_stats.json)(2026-07-11 單次量測) |
| FAISS IndexFlatIP 檔案大小 | ~205 MB(50,000 × 1024 × fp32) |
| Space 查詢延遲(ZeroGPU host CPU) | 編碼 ~1–3s + 檢索 <1ms |
| Space 冷啟動 | ~5 分鐘(裝套件 + 下載模型/索引 + 建 BM25) |
## 授權
- 程式碼:MIT
- 維基百科段落文字:[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/deed.zh-hant)
© Wikipedia 貢獻者(每筆結果都附原始條目連結;索引資料的完整署名見
[dataset repo](https://huggingface.co/datasets/steven0226/zhtw-wiki-semsearch-index))
## Source repository
程式碼、訓練與評估流程、測試與完整證據都在 GitHub:<https://github.com/kuotunyu/zhtw-wiki-semantic-search>。GitHub `kuotunyu` 與 Hugging Face `steven0226` 為同一人。
Source code, the training/evaluation pipeline, tests and the full evidence trail live at <https://github.com/kuotunyu/zhtw-wiki-semantic-search>. GitHub `kuotunyu` and Hugging Face `steven0226` are the same author.
|