LLM大语言模型调用本地知识库+faiss超级简单教程本地存储:
1、新建数据集./data/dz.json:
[{"id": "0","text": "你的名字","answer": "张三"
}, {"id": "1","text": "你是哪个公司开发的","answer": "xxxxxxxxx公司"
},.......更多知识库]
2、下载模型如: moka-ai/m3e-base · HF Mirror
下载后放到: ./downModels/moka-ai/m3e-base 目录下
3、以下是所以有代码:
#coding=utf-8
'''
pip install -U sentence-transformers -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install faiss-cpu -i https://pypi.tuna.tsinghua.edu.cn/simple/ 或 pip install faiss-gpu -i https://pypi.tuna.tsinghua.edu.cn/simple/https://hf-mirror.com/moka-ai/m3e-base
https://github.com/wangyingdong/m3e-base
https://github.com/wangyuxinwhy/uniem
'''
from sentence_transformers import SentenceTransformer
import faiss
import torch
import numpy as np
import json
#from FlagEmbedding import BGEM3FlagModel############################## 一、获取文本向量并保存到.npz中 ############################### 获取向量
def getEmbedding(sentences):# # 方式一、bge-m3# model = BGEM3FlagModel('./downModels/BAAI/bge-m3', use_fp16=True) #加载向量模型 # embeddings = model.encode(sentences)['dense_vecs'] #模型获取到向量,返回的是一个列表,因为传入是多个句子的,所以返回的也是多个句子的向量 (2, 1024)# return np.array(embeddings) #faiss要求向量必须为 numpy 数组,所以这里统一转换# 方式二、m3e-basemodel = SentenceTransformer('./downModels/moka-ai/m3e-base') #加载向量模型 embeddings = model.encode(sentences) #模型获取到向量,返回的是一个列表,因为传入是多个句子的,所以返回的也是多个句子的向量 (2, 768)return np.array(embeddings) #faiss要求向量必须为 numpy 数组,所以这里统一转换## 方式三、自训练m3e-base#model = SentenceTransformer('./downModels/moka-ai/diy2') #加载向量模型 #embeddings = model.encode(sentences) #模型获取到向量,返回的是一个列表,因为传入是多个句子的,所以返回的也是多个句子的向量 (2, 768)#return np.array(embeddings) #faiss要求向量必须为 numpy 数组,所以这里统一转换# 读取本地文本配置库
with open("./data/dz.json","r",encoding="utf-8") as file:dzData = json.load(file) # print(dzData[0]) #0 你的名字 尊小医# 是否初始化 - 初始化重新生成 .npz 所有向量: 0=用之前生成的,1=从新生成 isLoad
isLoad=1
if isLoad==1: dzSentences=[]#句子for line in dzData:dzSentences.append(line['text'])# print(line['id'],line['text'],line['answer']) #0 你的名字 尊小医# 生成本地向量文件.npz allEmbeddings = getEmbedding(dzSentences) # 获取所有向量 #(107, 768)np.savez('./data/dz.npz', allEmbeddings) #生成向量文件############################## 二、用.npz 向faiss表添加向量数据 ############################### 读取本地 .npz 向量数据库 - npz格式就这样,会有arr_0 : https://www.jb51.net/article/254220.htm
allEmbeddings = np.load("./data/dz.npz")['arr_0'] # 创建索引 faiss 数据表,并设置表的维度
faiss_index = faiss.IndexFlatIP(allEmbeddings.shape[1]) # m3e-base模型的向量的维度:768 , 现在改为自动获取维度# print(allEmbeddings[0].tolist()) # 测试
faiss.normalize_L2(allEmbeddings) # 添加之前归一化 - 对向量进行L2归一化
faiss_index.add(allEmbeddings) # 向索引768维度添加元素,使用 .add 方法# # # 保存索引 - 可以把上面的 一、二、步保存起来,到时直接加载。 如果使用的GPU索引,会稍微麻烦一点:https://zhuanlan.zhihu.com/p/107241260
# # faiss.write_index(faiss_index, "text_embedding_mysql_faiss.index")
# faiss_index = faiss.read_index("text_embedding_mysql_faiss.index") # 加载索引############################## 三、向量搜索 ############################### 三、搜索(根据搜索标题生成搜索向量,对faiss之前添加的向量进行搜索)
query = "你好"
query_embedding = getEmbedding([query]) # 生成搜索向量
faiss.normalize_L2(query_embedding) # 对向量进行L2归一化
distances, doc_indices = faiss_index.search(query_embedding, 3) #使用 .search 方法 进行搜索 faiss 向量表# 四、搜索结果查看
print(f"query: {query}")
print("recall result: ")
for i, sent_index in enumerate(doc_indices.tolist()[0]):print(f"rank: {i}, similarity: {distances.tolist()[0][i]}, text: {dzData[sent_index]}")
# reset index
faiss_index.reset()# 输出最近邻的索引和相似度
print("最近的邻居:", distances) #最近的邻居: [[0.9999999 0.8509952 0.81363904]]
print("距离:", doc_indices) #距离: [[1 0 2]]'''
query: 你好
recall result:
rank: 0, similarity: 0.7203549742698669, text: {'id': '0', 'text': '你的名字', 'answer': '我叫333xxx'}
rank: 1, similarity: 0.7203549146652222, text: {'id': '50', 'text': '你的名字', 'answer': '我叫xxx1111111'}
rank: 2, similarity: 0.6859931945800781, text: {'id': '70', 'text': '你叫什么名字', 'answer': '我叫xxx'}
最近的邻居: [[0.720355 0.7203549 0.6859932]]
距离: [[ 0 50 70]]
'''#备注: 上面的 similarity 阀值为0.9以上的就可以 代替llm大模型 输出了, 这样就可以准确的使用了~~