この記事は JPOUG Advent Calendar 2025 21日目の記事です。
20日目は Noriyoshi Shinoda さんの記事『Oracle AI Database 26ai でサポート対象外となったセキュリティ関連機能』でした。
また本記事は Oracle Cloud Infrastructure Advent Calendar 2025 シリーズ3 21日目 の記事でもあります。
Oracle Autonomous AI Database (以下ADB) には生成AI、機械学習とAIに纏わる機能が色々あります。
そこでAI同士を組み合わせて何か出来ないかと考え、AI (生成AI) からAI (機械学習) を呼び出す処理を最近お気に入りの SELECT AI Agent で実装してみました。
シナリオは以下イメージです。
- とある工場に設置されたセンサーデータから、複数の機器に関するIoTデータを収集
- そのデータをもとに機器の異常検知用の機械学習モデルを構築
- 生成AIの外部ツールとして学習済みモデルを利用し、指定した機器の最後に異常検知した時刻を生成AIより回答
なお実体は Oracle Machine Lerning (以下OML) を使ったファンクションをツールとして定義し、それをSELECT AI Agent から呼び出す、というものです。
当初は SELECT AI から PREDICTION 関数を呼び出して出来ないか模索していたのですが、やり方が良くないのか実現できそうになかったため、堅実な SELECT AI Agent に切り替えました。
目次
- 検証環境
- 機械学習モデル構築用の訓練データ準備
- ADB作成
- DBユーザ作成
- 検証用データのロード
- AutoMLで機械学習モデルを構築
- SELECT AI Agent利用の事前準備
- SELECT AI Agentの実装
- 動作確認
検証環境
OCI TokyoリージョンのADB 26ai を利用しました。
またSELECT AI Agent で使うLLMは OpenAI の gpt-4o になります。
機械学習モデル構築用の訓練データ準備
機械学習モデルの構築はADBが兼ね備える AutoML 機能を使いますが、そのためには訓練データが必要です。
今回はKaggleにて公開されている、とある工場のIoTデータを使いました。
ADB作成
詳細は省略しますが、以下などを参考に作成します。
DBユーザ作成
検証用DBユーザを作成します。
ADBインスタンス詳細画面の「データベース・アクション」から「データベース・ユーザー」を選択します。
「ユーザの作成」を選択します。
必要情報を入力します。
特に今回は「OML」と「REST...およびWebアクセス」の有効化を忘れずに行います。
また以降の手順ですが、DBユーザ名は IOT を前提に進めていきます。
問題なければ「ユーザーの作成」を選択します。
以下の通りロールが付与されていればOKです。
検証用データのロード
Data Studioに先ほど作成した IOT ユーザでログインします。
「データのロード」から事前にダウンロードしたKaggleのIoTデータ (csv形式のファイル) をアップロードし、新規テーブルに読み込みます。
今回は元データ 10万行 を訓練データ 8万行 とテストデータ 2万行 に分割し、それぞれ別のテーブルへロードしました。
訓練データは SENSOR_DATA_TRAIN テーブル、テストデータは SENSOR_DATA_TEST テーブルへロードしています。
AutoMLで機械学習モデルを構築
お手軽に機械学習モデルを構築できるAutoMLを使っていきます。
複数のアルゴリズムで学習し、精度の良いモデルを自動提示してくれます。
以下資料によると特徴量に対する欠損値の処理や正規化なども自動で行ってくれるようで、大変ありがたいです。
OMLではモデルの作成時に、データベース内の自動データ準備(ADP)を利用して、欠落値、データのビン化、データの正規化、データのスケーリングが処理されます。
IOT ユーザで「データベース・アクション」にログインします。
「機械学習」を選び、「開く」ボタンを選択します。
OMLのトップ画面から「AutoML」を選択します。
AutoML実験画面で「作成」を選択します。
以下の通り読み込んだ検証用データの選択など、必要な項目を入力します。
なお説明変数と目的変数は以下の通り設定しています。
- 目的変数
- ANOMALY_FLAG
- 説明変数
- ENERGY_CONSUMPTION
- HUMIDITY
- MACHINE_ID
- MACHINE_STATUS
- TEMPERATURE
- VIBRATION
- PRESSURE
右上の「開始」から今回は「より速い結果」を選択しました。
しばらく経つと以下のように、自動データ準備や複数アルゴリズムによる学習が完了します。
この中から本検証では「ディシジョン・ツリー」を使うことにしました。
後で利用しやすいように、ディシジョン・ツリーを平易なモデル名に変更しておきます。
SELECT AI Agent利用の事前準備
ここから「データベース・アクション」の「SQL Developer Web」上で作業していきます。
なおSELECT AI Agentについては以前に投稿した以下記事もご参考になります。
まずは ADMIN ユーザで IOT ユーザに必要な権限を付与します。
GRANT EXECUTE ON DBMS_CLOUD TO IOT;
GRANT EXECUTE ON DBMS_CLOUD_AI TO IOT;
GRANT EXECUTE on DBMS_CLOUD_AI_AGENT to IOT;
GRANT EXECUTE on DBMS_CLOUD_PIPELINE to IOT;
OpenAIのサービスを利用するため、ACL許可を設定します。
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => 'api.openai.com',
ace => xs$ace_type(privilege_list => xs$name_list('http'),
principal_name => 'IOT',
principal_type => xs_acl.ptype_db)
);
END;
/
OpenAIのサービスを使うために資格証明を作成します。
BEGIN
DBMS_CLOUD.CREATE_CREDENTIAL(
credential_name => 'OPENAI_CRED',
username => 'OPENAI',
password => 'your api key'
);
END;
/
gpt-4o を使うためにAIプロファイルを作成します。
BEGIN
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name =>'OPENAI',
attributes =>'{
"provider" : "openai",
"model" : "gpt-4o",
"credential_name" : "OPENAI_CRED",
"comments" : "TRUE",
"conversation" : "TRUE"
}'
);
END;
/
SELECT AI Agentの実装
まずAgentを作成します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_AGENT(
agent_name => 'ANOMALY_DETECTOR',
attributes => '{"profile_name": "OPENAI",
"role": "あなたは保存されたセンサーデータをもとに異常値判定を行い、異常値が見られた最新の時間を回答する役割を担っています。"
}'
);
END;
/
異常値かどうかの予測をもとに、最後に異常が発生したと考えられる時刻を返すファンクションを定義します。
本ファンクションにおいて、先ほどAutoMLで学習させたディシジョン・ツリー IOT_DTREE を使っています。
異常値かどうかの予測は PREDICTION 関数で行っています。
また予測に使うデータはテスト用に用意した SENSOR_DATA_TEST テーブルを使います。
CREATE OR REPLACE FUNCTION predict_latest_abnormal(mid IN NUMBER) RETURN DATE IS
l_time DATE;
BEGIN
SELECT timestamp into l_time
FROM sensor_data_test
WHERE machine_id = mid AND PREDICTION(IOT_DTREE USING sensor_data_test.*) = 1
ORDER BY timestamp DESC
FETCH FIRST 1 ROWS ONLY;
RETURN l_time;
END;
/
作成したファンクションを呼び出すためにTOOLを作成して紐づけます。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TOOL(
tool_name => 'ANOMALY_DETECTOR_FOR_LATEST',
attributes => '{"instruction": "指定されたmachine_idに関して、異常値が見られた最新の時間を確認する際にこのツールを使います。", "function": "predict_latest_abnormal"}'
);
END;
/
TOOLを呼び出すためのTASKを作成します。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TASK(
task_name => 'DETECT_ANOMALY_TIME',
attributes =>'{"instruction": "指定されたmachine_idに関して、異常値が見られた最新の時間の確認を支援してください。ユーザからの質問: {query}' || '異常値判定を行う際は ANOMALY_DETECTOR_FOR_LATEST ツールを利用してください。",
"tools": ["ANOMALY_DETECTOR_FOR_LATEST"],
"enable_human_tool" : "False"
}'
);
END;
/
最後にAgent TEAMを作成し、これまでに作成した各コンポーネントを実行可能な形にします。
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TEAM(
team_name => 'ANOMALY_DETECT',
attributes => '{"agents": [{"name":"ANOMALY_DETECTOR","task":"DETECT_ANOMALY_TIME"}],
"process": "sequential"
}');
END;
/
動作確認
それではAgent TEAM ANOMALY_DETECT を利用し、指定した機器において、異常値と思われるデータが最後に追加された時刻を聞いてみます。
DECLARE
l_conversation_id VARCHAR2(50);
l_final_answer VARCHAR2(4000);
BEGIN
SELECT DBMS_CLOUD_AI.CREATE_CONVERSATION INTO l_conversation_id;
l_final_answer := DBMS_CLOUD_AI_AGENT.RUN_TEAM(
team_name => 'ANOMALY_DETECT',
user_prompt => 'machine_idが17の機器において、センサーデータに異常値が見られた最新の時間を教えてください。',
params => '{"conversation_id": "' || l_conversation_id || '"}'
);
DBMS_OUTPUT.PUT_LINE(l_final_answer);
END;
/
以下が実行結果です。
元データをエクセルで確認すると、確かに合っているようです。
(ANOMALY_FLAG が 1 (異常値) のデータを timestamp の降順に表示)
別の machine_id でも試しましたが、想定通り動いてくれました。
元データの確認結果は以下の通りです。
ご参考までにTASK、TOOLの実行履歴は以下のようになっていました。
SELECT * FROM USER_AI_AGENT_TOOL_HISTORY WHERE TRUNC(START_DATE) = TRUNC(SYSDATE);
検証内容は以上です。
SELECT AI Agent を使えば様々なワークフローを自律化できそうですね。

















