向量数据库 FAISS

FAISS是什么

FAISS(Facebook AI Similarity Search) 是由 Meta(原 Facebook)开发的开源向量检索引擎,专为"海量向量的高效相似度搜索"而设计。它不是数据库,而是一个超高性能的 C++/Python 向量索引库,可以让你在本地环境下进行数百万级别的向量匹配操作。

它到底能干啥?

  • 语义检索:根据问句的语义找到最接近的文档片段
  • RAG 系统:作为大模型上下文召回的向量库
  • 文本聚类:找出相似内容或主题群组
  • 图像 / 视频搜索:嵌入图像特征后进行相似内容比对

特点

特点 优势说明
🚀 性能极强 支持百万向量以内毫秒级响应(本地 CPU / GPU)
🧩 部署轻量 不需要服务器,不需要 Docker,一句 pip 即可
🔐 本地私有化友好 所有数据都在你机器上,无外泄风险
⚙️ 模块组合灵活 提供 10 多种索引结构,适配不同精度 / 速度场景

和 Milvus / Qdrant 有什么区别

对比点 FAISS Milvus Qdrant
部署复杂度 ✅ 超简单(即插即用) ⛔ 较高(需集群支持) ⚠️ 中等(需服务端部署)
本地部署友好度 ✅ 完美支持 ❌ 依赖服务端环境 🟡 支持但资源占用较大
量化搜索支持 ✅ 全面(PQ/OPQ/HNSW等) ✅ 支持 ✅ 部分支持
REST API ❌ 需自行封装 ✅ 原生提供 ✅ 原生提供
适用场景 本地/轻量/嵌入式系统 云原生大型项目 中型服务项目

FAISS 在 RAG 系统中的角色

在现代 RAG(检索增强生成)系统中,FAISS 扮演着**"语义中间人"**的角色:帮大模型找出最有可能相关的上下文

python 复制代码
知识库构建过程:
【文档】
     ↓
【文档内容向量化】
     ↓
【FAISS 向量索引存储】


提问过程:
【用户问题】
     ↓
【句子向量化】
     ↓
【FAISS 向量索引读取、检索】
     ↓
【相关文段 TopK】
     ↓
【Prompt 拼接】
     ↓
【大模型生成回答】

为什么大模型必须搭配向量检索?

  • 大模型不能**"凭空知道"你给的知识**;
  • 文档直接塞进 prompt 会超长、杂乱、失真;
  • FAISS 帮你精准提取与问题最相关的语义片段,极大提升准确率。

向量搜索基础知识快速入门

向量搜索(Vector Search)是当前语义检索的核心机制,相较传统关键词搜索,它能理解"意思相近但表达不同"的文本。

我们先从底层原理讲起,帮助你真正理解 FAISS 是在干什么。

向量 VS 关键词

传统关键词搜索(例如 Elasticsearch)基于的是词面匹配,而向量搜索是把文本编码成数学空间中的一个"点",然后找距离最近的点。

项目对比

搜索方式 关键词搜索 向量搜索
匹配方式 精确关键词匹配 语义相似度模糊匹配
示例问句 "股东责任" "投资人需要承担什么后果?"
命中结果 包含"股东责任"的文本段落 包含"出资方责任"的文本段落

什么是"向量"

一句话可以用一个固定长度的向量表示。例如用 768 维向量表示一段文本:

复制代码
[0.24, -0.88, 0.12, ..., 0.01]  ← 共 768 个维度

这些向量一般由预训练模型生成,如:

  • text2vec-base
  • bge-large-zh-v1.5
  • sentence-transformers 系列

向量检索

向量检索的本质是:你给我一个向量,我从海量向量中找到它的"邻居"们

常见的相似度度量方式有两种:

1. 欧氏距离(L2 距离)

衡量两个向量在空间中的"直线距离",距离越近表示越相似。

复制代码
D(x, y) = √[(x1 - y1)^2 + (x2 - y2)^2 + ... + (xn - yn)^2]

FAISS 中采用的索引类型为 IndexFlatL2

2. 余弦相似度(Cosine Similarity)

衡量两个向量之间的夹角,夹角越小相似度越高,值越接近 1 表示越相似。

复制代码
cos(θ) = (x · y) / (||x|| × ||y||)

其中:

  • x · y 表示两个向量的点积
  • ||x|| 是向量的 L2 范数(模长)

FAISS 中使用:IndexFlatIP + 向量归一化。

示例对比(实战感知)

python 复制代码
query = "法人责任如何界定?"

匹配结果(L2): "公司法人应承担的财务责任包括..."
匹配结果(Cosine): "董事会成员的责任范围主要涵盖..."

什么是 Top-K 检索

复制代码

你给出一个查询向量,FAISS 会返回前 K 个最相似的向量及其原文索引。

python 复制代码
D, I = index.search(query_vector, k=3)
  • D 是距离值(越小越相似)
  • I 是命中向量的索引列表(用来查原文)

这就是 RAG 系统中"文档召回"最关键的一步。

向量检索让 AI 系统不再死记硬背关键词,而是真正"理解语义",这正是构建智能问答系统的关键基石。

实战一:FAISS构建本地向量检索系统

复制代码

基于 FAISS 的向量检索系统:输入一份文档,转成向量后存入 FAISS,然后查询问句并返回最相关的段落。

1. 安装基础依赖

使用 sentence-transformers 生成文本向量,FAISS 做向量检索:

python 复制代码
pip install faiss-cpu sentence-transformers  # sentence-transformers嵌入模型

如需 GPU 支持,可使用:
pip install faiss-gpu

2. 文本准备(示例为法律文档)

创建一个简单的样本文本,内容如下(law.txt):

python 复制代码
第七条:公司是企业法人,有独立的法人财产。
第八条:公司以其全部财产对公司债务承担责任。
董事会对公司的经营决策具有最终权力。
股东大会是公司的最高权力机构。

3. 文本切片 + 嵌入向量生成

python 复制代码
from sentence_transformers import SentenceTransformer

# 读取文本内容、切块  后续可以使用langchain读取不同类型的文本、切块、优化切块
with open("law.txt", "r", encoding="utf-8") as f:
    texts = [line.strip() for line in f if line.strip()]

# 加载 embedding 模型(可替换为 bge/text2vec)
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")

# 生成向量(默认维度 384)
embeddings = model.encode(texts, normalize_embeddings=True)

print(f"共生成 {len(embeddings)} 个向量,每个维度为 {embeddings.shape[1]}")

sentence-transformers

离线下载使用sentence-transformers

python 复制代码
# 下载 text2vec-base-chinese  400MB
model = SentenceTransformer('shibing624/text2vec-base-chinese')
model.save('./text2vec-base-chinese')

# 或下载 bge-small-zh-v1.5  100MB
model = SentenceTransformer('BAAI/bge-small-zh-v1.5')
model.save('./bge-small-zh-v1.5')

# 使用:替换成本地目录
model = SentenceTransformer("./bge-small-zh-v1.5")

4. 构建 FAISS 索引

python 复制代码
# 创建 IndexFlatIP(使用 Cosine 相似度需先归一化)
dim = embeddings.shape[1]
index = faiss.IndexFlatIP(dim)
index.add(embeddings.astype('float32'))

实战二:向量检索 + 问句匹配(含代码)

完成索引构建后,我们就可以让系统回答"语义问题"了。

1. 输入问句,向量化

python 复制代码
# 查询向量
query = "公司法人要承担哪些责任?"
query_vec = model.encode([query], normalize_embeddings=True)

2. 使用 FAISS 执行搜索

python 复制代码
# 查询最相似的 top-k 向量
k = 2
D, I = index.search(query_vec.astype('float32'), k)
# 输出检索结果
for rank, idx in enumerate(I[0]):
    print(f"[Top {rank+1}] {texts[idx]}")

>>>:
[Top 1] 第七条:公司是企业法人,有独立的法人财产。
[Top 2] 第八条:公司以其全部财产对公司债务承担责任。

3. 构建简单 QA 返回结构

python 复制代码
def ask(query: str):
    query_vec = model.encode([query], normalize_embeddings=True)
    D, I = index.search(query_vec.astype('float32'), k=3)
    context = "\n".join([f"[{i+1}] {texts[j]}" for i, j in enumerate(I[0])])
    prompt = f"请根据以下资料回答问题:\n{context}\n\n问题:{query}"
    return prompt

prompt 输入本地 LLM完成 RAG 闭环。

4. 保存与加载索引

python 复制代码
# 保存向量索引
faiss.write_index(index, "law_faiss.index")

# 保存原文
import json
with open("law_docs.json", "w", encoding="utf-8") as f:
    json.dump(texts, f, ensure_ascii=False, indent=2)

# 读取向量索引
index = faiss.read_index("law_faiss.index")

# 读取原文json文件
with open("law_docs.json", "r", encoding="utf-8") as f:
    docs = json.load(f)
保存向量索引作用:
  • 将当前内存中的 Faiss 索引对象 index 序列化并保存成文件 law_faiss.index

  • 类似于"模型持久化",以后可直接加载,无需再次计算向量或重新构建索引。

保存向量索引内容包含:
  • 所有向量 embedding

  • 索引结构(IndexFlatIP 或其他结构)

  • 元数据如:维度、数量等

为什么要保存原文?

FAISS 只保存向量,不保存文本

未来做查询时返回的是文本下标,比如:

python 复制代码
I = [[3, 1]]

必须加载原始文档使向量查询返回的文本下标与文本内容对应上,才能得到:

python 复制代码
docs[3] → "第八条..."
docs[1] → "股东大会..."

实战小结

步骤 内容描述
文本处理 对文本进行段落分割处理,并清除空行
向量生成 使用 sentence-transformers 模型将文本编码为向量
FAISS 索引构建 采用 IndexFlatIP 方法构建索引(支持余弦相似度计算)
查询处理 将查询问句向量化后,返回 TopK 个最相似的原文段落
模型输入 将检索结果组织成 Prompt 格式输入大语言模型(详见下一节 RAG 集成说明)

优化与进阶:提升 FAISS 检索性能与准确率

1. 使用索引结构提升搜索效率

在实际项目中,当你面对的是成千上万条向量数据 ,或者需要更高检索精度与更快响应 时,仅靠 IndexFlatIP 已经不够。

FAISS 提供了丰富的高级索引结构与优化手段,以下是最推荐实用的几种。

IndexFlatIP(默认)

  • 精度:⭐⭐⭐⭐⭐
  • 速度:⭐⭐
  • 特点:暴力精确匹配,慢但稳
  • 适合小规模数据(≤5万条)

IndexIVFFlat(倒排索引)

python 复制代码
quantizer = faiss.IndexFlatIP(dim)
index = faiss.IndexIVFFlat(quantizer, dim, nlist)
index.train(embeddings)
index.add(embeddings)
  • 精度:⭐⭐⭐⭐
  • 速度:⭐⭐⭐⭐
  • 特点:先聚类再搜索,仅查部分分区
  • 适合 10万~100万 级别数据

nlist(聚类数)建议设置为 sqrt(N)

IndexHNSWFlat(图结构检索)

python 复制代码
index = faiss.IndexHNSWFlat(dim, M=32)
  • 精度:⭐⭐⭐⭐⭐
  • 速度:⭐⭐⭐
  • 特点:构建小世界图,性能介于暴力和倒排之间
  • 适合中等规模数据、精度要求高场景

2. 向量归一化 + Cosine 相似度

很多向量模型输出本质是方向(单位向量),不是位置。因此推荐使用余弦相似度:

python 复制代码
# 对所有向量归一化(单位向量)
embeddings = embeddings / np.linalg.norm(embeddings, axis=1, keepdims=True)

# 使用 IndexFlatIP(点积 = 余弦相似度)
index = faiss.IndexFlatIP(dim)
index.add(embeddings)

3. 向量去重与裁剪高频信息

  • 若一个段落多次出现,或多个片段高度相似,会导致"TopK 全部命中一样的内容";
  • 建议引入 hash 或简单文本比较去重;
  • 可以对嵌入向量用 PCA 做降噪压缩处理(参考:faiss.PCAMatrix

4. 分类型构建多个索引(可选)

faiss_index_law.index → 法律文档向量库

faiss_index_policy.index → 政策类向量库

faiss_index_case.index → 判例向量库

相关推荐
草根研究生3 天前
BM25, TF-IDF, Faiss-based methods
tf-idf·faiss
火云牌神3 天前
如何选择FAISS的索引类型
人工智能·faiss
沛沛老爹8 天前
LightRAG 系列 5:核心技术解析——HNSW 索引机制与 Web 应用中的毫秒级检索
faiss·hnsw·rag·lightrag·动态调整·索引机制·预热索引
dyxal13 天前
Faiss索引数据分享指南:从打包到云端共享
ai·faiss
wudl556618 天前
向量数据库--FAISS
数据库·faiss
paopao_wu20 天前
人脸检测与识别-InsightFace:向量相似性搜索Faiss
人工智能·yolo·目标检测·ocr·faiss
大白的编程笔记21 天前
FAISS系统解释
faiss
liliangcsdn1 个月前
如何用faiss强化基于mysql的文本检索
faiss
沛沛老爹2 个月前
用Faiss实现高效文本抄袭检测
llm·vector·向量·faiss·抄袭检测