Milvus应用开发实战【语义搜索】

news2024/11/15 20:05:02

美国总统竞选活动即将到来。 现在是回顾拜登政府上任头两年的一些演讲的好时机。 搜索一些演讲记录以了解更多关于白宫迄今为止关于某些主题的信息不是很好吗?

假设我们要搜索演讲的内容。 我们该怎么做? 我们可以使用语义搜索。 语义搜索是目前人工智能 (AI) 中最热门的话题之一。 随着我们看到像 ChatGPT 这样的自然语言处理 (NLP) 应用程序越来越受欢迎,它变得越来越重要。 我们可以使用矢量数据库来缓存结果(例如使用 GPTCache),而不是重复 ping GPT,这在经济和生态上都是昂贵的。

在这里插入图片描述

推荐:用 NSDT设计器 快速搭建可编程3D场景。

在本教程中,我们将在本地启动一个矢量数据库,以便我们可以按内容搜索拜登从 2021 年到 2022 年的演讲。 我们使用“The White House (Speeches and Remarks) 12/10/2022”数据集,我们在 Kaggle 上找到了这个数据集,并且可以通过 Google Drive 下载这个例子。 GitHub 上提供了本教程的演练笔记本。

1、准备开发环境

在我们深入研究代码之前,请确保下载开发环境。 我们需要四个库:PyMilvus、Milvus、Sentence-Transformers 和 gdown。 可以通过运行以下命令从 PyPi 获取必要的库:

pip3 install pymilvus==2.2.5 sentence-transformers gdown milvus

2、准备白宫演讲数据集

与几乎所有基于真实世界数据集的人工智能/机器学习项目一样,我们首先需要准备数据。 我们使用 gdown 下载数据集并使用 zipfile 将其解压缩到本地文件夹中。 运行下面的代码后,我们希望在名为“white_house_2021_2022”的文件夹中看到一个名为“The white house speeches.csv”的文件。

import gdown
url = 'https://drive.google.com/uc?id=10_sVL0UmEog7mczLedK5s1pnlDOz3Ukf'
output = './white_house_2021_2022.zip'
gdown.download(url, output)
 
 
import zipfile
 
 
with zipfile.ZipFile("./white_house_2021_2022.zip","r") as zip_ref:
   zip_ref.extractall("./white_house_2021_2022")

我们使用 pandas 加载和检查 CSV 数据。

import pandas as pd
df = pd.read_csv("./white_house_2021_2022/The white house speeches.csv")
df.head()

查看数据头部时,你会注意到什么? 我注意到的第一件事是数据有四列:标题、日期和时间、位置和演讲。 第二件事是有空值。 空值并不总是一个问题,但它们适用于我们的数据。

在这里插入图片描述

3、清理数据集

没有任何实质内容的演讲(“演讲”列中的空值)对我们来说完全没有用。 让我们删除空值并重新检查数据。

df = df.dropna()
df

在这里插入图片描述

现在我们看到实际上还有第二个问题,仅从数据的头部来看并不是很明显。 如果查看最后一个条目,会发现它只是一个时间; “中午 12 点 18 分。 EST”几乎不是演讲。 保存此条目没有意义。 我们无法从保存向量嵌入中获得任何价值。

让我们去掉所有小于一定长度的演讲。 对于此示例,我选择了 50,但你可以选择对你有意义的任何值。 在探索了许多不同的数字后,我选择了 50。 如果你查找 20 到 50 个字符之间的演讲记录,你会看到很多地点或时间都带有一些随机句子。

cleaned_df = df.loc[(df["Speech"].str.len() > 50)]cleaned_df

处理完简短、无实质内容的演讲后,我们再次查看我们的数据并注意到另一个问题。 许多演讲都包含 \r\n 值——换行符和回车符。 这些字符用于格式化,但不包含任何语义值。 我们数据清理过程的下一步是摆脱这些。

cleaned_df["Speech"] = cleaned_df["Speech"].str.replace("\r\n", "")
cleaned_df

在这里插入图片描述

这样看起来好多了。 最后一步是将“Date_time”列转换为更好的格式,以便将其存储在我们的矢量数据库中,并与其他日期时间进行比较。 我们使用日期时间库将这种日期时间格式简单地转换为通用的 YYYY-MM-DD 格式。

import datetime
 
# Convert the 'date' column to datetime objects
cleaned_df["Date_time"] = pd.to_datetime(cleaned_df["Date_time"], format="%B %d, %Y")
 
cleaned_df

在这里插入图片描述

4、为语义搜索建立矢量数据库

我们的数据现在是干净的,可以使用了。 下一步是建立一个矢量数据库,以根据内容实际搜索演讲。 对于这个例子,我们使用 Milvus Lite,这是 Milvus 的精简版,你可以在没有 Docker、Kubernetes 或处理任何类型的 YAML 文件的情况下运行。

我们做的第一件事是定义一些常量。 我们需要一个集合名称(用于向量数据库)、嵌入向量中的维数、批量大小和一个定义搜索时希望接收多少结果的数字。 此示例使用 MiniLM L6 v2 句子转换器,它生成 384 维嵌入向量。

COLLECTION_NAME = "white_house_2021_2022"
DIMENSION = 384
BATCH_SIZE = 128
TOPK = 3

我们使用 Milvus 的 default_server。 然后我们使用 PyMilvus SDK 连接到我们本地的 Milvus 服务器。 如果我们的矢量数据库中有一个集合与我们之前定义的集合名称同名,我们将删除该集合以确保我们从空白开始。

from milvus import default_server
from pymilvus import connections, utility
 
 
default_server.start()
connections.connect(host="127.0.0.1", port=default_server.listen_port)
 
 
if utility.has_collection(COLLECTION_NAME):
   utility.drop_collection(COLLECTION_NAME)

与大多数其他数据库一样,我们需要一个模式来将数据加载到 Milvus 矢量数据库中。 首先,我们定义希望每个对象具有的数据字段。 幸好我们之前查看了数据。 我们使用五个数据字段,我们之前有四个列和一个 ID 列。 但是这一次,我们使用语音的向量嵌入而不是实际的文本。

from pymilvus import FieldSchema, CollectionSchema, DataType, Collection
 
 
# object should be inserted in the format of (title, date, location, speech embedding)
fields = [
   FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
   FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=500),
   FieldSchema(name="date", dtype=DataType.VARCHAR, max_length=100),
   FieldSchema(name="location", dtype=DataType.VARCHAR, max_length=200),
   FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=DIMENSION)
]
schema = CollectionSchema(fields=fields)
collection = Collection(name=COLLECTION_NAME, schema=schema)

在准备好将数据加载到矢量数据库之前,我们需要定义的最后一件事是索引。 有许多矢量索引和模式,但对于本例,我们使用具有 128 个簇的 IVF_FLAT 索引。 较大的应用程序通常使用超过 128 个集群,但无论如何我们只有略多于 600 个条目。 对于我们的距离,我们使用 L2 范数进行测量。 一旦我们定义了我们的索引参数,我们就在我们的集合中创建索引并加载它以供使用。

index_params = {
   "index_type": "IVF_FLAT",
   "metric_type": "L2",
   "params": {"nlist": 128},
}
collection.create_index(field_name="embedding", index_params=index_params)
collection.load()

5、从演讲中获取向量嵌入

到目前为止,我们所讨论的大部分内容都适用于几乎所有数据库。 我们清理了一些数据,启动了一个数据库实例并为我们的数据库定义了一个模式。 除了定义索引之外,我们还需要为矢量数据库做的另一件事是获取嵌入。

首先,我们得到句子转换器模型MiniLM L6 v2,如上所述。 然后我们创建一个函数,对数据执行转换并将其插入到集合中。 此函数获取一批数据,获取语音转录本的嵌入,创建一个要插入的对象并将其插入到集合中。

对于上下文,此函数执行批量更新。 在此示例中,我们一次批量插入 128 个条目。 我们在插入中所做的唯一数据转换是将演讲文本转换为嵌入。

from sentence_transformers import SentenceTransformer
 
 
transformer = SentenceTransformer('all-MiniLM-L6-v2')
 
 
# expects a list of (title, date, location, speech)
def embed_insert(data: list):
   embeddings = transformer.encode(data[3])
   ins = [
       data[0],
       data[1],
       data[2],
       [x for x in embeddings]
   ]
   collection.insert(ins)

6、填充矢量数据库

有了创建批量嵌入和插入的功能,我们就可以填充数据库了。 对于此示例,我们循环遍历数据框中的每一行并附加到我们用于批处理数据的列表列表中。 一旦我们达到批量大小,我们就会调用 embed_insert 函数并重置我们的批量。

如果在我们完成循环后数据批中有任何剩余数据,我们将嵌入并插入剩余数据。 最后,为了完成填充我们的矢量数据库,我们调用 flush 来确保数据库被更新和索引。

data_batch = [[], [], [], []]
 
 
for index, row in cleaned_df.iterrows():
   data_batch[0].append(row["Title"])
   data_batch[1].append(str(row["Date_time"]))
   data_batch[2].append(row["Location"])
   data_batch[3].append(row["Speech"])
   if len(data_batch[0]) % BATCH_SIZE == 0:
       embed_insert(data_batch)
       data_batch = [[], [], [], []]
 
 
# Embed and insert the remainder
if len(data_batch[0]) != 0:
   embed_insert(data_batch)
 
 
# Call a flush to index any unsealed segments.
collection.flush()

7、语义搜索白宫演讲

假设我有兴趣找到总统在国家可再生能源实验室 (NREL) 发表的关于可再生能源影响的演讲,以及美国副总统和加拿大总理发表的演讲。 我可以使用我们刚刚创建的矢量数据库找到 2021-2022 年白宫成员发表的最相似演讲的标题。

我们可以在我们的矢量数据库中搜索与我们的描述最相似的演讲。 然后,我们所要做的就是使用与获取语音嵌入相同的模型将描述转换为向量嵌入,然后搜索向量数据库。

一旦我们将描述转换为向量嵌入,我们就可以在我们的集合上使用搜索功能。 我们将嵌入作为搜索数据传入,传入我们要查找的字段,添加一些关于如何搜索的参数、结果数量限制和我们要返回的字段。 在此示例中,我们需要传递的搜索参数是度量类型,它必须与我们在创建索引时使用的类型(L2 范数)和我们要搜索的聚类数(将 nprobe 设置为 10)相同。

import time
search_terms = ["The President speaks about the impact of renewable energy at the National Renewable Energy Lab.", "The Vice President and the Prime Minister of Canada both speak."]
 
 
# Search the database based on input text
def embed_search(data):
   embeds = transformer.encode(data)
   return [x for x in embeds]
 
 
search_data = embed_search(search_terms)
 
 
start = time.time()
res = collection.search(
   data=search_data,  # Embeded search value
   anns_field="embedding",  # Search across embeddings
   param={"metric_type": "L2",
           "params": {"nprobe": 10}},
   limit = TOPK,  # Limit to top_k results per search
   output_fields=["title"]  # Include title field in result
)
end = time.time()
 
for hits_i, hits in enumerate(res):

当我们搜索这个例子中的句子时,我们希望看到如下图所示的输出。 这是一次成功的搜索,因为标题正是我们期望看到的。 第一个描述返回拜登总统在 NREL 发表的演讲的标题,第二个描述返回反映副总统卡马拉哈里斯和总理贾斯汀特鲁多的演讲的标题。
在这里插入图片描述

8、结束语

在本教程中,我们学习了如何使用向量数据库对拜登政府在 2022 年中期选举前发表的演讲进行语义搜索。 语义搜索让我们可以通过模糊来寻找语义相似的文本,而不仅仅是句法相似的文本。 这使我们能够搜索对演讲的一般描述,而不是根据特定的句子或引语搜索演讲。 对于我们大多数人来说,这使得寻找我们感兴趣的演讲变得更加容易。


原文链接:Milvus应用开发实战 — BimAnt

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【谷粒商城之分布式锁Redisson-lock】

本笔记内容为尚硅谷谷粒商城分布式锁Redisson-lock部分 目录 一、分布式锁与本地锁 二、分布式锁实现 使用 RedisTemplate 操作分布式锁 三、Redisson 完成分布式锁 1、简介 2、导入依赖 3、配置 4、使用 1.可重入锁 2.公平锁(Fair Lock) 3…

记录-VUE中常用的4种高级方法

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. provide/inject provide/inject 是 Vue.js 中用于跨组件传递数据的一种高级技术,它可以将数据注入到一个组件中,然后让它的所有子孙组件都可以访问到这个数据。通常情况下&a…

DC-8通关详解

信息收集 漏洞发现 找个扫描器扫一下 msf试了几个exp都没用 那么手动找找 发现传参nid出存在sql注入 python sqlmap -u "http://192.168.45.144:80/?nid1" --union-cols1 -D d7db -T users -C name,pass --columns --tables --dump 用john爆密码 admin爆了20分钟没…

为Linux系统添加一块新硬盘,并扩展根目录容量

我的原来ubuntu20.04系统装的时候不是LVM格式的分区, 所以先将新硬盘转成LVM,再将原来的系统dd到新硬盘,从新硬盘的分区启动,之后再将原来的分区转成LVM,在融入进来 1:将新硬盘制作成 LVM分区 我的新硬盘…

Python进阶

1.Json数据格式(用于不同语言的数据交互) 特定格式的字符串 第一种形式的Json ,转换成字典 第二种形式的Json,转换成字典列表 1.1 Python的Json转化 dumps 方法 Python转Json loads 方法 Json转Python 1.2 字典转json 需要…

Studio One6Mac中文免费版数字音乐工作站DAW

无论你是第一次接触数字音乐工作站(DAW),还是第一次尝试 制作属于自己的音乐,Studio One 都能给你非凡的体验!Studio One 6中文版是一款音乐制作软件,通过新的智能模板、直观的拖放工作流、可定制的用户界面…

C# 使用自带的组件PrintPreviewDialog 和 PrintDocument实现打印预览(一)

文章目录 前言相关内容了解打印预览功能1 创建winform工程2 创建要打印的测试数据3 绘制打印页绘制页脚绘制内容PrintPage事件 完整的代码工程小节 前言 有这么个需求:DataTable中有一些数据是需要给显示或直接可以连接打印机进行打印的, 查阅了一下资料…

jenkins共享ci阶段

jenkins共享ci阶段 需求 一个产品包含多个服务,这些服务的流水线都是类似的:制作制品构建并推送镜像构建并推送chart包触发自动部署。我们期望将流水线拆分为ci流水线、cd流水线,ci流水线包含:制作制品构建并推送镜像构建并推送…

蓝牙协议栈之L2CAP使用

目录 前言一、逻辑链路层及自适应协议层(L2CAP)二、常用的L2CAP术语三、L2CAP的工作模式四、L2CAP通道五、L2CAP帧类型六、Fragmentation/Recombination七、Segmentation/Reassembly八、L2CAP MTU九、Controller to Host Flow Control十、总结 前言 本文…

七个值得推荐的物联网分析平台

物联网分析平台是一种软件工具,可以帮助企业收集和分析来自其广泛的物联网设备的数据。企业可以通过物联网收集大量数据,从消费者支出模式到流量使用,物联网数据分析平台在帮助企业获得竞争优势所需的洞察力方面至关重要。 物联网分析平台已…

「2023 最新」 Github、Gitlab Git 工作流「常用」 git 命令、规范以及操作总结

Git commit 规范 关于提交信息的格式,可以遵循以下的规则: feat: 新特性,添加功能fix: 修改 bugrefactor: 代码重构docs: 文档修改style: 代码格式修改test: 测试用例修改chore: 其他修改, 比如构建流程, 依赖管理 Git 基础知识 当我们通过…

Midjourney生成LOGO指南

目录 常见的Logo 宠物店Logo Graphic Logo​ Lettermark Logo​ Geometric Logo​ Mascot Logo​ 增加风格——艺术运动​ 每个产品都有自己的专属名称,也有自己专属的Logo,经过前几篇的学习,我相信你也有了一定的基础,今天…

TiDB实战篇-PD调度常见问题处理方法

常见的问题 调度产生和执行 常见的调度类型 参数调度的速度 调度典型场景 Leader分布不均匀监控 leader分布算法,每一个leader的size作为总和,还有TiKV的剩余空间等等。 可以手动设置权重。 分布不均衡处理 TiKV节点下线速度慢 TiKV下线速度慢解决方法 …

一文说透IO多路复用select/poll/epoll

概述 如果我们要开发一个高并发的TCP程序。常规的做法是:多进程或者多线程。即:使用其中一个线程或者进程去监听有没有客户端连接上来,一旦有新客户端连接,就新开一个线程(进程),将其扔到线程(或进程&…

C++——类和对象[下]

0.关注博主有更多知识 C知识合集 目录 1.再谈构造函数 1.1初始化列表 1.2初始化列表的初始化顺序 1.3构造函数的隐式类型转换 1.4explicit关键字 2.static成员 2.1static成员变量 2.2static成员函数 3.友元 3.1友元函数 3.2友元类 4.内部类 5.匿名对象 6.编译器…

美颜sdk对于移动端视频直播的优化效果研究报告

随着移动互联网的快速发展,移动端视频直播应用也越来越受到用户的青睐。然而,对于许多用户来说,直播的画质却成为了一个令人头疼的问题。为了解决这个问题,许多直播应用开始引入美颜sdk,以期提升直播画质和用户体验。本…

凌思微-蓝牙框架-流程理解

1.蓝牙SOC芯片主函数流程 int main() { sys_init_app(); ble_init(); dev_manager_init(dev_manager_callback); gap_manager_init(gap_manager_callback); gatt_manager_init(gatt_manager_callback); rtos_init(); ble_task_init(); app_task_init(); vTaskStartScheduler();…

第8章:聚合函数

目录 一、常见的聚合函数 二、GROUP BY 的使用 三、HAVING 的使用,过滤数据 四、SQL底层的执行原理 五、练习 一、常见的聚合函数 1.概念 聚合函数作用于一组数据,并对一组数据返回一个值。 2.聚合函数的类型 AVG(),SUM(),MAX(),MIN(),COUNT() 3. AV…

【Spring篇】AOP

🍓系列专栏:Spring系列专栏 🍉个人主页:个人主页 目录 一、AOP简介 1.什么是AOP? 2.AOP作用 3.AOP核心概念 二、AOP入门案例 1.需求分析 2.思路分析 3.环境准备 4.AOP实现步骤 三、AOP工作流程 1.AOP工作流程 2.AOP核心概念 四、AOP配置管…

Python小姿势 - 1. Python的设计理念

Python的设计理念 Python的设计理念是“优雅”、“明确”、“简单”。 优雅:Python代码风格优美,语法简洁明了,代码可读性高,易于理解和维护。 明确:Python语言规范清晰,标准库丰富,可用于开发各…