跳到主要内容

将 Milvus 与 WhyHow 集成

本指南演示了如何使用 whyhow.ai 和 Milvus Lite 进行基于规则的检索。

概述

WhyHow 是一个平台,为开发者提供组织、上下文化和可靠检索非结构化数据所需的构建块,以执行复杂的 RAG。基于规则的检索包是由 WhyHow 开发的 Python 包,使人们能够创建和管理具有高级过滤功能的检索增强生成 (RAG) 应用程序。

安装

在开始之前,请安装后续使用所需的所有必要 Python 包。

pip install --upgrade pymilvus, whyhow_rbr

接下来,我们需要初始化 Milvus 客户端以使用 Milvus Lite 实现基于规则的检索。

from pymilvus import MilvusClient

# Milvus Lite 本地路径
path="./milvus_demo.db" # 本地 milvus lite 数据库路径的随机名称

# 初始化 ClientMilvus
milvus_client = ClientMilvus(path)

您也可以通过 Milvus Cloud 初始化 Milvus 客户端

from pymilvus import MilvusClient

# Milvus Cloud 凭据
YOUR_MILVUS_CLOUD_END_POINT = "YOUR_MILVUS_CLOUD_END_POINT"
YOUR_MILVUS_CLOUD_TOKEN = "YOUR_MILVUS_CLOUD_TOKEN"

# 初始化 ClientMilvus
milvus_client = ClientMilvus(
milvus_uri=YOUR_MILVUS_CLOUD_END_POINT,
milvus_token=YOUR_MILVUS_CLOUD_TOKEN,
)

创建 Collection

定义必要的变量

# 定义 collection 名称
COLLECTION_NAME="YOUR_COLLECTION_NAME" # 使用您自己的 collection 名称

# 定义向量维度大小
DIMENSION=1536 # 由您使用的模型决定

添加模式

在向 Milvus Lite 数据库插入任何数据之前,我们需要首先定义数据字段,这里称为模式。通过创建 CollectionSchema 对象并通过 add_field() 添加数据字段,我们可以控制数据类型及其特征。这一步骤在向 Milvus 插入任何数据之前是必须的。

schema = milvus_client.create_schema(auto_id=True) # 启用 id 匹配

schema = milvus_client.add_field(schema=schema, field_name="id", datatype=DataType.INT64, is_primary=True)
schema = milvus_client.add_field(schema=schema, field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=DIMENSION)

创建索引

对于每个模式,最好有一个索引,这样查询会更加高效。要创建索引,我们首先需要一个 index_params,然后在这个 IndexParams 对象上添加更多索引数据。

# 开始为数据字段建立索引
index_params = milvus_client.prepare_index_params()
index_params = milvus_client.add_index(
index_params=index_params, # 传入 index_params 对象
field_name="embedding",
index_type="AUTOINDEX", # 使用自动索引而不是其他复杂的索引方法
metric_type="COSINE", # L2、COSINE 或 IP
)

这个方法是官方 Milvus 实现的轻量级包装器(官方文档)。

创建 collection

在定义了所有数据字段并为它们建立索引后,我们现在需要创建数据库 collection,以便快速准确地访问数据。需要注意的是,我们将 enable_dynamic_field 初始化为 true,这样您可以自由上传任何数据。代价是数据查询可能效率较低。

# 创建 Collection
milvus_client.create_collection(
collection_name=COLLECTION_NAME,
schema=schema,
index_params=index_params
)

上传文档

创建 collection 后,我们准备用文档填充它。在 whyhow_rbr 中,这是通过 MilvusClientupload_documents 方法完成的。它在底层执行以下步骤:

  • 预处理:读取提供的 PDF 文件并将其拆分为块
  • 嵌入:使用 OpenAI 模型嵌入所有块
  • 插入:将嵌入和元数据上传到 Milvus Lite
# 获取 pdf 文件
pdfs = ["harry-potter.pdf", "game-of-thrones.pdf"] # 替换为您的 pdf 文件路径

# 上传 PDF 文档
milvus_client.upload_documents(
collection_name=COLLECTION_NAME,
documents=pdfs
)

问答

现在我们终于可以进行检索增强生成了。

# 搜索数据并实现 RAG!
res = milvus_client.search(
question='What food does Harry Potter like to eat?',
collection_name=COLLECTION_NAME,
anns_field='embedding',
output_fields='text'
)
print(res['answer'])
print(res['matches'])

规则

在前面的示例中,我们索引中的每一个文档都被考虑了。但是,有时候只检索满足某些预定义条件的文档可能是有益的(例如 filename=harry-potter.pdf)。在通过 Milvus Lite 的 whyhow_rbr 中,这可以通过调整搜索参数来实现。

规则可以控制以下元数据属性

  • filename 文件名称
  • page_numbers 对应页码的整数列表(0 索引)
  • id 块的唯一标识符(这是最"极端"的过滤器)
  • 其他基于布尔表达式的规则
# 规则(在第 8 页的哈利·波特书中搜索):
PARTITION_NAME='harry-potter' # 在书籍中搜索
page_number='page_number == 8'

# 首先创建一个分区来存储书籍,然后在这个特定分区中搜索:
milvus_client.crate_partition(
collection_name=COLLECTION_NAME,
partition_name=PARTITION_NAME # 根据您的 pdf 类型分离
)

# 使用规则搜索
res = milvus_client.search(
question='Tell me about the greedy method',
collection_name=COLLECTION_NAME,
partition_names=PARTITION_NAME,
filter=page_number, # 添加任何遵循布尔表达式规则的规则
anns_field='embedding',
output_fields='text'
)
print(res['answer'])
print(res['matches'])

在这个示例中,我们首先创建一个存储哈利·波特相关 pdf 的分区,通过在这个分区内搜索,我们可以获得最直接的信息。此外,我们将页码作为过滤器来指定我们希望搜索的确切页面。记住,过滤器参数需要遵循布尔规则

清理

最后,在实施所有指令后,您可以通过调用 drop_collection() 来清理数据库。

# 清理
milvus_client.drop_collection(
collection_name=COLLECTION_NAME
)