使用 Elasticsearch 作为 Azure OpenAI On Your Data 的向量数据库

作者:来自 Elastic Paul Oremland

背景介绍

最近,[微软通过 Azure OpenAI 服务 "On Your Data" 将 Elasticsearch 直接集成到 Azure 中](techcommunity.microsoft.com/t5/ai-azure... "微软通过 Azure OpenAI 服务 "On Your Data" 将 Elasticsearch 直接集成到 Azure 中")。"On Your Data" 使组织能够利用强大的 AI 模型(如 GPT-4 和 RAG 模型)构建最先进的对话体验。这样可以让大型语言模型基于你的私有数据,从而确保对话内容的知情性和准确性。

在本文中,我想展示如何轻松启动一个 Elasticsearch 集群,使用 Elasticsearch 连接器来摄取数据,然后通过新的 Azure OpenAI 服务 "On Your Data" 集成来与这些数据进行对话。我们将在本文中使用的一个工具是最近新增的 Connectors API 和 CLI,这使我们能够完全通过编程方式与 Elasticsearch 进行交互,而无需在开发环境和 Kibana 之间来回切换。

先决条件

在本示例中,我将使用 openlibrary.org 中的 OpenLibrary 数据集。 为了使用此数据集,你需要做一些前期工作,让数据准备好摄取到 Elasticsearch 中。 具体来说,你需要:

  1. openlibrary.org/developers/... 下载最新的数据转储
  2. 将数据转储导入 PostgreSQL。 我使用了 github.com/LibrariesHa... 中列出的开源工具和步骤

虽然步骤 2 并不是绝对必要的,因为你可以编写自定义摄取脚本,但出于几个原因,我喜欢将数据暂存在 PostgreSQL 中。 首先,Elasticsearch 开箱即用地支持通过连接器从 PostgreSQL 获取数据。 连接器已经针对吞吐量进行了优化,并且内置了一些很好的弹性,我讨厌重新发明轮子。 其次,我可以编写自定义 SQL 查询以与连接器一起使用。 这意味着我有很大的灵活性,可以从数据集中仅提取我想要的数据,并且可以将 "book" 的高度规范化的数据表示为单个文档,而无需编写自定义代码来从原始参考数据转储中执行此操作。 因此,我不必花几天时间编写和调整自定义脚本来创建代表书籍的版本、作者和作品的单个文档,而是只需花费几分钟将数据导入 PostgreSQL 并设置连接器将数据提取到 Elasticsearch 中。

启动 Elasticsearch 集群

现在我已经准备好所有要摄取的数据,我将创建一个 Elasticsearch 部署。我选择使用 Elastic Cloud,因为我不想担心或管理任何基础设施。

注意,我将主要通过命令行和 curl 来完成大部分操作。我会使用一些需要在命令行中导出的 shell 变量,具体包括:

  • ES_URL:你的 Elasticsearch 部署的 URL
  • API_KEY:我们在后续步骤中创建的密钥
  • CONNECTOR_ID:在后续步骤中创建的连接器 ID

第一步是在 . cloud.elastic.co/deployments... 或者通过 API 创建一个部署。因为我知道我会对数百万文档生成嵌入并在查询中执行文本扩展,所以我要将机器学习实例的最小大小增加到 4GB。

展开 "Advanced settings" 部分。

向下滚动到机器学习实例并将 "Minimum size per zone" 更新为 4GB

现在你可以单击 "Create deployment" 按钮。 稍后你的部署就会完成。

接下来,让我们创建一个 API 密钥。 请记住将其保存在安全的地方,因为我们会经常使用它。 请注意,为了使这个示例简单,我使用了过于宽松的访问权限。 在实践中(和在生产中),你可能希望使用角色和/或限制来设置更细粒度的权限

vbnet 复制代码
1.  curl --user elastic -X PUT "${ES_URL}/_security/api_key?pretty" \
2.  -H "Content-Type: application/json" \
3.  -d'
4.  {
5.      "name": "books-api-key",
6.      "role_descriptors": {
7.          "role-name": {
8.              "cluster": ["all"],
9.              "index": [ { "names": ["*"], "privileges": ["all"] } ]
10.          }
11.      }
12.  }
13.  '

接下来,你需要创建索引并为 title 和 descriptions 字段设置 dense_vector 映射。 此步骤假设你知道文档架构,这会产生一种"先有鸡还是先有蛋"的问题,因为直到摄取数据之后你才知道该架构。 为了简单起见,我使用下面列出的相同步骤设置了一个临时索引,创建了一个连接器,并提取了一个文档(将 SQL 查询的限制设置为 1)。 这使我能够知道文档 schema 是什么样子,这样我就可以在开始时生成我想要的映射。 这是我们团队正在努力在未来版本中解决的已知尖锐问题。

vbnet 复制代码
1.  curl -X PUT "${ES_URL}/books-index?pretty" \
2.  -H "Authorization: ApiKey "${API_KEY}"" \
3.  -H "Content-Type: application/json" \
4.  -d'
5.  {
6.      "mappings": {
7.          "properties": {
8.              "public_author_works_authors_edition_isbns_editions_works_description": {
9.                  "type": "text",
10.                  "copy_to": ["description"]
11.              },
12.              "public_author_works_authors_edition_isbns_editions_works_title": {
13.                  "type": "text",
14.                  "copy_to": ["title"]
15.              },
16.              "description": { "type": "text" },
17.              "title": { "type": "text" },
18.              "title_embedding": { "type": "dense_vector" },
19.              "description_embedding": { "type": "dense_vector" }
20.          }
21.      }
22.  }
23.  '

现在我们已经创建了索引并设置了映射,让我们下载 E5 模型并将输入字段名称设置为我们刚刚创建的密集向量映射。

vbnet 复制代码
1.  curl -X PUT "${ES_URL}/_ml/trained_models/.multilingual-e5-small_linux-x86_64?pretty" \
2.  -H "Authorization: ApiKey "${API_KEY}"" \
3.  -H "Content-Type: application/json" \
4.  -d'
5.  {
6.      "input": {
7.          "field_names": ["title_embedding", "description_embedding"]
8.      }
9.  }
10.  '

接下来我们要部署模型。 如果你收到 408,则需要在执行上一个命令后等待一分钟,以便首先完成下载。

bash 复制代码
curl -X POST "${ES_URL}/_ml/trained_models/.multilingual-e5-small_linux-x86_64/deployment/_start?wait_for=started&deployment_id=for_search&pretty" -H "Authorization: ApiKey "${API_KEY}""

最后,我们需要创建一个推理管道,当我们从连接器获取数据时,该管道将在 title 和 decription 字段上创建嵌入。

vbnet 复制代码
1.  curl -X PUT "${ES_URL}/_ingest/pipeline/e5-small-books?pretty" \
2.  -H "Authorization: ApiKey "${API_KEY}"" \
3.  -H "Content-Type: application/json" \
4.  -d'
5.  {
6.      "processors": [{
7.          "inference": {
8.              "model_id": "for_search",
9.              "input_output": [
10.                  {
11.                      "input_field": "public_author_works_authors_edition_isbns_editions_works_title",
12.                      "output_field": "title_embedding"
13.                  },
14.                  {
15.                      "input_field": "public_author_works_authors_edition_isbns_editions_works_description",
16.                      "output_field": "description_embedding"
17.                  }
18.              ]
19.          }
20.      }]
21.  }
22.  '

摄取数据

现在我们已经创建、配置了集群并准备使用,让我们开始提取数据。 为此,我们将使用 Elasticsearch PostgreSQL 连接器。 我将从源代码中执行此操作,因为为什么不呢,但如果你想要更多开箱即用的东西,你可以从 Docker 安装

首先,让我们克隆 GitHub 存储库并安装所有依赖项。

bash 复制代码
git clone git@github.com:elastic/connectors.git 
bash 复制代码
cd connectors && make clean install

接下来,我将使用神奇的连接器 CLI 对我的 Elasticsearch 实例进行身份验证,并让它处理基本的连接器配置。 第一步是通过 CLI 登录 Elasticsearch,并在出现提示时输入你的 Elasticsearch 实例 URL 和 API 密钥。

bash 复制代码
./bin/connectors login --method apikey

接下来,创建连接器并在出现提示时输入 PostgreSQL 连接信息。

markdown 复制代码
1.  ./bin/connectors connector create \
2.  --from-index \
3.  --index-name books-index \
4.  --service-type postgresql \
5.  --index-language en \
6.  --update-config

8.  ? Connector name: books-postgresql-connector
9.  ? Host []: localhost
10.  ? Port []: 5432
11.  ? Username []: \<USERNAME>
12.  ? Password []: \<PASSWORD>
13.  ? Database []: openlibrary
14.  ? Schema []: public
15.  ? Comma-separated list of tables []: *
16.  ? Rows fetched per request []:
17.  ? Retries per request []:
18.  ? Enable SSL verification [False]:

因为我们的数据源有大量标准化数据,所以我们需要创建一个自定义 SQL 语句,我们可以将连接器配置为与其高级同步规则功能一起使用。 我们将使用以下 SQL 语句来帮助我们从高度相关的数据创建单个文档。 请注意,由于此 SQL 将通过 curl 命令发送,因此我们需要使用 ''' 转义 '。

sql 复制代码
1.  SELECT DISTINCT ON (author_works.work_key, editions.data->>'\''publish_date'\'') author_works.author_key, 
2.    editions.key, 
3.    author_works.author_key, 
4.    author_works.work_key, 
5.    edition_isbns.edition_key, 
6.    edition_isbns.isbn, 
7.    authors.key, 
8.    works.key, 
9.    works.data->>'\''title'\'' AS title, 
10.    authors.data->>'\''name'\'' AS author_name, 
11.    COALESCE(works.data->'\''description'\''->>'\''value'\'', '\'''\'') AS description, 
12.    edition_isbns.isbn AS isbn, 
13.    editions.data->>'\''publish_date'\'' as publish_date 
14.  FROM editions 
15.    JOIN edition_isbns on edition_isbns.edition_key = editions.key 
16.    JOIN works on works.key = editions.work_key 
17.    JOIN author_works on author_works.work_key = works.key 
18.    JOIN authors on author_works.author_key = authors.key 
19.  WHERE 
20.    EXISTS (SELECT 1 FROM jsonb_array_elements(editions.data->'\''languages'\'') AS elem WHERE elem->>'\''key'\'' = '\''/languages/eng'\'') 
21.  ORDER BY 
22.    editions.data->>'\''publish_date'\'' desc

起草高级同步规则。 连接器运行后,被创建的同步规则将在通过验证后激活。

注意:此 API 调用当前在 Elasticsearch Serverless 中可用,并将包含在 Elasticsearch 8.14 版本中。

vbnet 复制代码
1.  curl -X PUT "${ES_URL}/_connector/${CONNECTOR_ID}/_filtering?pretty" \
2.  -H "Authorization: ApiKey "${API_KEY}"" \
3.  -H "Content-Type: application/json" \
4.  -d'
5.  {
6.      "advanced_snippet": {
7.          "value": [{
8.              "tables": [ "editions", "works", "author_works", "authors", "edition_isbns" ],
9.              "query": "\<SQL FROM ABOVE>"
10.          }]
11.      }
12.  }
13.  '

我们还希望将连接器连接到我们之前创建的推理管道,以便在摄取文档时自动生成嵌入。

vbnet 复制代码
1.  curl -X PUT "${ES_URL}/_connector/${CONNECTOR_ID}/_pipeline?pretty" \
2.  -H "Authorization: ApiKey "${API_KEY}"" \
3.  -H "Content-Type: application/json" \
4.  -d'
5.  {
6.      "pipeline": {
7.          "extract_binary_content": true,
8.          "name": "e5-small-books",
9.          "reduce_whitespace": true,
10.          "run_ml_inference": true
11.      }
12.  }
13.  '

接下来,我们将使用 API 启动同步,将数据提取到 Elasticsearch 中。

vbnet 复制代码
1.  curl -X POST "${ES_URL}/_connector/_sync_job?pretty" \
2.  -H "Authorization: ApiKey "${API_KEY}"" \
3.  -H "Content-Type: application/json" \
4.  -d'
5.  {
6.      "id": $CONNECTOR_ID,
7.      "job_type": "full"
8.  }
9.  '

最后,是时候运行连接器了:

arduino 复制代码
make run 

你可以使用以下命令检查摄取了多少文档:

bash 复制代码
curl -X POST "${ES_URL}/books-index/_count&pretty" -H "Authorization: ApiKey "${API_KEY}""

将 Azure OpenAI On Your Data 连接到 Elasticsearch

现在我们已经部署了 Elasticsearch 并提取了所有数据,让我们使用 Azure OpenAI 服务的 "On Your Data" 与索引进行对话。 为此,我将使用 Azure OpenAI 控制台。

我们需要做的第一件事是打开 Azure AI Studio 的 Web 界面并:

  1. 打开 "Chat" 游乐场
  2. 选择 "Add your data" 选项卡
  3. 单击 "Add your data source" 按钮

接下来,选择 Elasticsearch 作为你的数据源,然后:

  1. 输入你的 Elasticsearch 端点 URL(上面的 $ES_URL)
  2. 输入你的 API 密钥(上面的 $API_KEY)
  3. 单击 "Verify connection" 按钮
  4. 选择你的 books-index
  5. 选中 "Use custom field mapping" 按钮
  6. 单击 "Next" 按钮

接下来,我们将通过以下方式设置搜索类型和嵌入模型:

  1. 从 Search type 下拉列表中选择 "Vector"
  2. 选择 "Elasticsearch - .multilingual-e5-small_linux-x86_64" 作为嵌入模型
  3. 单击 "Next" 按钮

接下来,我们将通过以下方式配置数据字段:

  1. 从 "Content data" 下拉列表中选择包含相关内容的所有字段(例如 "author_name" 和 "description")
  2. 保留 "title" 和 "Vector fields" 的默认值

在下一个屏幕上,检查你的 data source 设置,然后单击 "Save and close" 按钮,你就可以开始聊天了。

现在你已准备好与你的数据聊天。 这就是语义搜索真正发挥作用的地方。 我能够提出一个初始问题,然后使用聊天历史记录的语义和上下文,能够以自然语言询问我的数据的后续问题。

最棒的是我可以看到与弹出窗口中提供的上下文一致的引文。

接下来该怎么做?

与索引对话只是你能做的众多强大功能之一。在 Azure OpenAI On Your Data 集成之外,一旦你将数据导入 Elasticsearch,还有许多其他尝试,例如使用我们支持的众多第三方嵌入模型之一来部署文本嵌入模型

可以尝试以下内容:

  1. 使用由 Elastic 训练的稀疏向量检索模型 ELSER
  2. 使用 Cohere、HuggingFace 或 OpenAI 的嵌入模型设置语义搜索
  3. 一般来说,任何支持架构的训练模型都可以使用 eland 部署到 Elasticsearch 中。

Elasticsearch 还提供了以下功能:

  1. 使用搜索模板,这是一种存储的搜索,你可以使用不同的变量来运行搜索,而不需要向用户公开 Elasticsearch 的查询语法。搜索模板允许你在不修改应用程序代码的情况下更改搜索。
  2. 使用混合搜索,将词法(BM25)搜索与近似最近邻(kNN)搜索的强大功能结合起来。
  3. 使用学习排序(Learn To Rank)或查询重评分阶段重新排序,以及使用 Cohere 的重新排序 API

并非所有搜索用例都是语义搜索用例。如果词法搜索(BM25)更适合你的搜索用例,Elasticsearch 提供了几个功能来帮助你获得最相关的搜索结果:

  1. 同义词可以帮助你找到包含类似词语的文档,纠正常见拼写错误,或使特定领域的语言更易于用户理解。你可以使用 synonym API 在内部系统索引中定义和管理同义词,或将相关同义词分组到 "同义词集" 中。
  2. Query Rules 允许为符合指定条件的查询自定义搜索结果。这可以更好地控制结果,例如确保符合定义条件的推广文档出现在结果列表的顶部。

准备好自己尝试了吗?开始免费试用。 Elasticsearch 还集成了 LangChain、Cohere 等工具。加入我们的高级语义搜索网络研讨会,构建你的下一代 AI 应用程序!

原文:Azure OpenAI On Your Data: How to use Elasticsearch as the Vector Database --- Elastic Search Labs

相关推荐
time never ceases2 小时前
Elasticsearch安装和数据迁移
大数据·数据库·elasticsearch·es
随猿Fa6 小时前
arthas查看拼接好参数的sql, redis, es完整可直接执行的命令
redis·sql·elasticsearch
arnold667 小时前
ElasticSearch 分布式部署
elasticsearch
神的孩子都在歌唱10 小时前
es创建的索引状态一直是red
大数据·elasticsearch·jenkins
liupenglove10 小时前
快速掌握Elasticsearch检索之二:滚动查询获取全量数据(golang)
大数据·elasticsearch·搜索引擎
forestsea10 小时前
【Elasticsearch】数据分布与路由机制
大数据·elasticsearch·搜索引擎
运维&陈同学1 天前
【Kibana01】企业级日志分析系统ELK之Kibana的安装与介绍
运维·后端·elk·elasticsearch·云原生·自动化·kibana·日志收集
ly21st1 天前
elasticsearch安全认证
安全·elasticsearch
Mitch3111 天前
【漏洞复现】CVE-2014-3120 & CVE-2015-1427 Expression Injection
运维·web安全·elasticsearch·docker·apache
开心最重要(*^▽^*)1 天前
Metricbeat安装教程——Linux——Metricbeat监控ES集群
linux·elasticsearch