| 大家好,我是工藤学编程 🦉 | 一个正在努力学习的小博主,期待你的关注 |
|---|---|
| 实战代码系列最新文章😉 | C++实现图书管理系统(Qt C++ GUI界面版) |
| SpringBoot实战系列🐷 | 【SpringBoot实战系列】SpringBoot3.X 整合 MinIO 存储原生方案 |
| 分库分表 | 分库分表之实战-sharding-JDBC分库分表执行流程原理剖析 |
| 消息队列 | 深入浅出 RabbitMQ-RabbitMQ消息确认机制(ACK) |
| AI大模型 | 零基础学AI大模型之LangChain整合Milvus:新增与删除数据实战 |
前情摘要
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实战
33、零基础学AI大模型之Milvus向量Search查询综合案例实战
33、零基础学AI大模型之新版LangChain向量数据库VectorStore设计全解析
34、零基础学AI大模型之相似度Search与MMR最大边界相关搜索实战
35、零基础学AI大模型之LangChain整合Milvus:新增与删除数据实战
本文章目录
- 零基础学AI大模型之LangChain+Milvus实战:相似性搜索与MMR多样化检索全解析
-
- 一、实战核心目标
- 二、环境准备与基础配置
-
- [2.1 安装依赖](#2.1 安装依赖)
- [2.2 初始化配置](#2.2 初始化配置)
- [2.3 准备测试数据(含重复数据)](#2.3 准备测试数据(含重复数据))
- 三、相似性搜索实战(2种核心场景)
-
- [3.1 场景1:基础相似性搜索(无过滤)](#3.1 场景1:基础相似性搜索(无过滤))
- [3.2 场景2:带元数据过滤的相似性搜索](#3.2 场景2:带元数据过滤的相似性搜索)
- [3.3 相似性搜索关键参数解析](#3.3 相似性搜索关键参数解析)
- 四、MMR搜索实战(2种核心场景)
-
- [4.1 场景1:基础MMR搜索(平衡相关与多样)](#4.1 场景1:基础MMR搜索(平衡相关与多样))
- [4.2 场景2:带元数据过滤的MMR搜索](#4.2 场景2:带元数据过滤的MMR搜索)
- [4.3 MMR搜索关键参数解析](#4.3 MMR搜索关键参数解析)
- [五、相似性搜索 vs MMR搜索:结果对比(重复数据场景)](#五、相似性搜索 vs MMR搜索:结果对比(重复数据场景))
- 六、实战关键注意事项与避坑指南
- 七、常见问题排查
零基础学AI大模型之LangChain+Milvus实战:相似性搜索与MMR多样化检索全解析
一、实战核心目标
- 掌握LangChain+Milvus实现相似性搜索的两种场景(基础版+元数据过滤版)
- 精通MMR搜索的参数配置(k/fetch_k/lambda_mult)与调优逻辑
- 验证重复数据对两种搜索策略的影响(向量库不自动去重特性)
- 明确相似性搜索与MMR的适用场景与结果差异
- 实现RAG系统中"精准召回"与"多样化召回"的落地代码
二、环境准备与基础配置
2.1 安装依赖
确保已安装LangChain核心库、Milvus集成包和嵌入模型依赖:
bash
# 核心依赖
pip install langchain-core langchain-milvus
# 嵌入模型依赖(本文用DashScope,可替换为本地模型)
pip install dashscope
2.2 初始化配置
创建嵌入模型和Milvus VectorStore实例,后续所有检索操作基于此实例:
python
from langchain_milvus import Milvus
from langchain_core.documents import Document
from langchain_community.embeddings import DashScopeEmbeddings
# 1. 初始化嵌入模型(支持替换为SentenceTransformer、OpenAI等)
embeddings = DashScopeEmbeddings(
model="text-embedding-v2", # 通义千问嵌入模型(二代)
max_retries=3, # 失败重试次数
dashscope_api_key="你的API密钥" # 替换为自己的密钥,无密钥可换本地模型
)
# 2. 初始化Milvus VectorStore(自动创建集合)
vector_store = Milvus.from_documents(
documents=[], # 先创建空集合,后续手动插入数据(方便重复插入)
embedding=embeddings,
collection_name="langchain_mmr_demo", # 集合名称
connection_args={"uri": "http://192.168.229.128:19530"}, # 你的Milvus服务地址
drop_old=True # 启动时删除同名集合(测试环境专用)
)
print("Milvus VectorStore初始化成功!")
2.3 准备测试数据(含重复数据)
为了直观对比两种搜索策略的差异,我们手动构造4类核心文档,并重复插入3次(向量数据库不会自动去重,会保留重复记录),最终生成12条数据:
python
# 核心测试文档(工藤学编程相关内容,分4类主题)
core_documents = [
Document(
page_content="LangChain整合Milvus实现向量检索,工藤学编程实战教程",
metadata={"source": "gongtengxueshucheng.com/doc1", "category": "LangChain实战"}
),
Document(
page_content="RAG系统核心:相似性搜索与MMR多样化检索,工藤学编程原创解析",
metadata={"source": "gongtengxueshucheng.com/doc2", "category": "RAG技术"}
),
Document(
page_content="LangChain向量存储VectorStore设计原理,工藤学编程详解",
metadata={"source": "gongtengxueshucheng.com/doc3", "category": "LangChain核心"}
),
Document(
page_content="Milvus高性能向量搜索参数调优技巧,工藤学编程分享",
metadata={"source": "gongtengxueshucheng.com/doc4", "category": "Milvus优化"}
)
]
# 重复插入3次,制造重复数据(共12条记录)
for i in range(3):
vector_store.add_documents(documents=core_documents)
# 验证数据量
print(f"最终插入数据总量:{vector_store._collection.num_entities}") # 输出12,验证重复插入成功
三、相似性搜索实战(2种核心场景)
相似性搜索的核心是"召回最相关的结果",即使存在重复数据,也会优先返回相似度最高的条目(包括重复项),适合需要精准匹配的场景。
3.1 场景1:基础相似性搜索(无过滤)
根据查询文本的向量相似度,返回Top-K最相关的结果,不附加任何过滤条件:
python
# 定义查询(核心诉求:LangChain如何整合向量数据库)
query = "LangChain如何整合向量数据库实现检索?"
# 执行基础相似性搜索(返回前3条最相关结果)
similar_basic_results = vector_store.similarity_search(
query=query,
k=3 # 返回3条结果
)
# 解析并打印结果
print("=== 基础相似性搜索结果(无过滤)===")
for idx, doc in enumerate(similar_basic_results, 1):
print(f"\n第{idx}条:")
print(f"内容:{doc.page_content}")
print(f"元数据:{doc.metadata}")
# 结果说明:由于重复插入,可能会返回多条相同的doc1(相似度最高)
3.2 场景2:带元数据过滤的相似性搜索
在相似度匹配的基础上,通过元数据过滤(如category、source)筛选结果,实现"精准+定向"召回:
python
# 执行带过滤条件的相似性搜索(仅返回LangChain相关分类)
similar_filtered_results = vector_store.similarity_search(
query=query,
k=2, # 返回2条结果
filter='category == "LangChain实战" OR category == "LangChain核心"' # 多条件过滤
)
# 解析并打印结果
print("\n=== 带元数据过滤的相似性搜索结果 ===")
for idx, doc in enumerate(similar_filtered_results, 1):
print(f"\n第{idx}条:")
print(f"内容:{doc.page_content}")
print(f"元数据:{doc.metadata}")
# 结果说明:仅返回category为"LangChain实战"或"LangChain核心"的相关文档
3.3 相似性搜索关键参数解析
| 参数 | 作用说明 | 取值建议 |
|---|---|---|
| query | 检索查询文本(会自动转换为向量) | 明确业务诉求(如"XX如何实现") |
| k | 返回结果数量 | 3-10(过多易导致冗余) |
| filter | 元数据过滤条件(Milvus语法) | 结合业务维度(分类、来源等) |
四、MMR搜索实战(2种核心场景)
MMR(最大边界相关)搜索的核心是"平衡相关性与多样性",即使存在大量重复数据,也会优先选择不同主题的结果,避免内容冗余,适合需要多样化召回的场景(如推荐系统、知识发现)。
4.1 场景1:基础MMR搜索(平衡相关与多样)
通过lambda_mult参数调节相关性与多样性的权重,默认值0.5(完全平衡):
python
# 执行基础MMR搜索
mmr_basic_results = vector_store.max_marginal_relevance_search(
query=query,
k=3, # 最终返回3条结果
fetch_k=10, # 候选集大小(从10条中筛选,越大多样性越优)
lambda_mult=0.4, # 偏向多样性(0-1,越小越多样)
search_params={ # Milvus专属检索参数
"metric_type": "IP", # 内积相似度(适合嵌入向量)
"params": {"nprobe": 32} # IVF索引聚类访问数(平衡精度与速度)
}
)
# 解析并打印结果
print("\n=== 基础MMR搜索结果(偏向多样性)===")
for idx, doc in enumerate(mmr_basic_results, 1):
print(f"\n第{idx}条:")
print(f"内容:{doc.page_content}")
print(f"元数据:{doc.metadata}")
# 结果说明:不会返回重复文档,会覆盖LangChain、RAG、Milvus等多个相关主题
4.2 场景2:带元数据过滤的MMR搜索
结合元数据过滤和MMR算法,实现"定向+多样化"召回:
python
# 执行带过滤条件的MMR搜索(仅返回实战/技术类文档)
mmr_filtered_results = vector_store.max_marginal_relevance_search(
query=query,
k=2,
fetch_k=8,
lambda_mult=0.6, # 偏向相关性
filter='category in ["LangChain实战", "RAG技术", "Milvus优化"]', # IN语法过滤
search_params={"metric_type": "IP", "params": {"nprobe": 32}}
)
# 解析并打印结果
print("\n=== 带元数据过滤的MMR搜索结果(偏向相关性)===")
for idx, doc in enumerate(mmr_filtered_results, 1):
print(f"\n第{idx}条:")
print(f"内容:{doc.page_content}")
print(f"元数据:{doc.metadata}")
# 结果说明:仅在指定分类中选择,同时保证结果多样性(无重复主题)
4.3 MMR搜索关键参数解析
| 参数 | 作用说明 | 取值建议 |
|---|---|---|
| k | 最终返回结果数量 | 3-5(多样化场景无需过多) |
| fetch_k | 候选集大小(需大于k) | k的2-3倍(如k=3→fetch_k=8) |
| lambda_mult | 相关性与多样性权衡系数(0-1) | 偏向相关→0.6-0.8;偏向多样→0.2-0.4 |
| search_params | Milvus检索参数 | metric_type=IP(嵌入向量);nprobe=32-64 |
五、相似性搜索 vs MMR搜索:结果对比(重复数据场景)
通过重复数据场景的测试,两种搜索策略的差异一目了然,用表格总结核心区别:
| 对比维度 | 相似性搜索(Similarity) | MMR搜索(Maximal Marginal Relevance) |
|---|---|---|
| 结果多样性 | 低(易返回重复文档,聚焦单一主题) | 高(自动去重,覆盖多主题) |
| 相关性优先级 | 最高(仅按相似度排序) | 次高(平衡相关性与多样性) |
| 重复数据影响 | 受影响大(重复文档会多次出现) | 受影响小(自动过滤重复主题) |
| 适用场景 | 精准匹配(如文档查重、合规检测) | 多样化召回(如推荐系统、知识发现) |
| 计算成本 | 低(直接排序,无额外筛选) | 中(需候选集筛选,多一轮计算) |
可视化对比示例(基于本文测试数据)
| 搜索策略 | 返回结果(文档主题) | 核心特点 |
|---|---|---|
| 相似性搜索 | LangChain整合Milvus、LangChain整合Milvus、LangChain VectorStore | 重复+单一主题,相关性极强 |
| MMR搜索 | LangChain整合Milvus、RAG系统检索、Milvus参数调优 | 无重复+多主题,平衡相关与多样 |
六、实战关键注意事项与避坑指南
- 重复数据处理:向量数据库(如Milvus)不会自动去重,插入重复文档会生成多条记录------相似性搜索会返回重复结果,MMR会自动规避重复主题,但仍建议入库前手动去重(避免浪费存储)。
- 参数调优逻辑 :
- 追求精准→相似性搜索,k=3-5,无需调整其他参数;
- 追求多样→MMR搜索,lambda_mult=0.3-0.4,fetch_k=k*3。
- 嵌入模型一致性:检索时使用的嵌入模型必须与入库时一致,否则向量维度不匹配,会导致检索失败或结果不准确。
- 过滤条件语法 :两种搜索的
filter参数均遵循Milvus语法,字符串用单引号包裹,多条件用AND/OR/IN连接,避免语法错误。 - Milvus索引适配 :如果使用IVF类索引,
nprobe参数越大检索精度越高,但速度越慢;HNSW索引需调整ef参数(类似nprobe)。
七、常见问题排查
-
MMR搜索仍返回重复结果?
- 检查
fetch_k是否过小(建议至少为k的2倍); - 降低
lambda_mult参数(如从0.5改为0.3),增强多样性权重; - 确认文档主题是否真的多样(若所有文档都是同一主题,MMR也无法生成多样性结果)。
- 检查
-
相似性搜索结果不相关?
- 检查嵌入模型是否一致(入库和检索必须用同一模型);
- 优化查询文本(更明确的业务诉求,如"LangChain如何整合Milvus"而非"向量检索怎么做");
- 调整Milvus索引参数(nprobe增大,提升检索精度)。
-
过滤条件不生效?
- 检查元数据字段名是否与入库时一致(如"category"而非"Category",大小写敏感);
- 字符串值必须用单引号包裹(如
source == 'gongtengxueshucheng.com'); - 多条件过滤用
AND/OR连接,而非&&/||。
如果本文对你有帮助,欢迎点赞+关注,后续会持续输出AI大模型与LangChain的实战内容~