2025年5月8日木曜日

Oracle LiveLabsのワークショップをインブラウザ翻訳を使って日本語に翻訳して作業する

少し前(2025年4月2日)になりますが、Oracle LiveLabsのワークショップのインストラクションでインブラウザ翻訳ができるようになりました。

簡単なOracle APEXのワークショップを翻訳した手順に従って実施してみます。Converting your Spreadsheet into a Cloud App using Oracle APEXを取り上げます。

このインストラクションはSandboxで実行できます。せっかくなのでSandboxも取得してみます。

画面右上のStartをクリックし、Run on LiveLabs Sandboxを選択します。Sandboxを作成するにはOracle Accountでサインインする必要があります。


タイムゾーンを設定し、Start Workshop Nowオンにします。Submit Reservationをクリックし、Sandboxをリクエストします。


作成されたSandboxは左上のアカウント・メニューのMy Reservationsから参照できます。

Launch Workshopをクリックします。


ワークショップの手順のページが開きます。左上にSandboxへのログイン情報を参照するリンクView Login Infoがあります。これをクリックします。


Sandboxへのサインインに使用するUsernamePasswordを控えておきます。また、ワークショップで使用するAutonomous Databaseは、ここに記載されているCompartmentに作成するため、このCompartmentも控えておきます。ここで表示されているパスワードは初回のサイン・イン後に変更を求められます。

Launch OCIをクリックし、Oracle Cloudのコンソールへサインインします。


Oracle Cloudのコンソールへのサインインの画面が開きます。テナンシなどは変更不要なので、へ進みます。


Sandbox作成時に与えられたユーザー名パスワードを入力し、サイン・インをクリックします。


 初期パスワードの変更を求められます。新規パスワードを設定し、パスワードのリセットをクリックします。なぜかパスワードのリセットするページが表示されず、真っ白なページのままだったのでブラウザのURLの入力フィールドにカーソルを当て、Enterを入力しました。


以上でSandboxの環境にサインインできます。


APEXのワークショップではOCIのコンソールはほぼ使用しませんが、言語とタイムゾーンだけは日本に合わせます。

左上のユーザーのメニューを開き、Languageの選択を開きます。


Select a language日本語を選択し、Saveします。


タイムゾーンを設定するために、プロファイルのユーザー名またはユーザー設定を開きます。


マイ・プロファイルの編集をクリックします。


ユーザー・プリファレンスタイム・ゾーン東京を設定し、マイ・プロファイルを更新します。


以上で最低限のプロファイルの設定は完了です。

ワークショップで使用するAutonomous Databaseを作成します。

メニューからAutonomous Databaseを開きます。


Autonomous Databaseの作成をクリックします。


Autonomous Database Serverlessの作成画面が開きます。

表示名データベース名の設定は任意です。Sandboxとして与えられたコンパートメントを設定して、ワークロード・タイプトランザクション処理データベース・バージョンの選択23aiを選びます。自動スケーリングの計算チェックは外します。今回のワークショップであれば、ワークロード・タイプがAPEX、データベースは19cでも作業は同様に実施できるでしょう。


管理者資格証明のパスワードを設定し、作成をクリックします。


以上でAutonomous Databaseのプロビジョニングが開始し、数分待つと利用可能になります。

Autonomous Databaseの作成を確認した後、開発者サービスAPEXインスタンスを開きます。


作成したAutonomous Databaseの3点メニューを開き、APEXの起動を実行します。


APEXの管理サービスへのサインイン画面が開きます。Autonomous Database作成時に設定した管理者ユーザーADMINのパスワードを入力し、管理にサインインをクリックします。


初回なのでAPEXのワークスペースがまだ作成されていません。ワークスペースの作成をクリックします。


スキーマも作成されていないので、新規のスキーマを選択します。


ワークスペースとワークスペースの管理者ユーザーを作成します。以下ではワークスペース名WORKSHOPワークスペース・ユーザー名WORKSHOPとしています。ワークスペースに紐づくスキーマとしてWKSP_WORKSHOPがデータベースに作成されます。データベース・ユーザーとしてWORKSHOPも作成されます。こちらはワークスペースの管理者ユーザーになります。

以上でワークスペースの作成をクリックします。


ワークスペースWORKSHOPが作成されます。画面上部に表示されているリンクをクリックして、ワークスペースのサインイン画面を開きます。


ワークスペースWORKSHOPにユーザーWORKSHOPでサインインします。ワークスペース作成時に設定したパスワードを入力します。

サインインをクリックします。


ワークスペースWORKSHOPにサインインできました。これから、APEXを使ったアプリケーション開発作業を始めることができます。


My ReservationsLaunch Workshopを開くと、インストラクションと共にSandboxを利用できる残り時間が表示されます。


今までの作業はGet Startedに当たります。ワークショップはLab1より始めます。Lab 1のインストラクションを開き、ページ上で右クリックをしコンテキスト・メニューを表示します。

インブラウザ翻訳ができるようになったので、メニューに日本語に翻訳が含まれます。これを実行します。


ページが日本語に翻訳されます。Chrome、Microsoft Edge、Apple Safariで確認しましたが、どのブラウザもインブラウザ翻訳を実行できました。ブラウザ毎に翻訳に使用するエンジンは異なるため(ChromeはGoogle翻訳、EdgeはBing翻訳、AppleはAppleの翻訳)、翻訳の精度も異なります。


後は手順に従ってワークショップを進めます。

作業を進めていく上で気がついたことを列記します。

日本語に翻訳されたボタンすべてのタスクを展開は、展開するためにクリックを2回行う必要があります。


一回目のクリックで表示がExpand All Tasksに代わります。


続くクリックで、タスクが展開されます。


スクリーンショットは英語のままなので、インストラクションの指示、スクリーンショット、実際の作業画面に違いがあります。

例えば以下の画面は翻訳されたインストラクションでは「新しいアプリの作成」となっています。スクリーンショットは「Create a New App」、実際の画面は「新規アプリケーションの作成」です。この違いは翻訳されたインストラクションのすべてで発生しますが、インストラクションでの翻訳された指示と、実際に操作する画面の記述はかなり近く、思ったよりもストレスを感じずに作業を進めることができました。


ページ名などに翻訳された名前を入力すべきかどうかは迷います。例えば翻訳されたインストラクションでは、ページ名に「ニューヨーク市高校検索」およびニューヨーク市高校レポート」を設定するように指示されています。このページ名は後の作業では「NYC Highschool Search」、「NYC Highschool Report」として、英語のまま参照されています。

ページ・アイテム名のような翻訳されると明らかに問題があるものを除いて、翻訳されたインストラクションに従って日本語で入力する方が作業を進めやすいでしょう。


翻訳されたインストラクションでは、NYC Highschool Searchをクリックするように指示されています。


Google翻訳ではShow Chartが「グラフの表示」と訳されていました。実際の画面ではチャートの表示です。このような軽微な翻訳の違いは多々あります。


「縮小可能」、「最初は縮小」が「折りたたみ可能」、「最初は折りたたみ可能」と翻訳されていました。これも翻訳の違いです。


非表示列の選択では、インストラクションでは列名が翻訳され(ダブン、経度、緯度、などとなっている)ているため、かなり分かりにくいです。しかし、実際のアプリケーションも列名は英語のままなので、スクリーンショットから作業内容を確認できます。


計算(インストラクションでは「コンピューティング」となっていました)の列ラベルに「応募者数と座席数の比率」を設定するよう指示されていますが、インストラクションでは後から「Application to Seat Ratio」が列として追加されたと記述されています。同じ列を指しています。列ラベルに日本語を設定した方が、後の作業は進めやすかったです。


翻訳されたインストラクションでは、Borough自治区価値ファンクション関数向きオリエンテーション水平となっていました。少し翻訳の違いにストレスがあった箇所です。


ソート(インストラクションでは並び替え)も列名が翻訳されていることに気が付く必要がありました。


Lab 3、タスク3の6のインストラクションは以下のように翻訳されていて、ページ・アイテム名を推測するのに時間がかかりました。


ブレッドクラム
がインストラクションでは「パンくず」と翻訳されています。翻訳としては正しいのですが、知らないと何のことか分からないかもしれません。


全般にAPEXのリージョン地域と訳されていることがあります。Lab 4はマップ・リージョンを扱っているため、地域が地図上の地域のことかと勘違いしそうになります。

Lab 4のタスク2の3でも列名が翻訳されています。このような場合はスクリーンショットを参照します。


Lab 4のタスク3の3で、Tooltipがツールチップではなくツールヒントと訳されていました。微妙な翻訳の違いですが、ツールチップと気がつくまで少々時間がかかりました。これもスクリーンショットを確認するとTooltipだと分かります。

他でもそうなのですが、インストラクションに埋め込まれているコードについては翻訳の対象外になっているようです。そのため、変に翻訳されてエラーが発生するといったことは起こりません。


Lab 4のタスク3の8では、インストラクションでは行の割り当ての下(実際は行割当て)のこのレイヤーの値と翻訳されています。SELECT文の列PIN_COLORの返す値なので、ここは翻訳せずにredと入力する必要があります。黄はyellow、緑はgreenです。

インストラクションに埋め込まれたコードは翻訳されませんが、それを参照している設定値が翻訳されていることがあり、注意が必要です。


LiveLabsのワークショップのインストラクションを、インブラウザ翻訳で翻訳した手順に沿って作業を行った際に気がついた点は以上になります。

気を付ける点はありますが、慣れれば英語を読んで作業するより理解が早そうだと感じました。

今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

チャートのY軸のラベルに任意のフォーマットを適用する

バー・チャートのY軸のラベルに任意のフォーマットを適用します。以下のように主要目盛が300K毎に表示されているチャートで、ラベルを300K、600K、900K、そして1Mを超えると1.2M、1.5Mと略記記号を変えます。


確認に使用しているチャート・リージョンのソースSQL問合せとして、以下を設定しています。
SELECT 1000 + (LEVEL - 1) * 80000 AS val, level l
FROM dual
CONNECT BY 1000 + (LEVEL - 1) * 80000 <= 2000000;

チャートのシリーズの列のマッピングとして、ラベルLVALを割り当てています。


Y軸のラベルのフォーマットですが、主に書式および書式スケールで決定されます。


書式が- 選択 -(つまり無指定)で書式スケール自動とすると、Y軸のラベルは以下のように表示されます。APEXアプリケーションの言語が日本語の場合、30.0万、60.0万、...のように単位が万になっています。


APEXアプリケーションのアプリケーション言語が日本語の場合、書式スケールは万、億、兆は選べますが、K、M、G、Tといった記号を選ぶことはできません。これらの書式スケールを選ぶには、アプリケーション言語を英語に切り替える必要があります。チャートやY軸ラベルに限定してロケールを英語に切り替える方法は見つかりませんでした


アプリケーション言語が日本語でも数値の表記はK、M、G、Tといった略記にしたい場合は多いと思います。

チャートの初期化JavaScriptファンクションで設定できるのは、基本的にConverterOptionsなので、Converterインターフェースを実装したクラスが持つformatファンクションは定義できません。そのため、数値ラベルを変換するIntlNumberConverterのインスタンスを生成し、formatファンクションを置き換えた上で、チャートのY軸ラベルのConverterとして使用します。

Converterの置き換えはチャートのリフレッシュ後に実施します。

Y軸ラベルを置き換えるチャートに動的アクションを作成します。タイミングイベントリフレッシュ後です。


TRUEアクションとしてJavaScriptコードの実行を選択し、設定コードに以下を記述します。


IntlNumberConverterのインスタンスを生成しformatファンクションを置き換えた後、チャートのyAxis.tickLabel.converterに設定しています。


JavaScriptからチャートを参照するために、詳細静的IDとしてtestを設定しています。


また、チャートのY軸の書式少数を選択します。yAxis.tickLabel.converterに設定したIntlNumberConverterのインスタンスは、書式が少数のときに限り有効になるようです。


以上の設定で、アプリケーションが日本語でもY軸のラベルにK、Mといった略記が表示されます。

今回の記事は以上になります。

作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-y-axis-ticklabel-format.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。

2025年5月2日金曜日

任意のSELECT文をデータ・ソースとしたOracle JETの表を動的に生成する

以前の記事「任意のSELECT文をデータ・ソースとしたJETチャートを動的に生成する」では、Oracle JETのoj-chart要素を動的に生成してチャートを表示しました。本記事ではoj-chartの代わりにoj-table要素を動的に生成することにより、任意のSELECT文をソースとした表を表示します。

作成したアプリケーションは以下のように動作します。


アプリケーション自体はチャートの記事で作成したものとほぼ同じです。oj-chart要素は表示するデータを静的に割り当てることができましたが、oj-table要素はDataProviderとして割り当てる必要があります。そのため、アプリケーションの作り方が少し変わります。

このアプリケーションのエクスポートは以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/dynamic-jet-table.zip

以下よりチャートを表示するアプリケーションとの差分について説明します。

ページ・プロパティJavaScriptページ・ロード時に実行は以下になります。ojs/ojchartの代わりにojs/ojtableをロードします。

require(['ojs/ojtable'], function() {});


任意のSELECT文を渡して実行結果を得るAjaxコールバックGET_TABLEとして作成します。ソースPL/SQLコードとして以下を記述します。チャートのときはAjaxコールバックでHTMLを生成しましたが、oj-table要素はデータをHTMLの記述に含めることはできないため、列情報をcolumns属性、データをdata属性として持つJSONドキュメントを返すようにしています。



表の出力先となるDIV要素のIDをchartからtableに変更しています。

<div id="table"></div>


oj-table要素を生成するJavaScriptのコードは以下になります。ボタンGENERATEをクリックしたときに実行されるTRUEアクション設定コードを置き換えます。


以上でアプリケーションは完成です。

Oracle JETのoj-tableのリファレンスは以下になります。今回はoj-tableを表示するために最低限必要な属性であるcolumnsとdataのみを設定しています。他の属性を設定することにより、より使い勝手を向上させることも可能でしょう。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

チャートのタイトルを動的に変更する

Oracle APEXのチャートのタイトルを動的に変更する方法について調べてみました。設定を確認するために、以下のように動作するAPEXアプリケーションを作成しています。

表EMPをソースとしたバー・チャートを作成しています。選択リストのページ・アイテムで、バー・チャートの表示条件となるJOBを選択し、チャートを更新します。同時にチャートのタイトルを選択したJOBに変更しています。


このアプリケーションのエクスポートは以下に置いてあります。
https://github.com/ujnak/apexapps/blob/master/exports/update-chart-title.zip

チャートのタイトルの変更自体は簡単ですが、その実装方法はOracle APEXの公式なドキュメントに記載されていません。ただし、ChatGPTに聞くと大体教えてくれます。

ChatGPTに「Oracle APEXでJavaScriptでchart widgetを取得する手順を教えて」と聞いたところ、以下のコードを教えてくれました。
var chartWidget = apex.region("myChart").widget();
最後にChatGPTから「何を操作したいか(例:データ更新、再描画、ハイライトなど)も教えていただけますか?」と聞かれたので、「ChartのTitleを更新したい」と伝えたところ、以下のコードを教えてくれました。
var chart = apex.region("myChart").widget();
var currentOptions = chart.ojChart("option");

// タイトルを変更する
chart.ojChart("option", "title.text", "新しいタイトル");

// 必要に応じて再描画(通常は自動で反映されます)
Oracle JETのチャートのリファレンスは以下ですが、Oracle APEXのojChartインターフェース経由でどう使えるのかについては説明されていません。

カード・リージョン、ファセット・リージョン、対話グリッド、マップ・リージョンおよびテンプレート・コンポーネントといったJavaScriptの部分をOracle APEXの開発チームが実装しているコンポーネントについては、APIリファレンスにMethodsの説明があり、それを参照することによりJavaScriptで操作できます。

チャート・リージョンはOracle JETを使用しているため、Oracle APEXの開発チームにオーナーシップがありません。そのため、チャート・リージョンについてはページ・デザイナによる宣言的な設定がサポート範囲で、コードによる操作はサポートされません。そもそも、Oracle JETはOracle Corporationが保守しているオープンソース・プロジェクトであり、Oracle JET自体に一般的な製品サポートは提供されていません。

そういう意味ではコードで操作する場合、チャート・コンポーネントは他のオープンソースのフロントエンドのコンポーネントと同じ扱いになります。メンテナンス性を優先する場合は、使用は避けた方が良い、という点でも同じです。

以下より、今回作成したアプリケーションの実装を紹介します。

アプリケーションはすべてホーム・ページに実装しています。

チャートの表示条件となるページ・アイテムP1_JOB選択リストとして作成しています。LOVタイプSQL問合せを選択し、SQL問合せとして以下を記述しています。LOV表示値戻り値ともに表EMPの列JOBに含まれる個別値となります。

select job d, job r from emp group by job

P1_JOBで選択された戻り値をチャートのタイトルとして設定します。

ページ・アイテムが変更されたときに、チャートをリフレッシュする動的アクションを作成します。


チャート・リージョン識別名前給与として作成しています。

ソース表名EMPを指定し、WHERE句:P1_JOB is null or JOB = :P1_JOBを記述しています。送信するページ・アイテムP1_JOBを設定します。この設定により、リージョンのリフレッシュを実行した際に、P1_JOBが空であれば全従業員の給与がバーチャートに表示され、P1_JOBに値があれば、そのJOBを持つ従業員のみがバー・チャートに表示されます。

チャートをJavaScriptから操作するために、詳細静的IDmyChartを設定します。


チャートの属性タイトルとして&P1_JOB.を設定します。これはチャート、つまりOracle JETのチャート・コンポーネントが表示するタイトルになります。


基本的な設定は以上になります。

これから、チャートのタイトルを描画する処理について考えていきます。

最初にページがロードされると、ページに含まれる置換文字列&P1_JOB.が、ページ・アイテムP1_JOBの値で置き換えられます。

ページ・アイテムP1_JOBセッション・ステートストレージセッションごと(永続)としているため、ページ・ロード時にセッション・ステートに保存されている値が反映されます。これがリクエストごと(メモリーのみ)であれば、(デフォルト計算が未設定であれば)つねにページ・アイテムの値は空白になります。

ページ・アイテムP1_JOBの選択を変更したときに、動的アクションでチャートをリフレッシュしています。リージョンの送信するページ・アイテムP1_JOBが設定されていて、そしてセッション・ステートストレージセッションごと(永続)であるため、送信された値がセッション・ステートに保存されます。結果として、ページ・ロード時のP1_JOBの値は、直近のチャートのリフレッシュ時に送信されたP1_JOBの値になります。


置換文字列&P1_JOB.の置き換えはページ・ロード時にのみ行われます。チャートの属性タイトルに設定した&P1_JOB.は、ページ・ロード後はページ・アイテムP1_JOBの値が変わっても、その値が反映されることはありません。


次にチャート・リージョンの属性詳細初期化JavaScriptファンクションが実行されます。初期化JavaScriptファンクションでは、属性に設定項目が存在しない設定もできます。

今回のアプリケーションでは以下のように記述しています。ページ・デザイナで設定した値が引数optionsとして渡され、必要な変更をoptionsに適用して戻します。
function( options ) {
    apex.debug.info(options);
    const job = apex.items.P1_JOB.value ? apex.items.P1_JOB.value : "すべてのJOB";
    // const job = apex.items.P1_JOB.value;
    if ( options.title ) {
        // titleが初期化済みであれば、textのみを更新する。
        options.title.text = job;
        apex.debug.info("INIT: title.text is replaced, ", job);
    }
    else
    {
        // そうでない場合は中央揃えも含めてtitleを初期化する
        options.title = {
            "halign": "center",
            "text": job
        };
        apex.debug.info("INIT: title.text is created, ", job);
    };
    return options;
}
optionsにどのような値が設定されているか、または、どのような値が設定可能かについては、ドキュメント化されていないため、JavaScriptコンソールにoptionsを印刷するか、または、チャート・ウィジェットからoptionを取り出して確認します。

apex.region("myChart").widget().ojChart("option")

例えば、JavaScriptコンソールなどから実行します。


初期化JavaScriptファンクションに渡されるoptionsは、ページ・デザイナで設定している内容に限定されます。リージョンの属性タイトルに値がない場合は、title自体がnullになるため、options.title.textを設定することはできません。そのため初期化JavaScriptファンクションでは、options.titleに設定がない場合は、水平アラインメント(halign)の設定も含めてoptions.titleを設定しています。

初期化JavaScriptファンクションはページ・ロード時に実行されます。リージョンのリフレッシュ時には実行されません。そのため、ページ・アイテムP1_JOBの値が変更されたときは、動的アクションとして同等の処理を実行する必要があります。動的アクションには引数optionsが渡されないため、apex.region("myChart").widget().ojChart()を呼び出して設定を更新します。

チャート・リージョンに必ずタイトルが設定されている場合は、以下のコードでタイトルだけを変更できます。
const job = this.triggeringElement.value ? this.triggeringElement.value : "すべてのJOB";
// const job = this.triggeringElement.value;
apex.region("myChart").widget().ojChart(
    "option",
    "title.text",
    job
);
タイトルが未設定のときがあれば、以下のコードでタイトルを設定できます。
const job = this.triggeringElement.value ? this.triggeringElement.value : "すべてのJOB";
// const job = this.triggeringElement.value;
apex.region("myChart").widget().ojChart(
    "option",
    "title",
    {
        "halign": "center",
        "text": job
    }
);
同じ変更ですが、引数optionを除いて、以下のように呼び出せるようです。
const job = this.triggeringElement.value ? this.triggeringElement.value : "すべてのJOB";
// const job = this.triggeringElement.value;
apex.region("myChart").widget().ojChart(
    { 
        "title": {
            "halign": "center",
            "text": job
        }
    }
);
今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

2025年5月1日木曜日

Qwen3 30B A3B MLXをMacのLM Studioで実行しAPEXアプリケーションからツール呼び出しを行う

2025年4月29日にアリババより発表されたQwne3をmacOSのLM Studioで実行し、ローカルにインストールしたOracle APEXのアプリケーションより呼び出してみます。Qwen3の紹介文によると、tool callingが強化されているとのことなので、以前にOllama向けに作成したツール呼び出しに対応したAPEXアプリケーション(記事「Oracle APEXのアプリよりOllamaのTool supportを呼び出す」)を使用して、主にtool callingの動作を確認します。

APEXアプリケーションのエクスポートは以下です。APEX 24.2で作成しているため、それ以前のバージョンでは読み込めません。
https://github.com/ujnak/apexapps/blob/master/exports/chat-with-generative-ai-hc-242.zip

今回の記事はAPEXアプリケーションの作成方法の紹介を意図していないため、アプリケーションをインストールすると使えるように、サポートするオブジェクトに以下のスクリプトを登録しています。
  1. openai_tools.sql - 表OPENAI_TOOLSを作成するDDL
  2. utl_openai_chat_api.pkh - パッケージUTL_OPENAI_CHAT_APIの定義部
  3. utl_openai_chat_api.pkb - パッケージUTL_OPENAI_CHAT_APIの本体
  4. get_schema - データベースのスキーマ情報を返すファンクションget_schemaを作成
  5. run_sql - 受け取ったSELECT文を実行し、JSONでレスポンスを返すファンクションrun_sqlを作成
  6. tool definitions - 表OPENAI_TOOLSに登録するファンクションget_schemaとrun_sqlのツール定義
最終的に表OPENAI_TOOLS、パッケージUTL_OPENAI_CHAT_API、ファンクションGET_SCHEMAおよびRUN_SQLが作成され、表OPENAI_TOOLSに2行データが挿入されます。

APEXのパーシング・スキーマにサンプル・データセットをインストールし、そのデータについて問い合わせてみました。


システム・プロンプトとして以下を与えています。SQLの生成はQwen3が行うため、Oracle DatabaseのSQL方言を話すようにプロンプトで指示しています。また、スキーマWKSP_APEXDEVを参照するように、プロンプトで指示しています。
あなたは日本語を話すデータ・アナリストです。
実行するSELECT文はOracle Database向けに生成してください。
参照するスキーマは常にWKSP_APEXDEVです。
最初に以下のメッセージを与えました。(GIF動画とは結果が異なります)
日本の人口を教えて。
レスポンスは以下でした。ツール呼び出しとしては、get_schemaを一回、run_sqlは3回呼び出しています。これは最初の2回は結果を返さなかったためです。

日本の人口は126,860,301人です(データソース: WKSP_APEXDEV.EBA_COUNTRIES テーブル)。

この数値は2023年時点の推定値となります。より詳細な統計や最新データが必要な場合は、別途調整を検討してください。

次に以下のメッセージを与えてみました。
アジアで最も人口の少ない国は?
レスポンスは以下でした。

アジアで最も人口の少ない国はブルネイ・ダルサラーム(Brunei Darussalam)です。人口は433,285人(データソース: WKSP_APEXDEV.EBA_COUNTRIES_V テーブル)です。

この結果は、2023年時点の推定値に基づいています。より詳細な統計や最新データが必要な場合は、別の基準(例: 経済協力開発機構のデータなど)を検討することをお勧めします。

次に以下のメッセージを与えてみました。
アメリカで一番人口の多い国は?
レスポンスは以下でした。

アメリカ大陸(North America)で人口最多の国はアメリカ合衆国(United States of America)です。人口は3億2,906万4,917人(データソース: WKSP_APEXDEV.EBA_COUNTRIES_V テーブル)です。

ただし、データベースの構造上、「REGION = 'North America'」の条件で検索した際にはデータが取得できませんでした。このため、明示的に「United States of America」を指定して確認しました。もし大陸全体のランキングが必要な場合は、データの正確性を再検証する必要があります。

正確なランキングが必要です。以下の指示を与えました。
リージョンは表EBA_COUNTRY_REGIONSに定義されています。この情報を覚えてください。
以下のレスポンスが返されました。

リージョンの定義が表 EBA_COUNTRY_REGIONS に保存されていることを認識しました。この情報から、リージョン名(例: 'Asia'、'North America')は EBA_COUNTRIES_V テーブルの REGION カラムに直接記録されている可能性がありますが、正確なマッピングは EBA_COUNTRY_REGIONS の ID と NAME を参照する必要があります。

今後のクエリでリージョンを扱う際は、必要に応じて EBA_COUNTRIES_V と EBA_COUNTRY_REGIONS を結合するクエリを構築することで、より正確な結果を得られるようにします。

以下のメッセージを与えました。
では、アメリカ大陸全体で二番の人口を持つ国を教えて。
レスポンスは以下でした。

アメリカ大陸(Americas)で人口が2番目に多い国はブラジル(Brazil)です。人口は2億1,104万9,527人(データソース: WKSP_APEXDEV.EBA_COUNTRIES_V テーブル)です。

補足

  • リージョンの定義:データベース上の REGION カラムでは、「Americas」(アメリカ大陸)が1つのリージョンとして扱われており、北米と南米の国々が含まれます。
  • 順位:上位2国のリストは以下の通りです。
    1. United States of America(3億2,906万4,917人)
    2. Brazil(2億1,104万9,527人)

この結果は、リージョン「America」に属する国の人口に基づいています。

最後の回答を得るためにQwen3は以下のツール呼び出しを行なっています。

最初に以下のSELECT文を引数としてファンクションrun_sqlを呼び出しています。

SELECT NAME, POPULATION FROM WKSP_APEXDEV.EBA_COUNTRIES_V WHERE REGION IN ('North America', 'South America') ORDER BY POPULATION DESC FETCH FIRST 2 ROWS ONLY

run_sqlの回答は、"no data found, please consider to change the condition supplied with this select statment."です。ファンクションrun_sqlは、結果が得られないと条件を変えて、と応答するように作っています。

Qwen3は言われた通りにSELECT文の条件を変えてrun_sqlを呼び出しています。

SELECT NAME, POPULATION FROM WKSP_APEXDEV.EBA_COUNTRIES_V WHERE REGION = 'Americas' ORDER BY POPULATION DESC FETCH FIRST 2 ROWS ONLY

この場合もno data foundが返されます。Qwen3は諦めて表EBA_COUNTRY_REGIONSを読み込んでいます。以下のSELECT文をrun_sqlで実行しています。

SELECT ID, NAME FROM WKSP_APEXDEV.EBA_COUNTRY_REGIONS

run_sqlは以下のレスポンスを返します。

[{"ID":10,"NAME":"America"},{"ID":20,"NAME":"Europe"},{"ID":30,"NAME":"Asia"},{"ID":40,"NAME":"Oceania"},{"ID":50,"NAME":"Africa"}]

この回答を使って、REGIONにAmericaを指定したSELECT文を生成し、run_sqlを呼び出しています。

SELECT NAME, POPULATION FROM WKSP_APEXDEV.EBA_COUNTRIES_V WHERE REGION = 'America' ORDER BY POPULATION DESC FETCH FIRST 2 ROWS ONLY

run_sqlは以下のレスポンスを返します。

[{"NAME":"United States of America","POPULATION":329064917},{"NAME":"Brazil","POPULATION":211049527}]

2番目の国としてBrazilが得られたので、それが回答になっています。

ローカルで動かしているLLMが、ここまでプロンプトに追従するとは思いませんでした。

以下に若干、作業環境や設定などを紹介します。

LM Studioは0.3.15 (Build 11)を使っています。LM Studioにロードして実行したモデルは以下です。Content Lengthに40960を指定しています。


メモリは32.46GBと表示されています。4bit量子化のモデルであれば、32GBのメモリがあれば動きそうです。


問合せに使用するデータとして、サンプル・データセットをインストールしています。


APEXアプリケーションのアプリケーション定義置換文字列を設定しています。

APEXのデータベースはpodmanのコンテナとして実行しているため、LM StudioのAPIのエンドポイントの指定である置換文字列G_API_ENDPOINTには、http://host.containers.internal:8080/v1/chat/completionsを設定しています。LM Studioのローカル・サーバーはポート8080で待ち受けするように設定しています。

モデルの指定である置換文字列G_MODEL_NAMEにはqwen3-30b-a3b-mlxを設定しています。


スキーマ情報を返すファンクションget_schemaのコードは以下です。


ツール定義は以下になります。


SELECT文を受け取って実行するファンクションrun_sqlのコードは以下です。


ツール定義は以下になります。


最後にインストール時に作成されたオブジェクトは、以下のコマンドで削除できます。
drop function run_sql;
drop function get_schema;
drop package  utl_openai_chat_api;
drop table    openai_tools;
今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。