[Oracle Cloud]OCI Generative AI EmbeddingモデルでOracle Database 23ai表データをEmbeddingしてみた。(2024/05/05)

# はじめに

Oracle Database 23ai で、AI Vector Search機能が提供されました。
今回は、OCI Generative AIサービスのEmbeddingモデルを使ってOCI Base Database Oracle Database 23aiの表データをEmbeddingし、Vectorデータ型に格納してみました。

# 作業ステップ

- 事前作業
- credentialの作成
- Embeddingの確認
- 表データのEmbedding
- セマンティック検索の実行

# 事前作業

- 作業用データベースユーザの作成
PDBにSYSDBA権限で接続し、データベースユーザを作成し、「DB_DEVELOPER_ROLE」と「create credential」権限を付与します。

```sql
$ export NLS_LANG=American_America.AL32UTF8
$ sqlplus / as sysdba
alter session set container=pdb1;
CREATE USER docuser identified by <Password> DEFAULT TABLESPACE USERS quota unlimited on USERS;
GRANT DB_DEVELOPER_ROLE, create credential to docuser;
```

- ネットワークACLの設定 
データベースユーザーにホストに対する接続権限を付与

```sql
BEGIN
 DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
 host => '*',
 ace => xs$ace_type(privilege_list => xs$name_list('connect'),
 principal_name => 'docuser',
 principal_type => xs_acl.ptype_db));
END;
/
```

- サンプル表、データの作成
作成したデータベースユーザで表を作成し、データを格納します。

```sql
create table documentation_tab (id number,info varchar2(512));
insert into documentation_tab (id,info) values(	1,'San Francisco is in California.');
-- 省略
commit;
```

# credentialの作成
OCI Generative AIサービスを利用するための credentialを作成します。
OCI CLIの構成ファイル情報を使います。
- OCIユーザOCID
- テナンシーOCID
- コンパートメントOCID
- pem形式の秘密鍵(ファイルの内容を使用)
- API Keyフィンガープリント

```sql
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形式のパラメータ値

```sql
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
<以下略>
```

```sql
declare
  input clob;
  params clob;
  v vector;
begin
  input := 'こんにちは';

  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"
}';

  v := dbms_vector.utl_to_embedding(input, json(params));
  dbms_output.put_line(vector_serialize(v));
exception
  when OTHERS THEN
    DBMS_OUTPUT.PUT_LINE (SQLERRM);
    DBMS_OUTPUT.PUT_LINE (SQLCODE);
end;
/

[1.38320923E-002,5.4473877E-002,-3.61633301E-003,-3.08532715E-002,8.43811035E-00
3,1.01623535E-002,-2.00500488E-002,-6.60400391E-002,-1.26495361E-002,2.07519531E
-002,4.22668457E-002,2.97851562E-002,2.44140625E-002,8.65936279E-003,2.98461914E
<以下略>
```

# 表データのEmbedding
表のVarchar2列データをdbms_vector.utl_to_embeddingを使ってEmbeddingしてみます。
EmbeddingモデルにはOCI Generative AIの「cohere.embed-multilingual-v3.0」を使用します。

操作を簡略するためにEmbedding用のファンクションを作成します。

```sql
CREATE OR REPLACE FUNCTION vector_get(keywd IN CLOB)
RETURN vector IS
 v vector;
BEGIN
 select et.embed_vector into v
  from dbms_vector.utl_to_embeddings(
           keywd, 
           json('{
	        "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"
	        }')
	) 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;

    RETURN v;
END;
/
```

Vector列を持つ表(documentation_table)を作成し、サンプル表(documentation_tab)のデータEmbeddingします。

```sql
create table documentation_table (id number, text clob,v vector);
insert into documentation_Table select id,info,vector_get(info) from documentation_tab;
commit;
```

# セマンティック検索の実行
Embeddingされたデータを使ってセマンティック検索を実施してみます。

```sql
select text from documentation_table order by vector_distance(v, vector_get('&Keyword'), EUCLIDEAN) fetch first 5 rows only;

Enter value for keyword: cars
old   1: select text from documentation_table order by vector_distance(v, vector_get('&Keyword'), EUCLIDEAN) fetch first 5 rows only
new   1: select text from documentation_table order by vector_distance(v, vector_get('color'), EUCLIDEAN) fetch first 5 rows only

TEXT
--------------------------------------------------------------------------------
Teslas are electric.
Ford 150 are popular.
Toyotas are reliable.
Hondas are reliable.
Porsches are fast and reliable.

5 rows selected.

/
Enter value for keyword: NY
old   1: select text from documentation_table order by vector_distance(v, vector_get('&Keyword'), EUCLIDEAN) fetch first 5 rows only
new   1: select text from documentation_table order by vector_distance(v, vector_get('NY'), EUCLIDEAN) fetch first 5 rows only

TEXT
--------------------------------------------------------------------------------
Queens is in New York.
Manhattan is in New York.
The Bronx is in New York.
Staten Island is in New York.
Brooklyn is in New York.

5 rows selected.

```

「Cars」のキーワードで検索した結果
Tesla / Ford / Toyota / Honda / Porsche  の文字が含まれた文が返されました。
「NY」のキーワードで検索した結果
New York の文字が含まれた文が返されました。


# おわりに

Oracle Database 23ai の AI Vestor Search機能でOCI Generative AIのEmveddingモデルを使ったEmveddingを表データに対して実施してみました。Embeddingされたデータに対してセマンティック検索をすることができました。

## 参考情報
- [Convert Text String to Embedding](https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/convert-text-string-embedding.html)

- [ベクトル・ユーティリティPL/SQLパッケージの使用条件](https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/terms-using-vector-utility-pl-sql-packages.html)
Embeddingモデルに利用できるサードパーティのRESTプロバイダには、Cohere、Google AI、Hugging Face、Generative AI、OpenAI、Vertex AIなどがあります。