【腾讯云云上实验室-向量数据库】Tencent Cloud VectorDB在实战项目中替换Milvus测试

为什么尝试使用Tencent Cloud VectorDB替换Milvus向量库?

亮点:Tencent Cloud VectorDB支持Embedding,免去自己搭建模型的负担(搭建一个生产环境的模型实在耗费精力和体力)。

腾讯云向量数据库是什么?

腾讯云向量数据库是一款全托管的自研企业级分布式数据库服务,专用于存储、检索、分析多维向量数据。该数据库支持多种索引类型和相似度计算方法,单索引支持10亿级向量规模,可支持百万级 QPS 及毫秒级查询延迟。腾讯云向量数据库不仅能为大模型提供外部知识库,提高大模型回答的准确性,还可广泛应用于推荐系统、NLP 服务、计算机视觉、智能客服等 AI 领域。

Milvus是什么?

Milvus是在2019年创建的,其唯一目标是存储、索引和管理由深度神经网络和其他机器学习(ML)模型生成的大规模嵌入向量。作为一个专门设计用于处理输入向量查询的数据库,它能够处理万亿级别的向量索引。与现有的关系型数据库主要处理遵循预定义模式的结构化数据不同,Milvus从底层设计用于处理从非结构化数据转换而来的嵌入向量。

项目展示

游戏内提问
问答缓存库后台管理系统

项目介绍游戏内部接入ChatGPT的智能NPC,可以与她进行语音交流。可以回答与游戏相关的问题(这个专业问题是为了编写这个文章,专门添加到问答缓存库中的,游戏内会拒绝回答此类问题)。为了加快ChatGPT的回复速度和降低ChatGPT的费用,增加问答缓存机制。这里运用向量数据库的相似文本相似度高的特性,通过向量搜索,匹配相似度大于一定值,例如:0.95。搜索到相似问题,直接返回答案,不在进行ChatGPT访问。

其次,存在缓存,针对相似问题,还可以给予特定回复答案。例如上面示例,当提问“介绍一下腾讯向量数据库”,直接回复“腾讯云向量数据库是一款全托管的自研企业级分布式数据库服务,专用于存储、检索、分析多维向量数据。该数据库支持多种索引类型和相似度计算方法,单索引支持10亿级向量规模,可支持百万级 QPS 及毫秒级查询延迟。腾讯云向量数据库不仅能为大模型提供外部知识库,提高大模型回答的准确性,还可广泛应用于推荐系统、NLP 服务、计算机视觉、智能客服等 AI 领域。”

为什么使用向量数据库?

重点:速度
向量相似度匹配是很长的数组,例如:bge-large-zh模型文本转向量,生成的是768维的float数组。拿问题文本转换为的768维向量与缓存的所有问题的向量进行相似性计算,然后获取最相似的几条数据,这个运算量非常大,速度非常慢。
测试代码:
与300个768维向量进行相似比对,获取最相似的一条数据,耗时几秒钟。按照这个速度,如果与几千上万条数据进行这么计算,简直无法忍受。
这时就必须使用向量数据库了,向量数据库可以支持毫秒级检索上百万行数据。本人曾使用Milvus数据库,分别插入1000行数数据和插入10万行数据,然后进行搜索对比,都在几十毫秒返回结果,数据量的增多,对检索速度几乎没有任何影响。

本项目哪里需要使用向量数据库?

  • 玩家提问:玩家提问先通过embedding转换为向量,在向量库检索相似的问题,满足匹配条件,直接返回对应的答案。
  • 后台相似问题检索:后台通过向量检索相似问题,以便对特定问题进行增删改查。

使用腾讯云向量数库(Tencent Cloud VectorDB)的优点?

  1. 支持Embedding:腾讯云向量数据库(Tencent Cloud VectorDB)提供将非结构化数据转换为向量数据的能力,目前已支持文本 Embedding 模型,能够覆盖多种主流语言的向量转换,包括但不限于中文、英文。对于小型项目这是一个非常大的优势。可以降低自己搭建embedding模型或者使用第三方embedding模型的成本。
  2. FilterIndex的field_type支持数据类型简单:只有String和Uint64,使用起来非常省心。而Milvus数据支持10几种类型,对于初学者不友好,还要研究具体如何使用。

指定 Filter 字段的数据类型。取值如下:
String:字符型。若 name 为 id,则该参数固定为 FieldType.String。
Uint64:指无符号整数,该参数可设置为 FieldType.Uint64。

研究Tencent Cloud VectorDB,测试并封装代码库my_tc_vector_db.py

if __name__ == '__main__':# 初始化myTcVectorDB = MyTcVectorDB("http://****************.tencentclb.com:30000", "root","2epSOV3HK6tiyALo6UqE3mGV**************")# 删除数据库myTcVectorDB.drop_collection("db-qa", "question_768")myTcVectorDB.drop_database("db-qa")# 创建数据库myTcVectorDB.create_database("db-qa")# 创建索引和embedding,并创建集合index = Index(FilterIndex(name='id', field_type=FieldType.String, index_type=IndexType.PRIMARY_KEY),FilterIndex(name='question', field_type=FieldType.String, index_type=IndexType.FILTER),VectorIndex(name='vector', dimension=768, index_type=IndexType.HNSW,metric_type=MetricType.COSINE, params=HNSWParams(m=16, efconstruction=200)))embedding = Embedding(vector_field='vector', field='text', model=EmbeddingModel.BGE_BASE_ZH)collection = myTcVectorDB.create_collection("db-qa", "question_768", index, embedding)# 批量插入myTcVectorDB.upsert("db-qa", "question_768", [Document(id='0001', text='罗贯中', question='罗贯中'),Document(id='0002', text='吴承恩', question='吴承恩'),Document(id='0003', text='曹雪芹', question='曹雪芹'),Document(id='0004', text='郭富城', question='郭富城')])# 单条插入myTcVectorDB.upsert_one("db-qa", "question_768", id='0005', text='周杰伦', question='周杰伦')myTcVectorDB.upsert_one("db-qa", "question_768", id='0006', text='林俊杰', question='林俊杰')# 删除0003myTcVectorDB.delete_by_id("db-qa", "question_768", "0003")# 文本搜索(无需向量转换)text = myTcVectorDB.search_by_text("db-qa", "question_768", "郭富城")# 打印结果print_object(text)# 仅打印idif len(text[0]) > 0:for i in text[0]:print(i['id'])

解释代码功能:

  1. 初始化:传入tcVectorDB的url、username和key,创建myTcVectorDB.

  2. 删除数据库db-qa下的数据集question_768,然后删除数据库db-qa

  3. 重新创建数据库db-qa

  4. 指定索引和embedding,并创建集合question_768:这里指定id为主键、question为FilterIndex标量索引,vector为VectorIndex向量索引(注意官方文档说明:指定向量索引字段名,固定为 vector。)因为使用中文检索,Embedding使用BGE_BASE_ZH。官方文档的VectorIndex介绍

  5. 批量插入测试数据

  6. 单行插入测试数据

  7. 测试删除单行数据

  8. 测试文本搜索,并打印结果

MyTcVectorDB库代码

import jsonimport tcvectordb
from tcvectordb.model.collection import Embedding
from tcvectordb.model.document import Document, SearchParams
from tcvectordb.model.enum import ReadConsistency, MetricType, FieldType, IndexType, EmbeddingModel
from tcvectordb.model.index import Index, FilterIndex, VectorIndex, HNSWParamsclass MyTcVectorDB:def __init__(self, url: str, username: str, key: str, timeout: int = 30):self._client = tcvectordb.VectorDBClient(url=url, username=username, key=key,read_consistency=ReadConsistency.EVENTUAL_CONSISTENCY, timeout=timeout)def create_database(self, database_name: str):"""Create a database:param database_name: database name:return: database"""return self._client.create_database(database_name=database_name)def drop_database(self, database_name: str):"""Drop a database:param database_name: database name:return: result"""return self._client.drop_database(database_name=database_name)def create_collection(self, db_name: str, collection_name: str, index: Index, ebd: Embedding):db = self._client.database(db_name)# 第二步,创建 Collectioncoll = db.create_collection(name=collection_name,shard=1,replicas=0,description='this is a collection of question embedding',index=index,embedding=ebd)return colldef drop_collection(self, db_name: str, collection_name: str):"""Drop a collection:param db_name: db name:param collection_name: collection name:return: result"""db = self._client.database(db_name)return db.drop_collection(collection_name)def upsert_one(self, db_name: str, collection_name: str, **kwargs):"""Upsert one document to collection:param db_name : db name:param collection_name: collection name:param document: Document:return: result"""db = self._client.database(db_name)coll = db.collection(collection_name)res = coll.upsert(documents=[Document(**kwargs)])return resdef upsert(self, db_name: str, collection_name: str, documents):"""Upsert documents to collection:param db_name : db name:param collection_name: collection name:param documents: list of Document:return: result"""db = self._client.database(db_name)coll = db.collection(collection_name)res = coll.upsert(documents=documents)return resdef search_by_text(self, db_name: str, collection_name: str, text: str, limit: int = 10):"""Search documents by text:param db_name : db name:param collection_name: collection name:param text: text:return: result"""db = self._client.database(db_name)coll = db.collection(collection_name)# searchByText 返回类型为 Dict,接口查询过程中 embedding 可能会出现截断,如发生截断将会返回响应 warn 信息,如需确认是否截断可以# 使用 "warning" 作为 key 从 Dict 结果中获取警告信息,查询结果可以通过 "documents" 作为 key 从 Dict 结果中获取res = coll.searchByText(embeddingItems=[text],params=SearchParams(ef=200),limit=limit)return res.get('documents')def delete_by_id(self, db_name: str, collection_name: str, document_id):"""Delete document by id:param db_name : db name:param collection_name: collection name:param document_id: document id:return: result"""db = self._client.database(db_name)coll = db.collection(collection_name)res = coll.delete(document_ids=[document_id])return resdef print_object(obj):"""Print object"""for elem in obj:# ensure_ascii=False 保证中文不乱码if hasattr(elem, '__dict__'):print(json.dumps(vars(elem), indent=4, ensure_ascii=False))else:print(json.dumps(elem, indent=4, ensure_ascii=False))

开始动手使用Tencent Cloud VectorDB在项目中替换Milvus

1、创建问题库db-qa和集合question_768

与测试代码基本一致

    # 初始化myTcVectorDB = MyTcVectorDB("http://****tencentclb.com:30000", "root","2epSOV3HK6tiyALo6UqE3mGVMbpP*******")# 创建数据库myTcVectorDB.create_database("db-qa")# 创建索引和embedding,并创建集合index = Index(FilterIndex(name='id', field_type=FieldType.String, index_type=IndexType.PRIMARY_KEY),FilterIndex(name='question', field_type=FieldType.String, index_type=IndexType.FILTER),VectorIndex(name='vector', dimension=768, index_type=IndexType.HNSW,metric_type=MetricType.COSINE, params=HNSWParams(m=16, efconstruction=200)))embedding = Embedding(vector_field='vector', field='text', model=EmbeddingModel.BGE_BASE_ZH)collection = myTcVectorDB.create_collection("db-qa", "question_768", index, embedding)

2、游戏端和后台文本向量搜索,用MyTcVectorDB替换Milvus

两处代码基本一致。这里去掉文本转向量的步骤,因为TcVectorDB支持Embedding

    # 获取问题转换后的向量# success, vector = get_vector_from_text(question)# if not success:#     return {"code": -1, "id": 0, "answer": "向量计算失败"}# results = questionCollection.search(vector, limit)results = myVectorDB.search_by_text("db-qa", "question_768", question, limit)...

上面代码需要注意一点,腾讯向量数据的search结果与milvus的搜索结果是不一样的,需要做一下适配。

3、重建向量数据库

问答缓存的数据保存在mysql数据库,向量数据库主要作用是向量搜索。如果更换向量库,只需要重建向量库即可。下面代码:

  1. 从mysql中获取所有的问题
  2. 遍历所有问答
  3. 把问题作为向量索引,问答的id为标量索引插入向量库中
    当前mysql数据库中有大几千条数据,重新构建向量就耗时10分钟左右。
def rebuild_vector():# 查找所有的数据select_all = qaTable.select_all_qa()# 遍历所有的数据for qa in select_all:insertId = qa[0]question = qa[1]timestamp = int(time.time())print(question)# 计算向量# 更新向量# success, vector = get_vector_from_text(question)# if not success:#     # 向量计算失败,question#     logging.error("向量计算失败,insertId:%s, question:%s", insertId, question)#     continue# # 删除原有的向量# questionCollection.delete_question(insertId)# # 插入新的向量# questionCollection.insert_question(insertId, vector, question, timestamp)myVectorDB.delete_by_id("db-qa", "question_768", str(insertId))myVectorDB.upsert_one("db-qa", "question_768", id=str(insertId), text=question, question=question)return "重建向量库成功"

4、修改后台展示,看下修改后的效果图更换腾讯云向量库

  • 使用的文本转向量的模型是:BGE_BASE_ZH
  • 向量索引是:VectorIndex(name=‘vector’, dimension=768, index_type=IndexType.HNSW, metric_type=MetricType.COSINE, params=HNSWParams(m=16, efconstruction=200))
  • 搜索文本返回结果代表的是相似度,保存在score中。

总结:

  1. 使用腾讯向量数据库要比使用Milvus更加简单易用,无需自己部署服务器。
  2. 腾讯云向量库支持主流Embedding,直接支持文本向量搜索,避免自己部署Embedding模型,并避免调用文本转向量的过程。对于开发者来说非常便利。
    如果是个人,或者小型项目开发,非常值得使用腾讯云数据库。如果是大型项目,不缺钱的话也非常推荐使用腾讯云数据库,稳定、高效且安全。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/164470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rsync配置和守护进程实践

目录 一、rsync概念 1.rsync简介 2.rsync特点 3、增量和全局传输 二、Rsync工作方式 1.准备好rsync备份服务器 2.本地的数据传输模式 3.远程的数据传输模式 4.rsync数据推拉模式 三、实践 1.准备三台虚拟机 2.都安装rsync服务 3.拉取远程文件 3.推送文件 4.rsyn…

Oracle用户(User)和表空间(Tablespace)

3. 用户和表空间 3.1. 用户 1)概念 Oracle数据库中,用户(User)是访问数据库的途径和认证方式,同时,用户也是数据库对象的逻辑集合。我们通过数据库用户和密码来登录数据库,然后,可以在该用户下创建和操作数据库对象。 2)创建和配置 创建Oracle用户,需要具备创建…

python系统编程

文章目录 系统编程系统工具概述sys模块os模块 脚本运行上下文当前工作路径命令行参数shell环境变量标准流 文件和目录工具文件工具目录工具 并行系统工具进程分支线程 系统编程 系统工具 概述 python系统模块: 模块名作用*sys负责导出与怕以后呢解释器本身相关的组件*os包含…

Django DRF序列化器serializer

以下案例由浅到深&#xff0c;逐步深入&#xff0c;通过实例介绍了序列化器的使用方法&#xff0c;和其中遇到的常见问题的解决。 一、序列化器serializers.Serializer 1、urls.py urlpatterns [path("api/<str:version>/depart/",views.DepartView.as_vie…

缓存雪崩、击穿、穿透及解决方案_保证缓存和数据库一致性

文章目录 缓存雪崩、击穿、穿透1.缓存雪崩造成缓存雪崩解决缓存雪崩 2. 缓存击穿造成缓存击穿解决缓存击穿 3.缓存穿透造成缓存穿透解决缓存穿透 更新数据时&#xff0c;如何保证数据库和缓存的一致性&#xff1f;1. 先更新数据库&#xff1f;先更新缓存&#xff1f;解决方案 2…

【问题解决】RuntimeError: apex.optimizers.FusedSGD requires cuda extension 问题解决

在使用 apex 库时&#xff0c;按照官方的方式安装后&#xff0c;虽然安装成功&#xff0c;但调用的时候会报错如下&#xff0c;也就是说其实没有成功安装可调用 cuda 的 apex&#xff1a; RuntimeError: apex.optimizers.FusedSGD requires cuda extension我找了很多解决方式&…

【蓝桥杯省赛真题46】Scratch魔术表演 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解

目录 scratch魔术表演 一、题目要求 编程实现 二、案例分析 1、角色分析

微信小程序bindtap和catchtap的区别?

子元素用bindtap绑定事件后&#xff0c;执行的时候&#xff0c;会冒泡到父元素&#xff08;触发父亲元素上绑定的bindtap事件&#xff09; 如果不想冒泡到父元素&#xff0c;可以用catchtap代替 bindtap事件绑定不会阻止冒泡事件向上冒泡 catchtap事件绑定可以阻止冒泡事件向上…

centos 7.7 安装Python-3.7.4

一、安装PYTHON 编译依赖包 1.1 首先安装gcc编译器&#xff0c;gcc有些系统版本已经默认安装&#xff0c;通过 gcc --version 查看&#xff0c;没安装的先安装gcc&#xff0c; yum -y install gcc glibc make1.2 安装其它依赖包&#xff0c;&#xff08;注&#xff1a;不要缺…

【双指针】和为 s 的两个数字

和为 s 的两个数字 文章目录 和为 s 的两个数字题目描述算法思路暴力枚举双指针 代码编写Java代码C代码编写 LCR 179. 查找总价格为目标值的两个商品 - 力扣&#xff08;LeetCode&#xff09; 题目描述 购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品…

Android修行手册-超出父布局进行显示以及超出父布局实现点击

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

shopee数据分析软件丨探索Shopee数据分析软件——知虾

随着电子商务的快速发展&#xff0c;越来越多的商家和企业开始关注数据分析的重要性。在这个竞争激烈的市场中&#xff0c;了解消费者行为、市场趋势和竞争对手的策略是取得成功的关键。而Shopee数据分析软件——知虾&#xff0c;成为了许多商家和企业的首选工具。本文将深入探…

ubuntu20.04 nginx 部署静态网页

1、安装nginx Ubuntu环境下安装部署Nginx&#xff08;有网&#xff09;_ubuntu 安装nginx_荒Huang的博客-CSDN博客 2、压缩并上传文件到服务器指定位置(unzip命令)&#xff0c;修改nginx配置文件&#xff0c;指定root目录为文件的目录&#xff0c;index 值为指定的html文件 …

【拿完年终奖后】想要转行网络安全,一定不要错过这个时间段。

网络安全&#xff0c;作为当下互联网行业中较为热门的岗位&#xff0c;薪资可观、人才需求量大&#xff0c;作为转行必考虑。 在这里奉劝所有零基础想转行&#xff08;入门&#xff09; 网络安全的朋友们 在转行之前&#xff0c;一定要对网络安全行业做一个大概了解&#xf…

latex通过bib添加参考文献作者名字有特殊符号如字母上有两点乱码解决办法

一、背景 在使用latex写英文论文时&#xff0c;一般是通过bib的方式添加参考文献。但有的参考文献作者是法国人或其他国家的&#xff0c;名字会有特殊符号&#xff0c;如某个字母上有两个点&#xff0c;或者声调符号等等&#xff0c;如下图所示&#xff1a; 如果不进行特殊操作…

【C++初阶】第一站:C++入门基础(中)

前言&#xff1a; 这篇文章是c入门基础的第一站的中篇,涉及的知识点 函数重载:函数重载的原理--名字修饰 引用:概念、特性、使用场景、常引用、传值、传引用效率比较的知识点 目录 5. 函数重载 &#xff08;续&#xff09; C支持函数重载的原理--名字修饰(name Mangling) 为什么…

ACE前摄器Proactor

转载的&#xff0c;已经找不到原文地址了 Proactor是异步模式的网络处理器&#xff0c;ACE中叫做“前摄器”。 先讲几个概念&#xff1a; 前摄器&#xff08;Proactor&#xff09;&#xff0d;异步的事件多路分离器、处理器&#xff0c;是核心处理类。启动后由3个线程…

csv文件添加文件内容和读取

append content to file import numpy as np acc_listnp.array([0.97,0.92,0.93,0.89]) # 注意这个地方添加文件不需要特别声明是什么文件 file open("result.csv", "a") print("{:.2f}, {:.2f}".format(acc_list.mean(), acc_list.std()), f…

【JavaEE】Spring小练习——存储和获取对象

一、题目&#xff1a; 在 Spring 项目中&#xff0c;通过 main 方法获取到 Controller 类&#xff0c;调用 Controller 里面通过注入的方式调用Service 类&#xff0c;Service 再通过注入的方式获取到 Repository 类&#xff0c;Repository 类里面有一个方法构建⼀个 User 对象…

YOLO目标检测——垃圾检测数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;智能化垃圾分类系统、垃圾回收和处理领域的优化管理等方面数据集说明&#xff1a;垃圾分类检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;含报纸、蛋壳、矿泉水瓶、电池、拉链顶罐、塑料餐盒、纸质药盒、香蕉皮…