本番環境向けのベクトル検索の構築
本番環境のベクトル検索構築
ベクトルストアは、機械学習の進化において重要な役割を果たし、データの数値エンコーディングのための必須のリポジトリとして機能します。ベクトルは、多次元空間でカテゴリデータポイントを表すために使用される数学的なエンティティです。機械学習の文脈では、ベクトルストアはこれらのベクトルを格納、検索、フィルタリング、操作する手段を提供します。
ベクトルモデルはデータポイント間の類似性を見つけることに優れているため、大規模な言語モデルにとって欠かせないものであり、また、予測、類似性検索、コンテキスト検索の多くのユースケースの基盤となっています。
データ表現への迅速かつ構造化されたアクセスを可能にすることで、ベクトルストアは複雑なデータからの処理と学習を効率的に行うことができ、産業や技術を再構築し続ける先進的なAIアプリケーションの開発を支援します。
- 「Numexprの探索:Pandasの背後にある強力なエンジン」
- 「GPU インスタンスに裏打ちされた SageMaker マルチモデルエンドポイントを利用して、数百の NLP モデルをホストします」
- 「ABBYYインテリジェントオートメーションレポートによると、AIの予算は80%以上増加していることが明らかになりました」
Qwakベクトルストア
Qwakは、管理されたベクトルストアサービスのリリースを発表しました。Qwakベクトルストアは、ベクトルデータの変換と組み込みのためのスケーラブルなソリューションを提供し、メタデータとプロパティに対する高速なクエリエンジンを提供します。
Qwakベクトルストアは、Qwakプラットフォーム内にシームレスに組み込まれており、モデルをベクトルストアに接続してトレーニングと予測を行い、すべての機械学習インフラを一元管理することができます。
本番向けのベクトル検索の構築
このチュートリアルでは、Qwakベクトルストアの実装を進めます。Wikipediaの記事テキストを埋め込みに変換し、関連する記事に関連するメタデータとともに埋め込みデータをQwakベクトルストアに格納し、最後に、検索条件に類似したオブジェクトを取得するためにベクトルストアにクエリを発行します。
単語をベクトルに変換するモデルの作成
まず、Qwakプラットフォーム上で入力テキストを変換して埋め込むモデルを作成する必要があります。幸いなことに、これはすべてQwakプラットフォームで行うことができます。
このモデルでは、Hugging Faceのsentence transformerのall-MiniLM-L12-v2モデルを使用します。まず、qwak-sdkからQwakModelクラスをインポートし、ベースモデルを定義します。
build()関数とpredict()関数の2つの関数を定義する必要があります。モデルが事前学習されているため、build関数に渡し、self.modelをSentenceTransformerのインスタンスに設定するだけです。
predict関数では、モデルが入力データをどのように処理するかを定義します。
import qwak
from pandas import DataFrame
from qwak.model.base import QwakModel
from qwak.model.schema import ModelSchema, ExplicitFeature
from sentence_transformers import SentenceTransformer
from helpers import get_device
class SentenceEmbeddingsModel(QwakModel):
def __init__(self):
self.model_id = "sentence-transformers/all-MiniLM-L12-v2"
self.model = None
self.device = None
def build(self):
qwak.log_metric({"val_accuracy": 1})
def schema(self):
return ModelSchema(
inputs=[
ExplicitFeature(name="input", type=str),
]
)
def initialize_model(self):
self.device = get_device()
print(f"Inference using device: {self.device}")
self.model = SentenceTransformer(
model_name_or_path=self.model_id,
device=self.device,
)
@qwak.api()
def predict(self, df):
text_embeds = self.model.encode(
df["input"].values.tolist(),
convert_to_tensor=True,
normalize_embeddings=True,
device=self.device,
batch_size=128,
).tolist()
return DataFrame({"embeddings": text_embeds})
入力テキストをリストに変換して、SentenceTransformerのエンコーディングロジックで処理できるようにし、バッチサイズを定義し、いくつかの設定を追加します。
出力として、フィールドのoutputとベクトルのリストを持つDataFrameを返します。
リアルタイムエンドポイントとしてビルドして展開する必要がありますので、ベクトルストアのクエリ時に埋め込み関数を呼び出すことができます。
このモデルの例は、私たちのQwakの例のリポジトリで見つけることができます。
- リポジトリをローカルにクローンします。
- Qwak CLIがインストールおよび設定されていることを確認してください。
- sentence_transformers_poetryディレクトリに移動します。
- make buildを実行して、このモデルのトレーニングジョブを開始します。QwakのUIのModels -> Buildsタブに移動してビルドの進行状況を監視することもできます。
- モデルが正常にトレーニングされ、Qwakモデルリポジトリに保存されたので、make deployを実行してこのビルドバージョンをリアルタイムエンドポイントとして展開できます。QwakのUIのModels -> Deploymentsタブに移動してデプロイの手順を監視することもできます。
- デプロイが完了したら、プラットフォームの右上隅にあるTest Modelタブをクリックし、Qwakが使用する例の推論コールを生成します。これを使用してリアルタイムエンドポイントを呼び出し、予測をライブでテストできます!
ドキュメントでQwakのビルドとデプロイのプロセスについて詳しく読む
コレクションの作成
コレクションは、ベクトルストア全体のベクトルグループを構造化して管理するためのQwakの組織機能です。コレクションでは、ベクトルのグループ化およびインデックス化に対する細粒度な制御を提供するために、メトリック構成(コサイン、L2)およびベクトルの次元数を指定できます。
コレクションはUIで作成するか、qwak-sdkを使用してコードで定義することができます。このチュートリアルでは、以下に作成した例のコレクションをご覧いただけます。コサインメトリックを選択し、ベクトル平面で使用する384次元を選択します。また、ベクトル化器を選択する必要もあります。
ベクトル化器は、データを入力として受け取り、予測関数でベクトルを返すデプロイされたQwakモデルです。先ほど作成したモデルと同様です!
ここでは、Qwakプラットフォームで実行されているsentence-transformerモデルを選択し、Qwak Vector Storeは、ベクトルストアへの挿入または検索のために入力データの準備にこのモデルの埋め込み関数を自動的に使用します。これにより、QwakコレクションAPIに自由なテキストを送信できます。
モデルを展開し、コレクションを配置したので、ベクトルストアを使用する準備が整いました。
ベクトルストアにデータを挿入する
まず、データを適切にベクトルストアに挿入できるように準備してフォーマットする必要があります。
まず、プロジェクトの依存関係をインストールしましょう。
pip install pandas pyarrow numpy qwak-sdk
Wikipediaの記事とその内容を含む一連のソースparquetファイルがあります。また、ベクトルのプロパティとして使用するためのurl、記事のタイトル、およびテキストの長さのフィールドもあります。まず、pandasを使用してparquetファイルをDataframeに読み込み、テキストを含まない記事をフィルタリングします。
import pandas as pd
import numpy as np
import os
df = pd.read_parquet("short_articles.parquet")
df = df[df["text"].str.len() > 0].sample(frac=0.25)
df = df.reset_index()
次に、保存する各ベクトルに対して一意の識別子が必要なので、記事IDフィールドを選択します。また、ベクトルに含めるプロパティも選択します。幸い、これらのフィールドはかなり簡単なので、ほとんど変換する必要はありません。
## 各記事のIDを収集する
ids = df["article_id"].tolist()
## 各ベクトルに追加するプロパティを収集する
properties = df.apply(
lambda r:{
"url": r.url,
"title": r.title,
"title_len": r.title_len,
"text": r.text,
"text_len": r.text_len}
, axis=1
).tolist()
UIで作成したコレクションを取得する必要があります。Qwak VectorStoreClientを使用して、前の手順で作成したコレクションを見つけるか、create_collection()メソッドを使用して新しいコレクションを作成することができます。
from qwak.exceptions import QwakException
from qwak.vector_store import VectorStoreClient
## ベクトルクライアントを作成し、コレクションを取得する
client = VectorStoreClient()
# コレクションを取得するか新しいコレクションを作成する
collection_name = "wikipedia-vectorizer-demo"
try:
collection = client.get_collection_by_name(collection_name)
except QwakException:
collection = client.create_collection(
name=collection_name,
description="Wikipedia記事のインデックス化",
dimension=384,
metric="cosine",
vectorizer="sentence_transformer" # Qwakにデプロイされたリアルタイムモデルの名前
)
適切な形式でIDとメタデータを準備したので、Dataframeから記事テキストフィールドを選択します。これはベクトルストアに埋め込む列です。前の手順で取得したコレクションクライアントのupsert()メソッドを使用します。記事テキスト用の「natural_inputs」パラメータを使用して、upsertコマンドはリアルタイムモデルを呼び出し、予測関数を使用して記事テキストをベクトルとして返し、ベクトルをデータベースに保存します。
collection.upsert(
## 記事IDのリスト
ids=ids,
# ナチュラルインプット
natural_inputs=df['text'].tolist(),
## 記事プロパティのリスト(辞書)
properties=properties
)
ベクトルストアをクエリし、結果を確認する
ベクトルストアが作成されたので、使用してみましょう!
ベクトルストアをクエリして、アヒルに関連するコンテンツが含まれているかどうかを確認しましょう。upsertステップで作成したVectorStoreClientを使用できます。
クエリ「アヒル」を取り、それをクライアントのsearch()メソッドに渡します。バックエンドでは、ベクトルクライアントはsentence-transformerモデルを呼び出して検索クエリをベクトル化し、ベクトルストアで正しく使用できるようにします。返される結果の数と返されるベクトルプロパティを指定することもできます。また、返された結果と入力の距離を返すこともできます。これにより、クエリのパフォーマンスやベクトルのインデックスの品質を評価することができます。
from qwak.vector_store import VectorStoreClient
## モデルが提供するベクトルを使用してベクトルストアを検索する
search_results = collection.search(
natural_input="アヒル",
top_results=2,
output_properties=["title", "title_len", "url"],
include_distance=True,
include_vector=False
)
クライアントに対して、3つの最も近い記事のタイトル、タイトルの文字数、URLを返すように指定し、以下は結果です!
[print(x.properties, x.distance) for x in search_results]
# 検索結果のオブジェクト
{'title': 'Anaheim Ducks', 'title_len': 13.0, 'url': 'https://simple.wikipedia.org/wiki/Anaheim%20Ducks'} 0.38589573
{'title': 'Duck', 'title_len': 4.0, 'url': 'https://simple.wikipedia.org/wiki/Duck'} 0.4547128
クエリは、NHLのホッケーチームであるアナハイムダックスやアヒルの鳴き声「クワック」に関連する記事を返しました。最良の検索結果ではありませんが、数千の記事ベクトルだけでこの結果は受け入れられます!コレクションのメトリック機能を使用して、さまざまな距離計算を試してパフォーマンスにどのように影響するかを測定することをお勧めします。
ベクトルクエリの事前フィルタリングのサポート
Qwakは、検索クエリの最適化に向けたベクトルの事前フィルタリングを提供しています。これにより、クエリが高速かつ軽量になります。
事前フィルタリングは、ベクトル検索を開始する前に候補者を特定するアプローチを表します。その後、ベクトル検索では「allow」リストに存在する候補のみを対象とします。
プリフィルタクエリの主な利点は次のとおりです:
- 結果数の予測:フィルタをすでに減少した候補リストに適用することで、検索結果の要素数を簡単に推定することができます。
- 即座の一致検出:フィルタが非常に制限的であり、つまりデータセットのサイズに対してデータポイントの一部のみに一致する場合、元のベクトル検索に一致がないことがすぐにわかります。
from qwak.vector_store import VectorStoreClient
from qwak.vector_store.filters import Or, GreaterThan, Equal
## モデルで提供されるベクトルを使用してベクトルストアを検索する
search_results = collection.search(
natural_input="アヒル",
top_results=2,
output_properties=["title", "title_len", "url"],
filter=Or(
GreaterThan(property="text_len", value=110.0),
Equal(property="title_len", value=16.0)
)
)
プリフィルタベクトルクエリについての詳細は、当社のドキュメントをご覧ください。
概要
Qwak Vector Storeは現在利用可能であり、Qwak UIのコレクションタブに移動して新しいコレクションを作成することで、今日から利用を開始できます。 Qwak Vector Storeのすべての機能について詳しくは、当社のドキュメントをご覧いただくか、Qwakチームのメンバーにお問い合わせください。
元の記事はこちらに掲載されています。 許可を得て再掲載されました。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles