使用pgvector和Node.js在PostgreSQL中实现语义搜索,无需大型语言模型
使用pgvector和Node.js在PostgreSQL中实现语义搜索,无需大型语言模型:MiniLM嵌入、分块处理、IVFFlat索引、距离运算符以及如何读取得分。
来源: Talk to Your Database Like a Human — No LLM Required: Semantic Search with Node.js + PostgreSQL
数据库能够用普通英语回答问题,且整个流程中无需任何语言模型。实现这一功能的正是向量搜索。借助 Node.js、PostgreSQL 以及 pgvector 扩展,你可以构建一个根据意图而非关键词进行匹配的系统,而其中仅需要一个将文本转换为数字的小型嵌入模型。
只要提出恰当的问题,关系型数据库在存储和检索数据方面一直表现优异。精确匹配、过滤和结构化查询功能强大,但适用范围有限。而向量数据库似乎是为解决不同问题而出现的:它根据内容的含义而非所含词汇来搜索非结构化数据。
四个需要弄清楚的术语
标记。模型处理的最低级别的文本单元。标记并不总是完整的单词,它可能是一个完整的单词如“hello”,也可能是片段(比如“unbelievable”可以拆分为“un”、“believ”和“able”),或是单个字符如“!”,或是少量的标点符号或空白字符。像“ChatGPT is great”这样的短语可能会被拆分为“Chat”、“G”、“PT”、“is”和“great”。
分块。较大文档中独立的小片段,通常为几句话或一个段落。若一次性将整个文档嵌入模型,效果会很差,因此需要先对其进行分块。分块能够加快处理速度,提高搜索精度,并确保结果与查询内容相关。
嵌入向量。一种用于表示文本、图像或音频的数值替代物,能够捕捉其含义。例如,MiniLM这样的机器学习模型就可以生成嵌入向量。可以把嵌入向量视为数据背后的核心思想。
向量。嵌入向量的实际存储形式:一组数字。
[0.2, -0.5, 0.9, ...]
这就是在安装了如 pgvector 这样的扩展后,存储在内存及 PostgreSQL 中的格式。
总而言之,其原理如下:文字、句子或图像会被转化为嵌入向量。含义相似的元素对应的向量会彼此靠近,而无关的元素对应的向量则相距较远。像“Hello world”这样的字符串会变成一长串浮点数:
// "Hello world" turns into this embedding:
const embedding = [0.01, -0.42, 0.15, ..., 0.99]; // ← this is a vector
然后该列表会被保存在原文旁边:
INSERT INTO documents (content, embedding)
VALUES ('Hello world', embedding);
为何关系型数据库不够用
传统的关系型数据库管理系统以表格、行和列的形式运作,能够轻松处理诸如“状态为OPEN的所有工单”或“2024年后创建的用户”之类的查询。然而现代应用还需要处理文档、对话、图片和音频等内容,单纯的全文匹配对此类数据作用有限。
向量数据库会在数据旁存储嵌入向量,并通过相似度和上下文来查找相关项。因此,你不必查询包含“error”这个词的文档,只需查询与认证问题相关的文档,即便“error”从未出现也能找到对应结果。这种比对是基于向量之间的数学距离,而非文本匹配。
常见的处理流程如下:
- 原始内容被输入:文档、工单或其他任何内容。
- 嵌入模型将其转换为向量。
- 这些向量会被存储起来,例如使用 pgvector 存储在 PostgreSQL 中。
- 近似最近邻索引可加快查询速度。
- 用户的查询也会被转换为向量。
- 数据库会返回与之最接近的向量,也就是语义上最相似的向量。
这带来了以下优势:
- 基于查询的语义而非仅其确切词汇进行语义搜索。
- 为大型语言模型提供长期记忆功能,通过保存过去的交互记录、文档或事实,使模型即便在训练数据中未见过这些内容也能回忆起来。
- 通过查找嵌入空间中相似的项或行为来提供推荐功能。
- 对文本、图像、音频或视频进行相似度搜索。
作为向量存储的 PostgreSQL
实现这一切无需更换新的数据库。借助 pgvector,PostgreSQL 可以直接存储嵌入向量,执行相似度查询,并利用如 IVFFlat 这样的索引来保持高速运行。您现有的数据库只需新增一项功能,即可从单纯存储数据转变为能够比较数据含义。搜索方式也从匹配文字转变为匹配含义。
逐步设置
1. 安装 PostgreSQL 并启用 pgvector。从官方下载页面安装 PostgreSQL,连接后启用该扩展:
CREATE EXTENSION IF NOT EXISTS vector;
2. 创建文档表格。该表格用于存储原始文本及其嵌入向量。定义中的384指的是all-MiniLM-L6-v2模型的输出维度。
-- Note: 384 is the embedding size output by all-MiniLM-L6-v2
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding VECTOR(384)
);
3. 添加向量索引。为保证相似度搜索的高效性,可使用近似最近邻索引:
CREATE INDEX documents_embedding_idx
ON documents
USING ivfflat (embedding vector_l2_ops)
WITH (lists = 100);
该方法选择IVFFlat以实现快速近似查询,使用L2(欧几里得)距离进行度量,并将向量划分为100个簇。
4. 将查询操作符与索引匹配。查询中的操作符必须与构建索引时所使用的操作符类别一致。pgvector提供了多种操作符,每种操作符都有对应的类别。此示例使用<#>进行查询,并配置了vector_l2_ops。需要注意的是,在pgvector的文档中,L2距离通常与<->搭配使用,而<#>表示负内积,因此请确保查询与索引的设置相匹配。
5. 运行项目。一个完整的可运行示例位于名为vectorgarquer/vectorized-database-embeddings的GitHub仓库中。克隆或 fork该仓库,然后安装依赖项:
npm install
将 .env.example 复制到项目根目录下的 .env 文件中,并填写您的 PostgreSQL 连接信息。之后启动它:
npm start
6. 观察其搜索过程。程序启动后会自动建立连接、插入嵌入向量并执行语义搜索,无需进一步输入操作。之后你可以向它提供自己的数据与查询条件。示例中搜索了“生成式AI是什么意思?”,它在数据库中找到的匹配结果如下所示:
Search Results:
[1] Distance: -0.7562
n be represented in another modality such as text.
2.2 A Model-, System-, and Application-Level View
of Generative AI
2.2.1 Model-Level View
A generative AI model is a type of machine learning
architecture that uses AI algorithms to create novel data
instances, drawing upon the patterns and relationships
observed in the training data. A generative AI model is of
critically central yet incomplete nature, as it requires fur-
ther fine-tuning to specific tasks thro
[2] Distance: -0.7562
n be represented in another modality such as text.
2.2 A Model-, System-, and Application-Level View
of Generative AI
2.2.1 Model-Level View
A generative AI model is a type of machine learning
architecture that uses AI algorithms to create novel data
instances, drawing upon the patterns and relationships
observed in the training data. A generative AI model is of
critically central yet incomplete nature, as it requires fur-
ther fine-tuning to specific tasks thro
[3] Distance: -0.7562
n be represented in another modality such as text.
2.2 A Model-, System-, and Application-Level View
of Generative AI
2.2.1 Model-Level View
A generative AI model is a type of machine learning
architecture that uses AI algorithms to create novel data
instances, drawing upon the patterns and relationships
observed in the training data. A generative AI model is of
critically central yet incomplete nature, as it requires fur-
ther fine-tuning to specific tasks thro
[4] Distance: -0.7562
n be represented in another modality such as text.
2.2 A Model-, System-, and Application-Level View
of Generative AI
2.2.1 Model-Level View
A generative AI model is a type of machine learning
architecture that uses AI algorithms to create novel data
instances, drawing upon the patterns and relationships
observed in the training data. A generative AI model is of
critically central yet incomplete nature, as it requires fur-
ther fine-tuning to specific tasks thro
[5] Distance: -0.7094
assistants, personalized education and service, and digital
art. As such, generative AI has substantial implications for
BISE practitioners and scholars as an interdisciplinary
research community. In our Catchword article, we offered
a conceptualization of the principles of generative AI along
a model-, system-, and application-level view as well as a
social-technical view and described limitations of current
generative AI. Ultimately, we provided an impactful
rese
查看输出结果
运行完成后,你会得到如下格式的列表:
Search Results:
[1] Distance: -0.7562
...
[5] Distance: -0.7094
...
距离值表示存储的文本块与查询嵌入向量的接近程度。文本块和查询都会被转换为向量,PostgreSQL通过pgvector来衡量二者之间的差距。规则很简单:距离越小,内容相似度越高。
这些数值为负数,例如:
-0.7562
这是因为 <#> 运算符会返回一个取反后的值,这样普通排序就会将最相似的行排在最前面。实际上,数值越负表示匹配度越高、相关性越强,而数值越接近零则表示匹配度越低、相关性越弱。
从排名来看,第1到第4条结果的得分均为-0.7562,因此它们对查询的相关性相同。第5条结果的得分为-0.7094,虽然仍有相关性,但相似度稍低。
你可能还会注意到一些文本几乎完全相同的结果,这是正常现象。原始文档被分割成了多个片段,相邻的片段会存在内容重叠或重复,而且每个片段都有独立的嵌入向量。
结果所显示的内容
即使在查询时没有大型语言模型,该系统依然能够理解文本的含义而不仅仅是关键词,它会筛选出符合上下文的文本,并根据向量相似度对其进行排序。返回的段落多围绕生成式AI模型、模型级视角以及机器学习架构展开,由此可见该搜索功能是在概念层面而非确切词汇层面工作的。
其结果就是一种内置在PostgreSQL中的语义搜索引擎。查询时无需大型语言模型,也没有独立的向量数据库,嵌入向量与pgvector共同完成所有工作。
相关阅读
- 使用 Redis 为 LLM 智能体实现语义缓存:降低成本与延迟 — 语义缓存如何减少 LLM 的使用成本与延迟:包括嵌入向量、阈值设置、Redis 与 RedisVL 的应用、精度调优,以及在智能体工作流中实现子问题的缓存。
- 为何 AI 分析智能体需要语义层而非原始 SQL — 直接对原始数据表进行文本转 SQL 操作会自行定义指标并忽略访问规则。了解如何通过 Cube 等语义层结合 MCP,为智能体提供受规则约束的业务含义。