※ 本記事は、Andy Rivenesによる”Getting Started with Oracle Database 23ai AI Vector Search“を翻訳したものです。
2025年3月17日
Oracleは、2024年5月にOracle Database 23aiの提供開始を発表しました。300以上の新機能があり、学ぶべきことはたくさんあります。Dominic Gilesは、自身のブログ投稿でいくつかの重要な機能を紹介していますが、Oracle Database 23aiの最もエキサイティングな新機能の1つがOracle AI Vector Searchです。
AI Vector Searchのご紹介はこちらから入手できます。ここでは類似性検索をサポートするOracle Databaseの追加機能について詳しく説明し、主な利点や、AI Vector Searchが対処するユース・ケースについても述べています。
また、ベクトル埋め込みモデルを使用してベクトルを作成し、類似性検索を実行するために必要な手順を説明するブログやラボもいくつかあります。しかし、これらが一体何なのか、なぜ知っておく必要があるのかを説明する記事は多くありません。この投稿では、Oracle Database のAI Vector Searchで、これらの機能がどう役立つか、さらに説明し、例を紹介します。
AI Vector Searchの中心にあるのは、類似性検索を行う機能です。類似性検索は、値(単語やピクセル)ではなく、データの意味表現を用いて、類似オブジェクトをすばやく見つけます。たとえば、これに似た他のイメージやドキュメントを探したい、そのような時です。ベクトル(より正確にはベクトル埋込み)を使用して、「互いの近接性」に基づいて、意味的に類似したオブジェクトを検索します。つまり、ベクトル埋込みは、テキスト、イメージ、ビデオ、音楽など、ほぼすべての種類のデータを、それらのポイントへの位置と他のデータとの近接性が意味的に意味のある多次元空間内のポイントとして表す方法です。
従来、リレーショナル検索は属性値またはキーワードに基づいていました。AI Vector Searchでは、構造化データ、さらに重要なことに、非構造化データを用いて、データの意味に基づいて類似性を検索できます。これにより、まったく新しい可能性の世界が開かれ、だからこそ、この新機能をめぐる興奮は大きく広がっています。チャットボット、自然言語処理、データ分析、画像処理、地理分析などのユース・ケースでは、AI Vector Searchを新しくエキサイティングな方法で活用できます。
Oracle AI Vector Searchには、Oracle Database内でセマンティック検索または類似性検索を可能にする機能のコレクションが含まれています。これらの機能には次のモノが含まれます。
• ベクトル埋め込みを格納するための新しいVECTORデータ型
• 事前トレーニング済埋込みモデルのOracle Databaseへのインポート
• データベースに埋め込みをローカルで作成する、あるいは、外部で生成した埋め込みをロードする
• 類似性検索を高速化するための新しい最先端のベクトル索引
• ビジネス・データに対するリレーショナル検索とセマンティック検索を簡単に組み合せる新しいSQL演算子および構文
• Retrieval Augmented Generation(RAG)をサポートし、企業固有のコンテンツでLLM応答を拡張
これらの各機能の説明を繰り返すのではなく、この投稿の残りの部分と今後の投稿では、これらの機能の例と、これらの機能を利用して類似性検索を有効活用する方法について説明します。
はじめに
Oracle AI Vector Searchには、Oracle Database 23aiが必要です。現在、Oracle Cloud(Oracle Autonomous Databaseを含む)、Oracle Cloud@Customer、Oracle Exadata、Oracle Database Appliance、Oracle Database@Azure、Oracle Database@Google Cloud、Oracle Database@AWS、Oracle Database 23ai Freeでご利用いただけます。各プラットフォーム毎の最新情報については、現在のデータベース・リリースのMOSノート・リリース・スケジュール(ドキュメントID 742060.1)を参照してください。
サンプル・データ・セット
この投稿の次の例では、シカゴ・データ・ポータルで入手可能な犯罪事件データセットの一部を使用します。このデータセットは、両方のカテゴリ・フィールドと、類似性検索の実行方法、および類似性検索でリレーショナル検索を実行するための属性フィルタリングと組み合せる方法を強調するために使用するテキストの説明を組み合せます。ダウンロードしたデータには、複数年にわたる約680万行が含まれています。
データセットのサブセットを使用し、次の列をSEARCH_DATAという新しい表に格納します:
SQL> desc search_data Name Null? Type ----------------------------- -------- -------------------- ID NUMBER DESCRIPTION VARCHAR2(100) LOCATION_DESC VARCHAR2(100) DISTRICT VARCHAR2(20) WARD NUMBER COMMUNITY VARCHAR2(20) C_YEAR NUMBER
SEARCH_DATA表には、2004年の469,380行があります。前述のDESCRIPTION列には、次のような内容があります:
DESCRIPTION ------------------------------------------------------ TO PROPERTY POSS: CANNABIS 30GMS OR LESS AGGRAVATED: HANDGUN OTHER VEHICLE OFFENSE AUTOMOBILE
ベクトル埋め込みモデル
類似性検索を有効にするには、検索する列(この例ではDESCRIPTION列)のベクトル埋込みを作成する必要があります。ベクトル埋込みは、VECTORデータ型の列に格納されます。ベクトル埋込みは、データ・ポイントの数学的ベクトル表現、シンプルに言えば数値の配列です。ベクトル埋込みは、機械学習モデルを使用して生成されます。これが、AIが登場する初めての場所です。
使用する埋込みモデルをどのように決めるかは、結局のところ、オープンソースの埋め込みモデルと独自の埋め込みモデルがあり、有料の場合もあれば、独自の埋め込みモデルを作成してトレーニングすることもできます。少し混乱するのは、各埋込みモデルは特定のデータについてトレーニングされていることです。使用する埋込みモデルのタイプは、埋め込む予定のデータ・タイプと、自分またはアプリケーションで実行する必要がある検索に対して、そのモデルがどの程度パフォーマンスを発揮するかによって異なります。
試行する埋込みモデルを1つ以上選択したら、データベースの外部にベクトル埋込みを作成するか、モデルがOpen Neural Network Exchange (ONNX)標準と互換性がある場合は、モデルをOracle Databaseに直接インポートしてデータベース内にベクトル埋込みを作成するかを選択できます。Oracle DatabaseはONNXランタイムをデータベース内で直接実装するため、これらのインポートされたモデルを使用して、Oracle Databaseでベクトル埋込みを生成できます。
次の例では、テキストベースのデータを操作するため、センテンス・トランスフォーマ・モデルを使用します。これは、ディープラーニング用のオープンソースPythonライブラリをホストし、数千の事前トレーニング済みモデルを提供するサイトであるHugging Faceの事前トレーニング済みトランスフォーマーモデルを、OML4Pyと呼ばれるOracleユーティリティを使用してONNX形式に変換する方法を詳しく説明したブログ投稿です。次に、Oracle Databaseにモデルをロードする方法を詳しく説明します。
これらの別のブログ投稿では、ONNX形式に変換するために必要なプリ・ポスト処理でモデルを補強することなく、事前に構築されたベクトル埋め込みモデルをデータベースにロードする方法を詳細に説明しています。そして最後に、AI Vector Searchでテストされた埋め込みモデルの種類を詳しく説明した記事を紹介します。
この例では、簡単な段取りで、前述の事前構築済ベクトル埋込みモデルの使用に関するブログ投稿で詳細に説明されている、事前構築済のall-MiniLM-L12-v2モデルを使用します。コンパクトでありながらパワフルなセンテンス・トランス・モデルで、データ要件に対応できます。データベース・サーバー上のOSディレクトリに解凍され、そのOSディレクトリを指すDM_DUMPというデータベース・ディレクトリが作成されています。その後、次のコマンドを実行して、ONNXファイルをデータベースにインポートできます:
SQL> exec dbms_vector.load_onnx_model('DM_DUMP','all_MiniLM_L12_v2.onnx','minilm_l12_v2',
JSON('{"function" : "embedding", "embeddingOutput" : "embedding", "input": {"input": ["DATA"]}}'));
次のSQLを実行すると、モデル名”MINILM_L12_V2″がデータベースにロードされたことがわかります:
SQL> SELECT model_name, mining_function, algorithm, algorithm_type, model_size
FROM user_mining_models;
MODEL_NAME MINING_FUNCTION ALGORITHM ALGORITHM_TYPE MODEL_SIZE
-------------- ---------------- ---------- -------------- ----------
MINILM_L12_V2 EMBEDDING ONNX NATIVE 133322334
SQL>
モデルの特性を表示することもできます:
SQL> SELECT model_name, attribute_name, attribute_type, data_type, vector_info
FROM user_mining_model_attributes;
MODEL_NAME ATTRIBUTE_NAME ATTRIBUTE_TYPE DATA_TYPE VECTOR_INFO
-------------- ---------------- --------------- ----------- -------------------
MINILM_L12_V2 ORA$ONNXTARGET VECTOR VECTOR VECTOR(384,FLOAT32)
MINILM_L12_V2 INPUT TEXT VARCHAR2
SQL>
VECTOR_INFO列に注目してください。これは、モデルのディメンション形式を示します。ディメンション形式については、「ベクトル埋込みの作成」の項で詳しく説明します。
“hello”という単語の埋込みベクトルを確認する簡単なクエリーを実行して、これまでに実行した内容をテストできます:
SQL> SELECT TO_VECTOR(VECTOR_EMBEDDING(minilm_l12_v2 USING 'hello' as input)); TO_VECTOR(VECTOR_EMBEDDING(MINILM_L12_v2USING'HELLO'ASINPUT)) ------------------------------------------------------------------------------------------------------------------------------------------------------ [-7.49069825E-002,-1.44330608E-002,4.86499295E-002,-2.713810 28E-002,-4.30882089E-002,-1.47763401E-001,6.88331053E-002,-1 .37038985E-002,-5.35686724E-002,2.69752908E-002,-6.28339127E -003,-3.98834869E-002,7.65678426E-003,-3.78089696E-002,-1.17 558083E-002,-3.46409045E-002,1.29357144E-001,-2.52777878E-00 2,-1.52099226E-002,7.30356318E-004,-8.06888491E-002,2.693785 54E-002,-9.87356976E-002,-3.41076851E-002,-2.70294175E-002,- 7.32003674E-002,5.08588664E-002,-1.72562376E-002,7.28218481E < A bunch of numbers have been deleted > 41633E-002,5.40374406E-002,4.60668281E-003,4.81108278E-002,- 1.18950203E-001,-4.22098711E-002,4.28496249E-004,-4.60483041 E-003,-6.80256784E-002,2.4777215E-002,5.72777987E-002,3.3987 131E-002,-3.80932316E-002,5.46789682E-003,1.50439981E-002,-1 .71866838E-003,-4.49497951E-003,8.36174041E-002,3.61522138E- 002,-2.27608755E-002,1.0930731E-002,-4.64579314E-002,-2.5119 7945E-002,3.10342927E-002,1.40036559E-002,2.80776881E-002,-7 .75460666E-003,-3.13466154E-002,5.54159284E-002] SQL>
ベクトル埋込みの作成
これで、DESCRIPTION列のベクトル埋込みを作成する準備ができました。まず、ベクトル埋め込みを格納するためにテーブルに列を追加する必要があります。列のデータ型はVECTORになります。オプションで、ディメンションの数とそのフォーマットを指定できます。これらのいずれも指定しない場合は、異なるフォーマット・異なるディメンションのベクトルを格納できます。Oracle Databaseでベクトルの使用を開始する際、ベクトル埋込みモデルを後で変更し、異なる数のディメンションまたはフォーマット(あるいはその両方)を使用する場合に、この簡略化が役立ちます。ベクトル定義を再作成する必要がなくなります。
ディメンションの数は必ずゼロより大きく、非BINARYベクトルの場合は最大65535、BINARYベクトルの場合は65528です。
使用可能なディメンションのフォーマットは次のとおりです:
• INT8 (8ビット整数)
• FLOAT32 (32ビットIEEE浮動小数点数)
• FLOAT64 (64ビットIEEE浮動小数点数)
• BINARY (パックされたUINT8バイト(各ディメンションが単一ビットの場合))
既存の表にベクトル列を追加するには、ALTER TABLE文のみで済みます:
SQL> ALTER TABLE search_data ADD vector_desc VECTOR;
ディメンションの数とフォーマットが含まれていない場合は、describeコマンドで、VECTOR(*, *)の定義が表示されることにご注意ください。
SQL> desc search_data Name Null? Type ----------------------------- -------- -------------------- ID NUMBER DESCRIPTION VARCHAR2(100) LOCATION_DESC VARCHAR2(100) DISTRICT VARCHAR2(20) WARD NUMBER COMMUNITY VARCHAR2(20) C_YEAR NUMBER VECTOR_DESC VECTOR(*, *)
ベクトル埋込みを生成し、それらをベクトル・データ型列にロードするには、様々な方法があります。この例では、CREATE TABLE AS SELECTコマンドを実行することを選択しました。データベースにロードされた埋込みモデルを使用する場合に、最も簡単で高速な方法だと考えられます。
SQL> DROP TABLE search_data PURGE;
SQL> CREATE TABLE search_data AS
SELECT id, description, location_desc, district, ward, community, c_year,
vector_embedding(minilm_l12_v2 using DESCRIPTION as input) as vector_desc
FROM chicago_data WHERE c_year = 2004;
同じことを実施する方法は他にもたくさんあります。VECTOR列を追加した後に、表に対してUPDATE文を実行することもできますし、元の表の対応するID列を使用してデータを別の表にINSERTすることもできます。ベクトル埋込みをデータベースの外部で生成し、SQL Loaderを使ってデータをロードすることもできます。
類似性検索
大きな回り道をしたように見えるかもしれませんが、ベクトル埋め込みを作成したので、犯罪事件データに戻り、それをどのように活用できるかを探る準備が整いました。類似性検索を使う理由は、意味的に類似した用語に基づいてデータを検索する必要があるためです。最初の例では、強盗(robberies)の記述を見つけることができるかどうかを確認します。ただし、「DESCRIPTION」列には「robbery」という語は出てきません。
SQL> SELECT count(*) FROM search_data
2 WHERE UPPER(description) LIKE '%ROBBERY%';
COUNT(*)
----------
0
例えばデータをふるいにかけて意味的に似た単語を自分で整理しラベル付けすることで、SQL問合せに対応できるかもしれません。しかし、大規模なデータ・セットと、あまり使われない類似語も多数あったらどうでしょうか。次に、AI Vector Searchで類似性検索を実行するとどうなるかを見てみましょう。次に、SQLとその結果を示します:
select description, TO_NUMBER(vector_distance) as vector_distance
from (
select id, description,
vector_distance(vector_desc, VECTOR_EMBEDDING(minilm_l12_v2 USING 'ROBBERY' as data),
COSINE) as vector_distance
from search_data
order by 3
fetch exact first 50000 rows only )
group by description, vector_distance
order by 2
fetch first 10 rows only ;
DESCRIPTION VECTOR_DISTANCE
---------------------------------------- ---------------
RETAIL THEFT .299974263
ATTEMPT THEFT .336217165
KIDNAPPING .449222624
PREDATORY .450500667
OTHER CRIME INVOLVING PROPERTY .462044001
AGGRAVATED FINANCIAL IDENTITY THEFT .462046862
EXTORTION .466129601
FORGERY .481875181
ATTEMPT FINANCIAL IDENTITY THEFT .485770345
THEFT/RECOVERY: AUTOMOBILE .494581938
類似性検索のSQL構文は、慣れ親しんだものと少し異なる場合があります。ベクトルを操作し、他の類似したベクトルとの距離を確認するため、新しいVECTOR_DISTANCE関数を使用します。この例では、検索語「ROBBERY」をベクトル化し、そこからの距離をSEARCH_DATA表の他のベクトルと比較しています。ここではベクトル距離を表示し、それぞれの記述が検索ベクトルからどれくらい遠いかを確認できるようにしました。
また、VECTOR_DISTANCE関数はORDER BY句の一部として、VECTOR_DISTANCE計算を含むSELECTリストの列位置3として指定しています。これは、類似性検索では、データ・セット内の他のベクトルと問合せベクトルとの相対距離が検索されるので、最も近い最上位のベクトルを得るためです。
問合せ結果は有望に見えます。確かに、「盗難(theft)」という言葉を含む記述は、強盗(robberies)と見なされます。データセットをさらに確認したところ、犯罪事件の説明を実際に分類するPRIMARY_TYPEという別の属性があることがわかりました。実はこの発見にがっかりしました。ROBBERYのカテゴリと、THEFTおよびBURGLARYなどのPRIMARY_TYPEを問合せれば、様々な種類の強盗を確認できるのに、なぜAI Vector Searchを使用するのでしょうか? その後、これは本当に大きな利点であることに気付きました。なぜなら、類似性の検索がどれほど正確であるかを確認する方法となるからです。結局のところ、類似性検索の大きな利点の1つは、意味的に類似したデータを検索できることです。
PRIMARY_TYPE属性を追加した同じ問合せを次に示します(最初にPRIMARY_TYPE列を含んでいなかったので、表を再作成しました。属性とデータを追加する最も簡単な方法であるように思います):
select primary_type, description
from (
select primary_type, description,
vector_distance(vector_desc, VECTOR_EMBEDDING(minilm_l12_v2 USING 'ROBBERY' as data),
COSINE) as vector_distance
from search_data
order by 3
fetch exact first 50000 rows only )
group by primary_type, description, vector_distance
order by TO_NUMBER(vector_distance)
fetch first 10 rows only ;
PRIMARY_TYPE DESCRIPTION
-------------------- ----------------------------------------
THEFT RETAIL THEFT
THEFT ATTEMPT THEFT
KIDNAPPING KIDNAPPING
CRIM SEXUAL ASSAULT PREDATORY
OTHER OFFENSE OTHER CRIME INVOLVING PROPERTY
DECEPTIVE PRACTICE AGGRAVATED FINANCIAL IDENTITY THEFT
INTIMIDATION EXTORTION
DECEPTIVE PRACTICE FORGERY
THEFT ATTEMPT FINANCIAL IDENTITY THEFT
MOTOR VEHICLE THEFT THEFT/RECOVERY: AUTOMOBILE
PRIMARY_TYPE列とDESCRIPTION列データを確認することで、類似性検索がかなりうまくいったことが分かります。また、強盗や窃盗のキーワードで検索しても、ひったくりのような犯罪はヒットしないし、DECEPTIVE PRACTICE(不正行為)やおそらくMOTOR VEHICLE THEFT(自動車窃盗)のような他のカテゴリーの強盗も見逃しているかもしれません。この例では、類似性の検索によって利点が得られると思いますが、これは本当に氷山の一角にすぎません。データ、特にテキスト・データ以外のデータを検索する必要がある場合、類似点見つけるのはそれほど簡単ではないことを考えてみてください。
まとめ
この投稿では多くのことを取り上げましたが、今後の投稿でさらに詳しくお話しします。まず、AI Vector Searchの心臓部である類似性検索について紹介しました。次に、サンプル・データ・セット、ベクター埋込みモデルについて説明し、データベースにモデルをインポートしました。次に、そのモデルを使用してベクトル埋込みを作成し、VECTORデータ型列に格納しました。最後に、いくつかの類似性検索を実行し、テキストベースのデータの単純なキーワード検索とは対照的に、セマンティック比較の効力を確認しました。
