先の記事「APEX 26.1のAIエージェントでHTMLキャンバスに描画した車を動かす」にて、APEX 26.1のAIエージェントを使ってブラウザを操作するサンプル・アプリを作ってみました。本記事では、AIエージェントを使ってデータベースを操作するエージェントを作ってみます。
以下、プロンプトで従業員の給与を更新します。データ・ソースとしてはサンプル・データセットのEMP/DEPTの含まれる表EMPを使用します。
作成するAPEXアプリケーションは以下のように動作します。LLMにmacOSのLM Studioで実行しているgoogle/gemma-4-31b-qatを使用しているため、処理に時間がかかっています(動作も若干安定しないです)。
ページ・アイテムP1_ENAMEにKINGが選択されているときに限り、AIエージェントのツールにupdate_salaryが含まれるようにしています。KING以外のときは「更新できません。」と返されます。
https://github.com/ujnak/APEXlang-exports/tree/main/salary-management-agent
AIアシスタントは、ページのロード時に実行する動的アクションで初期化しています。
以下より、作成したAPEXアプリケーションについて紹介します。主にAIエージェントの紹介になります。
ホーム・ページに、AIエージェントに含まれるツールupdate_salaryのサーバー側の条件に使用されるページ・アイテムP1_ENAMEが作成されています。
選択リストのソースとなるSQL問合せとして、以下を記述しています。
select ename d, ename r from emp order by 1
選択時のページ・アクションとして値のリダイレクトと設定を選び、セッション・ステートのストレージにセッションごと(永続)を選んでいます。そのため、ここで選択した値をAIエージェントのコード中で、バインド変数:P1_ENAMEから参照できます。
従業員一覧はクラシック・レポートで作成し、ソースの表名にEMPを設定しています。
給与の更新後にJavaScriptの実行によりレポートをリフレッシュするため、詳細のHTML DOM IDにEMPを設定しています。
AIエージェントへのプロンプトを入力するリージョンとして、静的コンテンツのリージョンを作成し、ソースのHTMLコードに以下を記述しています。
<div id="chat"></div>
作成したAIエージェントについて説明します。
AIエージェントの名前はSalary Management Agentとしています。生成AIのサービスとしてLM Studio Gemma4を設定しています。これはワークスペースに生成AIサービスとして作成済みです。
システム・プロンプトとして以下を記述しています。
「従業員の給与を更新します。
利用できるツールにupdate_salaryが含まれていない場合は、給与の更新手段がありません。その場合は、更新できません、と返します。」
4つのツールを作成しています。
システム・プロンプト拡張としてinject_schema_informationを作成しています。
このツールによって、システム・プロンプトに表EMPとDEPTの定義情報を追記しています。
実行ポイントがシステム・プロンプト拡張のツールをツールと呼ぶと、LLMのツール呼び出しに含まれるツール定義と混同しそうです。実行ポイントがオンデマンドのツールのみが、いわゆるLLMが扱うツールになります。
タイプにデータの取得を選んでいます。データの取得の処理は、データベース・サーバー側で実行されます。サーバー側の処理は、設定のタイプにてSQL問合せ、ファンクション本体、静的値の3つから選べます。
識別のタイプで、クライアント側のコードを実行、サーバー側のコードを実行、データの取得が選べるように見えますが、実行ポイントがシステム・プロンプト拡張の場合、データの取得はサーバー側のコードを実行を含んでいるため、タイプにサーバー側のコードを実行は選べません。選ぶと実行ポイントがオンデマンドに変わります。
設定の説明に「従業員給与を保持するスキーマ情報。」と記述します。この文章もシステム・プロンプトに追記されます。タイプにファンクション本体を選択します。
言語にPL/SQLを選び、CLOBを返すファンクション本体として以下を記述します。
declare
l_text clob;
begin
l_text := apex_db_dictionary.get_table_info(
p_table_names => 'EMP, DEPT' );
return l_text;
end;
以上で、表EMP/DEPTのメタデータが、つねにシステム・プロンプトに追記されるようになりました。
説明に「従業員名から従業員番号を取得します。」と記述しています。この説明を元に、LLMはツールを選択します。
パラメータとしてENAMEを追加しています。説明は従業員名、データ型はVARCHAR2、必須ははいです。
設定の言語にPL/SQLを選択し、PL/SQLコードとして以下を記述します。
declare
l_empno emp.empno%type;
l_response clob;
begin
select empno into l_empno from emp where ename = :ENAME;
l_response := apex_string.format('empno %s found for ename %s', l_empno, :ENAME);
apex_ai.set_tool_result( p_result => l_response );
exception
when no_data_found then
l_response := apex_string.format('No empno found for %s, perhapse the employee with the name does not exist.', :EMPNO);
apex_ai.set_tool_result( p_result => l_response );
end;
従業員一覧のレポートをリフレッシュするツールをrefresh_reportとして作成しています。タイプはクライアント側のコードを実行、実行ポイントはオンデマンドです。
ツールの説明として「従業員一覧のレポートをリフレッシュします。」を記述します。
設定のコードに以下の1行を記述します。
apex.region("EMP").refresh();
本記事の主題である、従業員の給与を更新するツールをupdate_salaryとして作成しています。
タイプはサーバー側のコードを実行です。実行ポイントは必ずオンデマンドになります。
ツールの説明として。以下を記述します。
「指定した従業員番号の従業員の給与を更新します。
更新後はツールrefresh_reportを呼び出して、レポートの表示を更新します。」
パラメータとしてEMPNOとSALを追加します。
EMPNOの説明は従業員番号、データ型はNUMBER、必須ははいです。SALの説明は給与、データ型はNUMBER、必須ははいです。
設定の言語にPL/SQLを選択し、PL/SQLコードとして以下を記述します。
declare
begin
update emp set sal = :SAL where empno = :EMPNO;
end;
ツールupdate_salaryについては、以下の条件も設定します。
User ApprovalのRequire Confirmationをオンにします。Confirmation Titleを給与の更新とし、Confirmation Messageに以下を記述します。
「従業員&EMPNO.の給与を&SAL.に更新します。」
LLMがツールupdate_salaryを実行するようにレスポンスを返したときに、以下のようにユーザーに確認を求めるダイアログが開きます。
OKをクリックすると、ツールupdate_salaryが実行されます。OKや取消といったラベルは、Approve LabelやCancel Labelを設定して変更できます。
通知のメッセージに「給与を更新しました。」と記述します。タイプに成功を選択します。
上記のように設定した通知は、以下のように表示されます。通知の設定の有無に関わらず、LLMからのレスポンスも表示されるようです。
サーバー側の条件として、タイプに式、言語にPL/SQL、式1に以下を記述しています。
:P1_ENAME = 'KING'
上記の条件により、ツールupdate_salaryはページ・アイテムP1_ENAMEにKINGが設定されているときに限り、LLMに送信するツール定義に含まれます。それ以外の従業員はツールupdate_salaryがツールに含まれていないため、給与を更新するようにプロンプトを送信しても、システム・プロンプトに設定しているように「更新できません。」と返されます。
今回作成したAPEXアプリケーションの説明は以上になります。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完

















































