RAG 中的 SQL 为什么是 PgSQL
RAG 是什么?
RAG 的官方定义是 Retrieval-Augmented Generation,也就是检索增强生成技术。
简单来说,RAG 并不是让大语言模型直接回答所有问题,而是在用户提出问题之后,先从外部知识库中检索与问题相关的内容,然后将检索到的内容作为上下文交给大语言模型,最终生成答案。
例如:
用户问题
↓
将问题转换为向量
↓
在向量数据库中进行相似度搜索
↓
获取相关文档
↓
将文档作为上下文交给大语言模型
↓
生成最终答案
假设知识库中存在以下内容:
Spring Boot 是一个基于 Spring 的快速开发框架。
当用户提问:
Spring Boot 是什么?
RAG 系统会先将用户的问题转换为向量,然后在知识库中寻找语义上最相似的文本。
如果检索到:
Spring Boot 是一个基于 Spring 的快速开发框架。
那么这段文本就会作为上下文传递给大语言模型。
因此,RAG 的核心流程可以概括为:
文档
↓
文本切分
↓
Embedding 模型
↓
生成向量
↓
存储向量
↓
用户提问
↓
生成问题向量
↓
相似度搜索
↓
获取相关文档
↓
大语言模型生成答案
所以,一个 RAG 系统通常需要具备以下能力:
- 文本数据存储能力
- 向量数据存储能力
- 向量相似度计算能力
- 高效的向量检索能力
这也是为什么数据库是否支持向量搜索,成为构建 RAG 系统时需要考虑的重要问题。
所以,RAG 需要的不一定是独立的向量数据库,但至少需要一种能够高效存储和搜索向量数据的方案。
PostgreSQL 和 MySQL 的区别
在我学习的 RAG 项目中,使用的是 PostgreSQL,而不是我更加熟悉的 MySQL。
这让我产生了一个疑问:
为什么 RAG 项目经常使用 PostgreSQL?
要回答这个问题,首先需要了解 PostgreSQL 和 MySQL 在向量搜索方面的能力。
PostgreSQL
PostgreSQL 本身是一款功能强大的开源关系型数据库。
通过安装 pgvector 扩展,PostgreSQL 可以支持向量数据的存储和相似度搜索。
首先安装扩展:
CREATE EXTENSION vector;
然后就可以使用:
VECTOR
数据类型。
例如:
CREATE TABLE vector_store (
id UUID PRIMARY KEY,
content TEXT,
metadata JSONB,
embedding VECTOR(768)
);
这里:
content
用于保存原始文本。
metadata
用于保存元数据,例如:
{
"knowledge": "group-buy-market-liergou",
"fileName": "README.md"
}
而:
embedding
用于保存文本经过 Embedding 模型转换后的向量。
例如:
原始文本:
Spring Boot 是一个 Java 开发框架。
↓
Embedding 模型
↓
[0.12, -0.31, 0.55, ...]
最终这个向量就可以保存到:
embedding VECTOR(768)
字段中。
这里的 768 代表向量的维度。
不同的 Embedding 模型,生成的向量维度可能不同。
例如:
Embedding 模型
↓
生成 768 维向量
Embedding 模型
↓
生成 1536 维向量
Embedding 模型
↓
生成 3072 维向量
因此,数据库中的:
VECTOR(768)
必须与 Embedding 模型实际生成的向量维度保持一致。
PostgreSQL 如何进行向量搜索?
假设数据库中存在以下数据:
文档 A → [0.1, 0.2, 0.3]
文档 B → [0.8, 0.7, 0.6]
文档 C → [0.2, 0.3, 0.4]
用户的问题经过 Embedding 模型转换之后得到:
查询向量 → [0.1, 0.2, 0.35]
接下来就可以计算查询向量与数据库中其他向量之间的距离。
例如:
SELECT *
FROM vector_store
ORDER BY embedding <=> '[0.1, 0.2, 0.35]'
LIMIT 5;
其中:
<=>
可以用于计算余弦距离。
距离越小,表示两个向量越相似。
最终数据库就可以找到:
与用户问题最相关的前 5 个文档
这就是 RAG 中的检索过程。
pgvector 的索引
如果数据量比较小,直接计算每一条向量之间的距离也许没有问题。
但是,如果数据库中有:
100 万条向量
每次查询都与所有向量进行计算,效率就会比较低。
因此,pgvector 支持使用近似最近邻搜索索引。
常见的索引包括:
IVFFlat
HNSW
例如:
CREATE INDEX ON vector_store
USING hnsw (embedding vector_cosine_ops);
这样在进行向量搜索时,就可以通过索引提高搜索效率。
需要注意的是:
向量搜索的准确率和搜索速度之间通常需要进行权衡。
使用近似最近邻搜索时,并不一定会精确计算所有向量之间的距离,而是通过索引快速找到最可能相关的结果。
MySQL 能不能存储向量?
答案是:
可以。
不能简单地说:
MySQL 不支持向量。
较新的 MySQL 版本已经提供了 VECTOR 数据类型和向量相关函数,可以用于存储和处理向量数据。
例如:
CREATE TABLE items (
id BIGINT PRIMARY KEY,
embedding VECTOR(768)
);
MySQL 也提供了向量距离计算相关的功能。
例如:
VECTOR
↓
DISTANCE()
↓
计算两个向量之间的距离
因此,从理论上来说:
MySQL
+
VECTOR
