2023年12月24日日曜日

Google Geminiのマルチターンと関数呼び出しを実装する

Google Gemniを呼び出すアプリケーションにマルチターン(いわゆるチャット)と関数呼び出しを行うページを追加します。どちらの呼び出し方も、OpenAIのChat Completions APIに非常に近いため、以下の記事の実装を援用します。

OpenAIのChatGPTのAPIを呼び出すAPEXアプリを作る

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

関数呼び出しが行われた場合(Chat HistoryのタイプでfunctionResponseが現れた場合)関数呼び出しの戻り値をGeminiに渡すため、Textを空白にしてRunをクリックする必要があります。


最初に関数呼び出しの、呼び出し対象となるファンクションを登録する表を作成します。

クイックSQLの以下のモデルより、表GEMINI_FUNCTIONSを作成します。

この表はOpenAIでの作業の際に作成した表OPENAI_FUNCTIONSとOPENAI_FUNCTION_SETを(不具合の修正も合わせて)簡素にしています。この表にサンプルとして設定するファンクションとして、OpenAIのときと同じget_current_weatherを使用します。


表を作成した後、この表にデータを投入するためにフォーム付き対話モード・レポートのページを作成します。

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


対話モード・レポートを選択します。


対話モード・レポートのページのページ名はFunctionsとします。フォーム・ページを含めるチェックします。フォーム・ページ名Function Detailとします。

データ・ソース表/ビューの名前GEMINI_FUNCTIONSを指定します。

へ進み、主キー列1ID (Number)を選択しページの作成をクリックすると、表GEMINI_FUNCTIONS対話モード・レポートフォームのページが作成されます。


ファンクションGET_CURRENT_WEATHERも作成しておきます。元記事に説明がありますが、このファンクションは引数である都市名から座標を得るために、アマノ技研さんより提供されている「世界の百万都市の位置データ Location Data of Megacities」のCSVファイルを表AMANO_CITY_LOCATIONSにロードしています。

アプリケーションを実行しFunctionsのページを開き、作成をクリックします。


ファンクションGET_CURRENT_WEATHERを登録します。

Function nameとしてget_current_weatherFunction Set NameとしてWeatherDescriptionとしてGet the current weather in a given locationParametersには以下のJSONドキュメントを記述します。
{
  "type": "object",
  "properties": {
    "location": {
      "type": "string",
      "description": "The city name"
    },
    "unit": {
      "type": "string",
      "enum": [
        "celsius",
        "fahrenheit"
      ]
    }
  },
  "required": [
    "location"
  ]
}
これらはOpenAIでFunction Callingを行う際に設定した内容とほぼ同じです。双方とも関数呼び出しの引数の定義は、OpenAPI 3.0に準拠しています。

作成をクリックします。


ファンクションget_current_weatherが設定されます。


APEXアプリケーションへマルチターンの処理を行うページを追加します。

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


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


ページ番号は、ページの名前Chatとします。

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


空白のページが作成されます。

会話を初期化するボタンINIT_CONVERSATIONを作成します。ラベルはInitialize Conversation動作アクションはデフォルトのページの送信です。テンプレート・オプションWidthStretchに変更しています。


プロセス・ビューを開き、このボタンINIT_CONVERSATIONがクリックされたときに実行されるプロセスを作成します。

作成したプロセスの識別名前Initialize Conversationとします。タイプコードを実行です。ソースPL/SQLコードに以下を記述します。チャット履歴を保持するAPEXコレクションGEMINIを初期化しています。
apex_collection.create_or_truncate_collection(
    p_collection_name => 'GEMINI'
);
サーバー側の条件ボタン押下時INIT_CONVERSATIONを指定します。


レンダリング・ビューに戻ります。

テキストを入力するページ・アイテムP6_TEXTを作成します。タイプテキスト領域ラベルTextとします。

セッション・ステートデータ型CLOBを選択し、続けて同じテキストを送信してしまわないように、ストレージとしてリクエストごと(メモリーのみ)を選択します。


ファンクション・セットを選択するページ・アイテムP6_FUNCTION_SETを作成します。

タイプ選択リストラベルFunction Setとします。LOVタイプSQL問合せを選択し、SQL問合せとして以下を記述します。
select function_set_name d, function_set_name r from gemini_functions group by function_set_name order by 1 asc
追加値の表示オフNULL値の表示オンとし、NULL表示値として- ファンクション・セットを選択 -と記述します。

セッション・ステートストレージセッションごと(永続)を選択します。


会話を実行するボタンRUNを作成します。ラベルはRun動作アクションはデフォルトのページの送信です。外観ホットオンにします。テンプレート・オプションWidthStretchに変更しています。


プロセス・ビューを開き、このボタンRUNがクリックされたときに実行されるプロセスを作成します。

作成したプロセスの識別名前Run Conversationとします。タイプコードを実行です。ソースPL/SQLコードに以下を記述します。

サーバー側の条件ボタン押下時RUNを指定します。


レンダリング・ツリーに戻り、チャット履歴を表示するクラシック・レポートのリージョンを作成します。

識別タイトルChat HistoryソースタイプとしてSQL問合せを選択し、SQL問合せとして以下を記述します。
select c001, c002, clob001 from apex_collections where collection_name = 'GEMINI' order by seq_id

C001ヘッダーroleとします。


C002のヘッダーをtypeとします。


CLOB001タイプリッチ・テキストに変更します。ヘッダーtextです。設定書式としてマークダウンを選択します。


以上でアプリケーションは完成です。アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。

今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/google-gemini2.zip

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

2023年12月23日土曜日

Google Geminiを呼び出すAPEXアプリケーションを作る

Google AI Gemini APIを呼び出すAPEXアプリケーションを作ってみました。

以下のように動作します。Gemini APIはチャット形式のやり取り(OpenAIのChat Completionsとほぼ同じ)と関数呼び出し(OpenAIのFunction Callingとほぼ同じ)もサポートしていますが、これらの実装はまた別の機会にしようと思います。


写っている動物の質問に使った画像は以下です。


タヌキなんですがハクビシンといわれています。世界的にみると珍しい動物らしいので、学習されていないのでしょうか。

APEXのアプリケーションの作りは単純です。

Textのページは、質問を入力するテキスト領域のページ・アイテムであるP2_TEXT、質問を送信ボタンRUN、Geminiのレスポンスのマークダウン読み取り専用で表示するP2_RESPONSEから構成されています。


ボタンRUNを押した時に実行されるプロセスとして、以下のコードを記述します。ほとんどの処理はパッケージUTL_GOOGLE_GEMINI_APIで行っています。このコードは記事の末尾に添付しています。



画像の問い合わせをするページには、APEX 23.2で新設されたイメージ・アップロードを使っています。


Geminiを呼び出すプロセスのコードは以下になります。


今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/google-gemini.zip

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


2023年12月22日金曜日

Autonomous Database Free Container Imageを実行する

更新: 2026年2月9日- ARM 64-bitの対応に合わせて更新

オラクル社よりOracle Autonomous Database Free Container Imageという、Always FreeのAutonomous Databaseと同等のインスタンスをDockerやPodmanで動かせるイメージが提供されています。

Oracle Container Registryにイメージや導入手順の説明があります。

Other Open Source Licensesの箇所に、このContainer ImageがOracle Free Use Terms and Conditionsの元で配布されていると記載されています。


Oracle APEXのアプリケーション開発に使えるかと考えたのですが、Oracle APEXに関していうと、英語以外の言語リソースがインストールされていないため、使用は難しいというのが結論です。構成がAutonomous DatabaseであるためAPEXのスキーマが保護されていて、言語リソースの追加インストールもできません。

Oracle APEXの追加言語は開発ツールを多言語に対応させるためのものです。日本語などを含む作成済みのアプリケーションは言語リソースがインストールされていなくても、そのまま各国語の言語で動作します。アプリケーションを実行する環境としてであれば、日本語のアプリケーションを実行することはできます。

とはいえ、macOS上でAutonomous Database Free Container Imageを動作させたので、その手順を記録しておきます。

Oracle AI Database 23ai Freeを含むコンテナ・イメージの最新版のタグはlatest-23aiです。latest-23aiのコンテナ・イメージはx86_64向けとARM 64-bit向けの双方が提供されています。Oracle Database 19cを含むコンテナ・イメージの最新版のタグはlatestです。こちらは、x86_64向けのコンテナ・イメージのみが提供されています。

Appleシリコンのmac0Sにpodmanをインストールし、Autonomous Database Free Container Imageを実行します。Oracle Container Registryのページに記載されている手順にそって、作業を実施します。

Podmanをインストールします。

brew install podman

すでにインストールされていたので、そのようなメッセージが表示されています。

~ % brew install podman

Warning: podman 5.7.1 is already installed and up-to-date.

To reinstall 5.7.1, run:

  brew reinstall podman

~ % 


Podmanの仮想マシンを作成します。

podman machine init

 ~ % podman machine init  


Looking up Podman Machine image at quay.io/podman/machine-os:5.7 to create VM

Getting image source signatures

Copying blob 755f2149fbd7 done   | 

Copying config 44136fa355 done   | 

Writing manifest to image destination

755f2149fbd7459cd18238941fb6e9e701a2fff9c3af468f81315ccf601ac8d2

Extracting compressed file: podman-machine-default-arm64.raw: done  

Machine init complete

To start your machine run:


podman machine start


~ % 


最低限のCPUとメモリはx86_64向けの情報ですが、ARM 64-bitでも同じ値を設定します。

podman machine set --cpus 4 --memory 8192

~ % podman machine set --cpus 4 --memory 8192

~ %

 
仮想マシンを起動します。

podman machine start

 ~ % podman machine start


Starting machine "podman-machine-default"


This machine is currently configured in rootless mode. If your containers

require root permissions (e.g. ports < 1024), or if you run into compatibility

issues with non-podman clients, you can switch using the following command:


podman machine set --rootful


API forwarding listening on: /var/folders/fw/z20l7ys92zz_b2ryx2224y040000gn/T/podman/podman-machine-default-api.sock


The system helper service is not installed; the default Docker API socket

address can't be used by podman. If you would like to install it, run the following commands:


        sudo /opt/homebrew/Cellar/podman/5.7.1/bin/podman-mac-helper install

        podman machine stop; podman machine start


You can still connect Docker API clients by setting DOCKER_HOST using the

following command in your terminal session:


        export DOCKER_HOST='unix:///var/folders/fw/z20l7ys92zz_b2ryx2224y040000gn/T/podman/podman-machine-default-api.sock'


Machine "podman-machine-default" started successfully

~ % 


仮想マシンの起動を確認します。

podman machine ls

~ % podman machine ls

NAME                     VM TYPE     CREATED         LAST UP            CPUS        MEMORY      DISK SIZE

podman-machine-default*  applehv     16 minutes ago  Currently running  4           8GiB        100GiB

~ % 


環境変数MYPASSとして、作成するコンテナに設定するパスワードをあらかじめ設定します。ウォレットのパスワードとユーザーADMINのパスワードに同じ値を設定します。

export MYPASS=[パスワード]

% export MYPASS=[パスワード] 

%


Autonomous Database Free Containerを実行します。作成されるコンテナの名前はadb-freeになります。環境変数WALLET_PASSWORDおよびADMIN_PASSWORDに、パスワードを指定します。
podman run -d \
-p 1521:1522 \
-p 1522:1522 \
-p 8443:8443 \
-p 27017:27017 \
-e WORKLOAD_TYPE=ATP \
-e WALLET_PASSWORD=$MYPASS \
-e ADMIN_PASSWORD=$MYPASS \
--cap-add SYS_ADMIN \
--device /dev/fuse \
--name adb-free \
container-registry.oracle.com/database/adb-free:latest-23ai

~ % podman run -d \

-p 1521:1522 \

-p 1522:1522 \

-p 8443:8443 \

-p 27017:27017 \

-e WORKLOAD_TYPE=ATP \

-e WALLET_PASSWORD=$MYPASS \

-e ADMIN_PASSWORD=$MYPASS \

--cap-add SYS_ADMIN \

--device /dev/fuse \

--name adb-free \

container-registry.oracle.com/database/adb-free:latest-23ai


Trying to pull container-registry.oracle.com/database/adb-free:latest-23ai...

Getting image source signatures

Copying blob sha256:1acde01a60f5ceef456f7dbe534cc7bd24e783f20c95a872eb96749e90824e9b

Copying blob sha256:7fb6ba14c3282911ab3cbdcabf4b2fe647ff8da78297af696e40e722d8c0878a

Copying blob sha256:be7d2334546ec3354ee8afdb51f526777338c863bfb4248e617af8cf163a9d21

Copying config sha256:ba51669197b517432de2e2eb6cd8242a5fc2db753fc62734d534e36233d44ea3

Writing manifest to image destination

8f93728d79aeaa17345a9c755d4325a66f29c03ec40dac7027d84a10a2d98b47

~ % 


ADB Freeのコンテナは作成時にPDBにイメージをダウンロードするため、コンテナの新規作成時は起動までに時間がかかります。

podman logs -f adb-free

ワークロード・タイプがATPの場合、535MBのPDBのイメージをダウンロードしています。

TIME ELAPSED Wallet Generation: 0 minutes and 41 seconds elapsed

User has requested to download '.pdb' archive file from Object Storage bucket

Downloading MY_ATP.pdb..

100%|██████████| 535M/535M [03:10<00:00, 2.95MB/s] 

Download complete for MYATP.pdb

PDB archive file saved at: /u01/data/MYATP.pdb

TIME ELAPSED Downloaded PDBs: 3 minutes and 11 seconds elapsed



環境変数MYPASSを消去します。

unset MYPASS

~ % unset MYPASS

~ % 


コンテナの実行を確認します。

podman container ps

~ % podman container ps


CONTAINER ID  IMAGE                                                        COMMAND     CREATED         STATUS                   PORTS                                                                                             NAMES

8f93728d79ae  container-registry.oracle.com/database/adb-free:latest-23ai              13 minutes ago  Up 13 minutes (healthy)  0.0.0.0:1521->1522/tcp, 0.0.0.0:1522->1522/tcp, 0.0.0.0:8443->8443/tcp, 0.0.0.0:27017->27017/tcp  adb-free

~ % 


手元のブラウザよりATPのAPEXにアクセスします。


自己署名証明書なので、接続にあたって確認を求められます。


警告を無視して接続します。ORDSのランディング・ページが表示されます。

Oracle APEXを実行します。


データベースにインストールされているAPEXは24.2.7ですが、ブラウザには24.2.8の静的リソースが読み込まれていると警告されます。latest-23ai(実際には25.9.3.2-23ai-arm64)の設定が正しくない模様です。x86_64向けの25.9.3.2-23ai-amd64では、データベースにインストールされているAPEXのバージョンは24.2.8なので、この警告は表示されません。


SQL Developer Webより管理者ユーザーADMINでサインインし、設定を修正します。


SQLワークシートより以下のスクリプトを実行し、24.2.7の静的リソースを参照する様に変更します。

exec apex_instance_admin.set_parameter('IMAGE_PREFIX','https://static.oracle.com/cdn/apex/24.2.7/');

タグlatest - 25.10.2.1のx86_64のインスタンスでは、24.2.9の静的リソースを参照するため、以下のスクリプトを実行する必要があります。

exec apex_instance_admin.set_parameter('IMAGE_PREFIX','https://static.oracle.com/cdn/apex/24.2.8/');


APEXの作業に戻ります。

APEXの管理サービスへの接続画面が開きます。言語のセレクタがありません

podman run実行時にADMIN_PASSWORDとして指定したパスワードを入力し、管理サービスにサインインします。


管理サービスにサインインします。

Create Workspaceをクリックします。


New Schemaを選択します。


Workspace NameWorkspace UsernameWorkspace Passwordを設定し、Create Workspaceを実行します。


ワークスペースが作成されます。成功メッセージに含まれるワークスペース名のリンクをクリックして、ワークスペースのサインイン画面を開きます。


ワークスペース管理者のパスワードを入力し、ワークスペースにサインインします。言語リソースがロードされていないため、英語以外の言語の選択がありません。


APEXの開発画面が開きます。ここまで、非常にすばやく開発環境の作成ができています。言語リソースが含まれていないことが残念です。


コンテナadb-freeに接続してみます。

podman exec -it adb-free /bin/bash

~ % podman exec -it adb-free /bin/bash

[oracle@16b9125f5cc5 /]$ 


PDBのMY_ATPに接続します。以下の環境変数を設定します。
export ORACLE_HOME=/u01/app/oracle/product/23.0.0.0/dbhome_1
export ORACLE_SID=POD1
export NLS_LANG=American_America.AL32UTF8
export PATH=$ORACLE_HOME/bin:$PATH
export TNS_ADMIN=/u01/app/oracle/wallets/tls_wallet

[oracle@16b9125f5cc5 /]$ export ORACLE_HOME=/u01/app/oracle/product/23.0.0.0/dbhome_1 

[oracle@16b9125f5cc5 /]$ export ORACLE_SID=POD1

[oracle@16b9125f5cc5 /]$ export NLS_LANG=American_America.AL32UTF8

[oracle@16b9125f5cc5 /]$ export PATH=$ORACLE_HOME/bin:$PATH

[oracle@16b9125f5cc5 /]$ export TNS_ADMIN=/u01/app/oracle/wallets/tls_wallet


ユーザーADMINで接続します。DATABASE_NAMEのデフォルトはMYATPなので、接続先のTNS名としてmyatp_lowを選びます。

sqlplus admin@myatp_low

[oracle@16b9125f5cc5 /]$ sqlplus admin@myatp_low


SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Mon Feb 9 03:42:33 2026

Version 23.9.0.25.08


Copyright (c) 1982, 2025, Oracle.  All rights reserved.


Enter password: ***********

Last Successful login time: Mon Feb 09 2026 03:27:53 +00:00


Connected to:

Oracle Database 23ai Enterprise Edition Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems

Version 23.9.0.25.08


SQL> exit

Disconnected from Oracle Database 23ai Enterprise Edition Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems

Version 23.9.0.25.08

[oracle@16b9125f5cc5 /]$ 


exitで切断します。

[oracle@16b9125f5cc5 /]$ exit

exit

~ % 


コンテナadb-freeを停止します。

podman container stop adb-free

~ % podman container stop adb-free

adb-free

~ % 


仮想マシンを停止します。

podman machine stop

~ % podman machine stop

Machine "podman-machine-default" stopped successfully

~ %


Oracle Autonomous Database Free Container ImageをmacOS上で動かした作業履歴は以上になります。