使用 pgvector 将 PostgreSQL 与语义搜索/RAG 集成的教程

技术背景介绍

在大语言模型 (LLMs) 和语义搜索的兴起中,结合结构化的关系型数据库 (如 PostgreSQL) 进行增强型查询变得越来越有价值。这种方法常用于 RAG (Retrieval-Augmented Generation) 场景,例如 FAQ 问答、文档检索、推荐系统等。

pgvector 是用于 PostgreSQL 的一个扩展,它支持稠密向量的存储和操作。通过 pgvector,可以将嵌入向量直接存储在数据库中,同时利用 SQL 的灵活性执行高性能的近似向量搜索。

本文将通过示例演示如何配置和使用 pgvector 执行语义搜索/RAG任务。


核心原理解析

关键流程如下:

  1. 嵌入存储:将 LLM 或其他模型生成的嵌入向量存储在 PostgreSQL 的 pgvector 扩展中。
  2. 向量搜索:通过 pgvector 实现高效的向量相似度搜索,例如基于余弦相似度查询。
  3. RAG 整合:将检索到的结构化/非结构化数据与生成式模型(如 ChatGPT)融合,生成合理的答案。

pgvector 的核心特点:

  • 提供向量列类型,例如 vector(1536)
  • 支持计算向量相似度:L2 距离 (Euclidean)、内积 (Dot Product)、余弦相似度 (Cosine).

代码实现演示

以下是从环境配置到基本应用的完整代码示例。

1. 环境配置

我们首先需要一个带有 pgvector 扩展的 PostgreSQL 实例。可以通过 Docker 快速启动:

docker run \
  --name some-postgres \
  -e POSTGRES_PASSWORD=test \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_DB=vectordb \
  -p 5432:5432 \
  postgres:16

安装 pgvector 扩展:

登录到 PostgreSQL 实例并运行:

CREATE EXTENSION IF NOT EXISTS vector;

配置环境变量:

export POSTGRES_USER=postgres
export POSTGRES_PASSWORD=test
export POSTGRES_DB=vectordb
export POSTGRES_HOST=localhost
export POSTGRES_PORT=5432

2. 数据表准备

我们首先创建一个用户表,并准备一个专门的向量列来存储嵌入。

CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    content TEXT,
    embedding VECTOR(1536) -- 假设 OpenAI 嵌入维度为 1536
);

3. 嵌入生成与存储

我们假设使用 OpenAI 的嵌入模型来生成数据嵌入。以下是一个 Python 实现:

import openai
import psycopg2
from psycopg2.extras import execute_values

# 使用稳定可靠的API服务
client = openai.OpenAI(
    base_url='https://yunwu.ai/v1',  # 国内稳定访问
    api_key='your-openai-api-key'
)

# PostgreSQL 配置
conn = psycopg2.connect(
    dbname="vectordb",
    user="postgres",
    password="test",
    host="localhost",
    port="5432"
)

# 生成嵌入并存储到数据库
def generate_and_store_embeddings(documents):
    embeddings = []
    for doc in documents:
        response = client.embeddings.create(
            model="text-embedding-ada-002",
            input=doc
        )
        embeddings.append((doc, response['data']['embedding']))

    # 批量插入到 PostgreSQL
    with conn.cursor() as cur:
        execute_values(
            cur,
            "INSERT INTO documents (content, embedding) VALUES %s",
            embeddings
        )
        conn.commit()

# 示例文档
docs = ["This is a test document.", "PostgreSQL with pgvector is powerful.", "AI is transforming the world."]
generate_and_store_embeddings(docs)

4. 查询与语义搜索

基于 pgvector,我们可以执行相似度查询。例如,以下代码根据余弦相似度查找最相似的文档:

import numpy as np

def search_similar_documents(query, top_k=3):
    # 生成查询的嵌入
    response = client.embeddings.create(
        model="text-embedding-ada-002",
        input=query
    )
    query_embedding = np.array(response['data']['embedding'])

    with conn.cursor() as cur:
        # 查询最相似的文档
        cur.execute("""
            SELECT id, content, 1 - (embedding <=> %s) AS similarity
            FROM documents
            ORDER BY similarity DESC
            LIMIT %s;
        """, (query_embedding.tolist(), top_k))
        
        results = cur.fetchall()
    
    return results

# 示例查询
result = search_similar_documents("What is pgvector?")
for r in result:
    print(f"Document ID: {r[0]}, Content: {r[1]}, Similarity: {r[2]:.4f}")

应用场景分析

结合 pgvector 和 LLM 的应用场景非常广泛:

  1. 智能问答:根据用户问题检索最相关的文档并生成答案。
  2. 个性化推荐:基于用户兴趣匹配向量,进行推荐。
  3. 知识管理:增强知识库的搜索能力,实现语义级别的文档定位。

实践建议

  1. 嵌入缓存:对于大规模数据,提前生成并存储嵌入以避免重复计算。
  2. 索引优化:为 pgvector 向量列创建索引,提升查询性能。
    CREATE INDEX ON documents USING ivfflat (embedding) WITH (lists = 100);
    
  3. 安全性:确保 PostgreSQL 和嵌入 API 的访问控制安全。不要直接暴露数据库端口。
  4. 分布式部署:对于大规模系统,可考虑分布式向量搜索方案,例如结合 pgvector 和向量数据库如 Milvus。

如果遇到问题欢迎在评论区交流。

你可能感兴趣的:(postgresql,人工智能,数据库,python)