使用 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

相关推荐
不能放弃治疗26 分钟前
重生之我们在ES顶端相遇第 18 章 - Script 使用(进阶)
elasticsearch
hengzhepa1 小时前
ElasticSearch备考 -- Search across cluster
学习·elasticsearch·搜索引擎·全文检索·es
Elastic 中国社区官方博客3 小时前
Elasticsearch:使用 LLM 实现传统搜索自动化
大数据·人工智能·elasticsearch·搜索引擎·ai·自动化·全文检索
慕雪华年4 小时前
【WSL】wsl中ubuntu无法通过useradd添加用户
linux·ubuntu·elasticsearch
Elastic 中国社区官方博客6 小时前
使用 Vertex AI Gemini 模型和 Elasticsearch Playground 快速创建 RAG 应用程序
大数据·人工智能·elasticsearch·搜索引擎·全文检索
alfiy7 小时前
Elasticsearch学习笔记(四) Elasticsearch集群安全配置一
笔记·学习·elasticsearch
alfiy7 小时前
Elasticsearch学习笔记(五)Elastic stack安全配置二
笔记·学习·elasticsearch
丶21361 天前
【大数据】Elasticsearch 实战应用总结
大数据·elasticsearch·搜索引擎
闲人编程1 天前
elasticsearch实战应用
大数据·python·elasticsearch·实战应用
世俗ˊ1 天前
Elasticsearch学习笔记(3)
笔记·学习·elasticsearch