はじめに
Oracle Database 23ai の AI Vector Search機能を使って類似性検索をすることができます。
今回は、リレーショナル表の複数の列値からJSONを生成し、JSON列をEmbeddingし類似性検索をする簡単なテストを実施してみました。
EmbeddingモデルにはOCI Generative AIサービスのcohere.embed-multilingual-v3.0モデルを使用しました。
作業ステップ
- 事前作業
- JSONデータのEmbedding
- 類似性検索
事前作業
- 作業用データベースユーザの作成
PDBにSYSDBA権限で接続し、データベースユーザを作成し、「DB_DEVELOPER_ROLE」、「create credential」権限を付与します。
$ export NLS_LANG=American_America.AL32UTF8
$ sqlplus / as sysdba
alter session set container=pdb1;
CREATE USER IRIS identified by <password> DEFAULT TABLESPACE USERS quota unlimited on USERS;
GRANT DB_DEVELOPER_ROLE, create credential to IRIS;
- ネットワークACLの設定
データベースユーザーにホストに対する接続権限を付与
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '*',
ace => xs$ace_type(privilege_list => xs$name_list('connect'),
principal_name => 'iris',
principal_type => xs_acl.ptype_db));
END;
/
- サンプル表、データの作成
作成したデータベースユーザで表を作成し、データを格納します。
今回は Iris Dataset:あやめ(花びら/がく片の長さと幅の4項目)の表形式データセットを使用しました。
CREATE TABLE "IRIS"."IRIS"
( "SEPAL_LENGTH" NUMBER,
"SEPAL_WIDTH" NUMBER,
"PETAL_LENGTH" NUMBER,
"PETAL_WIDTH" NUMBER,
"CLASS" VARCHAR2(64 BYTE)
);
-
credentialの作成
OCI Generative AIサービスを利用するための credentialを作成します。
OCI CLIの構成ファイル情報を使います。- OCIユーザ
- OCIDテナンシー
- OCIDコンパートメントOCID
- pem形式の秘密鍵(ファイルの内容を使用)
- API Keyフィンガープリント
exec dbms_vector.drop_credential('OCI_GENAI_CRED');
declare
jo json_object_t;
begin
jo := json_object_t();
jo.put('user_ocid','ocid1.user.oc1..aaaaaaaa');
jo.put('tenancy_ocid','ocid1.tenancy.oc1..aaaaaaaa');
jo.put('compartment_ocid','ocid1.compartment.oc1..aaaaaaaa');
jo.put('private_key','aaaaaaaa');
jo.put('fingerprint','aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa');
dbms_output.put_line(jo.to_string);
dbms_vector.create_credential(
CREDENTIAL_NAME => 'OCI_GENAI_CRED',
PARAMS => json(jo.to_string));
end;
/
- OCI Generative AI Serviceを呼び出して、Embeddingできるか確認
credentialが正しく作成されているか確認を兼ねてdbms_vector.utl_to_embeddingsファンクションでEmbeddingを実施します。Embeddingモデルに「cohere.embed-multilingual-v3.0」を使用してみます。
- provider : ocigenai
- credential_name : 作成した credential
- url : OCI Generative AI Embedding のエンドポイントURL
- model : 使用する Embedding モデル
- utl_to_embeddinsの引数 :Embeddingする文字列(CLOB)とJSON形式のパラメータ値
var embed_genai_params clob;
exec :embed_genai_params := '{"provider": "ocigenai", "credential_name": "OCI_GENAI_CRED", "url": "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText", "model": "cohere.embed-multilingual-v3.0"}';
select et.* from dbms_vector.utl_to_embeddings('こんにちは', json(:embed_genai_params)) et;
COLUMN_VALUE
--------------------------------------------------------------------------------
{"embed_id":"1","embed_data":"こんにちは","embed_vector":"[0.0138
32092,0.054473877,-0.003616333,-0.030853
271,0.00843811,0.0101623535,-0.020050049
<以下略>
JSONデータのEmbedding
JSON列とVECTOR列の追加
JSONを格納するIRISJSON列とEmbedding結果を格納するIRISVECTOR列を追加
alter table iris add (IRISJSON JSON);
alter table iris add (IRISVECTOR vector);
既存の列データからJSONデータの生成
既存の列値をキーと値として持つ JSONデータを生成し、追加したJSON列に値を追加します。
update iris set irisjson = JSON_OBJECT (
KEY 'SEPAL-LENGTH' VALUE SEPAL_LENGTH ,
KEY 'SEPAL-WIDTH' VALUE SEPAL_WIDTH ,
KEY 'PETAL-LENGTH' VALUE PETAL_LENGTH ,
KEY 'PETAL-WIDTH' VALUE PETAL_WIDTH
) ;
commit;
JSON列をEmbedding
JSON列の値をEmbeddingし、値を追加したVECTOR列に追加します。
var embed_genai_params clob;
exec :embed_genai_params := '{"provider": "ocigenai", "credential_name": "OCI_GENAI_CRED", "url": "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText", "model": "cohere.embed-multilingual-v3.0"}';
update iris set IRISVECTOR = dbms_vector.utl_to_embedding(to_CLOB(IRISJSON),json(:embed_genai_params))
類似性検索
JSONデータをパラメータとして類似性検索を実施
- パラメータ値: {"SEPAL-LENGTH":5.1,"SEPAL-WIDTH":3.5,"PETAL-LENGTH":1.4,"PETAL-WIDTH":0.2} での検索
var embed_genai_params clob;
exec :embed_genai_params := '{"provider": "ocigenai", "credential_name": "OCI_GENAI_CRED", "url": "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText", "model": "cohere.embed-multilingual-v3.0"}';
SELECT SEPAL_LENGTH,SEPAL_WIDTH,PETAL_LENGTH,PETAL_WIDTH,CLASS
FROM IRIS
ORDER BY VECTOR_DISTANCE(IRISVECTOR,dbms_vector.utl_to_embedding(to_CLOB('&keyword'), json(:embed_genai_params)), EUCLIDEAN) fetch first 5 rows only;
Enter value for keyword: {"SEPAL-LENGTH":5.1,"SEPAL-WIDTH":3.5,"PETAL-LENGTH":1.4,"PETAL-WIDTH":0.2}
検索結果
SEPAL_LENGTH SEPAL_WIDTH PETAL_LENGTH PETAL_WIDTH CLASS
------------ ----------- ------------ ----------- -----------
5.1 3.5 1.4 0.2 Iris-setosa
5.1 3.4 1.5 0.2 Iris-setosa
5.1 3.5 1.4 0.3 Iris-setosa
5.1 3.3 1.7 0.5 Iris-setosa
5.1 3.7 1.5 0.4 Iris-setosa
Elapsed: 00:00:06.666
5行が選択されました。
- パラメータ値: {"SEPAL-LENGTH":6.4,"SEPAL-WIDTH":2.8,"PETAL-LENGTH":5.6,"PETAL-WIDTH":2.2} での検索
var embed_genai_params clob;
exec :embed_genai_params := '{"provider": "ocigenai", "credential_name": "OCI_GENAI_CRED", "url": "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText", "model": "cohere.embed-multilingual-v3.0"}';
SELECT SEPAL_LENGTH,SEPAL_WIDTH,PETAL_LENGTH,PETAL_WIDTH,CLASS
FROM IRIS
ORDER BY VECTOR_DISTANCE(IRISVECTOR,dbms_vector.utl_to_embedding(to_CLOB('&keyword'), json(:embed_genai_params)), EUCLIDEAN) fetch first 5 rows only;
Enter value for keyword: {"SEPAL-LENGTH":6.4,"SEPAL-WIDTH":2.8,"PETAL-LENGTH":5.6,"PETAL-WIDTH":2.2}
検索結果
SEPAL_LENGTH SEPAL_WIDTH PETAL_LENGTH PETAL_WIDTH CLASS
------------ ----------- ------------ ----------- ---------------
6.4 2.8 5.6 2.2 Iris-virginica
6.4 2.8 5.6 2.1 Iris-virginica
6.4 3.1 5.5 1.8 Iris-virginica
6.4 3.2 4.5 1.5 Iris-versicolor
6.2 2.8 4.8 1.8 Iris-virginica
Elapsed: 00:00:06.052
5行が選択されました。
おわりに
既存の表の複数の列をJSON形式で保持し、JSON列に対してEmbedding化から類似性検索することで、幅広い場面で活用できるのではないでしょうか。