如何在 Elasticsearch 中使用 Openai Embedding 进行语义搜索

2023年 9月 30日 46.5k 0

随着强大的 GPT 模型的出现,文本的语义提取得到了改进。 在本文中,我们将使用嵌入向量在文档中进行搜索,而不是使用关键字进行老式搜索。

什么是嵌入 - embedding?

在深度学习术语中,嵌入是文本或图像等内容的数字表示。 由于每个深度学习模型的输入都应该是数字,因此要使用文本来训练模型,我们应该将其转换为一种数字格式。

有多种算法可以将文本转换为 n 维数字数组。 最简单的算法称为“Bag Of Word”,该算法中 n 是语料库中唯一单词的数量。 该算法只是简单地统计文本中出现的单词数量,并形成一个数组来表示它。



1.  >>> from sklearn.feature_extraction.text import CountVectorizer
2.  >>> corpus = [3.  ...     'This is the first document.',4.  ...     'This document is the second document.',5.  ...     'And this is the third one.',6.  ...     'Is this the first document?',7.  ... ]
8.  >>> vectorizer = CountVectorizer()
9.  >>> X = vectorizer.fit_transform(corpus)
10.  >>> vectorizer.get_feature_names_out()
11.  array(['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third',12.         'this'], ...)
13.  >>> print(X.toarray())
14.  [[0 1 1 1 0 0 1 0 1]
15.   [0 2 0 1 0 1 1 0 1]
16.   [1 0 0 1 1 0 1 1 1]
17.   [0 1 1 1 0 0 1 0 1]]


这种表示形式不够丰富,无法从文本中提取语义和含义。 由于变换器的强大功能,模型可以学习嵌入。 Openai 提供了嵌入 API 来计算文本的嵌入数组。 该表示可以存储在矢量数据库中以供搜索。

Openai 嵌入 API

要使用 openai,我们需要在 openai 网站上生成一个 API 密钥。 为此,我们需要在 “View API Keys” 页面中注册并生成一个新密钥。

Openai API key 页面

请记住:该密钥只会显示一次,因此请保存以供以后使用。

要检索文本嵌入,我们应该使用模型和文本调用 openai 嵌入 API。



1.  {
2.      "input": "The food was delicious and the waiter...",
3.      "model": "text-embedding-ada-002"
4.  }


输入是我们要计算嵌入数组的文本,模型是嵌入模型的名称。 Openai 对于此链接中提供的嵌入模型有多种选择。 在本文中,我们将使用默认的 “text-embedding-ada-002”。 为了调用 API,我们在 python 中使用以下脚本。



1.  import os
2.  import requests

4.  headers = {
5.      'Authorization': 'Bearer ' + os.getenv('OPENAI_API_KEY', ''),
6.      'Content-Type': 'application/json',
7.  }

9.  json_data = {
10.      'input': 'This is the test text',
11.      'model': 'text-embedding-ada-002',
12.  }

14.  response = requests.post('https://api.openai.com/v1/embeddings',
15.                           headers=headers,
16.                           json=json_data)
17.  result = response.json()


嵌入的响应将类似于:



1.  {
2.    "object": "list",
3.    "data": [
4.      {
5.        "object": "embedding",
6.        "embedding": [
7.          0.0023064255,
8.          -0.009327292,
9.          .... (1536 floats total for ada-002)
10.          -0.0028842222,
11.        ],
12.        "index": 0
13.      }
14.    ],
15.    "model": "text-embedding-ada-002",
16.    "usage": {
17.      "prompt_tokens": 8,
18.      "total_tokens": 8
19.    }
20.  }


result['data']['embedding'] 是给定文本的嵌入向量。 ada-002 模型的向量大小为 1536 个浮点数,输入的最大标记为 8191 个标记。

存储和搜索

有多种数据库选择来存储嵌入向量。 在本文中,我们将探索 Elasticsearch 来存储和搜索向量。

Elasticsearch 有一个预定义的向量数据类型,称为 “密集向量”。 为了存储嵌入向量,我们需要创建一个索引,其中包括一个文本字段和一个嵌入向量字段。



1.  PUT my_vector_index
2.  {
3.    "mappings": {
4.      "properties": {
5.        "embedding": {
6.          "type": "dense_vector",
7.          "dims": 1536
8.        },
9.        "text": {
10.          "type": "keyword"
11.        }
12.      }
13.    }
14.  }


对于 ada-002 模型,向量的维数应为 1536。 现在要查询该索引,我们需要熟悉不同类型的向量相似度得分。 余弦相似度是我们可以在 Elasticsearch 中使用的分数之一。 首先,我们需要计算搜索短语的嵌入向量,然后通过索引对其进行查询并获取 top-k 结果。



1.  POST my_vector_index/_search
2.  {
3.    "query": {
4.      "script_score": {
5.        "query": {
6.          "match_all": {}
7.        },
8.        "script": {
9.          "source": "cosineSimilarity(params.query_vector, 'embedding') + 1.0",
10.          "params": {
11.            "query_vector": [0.230, -0.120, 0.389, ...]
12.          }
13.        }
14.      }
15.    }
16.  }


当然,对于大规模部署,我们需要使用 aNN 搜索。请详细阅读 “Elasticsearch:在 Elastic Stack 8.0 中引入近似最近邻搜索”。

这将返回语义上与文本查询相似的文本。

结论

在本文中,我们探讨了新嵌入模型在文档中查找语义的强大功能。 你可以使用任何类型的文档,例如 PDF、图像、音频,并使用 Elasticsearch 作为语义相似性的搜索引擎。 该功能可用于语义搜索、推荐系统。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论