向量数据库Milvus快速入门——AIDOCZH.COM上线Milvus中文文档

Milvus 快速入门——AIDOCZH.COM上线Milvus中文文档

Milvus官方文档的中文翻译

AiDocZh.com 发布Milvus中文文档 http://www.aidoczh.com/docs/milvus/site/zh_CN/home.md

在这里插入图片描述

您可以在上面浏览最新的Milvus官网文档的中文翻译。

Milvus介绍

本页面旨在通过回答几个问题来为您提供Milvus的概述。阅读本页面后,您将了解Milvus是什么,它是如何工作的,以及关键概念、为什么使用Milvus、支持的索引和度量、示例应用程序、架构和相关工具。

什么是Milvus向量数据库?

Milvus是在2019年创建的,其唯一目标是存储、索引和管理由深度神经网络和其他机器学习(ML)模型生成的大规模嵌入向量

作为一个专门设计用于处理输入向量查询的数据库,它能够在万亿级别上对向量进行索引。与现有的主要处理遵循预定义模式的结构化数据的关系型数据库不同,Milvus是从底层开始设计的,用于处理从非结构化数据转换而来的嵌入向量。

随着互联网的发展和演变,非结构化数据变得越来越普遍,包括电子邮件、论文、物联网传感器数据、Facebook照片、蛋白质结构等。为了使计算机能够理解和处理非结构化数据,这些数据会使用嵌入技术转换为向量。Milvus存储和索引这些向量。Milvus能够通过计算它们的相似性距离来分析两个向量之间的相关性。如果两个嵌入向量非常相似,这意味着原始数据源也是相似的。

Workflow

关键概念

如果您对向量数据库和相似性搜索的世界还不熟悉,请阅读以下关键概念的解释,以便更好地理解。

了解更多关于Milvus术语表

非结构化数据

非结构化数据,包括图像、视频、音频和自然语言,是不遵循预定义模型或组织方式的信息。这种数据类型约占世界数据的80%,可以使用各种人工智能(AI)和机器学习(ML)模型将其转换为向量。

嵌入向量

嵌入向量是非结构化数据的特征抽象,例如电子邮件、物联网传感器数据、Instagram照片、蛋白质结构等。从数学上讲,嵌入向量是一组浮点数或二进制数。现代嵌入技术用于将非结构化数据转换为嵌入向量。

向量相似性搜索

向量相似性搜索是将一个向量与数据库进行比较,以找到与查询向量最相似的向量的过程。近似最近邻(ANN)搜索算法用于加速搜索过程。如果两个嵌入向量非常相似,那么原始数据源也是相似的。

为什么选择 Milvus?

  • 在处理大规模数据集上进行向量搜索时性能高。
  • 以开发者为先的社区,提供多语言支持和工具链。
  • 云扩展性强,即使发生中断也能保持高可靠性。
  • 通过将标量过滤与向量相似性搜索配对实现混合搜索。

支持的索引和度量标准是什么?

索引是数据的组织单元。在搜索或查询插入的实体之前,您必须声明索引类型和相似性度量标准。如果您不指定索引类型,Milvus 将默认执行暴力搜索。

索引类型

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

  • HNSW:HNSW 是基于图的索引,最适合对搜索效率有很高需求的场景。还有一个 GPU 版本 GPU_CAGRA,得益于 Nvidia 的贡献。
  • FLAT:FLAT 最适合在小型百万级数据集上寻求完全准确和精确搜索结果的场景。还有一个 GPU 版本 GPU_BRUTE_FORCE
  • IVF_FLAT:IVF_FLAT 是基于量化的索引,最适合在准确性和查询速度之间寻求理想平衡的场景。还有一个 GPU 版本 GPU_IVF_FLAT
  • IVF_SQ8:IVF_SQ8 是基于量化的索引,最适合在磁盘、CPU 和 GPU 内存消耗方面寻求显著减少的场景,因为这些资源非常有限。
  • IVF_PQ:IVF_PQ 是基于量化的索引,最适合在牺牲准确性的情况下追求高查询速度的场景。还有一个 GPU 版本 GPU_IVF_PQ
  • SCANN:SCANN 在向量聚类和产品量化方面类似于 IVF_PQ。它们的区别在于产品量化的实现细节以及使用 SIMD(单指令/多数据)进行高效计算。
  • DiskANN:基于 Vamana 图,DiskANN 可以在大型数据集内进行高效搜索。

更多详情请参阅 Vector Index

相似性度量标准

在 Milvus 中,相似性度量标准用于衡量向量之间的相似性。选择一个好的距离度量标准有助于显著提高分类和聚类性能。根据输入数据形式,选择特定的相似性度量标准以获得最佳性能。

用于浮点嵌入的常用度量标准包括:

  • 余弦相似度:这个度量标准是归一化的内积,通常用于文本相似性搜索(NLP)。
  • 欧氏距离(L2):这个度量标准通常在计算机视觉(CV)领域中使用。
  • 内积(IP):这个度量标准通常在自然语言处理(NLP)领域中使用。 在二进制嵌入中广泛使用的度量标准包括:
  • 汉明距离:这个度量标准通常在自然语言处理(NLP)领域中使用。
  • Jaccard 相似度:这个度量标准通常在分子相似性搜索领域中使用。

更多信息请参见相似性度量

示例应用

Milvus使得向应用程序添加相似性搜索变得轻而易举。Milvus的示例应用包括:

  • 图像相似性搜索:使图像可搜索,并即时从庞大数据库中返回最相似的图像。
  • 视频相似性搜索:通过将关键帧转换为向量,然后将结果输入Milvus,可以在几乎实时中搜索和推荐数十亿个视频。
  • 音频相似性搜索:快速查询大量音频数据,如语音、音乐、音效,并找到相似声音。
  • 推荐系统:根据用户行为和需求推荐信息或产品。
  • 问答系统:交互式数字问答聊天机器人,自动回答用户问题。
  • DNA 序列分类:通过比较相似的DNA序列,在毫秒内准确分类基因。
  • 文本搜索引擎:通过将关键词与文本数据库进行比较,帮助用户找到他们正在寻找的信息。

更多Milvus应用场景请参见Milvus教程Milvus采用者

Milvus的设计理念

作为一个云原生向量数据库,Milvus通过设计将存储和计算分离。为了增强弹性和灵活性,Milvus中的所有组件都是无状态的。

系统分为四个层级:

  • 访问层:访问层由一组无状态代理组成,作为系统的前端层和用户端点。
  • 协调器服务:协调器服务将任务分配给工作节点,充当系统的大脑。
  • 工作节点:工作节点充当手臂和腿部,是从协调器服务接收指令并执行用户触发的DML/DDL命令的哑执行器。
  • 存储:存储是系统的支柱,负责数据持久化。它包括元数据存储、日志代理和对象存储。

更多信息请参见架构概述

架构

比较Milvus

在探索各种向量数据库选项时,这篇全面的指南将帮助您了解Milvus的独特功能,确保您选择最适合您特定需求的数据库。值得注意的是,Milvus是一款领先的开源向量数据库,而Zilliz Cloud提供全面管理的Milvus服务。为了客观评估Milvus与其竞争对手,可以考虑使用基准工具来分析性能指标。

Milvus亮点

  • 功能性:Milvus不仅支持基本的向量相似度搜索,还支持高级功能,如稀疏向量批量向量过滤搜索多向量搜索功能。
  • 灵活性:Milvus支持各种部署模式和多个SDK,在一个强大的集成生态系统中实现。
  • 性能:Milvus通过优化的索引算法(如HNSWDiskANN)以及先进的GPU加速,保证高吞吐量和低延迟的实时处理。
  • 可扩展性:其定制的分布式架构轻松扩展,可容纳从小型数据集到超过100亿向量的集合。

总体比较

为了比较Milvus和Pinecone这两种向量数据库解决方案,以下表格旨在突出各种功能之间的差异。

功能PineconeMilvus备注
部署模式仅支持SaaSMilvus Lite、本地独立部署和集群、Zilliz Cloud SaaS和BYOCMilvus在部署模式上提供更大的灵活性。
支持的SDKPython、JavaScript/TypeScriptPython、Java、NodeJS、Go、Restful API、C#、RustMilvus支持更广泛的编程语言。
开源状态闭源开源Milvus是一款受欢迎的开源向量数据库。
可扩展性仅支持纵向扩展/缩减支持横向扩展/缩减和纵向扩展/缩减Milvus具有分布式架构,可实现更强大的可扩展性。
可用性基于Pod的架构在可用区内可用区故障转移和跨区域高可用Milvus CDC(变更数据捕获)实现主/备模式,提高可用性。
性能成本(每百万次查询美元)中等数据集起价为 $0.178,大型数据集为 $1.222Zilliz Cloud 中等数据集起价为 $0.148,大型数据集为 $0.635;提供免费版本参考 成本排名报告
GPU 加速不支持支持 Nvidia GPUGPU 加速显著提升性能,通常提升数量级。

术语比较

虽然 Milvus 和 Pinecone 都扮演着向量数据库的类似功能,但两者之间的领域专用术语略有不同。具体的术语比较如下。

PineconeMilvus备注
索引Collection在 Pinecone 中,索引作为存储和管理相同大小向量的组织单元,这个索引与硬件(称为 pods)紧密集成。相反,Milvus 的 collections 有类似的作用,但允许在单个实例中处理多个 collections。
集合备份在 Pinecone 中,集合本质上是索引的静态快照,主要用于备份目的,不能进行查询。在 Milvus 中,用于创建备份的等效功能更透明,命名也更直接。
命名空间分区键命名空间允许将索引中的向量分区为子集。Milvus 提供多种方法,如分区或分区键,以确保在集合内实现高效的数据隔离。
元数据标量字段Pinecone 的元数据处理依赖于键值对,而 Milvus 允许复杂的标量字段,包括标准数据类型和动态 JSON 字段。
查询搜索用于查找给定向量的最近邻居的方法名称,可能还会在其上应用一些额外的过滤器。
不可用迭代器Pinecone 缺乏通过索引中所有向量进行迭代的功能。Milvus 引入了搜索迭代器和查询迭代器方法,增强了跨数据集的数据检索能力。

能力比较

能力PineconeMilvus
部署模式仅支持 SaaSMilvus Lite,On-prem Standalone & Cluster,Zilliz Cloud Saas & BYOC
嵌入功能不可用支持 [pymilvusmodel]
数据类型字符串,数字,布尔值,字符串列表字符串,VarChar,数字(整数,浮点数,双精度),布尔值,数组,JSON,浮点向量,二进制向量,BFloat16,Float16,稀疏向量
度量和索引类型余弦相似度,内积,欧氏距离P族,S族余弦相似度,内积(点积),L2(欧氏距离),汉明距离,杰卡德相似度FLAT,IVF_FLAT,IVF_SQ8,IVF_PQ,HNSW,SCANN,GPU索引
模式设计灵活模式灵活模式,严格模式
多向量字段不适用多向量和混合搜索
工具数据集,文本工具,Spark连接器Attu,Birdwatcher,备份,命令行界面,CDC,Spark和Kafka连接器

主要见解

  • 部署模式:Milvus提供多种部署选项,包括本地部署,Docker,Kubernetes本地部署,云端SaaS以及企业自带云(BYOC),而Pinecone仅限于SaaS部署。
  • 嵌入函数:Milvus支持额外的嵌入库,可以直接使用嵌入模型将源数据转换为向量。
  • 数据类型:Milvus支持比Pinecone更广泛的数据类型,包括数组和JSON。Pinecone仅支持带有字符串、数字、布尔值或字符串列表的扁平元数据结构,而Milvus可以处理任何JSON对象,包括JSON字段中的嵌套结构。Pinecone将元数据大小限制为每个向量40KB。
  • 度量和索引类型:Milvus支持广泛的度量和索引类型,以适应各种用例,而Pinecone的选择更有限。在Milvus中,向量的索引是强制性的,同时提供AUTO_INDEX选项以简化配置过程。
  • 模式设计:Milvus为模式设计提供灵活的create_collection模式,包括快速设置具有动态模式的方案,以获得类似Pinecone的无模式体验,以及定制设置具有预定义模式字段和索引的方案,类似于关系数据库管理系统(RDBMS)。
  • 多向量字段:Milvus可以在单个集合中存储多个向量字段,这些字段可以是稀疏或密集的,维度也可以不同。Pinecone没有类似的功能。
  • 工具:Milvus提供更多的数据库管理和利用工具选择,例如Attu,Birdwatcher,备份,命令行界面,CDC以及Spark和Kafka连接器。

开始使用

在本地运行 Milvus Lite

本页面介绍了如何在本地运行 Milvus Lite 以进行开发和测试。

概述

Milvus Lite 是 Milvus 的轻量级版本,Milvus 是一个开源的向量数据库,通过向量嵌入和相似度搜索为 AI 应用提供支持。

Milvus Lite 可以被导入到您的 Python 应用程序中,提供 Milvus 的核心向量搜索功能。Milvus Lite 包含在 Milvus 的 Python SDK 中,因此可以通过 pip install pymilvus 简单部署。该存储库包含了 Milvus Lite 的核心组件。

Milvus Lite 与 Milvus 共享相同的 API,并覆盖了大部分 Milvus 的功能。它们共同为不同规模的环境提供一致的用户体验,适用于不同规模的用例。使用相同的客户端代码,您可以在 Milvus Lite 中快速演示少于百万个向量,或者在单台机器上托管 Milvus Docker 容器的小规模应用程序,最终在 Kubenetes 上进行大规模生产部署,以每秒数千次查询量为服务的数十亿向量。

先决条件

Milvus Lite 支持以下操作系统发行版和芯片类型:

  • Ubuntu >= 20.04 (x86_64)
  • MacOS >= 11.0 (Apple Silicon 和 x86_64)

请注意,Milvus Lite 适用于开始使用向量搜索或构建演示和原型。对于生产用例,我们建议在 DockerKubenetes 上使用 Milvus,或考虑在 Zilliz Cloud 上使用完全托管的 Milvus。

设置 Milvus Lite

Milvus Lite 已经与 pymilvus 打包在一起,pymilvus 是 Milvus 的 Python SDK 库。要设置 Milvus Lite,请在终端中运行以下命令。

pip install "pymilvus>=2.4.2"
连接到 Milvus Lite

您可以按照以下方式连接到 Milvus Lite。

from pymilvus import MilvusClient

client = MilvusClient("milvus_demo.db")

运行上述代码片段后,当前文件夹中将生成一个名为 milvus_demo.db 的数据库文件。

限制

在运行 Milvus Lite 时,请注意某些功能不受支持。

使用 Docker Compose 运行 Milvus

本页面介绍如何使用 Docker Compose 在 Docker 中启动 Milvus 实例。

先决条件
安装 Milvus

Milvus 在其存储库中提供了一个 Docker Compose 配置文件。要使用 Docker Compose 安装 Milvus,只需运行

# 下载配置文件
$ wget https://github.com/milvus-io/milvus/releases/download/v{{var.milvus_release_version}}/milvus-standalone-docker-compose.yml -O docker-compose.yml

# 启动 Milvus
$ sudo docker compose up -d

Creating milvus-etcd  ... done
Creating milvus-minio ... done
Creating milvus-standalone ... done

如果无法运行上述命令,请检查系统是否安装了 Docker Compose V1。如果是这种情况,请根据此页面上的说明迁移到 Docker Compose V2。

启动 Milvus 后,

  • 名为milvus-standalone、milvus-minio和milvus-etcd的容器已启动。
  • milvus-etcd 容器不向主机公开任何端口,并将其数据映射到当前文件夹中的 volumes/etcd
  • milvus-minio 容器在本地提供端口 90909091,使用默认身份验证凭据,并将其数据映射到当前文件夹中的 volumes/minio
  • milvus-standalone 容器在本地提供端口 19530,使用默认设置,并将其数据映射到当前文件夹中的 volumes/milvus

您可以使用以下命令检查容器是否正在运行:

$ sudo docker compose ps

      Name                     Command                  State                            Ports
--------------------------------------------------------------------------------------------------------------------
milvus-etcd         etcd -advertise-client-url ...   Up             2379/tcp, 2380/tcp
milvus-minio        /usr/bin/docker-entrypoint ...   Up (healthy)   9000/tcp
milvus-standalone   /tini -- milvus run standalone   Up             0.0.0.0:19530->19530/tcp, 0.0.0.0:9091->9091/tcp

您可以按以下方式停止和删除此容器

# 停止 Milvus
$ sudo docker compose down

# 删除服务数据
$ sudo rm -rf volumes

导入数据

本主题描述了如何通过批量加载在Milvus中导入数据。

通常,将大批实体插入Milvus的常规方法通常会导致跨客户端、代理、Pulsar和数据节点的大量网络传输。为了避免这种情况,Milvus 2.1支持通过批量加载从文件加载数据。您可以仅通过几行代码将大量数据导入集合,并为整个实体批量赋予原子性。

您还可以使用MilvusDM将数据迁移至Milvus,这是一个专门设计用于与Milvus导入和导出数据的开源工具。

本页上的代码片段使用新的MilvusClient(Python)与Milvus进行交互。未来更新将发布其他语言的新MilvusClient SDK。

准备数据文件

您可以按行或列准备数据文件。

  • 基于行的数据文件

基于行的数据文件是一个包含多行的JSON文件。根键必须是"rows"。文件名可以任意指定。

{
  "rows":[
    {"book_id": 101, "word_count": 13, "book_intro": [1.1, 1.2]},
    {"book_id": 102, "word_count": 25, "book_intro": [2.1, 2.2]},
    {"book_id": 103, "word_count": 7, "book_intro": [3.1, 3.2]},
    {"book_id": 104, "word_count": 12, "book_intro": [4.1, 4.2]},
    {"book_id": 105, "word_count": 34, "book_intro": [5.1, 5.2]},
  ]
}
  • 基于列的数据文件

基于列的数据文件可以是一个包含多列的JSON文件,几个包含单列的Numpy文件,每个文件包含一个列,或一个包含多列和一些Numpy文件的JSON文件。

  • 包含多列的JSON文件
{
        "book_id": [101, 102, 103, 104, 105],
        "word_count": [13, 25, 7, 12, 34],
        "book_intro": [
                [1.1, 1.2],
                [2.1, 2.2],
                [3.1, 3.2],
                [4.1, 4.2],
                [5.1, 5.2]
        ]
}
  • Numpy文件

    import numpy
    numpy.save('book_id.npy', numpy.array([101, 102, 103, 104, 105]))
    numpy.save('word_count.npy', numpy.array([13, 25, 7, 12, 34]))
    arr = numpy.array([[1.1, 1.2],
                [2.1, 2.2],
                [3.1, 3.2],
                [4.1, 4.2],
                [5.1, 5.2]])
    numpy.save('book_intro.npy', arr)
    
  • 一个JSON文件包含多列和一些Numpy文件。

    {
            "book_id": [101, 102, 103, 104, 105],
            "word_count": [13, 25, 7, 12, 34]
    }
    
    {
        "book_id": [101, 102, 103, 104, 105],
        "word_count": [13, 25, 7, 12, 34]
    }
    
数据插入到 Milvus

将数据导入到集合中。

  • 对于基于行的文件
from pymilvus import utility
tasks = utility.bulk_load(
    collection_name="book",
    is_row_based=True,
    files=["row_based_1.json", "row_based_2.json"]
)
  • 对于基于列的文件
from pymilvus import utility
tasks = utility.bulk_load(
    collection_name="book",
    is_row_based=False,
    files=["columns.json", "book_intro.npy"]
)
参数描述
collection_name要加载数据的集合名称。
is_row_based布尔值,指示文件是否基于行。
files要加载到 Milvus 中的文件名列表。
partition_name(可选)要插入数据的分区名称。
检查导入任务状态

检查导入任务的状态。

state = utility.get_bulk_load_state(tasks[0])
print(state.state_name())
print(state.ids())
print(state.infos())

状态代码及其对应的描述。

状态代码状态描述
0BulkLoadPending任务在待处理列表中
1BulkLoadFailed任务失败,使用 state.infos["failed_reason"] 获取失败原因
2BulkLoadStarted任务已分派到数据节点,即将执行
3BulkLoadDownloaded数据文件已从 MinIO 下载到本地
4BulkLoadParsed数据文件已验证并解析
5BulkLoadPersisted已生成并持久化新段
6BulkLoadCompleted任务已完成

单一向量搜索

在插入数据后,下一步是在 Milvus 集合中执行相似性搜索。

Milvus 允许您进行两种类型的搜索,取决于您的集合中向量字段的数量:

  • 单一向量搜索:如果您的集合只有一个向量字段,请使用 search() 方法查找最相似的实体。该方法将您的查询向量与集合中现有向量进行比较,并返回最接近的匹配项的 ID,以及它们之间的距离。可选地,它还可以返回结果的向量值和元数据。
  • 多向量搜索:对于具有两个或更多向量字段的集合,请使用 hybrid_search() 方法。该方法执行多个近似最近邻(ANN)搜索请求,并组合结果以在重新排序后返回最相关的匹配项。

本指南重点介绍如何在 Milvus 中执行单一向量搜索。有关多向量搜索的详细信息,请参阅 混合搜索

概述

有各种搜索类型可满足不同需求:

  • 基本搜索:包括单一向量搜索、批量向量搜索、分区搜索以及带有指定输出字段的搜索。
  • 过滤搜索:根据标量字段应用过滤条件以细化搜索结果。
  • 范围搜索:查找与查询向量在特定距离范围内的向量。
  • 分组搜索:根据特定字段对搜索结果进行分组,以确保结果的多样性。

准备工作

下面的代码片段重新利用现有代码,建立与 Milvus 的连接并快速设置一个集合。

# 1. 设置 Milvus 客户端
client = MilvusClient(
    uri=CLUSTER_ENDPOINT,
    token=TOKEN 
)

# 2. 创建集合
client.create_collection(
    collection_name="quick_setup",
    dimension=5,
    metric_type="IP"
)

# 3. 插入随机生成的向量
colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
data = []

for i in range(1000):
    current_color = random.choice(colors)
    data.append({
        "id": i,
        "vector": [ random.uniform(-1, 1) for _ in range(5) ],
        "color": current_color,
        "color_tag": f"{current_color}_{str(random.randint(1000, 9999))}"
    })

res = client.insert(
    collection_name="quick_setup",
    data=data
)

print(res)

# 输出
#
# {
#     "insert_count": 1000,
#     "ids": [
#         0,
#         1,
#         2,
#         3,
#         4,
#         5,
#         6,
#         7,
#         8,
#         9,
#         "(990 more items hidden)"
#     ]
# }

# 6.1 创建分区
client.create_partition(
    collection_name="quick_setup",
    partition_name="red"
)

client.create_partition(
    collection_name="quick_setup",
    partition_name="blue"
)

# 6.1 将数据插入分区
red_data = [ {"id": i, "vector": [ random.uniform(-1, 1) for _ in range(5) ], "color": "red", "color_tag": f"red_{str(random.randint(1000, 9999))}" } for i in range(500) ]
blue_data = [ {"id": i, "vector": [ random.uniform(-1, 1) for _ in range(5) ], "color": "blue", "color_tag": f"blue_{str(random.randint(1000, 9999))}" } for i in range(500) ]

res = client.insert(
    collection_name="quick_setup",
    data=red_data,
    partition_name="red"
)

print(res)

# 输出
#
# {
#     "insert_count": 500,
#     "ids": [
#         0,
#         1,
#         2,
#         3,
#         4,
#         5,
#         6,
#         7,
#         8,
#         9,
#         "(490 more items hidden)"
#     ]
# }

res = client.insert(
    collection_name="quick_setup",
    data=blue_data,
    partition_name="blue"
)

print(res)

# 输出
#
# {
#     "insert_count": 500,
#     "ids": [
#         0,
#         1,
#         2,
#         3,
#         4,
#         5,
#         6,
#         7,
#         8,
#         9,
#         "(490 more items hidden)"
#     ]
# }

基本搜索

在发送 search 请求时,您可以提供一个或多个向量值,表示您的查询嵌入,以及一个 limit 值,指示要返回的结果数量。

根据您的数据和查询向量,可能会获得少于 limit 个结果。当 limit 大于查询的可能匹配向量数量时,就会发生这种情况。

单向量搜索

单向量搜索是 Milvus 中最简单的 search 操作形式,旨在找到与给定查询向量最相似的向量。

要执行单向量搜索,请指定目标集合名称、查询向量和所需的结果数量(limit)。此操作返回一个结果集,包括最相似的向量、它们的 ID 和与查询向量的距离。 以下是搜索与查询向量最相似的前5个实体的示例:

# 单向量搜索
res = client.search(
    collection_name="test_collection", # 替换为您的集合实际名称
    # 替换为您的查询向量
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5, # 返回的最大搜索结果数
    search_params={"metric_type": "IP", "params": {}} # 搜索参数
)

# 将输出转换为格式化的 JSON 字符串
result = json.dumps(res, indent=4)
print(result)

输出类似于以下内容:

[
    [
        {
            "id": 0,
            "distance": 1.4093276262283325,
            "entity": {}
        },
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {}
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {}
        },
        {
            "id": 5,
            "distance": 0.7972343564033508,
            "entity": {}
        },
        {
            "id": 2,
            "distance": 0.5928734540939331,
            "entity": {}
        }
    ]
]

输出展示了与您的查询向量最接近的前5个邻居,包括它们的唯一ID和计算出的距离。

批量向量搜索

批量向量搜索扩展了单向量搜索的概念,允许在单个请求中搜索多个查询向量。这种搜索类型非常适用于需要为一组查询向量找到相似向量的场景,显著减少了所需的时间和计算资源。

在批量向量搜索中,您可以在data字段中包含多个查询向量。系统会并行处理这些向量,为每个查询向量返回一个单独的结果集,每个集合包含在集合中找到的最接近的匹配项。

以下是搜索两组不同的最相似实体的示例查询向量:

# 批量向量搜索
res = client.search(
    collection_name="test_collection", # 替换为您的集合实际名称
    data=[
        [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104],
        [0.3172005263489739, 0.9719044792798428, -0.36981146090600725, -0.4860894583077995, 0.95791889146345]
    ], # 替换为您的查询向量
    limit=2, # 返回的最大搜索结果数
    search_params={"metric_type": "IP", "params": {}} # 搜索参数
)

result = json.dumps(res, indent=4)
print(result)

输出类似于以下内容:

[
    [
        {
            "id": 1,
            "distance": 1.3017789125442505,
            "entity": {}
        },
        {
            "id": 7,
            "distance": 1.2419954538345337,
            "entity": {}
        }
    ], # 结果集 1
    [
        {
            "id": 3,
            "distance": 2.3358664512634277,
            "entity": {}
        },
        {
            "id": 8,
            "distance": 0.5642921924591064,
            "entity": {}
        }
    ] # 结果集 2
]

搜索结果包括两组最近邻居,每组对应一个查询向量,展示了批量向量搜索的效率,能够一次处理多个查询向量。

分区搜索

分区搜索将您的搜索范围缩小到集合的特定子集或分区。这对于数据被分成逻辑或分类部分的有序数据集特别有用,通过减少需要扫描的数据量,可以加快搜索操作的速度。

要进行分区搜索,只需在搜索请求的 partition_names 中包含目标分区的名称。这指定 search 操作仅考虑指定分区内的向量。

以下是在 red 中搜索实体的示例:

# 6.2 在分区内搜索
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]

res = client.search(
    collection_name="quick_setup",
    data=[query_vector],
    limit=5,
    search_params={"metric_type": "IP", "params": {"level": 1}},
    partition_names=["red"]
)

print(res)

输出结果类似于以下内容:

[
    [
        {
            "id": 16,
            "distance": 0.9200337529182434,
            "entity": {}
        },
        {
            "id": 14,
            "distance": 0.4505271911621094,
            "entity": {}
        },
        {
            "id": 15,
            "distance": 0.19924677908420563,
            "entity": {}
        },
        {
            "id": 17,
            "distance": 0.0075093843042850494,
            "entity": {}
        },
        {
            "id": 13,
            "distance": -0.14609718322753906,
            "entity": {}
        }
    ]
]

然后,在blue中搜索实体:

res = client.search(
    collection_name="quick_setup",
    data=[query_vector],
    limit=5,
    search_params={"metric_type": "IP", "params": {"level": 1}},
    partition_names=["blue"]
)

print(res)

输出结果类似于以下内容:

[
    [
        {
            "id": 20,
            "distance": 2.363696813583374,
            "entity": {}
        },
        {
            "id": 26,
            "distance": 1.0665391683578491,
            "entity": {}
        },
        {
            "id": 23,
            "distance": 1.066049575805664,
            "entity": {}
        },
        {
            "id": 29,
            "distance": 0.8353596925735474,
            "entity": {}
        },
        {
            "id": 28,
            "distance": 0.7484277486801147,
            "entity": {}
        }
    ]
]

红色中的数据与蓝色中的数据不同。因此,搜索结果将受限于指定的分区,反映该子集的独特特征和数据分布。

带有输出字段的搜索

带有输出字段的搜索允许您指定匹配向量中应包含在搜索结果中的哪些属性或字段。

您可以在请求中指定output_fields以返回具有特定字段的结果。

以下是返回具有color属性值的结果的示例:

# 使用输出字段进行搜索
res = client.search(
    collection_name="test_collection", # 替换为实际集合的名称
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5, # 返回的最大搜索结果数
    search_params={"metric_type": "IP", "params": {}}, # 搜索参数
    output_fields=["color"] # 要返回的输出字段
)

result = json.dumps(res, indent=4)
print(result)

输出类似于以下内容:

[
    [
        {
            "id": 0,
            "distance": 1.4093276262283325,
            "entity": {
                "color": "粉红色_8682"
            }
        },
        {
            "id": 16,
            "distance": 1.0159327983856201,
            "entity": {
                "color": "黄色_1496"
            }
        },
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {
                "color": "红色_4794"
            }
        },
        {
            "id": 14,
            "distance": 0.9803846478462219,
            "entity": {
                "color": "绿色_2899"
            }
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {
                "color": "红色_7025"
            }
        }
    ]
]

在最近邻的结果旁边,搜索结果将包括指定的字段 color,为每个匹配向量提供更丰富的信息集。

过滤搜索

过滤搜索对向量搜索应用标量过滤器,允许您根据特定条件细化搜索结果。您可以在布尔表达式规则中了解有关过滤表达式的更多信息,并在获取和标量查询中查看示例。

使用 like 运算符

like 运算符通过评估包括前缀、中缀和后缀在内的模式来增强字符串搜索:

  • 前缀匹配:要查找以特定前缀开头的值,请使用语法 'like "prefix%"'
  • 中缀匹配:要查找包含字符串任何位置的特定字符序列的值,请使用语法 'like "%infix%"'
  • 后缀匹配:要查找以特定后缀结尾的值,请使用语法 'like "%suffix"'

对于单字符匹配,下划线 (_) 作为一个字符的通配符,例如,'like "y_llow"'

搜索字符串中的特殊字符

如果要搜索包含特殊字符(如下划线 _ 或百分号 %)的字符串,这些字符通常用作搜索模式中的通配符(_ 代表任意单个字符,%代表任意字符序列),则必须转义这些字符以将其视为字面字符。使用反斜杠 (\) 来转义特殊字符,并记得转义反斜杠本身。例如:

  • 要搜索字面下划线,请使用 \\_
  • 要搜索字面百分号,请使用 \\%

因此,如果您需要搜索文本 "_version_",您的查询应格式为 'like "\\_version\\_"',以确保下划线被视为搜索项的一部分,而不是通配符。

过滤结果中 colorred 为前缀的:

# 使用过滤器进行搜索
res = client.search(
    collection_name="test_collection",  # 用您的集合实际名称替换
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5,  # 返回的最大搜索结果数
    search_params={"metric_type": "IP", "params": {}},  # 搜索参数
    output_fields=["color"],  # 要返回的输出字段
    filter='color like "red%"'
)

result = json.dumps(res, indent=4)
print(result)

输出类似于以下内容:

[
    [
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {
                "color": "red_4794"
            }
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {
                "color": "red_7025"
            }
        },
        {
            "id": 6,
            "distance": -0.4113418459892273,
            "entity": {
                "color": "red_9392"
            }
        }
    ]
]

过滤包含字符串中任何位置有 ll 字母的 color 结果:

# 针对颜色字段的中缀匹配
res = client.search(
    collection_name="test_collection",  # 替换为您的集合实际名称
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=5,  # 返回的最大搜索结果数
    search_params={"metric_type": "IP", "params": {}},  # 搜索参数
    output_fields=["color"],  # 要返回的输出字段
    filter='color like "%ll%"'  # 在颜色字段上进行过滤,中缀匹配"ll"
)

result = json.dumps(res, indent=4)
print(result)

输出类似于以下内容:

[
    [
        {
            "id": 5,
            "distance": 0.7972343564033508,
            "entity": {
                "color": "yellow_4222"
            }
        }
    ]
]

范围搜索

范围搜索允许您查找与查询向量在指定距离范围内的向量。

通过设置 radius 和可选的 range_filter,您可以调整搜索的广度,以包括与查询向量略有相似的向量,从而提供潜在匹配的更全面视图。

  • radius: 定义搜索空间的外部边界。只有距离查询向量在此距离内的向量才被视为潜在匹配项。
  • range_filter: 虽然 radius 设置了搜索的外部限制,但可以选择使用 range_filter 来定义内部边界,创建一个距离范围,在此范围内的向量才被视为匹配项。
# 进行范围搜索
search_params = {
    "metric_type": "IP",
    "params": {
        "radius": 0.8, # 搜索圆的半径
        "range_filter": 1.0 # 范围过滤器,用于过滤出不在搜索圆内的向量
    }
}

res = client.search(
    collection_name="test_collection", # 用实际集合名称替换
    data=[[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    limit=3, # 返回的最大搜索结果数
    search_params=search_params, # 搜索参数
    output_fields=["color"], # 要返回的输出字段
)

result = json.dumps(res, indent=4)
print(result)

输出类似于以下内容:

[
    [
        {
            "id": 4,
            "distance": 0.9902134537696838,
            "entity": {
                "color": "red_4794"
            }
        },
        {
            "id": 14,
            "distance": 0.9803846478462219,
            "entity": {
                "color": "green_2899"
            }
        },
        {
            "id": 1,
            "distance": 0.8519943356513977,
            "entity": {
                "color": "red_7025"
            }
        }
    ]
]

您会发现,返回的所有实体与查询向量的距离均在0.8到1.0的范围内。

radiusrange_filter 的参数设置随所使用的度量类型而变化。

度量类型特征范围搜索设置
L2较小的 L2 距离表示更高的相似度。要排除结果中最接近的向量,请确保: range_filter <= 距离 < radius
IP较大的 IP 距离表示更高的相似度。要排除结果中最接近的向量,请确保: radius < 距离 <= range_filter

注意:为了确保表格显示正确,range_filterradius 的说明部分换行前后没有任意额外的空格或字符。

这样就可以解决 MDX 编译错误。试试看重编译你的文档。

分组搜索

在 Milvus 中,通过特定字段进行分组搜索可以避免结果中相同字段项的冗余。您可以针对特定字段获得各异的结果集。

考虑一个文档集合,每个文档分为各种段落。每个段落由一个向量嵌入表示,并属于一个文档。为了找到相关文档而不是相似段落,您可以在 search() 操作中包含 group_by_field 参数,按文档 ID 对结果进行分组。这有助于返回最相关且唯一的文档,而不是来自同一文档的单独段落。

以下是按字段分组搜索结果的示例代码:

# 连接到 Milvus
client = MilvusClient(uri='http://localhost:19530') # Milvus 服务器地址

# 将数据加载到集合中
client.load_collection("group_search") # 集合名称

# 分组搜索结果
res = client.search(
    collection_name="group_search", # 集合名称
    data=[[0.14529211512077012, 0.9147257273453546, 0.7965055218724449, 0.7009258593102812, 0.5605206522382088]], # 查询向量
    search_params={
    "metric_type": "L2",
    "params": {"nprobe": 10},
    }, # 搜索参数
    limit=10, # 返回的最大搜索结果数
    group_by_field="doc_id", # 按文档 ID 对结果进行分组
    output_fields=["doc_id", "passage_id"]
)

# 提取 `doc_id` 列中的值
doc_ids = [result['entity']['doc_id'] for result in res[0]]

print(doc_ids)

输出类似于以下内容:

[5, 10, 1, 7, 9, 6, 3, 4, 8, 2]

在给定的输出中,可以观察到返回的实体不包含任何重复的 doc_id 值。

为了比较,让我们将 group_by_field 注释掉并进行常规搜索:

# 连接到 Milvus
client = MilvusClient(uri='http://localhost:19530') # Milvus 服务器地址

# 将数据加载到集合中
client.load_collection("group_search") # 集合名称

# 在没有 `group_by_field` 的情况下进行搜索
res = client.search(
    collection_name="group_search", # 集合名称
    data=query_passage_vector, # 用您的查询向量替换
    search_params={
    "metric_type": "L2",
    "params": {"nprobe": 10},
    }, # 搜索参数
    limit=10, # 返回的搜索结果的最大数量
    # group_by_field="doc_id", # 按文档 ID 对结果进行分组
    output_fields=["doc_id", "passage_id"]
)

# 提取 `doc_id` 列中的值
doc_ids = [result['entity']['doc_id'] for result in res[0]]

print(doc_ids)

输出类似于以下内容:

[1, 10, 3, 10, 1, 9, 4, 4, 8, 6]

在给定的输出中,可以观察到返回的实体包含重复的 doc_id 值。

限制

  • 索引: 此分组功能仅适用于使用 HNSWIVF_FLATFLAT 类型进行索引的集合。有关更多信息,请参阅内存索引
  • 向量: 目前,分组搜索不支持 BINARY_VECTOR 类型的向量字段。有关数据类型的更多信息,请参阅支持的数据类型
  • 字段: 目前,分组搜索仅允许单个列。您不能在 group_by_field 配置中指定多个字段名。此外,分组搜索与 JSON、FLOAT、DOUBLE、ARRAY 或向量字段的数据类型不兼容。
  • 性能影响: 请注意,随着查询向量数量的增加,性能会下降。以具有 2 个 CPU 核心和 8 GB 内存的集群为例,分组搜索的执行时间会随着输入查询向量数量的增加而成比例增加。
  • 功能: 目前,分组搜索不受范围搜索搜索迭代器多向量搜索的支持。

搜索参数

在上述搜索中,除了范围搜索外,适用默认搜索参数。在正常情况下,您无需手动设置搜索参数。

# 在正常情况下,您无需手动设置搜索参数
# 除了范围搜索。
search_parameters = {
    'metric_type': 'L2',
    'params': {
        'nprobe': 10,
        'level': 1'radius': 1.0
        'range_filter': 0.8
    }
}

下表列出了搜索参数中所有可能的设置。

参数名称参数描述
metric_type衡量向量嵌入之间相似性的方法。 可能的值为 IPL2COSINE,默认为加载的索引文件的值。
params.nprobe查询期间要查询的单位数。 该值在范围 [1, nlist[1]] 内。
params.level搜索精度级别。 可能的值为 123,默认为 1。较高的值会产生更准确的结果,但性能较慢。
params.radius查询向量和候选向量之间的最小相似度。 该值的范围为 [1, nlist[1]]。
params.range_filter相似度范围,可选择性地细化在范围内查找向量。 该值的范围为 [top-K[2], ∞]。
  • 31
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数智笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值