faiss的简单使用

Faiss是一个由FacebookAI团队开发的库,专门用于稠密向量的聚类和相似性搜索,支持大规模向量的近似近邻搜索。它包含多种搜索算法,并有C++实现,提供Python接口,部分核心功能还支持GPU加速。文章详细介绍了如何安装、创建、保存和加载Faiss索引,以及如何进行向量检索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   Faiss全称(Facebook AI Similarity Search)是Facebook AI团队开源的针对聚类和相似性搜索库,为稠密向量提供高效相似度搜索和聚类,支持十亿级别向量的搜索,是目前较成熟的近似近邻搜索库。
     它包含多种搜索任意大小向量集(备注:向量集大小由RAM内存决定)的算法,以及用于算法评估和参数调整的支持代码。
Faiss用C++编写,并提供与Numpy完美衔接的Python接口。除此以外,对一些核心算法提供了GPU实现。

faiss的安装

pip install faiss-cpu==1.7.3
# pip install faiss-gpu==1.7.2  

上面的是使用cpu的版本,如果使用GPU可以安装下面语句

faiss的创建步骤

  1. 获取向量文件或者向量库。
  2. 创建faiss的索引index,(训练)将向量添加到索引index中。
  3. 使用faiss进行检索。

  代码及目录结构 github

获取向量文件或者向量库

向量文件存储在item_vec.txt中, 格式是(商品ID,向量),具体结构是下图中展示。

   读取向量文件,返回向量的matrix,由于faiss必须处理np.array的形式,所以进行转换,商品id的一个列表,商品id和序列号的键值对。

import faiss
import os
import sys
import numpy as np

# 从文件中读取向量
"""
fea_v_matrix: np.array形式的特征向量矩阵
fea_s_list: id的顺序列表
key_d: id和位置的对应dict
"""
def load_fea_from_file(fname):
    line_num = 0
    fea_s_list = list()
    fea_v_list = list()
    
    key_d = dict()
    idx = 0
    with open(fname, "r", encoding="utf-8", errors="replace") as f:
        for row_content in f:
            line_num += 1
            
            try:
                raw_content_list = row_content.strip().split()
                fea_s = raw_content_list[0]
                fea_v = np.array(raw_content_list[1:]).astype(np.float32)
            except Exception as e:
                sys.exit("fail to load file vector")
                
            if fea_s not in key_d:
                key_d[fea_s] = idx
                idx += 1
                fea_s_list.append(fea_s)
                fea_v_list.append(fea_v)
    fea_v_matrix = np.array(fea_v_list)
    return fea_v_matrix, fea_s_list, key_d

创建索引

  检索索引使用的方式可以查看文档,此处创建了一个精度索引refine,提高检索的精度。

def build_index_fun(path):
    # path : './item_vec.txt'
    fv_mat, fea_s_list, key_d = load_fea_from_file(path)

    # cluster_num 是聚类的数量
    M = fv_mat.shape[1] // 4
    cluster_num = int(fv_mat.shape[0]) // 14
    # metric_type
    metric_type = faiss.METRIC_INNER_PRODUCT
    # 创建索引
    
    index = faiss.index_factory(fv_mat.shape[1], f"IVF{cluster_num},PQ{M}x4fs", metric_type)

    # 正则化矩阵特征向量
    faiss.normalize_L2(fv_mat)

    # 训练索引
    index.train(fv_mat)

    # 索引添加矩阵向量
    index.add(fv_mat)

    # 创建一个精度索引, 它细化了距离计算,并根据这些距离对结果重新排序
    index_refine = faiss.IndexRefineFlat(index, faiss.swig_ptr(fv_mat))
    return index, index_refine, fea_s_list, key_d

保存索引到文件

  将索引保存到文件中,使用的时候能够快速获取和使用, 键值对能够更快的查找

# 将faiss的索引index写到文件中
def write_index(path):
    # path = './item_vec.txt'
    index, index_refine, keys, key_d = build_index_fun(path)
    faiss.write_index(index, './vec/index_m.faiss')
    faiss.write_index(index_refine, './vec/index_refine_m.faiss')
    # 商品和序列的键值对也写到文件中
    with open('./vec/index_key.faiss', "w") as fout:
        for ky in keys:
            fout.write(ky)
            fout.write("\n")
    return index, index_refine, keys, key_d

write_index('./item_vec.txt')

加载索引和设置查询参数

def load_index(index_dir):
    # 加载索引文件
    index = faiss.read_index('./vec/index_m.faiss')
    index_refine = faiss.read_index('./vec/index_m.faiss')
    # 设置基础索引
    index_refine.base_index = index
    index_refine.k_factor = 10
    index.nprobe = 100
    # 商品位置键值对
    keys = list()
    key_d = dict()
    with open("./vec/index_key.faiss") as fin:
        idx = 0
        for line in fin:
            line = line.strip("\r\n")
            key_d[line] = idx
            idx += 1
            keys.append(line)
    return index, index_refine, keys, key_d

向量检索

  向量检索必须是矩阵的形式传入。

# 向量检索
def search():
    # 推荐的结果集(商品ID,得分)
    res_ans = []
    # 检索最近邻的数量
    k = 10
    # 输入一个index库里的向量,进行检索
    index, index_refine, keys, key_d = load_index('./item_vec.txt')
    
    # 获取一个商品的id
    fs = '653417384213'
    i = key_d[fs]
    # 根据位置获取
    index_refine.make_direct_map()
    fv = index_refine.reconstruct(i)
    
    # 检索必须是矩阵的形式
    matrix = np.expand_dims(fv, axis=0)
    D, I = index_refine.search(matrix, k)
    # 获取结果集
    res_id_list, res_dis_list = I[0], D[0]
    for i in range(len(res_id_list)):
        res_ans.append((keys[res_id_list[i]], res_dis_list[i]))
 
        
    print(res_ans)
    
   
# load_fea_from_file('./item_vec.txt')
# build_index_fun('./item_vec.txt')
write_index('./item_vec.txt')
search()

### Faiss与大模型的整合方案 Faiss 是 Facebook 开源的一个高效相似度搜索,特别适合处理大规模向量数据集中的最近邻查询[^1]。它能够加速基于嵌入空间(embedding space)的检索操作,在结合大模型的应用场景下具有显著优势。 #### 1. 数据预处理阶段 在使用 Faiss 和大模型之前,通常需要先通过大模型生成高质量的数据表示(embeddings)。这些 embeddings 可以由自然语言处理模型(如 BERT 或其他 Transformer 架构)、图像编码器或其他模态的大规模学习框架生成。具体来说: - **文本数据**:可以利用预训练的语言模型提取语义特征。 - **图片或视频数据**:可以通过卷积神经网络 (CNN) 提取视觉特征。 此过程的核心在于确保 embedding 的维度适配于后续索引构建的需求[^2]。 #### 2. 建立 Faiss 索引 一旦获得了 embeddings 向量集合,则可将其传递给 Faiss 来创建高效的近似最近邻索引结构。以下是建立索引的一些常见选项及其适用情况: - **Flat Indexes**: 对小型到中型数据非常有效,提供精确的结果但计算成本较高。 - **IVF (Inverted File)**: 将整个数据划分为若干子簇(cluster),从而减少每次比较的数量;适用于更大规模的数据集。 - **HNSW (Hierarchical Navigable Small Worlds)**: 支持快速高维稀疏数据上的 ANN 查询[^3]。 对于超大型数据集推荐采用复合策略比如 `IndexIVFPQ` 结合量化技术进一步降低存储需求并提升性能。 ```python import faiss import numpy as np d = 128 # dimension of the vectors nb = 100000 # number of vectors to index nlist = 100 # number of clusters in IVF # Generate random data for demonstration purposes only. np.random.seed(1234) xb = np.random.random((nb, d)).astype('float32') quantizer = faiss.IndexFlatL2(d) # Define quantizer used within IVF structure index = faiss.IndexIVFFlat(quantizer, d, nlist) assert not index.is_trained # Check if training is required before adding any vector index.train(xb[:5000]) # Train using a subset of your dataset index.add(xb) # Add all remaining points after successful train step print(f"Total indexed items count={index.ntotal}") ``` 上述代码片段展示了如何初始化一个简单的 IVF Flat 索引实例,并完成基本配置流程[^4]。 #### 3. 集成至实际应用环境 当 Faiss 已经准备好之后就可以无缝集成进入各种在线服务或者离线批处理作业当中去了。例如在一个问答系统里边,每当接收到新的提问时就调用相应的大模型得到其对应的 embedding 表达形式然后再交给预先搭建好的 Faiss 搜索引擎去寻找最接近的历史记录作为候选答案返回给前端展示出来。 值得注意的是为了保证实时响应速度可能还需要考虑缓存机制以及分布式部署等问题来优化整体架构设计[^5]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值