[Autonomous Database] Data Transformsを使ったベクトル埋め込みを試してみた

# はじめに
Data Transformsの演算子でベクトル埋め込みができるようになりました。ということで試してみます。
[Use Text Embedding Vector in a Data Flow](https://docs.oracle.com/en/database/oracle/sql-developer-web/sdwad/work-with-data-flow.html#GUID-4E4C693D-177B-4B30-8943-3DDF5AA408B1)

# 前提
+ Autonomous Databaseを23aiで構築済み
+ データベース・ユーザーDEMOUSER1を作成し、DWROLEを付与済み
+ OCIユーザー、コンパートメント、テナンシーのOCIDを確認済み。またOCIユーザーでAPI署名キー・ペアを作成し、秘密キー、フィンガープリントを確認済み（OCI Generative AIのアクセスに必要）
+ 2025/6時点で試した情報です

# データベースにサンプル表を作成
ADMINユーザーでDatabase Actionsにログインし、データロードでサンプルデータをロードして表を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/510ff34e-833b-463b-b984-f2b8ee9ebec3.png)

データの中身はこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/7b0658a4-d672-457e-8d5c-f3c85443216a.png)

成功しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/d312e931-a881-4382-bc35-2ecb20021f58.png)

# ADMINユーザーに外部ネットワークへのアクセスを許可
続けて、SQLにアクセスします。以下を実行し、ADMINユーザーに外部ネットワークへのアクセスを許可します。
```
BEGIN
   DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
      host => '*',
      ace => xs$ace_type(privilege_list => xs$name_list('connect'),
                        principal_name => 'admin',
                        principal_type => xs_acl.ptype_db));
END;
/ 
```
完了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/be817141-b96e-466b-8e6d-9bef0e854ac8.png)

# Data Transformsでデータフローを作成し、実行
## Connectionを編集する
Data TransformsにADMINユーザーでログインします。Connectionでデフォルトで作成されているConnectionを編集し、ADMINで接続できるように設定し、Test Connectionで接続ができることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/3e5fcf94-4a3b-49f8-822f-8ca9bf451739.png)

## Data Entityを検出する
Data Entityを選択して、Import Data Entitiesをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/13dd3abc-871d-4dba-a45a-9b1dc9b8dd60.png)

Autonomous DatabaseのConnectionでDEMOUSER1のDEMO_RECIPESを検出します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/1f031bc6-cdef-4c22-a196-62c59b9c32c5.png)

検出できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/5bd26c46-eb7e-4821-ab25-865b9be88c8c.png)

## OCI Generative AIへのConnectionを作成する
ConnectionsでCreate Connectionをクリックし、ServicesからOCI Generative AIを選択し、NEXTをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/e36dfb4e-088d-42d5-bc45-91f06ed0d803.png)


名前にOCI_GENAI_CONN、OCI URLには以下を設定します。
https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText
そのほかのUser OCID、Tenancy OCID、Compartment OCID、Private Key、Fingerprintは適切な値を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/5f268b14-c557-40a1-a7e6-296c38989ca7.png)

接続の確認をします。Test Connectionをクリックすると、Oracle Connectionの選択画面となりますので、Autonomous DatabaseのConnectionを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/0c26bca8-2245-4941-aa7a-8d35c89e6904.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/22c489b3-43ef-4e00-8329-fdd047ce8965.png)

成功することを確認後、Createをクリックして作成します。

## データフローを作成する
左のメニューからProjectsを選択し、Create Data Flowをクリックしてデータフローを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/4ad6571c-4a30-4bbc-8ca6-c0cd21930af8.png)

Add a Schemaで利用するスキーマを選択します。ConnectionにAutonomous DatabaseのConnection、SchemaにDEMOUSER1を選択し、OKをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/b323636f-26cf-41fc-905e-a1c938dfd6cc.png)

Data EntitiyにDEMO_RECIPESが表示されますので、キャンバスにドラッグアンドドロップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/00d112f2-d2c3-4554-9dd3-75d09da88319.png)

上のMachine Learningをクリックし、TextEmbeddingVectorをドラッグアンドドロップし、DEMO_RECIPESからリンクします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/c8e39f5d-04ca-4c02-9c33-ade79af64f67.png)

TextEmbeddingVectorのプロパティを入力していきます。
Generalでは以下のように設定します。
+ AI Service: OCI Generative AI
+ Connection:　OCI_GENAI（作成したGenerative AIのConnection）
+ AI　Model:　cohere.embed-multilingual-v3.0

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/cf575b53-d180-40d9-bd62-8dae45137b4b.png)

Attributeはそのまま

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/a8c555ad-cf20-4db1-bcba-ca1ec96873a8.png)

Column Mappingではchunk_dataをドラッグし、input_textとマッピングします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/828ed8a4-4362-43e4-a408-ea6b94db7630.png)

次にTextEmbeedingVectorの右上の+をクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/c8e39f5d-04ca-4c02-9c33-ade79af64f67.png)

Add Data Entityの画面になります。新しい表の設定をしていきます。NameにDEMO_RECIPES_EMBEDと入力し、Nextをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/2dbcd586-5bcb-4197-93e4-19b3cb90574b.png)

新しくVECTOR_EMBEDDINGデータが追加されていることを確認します。Nextをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/7b0d078e-967f-4f9b-9a69-bf91de6bd9d0.png)

プレビューを確認してSAVEします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/7068a23a-36c5-4df6-8ae0-9bf826413f4e.png)

## 作成したデータ・フローを実行する
実行ボタンをクリックし、データフローを実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/a9b19c65-cbf8-48af-a7ca-4beffb8c84fa.png)

右下のData Flow StatusがDoneとなり、成功しました!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/3956411e-3851-489f-831c-e89eee005908.png)

# SQLで検索
ADMINユーザーでDatabase ActionsのSQLにアクセスします
OCI Genrative AIのAPIコール用のクレデンシャルを作成します。OCIユーザー、コンパートメント、テナンシーのOCID、秘密キー、フィンガープリントを適切に指定して以下のSQLを実行します。


```
declare
  jo json_object_t;
  begin
  -- create an OCI credential
  jo := json_object_t();
  jo.put('user_ocid', 'ocid1.user.oc1..aaaa***********************');
  jo.put('tenancy_ocid', 'ocid1.tenancy.oc1..aaaa****************************************');
  jo.put('compartment_ocid', 'ocid1.compartment.oc1..aaaaaa**********************************************************');
  jo.put('private_key', '-----BEGIN RSA PRIVATE KEY-----
：
-----END RSA PRIVATE KEY-----');
  jo.put('fingerprint', '**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**');
  dbms_output.put_line(jo.to_string);
  dbms_vector.create_credential(
    credential_name => 'OCI_CRED',
    params          => json(jo.to_string));
  end;
  /
```

続けてクエリを実行します。例えば、”さっぱりしたものが食べたい”で検索してみました。
```
SELECT id, recipe, description
FROM demouser1.demo_recipes_embed
ORDER BY vector_distance(vector_embedding , (SELECT to_vector(et.embed_vector) embed_vector
FROM
dbms_vector_chain.utl_to_embeddings('さっぱりしたものが食べたい', 
JSON('{"provider": "ocigenai", "credential_name": "OCI_CRED", "url": "https://inference.generativeai.ap-osaka-1.oci.oraclecloud.com/20231130/actions/embedText", "model": "cohere.embed-multilingual-v3.0"}')) 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), COSINE) FETCH EXACT FIRST 4 ROWS ONLY;
```
さっぱりした料理が出力されました。（ペペロンチーノは違う気がしますが、、）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/7fd5eabf-86d7-4727-b39f-6d4d565fad7f.png)

# 試していて気づいたことをいくつか
## Test Connectionで失敗した場合は、選択したADBにクレデンシャルの残骸が残る
いずれも後で削除しましたが、USER_CREDENTIALSを検索してみると作成した覚えがないTEST_CREDで始まるクレデンシャルが存在。
```
select * from user_credentials;

CREDENTIAL_NAME          USERNAME                                                                     WINDOWS_DOMAIN COMMENTS                                                                              ENABLED 
------------------------ ---------------------------------------------------------------------------- -------------- ------------------------------------------------------------------------------------- ------- 
CRED_ADMIN               oracleidentitycloudservice/yuka.arashi@oracle.com                            null           {"comments":"Created via DBMS_CLOUD.create_credential"}                               TRUE    
OCI$RESOURCE_PRINCIPAL   ADMIN                                                                        null           {"comments":"Created resource principal credential via DBMS_CLOUD.create_credential"} TRUE    
OCI_CRED                 ocid1.user.oc1..aaaaaaaaz56xoppdvh6dgui6v2mes5jbsg2qelcgcv3u227lxqg4bfzzhbaa null           {"comments":"Created native credential via DBMS_CLOUD.create_credential"}             TRUE    
TEST_CRED_2025MAY26_0044 ocid1.user.oc1..aaaaaaaaz56xoppdvh6dgui6v2mes5jbsg2qelcgcv3u227lxqg4bfzzhbaa null           {"comments":"Created native credential via DBMS_CLOUD.create_credential"}             TRUE    


Elapsed: 00:00:00.015
4行が選択されました。
```
表も。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/3e2a14ee-28ff-4d01-8338-f6e44e50fea8.png)

## フロー実行時はクレデンシャルを都度作成し、完了すると削除されるよう
作成したデータフローのコードを参照してみると、DT_AI_CREDという名前のクレデンシャルを削除―作成―削除していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/ed984406-d18c-4524-b671-80d0f85e03b6.png)
：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/8f50e095-dcf3-45cb-aa66-07e857e78c15.png)
：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/ed984406-d18c-4524-b671-80d0f85e03b6.png)

## us-chicago-1では成功するが、ap-osaka-1はInternal Errorになる
まだすべてのリージョンで利用できるというわけではないようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/7cd53674-c9c2-4f1e-ad63-2d3aec3c1a1c.png)

## TextEmbeddingVectorの入力はCLOBのみのよう
生成されるコードを見るとdbms_vector_chain.utl_to_embeddingを実行していますが、入力がSUBSTR関数で2000文字で区切られていました。そのためSUBSTR関数の入力に利用できない配列の型（VECTOR_ARRAY_T）は使えなさそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/1aec8a14-dccc-44a5-87af-a43ee259b9f2.png)

# おわりに
Data Transformsでベクトルの埋め込みを試してみました。他にもDatabase Actionsのデータ・ロードを呼びだす機能も新しくリリースされていますし、Autonomous Databaseのデータ変換ツールとしてどんどん機能が拡張されているような気がします。