向量数据库chroma vs faiss的基础使用+索引验证方法

  • Chroma:开箱即用的向量库,自带元数据、文档存储、持久化,封装度高,适合快速搭建 RAG;底层可以选用 faiss 作为向量索引后端。
  • FAISS:Meta 开源向量检索库,只负责向量相似度计算,不存原始文本、元数据,轻量高性能,适合大规模向量检索,需要自己管理文档和向量映射关系。

一、环境准备,工具安装

# chroma
pip install chromadb

# faiss(根据你的cuda版本选择,cpu版如下)
pip install faiss-cpu
# GPU版本:pip install faiss-gpu

二、chroma 基础使用

核心特性:

1.向量、文档文本、metadata一起保存

2.自带持久化,不用手动管理向量和文本映射

3.内置embedding函数,也可以接入本地embedding模型

4.支持过滤查询,删除,更新集合

import chromadb
from chromadb.utils import embedding_functions

# 1. 初始化客户端,持久化存储到 ./chroma_db
client = chromadb.PersistentClient(path="./chroma_db")

# 2. 使用本地embedding(也可以用默认openai)
embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(model_name="all-MiniLM-L6-v2")

# 3. 创建集合
collection = client.get_or_create_collection(
    name="rag_demo",
    embedding_function=embedding_fn
)

# 4. 添加数据
docs = [
    "Chroma是轻量级向量数据库,支持持久化",
    "FAISS专注向量检索,不存储原文",
    "RAG通过向量检索召回文档片段给大模型"
]
ids = ["doc0", "doc1", "doc2"]
metas = [{"source": "note"}, {"source": "note"}, {"source": "note"}]

collection.add(
    documents=docs,
    ids=ids,
    metadatas=metas
)

# 5. 查询向量
res = collection.query(
    query_texts=["向量数据库有哪些"],
    n_results=2
)
print("召回文档:", res["documents"])
print("距离:", res["distances"])
print("元数据:", res["metadatas"])

Chroma 索引验证方法

Chroma 默认底层索引:小规模用 hnsw(内存),持久化版本也是封装好的,Chroma 不直接暴露 faiss 索引对象。

验证纬度:

1.验证入库数量:collection.count()

2.重复查询稳定性验证:相同的query多次查询,看召回id、距离是否一致;判断索引是否能正常加载

3.召回正确性验证:构造已知样本,查询相近文本,看top结果是否为预期文档。

4.持久化重启验证:关闭程序,重新PersistentClient加载集合,count()查看数量,再次 query,确认磁盘索引加载成功。

5.元数据过滤验证

res = collection.query(query_texts=["向量数据库"], n_results=2, where={"source":"note"})

验证过滤条件是否生效。

问题:Chroma 无法直接查看 faiss index 内部结构;如果需要精细调参索引,建议直接使用 FAISS。

 

三、FAISS 基础使用

FAISS 只管理浮点向量,文档、id、元数据必须自己维护字典映射。

常用索引:

  • IndexFlatL2:暴力检索,100% 准确,适合小数据集;无训练
  • IndexIVFFlat:倒排索引,大数据集,需要训练
  • IndexHNSWFlat:HNSW 图索引,速度快,内存占用高
# 示例:IndexFlatL2(暴力检索)
import
faiss import numpy as np from sentence_transformers import SentenceTransformer model = SentenceTransformer("all-MiniLM-L6-v2") # 原始文本库,需要自己维护 corpus = [ "Chroma是轻量级向量数据库,支持持久化", "FAISS专注向量检索,不存储原文", "RAG通过向量检索召回文档片段给大模型" ] # 向量化 embeds = model.encode(corpus, normalize_embeddings=True) embeds = np.array(embeds, dtype=np.float32) dim = embeds.shape[1] # 向量维度 index = faiss.IndexFlatL2(dim) # L2距离索引 index.add(embeds) # 添加向量 # 查询 query_vec = model.encode(["向量数据库"], normalize_embeddings=True) query_vec = np.array(query_vec, dtype=np.float32) D, I = index.search(query_vec, k=2) print("距离 D:", D) print("索引 I:", I) # 返回corpus数组下标,自己映射到原文 for idx in I[0]: print(corpus[idx])

FAISS 索引验证方法

1. 基础校验

print(index.ntotal) # 向量总数,验证写入数量
print(index.d)      # 向量维度,必须和编码模型输出一致

2. 向量写入校验:取一条已知向量,index.search,看是否召回自身,距离≈0。

D, I = index.search(embeds[0:1], k=1)
print(D, I)
# D[0][0]接近0,I[0][0]==0,代表向量入库正确

3. 索引加载验证

保存索引到文件,重启程序读取,执行检索,对比加载前后召回结果 (D,I) 完全一致。

4. 索引训练验证(IVFFlat 等需要训练的索引)

# IVFFlat示例
dim = embeds.shape[1]
nlist = 2 # 聚类中心数量
quantizer = faiss.IndexFlatL2(dim)
index_ivf = faiss.IndexIVFFlat(quantizer, dim, nlist)
# 必须先训练!
index_ivf.train(embeds)
assert index_ivf.is_trained # 验证是否训练完成
index_ivf.add(embeds)

5. 召回一致性验证

  • Flat 索引:精确检索,IVF/HNSW 是近似索引,允许少量召回偏差
  • 对比 IndexFlatL2(真值)和 IVF/HNSW 的召回结果,计算召回率,评估索引质量

6. 边界验证

  • 向量类型:必须float32;类型错误会直接报错
  • 向量归一化:使用内积索引IndexFlatIP时,向量需要归一化

四、Chroma 和 FAISS 对比总结

项目ChromaFAISS
存储向量 ✅ ✅
存储原文 / 元数据 ✅内置 ❌需要自己维护
持久化 ✅开箱即用 ✅手动 save/load
索引类型 底层封装 faiss,配置弱 丰富索引(Flat/IVF/HNSW)
适用场景 快速搭建 RAG 原型,文档管理 大规模向量检索,性能调优
索引验证 只能验证数量、召回结果,无法直接操作底层索引 可以直接读取索引参数、训练状态、向量总数

五、常见坑点

  1. Chroma:切换 embedding 模型后,旧向量和新向量维度不一致,查询结果错乱;同一个集合必须使用同一个 Embedding 模型
  2. FAISS:向量必须np.float32,很多人直接用 float64,检索异常;
  3. FAISS IVF 索引:训练样本太少,聚类效果差,召回率暴跌;
  4. FAISS 不存储文本,向量数组下标和文档 id 映射一旦错位,召回的文本完全错误。
posted @ 2026-09-23 18:17  sunshine_coast  阅读(17)  评论(0)    收藏  举报