查询指南
本节介绍如何使用txtai查询数据。最简单的搜索数据方法是构建一个包含所需内容的自然语言字符串。txtai还支持使用SQL进行查询。我们将在这里介绍这两种方法。
自然语言查询
在最简单的情况下,查询是文本,结果是与查询文本最相似的索引文本。
embeddings.search("feel good story")
embeddings.search("wildlife")
上述查询在索引中搜索与feel good story
和wildlife
相似的匹配项。如果启用了内容存储,则返回一个{**查询列}
的列表。否则,返回一个(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,就支持动态列。