作成したAPEXアプリケーションは以下のように動作します。
観光立国推進基本法の前文の最初のセンテンスを、小学生向けと中学生向けに言い換えてもらっています。言い換えを行なう生成AIとして、ローカルのLM Studioにロードしたphi-4@8bitを使用しています。
ちなみに、言い換えの対象とした観光立国基本法の前文は以下です。
「観光は、国際平和と国民生活の安定を象徴するものであって、その持続的な発展は、恒久の平和と国際社会の相互理解の増進を念願し、健康で文化的な生活を享受しようとする我らの理想とするところである。また、観光は、地域経済の活性化、雇用の機会の増大等国民経済のあらゆる領域にわたりその発展に寄与するとともに、健康の増進、潤いのある豊かな生活環境の創造等を通じて国民生活の安定向上に貢献するものであることに加え、国際相互理解を増進するものである。」
「観光って、とても大切なことなんだよ。みんなでお互いに仲良くするために、国や世界の人々が集まって遊びに来るんだよ。このことで、世界中の人々が仲良くなれたり、お互いを理解し合えるようになるんだ。 友達と一緒にお出かけするのと似ていて、観光は私たちが楽しさや素敵な経験を分かち合うことができるんだよ。また、観光は地域のお店を元気にしたり、仕事をたくさん作ってくれるんだ。 それから、観光で色々なところを訪れたりするのは、体も心も元気になるし、素敵で豊かな生活を送れるようにしてくれるんだ。さらに、異なる文化や考え方を知って楽しむことで、お互いのことをよく理解する手助けになるんだよ。 ね、観光って素晴らしいことだと思わない?みんなが楽しく、お互いを理解し合って生活できるように、観光はすごく役立っているんだね。」
中学生向けの言い換えとして、以下が生成されました。
法令データのロードには、以前の記事「日本の法令データをデータベースにロードする」で作成したアプリケーションを使用します。元記事を書いた時から2点、変更があります。
1点目は旧法令名(表JLAW_DATAの列LAW_TITLE_FORMER)の長さを600文字に拡張しています。2点目は、本文URLが変わっているため、列IDのデータ・プロファイルのソースのSQL式を以下のように変更しています。
旧
replace(BODY_URL, 'https://elaws.e-gov.go.jp/document?lawid=')
e-Gov法令検索リニューアル後
replace(replace(BODY_URL, 'https://laws.e-gov.go.jp/law/'),'/','_')
Oracle APEX 24.2で、元記事の手順に従って作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/laws-e-gov-0.zip
このアプリケーションでは、法令XMLのデータをURLから取得しています。データをロードするごとに、データのダウンロードを繰り返すことを避けるために、法令XMLのZIPファイルを一旦ファイルとしてダウンロードしたのちに、そのファイルをアップロードする機能を追加します。
ホーム・ページに、アップロードするファイルを選択するページ・アイテムを作成します。
識別の名前はP1_FILE、タイプはファイルのアップロードです。ラベルはFileとします。ストレージのタイプに表APEX_APPLICATION_TEMP_FILES、ファイルをパージするタイミングとしてリクエストの終わりを選択します。ファイル・タイプにapplication/zipを指定し、アップロード対象をZIPファイルに限定します。
セッション・ステートのストレージはリクエストごと(メモリーのみ)とします。
ZIPファイルをアップロードするボタンを作成します。
識別のボタン名はUPLOAD、ラベルはUploadとします。外観のホットをオンにし、テンプレート・オプションのWidthをStretchにします。
動作のアクションはデフォルトのページの送信です。
プロセス・ビューを開き、実行チェーン法令データのロードを選択します。
実行チェーンの子プロセスでアップロードされたファイルが参照できるように、設定の一時ファイル処理を移動に変更し、一時ファイル・アイテムとしてP1_FILEを選択します。
また、ボタンUPLOADのクリックでもロード処理が実行されるように、サーバー側の条件のボタン押下時を- 選択 -に戻し、タイプにリクエストは値に含まれる、値としてLOAD UPLOADを設定します。
バインド変数REQUESTに、ページの送信を実行したボタン名が設定されています。タイプの意味が分かりにくいですが、バインド変数REQUESTの値としてLOAD UPLOADのどれかが設定されている、という条件になっています。ボタンによるページの送信に限れば、ボタン押下時の設定は、リクエスト = 値と同じ条件になります。
プロセスLoad e-Gov CSV and XMLのソースのPL/SQLコードを以下に置き換えます。ボタンUPLOADのときはZIPファイルをAPEX_APPLICATION_TEMP_FILESより取り出すように、コードを追加しています。
以上で、URL指定の代わりにファイルをアップロードする機能が追加されました。
APEXアプリケーションを実行し、法令データをロードしてみます。
記事の先頭のGIF動画ではe-Gov法令のXML一括ダウンロードより、観光に関する法令データを読み込んで扱っています。この法令データは、5_xml.zipとしてダウンロードされます。
バックグランド処理のStatus CodeがSUCCESSで終了していれば、データのロードは成功です。
ここまで実装したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/laws-e-gov-1.zip
これから、法令データの言い換えを実装します。
法令データは、XML形式のままデータベースに保存しています。XML形式のままではAPEXで扱うのが難しいため、これを表として参照できるようにビューを定義します。CREATE VIEW文は、本記事の末尾に添付します。
作成するビューの中で、法令の前文を扱うビューJLAW_LAW_PREAMBLE_XVと、本則を扱うビューJLAW_LAW_MAINPROVISION_XVについて、対話モード・レポートで一覧します。
アプリケーションに空白のページを作成します。
ページの作成をクリックします。
空白ページを選択します。
識別の名前を前文とし、タイプに対話モード・レポートを選択します。ソースのSQL問合せに以下を記述します。
詳細のリージョン表示セレクタをオンにします。
列"Root_Num"、"Paragraph_Num"、"Sentence_Num"は数値のはずなのですが、1_1のような数値に変換できない文字列が含まれていることがあったため、ビューの検索時にエラーが発生しないようにXMLからは文字列として取り出しています。レポートのソースで、文字列から数値に変換しています。
特に本則の表示はデフォルトでは見にくいため、対話モード・レポートのカスタマイズが必要でしょう。
もう一つ、本則を表示する対話モード・レポートのリージョンを作成します。
識別の名前を本則とし、タイプに対話モード・レポートを選択します。ソースのSQL問合せに以下を記述します。
先頭のリージョンを、リージョン表示セレクタにします。装飾は不要なため、外観のテンプレートにBlank with Attributesを選択します。
詳細のリージョン表示セレクタをオンにします。
1ページに表示される情報量を制限するため、属性を開き、設定の「すべて表示」を含めるをオフにします。
ページを実行します。
対話モード・レポートとして法令の前文または本則が表示されます。
本則では、列として"Law Id"、"Lawtype"、"Lawnum"、"Parttitle"、"Chaptertitle"、"Sectiontitle"、"Subsectiontitile"、"Divisiontitle"、"Articletitle"、"Sentence Num"、"Sentence"などを表示します。
対話モード・レポートのソースとなるSELECT文にORDER BY句を含めるべきではありませんが、法令については表記の順番を変える必要はなく、また、対話モード・レポートとして設定できるソート列は6までなので、今回はソースのSELECT文で表示順序を決めています。
対話モード・レポートの属性のソートをオフにします。
列についてもソートをオフにすると、対話モード・レポートでソートの設定ができなくなります。
以上で、法令の前文と本則を表示する対話モード・レポートの設定は完了です。
これより、本題の動的アクションのAIによるテキストの生成を実装します。
生成AIはローカルのLM Studioを呼び出します。LLMとして、比較的速くレスポンスが返されるphi-4@8bitを使用します。
APEXのワークスペースに、ローカルのLM Studioを呼び出すための生成AIサービスの構成を作成します。ローカルのLM Studioの呼び出しにWeb資格証明は不要ですが、APEXの生成AIの構成では必須の設定になっています。そのため、ダミーのWeb資格証明を作成します。
ワークスペース・ユーティリティのWeb資格証明を作成します。
Web資格証明の一覧で作成をクリックし、以下のような形だけの資格証明を作成します。
名前はempty credential、静的IDとしてEMPTY_CRED、認証タイプにHTTPヘッダーを選択します。資格証明名はAuthorization、資格証明シークレットとしてbearer emptyを指定します。
以上の設定で、Web資格証明を作成します。
続いて、ワークスペース・ユーティリティの生成AIを開きます。
生成AIの一覧より作成をクリックし、生成AIサービスを作成します。
AIプロバイダにOpen AIを選択します。名前はphi-4@8bitとし、静的IDはPHI4とします。ベースURLは、podmanのコンテナとして実行されているOracle Databaseより、ホストのポート8080で待ち受けしているLM Studioのローカル・サーバーに接続するため、以下のように指定します。
http://host.containers.internal:8080/v1
資格証明として先ほど作成した空の資格証明EMPTY_CREDを選択します。詳細のAIモデルとして、呼び出すモデル名であるphi-4@8bitを設定します。
以上で接続のテストをクリックして、動作確認します。接続に成功したら、作成をクリックします。
生成AIサービスとしてphi-4@8bitが作成されました。
APEXワークスペースへの生成AIサービスの作成は以上で完了です。
APEXアプリケーションのAI構成を作成します。これはAPEX 24.2で追加された構成になります。
共有コンポーネントのAI構成を開きます。
AI構成として、法令を小学生向けに言い換える構成と、中学生向けに言い換える構成の2つを作成します。
作成をクリックします。
最初に小学生向けに言い換えを行なうAI構成を作成します。
識別の名前は小学生向け、静的IDはELEMENTARYとします。サービスに先ほど作成したphi-4@8bitを選択します。
システム・プロンプトとして以下を記述します。
「あなたには、日本の小学校の先生の役割が与えられています。与えられたメッセージを小学生に分かるように言い換えてください。」
以上で作成をクリックします。
生成AI構成として小学生向けが作成されます。RAGソースが設定可能な項目として表示されます。今回はRAGソースは構成しないため、そのまま変更の適用をクリックします。
識別の名前は中学生向け、静的IDはJUNIOR、生成AIのサービスはphi-4@8bitを選択し、システム・プロンプトとして以下を記述します。
「あなたには、日本の中学校の先生の役割が与えられています。与えられたメッセージを中学生に分かるように言い換えてください。」
以上の設定でAI構成を作成します。
AI構成として、小学生向けと中学生向けが作成されました。
APEXアプリケーションのページ番号3の説明のページに、言い換えの元になる法令を保持するページ・アイテムと言い換えた後の文章を表示するページ・アイテムおよび生成AIによる言い換えを呼び出すボタンを作成します。
言い換えの対象とする法令を保持するページ・アイテムはP3_TEXTとして作成します。タイプはテキスト領域、ラベルは法令とします。
セッション・ステートのデータ型はCLOB、ストレージはリクエストごと(メモリーのみ)とします。
動作のアクションとして動的アクションで定義を選択します。
同様に中学生に説明するボタンを作成します。ボタン名はEXPLAIN_JUNIORとします。
生成AIによる言い換えを表示するページ・アイテムとしてP3_EXPLAINを作成します。タイプはリッチ・テキスト・エディタとします。ラベルは言い換えとします。
設定の書式としてマークダウンを選択します。ただし、今回設定したシステム・プロンプトとphi-4@8bitの組み合わせでは、マークダウンは出力はされないようです。
セッション・ステートのデータ型はCLOB、ストレージはリクエストごと(メモリーのみ)を指定します。このページ・アイテムは表示しかしないため、読取り専用のタイプに常時を設定します。
ボタン小学生に説明するをクリックしたときに実行する動的アクションを作成します。
識別の名前はonClick EXPLAIN_ELEMENTARYとします。タイミングのイベントはクリック、選択タイプはボタン、ボタンはEXPLAIN_ELEMENTARYになります。
最初に実行されるTRUEアクションとしてクリアを実行し、言い換えを表示しているページ・アイテムP3_EXPLAINをクリアします。
続くTRUEアクションとしてAIによるテキスト生成を実行します。生成AIの構成に小学生向けを選択します。
入力値のタイプにアイテム、アイテムとしてP3_TEXTを選択します。入力値のタイプには、ページ・アイテムの他にシステム・プロンプトのみとJavaScriptコードがあります。入力値を加工したい場合、JavaScriptコードを使うことができます。
レスポンスの使用のタイプにアイテム、アイテムとしてP3_EXPLAINを選択します。レスポンスの使用のタイプには、ページ・アイテムの他にJavaScriptコードがあります。出力についても、JavaScriptコードで加工することができます。
以上で、ボタン小学生に説明するをクリックすると、ページ・アイテムP3_TEXTの内容を小学生向けに言い換えて、ページ・アイテムP3_EXPLAINに表示する機能が実装できました。
同様にボタン中学生に説明するの動的アクションを作成します。
動的アクションの識別の名前はonClick EXPLAIN_JUNIORとします。
小学生向けと同様に、最初のTRUEアクションでページ・アイテムP3_EXPLAINをクリアします。
後続のTRUEアクションとしてAIによるテキスト生成を実行します。小学生向けと同様ですが、生成AIの構成として、中学生向けを選択します。
以上で、APEX 24.2の新機能、AIによるテキスト生成を使った法令の言い換えが実装できました。
ページを実行し、対話モード・レポートに表示されている法令の文言を、ページ・アイテムの法令にコピーして、ボタン小学生に説明するをクリックします。
小学生向けの説明が、言い換えの領域に表示されます。
同様にボタン中学生に説明するをクリックすると、中学生向けの説明が表示されます。
毎回、対話モード・レポートから法令の文言をコピペするのは面倒なので、列Sentenceのセルをクリックしたときに、そのセルの文言をページ・アイテムにコピーするようにします。
前文を表示する対話モード・レポートのCSSクラスとしてlaw-Reportを設定します。これはセレクタで使用するためのクラスなので、CSSクラス自体は定義しません。
列Sentenceの静的IDとしてSENTENCE_COLUMNを設定します。Oracle APEXのほぼ全てのコンポーネントで静的IDは属性IDとして設定されますが、レポート列は例外で属性headersとして設定されます。
本則を表示する対話モード・レポートについても、同様の設定を行います。
対話モード・レポートのCSSクラスとしてlaw-Reportを設定します。
列Sentenceの静的IDとしてSENTENCE_COLUMNを設定します。
レポート列Sentenceからページ・アイテムP3_TEXTにテキストをコピーする動的アクションを作成します。
左ペインで動的アクション・ビューを開き、クリックのノードで新たに動的アクションを作成します。
識別の名前はClick to Copyとします。実行のイベント有効範囲に動的を選択し、静的コンテナ(jQueryセレクタ)に.law-Reportを指定します。タイプは即時です。
タイミングのイベントはクリック、選択タイプにjQueryセレクタを選び、jQueryセレクタとしてtd[headers="SENTENCE_COLUMN"]を指定します。
以上で、対話モード・レポートの列Sentence上でクリックしたときに、動的アクションが実行されます。
TRUEアクションとして値の設定を実行します。
設定のタイプの設定にJavaScript式を選択し、JavaScript式としてthis.triggeringElement.innerTextを記述します。ボタンのクリックはレポート上のTD要素上で発生するため、TD要素がtriggeringElementとなります。そのクリックされたTD要素のinnerTextが、コピーする対象の文字列になります。
影響を受ける要素の選択タイプはアイテム、アイテムとしてP3_TEXTを指定します。ページ・アイテムP3_TEXTがコピー先になります。
実行の初期化時に実行はオフとします。
これで、記事に先頭のGIF動画のように動作するAPEXアプリケーションは完成です。
完成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/laws-e-gov.zip
今回の記事は以上になります。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完