Hybrid Search 實戰:從中文分詞到向量資料庫選型完整指南
Hybrid Search 實戰:從中文分詞到向量資料庫選型完整指南
TL;DR
- 中文 BM25 問題:用 Python jieba 橋接 TypeScript,召回率從 30% 提升至 80%+
- 向量資料庫選型:小型專案用 LanceDB,企業級考慮 DashVector/火山引擎 LAS
- 混合架構可行:TS + Python 混用比全面重寫更務實
Part 1:中文 BM25 的問題與解決
問題背景
我的 Career RAG 專案使用 Hybrid Search(向量搜尋 + BM25 關鍵字搜尋):
Query → [BM25 Score] + [Vector Score] → Fusion (0.7v + 0.3b) → Rerank → Results
但中文 BM25 效果很差,因為預設 tokenizer 只處理英文:
// 原本的 tokenizer
function tokenize(text: string): string[] {
return text.toLowerCase().split(/\s+/); // 按空白分割
}
英文:"Kubernetes deployment" → ["kubernetes", "deployment"] ✅
中文:"台積電技術經理" → ["台積電技術經理"] ❌(整塊)
解決方案:TypeScript + Python 混合架構
TypeScript (BM25 計算)
│
▼ 偵測到中文
Python Script (jieba 分詞)
│
▼ JSON 回傳 tokens
TypeScript (繼續計算)
核心實作:
# scripts/tokenize_zh.py
import jieba
import json
import sys
# 載入自訂詞彙(公司名、技術詞)
jieba.load_userdict("user_dict.txt")
def tokenize(text):
return [t for t in jieba.cut(text.lower()) if len(t) > 1]
print(json.dumps(tokenize(sys.argv[1]), ensure_ascii=False))
// bm25.ts
function tokenize(text: string): string[] {
if (/[\u4e00-\u9fff]/.test(text)) {
// 呼叫 Python jieba
const result = execSync(`python tokenize_zh.py "${text}"`);
return JSON.parse(result);
}
return text.toLowerCase().split(/\s+/);
}
效果驗證
python tokenize_zh.py "台積電技術經理 Kubernetes 機器學習"
# 輸出: ["台積電", "技術經理", "kubernetes", "機器學習"]
| 指標 | 改進前 | 改進後 |
|---|---|---|
| 中文分詞 | 1 token(整塊) | 正確分詞 |
| BM25 召回率 | ~30-50% | ~80-90% |
| 專有名詞匹配 | ❌ | ✅ |
自訂詞彙字典
jieba 預設詞庫對專有名詞效果差,需要 user_dict.txt:
台積電 10 nz
聯發科 10 nz
機器學習 10 n
技術經理 10 n
Part 2:向量資料庫選型全景圖
解決了分詞問題後,我深入研究了向量資料庫的選擇。以下是不同規模場景的對比。
2.1 三種定位的比較
| 維度 | LanceDB | Supabase Vector | DashVector (阿里雲) |
|---|---|---|---|
| 本質 | 列式儲存格式 | PostgreSQL + pgvector | 雲原生向量 DB |
| 類比 | 「更適合 AI 的 Parquet」 | 「帶向量的 Postgres」 | 「向量版 RDS」 |
| 部署 | 嵌入式/本地 | Postgres 擴充 | 全託管雲服務 |
| 開源度 | ✅ 開源 | ✅ 開源 | ❌ 封閉(SDK) |
2.2 中國雲端生態的向量資料庫競爭
| 公司 | 產品 | 特色 | 開源參與 |
|---|---|---|---|
| 火山引擎(ByteDance) | LanceDB + LAS 數據湖 | 嵌入式、多模態、Spark 相容 | 高(LanceDB Committer) |
| 阿里雲 | DashVector | 雲原生、全託管、Proxima 引擎 | 低(封閉) |
火山引擎自 2024 年起深度整合 LanceDB,貢獻核心工程師,推出 AI 數據湖 LAS,將 LanceDB 無縫對接 Spark/Iceberg 生態,用於內部多模態向量儲存。
阿里雲則走自研路線,推出 DashVector 對抗 Pinecone 等雲向量市場。
2.3 Lance 格式 vs 傳統格式
Lance 是由 Apache Arrow、Hadoop、HBase 專家開發(Rust 編寫),設計為取代 Parquet/ORC/Iceberg:
| 效率指標 | Lance | Parquet |
|---|---|---|
| 隨機存取 | ✅ 優化 | ❌ 需全讀 |
| Schema 演進 | 零成本 | 重寫檔案 |
| 多模態支援 | 原生 | 有限 |
| AI 訓練場景 | 專為此設計 | 通用大數據 |
隨機存取是 Lance 核心:AI 訓練需要從 PB 級資料集隨機抽取樣本,傳統 Parquet 效率低。
零成本 Schema 演進:為數億條記錄添加新 Embedding 維度時,不需重寫整個檔案。
2.4 DashVector 效能規格
阿里雲 DashVector 基於 Proxima 引擎,雲原生架構,支援水平擴展:
| 實例類型 | 規模 | top-k=1 QPS / 延遲 | top-k=100 QPS / 延遲 |
|---|---|---|---|
| 效能型 P.large | 100萬×768維 | 962 / <30ms | 134 / <250ms |
| 儲存型 S.large | 500萬×768維 | 297 / <30ms | 37 / <300ms |
| Serverless | 自動擴展 | QPS<2 | 按請求計費 |
量化後 QPS 可再升 48%,適合高併發 RAG。
2.5 選型決策樹
你的場景是什麼?
├── 個人/小型專案(<100萬向量)
│ ├── 需要本地優先 → LanceDB ✅
│ ├── 已用 Postgres → Supabase Vector / pgvector
│ └── 需要雲託管 → Supabase
│
├── 中型專案(100萬-1億向量)
│ ├── 需要高 QPS → DashVector / Pinecone
│ ├── 需要開源 → Milvus / Qdrant
│ └── 已用阿里雲 → DashVector
│
└── 大型/企業級(>1億向量、AI 訓練)
├── 需要數據湖整合 → 火山引擎 LAS + Lance
├── 需要多模態 → Lance 格式
└── 需要全託管 → DashVector / Pinecone
2.6 我選擇 LanceDB 的理由
對於我的 Career RAG 專案(~100 條素材,512 維向量):
- 本地優先:資料存專案資料夾,不需外部服務
- 零配置:
npm install lancedb直接用 - 原生 Hybrid Search:Vector + BM25 內建支援
- 輕量:整個 DB 就是資料夾,可直接 git 版控
- AI 血統:前 Runway ML、Google 工程師創辦
實測效能(本地環境):
| 操作 | LanceDB | DashVector 估計 |
|---|---|---|
| 冷啟動 | ~50ms | ~200-500ms (網路) |
| 向量搜尋 | ~5-10ms | ~20-50ms (網路) |
| 批次寫入 100 條 | ~200ms | ~500ms+ |
對於本地 RAG,LanceDB 延遲優勢明顯。DashVector 的高 QPS 在我的場景屬於過殺。
Part 3:架構選擇思考
為什麼不整個專案改用 Python?
| 維持 TypeScript | 改用 Python |
|---|---|
| ✅ AI Agent Skills 整合順暢 | ❌ 需要額外橋接層 |
| ✅ 現有代碼可用 | ❌ 需要重寫 |
| ✅ 只需橋接分詞 | ✅ 原生 jieba 支援 |
結論:混合架構(TS 主體 + Python 分詞)比全面重寫更務實。
什麼時候值得重構為 Python?
- 需要更複雜的中文 NLP(關鍵詞提取、情感分析)
- 需要本地 embedding 模型(BGE-M3, text2vec-chinese)
- 需要 LangGraph 進階工作流
- 與 ML pipeline 整合(Pandas, scikit-learn)
Skills 整合說明
Skills 可以呼叫任何語言:
## 用 uv 執行 Python
cd mcp-server && uv run search_material.py --focus "AI"
uv 會自動處理虛擬環境,無需手動 activate。
關鍵學習總結
- 中文分詞:jieba + 自訂詞彙是最務實的解決方案
- 混合架構可行:TS + Python 橋接比全面重寫更高效
- 向量 DB 選型:小型用 LanceDB,企業級考慮 DashVector/Milvus
- Lance 格式趨勢:火山引擎深度採用,適合 AI 訓練場景
- uv 是好朋友:現代 Python 管理用 uv,比 pip 快 10-100 倍