本笔记本适用于以下场景:

  • 您的数据未进行向量化
  • 您希望在数据上运行混合搜索(了解更多
  • 您希望使用 Weaviate 和 OpenAI 模块(text2vec-openai)为您生成向量嵌入。

本笔记本将引导您完成设置 Weaviate 实例、连接到它(使用 OpenAI API 密钥)、配置数据模式、导入数据(这将自动为您的数据生成向量嵌入)以及运行混合搜索(向量搜索和 BM25 搜索的混合)的简单流程。

这是客户在安全环境中存储和搜索嵌入以及他们自己的数据以支持生产用例(如聊天机器人、主题建模等)的常见需求。

什么是 Weaviate

Weaviate 是一个开源向量搜索引擎,它将数据对象与其向量一起存储。这允许将向量搜索与结构化过滤相结合。

Weaviate 使用 KNN 算法创建向量优化索引,使您的查询运行速度极快。在此处了解更多信息(here)。

Weaviate 让您可以使用最喜欢的 ML 模型,并无缝扩展到数十亿个数据对象。

部署选项

无论您的场景或生产设置如何,Weaviate 都有适合您的选项。您可以在以下设置中部署 Weaviate:

  • 自我托管 – 您可以使用 docker 在本地或任何您想要的服务器上部署 Weaviate。
  • SaaS – 您可以使用 Weaviate Cloud Service (WCS) 来托管您的 Weaviate 实例。
  • 混合 SaaS – 您可以将 Weaviate 部署在您自己的私有云服务中

编程语言

Weaviate 提供四种客户端库,允许您从应用程序与 Weaviate 进行通信:

此外,Weaviate 还具有一个REST 层。基本上,您可以从任何支持 REST 请求的语言调用 Weaviate。

演示流程

演示流程是:

  • 先决条件设置:创建 Weaviate 实例并安装所需的库
  • 连接:连接到您的 Weaviate 实例
  • 模式配置:配置数据模式
    • 注意:在这里我们可以定义使用哪个 OpenAI 嵌入模型
    • 注意:在这里我们可以配置要索引的属性
  • 导入数据:加载演示数据集并将其导入 Weaviate
    • 注意:导入过程将自动索引您的数据 - 基于模式中的配置
    • 注意:您无需显式向量化数据,Weaviate 将与 OpenAI 通信为您完成此操作
  • 运行查询:查询
    • 注意:您无需显式向量化查询,Weaviate 将与 OpenAI 通信为您完成此操作

运行完此笔记本后,您应该对如何设置和使用向量数据库有一个基本的了解,然后可以继续处理更复杂的用例,利用我们的嵌入。

Weaviate 中的 OpenAI 模块

所有 Weaviate 实例都配备了 text2vec-openai 模块。

此模块负责在导入(或任何 CRUD 操作)期间以及运行查询时处理向量化。

无需手动向量化数据

这对您来说是个好消息。使用 text2vec-openai,您无需手动向量化数据,因为 Weaviate 会在需要时为您调用 OpenAI。

您需要做的就是:

  1. 在连接到 Weaviate 客户端时提供您的 OpenAI API 密钥
  2. 在模式中定义要使用的 OpenAI 向量化器

先决条件

在我们开始这个项目之前,我们需要设置以下内容:

  • 创建一个 Weaviate 实例
  • 安装库
    • weaviate-client
    • datasets
    • apache-beam
  • 获取您的 OpenAI API 密钥

===========================================================

创建 Weaviate 实例

要创建 Weaviate 实例,我们有两种选择:

  1. (推荐路径)Weaviate Cloud Service – 在云中托管您的 Weaviate 实例。免费沙盒应该足以满足此食谱的需求。
  2. 使用 Docker 在本地安装和运行 Weaviate。

选项 1 – WCS 安装步骤

使用 Weaviate Cloud Service (WCS) 创建免费的 Weaviate 集群。

  1. 创建一个免费帐户和/或登录 WCS
  2. 创建一个 Weaviate Cluster 并进行以下设置:
    • 沙盒:Sandbox Free
    • Weaviate 版本:使用默认值(最新)
    • OIDC 身份验证:Disabled
  3. 您的实例应该在一两分钟内准备就绪
  4. 记下 Cluster Id。该链接将带您进入集群的完整路径(稍后您需要它来连接)。它应该类似于:https://your-project-name.weaviate.network

选项 2 – 使用 Docker 的本地 Weaviate 实例

使用 Docker 在本地安装和运行 Weaviate。

  1. 下载 ./docker-compose.yml 文件
  2. 然后打开您的终端,导航到您的 docker-compose.yml 文件所在的位置,然后使用以下命令启动 docker:docker-compose up -d
  3. 一旦准备就绪,您的实例应该可以在 http://localhost:8080 访问

注意。要关闭您的 docker 实例,您可以调用:docker-compose down

了解更多

要了解更多关于在 Docker 中使用 Weaviate 的信息,请参阅安装文档

===========================================================

安装所需的库

在运行此项目之前,请确保拥有以下库:

Weaviate Python 客户端

Weaviate Python 客户端允许您从 Python 项目与 Weaviate 实例进行通信。

datasets & apache-beam

要加载示例数据,您需要 datasets 库及其依赖项 apache-beam

# 安装用于 Python 的 Weaviate 客户端
!pip install weaviate-client>3.11.0

# 安装 datasets 和 apache-beam 以加载示例数据集
!pip install datasets apache-beam

===========================================================

准备您的 OpenAI API 密钥

OpenAI API 密钥 用于导入时的数据向量化以及运行查询。

如果您没有 OpenAI API 密钥,可以从 https://beta.openai.com/account/api-keys 获取。

获取密钥后,请将其添加到您的环境变量中,名为 OPENAI_API_KEY

# 导出 OpenAI API 密钥
!export OPENAI_API_KEY="your key"
# 测试您的 OpenAI API 密钥是否已正确设置为环境变量
# 注意。如果您在本地运行此笔记本,则需要重新加载您的终端和笔记本才能使环境变量生效。
import os

# 注意。或者,您可以像这样设置一个临时环境变量:
# os.environ['OPENAI_API_KEY'] = 'your-key-goes-here'

if os.getenv("OPENAI_API_KEY") is not None:
    print ("OPENAI_API_KEY is ready")
else:
    print ("OPENAI_API_KEY environment variable not found")

连接到您的 Weaviate 实例

在本节中,我们将:

  1. 测试环境变量 OPENAI_API_KEY请确保您已完成 #Prepare-your-OpenAI-API-key 中的步骤
  2. 使用您的 OpenAI API Key 连接到您的 Weaviate
  3. 并测试客户端连接

客户端

在此步骤之后,client 对象将用于执行所有与 Weaviate 相关的操作。

import weaviate
from datasets import load_dataset
import os

# 连接到您的 Weaviate 实例
client = weaviate.Client(
    url="https://your-wcs-instance-name.weaviate.network/",
#   url="http://localhost:8080/",
    auth_client_secret=weaviate.auth.AuthApiKey(api_key="<YOUR-WEAVIATE-API-KEY>"), # 如果您没有为 Weaviate 实例使用身份验证(例如,本地部署的实例),请注释掉此行
    additional_headers={
        "X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
    }
)

# 检查您的实例是否正在运行并准备就绪
# 这应该返回 `True`
client.is_ready()

模式

在本节中,我们将:

  1. 配置数据模式
  2. 选择 OpenAI 模块

这是第二步也是最后一步,需要 OpenAI 特定的配置。 在此步骤之后,其余说明将仅涉及 Weaviate,因为 OpenAI 任务将自动处理。

什么是模式

在 Weaviate 中,您创建__模式__来捕获您将要搜索的每个实体。

模式是您告诉 Weaviate 的方式:

  • 应使用哪个 OpenAI 嵌入模型来向量化数据
  • 您的数据由什么组成(属性名称和类型)
  • 哪些属性应被向量化和索引

在此食谱中,我们将使用 Articles 数据集,其中包含:

  • title
  • content
  • url

我们希望向量化 titlecontent,但不向量化 url

为了向量化和查询数据,我们将使用 text-embedding-3-small

# 清除模式,以便我们可以重新创建它
client.schema.delete_all()
client.schema.get()

# 定义模式对象以在 `title` 和 `content` 上使用 `text-embedding-3-small`,但跳过 `url`
article_schema = {
    "class": "Article",
    "description": "A collection of articles",
    "vectorizer": "text2vec-openai",
    "moduleConfig": {
        "text2vec-openai": {
          "model": "ada",
          "modelVersion": "002",
          "type": "text"
        }
    },
    "properties": [{
        "name": "title",
        "description": "Title of the article",
        "dataType": ["string"]
    },
    {
        "name": "content",
        "description": "Contents of the article",
        "dataType": ["text"]
    },
    {
        "name": "url",
        "description": "URL to the article",
        "dataType": ["string"],
        "moduleConfig": { "text2vec-openai": { "skip": True } }
    }]
}

# 添加 Article 模式
client.schema.create_class(article_schema)

# 获取模式以确保其正常工作
client.schema.get()

导入数据

在本节中,我们将:

  1. 加载 Simple Wikipedia 数据集
  2. 配置 Weaviate 批量导入(以提高导入效率)
  3. 将数据导入 Weaviate

注意:
如前所述。我们无需手动向量化数据。
text2vec-openai 模块将负责处理此问题。

### 步骤 1 - 加载数据集

from datasets import load_dataset
from typing import List, Iterator

# 我们将使用 datasets 库来提取 Simple Wikipedia 数据集进行嵌入
dataset = list(load_dataset("wikipedia", "20220301.simple")["train"])

# 出于测试目的,限制为 2.5k 篇文章
dataset = dataset[:2_500]

# 限制为 25k 篇文章,用于更大的演示目的
# dataset = dataset[:25_000]

# 对于免费的 OpenAI 账户,您可以使用 50 个对象
# dataset = dataset[:50]
### 步骤 2 - 配置 Weaviate 批量导入,具有
# - 起始批量大小为 100
# - 根据性能动态增加/减少
# - 添加超时重试以防万一出现问题

client.batch.configure(
    batch_size=10,
    dynamic=True,
    timeout_retries=3,
#   callback=None,
)
### 步骤 3 - 导入数据

print("正在导入文章")

counter=0

with client.batch as batch:
    for article in dataset:
        if (counter %10 == 0):
            print(f"正在导入 {counter} / {len(dataset)} ")

        properties = {
            "title": article["title"],
            "content": article["text"],
            "url": article["url"]
        }

        batch.add_data_object(properties, "Article")
        counter = counter+1

print("文章导入完成")
# 测试所有数据是否已加载 – 获取对象计数
result = (
    client.query.aggregate("Article")
    .with_fields("meta { count }")
    .do()
)
print("对象计数: ", result["data"]["Aggregate"]["Article"], "\n")
# 通过检查一个对象来测试一篇文章是否成功
test_article = (
    client.query
    .get("Article", ["title", "url", "content"])
    .with_limit(1)
    .do()
)["data"]["Get"]["Article"][0]

print(test_article['title'])
print(test_article['url'])
print(test_article['content'])

搜索数据

如上所述,我们将向新索引发送一些查询,并根据与现有向量的接近程度获得结果

在此处了解有关 alpha 设置的更多信息(here

def hybrid_query_weaviate(query, collection_name, alpha_val):

    nearText = {
        "concepts": [query],
        "distance": 0.7,
    }

    properties = [
        "title", "content", "url",
        "_additional { score }"
    ]

    result = (
        client.query
        .get(collection_name, properties)
        .with_hybrid(nearText, alpha=alpha_val)
        .with_limit(10)
        .do()
    )

    # 检查错误
    if ("errors" in result):
        print ("\033[91m您可能已经用完了当前分钟的 OpenAI API 调用次数 – 限额为每分钟 60 次。")
        raise Exception(result["errors"][0]['message'])

    return result["data"]["Get"][collection_name]
query_result = hybrid_query_weaviate("modern art in Europe", "Article", 0.5)

for i, article in enumerate(query_result):
    print(f"{i+1}. { article['title']} (Score: {article['_additional']['score']})")
query_result = hybrid_query_weaviate("Famous battles in Scottish history", "Article", 0.5)

for i, article in enumerate(query_result):
    print(f"{i+1}. { article['title']} (Score: {article['_additional']['score']})")

感谢您的跟随,您现在已经具备了设置自己的向量数据库并使用嵌入来完成各种酷炫事情的能力 - 尽情享受吧!有关更复杂的用例,请继续处理此仓库中的其他食谱示例。