PostgreSQL 教程: 使用 pgvector 实现语义搜索

二月 20, 2025

摘要:在本教程中,您将学习如何在 PostgreSQL 中使用 pgvector 实现语义搜索。

目录

初始设置

近年来,由于生成式 AI 和大型语言模型生态系统的所有进步,语义搜索变得越来越流行。

在本教程中,我们将会使用 Kaggle 上的电影数据集,其中包括了截至 2017 年的 45000 部电影,这样的数据量对我们来说已经足够了。

我们将会使用 pgvector,这是一个 PostgreSQL 的开源扩展,它增加了对向量运算和相似性搜索的支持。它允许您直接在 PostgreSQL 数据库中存储、索引和查询向量数据。首先,让我们创建一个存放电影数据集的表:

CREATE TABLE IF NOT EXISTS movies (
    id integer,
    imdb_id text,
    title text,
    tagline text,
    overview text,
    release_date date,
    vote_average float,
    embedding vector(1536)
);

现在,让我们来使用 pgvector 和 OpenAI 嵌入模块,构建一个简单的语义搜索引擎!

import openai
import psycopg2
import csv

# Set up OpenAI API (replace with your actual API key)
openai.api_key = "your_openai_api_key"

# Function to get embeddings from OpenAI
def get_embedding(text):
    response = openai.embeddings.create(input=text, model="text-embedding-ada-002")
    return response['data'][0]['embedding']

# Function to add a document
def add_document(cur, row):
    content = """
                 Title: {0}
                 Tagline: {1}
                 Overview: {2}
                 Release date: {3}
                 Genres: {4}""".format(
                 row['title'],
                 row['tagline'],
                 row['overview'],
                 row['release_date'],
                 row['genres'])
    embedding = get_embedding(content)
    cur.execute("""INSERT INTO movies
                   (id, imdb_id, title, tagline, overview, release_date, vote_average, embedding)
                   VALUES (%s, %s, %s, %s, %s, %s, %s, %s)""",
                (row['id'], row['imdb_id'],
                 row['title'], row['tagline'], row['overview'], row['release_date'],
                 row['vote_average'], embedding))

# Connect to the database
conn = psycopg2.connect("dbname=your_database user=your_username")
cur = conn.cursor()

with open("./movies_metadata.csv", "r") as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        print(row['first_name'], row['last_name'])
        add_document(cur, row)
        conn.commit()

# Clean up
cur.close()
conn.close()

它使用了 OpenAI 的文本嵌入模型来嵌入文档,并将它们存储到带有 pgvector 的 PostgreSQL 数据库中。

演示

如果你搜索 “old movies”,你会得到一些老电影,因为我们在嵌入内容中包含了发布日期。

还有有趣的地方;如果你搜索 “virtual reality”,你会在前 20 个结果中得到 Oculus,这是一部由 Mike Flanagan 创作的恐怖电影。这部电影与 VR 没有任何关系,但标题刚好是一种流行的 VR 耳机的名称,这表明该模型有某种世界性的知识。

# Function to search for similar documents
def search_documents(query, limit=5):
    query_embedding = get_embedding(query)
    cur.execute("""
        SELECT title, overview, embedding <-> %s AS distance
        FROM movies
        ORDER BY distance
        LIMIT %s
    """, (query_embedding, limit))
    return cur.fetchall()

# Connect to the database
conn = psycopg2.connect("dbname=your_database user=your_username")
cur = conn.cursor()

# Perform a search
search_query = "wizard school poor boy"
results = search_documents(search_query)
print(f"Search results for: '{search_query}'")
for i, (title, overview, distance) in enumerate(results, 1):
    print(f"{i}. {title} {overview} (Distance: {distance:.4f})")

# Clean up
cur.close()
conn.close()

结论

pgvector 为 PostgreSQL 带来了强大的向量相似性搜索能力,对于希望将 AI 驱动的功能添加到基于 PostgreSQL 的现有应用程序的开发人员,它是一个绝佳选择。

虽然 pgvector 可能无法提供与 Pinecone 或 Milvus 等专用向量数据库相同的可扩展性和专业功能,但它与 PostgreSQL 的无缝集成使其成为许多场景的一个有吸引力的选择。

对于已经使用了 PostgreSQL 的项目,它特别适合需要在不引入新数据库系统的情况下添加向量搜索能力。

我们鼓励你在自己的项目中尝试 pgvector。无论您是在构建推荐系统、语义搜索引擎,还是任何其他需要相似性搜索的应用程序,pgvector 都可以成为数据科学工具包中的一个宝贵工具。

了解更多

PostgreSQL 管理