Oracle DB 23aiの機能で画像の説明文を生成してみた (23ai AI Vector Search + GPT-4o)

Oracle Database 23aiからベクトル検索として「AI Vector Search」が追加されました。
その機能の一つに、画像から説明文を生成するファンクションがあります。
今回は該当ファンクションの「DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT」を試してみました。

なおその他のファンクションについては下記マニュアルに一覧があります。
[Supported Third-Party Provider Operations and Endpoints](https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/supported-third-party-provider-operations-and-endpoints.html#GUID-BE3EE403-CD10-4708-A15F-EFB1FA69DF09__SECTION_CTG_SMC_YCC)

また今回は以下のチュートリアルを参考にしました。
[Describe Images Using Public REST Providers](https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/describe-images-using-public-third-party-apis.html)

## 検証環境

本検証ではOCIで提供されている Autonomous Database の 23ai (23.6) を利用しました。
またインプットする画像ファイルはOCIの Object Storage に格納しました。

## ADBの作成

ADBの作成は下記チュートリアルをご参照ください。
[ADBインスタンスを作成してみよう](https://oracle-japan.github.io/ocitutorials/adb/adb101-provisioning/)

ちなみに今回はSQLやPL/SQLを実行するツールとして、同チュートリアルに記載されている「データベース・アクション」を利用しています。

## DBユーザ作成

データベース・アクションでDBユーザを新規作成します。
ADBの詳細画面から赤枠の「データベース・ユーザ」を選択します。
![WS000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33182/6de7f867-7949-c0d5-0873-194a2e4a8270.jpeg)

右上の「ユーザーの作成」を選択します。
![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33182/e650d3dd-cd6c-62da-d935-351ccae80333.jpeg)

ユーザー名、パスワード等を入力します。
その際に表領域の割当て、Webアクセス (データベース・アクションの有効化) を下記画像の赤枠の通りに設定します。
![WS000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33182/4a167746-d702-8b19-e29f-78689e6d2847.jpeg)

ADMINユーザでデータベース・アクションのSQLにログインし、作成したユーザーに権限を付与します。

```sql
GRANT DB_DEVELOPER_ROLE to docuser;
GRANT DWROLE to docuser;
GRANT CREATE MINING MODEL TO docuser;
GRANT EXECUTE ON DBMS_CLOUD TO docuser;
GRANT EXECUTE ON DBMS_VECTOR TO docuser;
GRANT EXECUTE ON DBMS_VECTOR_CHAIN TO docuser;
```

作成したユーザーがREST API実行できるように設定します。

```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に作成したユーザーでログインし、各コマンドを実行していきます。

## 資格証明の作成

Object Storageにアクセスするための資格証明を作成します。
資格証明の作成に必要なトークンは下記チュートリアルを参照して準備します。
[OCIオブジェクトストレージへのアクセス情報を取得](https://oracle-japan.github.io/ocitutorials/adb/adb102-dataload/#2-1-oci%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%B8%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E6%83%85%E5%A0%B1%E3%82%92%E5%8F%96%E5%BE%97)

取得したトークンを使って資格証明を作成します。

```sql
BEGIN
  DBMS_CLOUD.CREATE_CREDENTIAL(
    credential_name => 'OBJ_CRED',
    username => '<your user name>',
    password => '<your access token>'
  );
END;
/
```

次に生成AIモデルを使うための資格証明を作成します。
私はGPT-4oを使ったため、OpenAI向けの資格証明を作成しました。

```sql
DECLARE
  jo json_object_t;
BEGIN
  jo := json_object_t();
  jo.PUT('access_token', '<your openai access token>');
  DBMS_VECTOR_CHAIN.CREATE_CREDENTIAL(
    credential_name   => 'OPENAI_CRED',
    params            => json(jo.to_string));
END;
/
```

## インプットする画像をObject Storageにアップロード

今回はこちらの画像を使いました。
![mtfuji.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33182/b1534bea-d6ee-4a29-6587-80486f097155.jpeg)

Object Storageへアップロードする手順、アップロードしたファイルのURL確認手順は下記チュートリアルをご参照ください。
[OCIオブジェクトストレージへのデータアップロード](https://oracle-japan.github.io/ocitutorials/adb/adb102-dataload/#2-2-oci%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%B8%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89)

これで画像から説明文を生成する準備が整いました。

## 画像から説明文を生成するPL/SQL

以下PL/SQLのコードでGPT-4oに画像をインプットし、説明文を取得して標準出力できます。

```sql
declare
    input clob;
    media_data blob;
    media_type varchar2(32);
    params clob;
    output clob;
begin
    input := '画像の内容について説明してください。';
    media_type := 'image/jpeg';
    params := '{
        "provider"       : "openai",
        "credential_name": "OPENAI_CRED",
        "url"            : "https://api.openai.com/v1/chat/completions",
        "model"          : "gpt-4o",
        "max_tokens"     : 200
    }';

    -- オブジェクトを取得
    media_data := DBMS_CLOUD.GET_OBJECT(
        credential_name => 'OBJ_CRED',
        object_uri => '<your object url>');
    
    output := dbms_vector_chain.utl_to_generate_text(
        input, media_data, media_type, json(params));
    dbms_output.put_line(output);
end;
/
```

出力結果は以下のようになりました。

```text
この画像には、富士山が映し出されています。山の頂上に雲がかかっており、周囲の景色は夕焼けの光に照らされています。山のふもとには湖が広がっており、湖の上には船が浮
かんでいます。背景には澄んだ青空が広がり、美しい自然の風景が描かれています。
```

![WS000004.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33182/ad2d6bf1-2c16-e0a3-d570-03c16fd46dfa.jpeg)

GPT-4oの説明文が的確すぎて驚愕しました...

## おわりに

23aiのAI Vector Searchを使えばDB内で画像から説明文を生成できることがお分かり頂けたかと思います。
これを使えばECサイトなど画像を大量に扱うシステムで、自動的に説明文を付与してより高精度な検索に活用する、といった仕組みが作れそうですね。
また生成された説明文をベクトル化すれば、画像から意味的に類似した画像を探す、もしくは文章から類似画像を探す、といったマルチモーダル検索も実装できそうです。