以前の記事でオンプレ版Oracle AI DB 26aiでSELECT AIを使う手順についてまとめました。
今回はこちらの記事にコメントした下記構成を実際に試しました。
もしローカルにllama.cppやLM StudioでOpenAI API互換の生成AIモデルをデプロイされている場合、LLMも含め全てオンプレで実装できるものと思われます。
ここは未検証のため要確認です。
ローカルに立てたPrivate LLMでSELECT AIを使えれば、インターネット経由で外部の生成AIサービスを使う必要がなくなります。
これにより、企業内にあるような構造化された機密データを、SELECT AIを通してデータ活用しやすくなるのではないかと思います。
ちなみに動作確認はSELECT AIに加え、ついでにSELECT AI with RAGも実施しました。
SELECT AI with RAGで使うEmbeddingは外部サービスを使わず、ONNXによるIn-Database Embeddingで対応しました。
ただしSELECT AI with RAGはObject Storage連携が必要なため、その仕組だけ外部サービスに依存しています。。
目次
検証環境
LLM用サーバ (OCI Compute)
- OS: Oracle Linux 8
- CPU: VM.Standard.E6.Flex 3 OCPU
- Memory: 33 GB
- Storage: 100 GB
DBサーバ (OCI Compute)
- OS: Oracle Linux 8
- CPU: VM.Standard.E5.Flex 1 OCPU
- Memory: 32 GB
- Storage: 150 GB
DBサーバには事前に26ai EE (Linux x86-64) をインストールしておきます。
手順は以下記事がご参考になります。
(RAC向け手順ですが、GI関連の手順をSkipすればシングル構成で構築できます。)
またSELECT AI with RAGをIn-Database Embeddingで試したい場合、以下記事の対象手順も実施しておきます。
- OML4Pyインストール (2.1.1)
- ONNXエクスポート
- DB事前準備
- ONNXインポート
- In-Memory Sharingの有効化
LLM用サーバ向け作業
セキュリティ設定
SELinuxを無効化しておきます。
sudo vim /etc/selinux/config
# 以下の通り編集
SELINUX=disabled
Private LLMに対するHTTPリクエストを許可するためFWを設定変更します。
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
リバースプロキシ設定
Private LLMはLlama.cppを使ってTCP 8080番ポートで稼働させます。
HTTPリクエストを80番で受けて8080番へポート転送するため、nginxによるリバースプロキシを構成します。
まずnginxをインストールします。
sudo dnf install nginx -y
nginxのconfigを編集し、ポート転送を設定します。
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
sudo vim /etc/nginx/nginx.conf
# 既存の server ブロックをコメントアウト
# 代わりに以下を追記
server {
listen 80;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
nginxのシンタックスが合っているかCheckします。
sudo nginx -t
Llama.cpp構成
Private LLMを動かすにあたり、今回はLlama.cppを使います。
まずはLlama.cppをインストールします。
wget https://github.com/ggml-org/llama.cpp/archive/refs/heads/master.zip
unzip master.zip
cd llama.cpp-master
sudo dnf install cmake gcc-c++ make -y
sudo dnf install libcurl-devel -y
# Llama.cppのビルドにはGCC 9以上が必要なため、追加インストール
sudo dnf install -y gcc-toolset-9
# このシェルだけ一時的にGCC 9を有効化
scl enable gcc-toolset-9 bash
# GCCバージョン確認
gcc --version
g++ --version
which gcc
which g++
# Llama.cppビルド
mkdir build
cd build
cmake ..
cmake --build .
ビルドが無事に終わりましたら、Private LLMとして使う推論モデルのGGUFファイルを配置します。
今回は以下にて配布されている gemma-3-12b-it-Q4_K_M.gguf を使いました。
GGUFをダウンロードできたらLLM用サーバにアップロードし、適切なフォルダに配置します。
今回は /home/opc/models に配置しました。
cd
mkdir models
mv /tmp/gemma-3-12b-it-Q4_K_M.gguf ./models/
簡単なプロンプトで動作確認します。
cd ~/llama.cpp-master
./build/bin/llama-cli -m ../models/gemma-3-12b-it-Q4_K_M.gguf -p "Hello world"
Llama.cppをサーバとして起動します。
nohup ./build/bin/llama-server -m ../models/gemma-3-12b-it-Q4_K_M.gguf --port 8080 > llama-server.log 2>&1 &
HTTPリクエストを投げて簡単なプロンプトで動作確認します。
<your server FQDN> はご自身のサーバのFQDNで置き換えてください。
curl -X POST http://<your server FQDN>/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gemma-3-12b-it-Q4_K_M.gguf",
"messages": [
{"role": "user", "content": "こんにちは"}
]
}'
DBサーバ向け作業
サンプルスキーマのインストール
SELECT AIで問い合わせるデータを準備するため、以下を参考にサンプルスキーマをインストールします。
SELECT AIを利用するための設定
SELECT AI関連機能を使うにはインストール作業が必要なため、以下記事の該当手順を実行します。
ただし「アクセス制御エントリ (ACE) の設定」は異なる対応が必要なため、それ以外を実施します。
DBMS_CLOUD、DBMS_CLOUD_AI パッケージの導入と設定
「アクセス制御エントリ (ACE) の設定」については以下を実行します。
まず以下を 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=/u01/app/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
)
);
dbms_network_acl_admin.append_host_ace(
host =>'*',
lower_port => 80,
upper_port => 80,
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 を sys ユーザで CDB$ROOT から実行します。
$ sqlplus / as sysdba
SQL> @dbc_aces.sql
さらに上記スクリプトをPDB用にコピーします。
cp -p dbc_aces.sql dbc_aces_pdb.sql
dbc_aces_pdb.sql の clouduser をPDB上の検証用スキーマ名に置き換えます。
vim dbc_aces_pdb.sql
sys ユーザで該当PDBにログインして実行します。
$ sqlplus / as sysdba
SQL> alter session set container=<PDB name>;
SQL> @dbc_aces_pdb.sql
本設定により80番ポート宛のHTTPリクエストが使えるようになり、Private LLMとの連携が可能となります。
AIプロファイル作成 (SELECT AI)
つづいてAIプロファイルを作成します。
今回はAPIキーが不要なPrivate LLMを使うため、資格証明の作成や provider の指定は不要です。
代わりに provider_endpoint にてPrivate LLMが稼働するサーバのFQDNを指定します。
そのため <your server FQDN> はご自身のLLM用サーバのFQDNに置き換えてください。
また model はLlama.cppの場合GGUFファイル名となります。
EXEC DBMS_CLOUD_AI.drop_profile(profile_name => 'LLAMACPP', force => true);
BEGIN
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name =>'LLAMACPP',
attributes =>'{
"provider_endpoint": "<your server FQDN>",
"model" : "gemma-3-12b-it-Q4_K_M.gguf",
"comments" : "TRUE",
"conversation" : "TRUE",
"object_list_mode" : "all"
}'
);
END;
/
動作確認 (SELECT AI)
Private LLM+オンプレ版SELECT AIの動作確認をしてみます。
SQL> exec DBMS_CLOUD_AI.SET_PROFILE('LLAMACPP');
SQL> select ai SHスキーマが持つSALES表のデータ件数は?;
record_count
------------
918843
SQL> select ai showsql SHスキーマが持つSALES表のデータ件数は?;
RESPONSE
---------------------------------------------------
SELECT COUNT(*) AS "record_count"
FROM "SH"."SALES"
SQL> select ai explainsql SHスキーマが持つSALES表のデータ件数は?;
RESPONSE
--------------------------------------------------------------------------------
```sql
SELECT COUNT(*) AS record_count
FROM "SH"."SALES";
\```
**Explanation:**
* **`SELECT COUNT(*)`**: This part of the query counts all rows in the specifi
ed table. `COUNT(*)` is an aggregate function that returns the number of rows.
* **`AS record_count`**: This assigns an alias "record\_count" to the result o
f the `COUNT(*)` function. This makes the output column more descriptive.
RESPONSE
--------------------------------------------------------------------------------
* **`FROM "SH"."SALES"`**: This specifies the table from which to retrieve the
data.
* `"SH"`: This is the schema name. It's enclosed in double quotes becaus
e schema names are case-sensitive in Oracle.
* `"SALES"`: This is the table name. It's enclosed in double quotes becaus
e table names are case-sensitive in Oracle.
This query will return a single row with a single column named "record\_count" c
ontaining the total number of rows in the "SH"."SALES" table.
explainsql はなぜか回答が英語になりましたが、ちゃんと使えているようです。
SELECT AI with RAGを利用するための設定
もしSELECT AI with RAGも試したい場合、以下手順を実施します。
バケットにはRAGで使うファイルをアップロードしておきます。
資格証明の作成
OCI Object Storageを使うための資格証明を作成します。
BEGIN
DBMS_CLOUD.CREATE_CREDENTIAL(
credential_name => 'OCI_CRED',
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プロファイル作成 (SELECT AI with RAG)
ONNXを使ったIn-Database Embedding用のAIプロファイルを作成します。
BEGIN
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name => 'EMBEDDING_PROFILE',
attributes => '{"provider" : "database",
"embedding_model": "DOC_MODEL"}'
);
END;
/
ベクトル索引を作ります。
location にはご自身のObject Storage URIを記入します。
BEGIN
DBMS_CLOUD_AI.CREATE_VECTOR_INDEX(
index_name => 'MY_INDEX',
attributes => '{"vector_db_provider": "oracle",
"location": "your oci object storage uri",
"object_storage_credential_name": "OCI_CRED",
"profile_name": "EMBEDDING_PROFILE",
"vector_dimension": 1024,
"vector_distance_metric": "cosine",
"chunk_size":500,
"chunk_overlap":200,
"refresh_rate":1
}');
END;
/
SELECT AI with RAGのAIプロファイルを作成します。
こちらも以下についてはSELECT AIと同様です。
今回はAPIキーが不要なPrivate LLMを使うため、資格証明の作成や
providerの指定は不要です。
代わりにprovider_endpointにてPrivate LLMが稼働するサーバのFQDNを指定します。
そのため<your server FQDN>はご自身のLLM用サーバのFQDNに置き換えてください。
またmodelはLlama.cppの場合GGUFファイル名となります。
EXEC DBMS_CLOUD_AI.drop_profile(profile_name => 'LLAMACPP_RAG', force => true);
BEGIN
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name =>'LLAMACPP_RAG',
attributes =>'{
"provider_endpoint": "<your server FQDN>",
"model" : "gemma-3-12b-it-Q4_K_M.gguf",
"conversation" : "TRUE",
"vector_index_name": "MY_INDEX",
"embedding_model":"database: DOC_MODEL"
}'
);
END;
/
動作確認 (SELECT AI with RAG)
Private LLM+オンプレ版SELECT AI with RAGの動作確認をしてみます。
RAGで参照するファイルは架空の製品のロードマップです。
SQL> exec DBMS_CLOUD_AI.SET_PROFILE('LLAMACPP_RAG');
SQL> SET ECHO ON
SQL> SET FEEDBACK 1
SQL> SET NUMWIDTH 10
SQL> SET LINESIZE 80
SQL> SET TRIMSPOOL ON
SQL> SET TAB OFF
SQL> SET PAGESIZE 10000
SQL> SET LONG 10000
SQL> SELECT AI narrate スマートヘルメットのロードマップは?;
RESPONSE
--------------------------------------------------------------------------------
2024年第1四半期:ヘルメットの音声認識機能を改善します。より自然で正確な音声入力
と出力を実現するために、AIやクラウドの技術を活用します。また、ヘルメットの音質も
向上させます。ノイズキャンセリングやサラウンドサウンドなどの機能を追加します。
2024年第2四半期:ヘルメットのHUD機能を強化します。より高解像度や高コントラストの
ディスプレイを採用します。また、HUDのカスタマイズも可能にします。乗り手が表示し
たい情報やレイアウトを自由に設定できるようにします。
2024年第3四半期:ヘルメットのセキュリティ機能を向上させます。ヘルメットの生体認
証や暗証番号などの機能を導入します。ヘルメットの盗難や紛失を防ぐとともに、個人情
報やデータの保護にも貢献します。
2024年第4四半期:ヘルメットのエコモード機能を開発します。ヘルメットの太陽光発電
や省電力などの機能を備えます。ヘルメットのバッテリーの持ちを延ばすとともに、環境
にやさしいエネルギーの利用にも配慮します。
Sources:
- product_roadmap.pdf (https://xxxxx.objectstorage.ap-osaka-1.oci.custome
r-oci.com/n/xxxxx/b/docs/o/product_roadmap.pdf)
1行が選択されました。
ちゃんとPrivate LLMと連携して使えていますね。
以上、ローカルに構築したPrivate LLM+オンプレ版26ai SELECT AIの動作確認でした。