[Oracle Database 23ai] マルチモーダルLLMを使用して画像の説明を生成してみた(2024/12/06)

# はじめに

Oracle Database 23ai の2024年10月のアップデートでUTL_TO_GENERATE_TEXTプロシージャのインプットにBLOBが追加されました。これにより、Google AI、Hugging Face、OpenAI、Vertex AIによって提供されるマルチモーダルLLMにイメージとテキストの質問を指定することで、イメージからテキストへの変換を実行することができます。

ユースケースに応じて、DBMS_VECTORまたはDBMS_VECTOR_CHAINパッケージのUTL_TO_GENERATE_TEXT関数を使用できますが、今回は、DBMS_VECTOR_CHAINパッケージとOpenAIを使って試してみました。


# 作業ステップ

- 事前作業
- UTL_TO_GENERATE_TEXTを使ってテキスト生成

# 事前作業
- 作業用データベースユーザの作成
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;
/
```

- イメージファイルの準備
イメージファイルを格納するローカルディレクトリ(/home/oracle/image)を作成しイメージファイル(bird.jpgなど)をディレクトリにアップロード。対応するディレクトリオブジェクト(IMAGE_DIR)を作成します。

```sql
create or replace directory IMAGE_DIR as '/home/oracle/image';
```

- イメージファイルを読み込むPL/SQLファンクションの作成
ディレクトリオブジェクトとファイル名を指定し、LOBにロードするファンクション（load_blob_from_file)を作成します。

```sql
create or replace function load_blob_from_file(directoryname varchar2, filename varchar2)
  return blob
is
  filecontent blob := null;
  src_file bfile := bfilename(directoryname, filename);
  offset number := 1;
begin
  dbms_lob.createtemporary(filecontent, true, dbms_lob.session);
  dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
  dbms_lob.loadblobfromfile(filecontent, src_file,
    dbms_lob.getlength(src_file), offset, offset);
  dbms_lob.fileclose(src_file);
  return filecontent;
end;
/
```

- アクセスするLLMプロバイダの資格証明を作成
2024年11月時点では、Google AI、Hugging Face、OpenAI、Vertex AIが対応しています。
今回はOpenAI を使用しました。

```sql
exec dbms_vector_chain.drop_credential('OPENAI_CRED');

declare
  jo json_object_t;
begin
  jo := json_object_t();
  jo.put('access_token', '<access_token>');
  dbms_vector_chain.create_credential(
    credential_name   => 'OPENAI_CRED',
    params            => json(jo.to_string));
end;
/
```


# UTL_TO_GENERATE_TEXTを使ってテキスト生成

以下の画像ファイル(bird.jpg)をデータベースサーバの指定ディレクトリにアップロードし、UTL_TO_GENERATE_TEXTを使ってテキスト生成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/61793b11-885a-bf53-28d8-1a629200f696.png)

テキストの質問に「Describe this image」を指定してテキスト応答を生成しています。


- SELECT文の例

```sql
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 10000
SET LONG 10000

var input clob;
var media_data blob;
var media_type clob;
var params clob;

begin
  :input := 'Describe this image';
  :media_data := load_blob_from_file('IMAGE_DIR', 'bird.jpg');
  :media_type := 'image/jpeg';
  :params := '
{
  "provider"       : "openai",
  "credential_name": "OPENAI_CRED",
  "url"            : "https://api.openai.com/v1/chat/completions",
  "model"          : "gpt-4o-mini",
  "max_tokens"     : 2048,
  "temperature": 1.0
}';
end;
/

select dbms_vector_chain.utl_to_generate_text(:input, :media_data, :media_type, json(:params));

DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT(:INPUT,:MEDIA_DATA,:MEDIA_TYPE,JSON(:PARA
--------------------------------------------------------------------------------
The image features a stylized bird in flight against a vibrant red background. T
he bird has a black and white body, with one wing appearing in orange and purple
 hues. Below, there are abstract clouds illustrated in a minimalist, wavy line s
tyle. The overall composition combines bright colors and graphic elements, creat
ing a modern and artistic representation of the bird.


1 row selected.
```

- PL/SQL の例

```sql
declare
  input clob;
  media_data blob;
  media_type varchar2(32);
  params clob;
  output clob;
begin
  input := 'Describe this image';
  media_data := load_blob_from_file('IMAGE_DIR', 'bird.jpg');
  media_type := 'image/jpeg';
  params := '
{
  "provider"       : "openai",
  "credential_name": "OPENAI_CRED",
  "url"            : "https://api.openai.com/v1/chat/completions",
  "model"          : "gpt-4o-mini",
  "max_tokens"     : 60,
  "temperature": 1.0
}';

  output := dbms_vector_chain.utl_to_generate_text(
    input, media_data, media_type, json(params));
  dbms_output.put_line(output);

  if output is not null then
    dbms_lob.freetemporary(output);
  end if;
  if media_data is not null then
    dbms_lob.freetemporary(media_data);
  end if;
exception
  when OTHERS THEN
    DBMS_OUTPUT.PUT_LINE (SQLERRM);
    DBMS_OUTPUT.PUT_LINE (SQLCODE);
end;
/


The image features a stylized bird, possibly a hummingbird, depicted in flight
against a reddish background. The bird has a distinct design, showcasing a
combination of colors including black, white, orange, and purple. Its wings are
outstretched, with the right wing featuring bold, swirling patterns.

PL/SQL procedure successfully completed.
```



# おわりに

外部のマルチモーダルLLMを使ってデータベースサーバー上のイメージファイルの説明を生成することができました。

## 参考情報
- [パブリックRESTプロバイダを使用したイメージの説明](https://docs.oracle.com/cd/G11854_01/vecse/describe-images-using-public-third-party-apis.html#GUID-D386049F-45B4-4047-B1E9-0A5955F9F1BA)
- [サポートされるサードパーティ・プロバイダの操作およびエンドポイント](https://docs.oracle.com/cd/G11854_01/vecse/supported-third-party-provider-operations-and-endpoints.html#GUID-BE3EE403-CD10-4708-A15F-EFB1FA69DF09)