Milvus 实战 | 基于 Milvus 的 CORD-19 论文检索引擎
论文检索是指根据用户输入的信息从大量的论文集合中查找出相关文本的一种技术。论文检索作为信息检索的一种,常用于搜索引擎、数字图书馆等领域,是信息检索技术的一个重要组成部分。
本文将介绍如何基于 Milvus 实现针对 CORD-19 开放研究数据集的论文检索引擎。具体实现过程与源码请参考 Milvus 训练营 [1]。
| 关键技术
本文项目是在开源项目 COVID-19 Open Research Dataset Search [2] 的基础上,用 Milvus 向量检索引擎替换了原项目使用的算法库 hnswlib,来实现向量相似度检索。本项目主要使用了 Anserini 和 Milvus 两种关键技术。首先,用 Anserini 实现相关文章的检索,即从文档集合中找出包含输入关键词的文档。之后,再使用 Milvus 检索出与上一步中得到的文档相似的若干文档。
Anserini
Anserini 是基于 Lucene 构建的一个开源信息检索工具,用于信息检索的实践和研究。Anserini 在核心 Lucene 库之上提供了包和扩展,使研究人员和工程师可以使用更直观的 API 来完成常见的研究任务和实践。Anserini 最初的工作集中在以下三个功能上:
- 可扩展的多线程倒排索引,处理现代 Web 规模的集合;
- 简化的 IR 评估,对标准测试集合进行即时检索;
- 可扩展的体系结构。
Anserini 项目及其提供的 Python SDK 详见 Anserini [3] 和 Pyserini [4]。
Milvus
Milvus 是一款开源向量相似度搜索引擎,在开源不到一年的时间内已在全球拥有数百家企业或组织用户。Milvus 充分利用现代处理器的并行计算能力,可以在单台通用服务器上完成对十亿级数据的毫秒级搜索,助力用户高效检索非结构化数据。
Milvus 支持使用多种 AI 模型将非结构化数据向量化,并为向量数据提供搜索分析服务,可广泛应用于图像处理、机器视觉、自然语言处理、语音识别、推荐系统以及新药发现。具体实现方式是:
- 通过深度学习模型将非结构化数据转化为特征向量,并导入 Milvus 库。
- 对特征向量进行存储并建立索引。
- 接收到用户的向量搜索请求后,返回与输入向量相似的结果。
| 实现
本项目检索过程可以分为 Anserini Retrieval 和 Milvus Search 两个部分。Anserini Retrieval 会根据用户输入的查询语句,从底库中查找出包含该查询语句的文章。Milvus Search 会根据前一步查询到的文章所对应的向量,在库中找出与前一步输出文章近似的文章。
数据集说明
本项目所使用的数据来源于CORD-19 [5]。CORD-19 (COVID-19 Open Research Dataset) 是有关 COVID-19 和相关历史冠状病毒的研究论文数据集,原始数据集中包含了约 13 万篇有关新型冠状病毒的学术文章。本项目选取了 CORD-19 中的部分数据。
CORD-19 中的数据已经过优化处理,包括构建索引和将文章向量化。其中,论文数据使用了开放接口 paper-embedding-public-apis 来实现文章标题和摘要的向量化,详情可参考项目 paper-embedding-public-apis。
Anserini Retrieval
本项目中,首先使用 Anserini 在经过预构建索引的 lucene-index-cord19-paragraph 索引文件中,检索与查询语句相似的文档。其中考虑了 Article、Paragraph、Sentence 三个粒度下的检索,并且使用到 BM25 来评估搜索语句和文档之间的相关性。
使用 Anserini 检索后,可以访问其结果的 contents 和 raw。contents 表示索引的实际内容,raw 通常表示原始文档。对于 CORD-19 中的文章,raw 保留了文章的完整 JSON,既包括文章内容,也含有元数据和其他信息。contents 是从实际被索引的文章中摘录的内容,例如标题和摘要。本项目中,我们通过访问检索结果的 contents 取出被检索到的文档的摘要。
然后,取出前面检索到的与查询语句相似的文章,把这些文章划分为句子。将每篇文章中的句子与查询语句作比较,取出每篇文章中相似度得分最高的前 N 个句子;根据这 N 个句子的总得分重新评估每篇文章与查询语句的相似程度,得出最后的排序结果。
# Get search results from Lucene index.
from pyserini.search import pysearch
searcher = pysearch.SimpleSearcher(index_path)
searcher.set_bm25_similarity(0.4, 0.9)
hits = searcher.search(query)
# Get paragraph or abstract if original document was retrieved.
paragraphs = [hit.contents.split('n')[-1] for hit in searcher_hits]
# Get predictions from T5.
t5_scores = T5Reranker(model, batch_tokenizer)
Milvus Search
从原始数据中取出与上一步 Anserini 检索出来的文章对应的向量,然后将得到的向量在 Milvus 中进行向量相似度检索。本项目使用了欧氏距离来计算向量相似度,检索出相似度前 100 的向量。最后根据查找到的相似向量返回其对应的文章。
status, results = related_searcher.milvus.search(collection_name=related_searcher.collection_name, query_records=[source_vector], top_k=100, params=parameters)
labels = results.id_array
distances = results.distance_array
| 结果展示
下面将具体展示上述两个检索过程。
- 启动服务后,打开前端界面,输入一段话,点击 Search 进行查询。此查询对应的是 Anserini Retrieval 这一过程,查找包含输入语句关键词信息的文章。
- 在上图检索结果中,点击每篇文章左下角的 Show more,可以看到该文章更详细的内容。同时,对该文章中与查询语句相似的关键句做了高亮处理,并对查到的关键词做了加粗处理。如下图所示:
- 此外,每篇被检索出的文章下有一个 Related articles 链接,点击后能够检索出库中与该文章相似的文章,如下图所示。此步查询对应的是 Milvus Search 这一过程,即用 Milvus 实现相似文章检索。用户还可以继续通过每篇文章下的 Related articles 获取更多相似文章。
| 结语
本项目中,我们用 Milvus 替换了 COVID-19 Open Research Dataset Search 原始项目中的算法库 hnswlib。相对于原来仅使用一个算法库来实现向量相似度检索过程,基于 Milvus 的文章检索系统可以轻松扩展数据规模,实现数据迁移,管理与查看库中的数据。
本文介绍了基于 Milvus 实现的 CORD-19 开放研究数据集检索引擎,展示了 Milvus 在 NLP 领域的应用。Milvus 向量相似度检索引擎在其他领域还有更多的应用场景,详见 Milvus 应用场景 [6]。你可以使用 Milvus 探索更多用法!
参考资料:
[1] Milvus 训练营
https://github.com/milvus-io/bootcamp/tree/master/EN_solutions/covidex
[2] COVID-19 Open Research Dataset Search
https://github.com/castorini/covidex
[3] Anserini:https://github.com/castorini/anserini
[4] Pyserini:https://github.com/castorini/pyserini
[5] CORD-19
https://www.semanticscholar.org/cord19/download
[6] Milvus 应用场景:https://milvus.io/cn/scenarios
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- SQL Server 每日一题--重复报名的人解析
- 逻辑回归项目实战-附Python实现代码
- 详解C# 序列化和反序列化
- SQL Server 每日一题--解析只逛不买
- 【Python】基于某些列删除数据框中的重复值
- SQL Server 每日一题--解析天气预报员
- 未读消息(小红点),前端与 RabbitMQ实时消息推送实践,贼简单~
- 手把手教你用neo4j搭建简单关联图谱(基于家有儿女中的人物关系)
- c#中的静态本地方法
- C#加解密
- SQL Server 每日一题--解析老N的收入
- neo4j中导入数据的两种常用方式(千万级和亿级)
- Entity Framework Core 实现全局查询过滤
- Entity Framework Core 捕获数据库变动
- SQL Server 每日一题--解析产品