2025年3月11日火曜日

APEX 24.2の動的アクション - AIによるテキストの生成 - を呼び出し法令を言い換えてもらう

e-Gov法令のサイトより法令データをダウンロードしOracle Databaseにロードします。そして、データベースに保存した法令を、生成AIを呼び出して言い換えてもらいます。生成AIの呼び出しにOracle APEX 24.2で新規に追加された動的アクション、AIによるテキストの生成を使用します。

作成した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とします。外観ホットオンにし、テンプレート・オプションWidthStretchにします。

動作アクションはデフォルトのページの送信です。


プロセス・ビューを開き、実行チェーン法令データのロードを選択します。

実行チェーンの子プロセスでアップロードされたファイルが参照できるように、設定一時ファイル処理移動に変更し、一時ファイル・アイテムとして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としてダウンロードされます。


File5_xml.zipを選択し、ボタンUploadをクリックします。


バックグランド処理の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について、対話モード・レポートで一覧します。

アプリケーションに空白のページを作成します。

ページの作成をクリックします。


空白ページを選択します。


ページの名前説明として、ページの作成をクリックします。


作成したページに3つのリージョンを作成します。1つは法令の前文を表示します。

識別名前前文とし、タイプ対話モード・レポートを選択します。ソースSQL問合せに以下を記述します。

詳細リージョン表示セレクタオンにします。

"Root_Num""Paragraph_Num""Sentence_Num"は数値のはずなのですが、1_1のような数値に変換できない文字列が含まれていることがあったため、ビューの検索時にエラーが発生しないようにXMLからは文字列として取り出しています。レポートのソースで、文字列から数値に変換しています。


もう一つ、本則を表示する対話モード・レポートのリージョンを作成します。

識別名前本則とし、タイプ対話モード・レポートを選択します。ソースSQL問合せに以下を記述します。

詳細リージョン表示セレクタオンにします。


先頭のリージョンを、リージョン表示セレクタにします。装飾は不要なため、外観テンプレートBlank with Attributesを選択します。


1ページに表示される情報量を制限するため、属性を開き、設定「すべて表示」を含めるオフにします。


ページを実行します。

対話モード・レポートとして法令の前文または本則が表示されます。


特に本則の表示はデフォルトでは見にくいため、対話モード・レポートのカスタマイズが必要でしょう。


前文のレポートでは、列として"Law Id"、"Lawnum"、"Lawtitle"、"Sentence Num"、"Sentence"を表示します。


結果として、レポートが以下のように表示されます。


本則では、列として"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とし、静的IDPHI4とします。ベース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構成を作成します。

識別名前小学生向け静的IDELEMENTARYとします。サービスに先ほど作成したphi-4@8bitを選択します。

システム・プロンプトとして以下を記述します。

「あなたには、日本の小学校の先生の役割が与えられています。与えられたメッセージを小学生に分かるように言い換えてください。」

以上で作成をクリックします。


生成AI構成として小学生向けが作成されます。RAGソースが設定可能な項目として表示されます。今回はRAGソースは構成しないため、そのまま変更の適用をクリックします。


同様の手順で、法令を中学生向けに言い換えるAI構成を作成します。

識別名前中学生向け静的IDJUNIOR生成AIサービスphi-4@8bitを選択し、システム・プロンプトとして以下を記述します。

「あなたには、日本の中学校の先生の役割が与えられています。与えられたメッセージを中学生に分かるように言い換えてください。」

以上の設定でAI構成を作成します。


AI構成として、小学生向け中学生向けが作成されました。


APEXアプリケーションのページ番号3の説明のページに、言い換えの元になる法令を保持するページ・アイテムと言い換えた後の文章を表示するページ・アイテムおよび生成AIによる言い換えを呼び出すボタンを作成します。

言い換えの対象とする法令を保持するページ・アイテムはP3_TEXTとして作成します。タイプテキスト領域ラベル法令とします。

セッション・ステートデータ型CLOBストレージリクエストごと(メモリーのみ)とします。


小学生向けの説明を生成するボタンをEXPLAIN_ELEMENTARYとして作成します。ラベル小学生に説明する、とします。

動作アクションとして動的アクションで定義を選択します。


同様に中学生に説明するボタンを作成します。ボタン名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がコピー先になります。

実行初期化時に実行オフとします。


以上で、対話モード・レポートでクリックした列Sentenceのセルの文字列が、ページ・アイテムP3_TEXTにコピーされるようになりました。

これで、記事に先頭のGIF動画のように動作するAPEXアプリケーションは完成です。

完成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/laws-e-gov.zip

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

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