SELECT AIを利用した自然言語による問い合わせ

# はじめに
OracleがOCI（Oracle Cloud Infrastructure）で提供しているAutonomous Databaseの機能であるSELECT AIを利用して自然言語による以下のような問い合わせを行います
```
SELECT AI <自然言語の問い合わせ>;
```
以下からOCIを無料で利用できます

https://oracle-japan.github.io/ocitutorials/beginners/acquiring-free-trial/

今回はGPT-4oを利用しているためAPI使用料金として最低5ドルの課金が必要です

# Autonomous Databaseの作成

https://oracle-japan.github.io/ocitutorials/adb/adb101-provisioning/

# ユーザー作成
SELECT AIを実行するためのユーザを作成します

データベース・アクション>データベースユーザー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766517/55eca496-1135-6a0d-9517-50872ffda2a8.png)
SELECTAIユーザーを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766517/f0d8e4b9-2826-6e47-72b0-dd4365509f93.png)
# データロード
csvはこちらから拝借

https://catalog.data.metro.tokyo.lg.jp/dataset/t000012d0000000016/resource/855ac9e9-3ff2-438d-af1e-3cf6a2217869

データベース・アクション>データロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766517/9a041915-430e-7419-b071-76b11e3e84e5.png)
データのロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766517/5fb37c3c-f2c4-6ea9-2c37-1578e31c2628.png)
ローカルファイルからのデータのロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766517/91ca53dd-8934-608f-6146-0eb12fc9e0a8.png)
スキーマ：SELECTAI、名前：PUBLIC_WIRELESS_LANとします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766517/a012a490-2846-55dc-087c-169d7a82ada7.png)
データのロード開始
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766517/d9eca8e3-24c8-87a4-873e-5a855c1dc865.png)
ロード完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766517/2fa41c74-2e6b-3f6b-a70e-46cb7b6a709d.png)
# SELECT AI
Autonomous Databaseへの接続方法は以下を参照

https://oracle-japan.github.io/ocitutorials/adb/adb204-setup-VM/

ADMINユーザでデータベースに接続し必要な権限をSELECTAIユーザに付与
```
sqlplus ADMIN/xxxxxxxxxx@xxxxxxxx

grant execute on DBMS_CLOUD to SELECTAI;
grant execute on DBMS_CLOUD_AI to SELECTAI;
```
今回はOpenAI APIを使用
httpアクセスを許可します
```
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => 'api.openai.com',
ace  => xs$ace_type(privilege_list => xs$name_list('http'),
principal_name => 'SELECTAI',
principal_type => xs_acl.ptype_db)
);
END;
/
```

SELECTAIユーザでデータベースに接続
```
sqlplus SELECTAI/xxxxxxxxxx@xxxxxxxx
```
APIキーの取得方法は以下を参照

https://qiita.com/shimmy-notat/items/1e22dcdaa06ea54208ac

クレデンシャルの作成
passwordの箇所に取得したAPIキーを貼り付けます
```
BEGIN
DBMS_CLOUD.CREATE_CREDENTIAL(
credential_name => 'OPENAI_CRED',
username        => 'OPENAI',
password        => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
);
END;
/
```

プロファイルの作成
```
BEGIN
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name => 'OPENAI',
attributes   => '{"provider": "openai",
"credential_name": "OPENAI_CRED",
"comments":"true",
"model": "gpt-4o",
"object_list": [
{"owner": "SELECTAI", "name": "PUBLIC_WIRELESS_LAN"}]
}'
);
END;
/
```
コメントを追加することで表の内容及び列名の補足をします
ここでは列名"名称"の補足をしています
```
COMMENT ON TABLE "PUBLIC_WIRELESS_LAN" IS '公共Wi-Fiの設置施設の名称を含む';
COMMENT ON COLUMN "PUBLIC_WIRELESS_LAN"."名称" IS '公共Wi-Fiが設置されている施設の名称';
```

SELECT AIの実行
```
EXEC DBMS_CLOUD_AI.SET_PROFILE('OPENAI');
```
```
SELECT AI Wi-Fiが設置されている赤坂の施設を教えて;

"FACILITY_NAME","TOWN","CITY","PREFECTURE","FULL_ADDRESS"
"公衆電話（港区赤坂8-12）","赤坂","港区","東京都","東京都港区赤坂8-12"
"観光案内標識（港区赤坂2-11）","赤坂","港区","東京都","東京都港区赤坂2-11"
"観光案内標識（港区赤坂2-14）","赤坂","港区","東京都","東京都港区赤坂2-14"
"観光案内標識（港区赤坂5-4）","赤坂","港区","東京都","東京都港区赤坂5-4"
"観光案内標識（港区赤坂6-1）","赤坂","港区","東京都","東京都港区赤坂6-1"
"観光案内標識（港区赤坂9-7）","赤坂","港区","東京都","東京都港区赤坂9-7"

6行が選択されました。
```
```
SELECT AI NARRATE Wi-Fiが設置されている赤坂の施設を教えて;

"RESPONSE"
"Wi-Fiが設置されている赤坂の施設は以下の通りです：

1. **施設名**: 公衆電話（港区赤坂8-12）
   - **都道府県**: 東京都
   - **市区町村**: 港区
   - **町字**: 赤坂
   - **番地以下**: 8-12
   - **SSID**: FREE_Wi-Fi_and_TOKYO
   - **URL**: [http://www.wifi-tokyo.jp/ja/](http://www.wifi-tokyo.jp/ja/)

2. **施設名**: 観光案内標識（港区赤坂2-11）
   - **都道府県**: 東京都
   - **市区町村**: 港区
   - **町字**: 赤坂
   - **番地以下**: 2-11
   - **SSID**: FREE_Wi-Fi_and_TOKYO
   - **URL**: [http://www.wifi-tokyo.jp/ja/](http://www.wifi-tokyo.jp/ja/)

3. **施設名**: 観光案内標識（港区赤坂2-14）
   - **都道府県**: 東京都
   - **市区町村**: 港区
   - **町字**: 赤坂
   - **番地以下**: 2-14
   - **SSID**: FREE_Wi-Fi_and_TOKYO
   - **URL**: [http://www.wifi-tokyo.jp/ja/](http://www.wifi-tokyo.jp/ja/)

4. **施設名**: 観光案内標識（港区赤坂5-4）
   - **都道府県**: 東京都
   - **市区町村**: 港区
   - **町字**: 赤坂
   - **番地以下**: 5-4
   - **SSID**: FREE_Wi-Fi_and_TOKYO
   - **URL**: [http://www.wifi-tokyo.jp/ja/](http://www.wifi-tokyo.jp/ja/)

5. **施設名**: 観光案内標識（港区赤坂6-1）
   - **都道府県**: 東京都
   - **市区町村**: 港区
   - **町字**: 赤坂
   - **番地以下**: 6-1
   - **SSID**: FREE_Wi-Fi_and_TOKYO
   - **URL**: [http://www.wifi-tokyo.jp/ja/](http://www.wifi-tokyo.jp/ja/)

6. **施設名**: 観光案内標識（港区赤坂9-7）
   - **都道府県**: 東京都
   - **市区町村**: 港区
   - **町字**: 赤坂
   - **番地以下**: 9-7
   - **SSID**: FREE_Wi-Fi_and_TOKYO
   - **URL**: [http://www.wifi-tokyo.jp/ja/](http://www.wifi-tokyo.jp/ja/)"
```
```
SELECT AI SHOWSQL Wi-Fiが設置されている赤坂の施設を教えて;

"RESPONSE"
"SELECT
    pwl.名称 AS facility_name,
    pwl.所在地_連結表記 AS full_address,
    pwl.SSID AS ssid,
    pwl.URL AS url
FROM
    SELECTAI.PUBLIC_WIRELESS_LAN pwl
WHERE
    pwl.所在地_町字 LIKE '%赤坂%'
```

# 参考

https://docs.oracle.com/cd//E83857_01/paas/autonomous-database/serverless/adbsb/sql-generation-ai-autonomous.html

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

https://qiita.com/ritokuna/items/d57da2a289f9125dcea8

https://qiita.com/marfujim/items/3e2fe1861a7b148e41b1