| 大家好,我是工藤学编程 🦉 | 一个正在努力学习的小博主,期待你的关注 |
|---|---|
| 实战代码系列最新文章😉 | C++实现图书管理系统(Qt C++ GUI界面版) |
| SpringBoot实战系列🐷 | 【SpringBoot实战系列】SpringBoot3.X 整合 MinIO 存储原生方案 |
| 分库分表 | 分库分表之实战-sharding-JDBC分库分表执行流程原理剖析 |
| 消息队列 | 深入浅出 RabbitMQ-RabbitMQ消息确认机制(ACK) |
| AI大模型 | 零基础学AI大模型之Milvus DML实战 |
前情摘要
1、零基础学AI大模型之读懂AI大模型
2、零基础学AI大模型之从0到1调用大模型API
3、零基础学AI大模型之SpringAI
4、零基础学AI大模型之AI大模型常见概念
5、零基础学AI大模型之大模型私有化部署全指南
6、零基础学AI大模型之AI大模型可视化界面
7、零基础学AI大模型之LangChain
8、零基础学AI大模型之LangChain六大核心模块与大模型IO交互链路
9、零基础学AI大模型之Prompt提示词工程
10、零基础学AI大模型之LangChain-PromptTemplate
11、零基础学AI大模型之ChatModel聊天模型与ChatPromptTemplate实战
12、零基础学AI大模型之LangChain链
13、零基础学AI大模型之Stream流式输出实战
14、零基础学AI大模型之LangChain Output Parser
15、零基础学AI大模型之解析器PydanticOutputParser
16、零基础学AI大模型之大模型的"幻觉"
17、零基础学AI大模型之RAG技术
18、零基础学AI大模型之RAG系统链路解析与Document Loaders多案例实战
19、零基础学AI大模型之LangChain PyPDFLoader实战与PDF图片提取全解析
20、零基础学AI大模型之LangChain WebBaseLoader与Docx2txtLoader实战
21、零基础学AI大模型之RAG系统链路构建:文档切割转换全解析
22、零基础学AI大模型之LangChain 文本分割器实战:CharacterTextSplitter 与 RecursiveCharacterTextSplitter 全解析
23、零基础学AI大模型之Embedding与LLM大模型对比全解析
24、零基础学AI大模型之LangChain Embedding框架全解析
25、零基础学AI大模型之嵌入模型性能优化
26、零基础学AI大模型之向量数据库介绍与技术选型思考
27、零基础学AI大模型之Milvus向量数据库全解析
28、零基础学AI大模型之Milvus核心:分区-分片-段结构全解+最佳实践
29、零基础学AI大模型之Milvus部署架构选型+Linux实战:Docker一键部署+WebUI使用
30、零基础学AI大模型之Milvus实战:Attu可视化安装+Python整合全案例
31、零基础学AI大模型之Milvus索引实战
32、零基础学AI大模型之Milvus DML实战
本文章目录
- 零基础学AI大模型之Milvus向量Search查询综合案例实战
-
- 一、实战核心目标
- 二、Search语法深度解析
-
- [2.1 核心语法结构](#2.1 核心语法结构)
- [2.2 关键参数详解](#2.2 关键参数详解)
- 三、完整实战流程(MilvusClient方式)
-
- [3.1 环境准备](#3.1 环境准备)
- [3.2 步骤1:创建客户端与集合](#3.2 步骤1:创建客户端与集合)
- [3.3 步骤2:批量插入测试数据](#3.3 步骤2:批量插入测试数据)
- [3.4 步骤3:创建向量索引(提升查询效率)](#3.4 步骤3:创建向量索引(提升查询效率))
- [3.5 步骤4:加载集合到内存(查询前必须执行)](#3.5 步骤4:加载集合到内存(查询前必须执行))
- 四、多场景查询案例实战
-
- [4.1 场景1:基础向量查询(无过滤条件)](#4.1 场景1:基础向量查询(无过滤条件))
- [4.2 场景2:带过滤条件的混合查询(核心场景)](#4.2 场景2:带过滤条件的混合查询(核心场景))
- [4.3 场景3:分页查询(海量结果时使用)](#4.3 场景3:分页查询(海量结果时使用))
- [4.4 场景4:批量查询(多向量同时查询)](#4.4 场景4:批量查询(多向量同时查询))
- 五、集合与索引状态验证
- 六、Milvus新旧版本接口对比
- 七、实战关键注意事项
零基础学AI大模型之Milvus向量Search查询综合案例实战
一、实战核心目标
- 掌握混合数据类型(标量+向量)集合的创建方法
- 实现结构化+非结构化数据的批量插入
- 精通带过滤条件的向量混合查询(核心重点)
- 理解Milvus Search语法核心参数与使用场景
- 验证向量搜索端到端流程,适配RAG系统落地需求
二、Search语法深度解析
Milvus的Search接口是向量查询的核心,支持纯向量查询、标量过滤查询、批量查询等多种场景,先吃透语法和参数再动手实战更高效。
2.1 核心语法结构
python
results = client.search(
collection_name="集合名", # 目标集合(必须)
data=[[0.12, 0.23, ..., 0.88]], # 查询向量列表(必须)
anns_field="向量字段名", # 要搜索的向量字段(必须)
param={"metric_type": "L2", "params": {"nprobe": 10}}, # 搜索配置(必须)
limit=10, # 返回结果数量(默认10)
filter="price > 50", # 标量过滤条件(可选)
output_fields=["product_id", "price"], # 需要返回的标量字段(可选)
offset=0 # 分页偏移量(可选)
)
2.2 关键参数详解
- data:二维数组格式的查询向量列表,支持单向量和多向量批量查询。
- anns_field:必须与集合创建时定义的向量字段名一致,不可随意填写。
- param :搜索核心配置,包含距离度量类型和索引参数。
- metric_type:距离计算方式,常用L2(欧氏距离)、IP(内积)、COSINE(余弦相似度)。
- params:索引对应的参数,IVF类索引用nprobe(查询时遍历的聚类中心数),默认10。
- limit:返回匹配结果的数量,建议根据实际需求设置5-100,过多会影响查询效率。
- filter:标量过滤表达式,支持多条件组合(AND/OR),语法类似SQL。
- output_fields:指定需要返回的标量字段,不指定时仅返回主键和距离。
- offset:分页偏移量,配合limit实现分页查询,比如offset=2、limit=3表示查询第3-5条结果。
三、完整实战流程(MilvusClient方式)
本文采用MilvusClient新版接口(推荐生产使用),相比旧版更简洁、易维护,全程基于Python实现,可直接复制运行。
3.1 环境准备
首先确保已安装pymilvus库,若未安装执行以下命令:
bash
pip install pymilvus>=2.4.0
3.2 步骤1:创建客户端与集合
集合是Milvus存储数据的基本单元,需先定义字段结构(标量+向量),再创建集合。
python
from pymilvus import MilvusClient, FieldSchema, CollectionSchema, DataType
import random
# 1. 创建Milvus客户端(连接远程或本地Milvus服务)
client = MilvusClient(uri="http://192.168.229.128:19530") # 替换为你的Milvus地址
# 2. 避免重复创建,删除已存在的同名集合
if client.has_collection("book"):
client.drop_collection("book")
# 3. 定义字段结构(标量字段+向量字段)
fields = [
# 主键字段:自增ID,无需手动插入
FieldSchema(name="book_id", dtype=DataType.INT64, is_primary=True, auto_id=True),
# 标量字段:图书标题(字符串类型)
FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=200),
# 标量字段:图书分类(字符串类型)
FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=50),
# 标量字段:图书价格(浮点型)
FieldSchema(name="price", dtype=DataType.DOUBLE),
# 向量字段:图书简介的嵌入向量(4维,实际场景需根据嵌入模型调整维度)
FieldSchema(name="book_intro", dtype=DataType.FLOAT_VECTOR, dim=4)
]
# 4. 创建集合Schema
schema = CollectionSchema(
fields=fields,
description="用于图书搜索的混合类型集合(标量+向量)"
)
# 5. 最终创建集合
client.create_collection(collection_name="book", schema=schema)
print("集合创建成功!")
3.3 步骤2:批量插入测试数据
生成包含标量和向量的测试数据,批量插入集合,效率远高于单条插入。
python
# 1. 定义测试数据的基础配置
num_books = 1000 # 数据总量
categories = ["科幻", "科技", "文学", "历史"] # 图书分类选项
titles = ["量子世界", "AI简史", "时光之轮", "文明起源", "未来简史", "数据科学"] # 图书标题前缀
# 2. 生成1000条测试数据(字典列表格式,与字段名对应)
data = []
for i in range(num_books):
data.append({
"title": f"{random.choice(titles)}_{i}", # 标题+序号,避免重复
"category": random.choice(categories), # 随机分类
"price": round(random.uniform(10, 100), 2), # 10-100元随机价格,保留2位小数
"book_intro": [random.random() for _ in range(4)] # 4维随机向量(模拟嵌入结果)
})
# 3. 批量插入数据到集合
insert_result = client.insert(
collection_name="book",
data=data
)
# 4. 验证插入结果
print(f"成功插入数据量:{len(insert_result['ids'])}") # 输出插入的主键ID数量
3.4 步骤3:创建向量索引(提升查询效率)
向量索引是加速查询的关键,未创建索引时会执行全量扫描,效率极低。
python
# 1. 准备索引参数(针对向量字段book_intro)
index_params = MilvusClient.prepare_index_params()
# 2. 配置索引信息(IVF_FLAT索引,适合中小规模数据)
index_params.add_index(
field_name="book_intro", # 必须是向量字段
metric_type="L2", # 距离计算方式:欧氏距离
index_type="IVF_FLAT", # 索引类型,新手推荐IVF_FLAT
index_name="book_intro_index", # 索引名称(自定义)
params={"nlist": 128} # 聚类中心数,建议值为数据量的平方根(1000的平方根≈32,这里取128适配更多数据)
)
# 3. 创建索引
client.create_index(
collection_name="book",
index_params=index_params
)
print("向量索引创建完成!")
3.5 步骤4:加载集合到内存(查询前必须执行)
Milvus的查询操作需要先将集合加载到内存,加载后可多次查询,无需重复加载。
python
client.load_collection(collection_name="book")
print("集合已加载到内存,可执行查询操作!")
四、多场景查询案例实战
掌握基础流程后,通过4个核心场景实战,覆盖大部分实际使用需求。
4.1 场景1:基础向量查询(无过滤条件)
仅根据向量相似度查询,返回最匹配的结果。
python
# 1. 生成查询向量(4维,与集合向量字段维度一致)
query_vector = [random.random() for _ in range(4)]
# 2. 执行基础向量查询
basic_results = client.search(
collection_name="book",
data=[query_vector], # 单向量查询
anns_field="book_intro",
param={"metric_type": "L2", "params": {"nprobe": 10}},
limit=5, # 返回前5个最相似结果
output_fields=["title", "category", "price"] # 返回需要的标量字段
)
# 3. 解析并打印结果
print("\n=== 基础向量查询结果(前5条)===")
for idx, result in enumerate(basic_results[0]):
print(f"第{idx+1}条:")
print(f" 图书ID:{result['book_id']}")
print(f" 相似度距离:{result['distance']:.4f}") # 距离越小越相似
print(f" 图书标题:{result['entity']['title']}")
print(f" 分类:{result['entity']['category']}")
print(f" 价格:{result['entity']['price']:.2f}元")
print("-" * 40)
4.2 场景2:带过滤条件的混合查询(核心场景)
结合标量过滤+向量相似度,实现精准查询(如"科幻类+价格<50元"的相似图书)。
python
# 1. 复用之前的查询向量(也可重新生成)
# 2. 执行混合查询:科幻类 + 价格<50元 + 向量相似
mixed_results = client.search(
collection_name="book",
data=[query_vector],
anns_field="book_intro",
param={"metric_type": "L2", "params": {"nprobe": 10}},
filter="category == '科幻' and price < 50", # 多条件过滤(AND连接)
limit=3, # 返回前3条匹配结果
output_fields=["title", "category", "price"]
)
# 3. 解析结果
print("\n=== 混合查询结果(科幻类+价格<50元)===")
for idx, result in enumerate(mixed_results[0]):
print(f"第{idx+1}条:")
print(f" 图书ID:{result['book_id']}")
print(f" 相似度距离:{result['distance']:.4f}")
print(f" 图书标题:{result['entity']['title']}")
print(f" 分类:{result['entity']['category']}")
print(f" 价格:{result['entity']['price']:.2f}元")
print("-" * 40)
4.3 场景3:分页查询(海量结果时使用)
当匹配结果过多时,通过offset+limit实现分页,避免一次性返回大量数据。
python
# 执行分页查询:跳过前2条,返回接下来的3条
page_results = client.search(
collection_name="book",
data=[query_vector],
anns_field="book_intro",
param={"metric_type": "L2", "params": {"nprobe": 10}},
filter="category == '科技'", # 过滤科技类图书
offset=2, # 跳过前2条结果
limit=3, # 返回3条结果(第3-5条)
output_fields=["title", "category", "price"]
)
# 解析结果
print("\n=== 分页查询结果(科技类,第3-5条)===")
for idx, result in enumerate(page_results[0]):
print(f"第{idx+1}条(总第{idx+3}条):")
print(f" 图书ID:{result['book_id']}")
print(f" 相似度距离:{result['distance']:.4f}")
print(f" 图书标题:{result['entity']['title']}")
print(f" 价格:{result['entity']['price']:.2f}元")
print("-" * 40)
4.4 场景4:批量查询(多向量同时查询)
支持一次性传入多个查询向量,每个向量独立返回匹配结果,效率更高。
python
# 1. 生成2个查询向量
batch_query_vectors = [
query_vector, # 复用之前的向量
[0.5, 0.5, 0.5, 0.5] # 自定义向量
]
# 2. 执行批量查询:2个向量各返回2条结果
batch_results = client.search(
collection_name="book",
data=batch_query_vectors, # 多向量批量查询
anns_field="book_intro",
param={"metric_type": "L2", "params": {"nprobe": 10}},
limit=2, # 每个向量返回2条结果
output_fields=["title", "category"]
)
# 3. 解析结果(batch_results与查询向量一一对应)
print("\n=== 批量查询结果 ===")
for vec_idx, vec_results in enumerate(batch_results):
print(f"\n查询向量{vec_idx+1}的匹配结果:")
for res_idx, result in enumerate(vec_results):
print(f" 第{res_idx+1}条:")
print(f" 图书ID:{result['book_id']}")
print(f" 相似度距离:{result['distance']:.4f}")
print(f" 图书标题:{result['entity']['title']}")
print(f" 分类:{result['entity']['category']}")
五、集合与索引状态验证
查询完成后,可通过以下方法验证集合和索引的状态,确保后续操作正常。
python
# 1. 查看集合详情(字段、数据量等)
collection_info = client.describe_collection("book")
print("\n=== 集合详情 ===")
print(f"集合名称:{collection_info['collection_name']}")
print(f"字段数量:{len(collection_info['fields'])}")
print(f"数据量:{collection_info['num_entities']}")
# 2. 查看索引列表
index_list = client.list_indexes("book")
print("\n=== 索引列表 ===")
for index in index_list:
print(f"索引名称:{index['index_name']}")
print(f"关联字段:{index['field_name']}")
print(f"索引类型:{index['index_type']}")
# 3. 卸载集合(释放内存,无需查询时执行)
client.release_collection(collection_name="book")
print("\n集合已卸载,内存已释放!")
六、Milvus新旧版本接口对比
很多开发者可能接触过旧版PyMilvus接口,这里整理核心差异,方便快速迁移。
| 功能 | PyMilvus旧版(<2.3) | MilvusClient新版(≥2.4) |
|---|---|---|
| 连接管理 | 需要手动调用connections.connect() | 客户端自动管理,创建时传入uri即可 |
| 数据插入格式 | 多列表结构(如ids=[], titles=[]) | 字典列表格式(更直观,与字段名对应) |
| 字段定义 | 需单独创建FieldSchema和CollectionSchema | 可直接在create_collection中定义(简化) |
| 返回结果格式 | 自定义对象,需通过属性访问(如res.id) | 标准化字典格式,键值对访问(更易用) |
| 错误处理 | 需捕获特定异常类 | 统一错误码系统,排查更高效 |
| 动态字段支持 | 需要额外配置schema | 开启参数即可支持,无需修改schema |
推荐:新项目直接使用MilvusClient新版接口,旧项目逐步迁移,开发效率和维护性更优。
七、实战关键注意事项
- 向量维度必须一致:查询向量的维度需与集合向量字段的dim完全一致,否则会报错。
- 索引参数匹配:nprobe(查询聚类中心数)越大,查询精度越高但速度越慢,需根据数据量平衡(建议10-100)。
- 过滤条件语法:filter参数支持=、!=、>、<、>=、<=、IN等运算符,多条件用AND/OR连接,字符串需用单引号包裹。
- 集合加载:加载集合是重量级操作,避免频繁加载/卸载,建议长期查询时保持加载状态。
- 数据量适配:IVF_FLAT索引适合100万条以下数据,更大数据量可选择IVF_SQ8、HNSW等索引。
如果本文对你有帮助,欢迎点赞+关注,后续会持续输出AI大模型与向量数据库的实战内容~
