请添加图片描述
在推荐系统中,向量的最邻近检索是极为关键的一步,特别是在召回流程中。一般常用的如Annoy、faiss都可以满足大部分的需求,今天再来介绍另外一个:Milvus

Milvus

Milvus不同于Annoy、faiss这类型的向量检索工具,它更是一款开源向量数据库,赋能 AI 应用和向量相似度搜索。

涉及的术语

  1. Field:类似表字段,可以是结构化数据,当然还可以是向量;
  2. Entity:一组Field,类似表的一条数据;
  3. Collection:一组Entity,类似于表;

亮点

  1. Milvus不单单是向量检索工具,而是向量数据库,能对不同业务的向量隔离,分开存储;
  2. 提供可视化管理工具;
  3. 支持带过滤条件的向量混合检索。

前言提示

本文介绍的是官方最新版本2.0.0rc4:https://milvus.io/cn/docs/v2.0.0/home,因为新增了许多强大的功能,所以尝鲜实验了一把。但2.x还在迭代中,并不是稳定版本。实验后,也发现存在一些问题,如有时无法查询,而1.x则不存在这些问题。

所以,大家实际使用最好是用最新的稳定版本1.1.1 ,不过缺少一些功能。https://milvus.io/cn/docs/v1.1.1/home

具官网表明,2.x的稳定版本也即将上线,到时再更新2.X版本投入生产环境。

Milvus 2.0Milvus 1.x
架构云原生共享存储
可扩展性500+ 个节点1 - 32 个读节点,1 个写节点
持久性对象存储 (OSS)、分布式文件系统 (DFS)本地磁盘、网络文件系统 (NFS)
可用性99.9%99%
数据一致性多种一致性StrongBounded StalenessSessionConsistent prefix最终一致
数据类型支持向量数据标量数据字符串与文本 (开发中)向量数据
基本操作插入数据删除数据 (开发中)、数据查询相似最邻近(ANN)、搜索基于半径的最近邻算法(RNN) (开发中)插入数据删除数据相似最邻近(ANN)搜索
高级功能标量字段过滤Time Travel多云/地域部署数据管理工具MishardsMilvus DM 数据迁移工具
索引类型Faiss、Annoy、Hnswlib、RNSG、ScaNN (开发中)、On-disk index (开发中)Faiss、Annoy、Hnswlib、RNSG
SDKPythonGo (开发中)Java (开发中)RESTful (开发中)C++ (开发中)Python、Java、Go、RESTful、C++
当前状态预览版本。预计 2021 年 8 月发布稳定版本。长期支持(LTS)版本

Docker安装

安装milvus之前:docker安装

如果安装了docker,但没有docker-compose的话,可以通过pip进行安装。https://docs.docker.com/compose/install/

pip install docker-compose

单机版安装

这里介绍docker的安装方式,官方还提供了使用Kubernetes安装

  1. 下载docker镜像文件

    wget https://raw.githubusercontent.com/milvus-io/milvus/ecfebff801291934a3e6c5955e53637b993ab41a/deployments/docker/standalone/docker-compose.yml -O docker-compose.yml
    

    没办法翻墙的可以自己新建docker-compose.yml文件,然后填入以下内容:

    version: '3.5'
    
    services:
      etcd:
        container_name: milvus-etcd
        image: quay.io/coreos/etcd:v3.5.0
        volumes:
          - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
        command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
    
      minio:
        container_name: milvus-minio
        image: minio/minio:RELEASE.2020-12-03T00-03-10Z
        environment:
          MINIO_ACCESS_KEY: minioadmin
          MINIO_SECRET_KEY: minioadmin
        volumes:
          - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
        command: minio server /minio_data
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
          interval: 30s
          timeout: 20s
          retries: 3
    
      standalone:
        container_name: milvus-standalone
        image: milvusdb/milvus:v2.0.0-rc4-20210811-bdb8396
        command: ["milvus", "run", "standalone"]
        environment:
          ETCD_ENDPOINTS: etcd:2379
          MINIO_ADDRESS: minio:9000
        volumes:
          - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
        ports:
          - "19530:19530"
        depends_on:
          - "etcd"
          - "minio"
    
    networks:
      default:
        name: milvus
    
  2. 拉取镜像并启动

docker-compose up -d

这条是启动命令,第一次运行时需要联网拉取以下三个镜像:
请添加图片描述

启动的服务默认端口是19530,包括以下三个docker容器:
请添加图片描述

分布式版安装

https://milvus.io/cn/docs/v2.0.0/install_cluster-docker.md

Python SDK

安装依赖

pip install pymilvus-orm==2.0.0rc4

官网说明最新版本需要python3.6以上,但实际测试,需要python3.8才能成功安装(主要是pandas的版本要求比较高)

连接milvus服务

from pymilvus_orm import connections, FieldSchema, CollectionSchema, DataType, Collection

# 连接milvus服务器
connections.connect(host='localhost', port='19530')

##创建collection

collection必须要有一个field是主键,一个field是存储向量,另外还可以创建其他类型的field

field_name = "example_field"


def create_collection():
    """
    创建集合collection
    :return:
    """
    collection_name = "example_collection"
    from pymilvus_orm import Collection, CollectionSchema, FieldSchema, DataType
    # 主键
    field_id = FieldSchema(name="field_id", dtype=DataType.INT64, is_primary=True, auto_id=True)
    # 向量检索的field
    field = FieldSchema(name=field_name, dtype=DataType.FLOAT_VECTOR, dim=8)
    cat_id = FieldSchema(name="cat_id", dtype=DataType.INT64)
    schema = CollectionSchema(fields=[field_id, field, cat_id], description="example collection")

    collection = Collection(name=collection_name, schema=schema)
    print(pymilvus_orm.utility.get_connection().has_collection(collection_name))
    print(pymilvus_orm.utility.get_connection().list_collections())

    return collection

collection还可以将数据存储在不同的分区。默认是有一个"Default partition"的分区,不指定分区的话,都会存储在default分区。

def create_partition(collection: Collection):
    """
    为collection创建分区
    :param collection:
    :return:
    """
    partition_name = "example_partition"
    partition = collection.create_partition(partition_name)

    print(collection.partitions)

    print(collection.has_partition(partition_name))

插入数据

插入数据可以根据实际需要,是否插入到特定的分区。

  1. 当前版本数据格式只能是list,numpy的ndarray也不行;
  2. 如果主键设置自增auto_id=True,则无需添加主键的值了;
  3. 数据插入之后,它是存储在内存中,还需要将其传输到磁盘中,下次可以继续使用。
def insert(collection: Collection, partition_name=None):
    """
    插入数据
    :param partition_name: 指定插入的分区
    :param collection:
    :return:
    """
    # 由于主键field_id设置自增,所以无需插入
    mr = collection.insert([
        # 只能是list
        np.random.random([10000, 8]).tolist(),  # 向量
        np.random.randint(0, 10, [10000]).tolist()  # cat_id
    ], partition_name=partition_name)
    print(mr.primary_keys)

    # 插入的数据存储在内存,需要传输到磁盘
    pymilvus_orm.utility.get_connection().flush([collection.name])

创建索引

为向量对应的field创建索引,目的就是实现高效的向量邻近搜索。

目前支持的索引类型包括:
请添加图片描述

def create_index(collection: Collection):
    """
    为向量检索的field 创建索引
    :param collection:
    :return:
    """
    index_param = {
        "metric_type": "L2",
        "index_type": "IVF_FLAT",
        "params": {"nlist": 1024}
    }
    collection.create_index(field_name=field_name, index_params=index_param)
    print(collection.index().params)

查询

除了一般的向量搜索,milvus还支持带表达式的标量过滤功能。

例如下方代码中,就增加expr="cat_id==2"条件:即只在cat_id为2的向量中进行检索(上面创建了名称为cat_id的field)。

但是目前还不支持字符串的过滤功能,官方后续会增加;

支持关系运算符(如==, >)、逻辑运算符(AND &&, OR ||)和IN运算符。

def search(collection: Collection, partition_name=None):
    """
    向量检索
    :param collection:
    :param partition_name: 检索指定分区的向量
    :return:
    """
    # 将collection加载到内存
    collection.load()
    search_params = {"metric_type": "L2", "params": {"nprobe": 10}}
    # 向量搜索
    result = collection.search(data=np.random.random([5, 8]).tolist(),
                               anns_field=field_name, param=search_params, limit=10,
                               partition_names=[partition_name] if partition_name else None)
    print(result[0].ids)
    print(result[0].distances)

    # 表达式:只检索cat_id为2的向量
    result = collection.search(data=np.random.random([5, 8]).tolist(),
                               anns_field=field_name, param=search_params, limit=10,
                               expr="cat_id==2")
    print(result[0].ids)
    print(result[0].distances)

删除数据

目前支持以下三种删除操作

def drop(collection: Collection):
    # 删除collection
    collection.drop()
    # 删除索引
    collection.drop_index()
    # 删除分区
    collection.drop_partition("partition_name")

释放

def release(collection: Collection = None):
    # 从内存中释放collection
    if collection:
        collection.release()

    # 断开与服务器的连接,释放资源
    connections.disconnect("default")

其他SDK

1.x版本支持:
请添加图片描述

2.x版本目前只有python,其他还在开发中

可视化管理

milvus的强大之处,还在于它提供了可视化的管理工具。

也是以docker的形式进行安装和启动:

docker run -p 8000:3000 -e HOST_URL=http://{ your machine IP }:8000 -e MILVUS_URL={your machine IP}:19530 milvusdb/milvus-insight:latest

注意:这里的IP不能写localhost,否则可能会出现连接问题。

  1. 查看load到内存的collection
    请添加图片描述

  2. 查看collection的结构和分区,还支持删除和导入操作
    请添加图片描述

请添加图片描述

  1. 在线向量检索

请添加图片描述

后续功能

其实,到这里,milvus已经足够强大,但他们还在持续支持许多强大的新功能。
请添加图片描述
请添加图片描述
请添加图片描述

GitHub 加速计划 / mi / milvus
28.68 K
2.76 K
下载
A cloud-native vector database, storage for next generation AI applications
最近提交(Master分支:3 个月前 )
1e76d2b9 Related to #37574 --------- Signed-off-by: Congqi Xia <congqi.xia@zilliz.com> 9 小时前
8c9dab5c Related to #37768 Signed-off-by: Congqi Xia <congqi.xia@zilliz.com> 12 小时前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐