向量数据库(Mivus)学习指南及简朴操纵

饭宝  论坛元老 | 2024-6-19 11:09:35 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1041|帖子 1041|积分 3123

github代码
https://github.com/Xiaomkuaipao/Milvus


b站讲解
https://space.bilibili.com/430576513
前记:


  • Milvus和Weaviate-client 这俩库有辩论,单开两个环境;
  • 本次测试中,Milvus和Weaviate在查询精度上完全相同;
  • 小数据集搜索中,参数设置相同时,Milvus的查询时间是Weaviate的三倍左右,即Weaviate更快;
  • Milvus在介绍中表明,在处置惩罚大规模数据集的向量搜索具有高性能,本次测试时间大概和数据集小有关;
Milvus

一、参考链接

Milvus中文文档
Milvus官方文档
集群使用(知乎)
非常详细的介绍CSDN
二、概念

2.1 优缺点(个人观点)

1. 优点



  • 操纵相对简朴
  • 强可视化
2. 缺点



  • 查询速度慢:数据量少的情况下,用时是Weaviate的3倍多(156条问答对,312次查询)
2.2 设计原理

作为云原生向量数据库,Milvus的设计通过分离存储与计算来实现。为了增强弹性和灵活性,Milvus中的所有组件都是无状态的。
系统分为四个条理:


  • 访问层:访问层由一组无状态代理构成,作为系统的前层和用户端点。
  • 调和器服务:调和器服务将任务分配给工作节点,并充当系统的大脑。
  • 工作节点:工作节点是系统的手臂和腿部,是执行来自调和器服务的指令并执行用户触发的DML/DDL下令的“哑执行者”。
  • 存储:存储是系统的骨头,负责数据长期化。它包罗元数据存储、日志代理和对象存储。
2.3 名词概念



  • 聚集(Collection):可以包含一个或多个Segment
  • 段(Segment):一个Segment相当于是一个表
  • 实体(Entity):相当于是一个字段(行),Milvus不支持主键去重,大概会存在重复的主键
  • 字段(Field): 构成实体的单位
  • 集群(cluster):实现高可用性和易扩展性
  • Schema:定义数据类型和数据属性的元信息。定义聚集的字段、启用自动 ID(主键)分配,并包罗聚集描述。聚集 schema 中还包罗定义字段名称、数据类型和其他属性的字段模式。(定义方式比Weaviate简朴好多)
  • 向量相似度搜索:通常采用近似最近邻算法(ANN)搜索,Weaviate中也是
2.4 索引类型[测试时用的IVF_FLAT,试一下别的方式]

大多数由Milvus支持的向量索引类型使用近似最近邻搜索(ANNS),包罗:


  • FLAT:FLAT最得当于在小规模,百万级数据集上寻求完全准确和准确的搜索结果的场景。
  • IVF_FLAT:IVF_FLAT是一种量化索引,最得当于在精度和查询速度之间寻求理想平衡的场景。
  • IVF_SQ8:IVF_SQ8是一种量化索引,最得当于在磁盘、CPU和GPU内存斲丧非常有限的场景中显著淘汰资源斲丧。
  • IVF_PQ:IVF_PQ是一种量化索引,最得当于在高查询速度的情况下以牺牲精度为代价的场景。
  • HNSW:HNSW是一种基于图形的索引,最得当于对搜索效率有很高需求的场景。
  • ANNOY:ANNOY是一种基于树形结构的索引,最得当于寻求高召回率的场景。
2.5 相似度度量

在 Milvus 中,相似度度量用于权衡向量之间的相似性。选择一个好的隔断度量方法可以显著进步分类和聚类的性能。根据输入数据的形式,选择特定的相似度度量方法可以获得最优的性能。
对于浮点嵌入,通常使用以下指标:


  • 欧氏隔断(L2):该指标通常用于计算机视觉领域(CV)。
  • 内积(IP):该指标通常用于自然语言处置惩罚领域(NLP)。
在二元嵌入中广泛使用的度量标准包罗:


  • 哈明隔断:这个度量标准通常用于自然语言处置惩罚(NLP)领域。
  • 杰卡德隔断:这个度量标准通常用于分子相似性搜索领域。
  • 塔尼莫托隔断:这个度量标准通常用于分子相似性搜索领域。
  • 超结构隔断:这个度量标准通常用于搜索分子的雷同超结构。
  • 亚结构隔断:这个度量标准通常用于搜索分子的雷同亚结构。
三、安装和使用

3.1 安装



  • milvus
  • 我安装时间参考的链接,一次成功
  • 单机版的docker安装方法(官方链接)
  1. wget https://github.com/milvus-io/milvus/releases/download/v2.3.4/milvus-standalone-docker-compose.yml -O docker-compose.yml
复制代码


  • 图形化界面安装
  • 软件位置,下载attu-Setup-***.exe直接点击下一步举行安装即可
3.2 使用

此中,第1、2、3步是固定顺序,做完才气举行其他操纵。
1. 先毗连上数据库
  1. # 先连接上数据库,连接到本地ip 127.0.0.1
  2. from pymilvus import (connections, utility, FieldSchema, CollectionSchema, DataType, Collection)
  3. connections.connect("default", host="localhost", port="19530", db_name='KnowledgeBase')
复制代码
2. 创建表
  1. from pymilvus import (
  2.     connections,
  3.     utility,
  4.     FieldSchema, CollectionSchema, DataType,
  5.     Collection, loading_progress,
  6. )
  7. # 本地连接ip 127.0.0.1
  8. connections.connect("default", host="localhost", port="19530", db_name='KnowledgeBase')
  9. fields = [
  10.     FieldSchema(name="uid", dtype=DataType.INT64, is_primary=True, auto_id=False, max_length=100),
  11.     FieldSchema(name="Question", dtype=DataType.VARCHAR,max_length=5000),
  12.     FieldSchema(name="embeddings_Q", dtype=DataType.FLOAT_VECTOR, dim=768),
  13.     FieldSchema(name="Answer", dtype=DataType.VARCHAR,max_length=5000)
  14. ]
  15. # 表的field块以及对表的描述
  16. schema = CollectionSchema(fields, "存储向量数据")
  17. # 表名,Strong是只要更新用户就能看到
  18. docs_data = Collection("Milvus_Test", schema, consistency_level="Strong")  
复制代码
3. 创建Index
  1. """
  2. 为attribute_name创建索引
  3. :param Collection_Name:连接的表名,即段(Segment)名
  4. :param attribute_name: 加入索引的属性名,即字段(Field)名, 列名。
  5. :param index: 索引的属性
  6. """
  7. def Index_create(Collection_Name: str, attribute_name: str, index: dict):
  8.     try:
  9.         collection = Collection(Collection_Name)
  10.         collection.create_index(field_name=attribute_name, index_params=index)
  11.     except Exception as e:
  12.         print(e)
  13.     else:
  14.         print("Index插入成功")   
  15.    
  16. index = {
  17.     "index_type": "IVF_FLAT",  # 适合于在精度和查询速度之间寻求理想平衡的场景,试一试别的索引方式,再查一下
  18.     "metric_type": "L2",  # 距离,这个更适合图像,后面再试试其它的
  19.     "params": {"nlist": 128},  # 倒排文件中创建128个倒排列表(inverted lists),大nlist值有助于提高搜索速度,但会增加索引的内存消耗
  20. }
  21. Index_create("Milvus_Test", "embeddings_Q", index)
复制代码
4. 插入数据
  1. # vector.py
  2. def Insert_vector(id_list: list, Q_list: list, A_list: list, embeddings_Q, Collection):
  3.     """
  4.     id_list:key list
  5.     Q_list:Question list
  6.     A_list:Answer list
  7.     embeddings_Q: Question embedding list
  8.     Collection: 建立好的连接
  9.     """
  10.     try:
  11.         collection = Collection
  12.         for id_key, sentence_Q, embedding_Q, sentence_A in zip(id_list, Q_list, embeddings_Q, A_list):
  13.             # sentence:原文
  14.             # embedding:转换后的向量
  15.             entities = [[id_key], [sentence_Q], [embedding_Q], [sentence_A]]
  16.             collection.insert(entities)
  17.             print(f"编号{id_key}插入完毕")
  18.         collection.flush()
  19.     except Exception as e:
  20.         print(e)
  21.    
  22.    
  23. # InsertVector.py   
  24. import time
  25. import pandas as pd
  26. from pymilvus import (connections, utility, FieldSchema, CollectionSchema, DataType, Collection)
  27. from langchain_community.embeddings import HuggingFaceEmbeddings
  28. csv_file_path = r'D:\TTShixi\Code\MilvusTest\pythonProject\MilvusTest\QA_Pair.csv'
  29. model = HuggingFaceEmbeddings(model_name="moka-ai/m3e-base", model_kwargs={"device": "cpu"})
  30. Collection_Name = 'Milvus_Test'
  31. collection = Collection(Collection_Name)
  32. # 读取数据
  33. df = pd.read_csv(csv_file_path, index_col=0)
  34. # 分配数据 list
  35. sentenceQ_data = df.Q.values
  36. sentenceA_data = df.A.values
  37. id_list = df.index
  38. # 计算需要的embedding列的list
  39. sentenceQ_embeddings = model.embed_documents(sentenceQ_data)
  40. start_time = time.time()
  41. Insert_vector(id_list, sentenceQ_data, sentenceA_data, sentenceQ_embeddings, Collection=collection)
  42. end_time = time.time()
  43. print(f"插入数据用时为: {end_time - start_time}秒, 平均一条的插入时间为: {(end_time - start_time)/len(id_list)}")
复制代码
5. 搜索
  1. # vector.py
  2. def Similarity_search(collection, Query_embeding, anns_field, k, search_params) -> list:
  3.     """
  4.     全库检索
  5.     :param Query: 问题
  6.     :param Collection_Name: 表名
  7.     :param k: 保留结果数
  8.     :param anns_field: 要搜索的field
  9.     :return:
  10.     """
  11.     try:
  12.         result = collection.search([Query_embeding], anns_field=anns_field, param=search_params, limit=k, output_fields=["uid", "Question", "Answer"])
  13.         # 可以拿result[0].distance来限制距离,给一个临界值,超过之后才能匹配上
  14.         return result[0][0].fields['uid']
  15.     except Exception as e:
  16.         result = '程序异常中断,Error'
  17.         print(result)
  18.         
  19.         
  20.         
  21. # Similarity_Search.py
  22. import time
  23. # from vector import Similarity_search
  24. from langchain.embeddings import HuggingFaceEmbeddings
  25. import pandas as pd
  26. from pymilvus import (connections, utility, FieldSchema, CollectionSchema, DataType, Collection)
  27. csv_file_path = r'D:\TTShixi\Code\MilvusTest\pythonProject\vectorstores\Weaviate_Test\QA_上海证券交易所.csv'
  28. anns_field = "embeddings_Q"
  29. model = HuggingFaceEmbeddings(model_name="moka-ai/m3e-base", model_kwargs={"device": "cpu"})
  30. Collection_Name = 'Milvus_Test'
  31. collection = Collection(Collection_Name)
  32. # collection.load()
  33. df = pd.read_csv(csv_file_path, index_col=0)
  34. sentence_data_QS1 = df.QS1.values
  35. sentence_data_QS2 = df.QS2.values
  36. num_all = len(sentence_data_QS1)
  37. num_cor = 0
  38. search_params = {
  39.     "metric_type": "L2",  # 设置距离度量方式为L2
  40.     "params": {"nprobe": 10},  # 从倒排列表中查找 10 个最相近的候选项进行精确的距离计算
  41. }
  42. start = time.time()
  43. # i应该改为df的行号
  44. for i in range(num_all):
  45.     query = model.embed_documents([sentence_data_QS1[i]])[0]
  46.     if (i+1) == Similarity_search(collection, query, anns_field=anns_field, k=1, search_params=search_params):
  47.         num_cor += 1
  48.     query = model.embed_documents([sentence_data_QS2[i]])[0]
  49.     if (i+1) == Similarity_search(collection, query, anns_field=anns_field, k=1, search_params=search_params):
  50.         num_cor += 1
  51.     print(f"测到第{i+1}个了")
  52. end = time.time()
  53. print(f"查询时间为:{end-start}秒,平均每条的查询时间为{(end-start)/num_all/2}秒")
  54. print(f"正确率为{num_cor/num_all/2*100}%")
复制代码
6. 删除实体
  1. # vector.py
  2. def Delete_Entity(Collection, id: int) -> bool:
  3.     """
  4.     删除表里的某一行
  5.     :param Collection: 连接过的直接传过来
  6.     :param id: key值
  7.     :return: 布尔值
  8.     也可以通过匹配问题,然后找到这个问题的uid之后再删,后续可以改
  9.     """
  10.     try:
  11.         collection = Collection
  12.         expr = f"uid in [{id}]"
  13.         collection.delete(expr)  # 可以指定分区
  14.         return True
  15.     except Exception as e:
  16.         print(e)
  17.         return False
  18.         
  19. # Entity_delete.py
  20. # from vector import Delete_Entity
  21. from pymilvus import (connections, utility, FieldSchema, CollectionSchema, DataType, Collection)
  22. collection = Collection('Milvus_Test')
  23. for i in range(156):
  24.     de = Delete_Entity(Collection=collection, id=i)
  25.     if de:
  26.         print(f"第{i}条数据删除成功")
  27.     else:
  28.         print(f"第{i}条数据删除失败")
  29. collection.flush()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

饭宝

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表