数据库内部的向量使用 vector 列存储在常规 PostgreSQL 表中。vector 列类型由 pgvector 扩展提供。存储向量的常用方法是与它们索引的数据一起存储。例如,为了存储文档的嵌入,一个常见的表结构是

CREATE TABLE IF NOT EXISTS document_embedding (
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
document_id BIGINT FOREIGN KEY(document.id)
metadata JSONB,
contents TEXT,
embedding VECTOR(1536)
)

该表包含一个主键,一个指向文档表的外键,一些元数据,正在嵌入的文本(在 contents 列中),以及嵌入向量。

这看起来可能有点奇怪的设计:为什么嵌入不只是文档表中的一个单独列?答案与嵌入模型和 LLM 的上下文长度限制有关。当嵌入数据时,您可以嵌入的内容长度是有限制的(例如,OpenAI 的 ada-002 限制为 8191 个 tokens ),因此,如果您要嵌入一段长文本,则必须将其分解为较小的块并分别嵌入每个块。因此,在数据库层考虑这个问题时,通常在被嵌入的事物和嵌入之间存在一对多的关系,这通过从嵌入到事物的外键来表示。

当然,如果您不想将原始数据存储在数据库中,而只是存储嵌入,那也完全可以。只需从表中省略外键即可。另一种流行的替代方法是将外键放入元数据 JSONB 中。

向量的规范查询是查找最接近用户查询嵌入的查询向量。 这也称为查找 K 最近邻

在下面的示例查询中,$1 是一个参数,用于获取查询嵌入,<=> 运算符计算查询嵌入与数据库中存储的嵌入向量之间的距离(并返回一个浮点值)。

SELECT *
FROM document_embedding
ORDER BY embedding <=> $1
LIMIT 10

上面的查询返回查询的嵌入与行的嵌入之间距离最小的 10 行。当然,由于这是 PostgreSQL,您可以添加额外的 WHERE 子句(例如元数据上的过滤器)、连接等。

上面显示的查询使用称为余弦距离(使用 <=> 运算符)来衡量两个嵌入的相似程度。但是,有多种方法可以量化两个向量之间的距离。

注意

在实践中,距离度量方法的选择并不重要,建议大多数应用都坚持使用余弦距离。

以下是三种常见向量距离度量的简明描述

  • 余弦距离,又名角度距离:这测量两个向量之间角度的余弦值。 从数学意义上讲,它不是真正的“距离”,而是一种相似性度量,其中较小的角度对应于较高的相似性。余弦距离在高维空间中特别有用,在这些空间中,向量的大小(它们的长度)不太重要,例如在文本分析或信息检索中。它的范围从 -1(表示完全相反)到 1(完全相同),其中 0 通常表示正交性(没有相似性)。有关更多信息,请参阅 余弦相似度

  • 负内积:这只是两个向量的内积(也称为点积)的负值。内积根据向量的大小和它们之间角度的余弦值来衡量向量的相似性。较高的内积表示更高的相似性。但是,重要的是要注意,与余弦相似度不同,向量的大小会影响内积。

  • 欧几里得距离:这是欧几里得空间中两点之间的“普通”直线距离。就向量而言,它是向量的对应元素之间平方差之和的平方根。此度量对向量的大小敏感,并广泛用于聚类和最近邻搜索等各个领域。

许多嵌入系统(例如 OpenAI 的 ada-002)使用长度为 1 的向量(单位向量)。对于这些系统,所有三种度量的排名(排序)是相同的。特别是,

  • 余弦距离是 1−点积
  • 负内积是 −点积
  • 欧几里得距离与点积相关,其中平方欧几里得距离是 2(1−点积)

建议使用余弦距离,尤其是在单位向量上。这些建议基于 OpenAI 的 建议 以及单位向量上不同距离的排名保持不变的事实。

在 PostgreSQL 和其他关系数据库中,索引是一种加速查询的方法。对于向量数据,索引加速了上面显示的相似性搜索查询,您可以在其中找到与给定查询嵌入最相似的嵌入。这个问题通常被称为查找 K 最近邻

注意

“索引”一词在向量数据库的上下文中具有多种含义。它可以指代数据的存储机制和提高查询效率的工具。这些文档使用后一种含义。

查找 K 最近邻在 PostgreSQL 中并不是一个新问题,但现有技术仅适用于低维数据。当处理大于约 10 维的数据时,由于“维度灾难”,这些方法不再有效。鉴于嵌入通常包含一千多个维度(OpenAI 的为 1,536),因此必须开发新技术。

在如此高维空间中有效地搜索没有已知的精确算法。然而,有一些优秀的近似算法属于近似最近邻算法的范畴。

作为 Timescale 上的 pgai 的一部分,有 3 种不同的索引算法可用:StreamingDiskANN、HNSW 和 ivfflat。下表说明了这些算法之间的高级差异

算法构建速度查询速度更新后是否需要重建
StreamingDiskANN最快
HNSW
ivfflat最快最慢

有关每个索引在 100 万个 OpenAI 嵌入数据集上的性能详情,请参阅性能基准

对于大多数应用,建议使用 StreamingDiskANN 索引。

关键词

在此页面上发现问题?报告问题 或 在 GitHub 上编辑此页