Google GeminiのAPIを呼び出して、動画について説明してもらいます。説明してもらう動画ファイルはGoogle Cloud Storageにアップロードし、 そのURIをAPIリクエストのfileDataにfileUriとして指定します。APIリクエストにファイルをそのまま埋め込む場合は、inlineDataとしてbase64でエンコーディングした文字列を指定できますが、APIリクエストの最大サイズに制限されます。
Gemini APIでGoogle Cloud Storage上のファイルを扱うには、Vertex AIのGemini APIを呼び出す必要があります。APIの認証はAPIキーではなく、サービス・アカウントによる認証を使います。
以下のGIF動画では、キリンの動画をGoogle Cloud Storageにアップロードし、動画の説明をお願いしています。
作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/google-vertex-gemini.zip
今回の作業で追加、変更した機能は以下になります。
- APIの呼び出しをGoogle AIからVertex AIに変更しています。
- Google Cloud Storageの操作画面を追加しています。操作画面の作成方法は、記事「Google Cloud StorageにCloud Storage JSON APIでアクセスする」にて紹介しています。
- Gemini APIの呼び出しにあたって、Google Cloud Storage上のファイルをリクエストに含めることができるページを作成しています。
- ベクトル埋め込み(embedding)の生成に、Vertex AIのモデルmultimodalembeddingを使うように変更しました。
https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent
Vertex AI Gemini APIのAPIエンドポイントは以下です。(同等のモデルの場合)
https://{REGION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/publishers/google/models/{MODEL_ID}:streamGenerateContent
Vertex AIではgenerateContentではなくstreamGenerateContentを呼び出します。送信するJSONのリクエストの仕様には差異は無さそうですが、streamGenerateContentでは単一の応答の代わりに応答の配列が返されます。
Googleの以下のドキュメントでは、属性candidatesを含みJSONドキュメントが応答として記載されています。
実際には属性candidatesを含むJSONオブジェクトの配列が返されます。
[{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "* **成人式とは?**\n\n 成人式とは、毎年1月1"
}
]
},
"safetyRatings": [
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE"
}
]
}
]
}
,
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "5日に行われる日本の国民的行事で、20歳になった男女を祝"
}
]
},
"safetyRatings": [
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE"
}
]
}
]
}
,
/* この繰り返しなので省略します。 */
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "、日本の伝統的な衣装であり、成人式に振袖を着ることで、成人になったことを祝う意味があります。振袖は、未婚女性の礼装であり、成人式だけでなく、結婚式や卒業式などにも着られます。\n\n\n* **成人式の過ごし方**\n\n 成人式は、20歳になったことを祝うため、友人や家族と食事をしたり、旅行に出かけたりして過ごす人が"
}
]
},
"safetyRatings": [
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE"
}
]
}
]
}
,
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "多いです。また、成人式の前には、成人式の記念写真を撮影したり、成人式の準備をしたりして、成人式を祝う準備をします。"
}
]
},
"finishReason": "STOP",
"safetyRatings": [
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE"
}
]
}
],
"usageMetadata": {
"promptTokenCount": 8,
"candidatesTokenCount": 373,
"totalTokenCount": 381
}
}
]
Googleから提供されているSDKを使ってGemini APIを呼び出していると、低レベルの動作を気にする必要はないのですが、PL/SQLではそうも行きません。GoogleのAPIのドキュメントには、レスポンスのフォーマットについて詳細が記載されていないため、今回の実装ではレスポンスの属性candidatesの配列の要素は1つだけ、属性partsの配列の要素も1つだけ、そして属性textも1つだけ含まれる、という前提でAPIのレスポンスを処理しています。
Gemini APIを呼び出すパッケージをUTL_GOOGLE_GEMINI_APIとして作成しています。これを少し変更してVertex AIのGemini APIを呼び出すようにしたパッケージUTL_VERTEX_AI_GEMINI_APIを作成しました。コードは記事の末尾に添付しています。
APIのエンドポイントをVertex AIに変更し、上記のレスポンスの扱いも変更しているため、同名のプロシージャやファンクションでも引数は異なっています。
以下より、動画のfileUriをAPIのリクエストに含めて、マルチモーダルの問い合わせを行なうページを作成します。
APIエンドポイントを決める際にプロジェクトIDとリージョンの指定が必要になります。そのため、アプリケーション定義の置換に置換文字列としてG_PROJECT_IDとG_REGIONを作成し、値を設定します。
最初にGoogle Cloud Storage上のファイルを選択する際に使用する、共有コンポーネントのLOVを作成します。
作成済みのLOVが一覧されます。作成をクリックします。
LOVの作成は最初からです。
次へ進みます。
次へ進みます。
データ・ソースとしてRESTデータ・ソースを選択します。RESTデータ・ソースはGoogle Cloud Storage JSON APIを選択します。このデータ・ソースは、Google Cloud StorageのファイルをアクセスするページをAPEXアプリケーションに追加する際に作成しています。
次へ進みます。
作成をクリックします。
LOVとしてGOOGLE CLOUD STORAGE FILESが作成されます。
編集するために、リンクをクリックします。
RESTソース・パラメータbucketの鉛筆アイコンをクリックし、bucketの値を指定します。
値タイプは静的、静的値として&G_BUCKET_NAME.を設定します。
変更の適用をクリックします。
追加表示列の列の選択をクリックします。
列NAMEに加えて列CONTENTTYPEも表示されるようにします。
列CONTENTTYPE(Varchar2)を選択し、更新をクリックします。
追加表示列としてCONTENTTYPEが追加されます。
列NAMEは最初から表示列となっていますが、列NAMEは戻り列として設定されているため、ヘッダーに値がありません。また表示可能などもNoとなっています。
列NAMEのヘッダーにNameを設定し、表示可能および検索可能をYesに変更します。
変更の適用をクリックします。
以上でLOVの作成は完了です。
Gemini APIを呼び出すページは、ページ番号3のImageのページをコピーして作成します。
ページの作成をクリックします。
コピーとしてのページの作成をクリックします。
次へ進みます。
コピー元ページとして3. Imageを選択します。新規ページ番号は10、新規ページ名はMovieとします。
ページにブレッドクラムを作るため、ブレッドクラムを選択します。親エントリなし、エントリ名はMovieとします。
次へ進みます。
ナビゲーションのプリファレンスとして新規ナビゲーション・メニュー・エントリの作成を選びます。
新規ナビゲーション・メニュー・エントリはMovie、親ナビゲーション・メニュー・エントリとして- 親が選択されていません -を選択します。
次へ進みます。
コピーをクリックします。
ページがコピーされます。
コンテント・タイプを保持するページ・アイテムを作成します。
識別の名前はP10_CONTENT_TYPE、タイプはテキスト・フィールド、ラベルはContent Typeとします。
デバッグのためにAPIのレスポンスをそのまま表示するページ・アイテムを作成します。
識別の名前はP10_RESPONSE_RAW、タイプはテキスト領域、ラベルはResponse Rawとします。
大きなデータも扱えるように、セッション・ステートのデータ型にCLOBを選択します。
ページ・アイテムP10_IMAGEを選択し、ローカルのコンピュータ上のファイルを選択するページ・アイテムから、Google Cloud Storage上のファイルを選択するページ・アイテムに変更します。
識別の名前をP10_MOVIEに変更します。タイプはポップアップLOVに変更します。ラベルはMovieに変更済みです。
追加出力としてCONTENTTYPE:P10_CONTENT_TYPEを設定します。APIリクエストのfileDataは複数(最大16個まで)にすることができますが、今回の実装では1つだけにしています。複数の値をオンにすると追加出力ができなくなるため、複数のファイルを選択するには列CONTENT_TYPEの値を取る追加の実装が必要になります。
LOVのタイプに共有コンポーネントを選択し、LOVとしてGOOGLE CLOUD STORAGE FILESを選択します。追加値の表示はオフ、NULL表示値として- ファイルを選択 -を設定します。
セッション・ステートのストレージとしてリクエストごと(メモリーのみ)を選択します。理由は不明ですが、セッションごと(永続)の場合エラーが発生しました。
左ペインでプロセス・ビューを開き、プロセス画像を含む呼び出しを選択します。
名前を動画を含む呼び出しに変更し、ソースのPL/SQLコードも以下に入れ替えます。
保存をクリックします。
以上でアプリケーションは完成です。アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。
Googleのドキュメント「マルチモーダル プロンプト リクエストを送信する」を参照すると、色々と考慮しなければいけないことが書かれています。
https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/send-multimodal-prompts
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完
パッケージUTL_VERTEX_AI_GEMINI_APIのコード: