有一千種方法(可能更多)可以加速 Postgres 工作負載。這取決于您存儲數(shù)據(jù)、查詢數(shù)據(jù)的方式、數(shù)據(jù)有多大以及運行這些查詢的頻率。在這篇博文中,我們將探討 pgvector 如何幫助處理 Postgres 中基于 AI 的工作負載,使您的數(shù)據(jù)庫向量操作更快、更高效。
pgvector:在 Postgres 中存儲和查詢向量
pgvector是一個 PostgreSQL 擴展,允許您存儲、查詢和索引向量。
Postgres 尚不具備原生向量功能(從 Postgres 16 開始),而 pgvector 旨在填補這一空白。您可以將向量數(shù)據(jù)與其他數(shù)據(jù)一起存儲在 Postgres 中,并進行向量相似性搜索,同時仍然可以利用 Postgres 提供的所有強大功能。
誰需要向量相似性搜索?
在處理高維數(shù)據(jù)時,尤其是在推薦引擎、圖像搜索和自然語言處理等應用中,向量相似性搜索是一項關鍵功能。許多人工智能應用程序會涉及根據(jù)用戶行為或內(nèi)容相似性查找相似的項目或推薦。pgvector 可以高效地執(zhí)行向量相似度搜索,使其適用于推薦系統(tǒng)、基于內(nèi)容的過濾和基于相似度的 AI 任務。
pgvector 擴展與 Postgres 無縫集成 - 允許用戶在現(xiàn)有數(shù)據(jù)庫基礎設施中利用其功能。這簡化了人工智能應用程序的部署和管理,因為不需要單獨的數(shù)據(jù)存儲或復雜的數(shù)據(jù)傳輸過程。
向量到底是什么?
簡而言之,向量只是數(shù)字列表。如果您曾經(jīng)學習過線性代數(shù)課程,那么現(xiàn)在是獲得好處的時候了,因為相似性搜索畢竟是在進行一系列向量運算!
在幾何中,向量表示 n 維空間中的坐標,其中 n 是維數(shù)。下圖中有一個二維向量 (n=2)。在機器學習中,我們使用高維向量,但想象它們并不像下面所示的簡單向量那么容易。
圖片來源:https://media5.datahacker.rs/2020/03/Picture36-1-768x712.jpg
應用示例:
在本文示例中,我們將存儲一些文檔,生成向量嵌入并將它們存儲在 Postgres 中。我們將對嵌入數(shù)據(jù)建立索引并對嵌入運行相似性查詢。
示例代碼:https://github.com/gulcin/pgvector_blog
先決條件:
已安裝 PostgreSQL(pgvector 支持 PostgreSQL 11+)
已安裝 pgvector 擴展(請參閱安裝說明)
擁有OpenAPI 帳戶并有一些信用余額(使用量少于 1 美元)。
安裝 pgvector 后,您可以在 Postgres 數(shù)據(jù)庫中通過創(chuàng)建擴展啟用它:
postgres=# Create extension vector;
CREATE EXTENSION
第 1 步:創(chuàng)建文檔表格
讓我們創(chuàng)建一個簡單的表來存儲文檔。該表中的每一行代表一個文檔,我們存儲文檔的標題和內(nèi)容。
創(chuàng)建文檔表:
CREATE TABLE documents (
id int PRIMARY KEY,
title text NOT NULL,
content TEXT NOT NULL
);
對于我們存儲的每個文檔,將生成一個嵌入,在這里我們創(chuàng)建一個 document_embeddings 表來存儲它們。您可以看到嵌入向量的大小為 1536,這是因為我們使用的 OpenAI 模型有 1536 維。
-- Create document_embeddings table
CREATE TABLE document_embeddings (
id int PRIMARY KEY,
embedding vector(1536) NOT NULL
);
讓我們使用 HNSW 索引對數(shù)據(jù)進行索引。
CREATE INDEX document_embeddings_embedding_idx ON document_embeddings USING hnsw (embedding vector_l2_ops);
我將在下一篇博客文章中討論向量數(shù)據(jù)庫中的索引,因此我不會在這里詳細介紹,但我們知道HNSW比 IVFFlat 具有更好的查詢性能。
同樣對于IVFFlat索引,建議在表有一些數(shù)據(jù)后創(chuàng)建索引,但 HNSW 索引沒有像 IVFFlat 那樣的訓練步驟,因此可以在表中沒有任何數(shù)據(jù)的情況下創(chuàng)建索引。您可能已經(jīng)注意到,我在按照建議將數(shù)據(jù)插入表之前創(chuàng)建了索引。
現(xiàn)在我們可以將一些示例數(shù)據(jù)插入表中。對于示例數(shù)據(jù),我選擇了 Postgres 擴展及其簡短描述。
-- Insert documents into documents table
INSERT INTO documents VALUES ('1', 'pgvector', 'pgvector is a PostgreSQL extension that provides support for vector similarity search and nearest neighbor search in SQL.');
INSERT INTO documents VALUES ('2', 'pg_similarity', 'pg_similarity is a PostgreSQL extension that provides similarity and distance operators for vector columns.');
INSERT INTO documents VALUES ('3', 'pg_trgm', 'pg_trgm is a PostgreSQL extension that provides functions and operators for determining the similarity of alphanumeric text based on trigram matching.');
INSERT INTO documents VALUES ('4', 'pg_prewarm', 'pg_prewarm is a PostgreSQL extension that provides functions for prewarming relation data into the PostgreSQL buffer cache.');
第 2 步: 生成嵌入
現(xiàn)在我們已經(jīng)存儲了文檔,我們將使用嵌入模型將文檔轉(zhuǎn)換為嵌入(復雜的問題交給大模型來處理)。
圖片來源:https://cdn.openai.com/new-and-improved-embedding-model/draft-20221214a/vectors-1.svg
首先,我們來談談嵌入。我最喜歡OpenAI 文檔中的定義,因為它簡單切題:
“嵌入是浮點數(shù)的向量(列表)。兩個向量之間的距離衡量它們的相關性。距離小表明相關性高,距離大表明相關性低。”
因此,如果我們要比較兩個文檔在語義上的相關程度,則必須將這些文檔轉(zhuǎn)換為嵌入并對它們運行相似性搜索。
在本示例中,我使用了 OpenAI API 和 Python。有多個 API 提供商可供選擇,可以通過您選擇的語言使用這些 API??紤]簡單性以及我之前的使用經(jīng)驗,我選擇了 OpenAI API,Python 是我的首選語言。示例中使用的嵌入模型是“text-embedding-ada-002”,它非常適合我們的使用案例,因為它便宜且易于使用。在實際應用程序中使用此模型時,您可能需要根據(jù)具體用例評估不同的模型。
讓我們開始吧!下面的 Python 代碼,您需要獲取 OpenAI API 密鑰,并填寫連接字符串以連接到 Postgres 數(shù)據(jù)庫。
# Python code to preprocess and embed documents
import openai
import psycopg2
# Load OpenAI API key
openai.api_key = "sk-..." #YOUR OWN API KEY
# Pick the embedding model
model_id = "text-embedding-ada-002"
# Connect to PostgreSQL database
conn = psycopg2.connect(database="postgres", user="gulcin.jelinek", host="localhost", port="5432")
# Fetch documents from the database
cur = conn.cursor()
cur.execute("SELECT id, content FROM documents")
documents = cur.fetchall()
# Process and store embeddings in the database
for doc_id, doc_content in documents:
embedding = openai.Embedding.create(input=doc_content, model=model_id)['data'][0]['embedding']
cur.execute("INSERT INTO document_embeddings (id, embedding) VALUES (%s, %s);", (doc_id, embedding))
conn.commit()
# Commit and close the database connection
conn.commit()
以上代碼只是從數(shù)據(jù)庫中獲取文檔內(nèi)容,并使用 OpenAI API 生成嵌入并將其存儲回數(shù)據(jù)庫中。這對于我們的小型數(shù)據(jù)庫來說很好,但在現(xiàn)實場景中,您可能希望對現(xiàn)有數(shù)據(jù)使用批處理,并且可能需要某種事件觸發(fā)器或更改流,以在數(shù)據(jù)庫更改時保持向量最新。
第 3 步:查詢嵌入
現(xiàn)在我們已經(jīng)將嵌入存儲在數(shù)據(jù)庫中,我們可以使用 pgvector 查詢它們。下面的代碼顯示了如何執(zhí)行相似性搜索來查找與給定查詢文檔相似的文檔。
# Python code to preprocess and embed documents
import psycopg2
# Connect to PostgreSQL database
conn = psycopg2.connect(database="postgres", user="gulcin.jelinek", host="localhost", port="5432")
cur = conn.cursor()
# Fetch extensions that are similar to pgvector based on their descriptions
query = """
WITH pgv AS (
SELECT embedding
FROM document_embeddings JOIN documents USING (id)
WHERE title = 'pgvector'
)
SELECT title, content
FROM document_embeddings
JOIN documents USING (id)
WHERE embedding <-> (SELECT embedding FROM pgv) < 0.5;"""
cur.execute(query)
# Fetch results
results = cur.fetchall()
# Print results in a nice format
for doc_title, doc_content in results:
print(f"Document title: {doc_title}")
print(f"Document text: {doc_content}")
print()
該查詢首先獲取標題為“pgvector”的文檔的嵌入向量,然后使用相似性搜索來獲取具有相似內(nèi)容的文檔。
請注意 <->
運算符,這是所有 pgvector 魔法發(fā)生的地方。這就是我們?nèi)绾问褂?HNSW 索引獲得兩個向量之間的相似性。“0.5”是一個相似性閾值,它將高度依賴于用例,并且需要在實際應用程序中進行微調(diào)。
返回結(jié)果時刻
當我們對導入的數(shù)據(jù)運行查詢腳本時,我們看到相似性搜索找到了兩個與 pgvector 相似的文檔,其中之一就是 pgvector 本身。
? python3 query.py
Document title: pgvector
Document text: pgvector is a PostgreSQL extension that provides support for vector similarity search and nearest neighbor search in SQL.
Document title: pg_similarity
Document text: pg_similarity is a PostgreSQL extension that provides similarity and distance operators for vector columns.
本文內(nèi)容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。