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)。」

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!