Skip to main content

3 posts tagged with "elasticsearch"

View All Tags

使用 ElasticSearch 和 Transformers 实现语义搜索

· 11 min read

语义/矢量搜索是一种强大的技术,可以大大提高搜索结果的准确性和相关性。与传统的基于关键字的搜索方法不同,语义搜索使用单词的含义和上下文来理解查询背后的意图并提供更准确的结果。实现语义搜索的最流行的工具之一是 Elasticsearch,这是一个高度可扩展且功能强大的搜索引擎,可用于索引和搜索大量数据。在本文中,我们将探讨语义搜索的基础知识以及如何使用 Elasticsearch 实现它。在本文结束时,您将对语义搜索的工作原理以及在项目中实现语义搜索的实用技能有深入的了解。

Elasticsearch

Elasticsearch 是一个基于 Lucene 库的强大且可扩展的开源搜索引擎。它旨在处理大量非结构化数据并提供快速准确的搜索结果。Elasticsearch 使用分布式架构,这意味着它可以在多个服务器上水平扩展,以处理大量数据和流量。

Elasticsearch 建立在 RESTful API 之上,这使得它很容易与各种编程语言和工具集成。它支持复杂的搜索查询,包括全文搜索、分面搜索和地理搜索。Elasticsearch 还提供了一个强大的聚合框架,允许您对搜索结果执行复杂的数据分析。

Transformers

Transformers 是一种机器学习模型,它彻底改变了自然语言处理 (NLP) 任务,例如语言翻译、文本摘要和情绪分析。Transformers 最初是由 Vaswani 等人在 2017 年的一篇论文“注意力是你所需要的一切”中引入的,此后成为许多 NLP 任务的最新模型。

与依赖于递归神经网络(RNN)和卷积神经网络(CNN)的传统 NLP 模型不同,Transformers 使用自我注意机制来捕获句子中单词之间的关系。自我注意允许模型专注于输入序列的不同部分,以确定单词之间最重要的关系。这使得转换器在处理单词之间的长期依赖关系和上下文关系方面比传统模型更有效。

在本文中,我将使用 TensorFlow 的通用句子编码器来编码/矢量化数据。您也可以选择任何其他形式的编码器。

先决条件

在开始之前,需要如下准备工作:

  • 了解 python,包括使用外部库和 IDE 的知识。
  • 了解 Transformers / Vectorizers 及其输出的维度数组。
  • Elasticsearch 8.6 及更高版本。

开始构建

为了构建语义搜索功能,我们使用 Python 作为后端,Elasticsearch 8.6.1 ,以及 TensorFlow 的 Universal Sentence Encoder 用于获取嵌入/向量。

先安装依赖项:

pip install elasticsearch==8.6.1
pip install tensorflow==2.10.0

安装依赖项后,首先需要文本数据。获取文本数据后,在首选 IDE 中使用 python 读取它。

from elasticsearch import Elasticsearch
import pandas as pd
import numpy as np

df = pd.read_csv('your_text_dataset.csv')

现在读取文本数据后,第一个任务是将其转换为向量或嵌入。正如我之前提到的,我使用的是 TensorFlow 的通用句子编码器,它在提供字符串时输出“512”维度的向量/嵌入。

对于其他转换器/矢量器,这将有所不同,您需要记住这一点以进一步的步骤。

让我们首先加载通用句子编码器模型,这里我已将其存储在系统中。您也可以在其 网站 上找到相关 API。

model = hub.load("path/model v4")

成功加载模型后,现在我们的下一个任务是将数据集中的文本转换为向量/嵌入,并将其存储在名为 Embeddings 的新字段/列中。

with tf.compat.v1.Session() as session:
session.run([tf.compat.v1.global_variables_initializer(), tf.compat.v1.tables_initializer()])
query_array = session.run(model(df["Text"]))

vectors = []
for i in query_array:
vectors.append(i)

df["Embeddings"] = vectors

df.to_csv("your_text_dataset_with_embeddings.csv", index=False)

注意:在这个的数据集中,有一个名为 Text 的字段/列。请根据您的数据集的情况来修改该字段名。

一旦嵌入完成并存储在新字段中,就可以将这些数据插入到前面我们安装的 Elasticsearch 中。

要插入数据,我们首先必须连接到 Elasticsearch,我们使用 python 来实现这个操作:

http_auth = ("elastic_username", "elastic_password")
es_host = "https://localhost:9200"
context = create_default_context(cafile="http_ca.crt")
es = Elasticsearch(
es_host,
basic_auth=http_auth,
ssl_context=context
)

要验证是否已建立连接,您可以先在浏览器上打开 https://localhost:9200 检查是否可以正常访问。您还可以通过运行 es.ping() 来检查来自 IDE 的连接。如果成功连接,输出应为 True

现在我们已经建立了与 Elasticsearch 的连接,接下来继续配置 Elasticsearch 索引:

configurations = {
"settings": {
"analysis": {
"filter": {
"ngram_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 15,
},
"english_stop": {
"type": "stop",
"stopwords": "_english_"
},
"english_keywords": {
"type": "keyword_marker",
"keywords": ["example"]
},
"english_stemmer": {
"type": "stemmer",
"language": "english"
},
"english_possessive_stemmer": {
"type": "stemmer",
"language": "possessive_english"
}
},
"analyzer": {
"en_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase",
"ngram_filter",
"english_stemmer",
"english_possessive_stemmer",
"english_stop"
"english_keywords",
]
}
}
}
},
"mappings": {
"properties": {
"Embeddings": {
"type": "dense_vector",
"dims": 512,
"index": True,
"similarity": "cosine"
},
}
}
}
configurations["settings"]

上述配置可以让我们在插入数据时进行索引配置,让我们仔细看看一些重要的参数。

  • “type”:类型必须始终设置为“dense_vector”。这样做是为了让 ElasticSearch 了解这些是向量,并且不会自行为此字段分配浮点类型。
  • “dims”:也就是维度。就像我之前提到的,通用句子编码器产生并输出“512”维度,这就是为什么我们在参数中提供“512”的原因。
  • “index”:索引必须设置为“True”,以便创建此字段并在 ElasticSearch 中具有 dense_vector 类型的特性。
  • “similarity”:求余弦相似性。

配置索引后,继续创建索引:

es.indices.create(index='my_new_index',
settings=configurations["settings"],
mappings=configurations["mappings"]
)

这里我们将索引命名为 “my_new_index”,最后我们准备将数据插入到 Elasticsearch 上的这个索引中:

actions = []
index_name = 'my_new_index'
for index, row in df.iterrows():
action = {"index": {"_index": index_name, "_id": index}}
doc = {
"id": index,
"Text": row["Text"],
"Price": row["Price"],
"Quantity": row["Quantity"],
"Embeddings": row["Embeddings"]
}
actions.append(action)
actions.append(doc)

es.bulk(index=index_name, operations=actions)

搜索

一旦完成数据插入后,就可以搜索这些数据并提出一些相关问题。我们从一个我们想要获得答案的问题开始。

query = "Which is the latest phone available in your shop?"

由于我们要在 Elasticsearch 上进行语义搜索,因此需要将此文本转换为嵌入/向量。

with tf.compat.v1.Session() as session:
session.run([tf.compat.v1.global_variables_initializer(), tf.compat.v1.tables_initializer()])
query_array = session.run(model([query])).tolist()[0]

将文本转换为嵌入/向量后,就根据 Elasticsearch 中的现有数据搜索此文本。为此,我们首先必须构建一个查询从 Elasticsearch 获取数据。

query_for_search = {
"knn": {
"field": "Embeddings",
"query_vector": query_array,
"k": 5,
"num_candidates": 2414
},
"_source": [ "Text"]
}

我们通过上述代码在 Elasticsearch 进行查询。在我们查看下一步之前,先看看这个查询:

  • "knn": Elasticsearch 支持 K-Nearest Neighbors 又名 kNN 算法,并且已经在 Elasticsearch 中可用。您不需要单独训练它。
  • "field": 嵌入/向量存储在 Elasticsearch 中的字段名。
  • "query_vector": 输入的向量/嵌入形式 "k": 需要获取的结果数
  • "num_candidates": 以令牌为单位的输出/搜索结果的长度。
  • "_source": 必须从中提供输出/搜索结果的字段名。

开始搜索:

result = es.search(
index="my_new_index",
body=query_for_search)
result0["hits"]

借助上述查询,您将能够从之前存储数据的索引中获取搜索结果。

请记住,您只能对具有配置字段的索引执行语义搜索,包含嵌入/向量的字段类型必须为“dense_vector”,并且查询/问题和存储在 Elasticsearch 中的数据的向量维度必须完全相同。例如,在上面的教程中,我们在 Elasticsearch 中的数据处于“512”维度中,并且在我们继续搜索操作之前,查询/问题也转换为“512”维度。

结论

语义搜索是一种强大的工具,可以通过理解单词的含义和上下文来大大提高搜索结果的准确性和相关性。Elasticsearch 是一个高度可扩展且灵活的搜索引擎,可用于实现从电子商务到医疗保健的各种应用程序的语义搜索。通过利用 Elasticsearch 强大的搜索和索引功能,以及查询扩展、同义词检测和实体识别等技术,您可以构建一个语义搜索系统,提供快速准确的结果。无论您是开发人员、数据科学家还是企业主,使用 Elasticsearch 掌握语义搜索都可以帮助您从数据中发掘新的见解和机会。

本文的完整代码请看 https://github.com/Pritam868/Semantic-Search-ElasticSearch

本文译自 https://medium.com/@pablopaul1999/semantic-search-using-transformers-and-elasticsearch-6e968fdd85d5

使用 OpenAI 的 Embeddings 接口实现文本和代码的语义搜索

· 9 min read

本文主要介绍 OpenAI 的 Embeddings (嵌入) 接口,该接口可以轻松执行自然语言和代码任务,如语义搜索、聚类、主题建模和分类。

Embeddings 是转换为数字序列的概念的数字表示,使计算机可以轻松理解这些概念之间的关系。Embeddings 在 3 个标准基准测试中优于顶级模型,其中代码搜索的改进相对提升了 20%。

Embeddings 对于处理自然语言和代码非常有用,因为它们可以很容易地被其他机器学习模型和算法(如聚类或搜索)使用和比较。

Vector

在 Embeddings 中,两组相似的数值在语义上也是相似的。例如,“犬类同伴说”的嵌入向量将更类似于“woof”的嵌入向量,而不是“meow”的嵌入向量。

新的接口使用神经网络模型(GPT-3 的后代)将文本和代码映射到矢量数据上 - 将它们“嵌入”在高维空间中。每个维度捕获输入的某些方面。

OpenAI API 中的新 /embeddings 端点提供包含几行代码的文本和代码嵌入:

import openai
response = openai.Embedding.create(
input="canine companions say",
engine="text-similarity-davinci-001")

OpenAI 发布了三个系列的嵌入模型,每个系列都经过调整以在不同的功能上表现良好,包括:文本相似性、文本搜索和代码搜索。这些模型将文本或代码作为输入,并返回嵌入向量。

模型使用场景
文本相似度: 捕获文本片段之间的语义相似性.text-similarity-{ada, babbage, curie, davinci}-001聚类、回归、异常检测、可视化
文本搜索:文档的语义信息检索。text-search-{ada, babbage, curie, davinci}-{query, doc}-001搜索, 上下文相关性, 信息检索
代码搜索:使用自然语言查询查找相关代码。code-search-{ada, babbage}-{code, text}-001代码搜索和相关性

文本相似性模型

文本相似性模型提供用于捕获文本片段的语义相似性。这些模型可用于许多任务,包括聚类分析、数据可视化和分类。

以下交互式可视化显示了来自 DBpedia 数据集的文本示例的嵌入:

clusting

来自 text-similarity-babbage-001 模型,使用的是 DBpedia 数据集。我们从涵盖 5 个类别的数据集中随机选择了 100 个样本,并通过 /embeddings 端点计算嵌入。不同的类别在嵌入空间中显示为 5 个清晰的簇。为了可视化嵌入空间,我们使用 PCA 将嵌入维度从 2048 减少到 3。有关如何在 3D 维度中可视化嵌入空间的代码,请参阅此处

要比较两段文本的相似性,您只需在文本嵌入上使用点积即可。结果是 –1 和 1 之间的“相似性得分”,有时称为“余弦相似性”,其中数字越大意味着相似性越大。在大多数应用中,可以预先计算嵌入,然后非常快速地进行点积比较。

import openai, numpy as np

resp = openai.Embedding.create(
input=["feline friends say", "meow"],
engine="text-similarity-davinci-001")

embedding_a = resp['data'][0]['embedding']
embedding_b = resp['data'][1]['embedding']

similarity_score = np.dot(embedding_a, embedding_b)

Embeddings 的一个常见用途是将它们用作机器学习任务(如分类)中的特征。在机器学习文献中,当使用线性分类器时,这种分类任务称为“线性探针”。我们的文本相似性模型在 SentEval 中实现了线性探针分类的最新结果(Conneau et al.,2018),这是评估嵌入质量的常用基准。

7 个数据集的线性探针分类

linear-probe

文本搜索模型

文本搜索模型提供嵌入,支持大规模搜索任务,例如在给定文本查询的文档集合中查找相关文档。文档和查询的嵌入分别生成,然后使用余弦相似性来比较查询与每个文档之间的相似性。

基于嵌入的搜索可以比经典关键字搜索中使用的单词重叠技术更好地概括,因为它捕获文本的语义含义,并且对确切的短语或单词不太敏感。我们评估了文本搜索模型在 BEIR (Thakur, et al. 2021)搜索评估套件上的性能,并获得了比以前方法更好的搜索性能。我们的文本搜索指南提供了有关将嵌入用于搜索任务的更多详细信息。

BEIR 中 11 个搜索任务的平均准确率

BEIR

代码搜索模型

代码搜索模型为代码搜索任务提供代码和文本嵌入。给定一组代码块,任务是查找自然语言查询的相关代码块。我们在 CodeSearchNetHusian et al., 2019)评估套件上评估代码搜索模型,其中我们的嵌入比以前的方法获得了明显更好的结果。可以通过 代码搜索指南 来了解使用嵌入进行代码搜索的方法。

超过 6 种编程语言的平均准确度

code search

嵌入 API 的实际应用示例

JetBrains Research

JetBrains Research 的 Astroparticle Physics Lab 分析了 The Astronomer’s Telegram 和 NASA 的 GCN Circulars 等数据,这些报告包含传统算法无法解析的天文事件。

在 OpenAI 嵌入这些天文报告的支持下,研究人员现在能够在多个数据库和出版物中搜索诸如“蟹状脉冲星爆发”之类的事件。 嵌入还通过 k 均值聚类在数据源分类上实现了 99.85% 的准确率。

FineTune Learning

FineTune Learning 是一家为学习构建人机混合解决方案的公司,例如帮助学生达到学术标准的自适应学习循环

OpenAI 的嵌入显着改进了根据学习目标查找教科书内容的任务。 OpenAI 的文本搜索居里嵌入模型达到了 89.1% 的前 5 准确率,优于之前的方法,如 Sentence-BERT (64.5%)。 虽然人类专家仍然更好,但 FineTune 团队现在能够在几秒钟内标记整本教科书,而专家则需要数小时。

FineTune

Fabius

Fabius 帮助公司将客户对话转化为结构化的内容,为规划和优先级排序提供信息。 OpenAI 的嵌入允许公司更轻松地查找和标记具有功能请求的客户通话记录。

例如,客户可能会使用“自动化”或“易于使用”等词来要求更好的自助服务平台。 此前,Fabius 曾使用模糊关键字搜索来尝试为那些带有自助服务平台标签的成绩单打上标签。 借助 OpenAI 的嵌入,他们现在能够找到 2 倍以上的一般示例,以及 6 到 10 倍的具有抽象用例的特征示例,这些用例没有客户可能使用的明确关键字。

所有 API 客户都可以开始使用嵌入文档,以便在他们的应用程序中使用嵌入。

本文译自 https://openai.com/blog/introducing-text-and-code-embeddings

Indexea 正式上线啦

· 3 min read

欢迎来到 Indexea 的博客频道!在这里,我们将会分享 Indexea 的发展历程、技术实践、行业动态和客户案例等内容。我们希望通过这个博客频道,让大家更好地了解 Indexea,并与广大用户建立更紧密的联系和沟通。

Indexea

Indexea 是一款全文检索和搜索引擎产品,它能够快速、准确地搜索和检索各种文档、文件、图片、音视频等内容,为用户提供高效、便捷的搜索体验。我们的团队致力于为客户提供高质量、高性能的搜索服务,帮助客户在信息化时代获取更多的商业价值。

Indexea 的发展历程可以追溯到几年前。当时,我们团队对当前市场上的搜索引擎产品进行了全面的调研和分析,发现市场上缺乏一款同时具备高性能、易用性和可扩展性的搜索引擎产品。于是,我们决定开发一款全新的搜索引擎产品,以满足市场的需求。

经过多年的技术研发和市场验证,我们的团队成功地开发出了 Indexea,这是一款全面升级的全文检索和搜索引擎产品。Indexea 支持多种数据类型和数据源,具有快速、准确、可扩展等优点,已经成功地服务于各种企业和组织。

在未来,我们将继续致力于 Indexea 的研发和推广,为客户提供更好的搜索服务和技术支持。同时,我们也将不断开拓创新,推出更多优秀的产品和解决方案,为客户创造更多的商业价值。

感谢大家的支持和关注!我们将会不断更新博客内容,分享 Indexea 的最新动态和技术成果。同时,我们也欢迎大家提出宝贵的意见和建议,共同推动 Indexea 的发展。