数据库内部的向量使用 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_embeddingORDER BY embedding <=> $1LIMIT 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 上编辑此页。