RAG开发中,如何用Milvus 2.5 BM25算法实现混合搜索

978adb9df7fb17d0fbb6e903f1cd2edf.png

93e94e828957d084a6757e1ea7266c0a.png

01.

背景

混合搜索(Hybrid Search)作为RAG应用中Retrieve重要的一环,通常指的是将向量搜索与基于关键词的搜索(全文检索)相结合,并使用RRF算法合并、并重排两种不同检索的结果,最终来提高数据的召回率。全文检索与语义检索不是非此即彼的关系。我们需要同时兼顾语义理解和精确的关键字匹配。比如学术论文的写作中,用户不仅希望在搜索结果看到与搜索查询相关的概念,同时也希望保留查询中使用的原始信息返回搜索结果,比如基于一些特殊术语和名称。因此,许多搜索应用正在采用混合搜索方法,结合两种方法的优势,以平衡灵活的语义相关性和可预测的精确关键字匹配。

从 Milvus 2.4 版本开始,我们引入了多向量搜索和执行混合搜索(多向量搜索)的能力。混合搜索允许用户同时搜索跨多个向量列的内容。这个功能使得可以结合多模态搜索、混合稀疏和全文关键词搜索、密集向量搜索以及混合密集和全文搜索,提供多样且灵活的搜索功能,增强了我们的向量相似性搜索和数据分析。

02.

Milvus BM25

在最新的Milvus 2.5里,我们带来了“全新”的全文检索能力

  • 对于全文检索基于的 BM25 算法,我们采用的是 Sparse-BM25,基于 Sparse Vector 实现的 BM25 在存储效率、检索性能上都打开了更多的空间,同时也融合在了 Milvus 以向量为核心检索范式的产品理念里;

  • 同时引入了原始文本插入和查询的能力,不需要用户手动将文本转成 Sparse Vector,这使得 Milvus 朝着非结构化数据处理的方向迈进了一步。

详情请参见 Milvus 2.5:全文检索上线,标量过滤提速,易用性再突破

Sparse-BM25 其原理类似 Elasticsearch 和其他全文搜索系统中常用的BM25算法,但针对稀疏向量设计,可以实现相同效果的全文搜索功能。

  • 具有数据剪枝功能的高效检索算法:通过剪枝来丢弃搜索查询中的低值稀疏向量,向量数据库可以显著减小索引大小并以最小的质量损失达成最优的性能。

  • 带来进一步的性能优化:将词频表示为稀疏向量而不是倒排索引,可以实现其他基于向量的优化。比如:用图索引替代暴力扫描,实现更有效的搜索;乘积量化(PQ)/标量量化(SQ),进一步减少内存占用。

详情请参见 Elasticsearch vs 向量数据库:寻找最佳混合检索方案

03.

Milvus BM25 Hybrid Search

1. 首先,准备数据和问题,数据来自Milvus 2.5 release notes,且通过llama-index的SentenceWindowNodeParser对于数据进行分块处理。

!wget https://raw.githubusercontent.com/milvus-io/milvus-docs/v2.5.x/site/en/release_notes.md -O milvus_2_5.md

documents = SimpleDirectoryReader(
        input_files=["./milvus_2_5.md"]
).load_data()

# Create the sentence window node parser 
node_parser = SentenceWindowNodeParser.from_defaults(
    window_size=3,
    window_metadata_key="window",
    original_text_metadata_key="original_text",
)

# Extract nodes from documents
nodes = node_parser.get_nodes_from_documents(documents)

# query question
query = "What are the key features in milvus 2.5?"

2. 其次,创建collection的schema以及索引,其中原始文本数据存于text列,而Sparse-BM25数据存于sparse_bm25列,这里需要通过转换Function来实现

bm25_function = Function(
        name="bm25",
        function_type=FunctionType.BM25,
        input_field_names=["text"],
        output_field_names="sparse_bm25",
    )
schema = MilvusClient.create_schema(
    auto_id=False,
    enable_dynamic_field=True,
)

# Add fields to schema
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=512, enable_analyzer=True)
schema.add_field(field_name="sparse_bm25", datatype=DataType.SPARSE_FLOAT_VECTOR)
schema.add_field(field_name="dense", datatype=DataType.FLOAT_VECTOR, dim=dense_dim)

bm25_function = Function(
        name="bm25",
        function_type=FunctionType.BM25,
        input_field_names=["text"],
        output_field_names="sparse_bm25",
    )
schema.add_function(bm25_function)

index_params = client.prepare_index_params()

# Add indexes
index_params.add_index(
    field_name="dense",
    index_name="dense_index",
    index_type="IVF_FLAT",
    metric_type="IP",
    params={"nlist": 128},
)

index_params.add_index(
    field_name="sparse_bm25",
    index_name="sparse_bm25_index",
    index_type="SPARSE_WAND", 
    metric_type="BM25"
)

# Create collection
client.create_collection(
    collection_name=collection_name,
    schema=schema,
    index_params=index_params
)

3. 然后,把数据进行Embedding之后,插入到Collection里,这里Embedding采用的是 OpenAI的 text-embedding-3-large

def gen_embedding(docs):
    model_name = "text-embedding-3-large"
    openai_ef = model.dense.OpenAIEmbeddingFunction(
        model_name=model_name, 
        api_key=os.environ["OPENAI_API_KEY"]
    )
    
    return openai_ef.encode_documents(docs)

docs_embeddings = gen_embedding(docs)
query_embeddings = gen_embedding([query])

# Assemble data
data = [
    {"id": idx, "dense": docs_embeddings[idx].data, "text": doc}
    for idx, doc in enumerate(docs)
]

# Insert data
res = client.insert(
    collection_name=collection_name,
    data=data
)

4. 最后,进行查询测试

4.1. 我们先测试下普通查询

search_params = {
        "metric_type": "IP",
        "params": {"nprobe": 10}
    }

res = client.search(
    collection_name=collection_name,
    data=[query_embeddings[0]],
    anns_field="dense",
    limit=5,
    search_params=search_params,
    output_fields=["text"]
)

查询结果

TopK results:
                                                                                                     0
0  Enhancements in cluster management, indexing, and data handling introduce new levels of flexibil...
1  With this release, Milvus integrates powerful new features like term-based search, clustering co...
2  Milvus 2.5 introduces a built-in Cluster Management WebUI, reducing system maintenance difficult...
3  \n\nv2.5.0-beta\n\nRelease date: November 26, 2024\n\n| Milvus version | Python SDK version | No...
4                                                 \n\nRelease Notes\n\nFind out what’s new in Milvus!

从查询结果来看,最后一条召回内容与查询问题相关度不大。

4.2. 然后进行Hybrid Search。定义向量搜索和Sparse-BM25搜索

k=5 # get the top 5 docs related to the query

search_params_dense: { "metric_type": "IP", "params": {"nprobe": 10}}
request_dense = AnnSearchRequest([query_embeddings[0].data], "dense", search_params_dense, limit=k)

search_params_bm25 = {"metric_type": "BM25"}
request_bm25 = AnnSearchRequest([query], "sparse_bm25", search_params_bm25, limit=k)

reqs = [request_dense, request_bm25]

这里使用RRFRanker来进行Hybrid Search

ranker = RRFRanker(100)

res = client.hybrid_search(
    collection_name=collection_name,
    reqs=reqs,
    ranker=ranker,
    limit=5,
    output_fields=["text"]
)
for hits in res:
    print("TopK results:")
    for hit in hits:
        print(hit)

查询结果:

TopK results:
                                                                                                     0
0  \n\nv2.5.0-beta\n\nRelease date: November 26, 2024\n\n| Milvus version | Python SDK version | No...
1  Enhancements in cluster management, indexing, and data handling introduce new levels of flexibil...
2  This feature is disabled by default in Milvus 2.5 and will be officially available in version 3....
3  With this release, Milvus integrates powerful new features like term-based search, clustering co...
4  Powered by Tantivy, Milvus 2.5 has built-in analyzers and sparse vector extraction, extending th...

从结果来看,基于Sparse-BM25的Hybrid Search可以准确找到与查询相关的内容。相对于普通查询,召回的内容准确度更大。

04.

总结

本文讲述了Milvus 2.5中引入的Sparse-BM25基础原理,以及如何利用BM25算法实现RAG开发中的Hybrid Search(混合搜索)实践。通过引入Sparse-BM25算法,Milvus能够在稀疏向量上执行高效的全文检索,并与密集向量搜索相结合,提升检索的召回率和精确度。

参考文档:

  • https://zilliz.com/blog/hybrid-search-with-milvus

  • https://milvus.io/docs/multi-vector-search.md

代码可通过链接获取:https://pan.baidu.com/s/1eArbrvqmkYTJ-DS8eDkbJA?pwd=1234 提取码: 1234

作者介绍

d3446255d7bd198ab10a167015641d96.jpeg

Zilliz 黄金写手:臧伟

推荐阅读

fb3d90dd4d68a73eb74d7ef3ac3a8971.png

560e5f378e592e8c1a4d7e8cdf0d3349.png

64743bc81432c36f6df5bf76c086a30d.png

802e235a127400cabe4a6a33fdc11a74.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/939010.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringAI人工智能开发框架002---SpringAI项目搭建_依赖导入_maven仓库引入_接口中转

然后看依赖.可以看到 看一下官网springAI的最新版本看到是0.8.1 这里我们用1.0.0这个最新的,快照版 1.0.0-snapshot 然后再来看,需要导入这个 spring-ai-openai-spring-boot-starter 这个依赖是openai的.

机器学习之偏差

机器学习中的偏差(Bias)是指模型的预测值与真实值之间的系统性误差,或者说模型无法准确捕捉数据中复杂模式的能力。偏差通常与模型的假设或学习能力有关,过高的偏差会导致模型的性能不佳,表现为欠拟合。 偏差的来源 模…

(css)鼠标移入或点击改变背景图片

(css)鼠标移入或点击改变背景图片 html <div class"mapTip"><divv-for"(item, index) of legendList":key"index"class"mapTipOne":class"{ active: change index }"click"legendHandle(item, index)"…

二、windows环境下vscode使用wsl教程

本篇文件介绍了在windows系统使用vscode如何连接使用wsl&#xff0c;方便wsl在vscode进行开发。 1、插件安装 双击桌面vscode&#xff0c;按快捷键CtrlShiftX打开插件市场&#xff0c;搜索【WSL】点击安装即可。 2、开启WSL的linux子系统 点击左下方图标【Open a Remote Win…

不同数据中心间海量数据的安全加密传输方案

安当TDE&#xff08;透明数据加密&#xff09;为实现不同数据中心间异地海量数据安全传输提供了一套高效且可靠的解决方案。以下是该解决方案的具体内容&#xff1a; 一、透明加密机制 安当TDE的核心在于其透明加密机制。在数据传输前&#xff0c;TDE能够自动对文件进行加密处…

前后端分离的项目使用nginx 解决 Invalid CORS request

我是这样打算的&#xff0c;前端用nginx代理&#xff0c;使用80 转443 端口走https 前端的地址就是http://yumbo.top 或https://yumbo.top 后端服务地址是&#xff1a;http://yumbo.top:8081 下面是我的完整配置&#xff0c;功能是正常的&#xff0c;加了注释 user nginx; …

边缘智能创新应用大赛获奖作品系列一:智能边缘计算✖软硬件一体化,开启全场景效能革命新征程

边缘智能技术快速迭代&#xff0c;并与行业深度融合。它正重塑产业格局&#xff0c;催生新产品、新体验&#xff0c;带动终端需求增长。为促进边缘智能技术的进步与发展&#xff0c;拓展开发者的思路与能力&#xff0c;挖掘边缘智能应用的创新与潜能&#xff0c;高通技术公司联…

【自动化】Python SeleniumUtil 工具 开启开发者模式 自动安装油猴用户脚本等

【自动化】Python SeleniumUtil 工具 【Python】使用Selenium 操作浏览器 自动化测试 记录-CSDN博客文章浏览阅读58次。文章浏览阅读42次。【附件】Selenium chromedriver 驱动及浏览器下载。【附件】Selenium chromedriver 驱动及浏览器下载-CSDN博客。3.安装Chrome浏览器驱动…

三、使用langchain搭建RAG:金融问答机器人--检索增强生成

经过前面2节数据准备后&#xff0c;现在来构建检索 加载向量数据库 from langchain.vectorstores import Chroma from langchain_huggingface import HuggingFaceEmbeddings import os# 定义 Embeddings embeddings HuggingFaceEmbeddings(model_name"m3e-base")#…

Springboot应用开发:工具类整理

目录 一、编写目的 二、映射工具类 2.1 依赖 2.2 代码 三、日期格式 3.1 依赖 3.2 代码 四、加密 4.1 代码 五、Http请求 5.1 依赖 5.2 代码 六、金额 6.1 代码 七、二维码 7.1 依赖 7.2 代码 八、坐标转换 8.1 代码 九、树结构 9.1 代码 9.1.1 节点 9.1…

【第一节】Git的简介和安装

目录 一、git的介绍 二、git 的安装 2.1 Linux 平台安装 2.2 源码安装 2.3 Windows 平台安装 2.4 Mac 平台安装 2.5 Git 配置 2.5.1 配置文件 2.5.2 用户信息配置 2.5.3 文本编辑器配置 2.5.4 差异分析工具配置 2.5.5 查看配置信息 一、git的介绍 Git 是一种开源的…

数据库和SQL的基本概念

目录 定义数据分类非结构化数据&#xff1a;半结构化数据 :​ 结构化数据 : SQL(Structured Query Language)概念分类 关系模型常用的概念数据库管理概念理解 定义 数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库。 数据库是长期储存在…

oneflow深度学习框架使用问题总结(Windows/Linux)

目录 1.简述 2.在Windows下使用Oneflow深度学习框架&#xff08;错误记录&#xff0c;谨慎&#xff0c;官方不支持&#xff0c;需要WSL&#xff09; 2.1安装Anaconda 2.1创建虚拟环境 2.2安装Pytorch 2.3安装Pycharm 2.4 安装Oneflow 3.在Linux下使用Oneflow深度学习框…

TypeScript 变量与常量

文章目录 一、变量声明(一)let 关键字(块级作用域)(二)var 关键字(函数级作用域,与 let 的区别)二、常量声明(一)const 关键字(不可重新赋值)一、变量声明 (一)let 关键字(块级作用域) 在 TypeScript 中,let 关键字用于声明变量,它所声明的变量具有块级作用…

【Go】-倒排索引的简单实现

目录 什么是倒排索引 定义 基本结构和原理 分词在倒排索引中的重要性 简单倒排索引的实现 接口定义 简单数据库的实现 倒排索引 正排索引 测试 总结 什么是倒排索引 定义 倒排索引&#xff08;Inverted Index&#xff09;是一种索引数据结构&#xff0c;它是文档检…

使用 Wireshark 和 Lua 脚本解析通讯报文

在复杂的网络环境中&#xff0c;Wireshark 凭借其强大的捕获和显示功能&#xff0c;成为协议分析不可或缺的工具。然而&#xff0c;面对众多未被内置支持的协议或需要扩展解析的场景&#xff0c;Lua 脚本的引入为Wireshark 提供了极大的灵活性和可扩展性。本文将详细介绍如何使…

黑马Java面试教程_P7_常见集合_P4_HashMap

系列博客目录 文章目录 系列博客目录4. HashMap相关面试题4.4 面试题-HashMap的put方法的具体流程 频54.4.1 hashMap常见属性4.4.2 源码分析 HashMap的构造函数面试文稿&#xff1a; 4.5 讲一讲HashMap的扩容机制 难3频4面试文稿&#xff1a; 4.6 面试题-hashMap的寻址算法 难4…

Netcat:网络中的瑞士军刀

免责声明&#xff1a;使用本教程或工具&#xff0c;用户必须遵守所有适用的法律和法规&#xff0c;并且用户应自行承担所有风险和责任。 文章目录 一、引言二、简述三、Netcat功能&#xff1f;四、参数选项五、Netcat 的常见功能六、高级用法多连接处理创建简单的代理 七、Netc…

这是一个vue3 + scss的数字滚动效果

介绍: 当数字变化时&#xff0c;只改变变化的数字位&#xff0c;其余的不变&#xff0c;可以递增、递减、骤变、负数也可以&#xff0c;但是样式要根据具体的项目需求去改&#xff1b; 效果1、增加数字&#xff1a; 效果2、减少数字&#xff1a; 使用方法&#xff1a; <te…

Pytest-Bdd vs Behave:选择最适合的 Python BDD 框架

Pytest-Bdd vs Behave&#xff1a;选择最适合的 Python BDD 框架 Pytest BDD vs Behave&#xff1a;选择最适合的 Python BDD 框架BDD 介绍Python BDD 框架列表Python BehavePytest BDDPytest BDD vs Behave&#xff1a;关键区别Pytest BDD vs Behave&#xff1a;最佳应用场景结…