跳到内容

查询指南

query query

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

自然语言查询

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

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

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

SQL

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

SQL 查询像自然语言查询一样通过 embeddings.search 运行,但为了简洁起见,下面的示例仅显示了 SQL 查询。

embeddings.search("SQL query")

similar 子句

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

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

similar 子句采用以下参数

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

txtai 查询层将关系存储和相似度索引这两个独立组件的结果连接起来。使用 similar 子句时,将运行一次相似度搜索,然后将这些 id 馈送到基础数据库查询。

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

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

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

Weights 设置索引同时包含稀疏索引和密集索引时的混合评分权重。

动态列

启用内容存储后,内容可以通过多种方式进行索引。请记住,输入文档采用 (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 with a bind parameter for similar clause
query = "SELECT id, text, score FROM txtai WHERE similar(:x)"
results = embeddings.search(query, parameters={"x": "feel good story"})

# Query with a bind parameter for column filter
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 支持存储和检索二进制对象。可以按以下示例所示检索二进制对象。

# Create embeddings index with content and object storage enabled
embeddings = Embeddings(content=True, objects=True)

# Get an image
request = open("demo.gif", "rb")

# Insert record
embeddings.index([("txtai", {"text": "txtai executes machine-learning workflows.",
                             "object": request.read()})])

# Query txtai and get associated object
query = "SELECT object FROM txtai WHERE similar('machine learning') LIMIT 1"
result = embeddings.search(query)[0]["object"]

# Query binary content with a bind parameter
query = "SELECT object FROM txtai WHERE similar(:x) LIMIT 1"
results = embeddings.search(query, parameters={"x": request.read()})

自定义 SQL 函数

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

# Translation pipeline
translate = Translation()

# Create embeddings index
embeddings = Embeddings(path="sentence-transformers/nli-mpnet-base-v2",
                        content=True,
                        functions=[translate]})

# Run a search using a custom SQL function
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('feel good story')
LIMIT 1
""")

查询翻译

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

embeddings.search("feel good story since yesterday")

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

select id, text, score from txtai where similar('feel good story') 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。请遵循前面的链接以了解有关此语法的更多信息。

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

# Find all paths between id: 0 and id: 5 between 1 and 3 hops away
embeddings.graph.search("""
MATCH P=({id: 0})-[*1..3]->({id: 5})
RETURN P
""")

# Standard embeddings search as graph
embeddings.search("query", graph=True)

子索引

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

# Query with index parameter
embeddings.search("query", index="subindex1")

# Specify with 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,则支持动态列。