FAISS 向量相似搜尋
FAISS (Facebook AI Similarity Search) 是 Facebook AI 開發的開源函式庫,專門用來在大規模向量集合中進行快速的相似度搜尋。
它是現代推薦系統、語意搜尋、RAG (檢索增強生成) 的底層核心引擎。
安裝 FAISS
pip install faiss-cpu # 或 faiss-gpu(如果有 GPU)
基本使用
import numpy as np
import faiss
import time
# 產生測試資料:10000 個 128 維向量
np.random.seed(42)
d = 128 # 向量維度
n = 10000 # 向量數量
xb = np.random.random((n, d)).astype('float32')
# 建立 Index(暴力掃描 L2 距離)
index = faiss.IndexFlatL2(d)
print(f"Index 是否訓練: {index.is_trained}")
# 加入向量
index.add(xb)
print(f"Index 中向量數: {index.ntotal}")
# 搜尋:找最近的 5 個鄰居
xq = np.random.random((5, d)).astype('float32') # 5 個查詢向量
start = time.time()
k = 5
distances, indices = index.search(xq, k)
elapsed = time.time() - start
print(f"\n=== 暴力搜尋結果 ===")
print(f"耗時: {elapsed*1000:.2f} ms")
for i in range(5):
print(f"查詢 {i}: 最近鄰居 = {indices[i]}, 距離 = {distances[i]}")
使用 IVF 加速大規模搜尋
當向量數量超過 100 萬時,暴力掃描太慢。我們使用 IVF (Inverted File) 索引:
# 建立 IVF 索引(使用 100 個聚類中心)
nlist = 100
quantizer = faiss.IndexFlatL2(d)
index_ivf = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)
# IVF 需要訓練
index_ivf.train(xb)
index_ivf.add(xb)
# 搜尋(nprobe 控制探索的聚類數)
index_ivf.nprobe = 10 # 探索 10 個最近的聚類
start = time.time()
distances_ivf, indices_ivf = index_ivf.search(xq, k)
elapsed_ivf = time.time() - start
print(f"\n=== IVF 搜尋結果 ===")
print(f"耗時: {elapsed_ivf*1000:.2f} ms (加速 {(elapsed/elapsed_ivf):.1f}x)")
# 檢查準確率
correct = sum(1 for i in range(5)
if set(indices[i]) == set(indices_ivf[i]))
print(f"前 5 完全匹配率: {correct/5:.0%}")
應用:向量-Based 推薦系統
# 模擬電影推薦
n_movies = 5000
n_dims = 64
# 產生電影特徵向量(每個維度代表一種風格)
movie_features = np.random.random((n_movies, n_dims)).astype('float32')
movie_titles = [f"電影 {i}" for i in range(n_movies)]
# 建立 Index
index_movies = faiss.IndexFlatIP(n_dims) # 內積 = 餘弦相似度(向量已正規化)
faiss.normalize_L2(movie_features)
index_movies.add(movie_features)
# 模擬使用者偏好
user_pref = np.random.random((1, n_dims)).astype('float32')
faiss.normalize_L2(user_pref)
# 推薦 10 部電影
D, I = index_movies.search(user_pref, 10)
print(f"\n=== 向量推薦結果 ===")
for idx, score in zip(I[0], D[0]):
print(f"推薦: {movie_titles[idx]} (相似度: {score:.4f})")
使用 Vibe Coding 整合 FAISS
🔥 【FAISS 詠唱範例】
「請幫我建立一個向量搜尋 API:1. 使用 FAISS 建立 100 萬條 256 維向量的索引。2. 使用 IVF1000 + PQ32 壓縮索引,控制記憶體在 1GB 內。3. 用 FastAPI 包裝成 POST /search 端點。4. 支援新增向量 (add) 與搜尋 (search)。5. 加入快取層減少重複查詢。6. 輸出搜尋耗時與每秒查詢數 (QPS)。」