
本教程系列将涵盖txtai的主要用例,这是一个 AI 驱动的语义搜索平台。该系列的每章都有相关代码,可也可以在colab 中使用。
colab 地址
在本文中,我们将采用第 2 部分中使用的相同 Hugging Face Dataset,在 Elasticsearch 中对其进行索引,并使用来自 txtai 的语义相似度函数对搜索结果进行排名。
安装依赖安装txtai,datasets和Elasticsearch.
# Install txtai, datasets and elasticsearch python client pip install txtai datasets elasticsearch # Download and extract elasticsearch wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.1-linux-x86_64.tar.gz tar -xzf elasticsearch-7.10.1-linux-x86_64.tar.gz chown -R daemon:daemon elasticsearch-7.10.1启动一个 Elasticsearch 实例
import os from subprocess import Popen, PIPE, STDOUT # Start and wait for server server = Popen(['elasticsearch-7.10.1/bin/elasticsearch'], stdout=PIPE, stderr=STDOUT, preexec_fn=lambda: os.setuid(1))
sleep 30将数据加载到 Elasticsearch
以下块将数据集加载到 Elasticsearch 中
from datasets import load_dataset
from elasticsearch import Elasticsearch, helpers
# 连接到 ES 实例
es = Elasticsearch(hosts=["http://localhost:9200"], timeout=60, retry_on_timeout=True)
# 下载HF数据集
dataset = load_dataset("ag_news", split="train")["text"][:50000]
# Elasticsearch 大容量缓冲区
buffer = []
rows = 0
for x, text in enumerate(dataset):
# 文章记录
article = {"_id": x, "_index": "articles", "title": text}
# 缓存文章
buffer.append(article)
# 增加处理的文章数量
rows += 1
# 缓存每1000条数据加载处理一次
if rows % 1000 == 0:
helpers.bulk(es, buffer)
buffer = []
print("Inserted {} articles".format(rows), end="r")
if buffer:
helpers.bulk(es, buffer)
print("Total articles inserted: {}".format(rows))
使用 Elasticsearch 查询数据
Elasticsearch 是一个基于令牌的搜索系统。查询和文档被解析为标记,并且使用评分算法计算最相关的查询文档匹配。默认评分算法是BM25。可以使用丰富的查询语法和Query DSL构建强大的查询。
以下部分针对 Elasticsearch 运行查询,查找前 5 个匹配项并返回与每个匹配项关联的相应文档。
from IPython.display import display, HTML
def table(category, query, rows):
html = """
@import url('https://fonts.googleapis.com/css?family=Oswald&display=swap');
table {
border-collapse: collapse;
width: 900px;
}
th, td {
border: 1px solid #9e9e9e;
padding: 10px;
font: 15px Oswald;
}
"""
html += "[%s] %sScore Text " % (category, query)
for score, text in rows:
html += "%.4f%s " % (score, text)
html += ""
display(HTML(html))
def search(query, limit):
query = {
"size": limit,
"query": {
"query_string": {"query": query}
}
}
results = []
for result in es.search(index="articles", body=query)["hits"]["hits"]:
source = result["_source"]
results.append((min(result["_score"], 18) / 18, source["title"]))
return results
limit = 3
query= "+yankees lose"
table("Elasticsearch", query, search(query, limit))
使用 txtai 对搜索结果进行排名
下面的代码创建了一个 Similarity 实例并定义了一个排名函数,以根据计算出的相似度对搜索结果进行排序。
ranksearch 查询 Elasticsearch 以获得更大的结果集,使用相似性实例对结果进行排名并返回前 n 个结果。
from txtai.pipeline import Similarity
def ranksearch(query, limit):
results = [text for _, text in search(query, limit * 10)]
return [(score, results[x]) for x, score in similarity(query, results)][:limit]
# Create similarity instance for re-ranking
similarity = Similarity("valhalla/distilbart-mnli-12-3")
现在让我们重新运行之前的搜索。
# Run the search
table("Elasticsearch + txtai", query, ranksearch(query, limit))
上面的结果在查找语义上与查询含义相似的结果方面做得更好。它不只是查找与yankees和 的匹配项lose,而是查找yankees lose.
这种组合是有效和强大的。它利用了 Elasticsearch 的高性能,同时增加了语义搜索能力。我们可能已经拥有一个大型 Elasticsearch 集群,其中包含 TB(或 PB)+ 的数据和多年的工程投资,可以解决大多数用例。对搜索结果进行语义排名是一种实用的方法。
更多例子现在来看更多比较 Elasticsearch 与 Elasticsearch + txtai 结果的示例。
for query in ["good news +economy", "bad news +economy"]:
table("Elasticsearch", query, search(query, limit))
table("Elasticsearch + txtai", query, ranksearch(query, limit))
参考
https://dev.to/neuml/tutorial-series-on-txtai-ibg
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)