Oracle AI Vector Search User's Guide
3 Getting Started
SQL Quick Start Using a FLOAT32 Vector Generator
3 Getting Started
SQL Quick Start Using a FLOAT32 Vector Generator
ドキュメントではコマンドを実行して動作を確認する手順になっています。Getting Startedがコマンドラインの操作というのも敷居が高いように感じたので、SQL Quick Start Using a FLOAT32 Vector Generatorに記載されている作業を実行できるAPEXアプリケーションを作ってみました。
注意:
ドキュメントに「Do not use the vector generator on production databases. The program is made available for testing and demo purposes.」記載されているように、Getting Startedの作業を本番データベースで実施しないでください。作成したAPEXアプリケーションは以下のように動作します。チャート表示にPlotlyのJavaScriptライブラリ(scatter3dチャート)を使用しています。
実行計画を表示するために、APEXのワークスペース・スキーマに以下の権限を割り当てています。
grant select_catalog_role to <APEXワークスペース・スキーマ>;
grant select on sys.v_$sql to <APEXワークスペース・スキーマ>;grant select on sys.v_$session to <APEXワークスペース・スキーマ>;
grant select on sys.v_$sql_plan to <APEXワークスペース・スキーマ>;
Plotlyのscatter3dチャートに検索結果を表示するため、ベクトルの次元数は3以上である必要があります。次元数は3より大きい値にできますが、チャートは最初の3次元だけを表示に使います。
記述したコードのほとんどは、データベースからPlotly向けにデータを取得するためのコードなので、Oracle DatabaseのVector Searchのサンプルというよりは、PlotlyのチャートをOracle APEXのアプリケーションに組み込んで使うサンプルになっています。
作成したAPEXアプリケーションのエクスポートを以下に置いています。
https://github.com/ujnak/apexapps/blob/master/exports/vector-search-genvec-plotly.zip
以下よりAPEXアプリケーションの実装と使用しているAPEXの機能について、大まかに説明します。
Oracle APEXのアプリケーションには、サポートするオブジェクトという項目があります。
サポートするオブジェクトでは、APEXアプリケーションのインストール、アップグレードおよび削除時の処理を定義できます。
ほとんどの場合、インストールではAPEXアプリケーションが必要としている表、ビューおよびパッケージの作成を行います。削除では、それらのデータベース・オブジェクトの削除を行います。
本記事のアプリケーションのインストール・スクリプトでは、表GENVECの作成とパッケージVECTOR_GEN_PKGの作成を行なっています。
削除スクリプトでは、パッケージVECTOR_GEN_PKGの削除と表GENVECの削除を行なっています。
APEXアプリケーションをインストールして実行します。
ナビゲーション・メニューには、ホーム、Index、Table、Configurationsの4つのメニューが含まれます。記事の先頭にあるGIF動画は、ホーム・ページでの作業になります。
Configurationsのページでは、上から近似近傍検索(ANN検索)に使用するSELECT文、完全一致検索に使用するSELECT文、検索条件が与えられていない場合に使用するSELECT文、HNSW索引を作成するDDL、IVF索引を作成するDDLの5つのスクリプトが登録されてます。概ねGetting Startedに記載されているSELECT文やCREATE INDEX文がデフォルトになっています。
索引名はHNSW、IVFともにGENVEC_VECTOR_IDXとしています。また、SELECT文にコメントとして/* my_vector_query */を含めることにより、実行計画を取り出しやすくしています。検索条件の第1引数としてベクトル値、第2引数として検索する件数が与えられます。
SELECT文やDDLを変更することで、例えば距離をEUCLIDEANからCOSINEに変更したり、索引の精度を変更したりできます。
これらのSELECT文やDDLを、共有コンポーネントのアプリケーション・アイテムに保存しています。
それぞれのアプリケーション・アイテムにアプリケーションの計算を作成し、デフォルト値を設定しています。計算ポイントに新規インスタンス(新規セッション)開始時を選択し、計算タイプに静的値、計算にデフォルトのスクリプトを記述しています。
結果として、セッション開始時にアプリケーションの計算に設定したスクリプトがアプリケーション・アイテムに設定されます。
アプリケーション・アイテムはページに直接配置できません。そのため、アプリケーション・アイテムをソースとしたページ・アイテムを作成しています。
ボタンSUBMITをクリックしたときに以下のコードを実行することにより、ページ・アイテムに記述したスクリプトをアプリケーション・アイテムに転記しています。
begin
apex_session_state.set_value('SELECT_EXACT', :P4_SELECT_EXACT);
apex_session_state.set_value('SELECT_APPROX', :P4_SELECT_APPROX);
apex_session_state.set_value('SELECT_DEFAULT', :P4_SELECT_DEFAULT);
apex_session_state.set_value('CREATE_INDEX_IVF', :P4_CREATE_INDEX_IVF);
apex_session_state.set_value('CREATE_INDEX_HNSW', :P4_CREATE_INDEX_HNSW);
end;
Tableのページでは、表GENVECへのデータの生成とトランケートを行います。データの生成にはVECTOR_GEN_PKG.GENERATE_VECTORSを呼び出します。ページ・アイテムはそれぞれ、VECTOR_GEN_PKG.GENERATE_VECTORSの引数に対応しています。
Oracle APEXではプロセス・タイプとしてAPIの呼出しを選択することにより、コードを記述せずにプロシージャおよびファンションを呼び出すことができます。
Truncate文のようなDDLは、EXECUTE IMMEDIATE文で実行します。こちらは若干ですが、コーディングが必要です。
begin
execute immediate 'truncate table genvec';
exception
when others then
null;
end;
Indexのページでは、HNSWとIVFの索引の作成および削除を行います。索引GENVEC_VECTOR_IDXが作成済みの場合は、V$VECTOR_INDEXの内容を表示します。
ドキュメントのGetting StartedではVECSYS.VECTOR$INDEXを検索していますが、この表はAutonomous Databaseには存在しないため、V$VECTOR_INDEXに置き換えています。
画面上のボタンとしてDrop Index、Create Hnsw Idx、Create Ivf Idxの3つがあります。
このボタンをクリックしたときに実行されるプロセスとして、以下の4つが作成されています。
- Drop Index
- Create Hnsw Index
- create Ivf Index
- Gather Table Stats
この内、Drop IndexおよびGather Tables Statsには、サーバー側の条件が無く、どのボタンを押しても実行されます。
ボタンCreate Ivf Idxがクリックされたは、プロセスCreate Ivf Indexが実行されます。この時、アプリケーション・アイテムCREATE_INDEX_IVFに設定されているコマンドが実行されます。
このようにサーバー側の条件を設定して、単一の処理を組み合わせた簡単な処理フローを定義することができます。これとは逆に、以下のようにプロセス中のコードで処理フローを記述することもできます。
declare
C_DROP_INDEX constant varchar2(400) := q'~DROP INDEX if exists genvec_vector_idx~';
begin
/* 索引のドロップ */
execute immediate C_DROP_INDEX;
/* 索引の作成 */
if :REQUEST = 'CREATE_HNSW_IDX' then
execute immediate :CREATE_INDEX_HNSW;
elsif :REQUEST = 'CREATE_IVF_IDX' then
execute immediate :CREATE_INDEX_IVF;
end if;
/* 統計情報の収集 */
DBMS_STATS.GATHER_TABLE_STATS(
ownname => null,
tabname => 'GENVEC',
estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
cascade => TRUE
);
end;
ホーム・ページには3つのボタン、Search、Approx SearchおよびResetがあります。ボタンResetはページ・アイテムに設定された値を空白にします。そのため、実質的な処理を行うボタンは、完全一致検索を行うSearch、近傍近似検索を行うApprox Searchになります。
ページ・プロパティのJavaScriptのファイルURLに以下を記述し、Plotlyのライブラリを読み込みます。
https://cdn.plot.ly/plotly-3.0.1.min.js
ファンクションおよびグローバル変数の宣言にて、scatter3dチャートのレイアウトをlayoutとして設定します。rangeにnullを設定していますが、rangeは検索結果に基づいて設定されます。
ボタンSearch、Approx Searchの双方とも、ボタンクリック時の動的アクションで以下のJavaScriptコードを実行します。
x01にthis.triggeringElement.idを与えることで、ボタンの違いを認識します。ボタン名をIDとして参照させるため、ボタンに静的IDを設定しています。Oracle APEXではHTML要素のIDにランダムな文字列を割り当てます。そのため、要素をID指定で参照する場合は、明示的に静的IDを設定する必要があります。
ベクトル検索の実行および呼び出し元に返すデータを生成するプロセスGET_DATAのコードは以下になります。
実行計画は動的コンテンツとして表示しています。ソースのCLOBを返すPL/SQLファンクション本体に以下を記述しています。
対話モード・レポートによる検索されたベクトルの一覧は、プロセスGET_DATA内で保存したベクトルの名前を元にしています。
ソースのSQL問合せは以下になります。
select * from genvec where name in (select column_value from apex_string.split(:P1_ALL_VECTORS,','))
今回の記事は以上になります。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完