オンプレのOracle AI Database 26ai (旧23ai) でもSELECT AIが使えるようになったと聞いたので、動作確認してみました。
ちなみにSELECT AIとは元々Oracle Autonomous AI Database (旧Oracle Autonomous Database、ADB) で提供されている機能で、自然言語からSQLを生成するNL2SQLの機能です。
SELECT AIを使うには DBMS_CLOUD および DBMS_CLOUD_AI パッケージが必要ですが、Autonomous AI Database以外の環境には初期状態でインストールされていません。
26aiのマニュアルから、それらパッケージのインストール方法が明記されるようになりました。
ただしオンプレの26aiは記事作成時点でODA、もしくはExadataでのみGAとなっています。
またお試し環境として 26ai Free が提供されており、Free版であればLinux、Windowsがインストールされた任意の環境で利用できます。
加えてDocker/Podmanのイメージもあります。
今回は任意の環境で手軽に試せる 26ai Free を使って検証しました。
以降は作業手順となります。
目次
- 検証環境
- 26ai Freeインストール
- DBMS_CLOUD、DBMS_CLOUD_AI パッケージの導入と設定
- サンプルスキーマのインストール
- SELECT AIを利用するための設定
- オンプレのSELECT AIを使ってみる
- おわりに
検証環境
環境はOCI上にたてたOracle Linux 9のComputeを使いました。
26ai Freeインストール
まずは 26ai Free をインストールします。
インストールに必要な各種設定を preinstall RPM で実行します。
sudo su -
dnf -y install oracle-ai-database-preinstall-26ai
26ai Freeインストール用のRPMをダウンロードします。
wget https://download.oracle.com/otn-pub/otn_software/db-free/oracle-ai-database-free-26ai-23.26.0-1.el9.x86_64.rpm
26ai Freeをインストールします。
dnf -y install oracle-ai-database-free-26ai-23.26.0-1.el9.x86_64.rpm
DBを構築します。
/etc/init.d/oracle/etc/init.d/oracle-free-26ai configure
opcユーザからoracleユーザに変更し、.bashrcに環境変数を追記します。
export ORACLE_SID=FREE
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=/opt/oracle/product/26ai/dbhomeFree
export PATH=/home/oracle/.local/bin:/home/oracle/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/opt/oracle/product/26ai/dbhomeFree/bin
DBMS_CLOUD、DBMS_CLOUD_AI パッケージの導入と設定
ここから DBMS_CLOUD、DBMS_CLOUD_AI パッケージをインストールしていきます。
冒頭のマニュアルに沿って作業を進めます。
またこれ以降の作業はoracleユーザとして実行します。
パッケージのインストール
同梱されているperlスクリプトを実行してパッケージをインストールします。
まずはパッケージ導入の前提として必要となるC##CLOUD$SERVICEスキーマを作成します。
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u sys/your-password -force_pdb_mode 'READ WRITE' -b dbms_cloud_install -d $ORACLE_HOME/rdbms/admin/ -l /tmp catclouduser.sql
次にDBMS_CLOUD系パッケージをビルドします。
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u sys/your-password -force_pdb_mode 'READ WRITE' -b dbms_cloud_install -d $ORACLE_HOME/rdbms/admin/ -l /tmp dbms_cloud_install.sql
DBログインしてインストールされたか確認します。
正常にインストールされていると複数行に渡って出力されます。
$ sqlplus / as sysdba
-- CDB$ROOTで確認
SQL> select con_id, owner, object_name, status, sharing, oracle_maintained from cdb_objects where object_name like 'DBMS_CLOUD%'
-- FREEPDB1で確認
SQL> alter session set container=freepdb1;
SQL> select owner, object_name, status, sharing, oracle_maintained from dba_objects where object_name like 'DBMS_CLOUD%';
SSLウォレット作成
DBから外部と通信するためにSSLウォレットの作成が必要となります。
まずはウォレットファイルを作成します。
今回は/opt/oracle/dcs/commonstore/wallets/ssl配下にウォレットを作成します。
-pwdオプションにはご自分のパスワードを設定します。
## ウォレットを格納するディレクトリ作成
mkdir -p /opt/oracle/dcs/commonstore/wallets/ssl
## 当該ディレクトリにウォレット作成
cd /opt/oracle/dcs/commonstore/wallets/ssl
orapki wallet create -wallet . -pwd your_password -auto_login
作成したウォレットに証明書を追加します。
追加する証明書はこちらのマニュアルにて配布されている証明書を使います。
また証明書は/home/oracle/dbc配下に配置します。
## 証明書を格納するディレクトリ作成
mkdir -p /home/oracle/dbc
## マニュアルにて配布されている証明書を取得
cd /home/oracle/dbc
wget https://objectstorage.us-phoenix-1.oraclecloud.com/p/KB63IAuDCGhz_azOVQ07Qa_mxL3bGrFh1dtsltreRJPbmb-VwsH2aQ4Pur2ADBMA/n/adwcdemo/b/CERTS/o/dbc_certs.tar
tar xf dbc_certs.tar
証明書は数が非常に多いため、スクリプトを作成してバッチ的に登録します。
add_cert.shというファイル名でスクリプトを保存します。
vim add_cert.sh
スクリプトの中身は以下の通りです。
#! /bin/bash
for i in $(ls /home/oracle/dbc/*cer)
do
orapki wallet add -wallet . -trusted_cert -cert $i -pwd SSL Wallet password
done
権限を付与して実行します。
chmod +x add_cert.sh
./add_cert.sh
念のため証明書が追加されたかウォレットの中身を確認します。
orapki wallet display -wallet .
sqlnet.oraに作成したウォレットを参照するよう設定を追記します。
vim $ORACLE_HOME/network/admin/sqlnet.ora
追記する内容は以下の通りです。
WALLET_LOCATION=
(SOURCE=(METHOD=FILE)
(METHOD_DATA=(DIRECTORY=/opt/oracle/dcs/commonstore/wallets/ssl)))
アクセス制御エントリ (ACE) の設定
DBから外部と通信するためには、DBに対してネットワーク許可設定が必要です。
それがアクセス制御エントリ (ACE) です。
まずはDBMS_CLOUDとDBMS_CLOUD_AIを所有するDBユーザC##CLOUD$SERVICEに対してACEを設定し、外部とのHTTPS接続を許可します。
今回はdbc_aces.sqlというファイル名で必要な構成変更をスクリプト化します。
cd /home/oracle/dbc
vim dbc_aces.sql
スクリプトの内容は以下の通りです。
マニュアルの例からほぼそのまま転用しています。
プロキシを経由する場合の追加設定は削除していますので、
もしプロキシ経由で外部と接続される場合は元のマニュアルの例をご参照ください。
@$ORACLE_HOME/rdbms/admin/sqlsessstart.sql
-- you must not change the owner of the functionality to avoid future issues
define clouduser=C##CLOUD$SERVICE
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE PROVIDED BY THE CUSTOMER-- - SSL Wallet directory
define sslwalletdir=/opt/oracle/dcs/commonstore/wallets/ssl
-- Create New ACL / ACE s
begin
-- Allow all hosts for HTTP/HTTP_PROXY
dbms_network_acl_admin.append_host_ace(
host =>'*',
lower_port => 443,
upper_port => 443,
ace => xs$ace_type(
privilege_list => xs$name_list('http', 'http_proxy'),
principal_name => upper('&clouduser'),
principal_type => xs_acl.ptype_db
)
);
-- Allow wallet access
dbms_network_acl_admin.append_wallet_ace(
wallet_path => 'file:&sslwalletdir',
ace => xs$ace_type(
privilege_list =>xs$name_list('use_client_certificates', 'use_passwords'),
principal_name => upper('&clouduser'),
principal_type => xs_acl.ptype_db));
end;
/
-- Setting SSL_WALLET database property
begin
if sys_context('userenv', 'con_name') = 'CDB$ROOT' then
execute immediate 'alter database property set ssl_wallet=''&sslwalletdir''';
end if;
end;
/
@$ORACLE_HOME/rdbms/admin/sqlsessend.sql
dbc_aces.sqlを実行してC##CLOUD$SERVICEのHTTPS外部接続を許可します。
$ sqlplus / as sysdba
SQL> @@/home/oracle/dbc/dbc_aces.sql
SSLウォレットとACEが正しく設定されているかテストします。
テスト用のスクリプトをdbc_test.sqlに保存します。
vim dbc_test.sql
スクリプトの内容は以下の通りです。
こちらもマニュアルの例をほぼそのまま転用しています。
your_passwordの箇所はご自分のパスワードを設定します。
define clouduser=C##CLOUD$SERVICE
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE PROVIDED BY THE CUSTOMER
-- - SSL Wallet directory and password
define sslwalletdir=/opt/oracle/dcs/commonstore/wallets/ssl
define sslwalletpwd=your_password
-- In environments w/ a proxy, you need to set the proxy in the verification code
-- define proxy_uri=<your proxy URI address>
-- create and run this procedure as owner of the ACLs, which is the future owner
-- of DBMS_CLOUD
CREATE OR REPLACE PROCEDURE &clouduser..GET_PAGE(url IN VARCHAR2) AS
request_context UTL_HTTP.REQUEST_CONTEXT_KEY;
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
data VARCHAR2(32767) default null;
err_num NUMBER default 0;
err_msg VARCHAR2(4000) default null;
BEGIN
-- Create a request context with its wallet and cookie table
request_context := UTL_HTTP.CREATE_REQUEST_CONTEXT(
wallet_path => 'file:&sslwalletdir',
wallet_password => '&sslwalletpwd');
-- Make a HTTP request using the private wallet and cookie
-- table in the request context
-- uncomment if proxy is required
-- UTL_HTTP.SET_PROXY('&proxy_uri', NULL);
req := UTL_HTTP.BEGIN_REQUEST(url => url,request_context => request_context);
resp := UTL_HTTP.GET_RESPONSE(req);
DBMS_OUTPUT.PUT_LINE('valid response');
EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 3800);
DBMS_OUTPUT.PUT_LINE('possibly raised PLSQL/SQL error: ' ||err_num||' - '||err_msg);
UTL_HTTP.END_RESPONSE(resp);
data := UTL_HTTP.GET_DETAILED_SQLERRM ;
IF data IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('possibly raised HTML error: ' ||data);
END IF;
END;
/
set serveroutput on
BEGIN
&clouduser..GET_PAGE('https://objectstorage.eu-frankfurt-1.oraclecloud.com');
END;
/
set serveroutput off
drop procedure &clouduser..GET_PAGE;
上記スクリプトを実行し、出力結果としてvalid responseと表示されれば正しく構成されています。
サンプルスキーマのインストール
SLECT AIで検索するサンプルスキーマをインストールします。
今回はSHスキーマを利用します。
SHスキーマのインストール方法は以下をご参照ください。
インストールできたらSHスキーマにACE設定と権限付与を行います。
ACE設定に必要な手順はスクリプト化して実行します。
今回はdbuser_aces.sqlというファイル名で保存します。
cd /home/oracle/dbc
vim dbuser_aces.sql
スクリプトの内容は以下の通りです。
こちらもマニュアルの例をほぼそのまま転用しています。
プロキシを経由する場合の手順だけ削除していますので、もしプロキシ経由で外部と接続される場合は元のマニュアルの例をご参照ください。
@$ORACLE_HOME/rdbms/admin/sqlsessstart.sql
-- target sample user
define clouduser=SH
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE PROVIDED BY THE CUSTOMER
-- - SSL Wallet directory
define sslwalletdir=/opt/oracle/dcs/commonstore/wallets/ssl
-- Create New ACL / ACEs
begin
-- Allow all hosts for HTTP/HTTP_PROXY
dbms_network_acl_admin.append_host_ace(
host =>'*',
lower_port => 443,
upper_port => 443,
ace => xs$ace_type(
privilege_list => xs$name_list('http', 'http_proxy'),
principal_name => upper('&clouduser'),
principal_type => xs_acl.ptype_db));
-- Allow wallet access
dbms_network_acl_admin.append_wallet_ace(
wallet_path => 'file:&sslwalletdir',
ace => xs$ace_type(
privilege_list =>xs$name_list('use_client_certificates', 'use_passwords'),
principal_name => upper('&clouduser'),
principal_type => xs_acl.ptype_db));
end;
/
@$ORACLE_HOME/rdbms/admin/sqlsessend.sql
SHスキーマをインストールしたPDB上で実行します。
sqlplus / as sysdba
alter session set container=freepdb1;
@dbuser_aces.sql
次にDB接続に必要なロール (CONNECT) やDBMS_CLOUD、DBMS_CLOUD_AIパッケージの利用権限を付与します。
GRANT CONNECT to SH;
GRANT EXECUTE on DBMS_CLOUD to SH;
GRANT EXECUTE on DBMS_CLOUD_AI to SH;
SELECT AIを利用するための設定
ここからの手順はAutonomous AI DatabaseでSELECT AIを使う場合と同様です。
まず生成AIモデル利用に必要な認証情報を資格証明オブジェクトとして作成します。
その後AIプロファイルを作成し、利用する生成AIモデルや参照するテーブルを指定します。
今回はOCI生成AIサービスが提供するCohereのcohere.command-r-plus-08-2024を利用します。
余談ですが、もしローカルにllama.cppやLM StudioでOpenAI API互換の生成AIモデルをデプロイされている場合、LLMも含め全てオンプレで実装できるものと思われます。
ここは未検証のため要確認です。
本題に戻りますが、まずOCIサービスの利用に必要な認証情報を資格証明オブジェクトとして作成します。
なおこれ以降の作業はSHユーザとして実行していきます。
各項目にはご自分の情報を入力してください。
BEGIN
DBMS_CLOUD.CREATE_CREDENTIAL(
credential_name => 'OCI_GENAI',
user_ocid => 'your user ocid',
tenancy_ocid => 'your tenancy ocid',
private_key => 'your user private key',
fingerprint => 'your fingerprint related to your user private key'
);
END;
/
上記の資格証明を利用したAIプロファイルを作成します。
参照するテーブルはSALESテーブルを指定しています。
またoci_compartment_idにはご自分の情報を入力してください。
BEGIN
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name =>'GENAI',
attributes =>'{
"provider" : "oci",
"region" : "ap-osaka-1",
"model" : "cohere.command-r-plus-08-2024",
"credential_name" : "GENAI_CRED",
"oci_compartment_id": "your compartment id",
"comments" : "TRUE",
"conversation" : "TRUE",
"object_list" : [
{"owner": "SH", "name": "SALES"}]
}'
);
END;
/
オンプレのSELECT AIを使ってみる
簡単な例ですが動作確認してみます。
SALES表のデータ件数を自然言語で聞いてみます。
まずはrunsqlです。
SELECT DBMS_CLOUD_AI.GENERATE(prompt => 'SALES表のデータ件数は?',
profile_name => 'GENAI',
action => 'runsql');
DBMS_CLOUD_AI.GENERATE(PROMPT=>'SALES表のデータ件数は?',PROFILE_NAME=>'GENAI',ACTION=>'RUNSQL')
__________________________________________________________________________________________
[
{"data_count":918843}
]
想定したデータが返ってきており、ちゃんと動作しているようです。
念のためshowsqlで生成されたSQLを確認します。
SELECT DBMS_CLOUD_AI.GENERATE(prompt => 'SALES表のデータ件数は?',
profile_name => 'GENAI',
action => 'showsql');
DBMS_CLOUD_AI.GENERATE(PROMPT=>'SALES表のデータ件数は?',PROFILE_NAME=>'GENAI',ACTION=>'SHOWSQL')
___________________________________________________________________________________________
SELECT COUNT(*) AS "data_count"
FROM "SH"."SALES"
生成されたSQLも想定された内容でした。
最後にnarrateで結果を自然言語で回答してもらいます。
SELECT DBMS_CLOUD_AI.GENERATE(prompt => 'SALES表のデータ件数は?',
profile_name => 'GENAI',
action => 'narrate');
DBMS_CLOUD_AI.GENERATE(PROMPT=>'SALES表のデータ件数は?',PROFILE_NAME=>'GENAI',ACTION=>'NARRATE')
___________________________________________________________________________________________
SH.SALES テーブルには 918,843 件のデータが含まれています。
こちらもちゃんと動作しました。
ちなみに参照する表や表内の各カラムにコメントを付与すれば、より曖昧な質問や複雑な質問でも精度高く回答できます。
いわゆるコンテキスト情報の付加になります。
コメント付与の具体的な方法は以下をご参照ください。
おわりに
これまでクラウド上のAutonomous AI Databaseでしか利用できなかったSELECT AIですが、オンプレ26aiでもRU23.7から利用できることが分かりました。
26aiにはRAG構成に使えるAI Vector Searchもあります。
オンプレに閉じた環境でも、AI Vector Searchによる非構造化データの活用、そしてSELECT AIによる既存の基幹データの活用が生成AIと組み合わせて可能になります。