使用向量数据库 Faiss +bge-small-zh-v1.5实现简单的相似度搜索功能

Faiss:用来将结构化数据转换成向量存储在向量数据库中,之后进行检索等操作

通过FAISS检索出Top-K结果需要 5个步骤

1.获取数据来源

2.将数据构造成向量数据集(向量数据的归化)

3.使用FAISS 构建索引

4.将向量数据集添加到索引中

5.在索引中进行相似度搜索

6.返回相似度最高的 Top-K结果

复制代码
#安装插件

#支持大量预训练模型(多语言 / 中文 / 专用领域)

pip install sentence-transformers
pip install modelscope
    
#阿里开源的中文优化语义模型
modelscope download --model BAAI/bge-small-zh-v1.5

完整代码

复制代码
import logging

import faiss
import numpy as np
from sentence_transformers import SentenceTransformer

from cs.models import Products

class ProductVectorStore:
    def __init__(self):
        """使用sentence-transformers简化版本"""
        # model_local_path = "/Users/jiajiamao/.cache/modelscope/hub/models/sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
        # self.model = SentenceTransformer(model_local_path)

        #使用阿里 bge-small-zh 语义
        model_local_path = "/Users/jiajiamao/.cache/modelscope/hub/models/BAAI/bge-small-zh-v1.5"
        self.model = SentenceTransformer(model_local_path)
        """引索"""
        self.product_index = None
        self.product_texts = []
        self.getProduct()

    """
        获取商品数据
    """
    def getProduct(self):
        #从mongo中获取 商品信息
        products_mongos = Products.objects.only('product_id', 'name', 'description')
        #转换成pbm
        products_dict = [products_mongo.to_dict() for products_mongo in products_mongos]
        logging.info(f"products_dict 商品列表 {products_dict}")

        #模型期望的是文本列表。需要从每个字典中提取文本信息,然后组合成模型可以处理的文本
        product_texts = [f"{p.get('name', '')} {p.get('description', '')}" for p in products_dict]
        self.product_texts = product_texts
        logging.info(f"提取文本信息 {self.product_texts}")
        logging.info(f"已添加 {len(self.product_texts)} 条中文文本")


        """转换商品向量   直接批量转换为向量 """
        product_vectors = self.model.encode(product_texts,convert_to_numpy=True)
        product_vectors = product_vectors.astype(np.float32)


        """归化 是不是就可以理解成  转换成一种比例"""
        """Faiss内置归一化函数"""
        faiss.normalize_L2(product_vectors)
        logging.info(f"商品归化列表 {product_vectors}")


        """
            创建索引 ------ 使用内积索引(适合归一化后的向量,等同于余弦相似度)
        """
        if self.product_index is None:
            """维数"""
            dimension = product_vectors.shape[1]
            #欧几里得距离(L2距离)索引,它计算的是向量之间的几何距离,不是语义相似度。
            # self.product_index = faiss.IndexFlatL2(dimension)
            #内积索引  内积 = 余弦相似度
            self.product_index = faiss.IndexFlatIP(dimension)
        """增加到索引中"""
        self.product_index.add(product_vectors)
        logging.info(f"增加到索引中数据总数 {self.product_index.ntotal} 条中文文本")


    def searchProduct(self,query,top):

        """ 转换向量 """
        search_product_vector = self.model.encode(query,convert_to_numpy=True)
        search_product_vector = search_product_vector.astype(np.float32)
        """把一维向量变成二维:(1, D)"""
        search_product_vector = search_product_vector.reshape(1, -1)

        """归化"""
        faiss.normalize_L2(search_product_vector)

        """搜索 top条 相似商品  返回两个数组:距离数组和索引数组 """
        scores, indices = self.product_index.search(search_product_vector,top)

        """将结果格式化为字典列表"""
        results = []
        for score, idx in zip(scores[0], indices[0]):
            if idx != -1 and idx < len(self.product_texts):  # 检查索引有效性
                # 从product_texts中获取商品文本,但实际可能需要完整商品信息
                results.append({
                    'index': int(idx),  # 索引位置
                    'text': self.product_texts[idx],  # 商品文本
                    'score': float(score)  # 距离分数(越小越相似)
                })

        return results

测试 发送请求

复制代码
@csrf_exempt
def getProducts(request):
    try:
        if request.method == 'GET':
          keywords = request.GET.get("message")
           #取10条结果数据
          vector = ProductVectorStore().searchProduct(keywords, 10)
        else:
            raise BusinessException(ResponseCodeEnum.METHOD_ERROR.status_code,
                                    ResponseCodeEnum.METHOD_ERROR.status_message)
        return JsonResponse(CommonResult.success_data(vector), json_dumps_params={'ensure_ascii': False})
    except BusinessException as e:
        return JsonResponse(CommonResult.error(e.code, e.message), json_dumps_params={'ensure_ascii': False})
相关推荐
Java后端的Ai之路5 小时前
【AI大模型开发】-基于FAISS的语义搜索系统(实战)
人工智能·faiss·向量数据库
程序猿炎义2 天前
【Easy-VectorDB】Faiss入门与环境搭建笔记
人工智能·faiss
锁我喉是吧3 天前
Android studio 编译faiss
android·android studio·faiss
小毅&Nora4 天前
【向量数据库】Milvus 向量数据库 ④ 向量索引的存储结构与查询执行模型:从 Faiss 到 Knowhere 的源码解剖
向量·milvus·faiss
菜鸟冲锋号10 天前
从零搭建高可用GraphRAG系统:LangChain+Neo4j+FAISS+Qwen-7B实战指南
langchain·neo4j·faiss
薛定谔的猫198212 天前
RAG(三)文档的加载 基于 LangChain+FAISS 构建本地文档向量检索系统
数据挖掘·langchain·faiss
Suahi12 天前
【HuggingFace LLM】FAISS语义搜索
faiss
Coder_Boy_13 天前
Java调用Python实现FAISS向量操作(两种方式完整实战)
java·python·faiss
Coder_Boy_17 天前
基于SpringAI的智能AIOps项目:微服务与DDD多模块融合设计概述
java·运维·人工智能·微服务·faiss