Autonomous Database：SELECT AI機能を使用してOpenAIを利用した自然言語によるクエリ実行を試してみた（日本語でも実行できた）

# はじめに
Autonomous Databaseで、自然言語からSQLを生成するSELECT AI機能が利用可能になったので、早速試してみました。

https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/sql-generation-ai-autonomous.html#GUID-9CE75F94-7455-4C09-A3F3-118C08E82B7E

2023年9月時点では、SELECT AI機能のAIプロバイダとしてOpenAIおよびCohereが利用可能となっていますが、今回の検証ではOpenAIをAIプロバイダーとして使用しました。

SELECT AI機能でAPプロバイダを利用する際の前提として、マニュアルに以下の記載がありましたので、OpenAIの有料アカウントを作成し、APIキーを作成しました。

```
You have a paid API account with AI providers like, OpenAI and Cohere.
```

なお、こちらの検証内容は、あくまで2023年9月時点の内容です。
また、実行される環境での動作が必ずしもこの記事の内容と同一であるかは保証致しません。

AIプロバイダとしてCohereを使用する場合の記事はこちら。

https://qiita.com/500InternalServerError/items/7ba0bd00439075ed15d0

AIプロバイダとしてAzure OpenAI Serviceを使用する場合の記事はこちら。

https://qiita.com/500InternalServerError/items/e3934a84bea97feecf29

# 1.ユーザの作成とロール/権限の付与

SQL*PlusからadminユーザとしてAutonomous Databaseに接続します。
なお、こちらの環境では環境変数NLS_LANGをJapanese_Japan.AL32UTF8に設定しています。
```
[opc@tools ~]$ sqlplus admin/Demo#1Demo#1@adb

SQL*Plus: Release 19.0.0.0.0 - Production on 土 9月 30 13:48:08 2023
Version 19.16.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: 土 9月  30 2023 13:39:37 +09:00


Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.21.0.1.0
に接続されました。
SQL> 
```
検証に使用するユーザselect_ai_userを作成し、必要なロールを付与します。
```
SQL> GRANT DWROLE, UNLIMITED TABLESPACE TO select_ai_user IDENTIFIED BY Demo#1Demo#1;

権限付与が成功しました。

SQL> 
```
select_ai_userに対して、SELECT AI機能の利用に必要なDBMS_CLOUD_AIパッケージの実行権限を付与します。
```
SQL> GRANT EXECUTE ON DBMS_CLOUD_AI TO select_ai_user;

権限付与が成功しました。

SQL> 
```
select_ai_userに対して、OpenAIのAPIのホストapi.openai.comに対するHTTPアクセスを許可します。
```
SQL> BEGIN
  2      DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
  3          host => 'api.openai.com',
  4          ace  => xs$ace_type(privilege_list => xs$name_list('http'),
  5                              principal_name => 'SELECT_AI_USER',
  6                              principal_type => xs_acl.ptype_db)
  7      );
  8  END;
  9  /

PL/SQLプロシージャが正常に完了しました。

SQL> 
```
SQL*Plusを終了します。
```
SQL> exit
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.21.0.1.0との接続が切断されました。
[opc@tools ~]$ 
```

# 2. SELECT AIでOpenAIを利用するための準備

SQL*Plusからselect_ai_userとしてAutonomous Databaseに接続します。
```
[opc@tools ~]$ sqlplus select_ai_user/Demo#1Demo#1@adb

SQL*Plus: Release 19.0.0.0.0 - Production on 土 9月 30 13:54:13 2023
Version 19.16.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.



Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.21.0.1.0
に接続されました。
SQL> 
```
DBMS_CLOUD.CREATE_CREDENTIALプロシージャで、OpenAIのAPIに接続するためのクレデンシャルopenai_credを作成します。
パスワードには、OpenAIのサイドで取得したAPIキーの値を設定します。
```
SQL> BEGIN
  2      DBMS_CLOUD.CREATE_CREDENTIAL(
  3          credential_name => 'OPENAI_CRED',
  4          username        => 'OPENAI',
  5          password        => 'xx-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  6      );
  7  END;
  8  /

PL/SQLプロシージャが正常に完了しました。

SQL>
```
DBMS_CLOUD_AI.CREATE_PROFILEプロシージャで、SELECT AIで使用するAIプロファイルopenaiを作成します。
・profile_nameには作成するプロファイル名を指定します。
・credential_nameには、先ほど作成したOpenAIのAPIに接続するためのクレデンシャルを指定します。
・attributesのobject_listには、このプロファイルで使用するスキーマ・オブジェクトの所有者とオブジェクト名を指定します。

この例では、Autonomous Databaseにデフォルトで用意されているサンプルスキーマSH内にあるcustomers、sales、produces、countriesの4つの表をこのプロファイルで使用するオブジェクトとして登録しています。
```
SQL> BEGIN
  2      DBMS_CLOUD_AI.CREATE_PROFILE(
  3          profile_name => 'OPENAI',
  4          attributes   => '{"provider": "openai",
  5                            "credential_name": "OPENAI_CRED",
  6                            "object_list": [{"owner": "SH", "name": "customers"},
  7                                            {"owner": "SH", "name": "sales"},
  8                                            {"owner": "SH", "name": "products"},
  9                                            {"owner": "SH", "name": "countries"}]
 10                           }'
 11      );
 12  END;
 13  /

PL/SQLプロシージャが正常に完了しました。

SQL>
```
以上で、SELECT AI機能のAIプロバイダーとしてOpenAIを利用する準備が整いました。


# 3. SELECT AI機能を使用した自然言語によるクエリの実行

DBMS_CLOUD_AI.SET_PROFILEプロシージャで、現在のセッションで使用するAIプロファイルに先ほど作成したopenaiを設定します。
```
SQL> EXEC DBMS_CLOUD_AI.SET_PROFILE('OPENAI');

PL/SQLプロシージャが正常に完了しました。

SQL> 
```
SELECT AIを使用して、自然言語によるクエリを実行してみます。
```
SQL> SELECT AI how many customers exist;

TOTAL_CUSTOMERS
---------------
	      55500

SQL> 
```
SELECT AI SHOWSQLで生成されたSQLを確認します。
```
SQL> SELECT AI SHOWSQL how many customers exist;

RESPONSE
----------------------------------------------------
SELECT COUNT(*) AS total_customers
FROM SH.CUSTOMERS


SQL>
```

試しに日本語で入力してみます。
```
SQL> SELECT AI 顧客は全部で何人いますか;

TOTAL_CUSTOMERS
---------------
	      55500

SQL> 
```
なんと！日本語で入力してもSQLが実行されました！
SELECT AI SHOWSQLで生成されたSQLを確認します。
```
SQL> SELECT AI SHOWSQL 顧客は全部で何人いますか;

RESPONSE
----------------------------------------------------
SELECT COUNT(*) AS TOTAL_CUSTOMERS
FROM SH.CUSTOMERS


SQL> 
```
英語で入力した場合と同じSQLに変換されていることがわかりました。


# まとめ
SELECT AI機能のAIプロバイダーとしてOpenAIを使用して、自然言語によるクエリの実行ができることが確認できました。
また、日本語で入力した場合でも英語で入力した場合と同様にSQLが生成され、自然言語によるクエリの実行が可能であることがわかりました。

# 参考情報

・[Use Select AI to Generate SQL from Natural Language Prompts](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/sql-generation-ai-autonomous.html)
・[DBMS_CLOUD_AI Package](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/dbms-cloud-ai-package.html#GUID-000CBBD4-202B-4E9B-9FC2-B9F2FF20F246)
・[DBMS_CLOUD.CREATE_CREDENTIALプロシージャ](https://docs.oracle.com/cd/E83857_01/paas/autonomous-database/adbsa/dbms-cloud-subprograms.html#GUID-742FC365-AA09-48A8-922C-1987795CF36A)