Skip to content

查询指南

查询 查询

本节介绍如何使用txtai查询数据。最简单的搜索数据方法是构建一个包含所需内容的自然语言字符串。txtai还支持使用SQL进行查询。我们将在这里介绍这两种方法。

自然语言查询

在最简单的情况下,查询是文本,结果是与查询文本最相似的索引文本。

embeddings.search("feel good story")
embeddings.search("wildlife")

上述查询在索引中搜索与feel good storywildlife相似的匹配项。如果启用了内容存储,则返回一个{**查询列}的列表。否则,返回一个(id, score)元组的列表。

SQL

txtai支持使用SQL进行更复杂的查询。这仅在启用了内容存储时支持。txtai有一个翻译层,用于分析输入的SQL语句,并将相似性结果与存储在关系数据库中的内容结合起来。

SQL查询通过embeddings.search运行,类似于自然语言查询,但下面的示例仅显示SQL查询以简洁起见。

embeddings.search("SQL query")

相似子句

相似子句是txtai的一个函数,支持使用SQL进行相似性搜索。

SELECT id, text, score FROM txtai WHERE similar('feel good story')

相似子句接受以下参数:

similar("查询", "候选结果数量", "索引", "权重")
参数 描述
查询 要运行的自然语言查询
候选结果数量 要返回的候选结果数量
索引 目标索引名称
权重 混合分数权重

txtai查询层将来自两个独立组件的结果连接起来,一个是关系存储,另一个是相似性索引。通过相似子句,运行相似性搜索并将这些id输入到底层数据库查询中。

在应用附加过滤子句时,候选结果数量应大于所需的结果数量。这确保在应用附加过滤器后仍返回limit结果。如果未指定候选结果数量,则默认如下:

  • 对于单个查询过滤子句,默认值为查询限制
  • 对于多个过滤子句,默认值为查询限制的10倍

索引名称仅在启用子索引时适用。这指定了用于查询的索引。

当索引同时具有稀疏和密集索引时,权重设置混合分数权重。

动态列

当启用内容存储时,内容可以以多种方式进行索引。记住输入文档的形式为(id, data, tags)元组。如果数据是字符串或二进制内容,则它被索引并通过similar()子句进行搜索。

如果数据是字典,则字典中的所有字段都被存储并通过SQL访问。text字段或在索引配置中指定的字段被索引并通过similar()子句进行搜索。

例如:

embeddings.index([{"text": "text to index", "flag": True,
                   "actiondate": "2022-01-01"}])

使用上述输入数据,查询现在可以有更复杂的过滤器。

SELECT text, flag, actiondate FROM txtai WHERE similar('query') AND flag = 1
AND actiondate >= '2022-01-01'

txtai的查询层自动检测列并将查询转换为底层数据库可以理解的格式。

支持嵌套字典/JSON,并可以使用括号语句进行转义。

embeddings.index([{"text": "text to index",
                   "parent": {"child element": "abc"}}])
SELECT text FROM txtai WHERE [parent.child element] = 'abc'

注意括号语句转义了名称中带有空格的嵌套列。

绑定参数

txtai支持SQL绑定参数。

# 使用绑定参数进行相似子句查询
query = "SELECT id, text, score FROM txtai WHERE similar(:x)"
results = embeddings.search(query, parameters={"x": "feel good story"})

# 使用绑定参数进行列过滤查询
query = "SELECT text, flag, actiondate FROM txtai WHERE flag = :x"
results = embeddings.search(query, parameters={"x": 1})

聚合查询

txtai查询语言的目标是紧密支持底层数据库引擎中的所有功能。主要挑战是确保动态列正确转义为引擎的本地查询函数。

聚合查询示例。

SELECT count(*) FROM txtai WHERE similar('feel good story') AND score >= 0.15
SELECT max(length(text)) FROM txtai WHERE similar('feel good story')
AND score >= 0.15
SELECT count(*), flag FROM txtai GROUP BY flag ORDER BY count(*) DESC

二进制对象

txtai 支持存储和检索二进制对象。二进制对象可以按如下示例所示进行检索。

# 创建启用了内容和对象存储的嵌入索引
embeddings = Embeddings(content=True, objects=True)

# 获取一张图片
request = open("demo.gif", "rb")

# 插入记录
embeddings.index([("txtai", {"text": "txtai 执行机器学习工作流程。",
                             "object": request.read()})])

# 查询 txtai 并获取关联的对象
query = "SELECT object FROM txtai WHERE similar('机器学习') LIMIT 1"
result = embeddings.search(query)[0]["object"]

# 使用绑定参数查询二进制内容
query = "SELECT object FROM txtai WHERE similar(:x) LIMIT 1"
results = embeddings.search(query, parameters={"x": request.read()})

自定义 SQL 函数

自定义的、用户定义的 SQL 函数通过附加逻辑扩展了选择、过滤和排序子句。例如,以下代码片段定义了一个使用翻译管道翻译文本的函数。

# 翻译管道
translate = Translation()

# 创建嵌入索引
embeddings = Embeddings(path="sentence-transformers/nli-mpnet-base-v2",
                        content=True,
                        functions=[translate]})

# 使用自定义 SQL 函数运行搜索
embeddings.search("""
SELECT
  text,
  translation(text, 'de', null) 'text (DE)',
  translation(text, 'es', null) 'text (ES)',
  translation(text, 'fr', null) 'text (FR)'
FROM txtai WHERE similar('感觉良好的故事')
LIMIT 1
""")

查询翻译

带有过滤器的自然语言查询可以转换为 txtai 兼容的 SQL 语句,使用查询翻译功能。例如:

embeddings.search("自昨天以来的感觉良好的故事")

可以转换为带有相似子句和日期过滤器的 SQL 语句。

select id, text, score from txtai where similar('感觉良好的故事') and
entry >= date('now', '-1 day')

这需要设置一个查询翻译模型。默认的查询翻译模型是 t5-small-txtsql,但可以轻松微调以处理不同的用例。

混合搜索

当嵌入数据库同时具有稀疏和密集索引时,除非另有指定,否则将查询这两个索引,结果将等权重。

embeddings.search("query", weights=0.5)
embeddings.search("SELECT id, text, score FROM txtai WHERE similar('query', 0.5)")

图搜索

如果嵌入数据库有关联的图网络,可以运行图搜索。以下搜索语法使用 openCypher。点击前面的链接了解更多关于此语法的信息。

此外,标准的嵌入搜索可以作为图返回。

# 查找 id: 0 和 id: 5 之间 1 到 3 跳的所有路径
embeddings.graph.search("""
MATCH P=({id: 0})-[*1..3]->({id: 5})
RETURN P
""")

# 标准嵌入搜索作为图
embeddings.search("query", graph=True)

子索引

子索引可以按如下方式查询:

# 使用索引参数查询
embeddings.search("query", index="subindex1")

# 使用 SQL 指定
embeddings.search("""
SELECT id, text, score FROM txtai
WHERE similar('query', 'subindex1')
""")

组合索引架构

txtai 具有多个存储和索引组件。内容存储在底层数据库中,以及近似最近邻(ANN)索引、关键词索引和图网络。这些组件结合在一起,提供了相似性搜索以及传统的结构化搜索。

ANN 索引存储每个输入元素的 id 和向量。当运行自然语言查询时,查询被转换为向量,相似性查询找到最佳匹配的 id。当数据库加入时,会执行一个额外的步骤。该步骤获取这些 id 并将它们有效地插入为底层数据库查询的一部分。对于关键词索引,步骤相同,只是使用词频索引来找到最佳匹配的 id。

通过底层引擎支持动态列。对于 SQLite,数据存储为 JSON,动态列被转换为 json_extract 子句。通过 SQLAlchemy 支持客户端-服务器数据库,只要底层引擎支持 JSON,就支持动态列。