如何使用Milvus构建向量检索系统:从入门到实践

本文将带你从零开始了解Milvus向量数据库,学会使用它构建高效的向量检索系统,适用于RAG、推荐系统、以图搜图等场景。

一、什么是Milvus

Milvus 是一款全球领先的开源向量数据库,专注于嵌入向量(Embedding Vector)的海量存储、索引与检索。它能够轻松应对十亿级向量规模的近似最近邻(ANN)检索需求。

核心特点

  • 高性能:毫秒级十亿向量检索
  • 分布式架构:支持水平扩展,轻松应对数据增长
  • 丰富的索引类型:支持 HNSW、IVF、DiskANN、SCANN 等多种索引
  • 多语言SDK:Python、Java、Go、Node.js 等
  • 云原生:支持 Kubernetes 部署和混合云架构
  • 开源生态:与 LangChain、LlamaIndex 等RAG框架深度集成

典型应用场景

  1. RAG(检索增强生成):为大语言模型提供准确的上下文知识
  2. 以图搜图:根据图片向量相似度搜索相似图片
  3. 推荐系统:基于用户/物品向量相似度进行推荐
  4. 语义搜索:超越关键词匹配的真正语义理解搜索
  5. 异常检测:通过向量距离识别异常模式

二、快速开始

环境要求

  • Docker & Docker Compose
  • Python 3.8+

1. 使用Docker快速部署

# 下载 docker-compose.yml
wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml -O docker-compose.yml

# 启动 Milvus 服务
docker compose up -d

启动后,Milvus服务默认监听在以下端口:

  • 19530:gRPC 端口(SDK 连接用)
  • 9091: metrics 端口(Prometheus 监控用)
  • 2379:etcd 端口
  • 9000:MinIO 端口(对象存储)

2. 安装Python SDK

pip install pymilvus

3. 连接Milvus

from pymilvus import MilvusClient

# 连接本地 Milvus
client = MilvusClient(uri="http://localhost:19530")

# 或使用Lite模式(无需部署服务器)
# client = MilvusClient("milvus_demo.db")

三、核心概念

在操作Milvus之前,需要了解几个核心概念:

概念 说明
Collection(集合) 相当于关系型数据库中的"表",是存储向量的基本单位
Entity(实体) Collection 中的一条记录/数据行
Field(字段) 实体中的具体字段,包含主键、向量、标量等
Index(索引) 用于加速向量检索的数据结构
Partition(分区) Collection 的逻辑分组,用于过滤和隔离数据
Vector(向量) 由Embedding模型生成的浮点数数组,代表数据的特征

四、实战:构建文档语义搜索

1. 创建集合

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost:19530")

# 检查并删除已存在的集合
if client.has_collection(collection_name="doc_search"):
    client.drop_collection(collection_name="doc_search")

# 创建集合
client.create_collection(
    collection_name="doc_search",
    dimension=768,  # 向量维度,这里使用 all-MiniLM-L6-v2 的输出维度
    metric_type="IP",  # 内积(余弦相似度)
    primary_field_name="id",
    auto_id=True,
    vector_field_name="embedding"
)

print("集合创建成功!")

2. 准备示例数据

# 模拟文档数据
documents = [
    "Milvus是一个开源的向量数据库,由Zilliz公司开发",
    "向量数据库专门用于存储和检索高维向量数据",
    "HNSW是一种高效的近似最近邻搜索算法",
    "RAG技术通过检索外部知识来增强大模型的生成能力",
    "嵌入模型可以将文本转换为固定维度的向量表示",
    "IVF索引通过将向量空间划分为多个簇来加速检索",
    "Milvus支持分布式部署,可以水平扩展",
    "相似度搜索可以应用于推荐系统和以图搜图",
]

# 使用 Sentence Transformers 生成向量
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("all-MiniLM-L6-v2")

# 将文档转换为向量
embeddings = model.encode(documents)
print(f"向量形状: {embeddings.shape}")  # (8, 768)

# 准备插入数据
data = [
    {"embedding": vec, "content": doc}
    for vec, doc in zip(embeddings, documents)
]

3. 插入数据

# 插入数据到集合
result = client.insert(
    collection_name="doc_search",
    data=data
)

print(f"成功插入 {result['insert_count']} 条数据")

4. 创建索引

# 创建 HNSW 索引
client.create_index(
    collection_name="doc_search",
    field_name="embedding",
    index_type="HNSW",
    metric_type="IP",
    index_params={
        "M": 16,        # 每个节点的最大连接数
        "efConstruction": 200  # 构建索引时的搜索范围
    }
)

# 加载集合到内存
client.load_collection(collection_name="doc_search")

print("索引创建并加载成功!")

5. 执行向量检索

# 查询:"什么是向量数据库?"
query_text = "什么是向量数据库?"
query_embedding = model.encode([query_text])

# 执行搜索
results = client.search(
    collection_name="doc_search",
    data=query_embedding,
    limit=3,  # 返回最相似的3条结果
    output_fields=["content"],  # 返回附加字段
    search_params={
        "metric_type": "IP",
        "params": {"ef": 100}  # 搜索时的搜索范围
    }
)

# 打印结果
print(f"\n查询: {query_text}")
print("-" * 50)
for i, hit in enumerate(results[0]):
    print(f"Top {i+1} - 相似度得分: {hit['distance']:.4f}")
    print(f"  内容: {hit['entity']['content']}")
    print()

6. 标量过滤

Milvus支持在向量检索的同时进行标量过滤:

# 假设我们有一个带分类字段的集合
results = client.search(
    collection_name="doc_search",
    data=query_embedding,
    filter='category == "技术"',  # 标量过滤条件
    limit=3,
    output_fields=["content", "category"],
    search_params={"metric_type": "IP", "params": {"ef": 100}}
)

五、高级用法

1. 使用不同的索引类型

# IVF_FLAT 索引 —— 适合精确度要求较高的场景
client.create_index(
    collection_name="doc_search",
    field_name="embedding",
    index_type="IVF_FLAT",
    metric_type="IP",
    index_params={"nlist": 1024}  # 聚类中心数量
)

# DISKANN 索引 —— 适合超大规模数据,基于磁盘的检索
client.create_index(
    collection_name="doc_search",
    field_name="embedding",
    index_type="DISKANN",
    metric_type="IP",
    index_params={
        "search_list_size": 100
    }
)

2. 稀疏向量检索

Milvus 2.4+ 支持稀疏向量(Sparse Vector),适用于 BM25 等稀疏嵌入场景:

from pymilvus import MilvusClient, DataType

client.create_collection(
    collection_name="hybrid_search",
    dimension=768,
    schema_fields=[
        MilvusClient.create_field_schema(
            name="dense_embedding",
            dtype=DataType.FLOAT_VECTOR,
            dimension=768
        ),
        MilvusClient.create_field_schema(
            name="sparse_embedding",
            dtype=DataType.SPARSE_FLOAT_VECTOR
        ),
        MilvusClient.create_field_schema(
            name="content",
            dtype=DataType.VARCHAR,
            max_length=65535
        )
    ]
)

3. 与 LangChain 集成

from langchain_community.vectorstores import Milvus
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

vector_store = Milvus.from_documents(
    documents=documents,
    embedding=embeddings,
    connection_args={"uri": "http://localhost:19530"},
    collection_name="langchain_docs"
)

docs = vector_store.similarity_search("Milvus是什么", k=3)
for doc in docs:
    print(doc.page_content)

六、性能调优建议

  1. 索引选择
  2. 数据量 < 100万:HNSW(构建快、查询快)
  3. 数据量 100万-1亿:IVF_FLAT 或 IVF_PQ
  4. 数据量 > 1亿:DISKANN(节省内存)

  5. 参数调优

  6. M 越大,精度越高但内存消耗越大(一般 16-64)
  7. efConstruction 越高,索引质量越好但构建时间越长
  8. ef 越高,搜索结果越精确但查询越慢

  9. 硬件建议

  10. 内存:至少 32GB(大规模数据建议 128GB+)
  11. SSD:建议使用 NVMe SSD 加速数据读写
  12. CPU:多核处理器有助于并行检索

七、总结

Milvus 作为一款专业的向量数据库,在AI应用场景中发挥着越来越重要的作用。从RAG到推荐系统,从以图搜图到异常检测,掌握Milvus的使用将为你构建AI应用提供强大的数据存储和检索能力。

学习资源


如果你有Milvus使用中的任何问题,欢迎在评论区交流讨论!