「PostgreSQLとOpenAI埋め込みを使用した意味検索」

美とファッションの専門家のあなたに、美とファッションの分野の豊富な知識を持ち、しばしば鮮やかで生き生きとした記事を書くことが得意です

Igor Omilaev氏によるUnsplashの画像

企業データベース内でのセマンティックサーチの実装は困難で、かなりの努力が必要です。しかし、それはこのような方法である必要がありますか?この記事では、データに対してセマンティックサーチを実装するために、PostgreSQLとOpenAI Embeddingsをどのように利用できるかを実演します。OpenAI Embeddings APIを使用したくない場合、無料の埋め込みモデルへのリンクも提供します。

非常に高いレベルで、LLMを備えたベクトルデータベースは、使用可能なデータ(データベース、ドキュメントなどに保存されたデータ)に対してセマンティックサーチを行うことができます。「ベクトル空間の単語表現の効率的な推定」としても知られる「Word2Vec Paper」(伝説的なJeff Deanも共著)によって、単語を実数値ベクトルとして表現する方法を知っています。単語の埋め込みは、意味的に類似した意味を持つ単語が近くに配置される、ベクトル空間上での単語の密なベクトル表現です。単語埋め込みは単語間の意味的関係を捉え、それを作成するための複数の技術があります。

著者による画像

さあ、OpenAIのtext-embedding-adaモデルを使いましょう! 距離関数の選択は通常あまり重要ではありませんが、OpenAIではコサイン類似度を推奨しています。OpenAIの埋め込みを使用したくない場合やAPI呼び出しではなくローカルで異なるモデルを実行したい場合、SentenceTransformersの事前学習モデルの1つを検討することをお勧めします。モデルを賢く選びましょう。

import osimport openaifrom openai.embeddings_utils import cosine_similarityopenai.api_key = os.getenv("OPENAI_API_KEY")def get_embedding(text: str) -> list: response = openai.Embedding.create(     input=text,     model="text-embedding-ada-002" ) return response['data'][0]['embedding']good_ride = "good ride"good_ride_embedding = get_embedding(good_ride)print(good_ride_embedding)# [0.0010935445316135883, -0.01159335020929575, 0.014949149452149868, -0.029251709580421448, -0.022591838613152504, 0.006514389533549547, -0.014793967828154564, -0.048364896327257156, -0.006336577236652374, -0.027027441188693047, ...]len(good_ride_embedding)# 1536

埋め込みの理解ができたので、いくつかのレビューをソートするためにそれを利用しましょう。

good_ride_review_1 = "I really enjoyed the trip! The ride was incredibly smooth, the pick-up location was convenient, and the drop-off point was right in front of the coffee shop."good_ride_review_1_embedding = get_embedding(good_ride_review_1)cosine_similarity(good_ride_review_1_embedding, good_ride_embedding)# 0.8300454513797334good_ride_review_2 = "The drive was exceptionally comfortable. I felt secure throughout the journey and greatly appreciated the on-board entertainment, which allowed me to have some fun while the car was in motion."good_ride_review_2_embedding = get_embedding(good_ride_review_2)cosine_similarity(good_ride_review_2_embedding, good_ride_embedding)# 0.821774476808789bad_ride_review = "A sudden hard brake at the intersection really caught me off guard and stressed me out. I wasn't prepared for it. Additionally, I noticed some trash left in the cabin from a previous rider."bad_ride_review_embedding = get_embedding(bad_ride_review)cosine_similarity(bad_ride_review_embedding, good_ride_embedding)# 0.7950041130579355

絶対的な差は小さく見えるかもしれませんが、数千件のレビューを持つソート機能を考えてみてください。このような場合、私たちはトップにはポジティブなものだけを重視して表示することができます。

単語や文書が埋め込みに変換された後、データベースに保存することができます。ただし、この操作だけではデータベースをベクトルデータベースとは自動的に分類するわけではありません。ベクトルに対する高速な操作をサポートするようになって初めて、それをベクトルデータベースと呼ぶことができます。

商用やオープンソースのベクトルデータベースは数多くあり、これは非常に議論の多いトピックです。最も人気のあるデータベースのためのベクトル類似性検索機能を提供する、オープンソースのPostgreSQL拡張機能であるpgvectorを使用して、ベクトルデータベースの動作をデモンストレーションします。

以下のコマンドを使用して、PostgreSQLコンテナをpgvectorで実行しましょう:

docker pull ankane/pgvectordocker run --env "POSTGRES_PASSWORD=postgres" --name "postgres-with-pgvector" --publish 5432:5432 --detach  ankane/pgvector

次に、pgcliを起動してデータベースに接続し、テーブルを作成し、上記で計算した埋め込みを挿入し、類似アイテムを選択しましょう:

-- pgvector拡張機能を有効化CREATE EXTENSION vector;-- 1536次元のベクトルカラムを作成します。「text-embedding-ada-002」モデルは1536次元です。CREATE TABLE reviews (text TEXT, embedding vector(1536));-- 上記から3つのレビューを挿入します(入力は省略しました)。INSERT INTO reviews (text, embedding) VALUES ('I really enjoyed the trip! The ride was incredibly smooth, the pick-up location was convenient, and the drop-off point was right in front of the coffee shop.', '[-0.00533589581027627, -0.01026702206581831, 0.021472081542015076, -0.04132508486509323, ...');INSERT INTO reviews (text, embedding) VALUES ('The drive was exceptionally comfortable. I felt secure throughout the journey and greatly appreciated the on-board entertainment, which allowed me to have some fun while the car was in motion.', '[0.0001858668401837349, -0.004922827705740929, 0.012813017703592777, -0.041855424642562866, ...');INSERT INTO reviews (text, embedding) VALUES ('A sudden hard brake at the intersection really caught me off guard and stressed me out. I was not prepared for it. Additionally, I noticed some trash left in the cabin from a previous rider.', '[0.00191772251855582, -0.004589076619595289, 0.004269456025213003, -0.0225954819470644, ...');-- サニティチェックselect count(1) from reviews;-- +-------+-- | count |-- |-------|-- | 3     |-- +-------+

これで、似たドキュメントを検索する準備が整いました。「良い乗り物」の埋め込みを再度短縮しましたが、1536次元を出力するのは過剰です。

--- ここで使用する埋め込みは「良い乗り物」のものですSELECT substring(text, 0, 80) FROM reviews ORDER BY embedding <-> '[0.0010935445316135883, -0.01159335020929575, 0.014949149452149868, -0.029251709580421448, ...';-- +--------------------------------------------------------------------------+-- | substring                                                                |-- |--------------------------------------------------------------------------|-- | I really enjoyed the trip! The ride was incredibly smooth, the pick-u... |-- | The drive was exceptionally comfortable. I felt secure throughout the... |-- | A sudden hard brake at the intersection really caught me off guard an... |-- +--------------------------------------------------------------------------+SELECT 3Time: 0.024s

完了です!ご覧の通り、複数のドキュメントの埋め込みを計算し、データベースに保存し、ベクトル類似性検索を行いました。その応用範囲は非常に広いです。企業の検索から、似た症状を持つ患者を特定する医療記録システムの機能までさまざまです。さらに、この方法はテキストに限られません。音声、ビデオ、画像など他の種類のデータに対しても類似性を計算することができます。

お楽しみください!

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more