Want to Become a Sponsor? Contact Us Now!🎉

vector-database
Pgvector:無料でPostgreSQLをベクトルデータベースに変える?

Pgvector:無料でPostgreSQLをベクトルデータベースに変える?

Published on

もしもあなたがPostgreSQLを使用していて、まだpgvectorについて聞いたことがないのであれば、これはゲームチェンジングな拡張機能を見逃していることになります。pgvectorは、PostgreSQLデータベースを活用するための究極のツールであり、効率的なベクトルのストレージと類似度検索を可能にします。これは単なる追加モジュールではなく、PostgreSQLとシームレスに統合された完全なソリューションです。

なぜpgvectorが重要なのでしょうか?現代のデータ駆動型の世界では、大規模なベクトルの効率的なストレージとクエリが、機械学習や推薦システムなどの応用において重要です。pgvectorはこれを実現するだけでなく、非常に効率的で高速な性能を発揮します。

PostgreSQLユーザーにとってpgvectorはなぜ不可欠なのか

pgvectorとは?

pgvectorは、ベクトルのストレージとそのベクトル内での類似検索を特化したPostgreSQLの拡張機能です。伝統的なPostgreSQLのデータ型とは異なり、pgvectorは高次元データに最適化されており、機械学習モデル、画像認識、自然言語処理のタスクに最適です。

ℹ️

pgvectorの主な機能:

  • 効率的なベクトルのストレージ:高次元ベクトルをデータの整合性を損なうことなく圧縮します。高次元データはストレージの悩みの種となることがあるため、これは大きな進歩です。

  • 複数の距離尺度:ユークリッド距離、コサイン距離、マンハッタン距離など、pgvectorはさまざまな距離尺度をサポートしています。さまざまな距離尺度を選択する柔軟性を備えており、特定のユースケースに最適なものを選ぶことができます。

  • シームレスな統合:pgvectorの最も素晴らしいところの一つは、PostgreSQLとのシームレスな統合です。異なるデータベース間で切り替える必要はありません。pgvectorはネイティブの拡張機能として機能し、PostgreSQL内で複雑なクエリを実行することができます。

さて、数字の話に入りましょう。pgvectorを使用すると、約1800クエリ/秒の速度で100万件のOpenAIエンベディングを実行し、91%の精度を達成することができます。より高い精度を目指す場合、約670クエリ/秒の速度で98%の精度を達成することが可能です。これらの指標は印象的だけでなく、革新的です。

pgvectorのパフォーマンスは、高い速度や精度だけでなく、非常にスケーラブルでもあります。8コアARM、32 GBのRAMを搭載した環境から、64コアARM、256 GBのRAMを搭載した環境まで、pgvectorはハードウェアリソースを最大限に活用して美しくスケーリングします。

pgvectorの実際の速度はどれくらい速いのか?(pgvectorのベンチマーク)

pgvectorの速度と精度を解説

ベクトル検索の速度と精度を求めるなら、pgvectorが最適です。最新バージョンのpgvector 0.4.0は、そのパフォーマンスを計測するために厳密なテストを受けています。詳細について説明しましょう:

ベンチマークの方法

  • テストランナー:Pythonスクリプトを使用して、データのアップロード、インデックスの作成、クエリの実行を行いました。
  • ランタイム:各テストは30〜40分間実行され、パフォーマンスを測定するためにさまざまなワークロードレベルがカバーされました。
  • プリウォーミングRAM:各テストの前に、10,000〜50,000件の「ウォームアップ」クエリを実行してRAMの利用を最適化しました。

テストに使用されたハードウェア

  • 2XL:8コアARM、32 GB RAM
  • 4XL:16コアARM、64 GB RAM
  • 8XL:32コアARM、128 GB RAM
  • 12XL:48コアARM、192 GB RAM
  • 16XL:64コアARM、256 GB RAM

データセット

テストにはdbpedia-entities-openai-1M (opens in a new tab)データセットが使用されました。これは1536次元の100万件のエンベディングを含んでいます。このデータセットはOpenAIを使用して作成され、Wikipediaの記事をベースにしています。

パフォーマンスの結果

  • プローブを10に設定した場合:pgvectorはaccuracy@10が0.91、QPS(クエリ/秒)が380という結果を達成しました。
  • プローブを40に設定した場合:pgvectorはさらに高速化し、accuracy@10が0.98、QPSが140という結果を維持しました。

データベースのスケーリング

pgvectorの性能は、データベースのサイズと予測可能なスケーリングが可能です。たとえば、プローブを40に設定した場合、4XLインスタンスではaccuracy@10が0.98、QPSが270を達成しました。8XLインスタンスではaccuracy@10が0.98、QPSが470となり、Qdrantの結果を上回りました。

pgvectorのベンチマーク結果

64コア、256 GBのサーバー上で、pgvectorはバージョン0.4.0で約1800 QPSと0.91の精度を達成しました。これは新しいバージョンでもさらなるパフォーマンス向上が期待されていることに注意してください。

pgvectorが商用のベクトルデータベースに勝る理由

pgvectorの印象的なベンチマークを詳しく見た後、Milvusなどの他の商用ベクトルデータベースソリューションと比較してどのようになるのか気になるかもしれません。さて、以下で解説しましょう:

統合の容易さ

  • Milvus独立したサービスとして動作し、技術スタックを複雑にします。
  • pgvector:PostgreSQLとシームレスに統合され、技術スタックを簡素化します。

データ同期

  • Milvus:ネイティブの統合がなく、データ同期の問題が発生します。
  • pgvectorネイティブの統合を提供し、同期の手間を省きます。

パフォーマンス指標

  • Milvus:pgvectorのパフォーマンスには及ばないです。
  • pgvector1800 QPS91%の精度100万件のOpenAIエンベディングを処理します。
メトリックMilvuspgvector
統合の複雑さ
データ同期問題があるシームレス
クエリ速度(QPS)低い1800
精度低い91%

要約すると、ベクトルの保存と検索について、効率的で高性能な解決策をお探しの場合は、pgvectorが明らかな勝者です。

pgvectorのパフォーマンス最適化のヒント

  • Postgresの設定を調整する:RAMとCPUコアと合わせるようにしてください。
  • データベースの事前ウォームアップ:以前説明したウォームアップのテクニックを使用してデータベースを事前に準備します。
  • 適切な距離関数を選択する:ベクトルが正規化されている場合は、L2やCosine距離よりも内積を優先します。
  • リストの定数を調整する:これを増やすことでクエリを加速させることができます。たとえば、OpenAIの埋め込みを使用したテストでは、提案された1000ではなく2000のリスト定数を使用しました。

これらの詳細なメトリックとヒントを見ると、pgvectorはベクトルの保存と類似性検索において堅牢なパフォーマンスを提供しており、PostgreSQLユーザーにとってトップの選択肢であることが明確です。

pgvectorでできること

pgvectorをオープンソースのベクトルデータベースとして使用する方法

pgvectorは単なる拡張機能ではありません。それはあなたのPostgreSQLデータベースを強力なベクトルデータベースに変える革新的なツールです。これは、専門のデータベースに切り替えることなく、高次元データでの複雑な操作を実行したい人に特に役立ちます。このセクションでは、pgvectorをオープンソースのベクトルデータベースとして設定および使用する方法について詳しく説明します。

インストールとセットアップ:

  1. リポジトリをクローンする:pgvector GitHubリポジトリをローカルマシンにクローンします。

    git clone https://github.com/your/pgvector/repo.git
  2. コンパイルとインストール:ディレクトリに移動し、拡張機能をコンパイルします。

    cd pgvector
    make
    make install
  3. データベースの設定:PostgreSQLデータベースにログインし、pgvector拡張機能を作成します。

    CREATE EXTENSION pgvector;
  4. テーブルの作成:高次元データを保存するベクトル列を持つテーブルを作成します。

    CREATE TABLE my_vectors (id SERIAL PRIMARY KEY, vector_field VECTOR(128));

基本操作:

  1. ベクトルの挿入:ベクトルフィールドにデータを挿入します。

    INSERT INTO my_vectors (vector_field) VALUES ('{1.1, 2.2, 3.3, ..., 128.128}');
  2. ベクトル検索:ベクトルフィールドを使用して類似性検索を実行します。

    SELECT * FROM my_vectors ORDER BY vector_field <-> '{3.3, 2.2, 1.1, ..., 128.128}' LIMIT 10;
  3. インデックス作成:類似性検索を高速化するためにインデックスを作成します。

    CREATE INDEX idx_vector_field ON my_vectors USING ivfflat(vector_field);

高度な機能:

  1. パラメータの調整:インデックスのパラメータを調整して速度と精度のバランスを取ることができます。

    SET pgvector.index_type = 'hnsw';
    SET pgvector.ef_search = 64;
  2. バッチ操作:pgvectorはベクトルの挿入や更新に対してバッチ操作をサポートしています。これは機械学習アプリケーションに特に便利です。

  3. 監視とオブザーバビリティ:PostgreSQLの組込みのモニタリングツールを使用してベクトル操作のパフォーマンスを監視することができます。

pgvectorのk-NN検索機能

k-NN検索とは?

k-NN(k-Nearest Neighbors)検索は、多次元空間で与えられた点に最も近い「k」点を見つけるためのアルゴリズムです。分類やクラスタリングなどの機械学習で広く使用されています。

pgvectorがk-NNを可能にする方法:

  • データ型:pgvectorはvectorという新しいデータ型を導入し、多次元データを格納できます。
  • 演算子:Euclidean距離の<->やcosine距離の<=>などの演算子を提供し、ベクトル間の類似性を計算できます。
  • インデックス作成:ベクトル列にインデックスを作成してk-NNクエリの高速化を図ることができます。

ここに、pgvectorを使用してk-NN検索を実行するSQL関数の例です:

CREATE OR REPLACE FUNCTION knn_search(query_vector vector, k int)
RETURNS TABLE(id INT, distance FLOAT)
LANGUAGE SQL STABLE AS $$
  SELECT id, query_vector <=> vector_column AS distance
  FROM your_table
  ORDER BY distance ASC
  LIMIT k;
$$;

pgvectorを使用してOpenAIの埋め込みを保存する

なぜOpenAIの埋め込みを保存するのですか? OpenAIの埋め込みは、テキストの意味を捉えた高次元ベクトルです。テキストの類似性、クラスタリング、分類などのタスクに役立ちます。

pgvectorを使用してOpenAIの埋め込みを保存する方法

  1. テーブルの作成vector型の列を持つPostgreSQLテーブルを作成します。
    CREATE TABLE documents (
      id SERIAL PRIMARY KEY,
      content TEXT,
      embedding VECTOR(1536)
    );
  2. データの挿入:OpenAIの埋め込みをembedding列に挿入します。
    INSERT INTO documents(content, embedding) VALUES ('some text', '{your 1536-dim vector}');
  3. クエリ:pgvectorの演算子を使用して埋め込みをクエリします。
    SELECT * FROM documents WHERE embedding <=> '{query vector}' < 0.5;

LangchainとPGVectorを組み合わせた高度なテキスト検索

LangchainとPGVectorを組み合わせることで、強力なテキスト検索と情報取得システムを作成することができます。以下は、PGVectorをLangchainと統合して高度なテキスト検索操作を実行する方法のガイドです。

前提条件

  • ノートブックの最初のセクションに示されているように、必要なパッケージをインストールし、環境変数を設定していることを確認してください。

ステップ1. Langchainコンポーネントを初期化する まず、OpenAIEmbeddingsTextLoaderCharacterTextSplitterなどのLangchainコンポーネントを初期化します。

from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import TextLoader
 
loader = TextLoader("your_text_file.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)

翻訳ログ: フロントマターはないので、そのまま全体を翻訳します。

docs = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()

ステップ2. PGVectorの初期化 次に、Postgresデータベースへの接続文字列を使用してPGVectorを初期化します。

from langchain.vectorstores.pgvector import PGVector
 
CONNECTION_STRING = "ここに接続文字列を入力してください"
COLLECTION_NAME = "ここにコレクション名を入力してください"
 
db = PGVector.from_documents(
    embedding=embeddings,
    documents=docs,
    collection_name=COLLECTION_NAME,
    connection_string=CONNECTION_STRING,
)

ステップ3. 類似性検索の実行 PGVectorのsimilarity_search_with_scoreメソッドを使用して、類似性検索を実行できます。

query = "ここに検索クエリを入力してください"
docs_with_score = db.similarity_search_with_score(query)
 
for doc, score in docs_with_score:
    print("スコア: ", score)
    print(doc.page_content)

ステップ4. Maximal Marginal Relevance (MMR) 検索 より高度な検索のために、Maximal Marginal Relevance (MMR) を使用して、クエリに対する類似性と選択されたドキュメントの多様性を最適化することができます。

docs_with_score = db.max_marginal_relevance_search_with_score(query)
 
for doc, score in docs_with_score:
    print("スコア: ", score)
    print(doc.page_content)

ステップ5. 既存の VectorStore での作業 既に既存のベクトルストアがある場合は、直接初期化してドキュメントを追加することができます。

store = PGVector(
    collection_name=COLLECTION_NAME,
    connection_string=CONNECTION_STRING,
    embedding_function=embeddings,
)
 
store.add_documents([Document(page_content="ここに新しいコンテンツを入力してください")])

ステップ6. 既存のベクトルストアの上書き 既存のコレクションを更新する必要がある場合は、上書きすることができます。

db = PGVector.from_documents(
    documents=docs,
    embedding=embeddings,
    collection_name=COLLECTION_NAME,
    connection_string=CONNECTION_STRING,
    pre_delete_collection=True,
)

ステップ7. ベクトルストアを検索器として使用する 最後に、ベクトルストアをより高度な操作のための検索器として使用することができます。

retriever = store.as_retriever()
print(retriever)

Amazon SageMaker、Amazon RDS for PostgreSQL、および pgvectorを使用したAIパワード検索の構築

このセクションでは、Amazon SageMakerとAmazon RDS for PostgreSQLを使用して、pgvector拡張機能を備えた製品カタログの類似性検索ソリューションを構築する方法を示します。トレーニング済みのHugging Faceモデルを使用してドキュメントの埋め込みを生成し、それらをRDS for PostgreSQLデータベースに保存します。そして、pgvectorの類似性検索機能を使用して、カスタマーの検索クエリに最も適合する製品カタログのアイテムを見つけます。

ソリューションの実装手順:

  1. SageMakerノートブックインスタンスのセットアップ: PythonコードをJupyterノートブックで実行するためのSageMakerノートブックインスタンスを作成します。

  2. データの準備: Amazon Translateを使用して、商品の説明をドイツ語から英語に翻訳します。

  3. モデルのホスティング: 事前にトレーニングされたHugging FaceモデルをSageMakerにデプロイし、製品カタログの384次元ベクトル埋め込みを生成します。

  4. データの保存: RDS for PostgreSQLに接続し、生のテキストとテキストの埋め込みを保存するためのテーブルを作成します。

  5. リアルタイム推論: SageMakerを使用して、クエリテキストを埋め込みにエンコードします。

  6. 類似性検索: RDS for PostgreSQLデータベースでpgvectorを使用して類似性検索を実行します。

前提条件:

  • 適切なIAM権限を持つAWSアカウント。
  • SageMaker、RDS、CloudFormationなどのAWSサービスについての知識。

デプロイ: AWS CloudFormationスタックを使用してソリューションをデプロイし、ネットワーキングコンポーネント、SageMakerノートブックインスタンス、RDS for PostgreSQLインスタンスなど、すべて必要なリソースが作成されます。

以下は、ソリューションの実装に使用するいくつかの主なコードの断片です:

  • データの取り込み: Amazon Translateを使用して、ドイツ語から英語への商品の説明の翻訳を行います。

    import boto3
    translate = boto3.client(service_name='translate', use_ssl=True)
    result = translate.translate_text(Text=str(j), SourceLanguageCode="de", TargetLanguageCode="en")
  • モデルのホスティング: 事前にトレーニングされたHugging FaceモデルをSageMakerにデプロイします。

    from sagemaker.huggingface.model import HuggingFaceModel
    predictor = HuggingFaceModel(env=hub, role=role).deploy(initial_instance_count=1, instance_type="ml.m5.xlarge")
  • データの保存: RDS for PostgreSQLに埋め込みを保存するためのテーブルを作成します。

    CREATE TABLE IF NOT EXISTS products(
      id bigserial primary key,
      description text,
      descriptions_embeddings vector(384)
    );
  • 類似性検索: pgvectorを使用して類似性検索を実行します。

    SELECT id, url, description, descriptions_embeddings
    FROM products
    ORDER BY descriptions_embeddings <-> ARRAY[...];

PgVectorのPythonでの使用方法

もちろん、pgvectorの機能をPythonで拡張し、カスタムメソッドを追加したり、他のPythonライブラリと統合したりすることができます。以下は、Djangoで2つのベクトル間のユークリッド距離を計算するメソッドを含むpgvectorを拡張する方法の例です。

Djangoの機能拡張

まず、ユークリッド距離を計算するメソッドを含むItemモデルのカスタムマネージャを作成しましょう。

from django.db import models
from pgvector.django import VectorField, L2Distance
import math
 
class ItemManager(models.Manager):
    def euclidean_distance(self, vector):
        # pgvectorのL2Distance関数を使用してユークリッド距離の2乗を取得します
        queryset = self.annotate(distance_squared=L2Distance('embedding', vector))
        
        # 実際のユークリッド距離を取得するために平方根を取ります
        for item in queryset:
            item.distance = math.sqrt(item.distance_squared)
        
        return queryset
 
class Item(models.Model):
    embedding = VectorField(dimensions=3)
    objects = ItemManager()

これで、Djangoのビューまたはシェルでこのカスタムマネージャを使用できます:

# ベクトル[3, 1, 2]に対するユークリッド距離でソートされたアイテムを取得する
items = Item.objects.euclidean_distance([3, 1, 2]).order_by('distance')
 
# アイテムとその距離を表示する
for item in items:
    print(f"アイテムID: {item.id}、距離: {item.distance}")

SQLAlchemyの機能拡張

同様に、カスタムクエリクラスを追加することでSQLAlchemyの機能を拡張することもできます。

from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, BaseQuery
from sqlalchemy.sql import func
from pgvector.sqlalchemy import Vector
 
Base = declarative_base()
 
class VectorQuery(BaseQuery):
    def euclidean_distance(self, vector):
        return self.add_columns(
            func.sqrt(
                func.pow(Vector.l2_distance(self._entities[0].field, vector), 2)
            ).label('distance')
        )
 
class Item(Base):
    __tablename__ = 'items'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    embedding = Column(Vector(3))
    
    @classmethod
    def query(cls):
        return VectorQuery(cls)
 
# データベースのセットアップ
engine = create_engine('postgresql://localhost/mydatabase')
Base.metadata.create_all(engine)
 
Session = sessionmaker(bind=engine)
session = Session()
 
# ベクトル[3, 1, 2]に対するアイテムとそのユークリッド距離を取得する
items_with_distance = session.query(Item).euclidean_distance([3, 1, 2]).all()
 
# アイテムとその距離を表示する
for item, distance in items_with_distance:
    print(f"アイテムID: {item.id}、距離: {distance}")

この例では、Itemクラスに主キーとしてidフィールドを追加しました。また、VectorQueryクラスはクエリの機能を拡張するために使用され、ユークリッド距離を計算するためのメソッドを追加しています。最後に、queryクラスメソッドを使用してこのカスタムクエリクラスをItemモデルに設定しています。

その後、次のようにSQLAlchemyのコードで使用できます:

# ベクトル[3, 1, 2]に対するアイテムとそのユークリッド距離を取得する
items = session.query(Item).euclidean_distance([3, 1, 2]).all()
 
# アイテムとその距離を表示する
for item, distance in items:
    print(f"アイテムID: {item.id}、距離: {distance}")

結論

Pgvectorは、PostgreSQLデータベースを使用している場合には革新的な存在です。それは単なるアドオンではなく、データベースのターボチャージャーのようなものです。大量のデータを素早くかつ正確に保存し、検索することができます。これは、機械学習などの場合に特に便利です。大量のデータを迅速に処理する必要がある場合に重宝します。

さらに、pgvectorはPostgreSQLに完全に統合されているため、複数のデータベースを管理する必要はありません。また、データポイント間の「距離」をどのように測定するかを選択することができる柔軟性もあります。さらに、DjangoなどのPythonフレームワークを使用している場合、機能を拡張することもできます。要するに、データとPostgreSQLを使用しているのであれば、pgvectorを見逃すべきではありません。

FAQ

Pgvectorの使用目的は何ですか?

Pgvectorは、大量のベクトルを保存して検索することに特化したPostgreSQLデータベースの拡張機能です。機械学習モデル、推薦システム、自然言語処理のタスクなど、迅速かつ正確な類似性検索が必要なアプリケーションに特に役立ちます。

Pgvectorの利点は何ですか?

Pgvectorには以下の利点があります:

  1. 速度:高次元データでも高速なクエリが可能です。
  2. 効率性:データを圧縮しても完全性を保持し、ストレージスペースを節約します。
  3. 柔軟性:ユークリッド距離、コサイン類似度、マンハッタン距離など、複数の距離指標をサポートし、ニーズに応じて最適なものを選択できます。
  4. シームレスな統合:PostgreSQLに直接統合されており、複数のデータベースを管理する必要がありません。
  5. スケーラビリティ:さまざまなハードウェア構成で高パフォーマンスを発揮し、リソースを最適に利用します。

PostgreSQLはベクトルデータベースですか?

いいえ、PostgreSQL自体はベクトルデータベースではありません。ただし、Pgvector拡張を使用することで、高次元データの類似性検索を格納および実行できるパワフルなベクトルデータベースに変換できます。

PostgreSQLでPgvectorを使用する方法は?

PostgreSQLでPgvectorを使用するには、次の手順が必要です:

  1. PostgreSQLデータベースで CREATE EXTENSION pgvector; を実行して、Pgvector拡張をインストールします。
  2. ベクトルカラムを持つテーブルを作成します。たとえば: CREATE TABLE my_vectors (id SERIAL PRIMARY KEY, vector_field VECTOR(128));
  3. ベクトルをテーブルに挿入します。 INSERT INTO my_vectors (vector_field) VALUES ('{1.1, 2.2, 3.3, ..., 128.128}');
  4. SQLクエリを使用して類似性検索を実行します。例: SELECT * FROM my_vectors ORDER BY vector_field <-> '{3.3, 2.2, 1.1, ..., 128.128}' LIMIT 10;
Anakin AI - The Ultimate No-Code AI App Builder