AI创想

标题: 【向量数据库】向量数据库的构建和检索 [打印本页]

作者: 米落枫    时间: 2 小时前
标题: 【向量数据库】向量数据库的构建和检索
作者:风好衣轻
1、使用 sentence-transformers 将文本编码为向量

安装 sentence-transformers:
  1. pip install-U sentence-transformers
复制代码
在 huggingface 下载 all-MiniLM-L6-v2 模型权重(1_Pooling 是文件夹,里面包含一个 config.json 文件):
  1. ~$ ls
  2. 1_Pooling    config_sentence_transformers.json  model.safetensors  sentence_bert_config.json  tokenizer_config.json  train_script.py
  3. config.json  data_config.json                   modules.json       special_tokens_map.json    tokenizer.json         vocab.txt
复制代码
运行下面的示例脚本,将一句话编码为一个向量:
  1. from sentence_transformers import SentenceTransformer
  2. model_path ="/hub/weights/all-MiniLM-L6-v2"
  3. model = SentenceTransformer(model_path)
  4. sentence =['This framework generates embeddings for each input sentence']
  5. embedding = model.encode(sentence)print(len(embedding),len(embedding[0]))# 1 384
复制代码
2、使用SQuAD-explorer数据集构建向量数据库

(, 下载次数: 0)


下载 SQuAD-explorer 数据集,这个数据集分为 Training SetDev SetDev Set 更小更方便格式化预览数据集的结构,也更方便调试。
也可以使用其他的数据集,像第一节演示的那样,只需要是模型支持的语言的句子就可以编码成向量。
.json文件加载后的第一层是一个Python dict,包含两个key:"version"和"data","data"对应的值是一个list,可以看一下这个list的长度:
  1. import json
  2. withopen("dev-v2.0.json","r")as f:
  3.     data = json.load(f)
  4. data = data["data"]print(len(data))# 35
复制代码
dev数据集中有35条,train数据集中有442条,对于每一条数据,也是包含两个key:"title"和"paragraphs","paragraphs"对应的值是一个list,"paragraphs"里的每一个元素是dict,我们只需要关注里面的"qas",即QA pairs,下面使用这些QA pairs来构建向量数据库。
下面先对数据进行读取,获取到数据集中包含的全部QA,由于有些问题含有多个答案,有些问题没有答案,这里统一排除掉没有答案的问题,对于包含多个答案的问题仅获取第一条答案,形成一对一的QA映射关系:
  1. import json
  2. withopen("dev-v2.0.json","r")as f:
  3.     dataset = json.load(f)
  4. qas =[(qas["question"], qas["answers"][0]["text"])for data in dataset["data"]for paragraphs in data["paragraphs"]for qas in paragraphs["qas"]if qas["answers"]]print(len(qas))print(qas[0])
复制代码
可以看到第一组问答已经被提取出来了:
  1. 5928('In what country is Normandy located?', 'France')
复制代码
接下来我们查询一个问题的答案,如果问题刚好和数据中存在的问题完全一致,就可以匹配到答案,例如:
  1. qas_dict =dict(qas)
  2. q ='In what country is Normandy located?'
  3. a = qas_dict.get(q)print(a)
复制代码
把 qas_dict 看作一个简易的 key-value 数据库,用精准的问题去查询可以得到问题的答案
  1. France
复制代码
但如果问题和数据库中的 key 有点偏差(字符串不相等),就无法检索到这个问题的答案,这也是普通的数据库和向量数据库的最主要的差别之一,为了保证相似的问题也可以检索到正确的答案,我们可以使用向量数据库。
  1. # 这里使用 CPU 版本的 faiss
  2. pip install faiss-cpu
复制代码
下面是完整的示例代码
  1. import json
  2. import faiss
  3. import numpy as np
  4. from sentence_transformers import SentenceTransformer
  5. model_path ="/path/to/all-MiniLM-L6-v2"
  6. model = SentenceTransformer(model_path)defload_qa_data(data_path):withopen(data_path,"r")as f:
  7.         dataset = json.load(f)
  8.     qas =[(qas["question"], qas["answers"][0]["text"])for data in dataset["data"]for paragraphs in data["paragraphs"]for qas in paragraphs["qas"]if qas["answers"]]return np.array(qas)defstr_to_vec(sentence_list):
  9.     embedding = model.encode(sentence_list)return embedding
  10. defbuild_faiss_index(vectors, nlist=100, pq_m=8):
  11.     d = vectors.shape[1]
  12.     quantizer = faiss.IndexFlatL2(d)
  13.     index = faiss.IndexIVFPQ(quantizer, d, nlist,8, pq_m)
  14.     index.train(vectors)
  15.     index.add(vectors)return index
  16. k =10
  17. qas = load_qa_data("dev-v2.0.json")
  18. q, a =[qa[0]for qa in qas],[qa[1]for qa in qas]
  19. q_vec = str_to_vec(q)print(q_vec.shape)
  20. index = build_faiss_index(q_vec)
  21. query_vector = str_to_vec(["What country does Normandy belong to?"])
  22. distances, indices = index.search(query_vector, k)for i inrange(k):print(f"==> distance: {distances[0][i]:.4f}, indice: {indices[0][i]}, {q[i]}")
复制代码
运行的结果:
  1. ==> distance: 0.5488, indice: 0, In what country is Normandy located?
  2. ==> distance: 0.6171, indice: 10, When were the Normans in Normandy?
  3. ==> distance: 0.6253, indice: 6, From which countries did the Norse originate?
  4. ==> distance: 0.6960, indice: 5255, Who was the Norse leader?
  5. ==> distance: 0.7582, indice: 12, What century did the Normans first gain their separate identity?
  6. ==> distance: 0.7674, indice: 4725, Who was the duke in the battle of Hastings?
  7. ==> distance: 0.7722, indice: 22, Who ruled the duchy of Normandy
  8. ==> distance: 0.7759, indice: 4488, What religion were the Normans
  9. ==> distance: 0.7777, indice: 5259, What is the original meaning of the word Norman?
  10. ==> distance: 0.8038, indice: 4706, When was the Latin version of the word Norman first recorded?
复制代码
可以发现即使是把问题换成了:
“What country does Normandy belong to?”
也仍然能够匹配到在384维的空间内与它最接近的一个句子(L2距离为0.5488):
“In what country is Normandy located?”
我们就可以通过它的索引 0 找到对应的答案了。

原文地址:https://blog.csdn.net/qq_41956187/article/details/141108866




欢迎光临 AI创想 (http://llms-ai.com/) Powered by Discuz! X3.4