Oracle Database 23aiの新機能「AI Vector Search」で、テキストをベクトルデータに変換して検索してみた

5/2に発表およびリリースされた、Oracle Databaseの最新バージョン「23c」改め「23ai」

自らaiと呼称する通り、AIにフォーカスを当てた新機能であるベクトル検索機能「AI Vector Search」が導入されています

その新機能である「AI Vector Search」を実際に導入し、ベクトル変換およびベクトル検索を試してみましたのでご紹介します

AI Vector Searchとは

AI Vector Searchは、非構造化データをベクトルと呼ばれる数値の並びに変換し、意味や文脈の類似性に基づいて検索する技術です。

例えば、以下の2つの文章があるとします。

私は犬が好きです。犬は忠実で愛らしい動物です。
猫は独立心が強く、気まぐれな性格の動物です。

これらの文章をベクトル化すると、以下のようになります。

(0.8, 0.2, 0.1, ...)
(-0.1, 0.6, 0.3, ...)

各数値は、文章の特徴を表現しています。例えば、最初の値が犬に関連する特徴、2番目の値が猫に関連する特徴を表しているとします。

ベクトル化された文章同士の類似性を計算することで、意味や文脈が近い文章を見つけ出すことができます。

例えば、「犬について教えて」という問い合わせに対してベクトル検索では1番目の文章を高い関連性を持つ結果として返します。

このように、AI Vector Searchはデータの意味や文脈を数値化し、類似性を計算することで、従来のキーワード検索よりも正確で関連性の高い検索結果を提供できる機能となっています。

どんな想定で検証を行ったのか

携帯電話キャリアのカスタマーサポートセンターに寄せられた過去のお問い合わせをベクトル化し、新しいお問い合わせが来た際に類似する過去事例を出力する、いわゆるナレッジ検索の検証を行いました。

(利用したデータはChatGPTで生成したもので、実際のデータではありません)

検証環境の準備

今回の検証では、DB内で変換から検索までを完結させたかったため、外部APIは利用せず、DBに直接モデルをインポートしてベクトル化を行う手順を採用しています。

VM準備

VMについて詳細な導入手順は触れませんが、今回はVirtualBoxのVMを2つ用意しています。

・1つはOracle 23aiのDB VM

・1つはoml4pyクライアントをインストールし、モデルをONNXファイルに変換するためのOracle Linux VM

後者は必須ではありませんが、実際の本番運用も鑑みて、DBMSのリソースを無駄に消費したり、必要以上のソフトウェアを入れないようにするために用意してみました。

Oracle Database 23aiのVM

https://www.oracle.com/jp/database/free/get-started/

Oracle_Database_23c_Free_Developer_Appliance.ova

上記のサイトから23ai freeのovaファイルをダウンロードし、VirtualBoxへインポートします。

(VirtualBoxマネージャーの[仮想アプライアンスのインポート]メニューから.ovaファイルを選択すればインポート可能です)

Oracle Machine Learning for Python(oml4py)クライアントインストール用のVM

https://public-yum.oracle.com/oracle-linux-isos.html

上記から任意のバージョンのOracle LinuxのISOファイルをダウンロードして環境を用意してください。 (自分はOracle Linux 9.3を利用)

ONNXファイルへのエクスポート時にメモリ不足に陥ったケースがあったため、メモリは8GB以上で作成することをお勧めします。

oml4pyクライアントのインストール

事前学習済みモデルをDBへインポートするためには、oml4pyでエクスポートした ONNXファイルが必要となるため、oml4pyクライアントインストール用のVM へoml4pyをインストールしていきます。

python3.12.0のインストール

cd /tmp
wget https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tgz
mkdir -p ~/python
tar -xvzf Python-3.12.0.tgz --strip-components=1 -C ~/python

必要なライブラリのインストール

sudo yum install perl-Env libffi-devel openssl openssl-devel tk-devel xz-devel zlib-devel bzip2-devel readline-devel libuuid-devel ncurses-devel

(自分の環境では以下のライブラリも追加インストールが必要でした)

sudo yum install gcc perl-File-Copy

python3.12.0のビルド

cd ~/python
./configure --enable-shared --prefix=~/python

make clean; make
make altinstall

PYTHONHOME環境変数をbashrcへ追記

cat << EOF >> ~/.bashrc
export PYTHONHOME=~/python
export PATH=$PYTHONHOME/bin:$PATH
export LD_LIBRARY_PATH=$PYTHONHOME/lib:$LD_LIBRARY_PATH
EOF

bashrcのリロード

source ~/.bashrc

シンボリックリンク作成

cd ~/python/bin
ln -s python3.12 python3
python3 -V

pipのバージョンアップ

pip3.12 install —upgrade pip

必要なサポートパッケージのインストール

pip3.12 install pandas
pip3.12 install setuptools
pip3.12 install scipy
pip3.12 install matplotlib
pip3.12 install oracledb
pip3.12 install joblib
pip3.12 install scikit-learn
pip3.12 install numpy
pip3.12 install onnxruntime
pip3.12 install onnxruntime-extensions
pip3.12 install onnx
pip3.12 install --extra-index-url "https://download.pytorch.org/whl/cpu" torch==2.2.0+cpu
pip3.12 install transformers
pip3.12 install sentencepiece

https://www.oracle.com/database/technologies/oml4py-downloads.html

から OML4Py 2.0 (Database 23ai) のClientをダウンロードし、以下で作成した~/oml4pyへコピーします。

mkdir ~/oml4py
cd ~/oml4py

oml4pyを解凍し、インストール

unzip oml4py-client-linux-x86_64-2.0.zip
perl -Iclient client/client.pl

oml4pyのインストールはこれで完了です。

事前学習済みモデルをONNXファイル形式でエクスポート

python3のインタラクティブシェルで事前学習済みモデルからONNXファイルの生成を行います。

今回は事前構成モデルの「sentence-transformers/all-MiniLM-L6-v2」(以下「MINILM」とする)と、

Google BERTの多言語モデル「google-bert/bert-base-multilingual-cased」(以下「BERT」とする)のエクスポートを行います。

作業ディレクトリ作成、移動

mkdir ~/onnx
cd ~/onnx

python3の起動

python3

MINILM からONNXファイルを生成

from oml.utils import EmbeddingModel, EmbeddingModelConfig
config = EmbeddingModelConfig.from_template("text",max_seq_length=512,quantize_model=True)
em = EmbeddingModel(model_name="sentence-transformers/all-MiniLM-L6-v2", config=config)
em.export2file("all-MiniLM-L6-v2",output_dir=".")

BERTからONNXファイルを作成

from oml.utils import EmbeddingModel, EmbeddingModelConfig
config = EmbeddingModelConfig.from_template("text",max_seq_length=512,quantize_model=True)
em = EmbeddingModel(model_name="google-bert/bert-base-multilingual-cased", config=config)
em.export2file("bert-base-multilingual-cased",output_dir=".")

「all-MiniLM-L6-v2.onnx」と「bert-base-multilingual-cased.onnx」というファイルがカレントディレクトリへ出力されます。

データベースへONNXファイルをインポート

ここからはDB VMで作業を実施します。

onnxファイル配置先兼ディレクトリオブジェクト用ディレクトリ作成

mkdir /home/oracle/onnx

上記のディレクトリへ「all-MiniLM-L6-v2.onnx」と「bert-base-multilingual-cased.onnx」のONNXファイルを配置します。

作業対象のPDBへ接続 (Oracle_Database_23c_Free_Developer_Applianceのデフォルトの設定を利用しています。)

sql system/oracle@localhost:1521/freepdb1

ONNXファイルを配置したディレクトリをインポート用のディレクトリオブジェクトへ設定

CREATE DIRECTORY DM_DUMP as '/home/oracle/onnx';

検証用のDBユーザ「DMUSER」を作成し、必要となる権限を付与

CREATE USER dmuser identified by "oracle" DEFAULT TABLESPACE USERS quota unlimited on USERS;
GRANT DB_DEVELOPER_ROLE to dmuser;
grant create mining model to dmuser;
grant read on directory DM_DUMP to dmuser;
grant write on directory DM_DUMP to dmuser;

作成したユーザで接続しなおし、ONNXファイルのインポートを行う

CONN dmuser/oracle@freepdb1

BERTのインポート

EXECUTE DBMS_VECTOR.LOAD_ONNX_MODEL( 'DM_DUMP', 'bert-base-multilingual-cased.onnx', 'model_bert', JSON('{"function" : "embedding", "embeddingOutput" : "embedding", "input": {"input": ["DATA"]}}'));

MINILMのインポート

EXECUTE DBMS_VECTOR.LOAD_ONNX_MODEL( 'DM_DUMP', 'all-MiniLM-L6-v2.onnx', 'model_minilm', JSON('{"function" : "embedding", "embeddingOutput" : "embedding", "input": {"input": ["DATA"]}}'));

ベクトルデータの生成検証

select et.* from dbms_vector.utl_to_embeddings('こんにちは', json('{"provider": "database", "model": "MODEL_BERT"}')) et;

select et.* from dbms_vector.utl_to_embeddings('こんにちは', json('{"provider": "database", "model": "MODEL_MINILM"}')) et;

結果

SQL> select et.* from dbms_vector.utl_to_embeddings('こんにちは', json('{"provider": "database", "model": "MODEL_BERT"}')) et;

COLUMN_VALUE
_________________________________________________________________________________________________________________________________________________________
{"embed_id":1,"embed_data":"こんにちは","embed_vector":"[-4.45263125E-002,-4.56667505E-002,1.81700056E-003,2.82725599E-002,5.13250567E-002,-1.96262635E-002

経過時間: 00:00:10.830
SQL>
SQL> select et.* from dbms_vector.utl_to_embeddings('こんにちは', json('{"provider": "database", "model": "MODEL_MINILM"}')) et;

COLUMN_VALUE
_________________________________________________________________________________________________________________________________________________________
{"embed_id":1,"embed_data":"こんにちは","embed_vector":"[-6.53214231E-002,1.00896575E-001,-4.13914323E-002,5.09274229E-002,-8.02713782E-002,7.31066391E-002

経過時間: 00:00:00.961
SQL>

テストデータ作成

お問い合わせ履歴格納用のテーブルを作成し、ChatGPTで生成したお問い合わせデータを100件インサートしていきます。

テーブル名:inquiry_history

ID:連番
DETAIL:お問い合わせ内容
MINI_VECTOR:all-MiniLMで生成したベクトル値
BERT_VECTOR:BERTで生成したベクトル値

テーブル作成

create table inquiry_history ( id number, detail varchar2(4000), mini_vector vector, bert_vector vector );

「料金」「通信速度」「データプラン」「SIMカード」「国際ローミング」「契約解除」「通話品質」「支払い方法」「故障」「ポイントプログラム」のカテゴリごとに10件ずつ生成したデータを挿入しました。

すべては書ききれないのでそれぞれ1行ずつ抜粋しています。

-- 料金に関する問い合わせ
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (1, '件名: 請求書の料金について\n内容: 今月の請求書に記載されている料金がいつもより高いです。詳細な内訳を教えてください。また、不明な料金が含まれているようなので確認していただけますか?\n回答: お問い合わせありがとうございます。請求書の内訳については、以下のリンクから詳細をご確認いただけます。不明な料金に関しては、当社のシステムに誤りがないか確認いたしますので、しばらくお待ちください。お手数ですが、再度お問い合わせいただけますか?');

-- 通信速度の問題
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (11, '件名: インターネットの速度が遅い\n内容: 最近、インターネットの速度が非常に遅くなっています。特に夜間は動画がスムーズに再生できません。対策を教えてください。\n回答: ご不便をおかけして申し訳ございません。通信速度の低下はネットワークの混雑や周辺環境の影響が考えられます。対策として、ルーターの再起動や周辺機器の配置変更をお試しください。改善しない場合は、詳細な調査を行いますので、再度ご連絡ください。');

-- データプランの変更
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (21, '件名: データプランの変更について\n内容: 現在のデータプランを変更したいのですが、どのように手続きすれば良いでしょうか?また、新しいプランの詳細と料金を教えてください。\n回答: データプランの変更についてのお問い合わせありがとうございます。新しいプランの詳細と料金は当社のウェブサイトでご確認いただけます。変更手続きは、オンラインまたはお近くの店舗で行うことができます。ご不明点がございましたら、お気軽にお問い合わせください。');

-- SIMカードのトラブル
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (31, '件名: SIMカードが認識されない\n内容: 新しく購入したスマートフォンにSIMカードを挿入しましたが、認識されません。どうすれば解決できますか?また、SIMカードの再発行は可能ですか?\n回答: SIMカードが認識されない問題についてお知らせいただき、ありがとうございます。まず、SIMカードを他の端末で試していただき、それでも問題が解決しない場合は、SIMカードの再発行をお手配いたします。再発行手続きについては、お近くの店舗にご来店いただくか、オンラインでお申し込みください。');

-- 国際ローミングの設定
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (41, '件名: 国際ローミングの設定方法\n内容: 来週海外に行く予定があるのですが、国際ローミングの設定方法を教えてください。現地での使用に際して追加料金が発生するかも知りたいです。\n回答: 国際ローミングの設定方法についてご案内いたします。設定は、お使いの端末の設定メニューから「モバイルネットワーク」→「国際ローミング」を有効にしてください。詳細な設定手順は当社のウェブサイトに掲載されています。現地での使用に際しては、使用量に応じて追加料金が発生する場合がありますので、料金プランをご確認ください。');

-- 契約解除の手続き
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (51, '件名: 契約解除について\n内容: 契約を解除したいのですが、どのような手続きが必要ですか?また、違約金や手数料についても教えてください。\n回答: 契約解除のお手続きについてご案内いたします。契約解除は、お近くの店舗で行うか、オンラインで申請できます。解除に際しての違約金や手数料は、契約内容によって異なりますので、詳細は契約書をご確認いただくか、当社カスタマーサポートにお問い合わせください。');

-- 通話品質の問題
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (61, '件名: 通話中にノイズが多い\n内容: 通話中にノイズが多くて相手の声が聞き取りにくいことが頻繁にあります。この問題を解決するためにはどうすれば良いでしょうか?\n回答: 通話中のノイズについてご不便をおかけし、申し訳ございません。まず、通話中の環境を確認し、他の電子機器が影響していないか確認してください。また、端末の再起動をお試しください。改善しない場合は、ネットワークの状況を確認いたしますので、再度ご連絡ください。');

-- 支払い方法の変更
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (71, '件名: 支払い方法を変更したい\n内容: 現在、銀行振込で支払っていますが、クレジットカード払いに変更したいです。変更方法を教えてください。\n回答: 支払い方法の変更についてのお問い合わせありがとうございます。クレジットカード払いへの変更は、当社のウェブサイトまたはお近くの店舗で行うことができます。オンラインでの手続きは、ログイン後に「支払い方法の変更」メニューから行ってください。');

-- 携帯電話の故障
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (81, '件名: 携帯電話が動かなくなった\n内容: 使用している携帯電話が突然動かなくなりました。電源が入らず、充電もできません。修理や交換の手続きを教えてください。\n回答: 携帯電話の故障についてご連絡いただき、ありがとうございます。まず、充電器やケーブルを確認し、他の充電器で試してみてください。それでも解決しない場合は、修理または交換の手続きをお手配いたします。最寄りの店舗にご持参いただくか、オンラインで修理依頼をしてください。');

-- ポイントプログラムの利用
INSERT INTO INQUIRY_HISTORY (ID, DETAIL) VALUES (91, '件名: ポイントの利用方法について\n内容: 貯まったポイントを使いたいのですが、どのように利用すれば良いでしょうか?また、ポイントの有効期限も教えてください。\n回答: ポイントのご利用方法についてご案内いたします。ポイントは、当社のウェブサイトまたは店舗での購入時に使用できます。詳細な使用方法は、会員ページにログインしてご確認ください。ポイントの有効期限は、最終利用日から1年間ですので、お早めにご利用ください。');

commit;

テストデータのベクトル変換

お問い合わせ内容(detail列)からベクトルデータを生成してそれぞれの列に格納していきます。

mini_vector列にMINILMで生成したベクトル値を挿入

update (
  select t.id, t.detail, t.mini_vector, j.embed_vector
  from (
    select *
    from inquiry_history i,
         dbms_vector.utl_to_embeddings( i.detail, json('{ "provider": "database", "model": "MODEL_MINILM" }') )
    ) t ,
    JSON_TABLE(
      t.column_value,
      '$[*]' COLUMNS (
        embed_id NUMBER PATH '$.embed_id',
        embed_data VARCHAR2(4000) PATH '$.embed_data',
        embed_vector CLOB PATH '$.embed_vector' )
    ) j
) a
set a.mini_vector = a.embed_vector;

commit;

bert_vector列にBERTで生成したベクトル値を挿入

update (
  select t.id, t.detail, t.bert_vector, j.embed_vector
  from (
    select *
    from inquiry_history i,
         dbms_vector.utl_to_embeddings( i.detail, json('{ "provider": "database", "model": "MODEL_BERT" }') )
    ) t ,
    JSON_TABLE(
      t.column_value,
      '$[*]' COLUMNS (
        embed_id NUMBER PATH '$.embed_id',
        embed_data VARCHAR2(4000) PATH '$.embed_data',
        embed_vector CLOB PATH '$.embed_vector' )
    ) j
) a
set a.bert_vector = a.embed_vector;

commit;

実践

「スマホが壊れた」というお客様のお問い合わせをベクトル化し、過去のお問い合わせ履歴の中から、ベクトル距離が近い10件を出力させてみます。

最初に今回の検証で精度が高かったBERTでベクトル検索を行った際の結果をお見せします。

VARIABLE var_inq varchar2
exec :var_inq := 'スマホが壊れた';

with var_vector as (
  select et.embed_vector
 from
   dbms_vector.utl_to_embeddings(
     :var_inq,
     json('{"provider": "database", "model": "MODEL_BERT" }')
   ) t,
   JSON_TABLE(
     t.column_value,
      '$[*]' COLUMNS (
        embed_id NUMBER PATH '$.embed_id',
        embed_data VARCHAR2(4000) PATH '$.embed_data',
        embed_vector CLOB PATH '$.embed_vector'
        )
    ) et
)
select
  vector_distance(var_vector.embed_vector, bert_vector) as distance,
  detail
from
  inquiry_history, var_vector
order by
  distance
fetch first 10 rows only;

vector_distance(var_vector.embed_vector, bert_vector)

vector_distance関数で「スマホが壊れた」のベクトルデータと、格納済みのベクトルデータとのベクトル距離を測っています。

デフォルトの距離メトリックはコサイン(COSINE)で、明記する場合は以下のように記載します。

vector_distance(var_vector.embed_vector, bert_vector, COSINE)

その他に DOT/EUCLIDEAN/EUCLIDEAN_SQUARED/HAMMING/MANHATTAN が使用できますが、今回の検証では距離メトリックの違いによる順番の変動はありませんでした。

結果は以下の通り。

DISTANCE               DETAIL                                                                                                                                                                
______________________ _____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
0.40472501516342163    件名: 通話中の切断\n内容: 通話中に突然切断されることがあります。原因と対策を教えてください。\n回答: 通話中の切断は、電波の強さやネットワークの問題が原因です。電波の強い場所で通話を行う、端末の再起動をお試しください。
0.40581953525543213    件名: 通話中のハウリング\n内容: 通話中にハウリングが発生します。対処方法を教えてください。\n回答: 通話中のハウリングは、端末のマイクとスピーカーの位置関係が原因です。イヤホンを使用することで改善する場合があります。
0.4108541011810303     件名: 通話中の音声遅延\n内容: 通話中に音声が遅延することがあります。対処方法を教えてください。\n回答: 通話中の音声遅延は、ネットワークの混雑や端末の性能が原因です。電波の強い場所で通話を行う、端末の再起動をお試しください。
0.41457128524780273    件名: オンラインゲーム中のラグ\n内容: オンラインゲームをしているとラグが発生します。改善方法を教えてください。\n回答: オンラインゲーム中のラグは、ネットワークの混雑やデバイスの性能が影響することがあります。優先接続の設定や、他のデバイスの使用を制限することで改善することがあります。                                                                         
0.4154418706893921     件名: 請求書に誤りがある\n内容: 今月の請求書に誤りがあるようです。先月分の料金が二重に請求されています。\n回答: 請求書の誤りについてご連絡ありがとうございます。調査の上、訂正させていただきます。訂正後の請求書を再送いたしますので、しばらくお待ちください。                                                                                                     
0.419796347618103      件名: 通話中の雑音\n内容: 通話中に雑音が入ります。対策を教えてください。\n回答: 通話中の雑音は、周囲の環境や端末の問題が原因です。静かな場所で通話を行う、端末の再起動をお試しください。
0.42413556575775146    件名: 通話品質の向上方法\n内容: 通話品質を向上させる方法を教えてください。\n回答: 通話品質の向上には、電波の強い場所で通話すること、他の電子機器から離れることが有効です。また、端末のソフトウェアを最新に保つこともお勧めします。
0.4264066815376282     件名: インターネットの速度が遅い\n内容: 最近、インターネットの速度が非常に遅くなっています。特に夜間は動画がスムーズに再生できません。対策を教えてください。\n回答: ご不便をおかけして申し訳ございません。通信速度の低下はネットワークの混雑や周辺環境の影響が考えられます。対策として、ルーターの再起動や周辺機器の配置変更をお試しください。改善しない場合は、詳細な調査を行いますので、再度ご連絡ください。
0.42750102281570435    件名: SIMカードが認識されない\n内容: 新しく購入したスマートフォンにSIMカードを挿入しましたが、認識されません。どうすれば解決できますか?また、SIMカードの再発行は可能ですか?\n回答: SIMカードが認識されない問題についてお知らせいただき、ありがとうございます。まず、SIMカードを他の端末で試していただき、それでも問題が解決しない場合は、SIMカードの再発行をお手配いたします。再発行手続きについては、お近くの店舗にご来店いただくか、オンラインでお申し込みください。
0.4283760190010071     件名: スピーカーの故障\n内容: 携帯電話のスピーカーが故障して音が出ません。修理方法を教えてください。\n回答: スピーカーの故障は、修理センターでの対応となります。修理依頼は店舗またはオンラインで行うことができます。

10行が選択されました。

経過時間: 00:00:06.373

通話の切断や遅延、品質劣化など、主にスマホが正常に動いていない過去のお問い合わせ履歴が出力されました。

続いて、参考までにベクトル距離が遠い10件を出力させてみました。(descにしたただけ)

with var_vector as (
  select et.embed_vector
 from
   dbms_vector.utl_to_embeddings(
     :var_inq,
     json('{"provider": "database", "model": "MODEL_BERT" }')
   ) t,
   JSON_TABLE(
     t.column_value,
      '$[*]' COLUMNS (
        embed_id NUMBER PATH '$.embed_id',
        embed_data VARCHAR2(4000) PATH '$.embed_data',
        embed_vector CLOB PATH '$.embed_vector'
        )
    ) et
)
select
  vector_distance(var_vector.embed_vector, bert_vector) as distance,
  detail
from
  inquiry_history, var_vector
order by
  distance desc
fetch first 10 rows only;

DISTANCE              DETAIL                                                                                                                                                                 
_____________________ ____________________________________________________________________________________________________________________________________________________________________________________________________________________
                      件名: 家族プランへの変更\n内容: 家族全員で利用できるプランに変更したいです。詳細を教えてください。\n回答: 家族プランへの変更については、当社のウェブサイトで詳細をご確認いただけます。変更手続きは、オンラインまたは店舗で行うことができます。
0.5215476155281067    件名: 請求書の記載内容について\n内容: 請求書の記載内容に不明点があります。詳しい説明をお願いします。\n回答: 請求書の不明点については、カスタマーサポートまでご連絡いただければ、詳細にご説明いたします。
0.5151771306991577    件名: 国際ローミングのプラン\n内容: 国際ローミングに対応したプランについて教えてください。\n回答: 国際ローミングに対応したプランは、当社のウェブサイトでご確認いただけます。プランの詳細や料金については、マイページからご確認ください。
0.5151727199554443    件名: ポイントの移行\n内容: ポイントを他のアカウントに移行したいのですが、可能でしょうか?\n回答: ポイントの移行はできませんが、同一アカウント内での使用が可能です。詳細はマイページでご確認いただけます。
0.51432204246521      件名: ポイントのキャンペーン\n内容: 現在開催中のポイントキャンペーンについて教えてください。\n回答: 現在開催中のポイントキャンペーンは、当社のウェブサイトでご確認いただけます。キャンペーン内容や期間については、随時更新されますのでご確認ください。
0.5132672786712646    件名: 支払い方法の変更期限\n内容: 支払い方法を変更する際の期限について教えてください。\n回答: 支払い方法の変更期限は、次回請求書発行日の1週間前までとなります。詳細はマイページでご確認ください。
0.5119727849960327    件名: 国際ローミングの料金\n内容: 海外でのデータ利用時の料金体系を教えてください。\n回答: 国際ローミングの料金は、利用する国や地域によって異なります。詳細な料金体系は当社のウェブサイトでご確認いただけます。
0.5059264898300171    件名: ポイントの利用方法について\n内容: 貯まったポイントを使いたいのですが、どのように利用すれば良いでしょうか?また、ポイントの有効期限も教えてください。\n回答: ポイントのご利用方法についてご案内いたします。ポイントは、当社のウェブサイトまたは店舗での購入時に使用できます。詳細な使用方法は、会員ページにログインしてご確認ください。ポイントの有効期限は、最終利用日から1年間ですので、お早めにご利用ください。
0.503799319267273     件名: 請求書の支払い期限について\n内容: 請求書の支払い期限について教えてください。\n回答: 請求書の支払い期限は、請求書に記載されている日付となります。通常、請求書発行後30日以内にお支払いいただく必要があります。
0.502672553062439     件名: 国際ローミングのデータプラン\n内容: 国際ローミング用のデータプランがあるか教えてください。\n回答: 国際ローミング用のデータプランは、当社のウェブサイトでご確認いただけます。プランの詳細や料金については、マイページからご確認ください。

10行が選択されました。

経過時間: 00:00:03.400

プラン変更、支払い、ポイント利用など、スマホの故障とは関連性の低い内容が出力されました。

(降順で検索した際にDISTANCEがnullとなるケースがありましたが、ベクトル値も入っており、比較対象とベクトル次元も一致していたのでなぜnullになってしまうのかは不明でした)

続いて、MINILMでの結果も見ていきましょう。

VARIABLE var_inq varchar2
exec :var_inq := 'スマホが壊れた';

with var_vector as (
  select et.embed_vector
 from
   dbms_vector.utl_to_embeddings(
     :var_inq,
     json('{"provider": "database", "model": "MINILM_MODEL" }')
   ) t,
   JSON_TABLE(
     t.column_value,
      '$[*]' COLUMNS (
        embed_id NUMBER PATH '$.embed_id',
        embed_data VARCHAR2(4000) PATH '$.embed_data',
        embed_vector CLOB PATH '$.embed_vector'
        )
    ) et
)
select
  vector_distance(var_vector.embed_vector, mini_vector) as distance,
  detail
from
  inquiry_history, var_vector 
order by
  distance
fetch first 10 rows only;

DISTANCE              DETAIL
_____________________ _____________________________________________________________________________________________________________________________________________
0.5397957563400269    件名: プラン変更のタイミング\n内容: データプランを変更したいのですが、いつ変更すれば良いですか?\n回答: データプランの変更は、月末までに申請いただければ翌月から適用されます。詳しい手続きはマイページでご確認いただけます。
0.548862099647522     件名: 通話が途切れる\n内容: 通話中に頻繁に途切れてしまいます。対処方法を教えてください。\n回答: 通話が途切れる場合、電波の強い場所で通話を行う、端末の再起動をお試しください。改善しない場合は、ネットワークの状況を確認いたしますので、再度ご連絡ください。
0.552870512008667     件名: 画面が割れた\n内容: 携帯電話の画面が割れてしまいました。修理費用と手続きを教えてください。\n回答: 画面割れの修理については、修理センターでの対応となります。修理費用はモデルによって異なりますので、詳細は当社のウェブサイトでご確認いただけます。
0.5536371469497681    件名: 速度制限の解除について\n内容: 速度制限がかかっているようですが、解除する方法を教えてください。\n回答: 速度制限は、月間データ使用量が上限に達した場合に適用されます。追加データを購入することで、速度制限を解除することができます。詳細はマイページでご確認ください。
0.5681867003440857    件名: プラン変更の確認\n内容: プラン変更が正しく反映されているか確認したいです。\n回答: プラン変更の反映については、マイページの「契約内容」セクションでご確認いただけます。
0.5724462270736694    件名: 契約解除の手数料免除\n内容: 契約解除の手数料を免除してもらうことは可能ですか?\n回答: 契約解除の手数料免除については、特別な事情がある場合に限り検討いたします。詳細はカスタマーサポートまでご連絡ください。
0.5736000537872314    件名: SIMカードのサイズ変更\n内容: 現在のSIMカードのサイズを変更したいのですが、手続き方法を教えてください。\n回答: SIMカードのサイズ変更は、店舗で行うことができます。新しい端末に対応するサイズのSIMカードをお渡しいたします。
0.5769633054733276    件名: 契約解除の手数料\n内容: 契約解除にかかる手数料について教えてください。\n回答: 契約解除にかかる手数料は、契約内容によって異なります。詳細は契約書またはマイページでご確認いただけます。
0.5814880132675171    件名: 新しいプランの適用\n内容: 新しいプランを適用したいのですが、手続き方法を教えてください。\n回答: 新しいプランの適用手続きは、マイページから行うことができます。ログイン後、「プラン変更」セクションをご確認ください。
0.5840420722961426    件名: SIMカードが壊れた\n内容: SIMカードが壊れてしまいました。再発行の手続きを教えてください。\n回答: 壊れたSIMカードの再発行は、オンラインまたは店舗で手続きを行うことができます。詳細は当社のウェブサイトでご確認ください。

10行が選択されました。

BERTとは結果が異なり、プラン変更に関連するお問い合わせ内容など、「スマホが壊れた」への回答としては人間からすると関連度が低いと思われる内容が今回のケースでは出力されてしまいました。

最後にもう一例。お問い合わせ内容を「夜になるとネットが途切れる」に変え、BERTで検索してみます。

VARIABLE var_inq varchar2
exec :var_inq := '夜になるとネットが途切れる';

with var_vector as (
  select et.embed_vector
 from
   dbms_vector.utl_to_embeddings(
     :var_inq,
     json('{"provider": "database", "model": "MODEL_BERT" }')
   ) t,
   JSON_TABLE(
     t.column_value,
      '$[*]' COLUMNS (
        embed_id NUMBER PATH '$.embed_id',
        embed_data VARCHAR2(4000) PATH '$.embed_data',
        embed_vector CLOB PATH '$.embed_vector'
        )
    ) et
)
select
  vector_distance(var_vector.embed_vector, bert_vector) as distance,
  detail
from
  inquiry_history, var_vector
order by
  distance
fetch first 10 rows only;

DISTANCE               DETAIL
______________________ _______________________________________________________________________________________________________________________________________________________________________________________________________________
0.38425612449645996    件名: 通話中の切断\n内容: 通話中に突然切断されることがあります。原因と対策を教えてください。\n回答: 通話中の切断は、電波の強さやネットワークの問題が原因です。電波の強い場所で通話を行う、端末の再起動をお試しください。
0.39424002170562744    件名: インターネットの速度が遅い\n内容: 最近、インターネットの速度が非常に遅くなっています。特に夜間は動画がスムーズに再生できません。対策を教えてください。\n回答: ご不便をおかけして申し訳ございません。通信速度の低下はネットワークの混雑や周辺環境の影響が考えられます。対策として、ルーターの再起動や周辺機器の配置変更をお試しください。改善しない場合は、詳細な調査を行いますので、再度ご連絡ください。
0.3960091471672058     件名: 通話が途切れる\n内容: 通話中に頻繁に途切れてしまいます。対処方法を教えてください。\n回答: 通話が途切れる場合、電波の強い場所で通話を行う、端末の再起動をお試しください。改善しない場合は、ネットワークの状況を確認いたしますので、再度ご連絡ください。
0.4035411477088928     件名: 通話中の音声遅延\n内容: 通話中に音声が遅延することがあります。対処方法を教えてください。\n回答: 通話中の音声遅延は、ネットワークの混雑や端末の性能が原因です。電波の強い場所で通話を行う、端末の再起動をお試しください。
0.40869396924972534    件名: 通話中の雑音\n内容: 通話中に雑音が入ります。対策を教えてください。\n回答: 通話中の雑音は、周囲の環境や端末の問題が原因です。静かな場所で通話を行う、端末の再起動をお試しください。
0.41707921028137207    件名: 通話中に声が聞こえない\n内容: 通話中に相手の声が聞こえなくなることがあります。対策を教えてください。\n回答: 通話中に声が聞こえない場合、まず端末の音量設定を確認してください。また、他の通話アプリを使用している場合は、設定を確認してください。改善しない場合は、ネットワークの状況を確認いたします。
0.42083191871643066    件名: インターネット接続が不安定\n内容: インターネット接続が頻繁に切れることがあります。原因と対策を教えてください。\n回答: インターネット接続が不安定な場合、ルーターやモデムの再起動をお試しください。また、接続機器や配線に問題がないか確認してください。改善しない場合は、詳細な調査を行いますので、再度ご連絡ください。
0.4244661331176758     件名: モバイルデータの速度が遅い\n内容: モバイルデータの速度が非常に遅く、使用に支障があります。改善方法を教えてください。\n回答: モバイルデータの速度が遅い場合は、まず端末の再起動をお試しください。それでも改善しない場合は、データ使用量や周辺環境の影響が考えられます。詳細な調査を行いますので、再度ご連絡ください。
0.42668086290359497    件名: 通話品質の向上方法\n内容: 通話品質を向上させる方法を教えてください。\n回答: 通話品質の向上には、電波の強い場所で通話すること、他の電子機器から離れることが有効です。また、端末のソフトウェアを最新に保つこともお勧めします。
0.4293612837791443     件名: 国際ローミングの停止方法\n内容: 海外でのデータ通信を停止したいのですが、方法を教えてください。\n回答: 海外でのデータ通信を停止するには、端末の設定から「データローミング」を無効にしてください。また、現地での使用を控えることも有効です。

10行が選択されました。

こちらも10番目以外は関連度の高い内容が出力されたのではないかと思います。

おわりに

今回の検証を通じて、ナレッジ検索においてベクトル検索が有用であることを実感しました。

テキストベースのナレッジ検索だけでなく、データベース内の様々な形式のデータをベクトル化することで新たな発見が生まれる可能性もあると感じました。

一方で、使用したモデル「sentence-transformers/all-MiniLM-L6-v2」では384次元、「google-bert/bert-base-multilingual-cased」では768次元のベクトル空間データを使用するため、多次元モデルを導入する際にはパフォーマンスと容量の面での考慮が必要になってきそうです。

23aiの導入を検討している皆さんも、まずは手持ちのデータをベクトル化してみてはいかがでしょうか。

参考サイト

Oracle® Database Oracle AI Vector Search User’s Guide 23ai

https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/index.html

Oracle® Machine Learning for Python User’s Guide Release 2.0

https://docs.oracle.com/en/database/oracle/machine-learning/oml4py/2/mlugp/index.html

DBMS_VECTOR

https://docs.oracle.com/en/database//oracle/oracle-database/23/arpls/dbms_vector1.html

VECTOR_DISTANCE

https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_distance.html

VECTOR_DIMENSION_COUNT

https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_dimension_count.html

FROM_VECTOR

https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/from_vector.html

Oracle Database 23ai のベクトル機能を試す手順 (1)

https://qiita.com/ryotayamanaka/items/156932a48e65d3ddc5ac

[Oracle Cloud]インポートしたONNXフォーマットモデルでOracle Database 23ai表データをEmbeddingしてみた。(2024/05/06)

https://qiita.com/kenwatan/items/153f0f6d2385fffaf606

Oracle Database 23ai FreeとAPEXでRAGを使った生成AIアプリをローコード開発してみた (事前準備編)

https://qiita.com/ssfujita/items/34d9e3c39ca730d29351

Oracle Database 23ai FreeとAPEXでRAGを使った生成AIアプリをローコード開発してみた (アプリ実装 前編)

https://qiita.com/ssfujita/items/c53579bbb3eed4145942

Oracle Database 23ai FreeとAPEXでRAGを使った生成AIアプリをローコード開発してみた (アプリ実装 後編)

https://qiita.com/ssfujita/items/53df4f342e28c238a5a2

Oracle Machine Learning for Pythonをインストールしてみた。(2024/01/30)

https://qiita.com/kenwatan/items/43d4776456d041718bc5

ブログの著者欄

市村 元識

GMOインターネットグループ株式会社

2017年10月GMOインターネットグループ株式会社に入社。データベース大好き!

採用情報

関連記事

KEYWORD

採用情報

SNS FOLLOW

GMOインターネットグループのSNSをフォローして最新情報をチェック