AI大模型项目实战v0.3版本中,会引入Milvus向量数据库。
这里提前介绍一下
-
Milvus是什么?
-
Milvus如何安装?
-
如何使用Python运行Milvus?
Milvus是什么?
Milvus于2019年创建,目标是存储、索引和管理由深度神经网络和其他机器学习(ML)模型生成的大量嵌入向量。
作为一个专门设计用于处理输入向量查询的数据库,它能够索引万亿级别的向量。与主要处理遵循预定义模式的结构化数据的现有关系数据库不同,Milvus从底层设计用于处理从非结构化数据转换而来的嵌入向量。
随着互联网的发展和演变,非结构化数据变得越来越普遍,包括电子邮件、论文、物联网传感器数据、Facebook照片、蛋白质结构等。为了让计算机理解和处理非结构化数据,这些数据被转换成向量。Milvus存储和索引这些向量。Milvus能够通过计算两个向量之间的相似度距离来分析它们之间的相关性。如果两个嵌入向量非常相似,这意味着原始数据源也很相似。
![图片](data:image/svg+xml,%3C%3Fxml version=‘1.0’ encoding=‘UTF-8’%3F%3E%3Csvg width=‘1px’ height=‘1px’ viewBox=‘0 0 1 1’ version=‘1.1’ xmlns=‘http://www.w3.org/2000/svg' xmlns:xlink=‘http://www.w3.org/1999/xlink'%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=‘none’ stroke-width=‘1’ fill=‘none’ fill-rule=‘evenodd’ fill-opacity=‘0’%3E%3Cg transform=‘translate(-249.000000, -126.000000)’ fill=’%23FFFFFF’%3E%3Crect x=‘249’ y=‘126’ width=‘1’ height=‘1’%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
主要概念
非结构化数据
非结构化数据,包括图像、视频、音频和自然语言,是不遵循预定义模型或组织方式的信息。这种数据类型占全球数据的约80%,可以使用各种人工智能(AI)和机器学习(ML)模型转换成向量。
嵌入向量
嵌入向量是非结构化数据的特征抽象,如电子邮件、物联网传感器数据、Instagram照片、蛋白质结构等。从数学上讲,嵌入向量是一个浮点数或二进制数的数组。现代嵌入技术用于将非结构化数据转换成嵌入向量。
向量相似性搜索
向量相似性搜索是将一个向量与数据库进行比较,以找到与查询向量最相似的向量的过程。使用近似最近邻(ANN)搜索算法来加速搜索过程。如果两个嵌入向量非常相似,这意味着原始数据源也很相似。
为什么选择Milvus?
-
在处理大规模数据集的向量搜索时表现出高性能。
-
一个以开发者为先的社区,提供多语言支持和工具链。
-
即使在中断事件中也具有云可扩展性和高可靠性。
-
通过将标量过滤与向量相似性搜索相结合,实现混合搜索。
支持哪些索引和度量标准?
索引是数据的组织单位。在进行搜索或查询插入的实体之前,您必须声明索引类型和相似性度量。如果您不指定索引类型,Milvus将默认进行暴力搜索。
索引类型
Milvus支持的大多数向量索引类型使用近似最近邻搜索(ANNS),包括:
-
FLAT:FLAT最适合在小型、百万级数据集上寻求完全准确和精确搜索结果的场景。
-
IVF_FLAT:IVF_FLAT是基于量化的索引,最适合寻求在准确性和查询速度之间取得理想平衡的场景。还有一个GPU版本GPU_IVF_FLAT。
-
IVF_SQ8:IVF_SQ8是基于量化的索引,最适合寻求显著减少磁盘、CPU和GPU内存消耗的场景,因为这些资源非常有限。
-
IVF_PQ:IVF_PQ是基于量化的索引,最适合寻求高查询速度,即使以牺牲准确性为代价的场景。还有一个GPU版本GPU_IVF_PQ。
-
HNSW:HNSW是基于图的索引,最适合对搜索效率有高要求的场景。
相似性度量
在Milvus中,相似性度量用于测量向量之间的相似性。选择一个好的距离度量可以显著提高分类和聚类性能。根据输入数据形式,选择特定的相似性度量以获得最佳性能。
广泛用于浮点嵌入的度量包括:
-
欧几里得距离(L2):该度量通常用于计算机视觉(CV)领域。
-
内积(IP):该度量通常用于自然语言处理(NLP)领域。
广泛用于二进制嵌入的度量包括:
-
汉明距离(Hamming):这个度量标准通常用于自然语言处理(NLP)领域。
-
杰卡德距离(Jaccard):这个度量标准通常用于分子最近邻搜索领域。
应用程序示例
Milvus 可以很容易地为应用程序添加最近邻搜索,例如:
-
图像相似搜索: 图像可以被搜索,并且可以从大量的数据库中即时返回最相似的图像。
-
视频相似搜索: 通过将关键帧转换为矢量,然后将结果输入 Milvus,数十亿的视频可以在近乎实时的情况下被搜索和推荐。
-
音频相似搜索: 快速查询大量的音频数据,如语音、音乐、音效和表面类似的声音。
-
推荐系统: 根据用户行为和需求推荐信息或产品。
-
问答系统: 交互式数字 QA 聊天机器人,自动回答用户的问题。
-
DNA 序列分类: 通过比较相似的 DNA 序列,以毫秒为单位精确地对基因进行分类。
-
文本搜索引擎: 通过将关键字与文本数据库进行比较,帮助用户找到他们正在查找的信息。
Milvus如何安装?
Milvus有多种安装方法,详情可以参考:
https://milvus.io/docs/install_standalone-docker.md
今天介绍基于Docker Compose(CPU)的安装方法:
-
安装docker
-
安装docker compose
-
安装milvus
Docker安装
<pre data-block="true" data-editor="faj32" data-offset-key="fq19f-0-0"><p><span>sudo apt install <span>-</span>y docker<span>.</span>io <span># 安装Docker Engine</span></span></p></pre>
apt install直接安装docker, 使用 -y 参数来避免确认,实现自动化操作
<pre data-block="true" data-editor="faj32" data-offset-key="3ba6v-0-0"><p><span>sudo service docker start <span># 启动docker 服务 </span><br>sudo usermod <span>-</span>aG docker $<span>{</span>USER<span>}</span> <span># 当前用户加入docker组</span></span></p></pre>
第一个 service docker start 是启动 Docker 的后台服务,第二个 usermod -aG 是把当前的用户加入 Docker 的用户组。这是因为操作 Docker 必须要有 root 权限,而直接使用 root 用户不够安全,加入 Docker 用户组是一个比较好的选择,这也是 Docker 官方推荐的做法。当然,如果只是为了图省事,你也可以直接切换到 root 用户来操作 Docker。上面的三条命令执行完之后,我们还需要退出系统(命令 exit ),再重新登录一次,这样才能让修改用户组的命令 usermod 生效。
验证docker 是否安装成功
docker version 会输出 Docker 客户端和服务器各自的版本信息
docker info 会显示当前 Docker 系统相关的信息,例如 CPU、内存、容器数量、镜像数量、容器运行时、存储文件系统等等.
Docker-Compose安装
按顺序运行以下命令
<pre data-block="true" data-editor="faj32" data-offset-key="90k8p-0-0"><p><span>sudo curl <span>-</span>SL https<span>:</span><span>//</span>github<span>.</span>com<span>/</span>docker<span>/</span>compose<span>/</span>releases<span>/</span>download<span>/</span>v2<span>.</span><span>23.3</span><span>/</span>docker<span>-</span>compose<span>-</span>linux<span>-</span>x86_64 <span>-</span>o <span>/</span>usr<span>/</span>local<span>/</span><span>bin</span><span>/</span>docker<span>-</span>compose</span></p></pre><pre data-block="true" data-editor="faj32" data-offset-key="24n4f-0-0"><p><span>sudo chmod <span>+</span>x <span>/</span>usr<span>/</span>local<span>/</span><span>bin</span><span>/</span>docker<span>-</span>compose</span></p></pre><pre data-block="true" data-editor="faj32" data-offset-key="evr0d-0-0"><p><span>sudo ln <span>-</span>s <span>/</span>usr<span>/</span>local<span>/</span><span>bin</span><span>/</span>docker<span>-</span>compose <span>/</span>usr<span>/</span><span>bin</span><span>/</span>docker<span>-</span>compose</span></p></pre>
安装完成之后,来看一下它的版本号,命令是 docker-compose version,用法和 docker version 是一样的:
Milvus安装
下载YAML文件
下载milvus-standalone-docker-compose.yml文件,并改名成docker-compose.yml
<pre data-block="true" data-editor="faj32" data-offset-key="b6knk-0-0"><p><span>wget https://github.com/milvus-io/milvus/releases/download/v2.3.4/milvus-standalone-docker-compose.yml -O docker-compose.yml</span></p></pre>
启动Milvus
在与 docker-compose. yml 文件相同的目录中,运行以下命令启动 Milvus:
<pre data-block="true" data-editor="faj32" data-offset-key="a3g78-0-0"><p><span>sudo docker-compose up -d</span></p></pre>
检查容器是否已经启动并运行。
sudo docker-compose ps
连接Milvus
验证 Milvus 服务器正在监听哪个本地端口。将容器名称替换为您自己的。
<pre data-block="true" data-editor="faj32" data-offset-key="vjts-0-0"><p><span>docker port milvus-standalone 19530/tcp</span></p></pre>
可以使用此命令返回的本地 IP 地址和端口号连接到 Milvus。
停止Milvus服务
<pre data-block="true" data-editor="faj32" data-offset-key="i7n7-0-0"><p><span>sudo docker-compose down</span></p></pre>
停止Milvus后,删除数据
<pre data-block="true" data-editor="faj32" data-offset-key="98kva-0-0"><p><span>sudo rm -rf volumes</span></p></pre>
如何使用Python运行Milvus?
准备工作:
-
Milvus: 上一步已经安装好
-
Python3:Linux默认已经安装好
-
PyMilvus:运行pip install pymilvus安装
下载示例代码
<pre data-block="true" data-editor="faj32" data-offset-key="a4486-0-0"><p><span>wget https://raw.githubusercontent.com/milvus-io/pymilvus/master/examples/hello_milvus.py</span></p></pre>
示例代码解释
导入 PyMilvus 包
<pre data-block="true" data-editor="faj32" data-offset-key="b6hpi-0-0"><p><span><span>from</span> pymilvus <span>import</span> <span>(</span><br> connections<span>,</span><br> utility<span>,</span><br> FieldSchema<span>,</span><br> CollectionSchema<span>,</span><br> DataType<span>,</span><br> Collection<span>,</span><br><span>)</span></span></p></pre>
连接服务
<pre data-block="true" data-editor="faj32" data-offset-key="58uml-0-0"><p><span>connections.connect("default", host="localhost", port="19530")</span></p></pre>
创建一个集合
<pre data-block="true" data-editor="faj32" data-offset-key="fe16s-0-0"><p><span>fields <span>=</span> <span>[</span><br> FieldSchema<span>(</span>name<span>=</span><span>"pk"</span><span>,</span> dtype<span>=</span>DataType<span>.</span>INT64<span>,</span> is_primary<span>=</span><span>True</span><span>,</span> auto_id<span>=</span><span>False</span><span>),</span><br> FieldSchema<span>(</span>name<span>=</span><span>"random"</span><span>,</span> dtype<span>=</span>DataType<span>.</span>DOUBLE<span>),</span><br> FieldSchema<span>(</span>name<span>=</span><span>"embeddings"</span><span>,</span> dtype<span>=</span>DataType<span>.</span>FLOAT_VECTOR<span>,</span> dim<span>=</span><span>8</span><span>)</span><br><span>]</span><br>schema <span>=</span> CollectionSchema<span>(</span>fields<span>,</span> <span>"hello_milvus is the simplest demo to introduce the APIs"</span><span>)</span><br>hello_milvus <span>=</span> Collection<span>(</span><span>"hello_milvus"</span><span>,</span> schema<span>)</span><br><br></span></p></pre>
在集合中插入向量
<pre data-block="true" data-editor="faj32" data-offset-key="1bp7o-0-0"><p><span><span>import</span> random<br>entities <span>=</span> <span>[</span><br> <span>[</span>i <span>for</span> i <span>in</span> <span>range</span><span>(</span><span>3000</span><span>)],</span> <span># field pk</span><br> <span>[</span><span>float</span><span>(</span>random<span>.</span>randrange<span>(</span><span>-</span><span>20</span><span>,</span> <span>-</span><span>10</span><span>))</span> <span>for</span> _ <span>in</span> <span>range</span><span>(</span><span>3000</span><span>)],</span> <span># field random</span><br> <span>[[</span>random<span>.</span>random<span>()</span> <span>for</span> _ <span>in</span> <span>range</span><span>(</span><span>8</span><span>)]</span> <span>for</span> _ <span>in</span> <span>range</span><span>(</span><span>3000</span><span>)],</span> <span># field embeddings</span><br><span>]</span><br>insert_result <span>=</span> hello_milvus<span>.</span>insert<span>(</span>entities<span>)</span><br>hello_milvus<span>.</span>flush<span>()</span> <br><br></span></p></pre>
在实体上生成索引
<pre data-block="true" data-editor="faj32" data-offset-key="9ikem-0-0"><p><span>index <span>=</span> <span>{</span><br> <span>"index_type"</span><span>:</span> <span>"IVF_FLAT"</span><span>,</span><br> <span>"metric_type"</span><span>:</span> <span>"L2"</span><span>,</span><br> <span>"params"</span><span>:</span> <span>{</span><span>"nlist"</span><span>:</span> <span>128</span><span>},</span><br><span>}</span><br>hello_milvus<span>.</span>create_index<span>(</span><span>"embeddings"</span><span>,</span> index<span>)</span><br><br></span></p></pre>
将集合加载到内存并执行向量相似性搜索
<pre data-block="true" data-editor="faj32" data-offset-key="88i95-0-0"><p><span>hello_milvus<span>.</span>load<span>()</span><br>vectors_to_search <span>=</span> entities<span>[</span><span>-</span><span>1</span><span>][</span><span>-</span><span>2</span><span>:]</span><br>search_params <span>=</span> <span>{</span><br> <span>"metric_type"</span><span>:</span> <span>"L2"</span><span>,</span><br> <span>"params"</span><span>:</span> <span>{</span><span>"nprobe"</span><span>:</span> <span>10</span><span>},</span><br><span>}</span><br>result <span>=</span> hello_milvus<span>.</span>search<span>(</span>vectors_to_search<span>,</span> <span>"embeddings"</span><span>,</span> search_params<span>,</span> limit<span>=</span><span>3</span><span>,</span> output_fields<span>=</span><span>[</span><span>"random"</span><span>])</span></span></p></pre>
执行向量查询
<pre data-block="true" data-editor="faj32" data-offset-key="u9k2-0-0"><p><span>result <span>=</span> hello_milvus<span>.</span>query<span>(</span>expr<span>=</span><span>"random > -14"</span><span>,</span> output_fields<span>=</span><span>[</span><span>"random"</span><span>,</span> <span>"embeddings"</span><span>])</span></span></p></pre>
执行混合搜索
<pre data-block="true" data-editor="faj32" data-offset-key="f3fkh-0-0"><p><span>result <span>=</span> hello_milvus<span>.</span>search<span>(</span>vectors_to_search<span>,</span> <span>"embeddings"</span><span>,</span> search_params<span>,</span> limit<span>=</span><span>3</span><span>,</span> expr<span>=</span><span>"random > -12"</span><span>,</span> output_fields<span>=</span><span>[</span><span>"random"</span><span>])</span></span></p></pre>
按照实体的主键删除实体
<pre data-block="true" data-editor="faj32" data-offset-key="3hd0h-0-0"><p><span>expr = f"pk in [{entities[0][0]}, {entities[0][1]}]" hello_milvus.delete(expr)</span></p></pre>
删除集合
<pre data-block="true" data-editor="faj32" data-offset-key="4ekiq-0-0"><p><span>utility.drop_collection("hello_milvus")</span></p></pre>
运行示例代码
<pre data-block="true" data-editor="faj32" data-offset-key="d5lfm-0-0"><p><span>python3 hello_milvus.py</span></p></pre>
返回的结果和查询延迟如下所示:
<pre data-block="true" data-editor="faj32" data-offset-key="ev7po-0-0"><p><span>=== start connecting to Milvus ===<br><br>Does collection hello_milvus exist in Milvus: False<br><br>=== Create collection `hello_milvus` ===<br><br><br>=== Start inserting entities ===<br><br>Number of entities in Milvus: 3000<br><br>=== Start Creating index IVF_FLAT ===<br><br><br>=== Start loading ===<br><br><br>=== Start searching based on vector similarity ===<br><br>hit: (distance: 0.0, id: 2998), random field: -11.0<br>hit: (distance: 0.11455299705266953, id: 1581), random field: -18.0<br>hit: (distance: 0.1232629269361496, id: 2647), random field: -13.0<br>hit: (distance: 0.0, id: 2999), random field: -11.0<br>hit: (distance: 0.10560893267393112, id: 2430), random field: -18.0<br>hit: (distance: 0.13938161730766296, id: 377), random field: -14.0<br>search latency = 0.2796s<br><br>=== Start querying with `random > -14` ===<br><br>query result:<br>-{'pk': 9, 'random': -13.0, 'embeddings': [0.298433, 0.931987, 0.949756, 0.598713, 0.290125, 0.094323, 0.064444, 0.306993]}<br>search latency = 0.2970s<br><br>=== Start hybrid searching with `random > -12` ===<br><br>hit: (distance: 0.0, id: 2998), random field: -11.0<br>hit: (distance: 0.15773043036460876, id: 472), random field: -11.0<br>hit: (distance: 0.3273330628871918, id: 2146), random field: -11.0<br>hit: (distance: 0.0, id: 2999), random field: -11.0<br>hit: (distance: 0.15844076871871948, id: 2218), random field: -11.0<br>hit: (distance: 0.1622171700000763, id: 1403), random field: -11.0<br>search latency = 0.3028s<br><br>=== Start deleting with expr `pk in [0, 1]` ===<br><br>query before delete by expr=`pk in [0, 1]` -> result: <br>-{'pk': 0, 'random': -18.0, 'embeddings': [0.142279, 0.414248, 0.378628, 0.971863, 0.535941, 0.107011, 0.207052, 0.98182]}<br>-{'pk': 1, 'random': -15.0, 'embeddings': [0.57512, 0.358512, 0.439131, 0.862369, 0.083284, 0.294493, 0.004961, 0.180082]}<br><br>query after delete by expr=`pk in [0, 1]` -> result: []<br><br><br>=== Drop collection `hello_milvus` ===</span></p></pre>
总结
至此,我们已经成功安装了 Milvus, 并执行了第一个向量相似性搜索。
相关阅读:
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek001/post/20240730/Milvus%E5%90%91%E9%87%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E5%85%A5%E9%97%A8/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com