TECH PLAY

株式会社G-gen

株式会社G-gen の技術ブログ

744

G-genの杉村です。 Agent Development Kit (ADK)を使い、社内外のドキュメントやナレッジを検索して、技術的な質問に回答する AI エージェントを開発した事例を紹介します。 はじめに 開発したもの 利用可能ユーザー 動作 ユースケース 技術的な仕様に関する質問 トラブルシューティング 学習リソースの提案 アーキテクチャ マルチエージェント なぜ AI エージェントなのか インフラ構成 Vertex AI Search バッチ処理 ADK 関連記事 はじめに 開発したもの 当記事では、G-gen のサービスとして提供されている G-gen Tech Agent の開発事例を紹介します。G-gen Tech Agent は、Google Cloud や Google Workspace に関する技術的な質問に回答するチャットツールです。バックエンドでは AI エージェントが稼働しており、以下のような情報ソースから情報を取得して、その結果を要約して回答を生成します。 Google Cloud 公式ガイド( https://cloud.google.com/ ) Google Workspace 管理者ヘルプ( https://support.google.com/ ) G-gen Tech Blog( https://blog.g-gen.co.jp/ ) G-gen の技術サポート窓口 G-gen Tech Agent の画面 ユーザーが自然言語による質問を行うと、AI エージェントはこれらのソースに対して、Google Cloud の Vertex AI Search (AI Applications サービスの1機能)という仕組みを使って検索を行います。 参考 : Vertex AI Searchを徹底解説! - G-gen Tech Blog Vertex AI Search の検索結果を、生成 AI モデル Gemini が解釈・要約を行い、ユーザーに対する回答を生成します。 参考 : 全Geminiプロダクトを徹底解説! - G-gen Tech Blog 公式ドキュメントに加え、G-gen の技術ブログや過去のサポートナレッジに基づいて生成が行われるため、高い精度が期待できます。 G-gen Tech Agent では、上記の「Vertex AI Search による複数データソースへの検索」「その結果を要約して最終回答を作成する」という一連の流れを、 Agent Development Kit (ADK)というフレームワークを使って実装しました。 利用可能ユーザー G-gen Tech Agent は、G-gen の Google Cloud / Google Workspace 請求代行サービスの付帯サービスとして顧客に提供されています。「Google Cloud と Google Workspace の両方で請求代行サービスを契約している」などの提供条件があります。 G-gen Tech Agent は、G-gen 独自の AI ソリューションである G-gen Tech Suite の一部として提供されています。G-gen Tech Suite には G-gen Tech Agent の他に、Google Cloud と Google Workspace の最新技術アップデート情報に関する解説を日本語で閲覧できる G-gen Tech Update という Web サービスも付帯しています。 利用条件など、詳細は営業担当者にお問い合わせください。 参考 : 株式会社G-gen、新サービス G-gen Tech Suite を提供開始 参考 : Google Cloud 請求代行 - 株式会社G-gen 参考 : Google Workspace 請求代行 - 株式会社G-gen 請求代行サービスに無料付帯する G-gen Tech Suite 動作 G-gen Tech Agent は、以下のように動作します。 URL にアクセスすると、Google アカウントでの認証画面が表示されます。認証が完了されると、以下のような画面が表示されます。 G-gen Tech Agent の画面 質問を画面下部のテキストボックスに入力し、送信します。マークダウン形式での入力に対応しており、AI に正しく質問内容を伝えるのに役立ちます。 バックエンドでは複数のデータソースに検索を行い、またそれらを要約するため、回答には30秒ほどかかる場合があります。 エージェントが思考中 回答が生成されました。AI エージェントには、前の会話を引き継いで続けて質問することもできます。また、公式ドキュメントや関連ブログ記事リンクなども表示されます。 生成された回答 関連リンクも表示される ユースケース 技術的な仕様に関する質問 「Google ドライブで共有ドライブ間でファイルを移動すると、共有リンクは変わってしまいますか?」 トラブルシューティング 「Vertex AI で Gemini API を呼び出していますが、 429 RESOURCE_EXHAUSTED というエラーが頻発します。どうしたらいいですか?」 学習リソースの提案 「BigQuery を学ぶのに役立つコンテンツを教えてください。」 アーキテクチャ マルチエージェント G-gen Tech Agent は、 マルチエージェント構成 となっています。マルチエージェント構成では、複数の AI エージェントが協働してタスクを遂行します。以下は、エージェント構成を示したものです。 G-gen Tech Agent のマルチエージェント構成 ユーザーが質問を行うとまず、ルートエージェント(root = 根)と呼ばれるエージェントが起動します。このエージェントは SequentialAgent と呼ばれる ADK の Class を用いて構成されています。 SequentialAgent は、複数のエージェントをシーケンシャルに(直列に)実行するものです。このエージェント自体は思考を行わず、単に複数エージェントを直列に実行するワークフローを構成するために存在します。 参考 : ADKのSequential agentsを使って実装するマルチエージェント SequentialAgent の指示に基づき、はじめにデータソース検索エージェントが起動します。このエージェントは ParallelAgent で実装されています。 ParallelAgent も、SequentialAgent と同様に、思考を行わず、複数のエージェントをパラレルに(並列で)実行するためのワークフロー制御を行うエージェントです。この ParallelAgent から呼び出されて、2つのエージェントが同時に起動します。公式ドキュメント検索エージェントと、G-gen ナレッジ検索エージェントです。 これらの検索エージェントは、Tools(エージェントが目的を達成するために使うプログラム群)として Vertex AI Search を用いて、Google の公式ドキュメントや G-gen のナレッジに対して検索を行います。パラレルに実行している理由は、回答までの時間を短縮するためです。 これらの検索ツールに対して検索を行う際、エージェントはユーザーからの質問を適切な検索クエリに変換して検索を実行します。この検索クエリ生成には、LLM の特性である 自然言語の解釈が必須 です。ユーザーからの質問をそのまま検索にかけたのでは、適切な検索結果は得られません。データソースに応じて、技術要素をスペース区切りの単語で検索したり、あるいは技術的な要素だけを抽出した自然な質問文に変換して、Vertex AI Search に対して検索または質問を実行します。 なお、G-gen ナレッジ検索エージェントは補助的な情報源として、Google 検索グラウンディングを有効化した Gemini による生成も用います。G-gen のナレッジだけを基にするのではなく、一般的なインターネット情報を追加の情報源とできるように、いわばサードオピニオンとして追加しています。 Vertex AI Search から検索結果が得られると、最後に最終回答作成エージェントが起動します。生成 AI モデル Gemini を用いて、前のエージェントが見つけ出した検索結果を統合・要約して、質問者の意図に沿う回答を生成します。 なぜ AI エージェントなのか 当システムを実装するにあたり、単純な RAG 構成等ではなく、ADK を使った AI マルチエージェントという実装を選択した理由として、以下が挙げられます。 AI エージェントおよび ADK の実証実験としての意義 複数のデータソースへの検索を統合して要約するというワークフロー的な処理の性質 前者については、当社が Google Cloud 専業インテグレーターであり、今後顧客に AI エージェントの実装を提案するにあたっての実証実験的な意義がありました。ただし、これはシステムの技術選定における本筋ではありません。 後者のほうが重要です。従来型の RAG では、例えば Gemini における実装であれば、API エンドポイントへ生成リクエストを送信するときに Tools として Google 検索ツールを渡し、グラウンディングを指示します。また Vertex AI Search であれば、あるデータソースをグラウンディング先として指定した Vertex AI Search アプリに対して answer メソッドで回答の生成を指示します。 参考 : Grounding with Google Search 参考 : Get answers and follow-ups これらの生成方法だと、「単一の生成リクエストで1つまたは複数のデータソースに対するグラウンディングを行う」ということはできても、「あるデータソースを根拠とした生成リクエスト A と、別のデータソースを根拠とした生成リクエスト B を統合して、複数の根拠や視点に基づいて結果を生成する」といったことはできません。実際に Vertex AI Search の Blended Search(複数のデータソースに対してグラウンディングを行う機能)を使って Google Cloud の技術に関する質問に回答させたところ、関連度が高いと判断された一部のデータソースに基づいて回答が生成されてしまい、AI エージェント構成とした場合よりも精度が低いものとなりました。 G-gen Tech Agent のユースケースでは、AI エージェントが複数の生成結果を統合することにより精度が高まったため、単純な RAG 構成よりも適切と判断されました。 インフラ構成 G-gen Tech Agent は Web サービスであり、ホストするためにサーバーが必要です。G-gen Tech Agent は、サーバーレスなプラットフォームである Cloud Run にホストされています。 AI エージェントのホスト先として、Google Cloud では他に Vertex AI Agent Engine が挙げられます。今回は、エージェントを Web 経由だけでなく社内の Slack 経由でも呼び出すなどの将来的な拡張性を見込み、より小回りの効く Cloud Run を採用しました(Agent Engine でも同様のことは実現できます。追加の採用理由として、類似の社内ツールが以前 Cloud Run で実装されていたため、このアセットを流用したという背景もあります)。 参考 : Agent Development Kitでエージェントを開発してAgent Engineにデプロイしてみた 構成図は、以下のとおりです。 インフラ構成図 すべての要素はサーバーレスで実装されています。利用した Google Cloud サービスは以下のとおりです。 Cloud Run(フロントエンド・バックエンド) Vertex AI(生成 AI モデル Gemini の API) AI Applications - Vertex AI Search(データソースに対する検索) Vertex AI Search 当システムでは、Vertex AI Search を使ってデータソースに対する検索を行っています。 G-gen が保有する Web サイトである G-gen Tech Blog に対しては、高度なインデックス登録(Advanced index)が有効化できます。これを行うことで、ウェブサイトに対して単なる単語検索ではなく、自然言語でクエリすると自然言語によって回答が返ってくる answer メソッド が利用可能になります。 参考 : 高度な機能について - ウェブサイトの高度なインデックス登録 参考 : Vertex AI Searchを徹底解説! - G-gen Tech Blog - Web データストア 一方で、Google の公式ドキュメントは G-gen が保有するものではないため、高度なインデックス登録に必須なドメイン認証を行うことができません。そのため通常のウェブサイト検索となり、検索には search メソッド を使っています。投げかける検索クエリはスペース区切りの単語としています。 また、過去サポートケースに基づいた FAQ に対しても、Vertex AI Search の answer メソッドを使っています。データストアは BigQuery に格納された構造化データです。 このようにデータソースに応じて適切な検索クエリが異なりますが、生成 AI により、適切な検索クエリを生成させています。 バッチ処理 G-gen の過去サポートケースについては、過去の顧客とのやりとりを直接的に検索させているわけではありません。日次のバッチ処理で顧客とのやりとりの情報を要約して FAQ 化し、BigQuery に格納したうえで、Vertex AI Search のデータストア化しています。 また FAQ には純粋な技術的な情報のみが含まれており、顧客固有の情報や機密情報、個人情報が入りこまないよう、検知と処理、人間の目によるチェックを行っています。さらに、バッチ処理時やフロントエンド側のシステムプロンプトでも、そういった情報が回答に入りこまないように LLM に指示されており、この対策は信頼度が絶対といえないまでも多層的な対策の一環を担っています。 過去のサポートケースを FAQ 化するための日次のバッチ処理でも、Gemini モデルが使われています。 バッチ処理構成図 ADK 関連記事 以下は、最近の ADK に関する関連記事です。開発にあたり、参考にしてください。 blog.g-gen.co.jp blog.g-gen.co.jp blog.g-gen.co.jp blog.g-gen.co.jp 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の杉村です。2025年7月のイチオシ Google Cloud(旧称 GCP)アップデートをまとめてご紹介します。記載は全て、記事公開当時のものですのでご留意ください。 はじめに 組織のポリシーの Policy Simulator が Preview -> GA Cloud SQL for MySQL/PostgreSQL で書き込みエンドポイントが GA Google Workspace の Gemini 関連の監査ログが強化 Gemini サイドパネルで、Gems が利用可能に Cloud Storage でバケット IP フィルタリングが Preview → GA Vertex AI Search で文字列の完全一致検索が可能に Google Meet のライブストリーミングで参加者がチャット送信可能に Google Drive Events API が Preview 公開 BigQuery でデフォルトの SQL が LegacySQL → GoogleSQL に変更 Vertex AI Agent Engine で Memory Bank が登場(Preview) Gmail に 「サブスクリプションを管理」画面が登場 SCC に Notebook Security Scanner が登場(Preview) Gemini アプリでVeo 3 による動画生成が可能に(一部ユーザーのみ) Vertex AI Search の回答生成モデルで Gemini 2.5 Flash が利用可能 SharePoint から Google ドライブへの移行ツールが Beta → GA Google Cloud Marketplace の自社データ販売機能が Preview → GA Google カレンダーのアポイント予約をメールに直接組み込めるように AppSheet Enterprise Plus エディションで AI Tasks が Preview -> GA Looker Studio レポートで Short query optimized mode が利用可能に BigQueryのパイプ構文が拡張 IAM 編集画面で Gemini による最小権限ロールの提案(Preview) Gemini 2.5 Flash-Lite が Preview → GA(一般公開) Google Maps グラウンディングが米国以外でも利用可能に(Preview) Looker で BigQuery への Optional job creation mode が使われるように Looker Studio レポートに Description(説明欄)が追加できるように Cloud Monitoring の1機能として Cost Explorer が Preview 公開 Code Interpreter が Looker と Looker Studio Pro で 試験運用版 →Preview Vertex AI と Model Armor が統合 (Preview) Gemini for Google Cloud API が BigQuery プロジェクトで自動で有効化 NotebookLM に「動画概要」機能が登場 はじめに 当記事では、毎月の Google Cloud(旧称 GCP)や Google Workspace(旧称 GSuite)のアップデートのうち、特に重要なものをまとめます。 また当記事は、Google Cloud に関するある程度の知識を前提に記載されています。前提知識を得るには、ぜひ以下の記事もご参照ください。 blog.g-gen.co.jp リンク先の公式ガイドは、英語版で表示しないと最新情報が反映されていない場合がありますためご注意ください。 組織のポリシーの Policy Simulator が Preview -> GA Test organization policy changes with Policy Simulator (2025-07-01) 組織のポリシーの Policy Simulator が Preview -> GA。 組織ポリシーの影響を事前にシミュレーションできる。「マネージド制約」や「カスタム制約」 のみで利用可能。通常の従来型の制約では利用できないので注意。 Cloud SQL for MySQL/PostgreSQL で書き込みエンドポイントが GA Cloud SQL for PostgreSQL release notes - July 01, 2025 (2025-07-01) Cloud SQL for MySQL/PostgreSQL で書き込みエンドポイントが Preview → GA。 Enterprise Plus Edition でのみ利用可。プライマリインスタンスのプライベート IP を指す DNS 名。インスタンスがフェイルオーバーしてもアプリ側で向き先を変える必要がない。 Google Workspace の Gemini 関連の監査ログが強化 Access Gemini Audit logs using the Reporting API, the security and audit investigation tools (2025-07-01) Google Workspace の Gemini 関連の監査ログが強化。 Drive、Gmail、Docs 上の Gemini アクションを記録。Security Investigation Tool で閲覧可能なほか、Reporting API で取得可能。 Gemini サイドパネルで、Gems が利用可能に Gems are now available in the side panel of Google Workspace apps (2025-07-02) Gemini サイドパネルで、Gems が利用可能になる。 Gems は事前にカスタムプロンプトを登録しておける機能。これまで Gemini アプリだけで使えたが、今後は Google Drive、Docs、Sheets、Slides、Gmail でも使えるようになる。順次ロールアウト。 Cloud Storage でバケット IP フィルタリングが Preview → GA Bucket IP filtering (2025-07-02) Cloud Storage でバケット IP フィルタリングが Preview → GA。 バケット単位で接続元 IP アドレスや接続元 VPC ネットワークを制限できる。BigQuery へのロードなどの機能が使用できなくなることに注意が必要。 Vertex AI Search で文字列の完全一致検索が可能に AI Applications release notes - July 02, 2025 (2025-07-02) Vertex AI Search で文字列の完全一致検索が可能に。 検索時に文字列をダブルクォーテーション( " )で囲うと、文字列完全一致での検索が可能になる。固有名詞や厳密な検索が必要なときに使える。 Google Meet のライブストリーミングで参加者がチャット送信可能に Live stream viewers can now send chat messages, plus additional host controls (2025-07-02) Google Meet のライブストリーミングで参加者がチャット送信可能になった。 管理設定で閲覧者が「チャット送信」「チャット閲覧」できるかどうかを設定できる(デフォルトはいずれも許可)。 Google Drive Events API が Preview 公開 Google Drive Events API now available in Developer Public Preview (2025-07-07) Google Drive Events API が Preview 公開。 Google ドライブのファイル変更通知を Pub/Sub で受け取る等が可能に。従来も notification channel 作成は可能だったが、今回発表の新 API は Google Workspace Events API と統合されており、イベント形式が CloudEvent 形式になっている。より Pub/Sub、Cloud Run 等と統合がしやすくなった。 BigQuery でデフォルトの SQL が LegacySQL → GoogleSQL に変更 BigQuery release notes - July 08, 2025 (2025-07-08) BigQuery で CLI/API のデフォルト SQL が LegacySQL → GoogleSQL に変更(2025-08-01から)。 古くから CLI/API で LegacySQL を実行している場合、引き続き LegacySQL を使うには明示的に設定が必要。管理者には以前からメールで通知されていた。G-gen からもお知らせメールを配信済み。 Vertex AI Agent Engine で Memory Bank が登場(Preview) Vertex AI Agent Engine Memory Bank overview (2025-07-08) Vertex AI Agent Engine で Memory Bank が登場(Preview)。 ユーザーと AI エージェントの会話を長期的に保管するストレージ。長期記憶のために DB を外部に作成する必要がなくなる。 短期記憶 → Session 管理 長期記憶 → Memory Bank Gmail に 「サブスクリプションを管理」画面が登場 Manage email subscriptions from a single location in Gmail (2025-07-08) Gmail で、メルマガ登録等のサブスクリプションを「サブスクリプションを管理」の1画面でまとめて管理(購読解除)できるようになる。順次ロールアウトされまもなく Web、iOS、Android アプリで使用可能になる。 SCC に Notebook Security Scanner が登場(Preview) Notebook Security Scanner (2025-07-11) Security Command Center の Premium/Enterprise ティアに Notebook Security Scanner が登場(Preview)。 Colab Enterprise ノートブック内で使われている Python パッケージを24時間ごとにスキャンして脆弱性を検知。現在は US と EU の一部リージョンのみ対応。 Gemini アプリでVeo 3 による動画生成が可能に(一部ユーザーのみ) Google Workspace Updates Weekly Recap - July 11, 2025 (2025-07-11) 一部の Google Workspace ユーザー(for select Workspace customers)の Gemini アプリで Veo 3 による動画生成が可能になった。 音声付きの8秒間の動画を、1日3回生成できる。写真から動画生成も可能。 Vertex AI Search の回答生成モデルで Gemini 2.5 Flash が利用可能 AI Applications release notes - June 26, 2025 (2025-06-26) Vertex AI Search の回答生成時のモデルに、Gemini 2.5 Flash が選択できるようになった。 これまでの最新は Gemini 2.0 Flash。コンテキストを意識した回答の生成で精度が向上する見込み。 SharePoint から Google ドライブへの移行ツールが Beta → GA Now Generally Available: Migrate files from Microsoft SharePoint Online to Google Drive (2025-07-14) SharePoint から Google ドライブへの移行ツールが Beta → 一般提供(GA)。 Workspace 管理画面組み込みのツール。ドキュメントライブラリ、フォルダ、ファイル、権限を移行可能。新規追加・更新されたファイルの差分転送も可能。 Google Cloud Marketplace の自社データ販売機能が Preview → GA Commercialize listings on Google Cloud Marketplace (2025-07-15) BigQuery sharing(旧 Analytics Hub)を使い Google Cloud Marketplace で自社データを販売する機能が Preview → GA。 自社保有データの収益化が容易になる。ただし規約上、まだ日本国内企業が対象になっていないため、日本企業はまだ利用できない。 Google カレンダーのアポイント予約をメールに直接組み込めるように Link your Google Calendar booking pages when composing emails in Gmail (2025-07-15) Google カレンダーのアポイント予約(apointment booking)を Gmail のメールに直接組み込めるように。順次ロールアウト。 AppSheet Enterprise Plus エディションで AI Tasks が Preview -> GA Now generally available: extract and categorize data in AppSheet with the power of Gemini (2025-07-16) AppSheet の Enterprise Plus エディションで使える AI Tasks が Preview -> GA(一般提供)。 Gemini が、写真や PDF からのデータ抽出や分類を Automation 内で自動的に行う。つまり、ノーコードで生成 AI アプリが簡単に作れる。 Looker Studio レポートで Short query optimized mode が利用可能に Looker Studio release notes - July 17, 2025 (2025-07-17) Looker Studio レポート(BigQuery データソース)で Short query optimized mode(Optional job creation mode)がサポート。 小規模クエリが高速化する可能性あり。データソースが「閲覧者の認証情報」を使っているなど特定条件でのみ適用される。 BigQuery の Optional job creation mode(オプションのジョブ作成モード)については以下も参照。 blog.g-gen.co.jp BigQueryのパイプ構文が拡張 BigQuery release notes - July 17, 2025 (2025-07-17) BigQueryのパイプ構文が拡張。以下の構文が利用可能になった。 WITH 使い回せるテーブル表現を定義 named windows ウインドウ関数と似ており結果の各行で共通して表示する集計を定義 DISTINCT 一意にレコードを抽出 IAM 編集画面で Gemini による最小権限ロールの提案(Preview) Get predefined role suggestions with Gemini assistance (2025-07-21) IAM 権限編集画面で Gemini による最小権限ロールの提案が使用可能になった(Preview)。 自然言語による質問で適切なロールを提案。ただしコンソールの言語を英語版にしないと使えない。 Gemini 2.5 Flash-Lite が Preview → GA(一般公開) Gemini 2.5 Flash-Lite (2025-07-22) Gemini 2.5 Flash-Lite が Preview → GA(一般公開)。 Gemini 2.5 Flash より軽量・高速・安価なモデル。バッチ推論にも対応。Vertex AI と Google AI Studio の両方で GA 版が利用可能。 Google Maps グラウンディングが米国以外でも利用可能に(Preview) Grounding with Google Maps in Vertex AI (2025-07-23) Gemini の Google Maps を使ったグラウンディングが米国以外でも利用可能に(Preview)。 これまで米国ユーザーのみプレビュー可能だった。Vertex AI 経由の Gemini 呼び出しで使える。 Looker で BigQuery への Optional job creation mode が使われるように Looker release notes - July 24, 2025 (2025-07-24) Looker Studio に続いて Looker でも、BigQuery に対する Optional job creation mode( Short query optimized mode)が使われるようになった。 小規模クエリがより短時間で返る可能性がある。 BigQuery の Optional job creation mode(オプションのジョブ作成モード)については以下も参照。 blog.g-gen.co.jp Looker Studio レポートに Description(説明欄)が追加できるように Looker Studio release notes - July 24, 2025 (2025-07-24) Looker Studio レポートに Description(説明欄)が追加できるようになった。 テキストで説明を付記できる。レポート検索時にも検索対象になる。 Cloud Monitoring の1機能として Cost Explorer が Preview 公開 Optimize costs with the Cost Explorer (2025-07-24) Cloud Monitoring の1機能として Cost Explorer が Preview 公開。 対応プロダクト(主に Compute 系)のコストを分析してダッシュボード表示してくれる。 Code Interpreter が Looker と Looker Studio Pro で 試験運用版 →Preview Conversational Analytics Code Interpreter (2025-07-25) 試験運用版だった Code Interpreter in Conversational Analytics が Looker と Looker Studio Pro で Preview 公開され全ユーザー利用可能になった。 データソースに対する、より高度な分析が自然言語で可能になる。 通常の Conversational Analytics => 自然言語を SQL に変換 Code Interpreter in Conversational Analytics => 自然言語を Python に変換 Vertex AI と Model Armor が統合 (Preview) Model Armor integration with Vertex AI (2025-07-29) Vertex AI と Model Armor が統合(Preview)。 最小限のソースコード変更で、Gemini へのリクエストとそのレスポンスを検査できる。プレビュー期間中は無料。 現時点で us-central1、us-east4、us-west1、europe-west4 の API エンドポイントにのみ対応している。 Model Armor と、上記の使い方については以下の記事に追記した。 blog.g-gen.co.jp Gemini for Google Cloud API が BigQuery プロジェクトで自動で有効化 BigQuery release notes - July 30, 2025 (2025-07-30) Gemini for Google Cloud API が BigQuery 使用中のプロジェクトで自動的に有効化される。 数ヶ月前から Google より管理者へ一斉通知があった通り。Gemini in BigQuery の SQL 生成・補完やデータキャンバスなどが無料で使用可能。 NotebookLM に「動画概要」機能が登場 Introducing Video Overviews and upgrades to the Studio panel in NotebookLM (2025-07-30) NotebookLM に「動画概要」機能が登場。 データソースに基づいて、解説動画を生成する。現在の対応言語は英語のみだが、今後は拡張予定。 2025 年 8 月 4 日の週に 100% ロールアウト完了予定。 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の min です。Looker Studio の機能である 計算フィールド について、その概要から具体的な使い方、トラブルシューティングを解説します。 計算フィールドとは 計算フィールドの種類 計算フィールドの作成方法 データソースの計算フィールドを作成する レポート固有の計算フィールドを作成する 関数 関数とは CASE 文の使い方 トラブルシューティング 構文エラー データ型の不一致 集計エラー 計算フィールドとは Looker Studio における 計算フィールド とは、データソースに元々存在するフィールドを基に、関数や数式を用いて新しいディメンションや指標を作成する機能です。 例えば、データソースに「売上」と「費用」の指標がある場合、これらを使って 売上 - 費用 という数式で「利益」という新しい指標を作成できます。また、「姓」と「名」のディメンションを結合して「氏名」という新しいディメンションを作成することも可能です。 このように、計算フィールドを利用することで、元のデータを加工したり、複数のフィールドを組み合わせたりして、レポートで表現したい形にデータを整形できます。可視化の幅を広げるために非常に重要な機能です。 参考 : 計算フィールドについて 計算フィールドの種類 計算フィールドには、作成する場所によって2つの種類があります。それぞれの特徴を理解し、用途に応じて使い分けることが大切です。 種類 説明 メリット デメリット データソースの計算フィールド データソースの編集画面で作成するフィールド。 そのデータソースを使用する全てのレポートで再利用できる。一貫性が保たれる。 作成・編集にはデータソースの編集者の権限が必要。 レポート固有の計算フィールド レポート内の特定のグラフ(表やスコアカードなど)に対して作成するフィールド。 レポートの編集者の権限があれば作成できる。特定のグラフでのみ使用する一時的な計算に便利。 他のグラフやレポートで再利用できない。同じ計算を複数のグラフで使う場合は都度作成が必要。 基本的には、複数のレポートやグラフで汎用的に使用するフィールドは データソースの計算フィールド として作成し、特定のグラフでのみ一時的に必要な計算は レポート固有の計算フィールド として作成するとよいでしょう。 計算フィールドの作成方法 データソースの計算フィールドを作成する Looker Studio のレポート編集画面で、メニューから「リソース」>「追加済みのデータソースの管理」を選択します。 計算フィールドを追加したいデータソースの「編集」をクリックします。 データソースのフィールド一覧画面の右上にある「フィールドを追加」>「計算フィールドを追加」をクリックします。 フィールドエディタが開きます。「フィールド名」を入力し、「計算式」の欄に数式を入力します。 右下の「保存」をクリックして完了です。作成したフィールドは、このデータソースを使用する全てのレポートで利用できます。 レポート固有の計算フィールドを作成する レポート編集画面で、計算フィールドを追加したいグラフ(表、スコアカードなど)を選択します。 画面右側のプロパティパネルで、「ディメンション」または「指標」セクションの下部にある「 ディメンションを追加 」または「 指標を追加 」をクリックします。 表示されたメニューから「 計算フィールドを追加 」を選択します。 フィールドエディタが開きます。「表示名」を入力し、「数式」の欄に数式を入力します。 データ型を選択し、「適用」をクリックします。作成したフィールドは、選択したグラフでのみ利用できます。 参考 : グラフ固有の計算フィールドの制約 関数 関数とは 計算フィールドでは、単純な四則演算( + , - , * , / )だけでなく、 関数 を利用することでより高度なデータ操作ができます。 関数はカテゴリごとに分類されています。以下に代表的な関数を紹介します。 カテゴリ 代表的な関数 説明 集計 SUM , AVG , COUNT , COUNT_DISTINCT 指標の合計、平均、個数、ユニークな値の個数を計算する。 算術 POWER , ROUND べき乗や四捨五入などの算術計算を行う。 日付 TODAY , YEAR , DATE_DIFF , DATETIME_TRUNC 今日の日付の取得、年から年の抽出、日付の差分計算、日付の切り捨てなどを行う。 テキスト CONCAT , LENGTH , LOWER , UPPER , SUBSTR , REGEXP_MATCH 文字列の結合、長さの取得、大文字・小文字変換、部分文字列の抽出、正規表現による一致判定などを行う。 条件分岐 CASE , IF 条件に応じて返す値を変更する。 全ての関数の一覧は、以下の公式ドキュメントを参照してください。 参考 : 関数リスト CASE 文の使い方 特に使用頻度が高いのが、条件分岐を行う CASE 文です。 CASE 文を使うと、フィールドの値に応じて新しい値を割り当てることができます。 構文は以下の通りです。 CASE WHEN 条件 1 THEN 結果 1 WHEN 条件 2 THEN 結果 2 ELSE その他の結果 END 例えば、「国コード」フィールド( JP , US など)を基に「国名」フィールド( 日本 , アメリカ など)を作成する場合は、以下のように記述します。 CASE WHEN Country_Code = " JP " THEN " 日本 " WHEN Country_Code = " US " THEN " アメリカ " WHEN Country_Code = " KR " THEN " 韓国 " ELSE " その他 " END また、正規表現関数と組み合わせることで、より柔軟な条件設定が可能です。 CASE WHEN REGEXP_MATCH(店舗名, " .*駅前.* " ) THEN " 駅前店舗 " WHEN REGEXP_MATCH(店舗名, " .*SC.* " ) THEN " SC内店舗 " ELSE " その他の店舗 " END トラブルシューティング 計算フィールドの作成時によく発生するエラーとその対処法を解説します。 構文エラー 関数名のスペルが間違っている 、 括弧が閉じていない といった単純な文法ミスです。 計算フィールドのエディタは、エラーがある箇所を赤くハイライトしてエラーメッセージを表示してくれます。メッセージをよく読み、数式を修正してください。 データ型の不一致 テキスト型のフィールドと数値型のフィールドを足し算しようとする など、異なるデータ型のフィールド間で不適切な演算を行うとエラーになります。 この場合、 CAST 関数を使ってデータ型を明示的に変換する必要があります。例えば、テキストとして保存されている数値を数値型に変換するには CAST(フィールド名 AS NUMBER) のように記述します。 集計エラー 「集計指標と非集計ディメンションを混在させることはできません」というエラーは、計算フィールドの作成時に頻繁に発生するエラーの一つです。 これは、 集計済みの値 と 未集計の値 を一つの数式内で混ぜて使おうとしたときに発生します。Looker Studio の指標は、グラフに表示される際に行単位のデータが SUM や AVG などで 集計 されてから表示されます。 例えば、以下のような店舗ごとの商品単価データがあるとします。 店舗名 商品名 単価 渋谷店 商品A 1,000 新宿店 商品A 1,200 池袋店 商品A 900 このデータを使って「渋谷店の単価が、全店舗の単価の合計に占める割合」を計算したいとします。 ここで、以下のような誤った数式を入力したとします。 // 誤った例 ( CASE WHEN 店舗名 = " 渋谷店 " THEN 単価 ELSE 0 END ) / SUM (単価) この数式がエラーになる原因は、分子と分母で値の集計レベルが異なるためです。 分母の SUM(単価) は 集計済みの値 です。これは、表全体の単価を合計した 1000 + 1200 + 900 = 3100 という単一の数値を返します。 一方、分子の (CASE WHEN 店舗名 = "渋谷店" THEN 単価 ELSE 0 END) は 未集計の値 です。この部分は行ごとに評価されるため、結果は 1000, 0, 0 という複数の数値の集まりになります。 この数式は、「行ごとの複数の値( 1000, 0, 0 )を、全体で一つしかない値 3100 で割る」という計算を意味します。Looker Studioはどの値を割れば良いか判断できないため、エラーを返します。 このエラーを解決するには、分子も分母と同じように集計済みの値にする必要があります。 // 正しい例 SUM ( CASE WHEN 店舗名 = " 渋谷店 " THEN 単価 ELSE 0 END ) / SUM (単価) この数式では、分子と分母の両方が集計済みの単一の値になるため、計算できます。 分子は SUM(CASE ...) によって SUM(1000, 0, 0) が計算され、 1000 という単一の値になります。 分母は SUM(単価) によって 3100 という単一の値になります。 1000 / 3100 という明確な計算となり、正しく割合が返されます。 どのタイミングで集計が必要かを理解することが、このエラーを回避する鍵となります。 参考 : 計算フィールドのトラブルシューティング 佐々木 愛美 (min) (記事一覧) クラウドソリューション部 データアナリティクス課。2024年7月 G-gen にジョイン。G-gen 最南端、沖縄県在住。最近覚えた島言葉は、「マヤー(猫)」。
アバター
G-gen の杉村です。人間からの自然言語での質問に基づいて BigQuery にクエリを実行する AI エージェントを、 Agent Development Kit (ADK)で開発する方法を紹介します。 概要 Agent Development Kit(ADK)とは BigQuery ツールセット 実装 ソースコード エージェント定義と非同期実行 BigQuery ツールの定義 BigQuery を使うエージェントの定義 動作確認 最終回答 エージェントとツールの挙動 精度確認 質問のしかたを変える 複雑な質問 会話型分析(参考情報) 概要 Agent Development Kit(ADK)とは Agent Development Kit (ADK)は、AI エージェントの開発、デプロイ、評価を効率化するために Google が開発したオープンソースのフレームワークです。2025年7月現在、Python および Java 向けのライブラリとして公開されています。 ADK を利用することで、AI エージェントを容易に開発できます。また、ADK に組み込みの Built-in tools を使うことで、最小限のコーディングでエージェントに様々なタスクを行わせることができます。当記事では、Built-in tools の1つである BigQuery ツールセットを使って、人間からの自然言語での質問に応じて BigQuery テーブルにクエリを行うエージェントを開発する方法を紹介します。 参考 : Agent Development Kit 参考 : Built-in tools BigQuery ツールセット BigQuery ツールセット は、ADK の組み込みツールセットです。最小限のコーディングで、AI エージェントがユーザーの質問に応じたクエリを自動的に生成し、結果を得て、それに応じた回答を生成します。このツールセットには、以下のようなツールが含まれています。 ツール名 説明 list_dataset_ids プロジェクト内の BigQuery データセットをリストアップする get_dataset_info BigQuery データセットの情報を取得する list_table_ids BigQuery データセット内のテーブル ID をリストアップする get_table_info BigQuery テーブルのメタデータ(スキーマや Description)を取得する execute_sql BigQuery にクエリ(SQL)を実行する 参考 : Built-in tools - BigQuery 上記のツールを使うことで、エージェントは BigQuery に対する一通りの操作が可能です。これらのツールを使うことにより、以下のようなユーザーの質問に対して、AI エージェントが自律的に情報を取得することができます。 「BigQuery テーブル `〇〇.〇〇.〇〇` から xxx を取得して xxx のように集計して」 「BigQuery データセット `〇〇.〇〇` から xxx の情報を探し出して」 「プロジェクト 〇〇 の BigQuery から xxx の情報を取得して教えてください」 実装 ソースコード サンプルとして以下のソースコードを用意しました。 import asyncio import logging from google.adk.agents import LlmAgent from google.adk.runners import Runner from google.adk.sessions import InMemorySessionService from google.adk.tools.bigquery import BigQueryCredentialsConfig from google.adk.tools.bigquery import BigQueryToolset from google.adk.tools.bigquery.config import BigQueryToolConfig from google.adk.tools.bigquery.config import WriteMode from google.genai import types import google.auth # 書き込みオペレーションが実行されるのを防ぐ tool_config = BigQueryToolConfig(write_mode=WriteMode.BLOCKED) # BigQuery への認証(Application Default Credentials) application_default_credentials, _ = google.auth.default() credentials_config = BigQueryCredentialsConfig( credentials=application_default_credentials ) # BigQuery ツールセットを定義 bigquery_toolset = BigQueryToolset( credentials_config=credentials_config, bigquery_tool_config=tool_config ) # BigQuery のジョブ実行プロジェクト ID(課金先) PROJECT_ID= "my-project" # BigQuery を使うエージェント bigquery_agent = LlmAgent( model= "gemini-2.5-flash" , name= "bigquery_agent" , instruction=f """ あなたは BigQuery のデータ分析をするエージェントです。 tools である `bigquery_toolset` を使って SQL を実行し、データを取得・分析してユーザーからの質問に回答を生成します。 BigQuery ジョブはプロジェクト ID `{PROJECT_ID}` で実行します。 """ , tools=[bigquery_toolset], ) # runner の定義 APP_NAME = "My Agent App" SESSION_SERVICE = InMemorySessionService() RUNNER = Runner( agent=bigquery_agent, app_name=APP_NAME, session_service=SESSION_SERVICE, ) async def stream_agent_events (query: str , user_id: str , session_id: str ): ''' # 概要 エージェントを実行します。 # 引数 query (str): エージェントに投げかけるクエリ(プロンプト) user_id (str): ユーザー ID session_id (str): セッション ID ''' # 既存セッションがなければ新規作成 session = await SESSION_SERVICE.get_session(app_name=APP_NAME, user_id=user_id, session_id=session_id) if not session: await SESSION_SERVICE.create_session(app_name=APP_NAME, user_id=user_id, session_id=session_id) # ユーザークエリを所定の形式で格納 content = types.Content(role= 'user' , parts=[types.Part(text=query)]) # エージェントの実行 async for event in RUNNER.run_async(user_id=user_id, session_id=session_id, new_message=content): parts = event.content.parts message = event.content.parts[ 0 ].text if message: yield (f "--- Message: {message}" ) return async def main (): """ エージェントを実行し、ストリーミングされたメッセージを出力するメイン関数 """ user_id= "test_user" session_id= "test_session" query= "BigQuery テーブル `bigquery-public-data.samples.shakespeare` から、シェイクスピア作品で頻出の単語のトップ10を教えてください。" # async for を使って非同期ジェネレータを処理 async for message in stream_agent_events(query=query, user_id=user_id, session_id=session_id): print (message) # ロギングを設定 logging.basicConfig( level=logging.DEBUG, format = '%(asctime)s - %(levelname)s - %(name)s - %(message)s' ) # スクリプトのエントリーポイント if __name__ == "__main__" : asyncio.run(main()) エージェント定義と非同期実行 エージェントの定義( LlmAgent() )やそれに対する非同期実行( run_async() 等)については、以下の記事を参照してください。 blog.g-gen.co.jp BigQuery ツールの定義 当サンプルコードでは、ADK の組み込みツールである BigQuery ツールを以下のように定義しています。 # 書き込みオペレーションが実行されるのを防ぐ tool_config = BigQueryToolConfig(write_mode=WriteMode.BLOCKED) # BigQuery への認証(Application Default Credentials) application_default_credentials, _ = google.auth.default() credentials_config = BigQueryCredentialsConfig( credentials=application_default_credentials ) # BigQuery ツールセットを定義 bigquery_toolset = BigQueryToolset( credentials_config=credentials_config, bigquery_tool_config=tool_config ) tool_config で BigQueryToolConfig(write_mode=WriteMode.BLOCKED) とすることで、BigQuery に誤って書き込みオペレーションが実行されてしまうことを防ぎます。 認証については、 google.auth.default() により、Application Default Credentials を取得しています。これは、実行環境が Cloud Run や Vertex AI Agent Engine であれば環境にアタッチされたサービスアカウントを参照し、ローカルの実行環境であれば gcloud auth application-default login で設定された Google アカウントの認証情報等を参照します。 参考 : gcloud auth loginとgcloud auth application-default loginの違いとは? - G-gen Tech Blog また BigQueryToolset() により、書き込みブロックの設定や認証情報を指定して、BigQuery ツールを定義します。 BigQuery を使うエージェントの定義 ツールとして BigQuery を使うエージェントの定義は、以下のようになっています。 # BigQuery のジョブ実行プロジェクト ID(課金先) PROJECT_ID= "my-project" # BigQuery を使うエージェント bigquery_agent = LlmAgent( model= "gemini-2.5-flash" , name= "bigquery_agent" , instruction=f """ あなたは BigQuery のデータ分析をするエージェントです。 tools である `bigquery_toolset` を使って SQL を実行し、データを取得・分析してユーザーからの質問に回答を生成します。 BigQuery ジョブはプロジェクト ID `{PROJECT_ID}` で実行します。 """ , tools=[bigquery_toolset], ) ここでは定義した bigquery_toolset を tools として指定するだけで、エージェントが BigQuery ツールセットを使用するようになります。また instruction にて、「BigQuery ジョブはプロジェクト ID `{PROJECT_ID}` で実行します。」と指示しています(Python の f-strings により {PROJECT_ID} は実際のプロジェクト ID に置き換わります)。 検証時は、この指示を入れない場合だと、ユーザーのプロンプトで BigQuery データセット bigquery-public-data.samples.shakespeare からデータを取ってきてください のように指定されたとき、エージェントはパブリックデータセットのプロジェクトに対してジョブを実行しようとしてしまい、権限不足でクエリが失敗しました。 なお検証では、認証時に google.auth.default(quota_project_id=PROJECT_ID) のようにクォータプロジェクト(課金先プロジェクト)を指定しても、同様の挙動でした。 BigQuery のジョブ実行権限についての解説は、以下の記事も参考にしてください。 blog.g-gen.co.jp 動作確認 最終回答 上記のソースコードを実行した結果、以下のような最終回答が得られました。 クエリ BigQuery テーブル bigquery-public-data.samples.shakespeare から、シェイクスピア作品で頻出の単語のトップ10を教えてください。 最終回答 --- Message: はい、BigQuery テーブル `bigquery-public-data.samples.shakespeare` から、シェイクスピア作品で頻出の単語トップ10は以下の通りです。 1. the: 25568回 2. I: 21028回 3. and: 19649回 4. to: 17361回 5. of: 16438回 6. a: 13409回 7. you: 12527回 8. my: 11291回 9. in: 10589回 エージェントとツールの挙動 ロギング設定(ログレベルが DEBUG)により、エージェントがツールを使う挙動が標準出力に出力されます。この出力を確認することで、エージェントがどのように思考し、ツールを使用したのかを確認できます。出力の一部を抜粋すると、以下のとおりでした。 Function calls: name: list_table_ids, args: { 'project_id' : 'bigquery-public-data' , 'dataset_id' : 'samples' } Function calls: name: get_table_info, args: { 'table_id' : 'shakespeare' , 'dataset_id' : 'samples' , 'project_id' : 'bigquery-public-data' } Function calls: name: execute_sql, args: { 'project_id' : my-project, 'query' : 'SELECT word, SUM(word_count) AS total_count FROM `bigquery-public-data.samples.shakespeare` GROUP BY word ORDER BY total_count DESC LIMIT 10' } Contents: { "parts" :[{ "text" : "BigQuery テーブル `bigquery-public-data.samples.shakespeare` から、シェイクスピア作品で頻出の単語のトップ10を教えてください。" }], "role" : "user" } { "parts" :[{ "function_call" :{ "args" :{ "project_id" : "bigquery-public-data" , "dataset_id" : "samples" }, "name" : "list_table_ids" }}], "role" : "model" } { "parts" :[{ "function_response" :{ "name" : "list_table_ids" , "response" :{ "result" :[ "github_nested" , "github_timeline" , "gsod" , "natality" , "shakespeare" , "trigrams" , "wikipedia" ]}}}], "role" : "user" } { "parts" :[{ "function_call" :{ "args" :{ "table_id" : "shakespeare" , "dataset_id" : "samples" , "project_id" : "bigquery-public-data" }, "name" : "get_table_info" }}], "role" : "model" } { "parts" :[{ "function_response" :{ "name" : "get_table_info" , "response" :{ "kind" : "bigquery#table" , "etag" : "BeoZAW5rQH2EllmuKl2a2A==" , "id" : "bigquery-public-data:samples.shakespeare" , "selfLink" : "https://bigquery.googleapis.com/bigquery/v2/projects/bigquery-public-data/datasets/samples/tables/shakespeare" , "tableReference" :{ "projectId" : "bigquery-public-data" , "datasetId" : "samples" , "tableId" : "shakespeare" }, "schema" :{ "fields" :[{ "name" : "word" , "type" : "STRING" , "mode" : "REQUIRED" , "description" : "A single unique word (where whitespace is the delimiter) extracted from a corpus." },{ "name" : "word_count" , "type" : "INTEGER" , "mode" : "REQUIRED" , "description" : "The number of times this word appears in this corpus." },{ "name" : "corpus" , "type" : "STRING" , "mode" : "REQUIRED" , "description" : "The work from which this word was extracted." },{ "name" : "corpus_date" , "type" : "INTEGER" , "mode" : "REQUIRED" , "description" : "The year in which this corpus was published." }]}, "numBytes" : "6432064" , "numLongTermBytes" : "6432064" , "numRows" : "164656" , "creationTime" : "1457975805856" , "lastModifiedTime" : "1457975805856" , "type" : "TABLE" , "location" : "US" , "numTimeTravelPhysicalBytes" : "0" , "numTotalLogicalBytes" : "6432064" , "numActiveLogicalBytes" : "0" , "numLongTermLogicalBytes" : "6432064" , "numTotalPhysicalBytes" : "485656" , "numActivePhysicalBytes" : "0" , "numLongTermPhysicalBytes" : "485656" , "numCurrentPhysicalBytes" : "485656" }}}], "role" : "user" } { "parts" :[{ "function_call" :{ "args" :{ "project_id" : "my-project" , "query" : "SELECT word, SUM(word_count) AS total_count FROM `bigquery-public-data.samples.shakespeare` GROUP BY word ORDER BY total_count DESC LIMIT 10" }, "name" : "execute_sql" }}], "role" : "model" } { "parts" :[{ "function_response" :{ "name" : "execute_sql" , "response" :{ "status" : "SUCCESS" , "rows" :[{ "word" : "the" , "total_count" : 25568 },{ "word" : "I" , "total_count" : 21028 },{ "word" : "and" , "total_count" : 19649 },{ "word" : "to" , "total_count" : 17361 },{ "word" : "of" , "total_count" : 16438 },{ "word" : "a" , "total_count" : 13409 },{ "word" : "you" , "total_count" : 12527 },{ "word" : "my" , "total_count" : 11291 },{ "word" : "in" , "total_count" : 10589 },{ "word" : "is" , "total_count" : 8735 }]}}}], "role" : "user" } 出力を見ると、ツールセットに含まれる list_table_ids 、 get_table_info 、 execute_sql が順に実行されています。エージェントはまずテーブルの存在確認を行い、次にテーブルのスキーマを取得して構造を理解しました。このとき、テーブルやカラムのメタデータ( description )も取得していることがわかります。最後に SELECT 文を実行し、データを取得し、それを解釈して回答を生成したことがわかります。 このような挙動からも、AI エージェントがテーブル構造を適切に理解してクエリを実行するには、メタデータ管理が重要であることがわかります。 参考 : メダリオンアーキテクチャ2.0とGoogle CloudのAIエージェント活用 - G-gen Tech Blog 精度確認 エージェントが生成したクエリを確認し、また念の為、エージェントが実行したクエリを手作業でも実行してみます。 質問内容に対して、エージェントの実行したクエリは適切であり、実行結果とも整合性が取れていることがわかります。 クエリ SELECT word, SUM (word_count) AS total_count FROM `bigquery- public -data.samples.shakespeare` GROUP BY word ORDER BY total_count DESC LIMIT 10 実行結果 word total_count the 25568 I 21028 and 19649 to 17361 of 16438 a 13409 you 12527 my 11291 in 10589 is 8735 質問のしかたを変える エージェントが自律的に判断して BigQuery の様々なタスクを実行できることを確認するため、以下のようなクエリも実行してみます。 BigQuery データセット bigquery-public-data.samples から、シェイクスピア作品で頻出の単語のトップ10を教えてください。 先程はテーブル ID を指定しましたが、今回はデータセット ID のみを指定しています。結果は、エージェントが適切にデータセット内からテーブルをリストアップし、適切なテーブルを見つけ出してクエリを実行しました。 最終回答 シェイクスピア作品で最も頻出する単語トップ10は以下の通りです。 1. the: 25568 2. I: 21028 3. and: 19649 4. to: 17361 5. of: 16438 6. a: 13409 7. you: 12527 8. my: 11291 9. in: 10589 10. is: 8735 これらの単語は、シェイクスピアの作品で最も多く使用されています。 エージェントの処理 Function calls: name: list_table_ids, args: {'project_id': 'bigquery-public-data', 'dataset_id': 'samples'} Function calls: name: get_table_info, args: {'dataset_id': 'samples', 'table_id': 'shakespeare', 'project_id': 'bigquery-public-data'} Function calls: name: execute_sql, args: {'project_id': my-project, 'query': 'SELECT word, SUM(word_count) AS total_word_count FROM `bigquery-public-data.samples.shakespeare` GROUP BY word ORDER BY total_word_count DESC LIMIT 10'} さらに、以下のようなクエリでも想定どおりの結果が返りました。 BigQuery プロジェクト bigquery-public-data から、シェイクスピア作品で頻出の単語のトップ10を教えてください。 この場合は、 list_dataset_ids → list_table_ids → get_table_info → execute_sql と順番にツールを使って処理が実行され、適切なテーブルにたどり着きました。 複雑な質問 AI エージェントは、以下のような少し複雑な質問にも対応できます。処理結果を見ると、必要な分、複数回のクエリを発行し、それを最後に LLM がまとめていることがわかります。このような質問にエージェントが回答できれば、より実践的なユースケースにも対応できる可能性が出てきます。 クエリ 米国で生まれた子供に多い名前の傾向を、2000年と2020年で比較してください。どのような違いがありますか? BigQuery テーブル bigquery-public-data.usa_names.usa_1910_current からデータを取得してください。 最終回答 2000年と2020年の米国における人気のある名前の傾向を比較すると、以下の点が挙げられます。 **2000年の人気上位の名前:** * **男の子:** Jacob, Michael, Matthew, Joshua, Christopher, Nicholas, Andrew, Joseph, Daniel, Tyler * **女の子:** Emily, Hannah, Madison, Ashley, Sarah, Alexis, Samantha, Jessica, Elizabeth, Taylor **2020年の人気上位の名前:** * **男の子:** Liam, Noah, Oliver, Elijah, William, James, Benjamin, Lucas, Henry, Alexander * **女の子:** Olivia, Emma, Ava, Charlotte, Sophia, Amelia, Isabella, Mia, Evelyn, Harper **主な違い:** * **名前のトレンドの変化:** 2000年と2020年の上位10位の名前には、ほとんど重複がありません。これは、わずか20年の間に名前の流行が大きく変化したことを示しています。 * **新しい名前の台頭:** 2020年には、「Liam」「Noah」「Olivia」「Ava」など、2000年には上位に入っていなかった新しい名前が人気を集めていることがわかります。 * **伝統的な名前の継続的な人気:** 「William」や「James」、「Elizabeth」など、比較的時間に左右されない伝統的な名前も依然として一定の人気を保っていることが伺えますが、上位を占めるのはより現代的な名前になっています。 この比較から、米国における子どもの名前の傾向は、社会や文化の変化を反映して、20年間で大きく移り変わっていることが明確にわかります。 処理の経緯 (一部のみ抜粋) Function calls: name: get_table_info, args: {'dataset_id': 'usa_names', 'project_id': 'bigquery-public-data', 'table_id': 'usa_1910_current'} 2025 - 07 - 29 09: 22 : 58 , 336 - DEBUG - google_adk.google.adk.models.google_llm - LLM Response: ----------------------------------------------------------- Text: 2000 年と 2020 年の米国で生まれた子供に多い名前の傾向を比較するため、`bigquery-public-data.usa_names.usa_1910_current` テーブルからデータを取得します。 まず、 2000 年の男女別人気上位 10 の名前を抽出します。 ----------------------------------------------------------- Function calls: name: execute_sql, args: { 'project_id' : my-project, 'query' : " \n SELECT \n name, \n SUM(number) as total_occurrences \n FROM \n `bigquery-public-data.usa_names.usa_1910_current` \n WHERE \n year = 2000 AND gender = 'M' \n GROUP BY \n name \n ORDER BY \n total_occurrences DESC \n LIMIT 10; \n " } 2025 - 07 - 29 09: 23 : 04 , 532 - DEBUG - google_adk.google.adk.models.google_llm - LLM Response: ----------------------------------------------------------- Text: 次に、 2020 年の男女別人気上位 10 の名前を抽出します。 ----------------------------------------------------------- Function calls: name: execute_sql, args: { 'project_id' : my-project, 'query' : " \n SELECT \n name, \n SUM(number) as total_occurrences \n FROM \n `bigquery-public-data.usa_names.usa_1910_current` \n WHERE \n year = 2020 AND gender = 'M' \n GROUP BY \n name \n ORDER BY \n total_occurrences DESC \n LIMIT 10; \n " } 会話型分析(参考情報) ADK とは関係のない参考情報ですが、BigQuery のデータに対して自然言語によるクエリや分析を行いたい場合、 Looker や Looker Studio Pro に搭載の Conversational Analytics (会話型分析)も有用な選択肢です。 この機能では、自然言語、かつチャット形式で Looker や Looker Studio の画面から問いを投げかけるだけで、AI が BigQuery 等のデータソースに対してクエリを発行し、分析や可視化が可能です。 参考 : Looker の会話分析 参考 : Looker Studio の会話分析 Looker Studio Pro の会話型分析 Looker や Looker Studio Pro については、以下の記事も参考にしてください。 blog.g-gen.co.jp blog.g-gen.co.jp 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の三浦です。当記事では、特定の GitHub リポジトリの内容を Gemini アプリに解説させる方法を紹介します。 概要 当機能について Gemini アプリとは 前提条件 検証手順 検証 リポジトリとディレクトリ構成 main.py error/error.py パブリックリポジトリのインポート コード理解と改善の確認 プライベートリポジトリのフォルダインポート デバッグとコード生成の確認 概要 当機能について Gemini アプリでは、GitHub のパブリックリポジトリまたはプライベートリポジトリをインポートして、その内容に関する質問や依頼ができます。 この機能は、ソースコードの理解の支援や改善案の提案、コード生成、エラー解析といった用途に利用できます。 詳細は以下の公式ドキュメントをご参照ください。 参考 : GitHub リポジトリをインポートして Gemini ウェブアプリでそれについて質問する Gemini アプリとは Gemini アプリ は、Google が提供する生成 AI チャットアプリケーションです。プログラミング、ドキュメント作成、質問応答など多用途に対応しています。 Google アカウントを持っていれば、ウェブブラウザで gemini.google.com にアクセスしたり、モバイルデバイス向けアプリをダウンロードすることで利用できます。 詳細は以下の公式ドキュメントや記事をご参照ください。 参考 : Gemini ウェブアプリを利用する 参考 : 全Geminiプロダクトを徹底解説! - G-gen Tech Blog - Gemini アプリ 前提条件 当機能は、以下の特定の Google Workspace エディションまたはアドオンでのみ利用できます。 Business Standard / Plus Enterprise Standard / Plus Gemini Education Education Premium 詳細は以下をご参照ください。 参考 : Upload code folders or import your GitHub repositories directly into the Gemini app 検証手順 検証手順は次のとおりです。 項番 内容 説明 1 パブリックリポジトリをインポートし、コード理解と改善を試行 GitHub リポジトリをインポートし、コードベースの理解や改善提案を Gemini に依頼します。 2 プライベートリポジトリのフォルダをインポートし、デバッグやコード生成を試行 フォルダをアップロードし、生成・デバッグ用途での使い方を確認します。 検証 リポジトリとディレクトリ構成 本検証に使用したリポジトリの構成は以下のとおりです。 # パブリックリポジトリ . ├── README.md └── main.py   # プライベートリポジトリ . ├── README.md └── error └── error.py main.py シンプルな Flask アプリを使用しています。ブラウザに "Hello, World!" を返すだけの最小構成です。 from flask import Flask   app = Flask(__name__)   @ app.route ( "/" ) def hello (): return "Hello, World!"   if __name__ == "__main__" : app.run() error/error.py 意図的に ZeroDivisionError を引き起こすテストコードです。Gemini アプリでのデバッグ用に使用します。 from flask import Flask   app = Flask(__name__)   @ app.route ( "/" ) def home (): return 1 / 0   if __name__ == "__main__" : app.run(debug= True )   パブリックリポジトリのインポート Gemini アプリ( https://gemini.google.com )へアクセスします。 [+(ファイルの追加)] > [コードをインポート] を選択します。 コードをインポートを選択 GitHub リポジトリの URL を入力し、「インポート」を選択します。 インポートの実施 内容を確認し、「接続」を選択します。 GitHub との接続を実施 接続が完了すると、接続した GitHub のリポジトリ情報が表示されます。 インポート確認 コード理解と改善の確認 まずは以下のプロンプトで、リポジトリのコード全体について説明を求めてみます。 このリポジトリのコードについて教えてください リポジトリのコード解説 次に以下のプロンプトで、アプリのセキュリティ改善の提案を依頼してみます。 この Web アプリに対して、セキュリティ上のリスクがあれば指摘し、改善案を提示してください リポジトリのコード改善 プライベートリポジトリのフォルダインポート Gemini アプリの新しいチャットから、再度 [+(ファイルの追加)] > [コードをインポート] を選択します。 [フォルダをアップロード] から、 error フォルダを選択します。 フォルダをアップロード 注意内容を確認し、[アップロード] を選択します。 アップロードを選択 アップロードしたフォルダが表示されていることを確認します。 アップロード確認 デバッグとコード生成の確認 以下のプロンプトで、エラーが出る原因と改善方法を確認します。 このアプリの実行時にエラーが出る理由を教えてください。また、修正方法も教えてください。 原因と改善方法の提示 次に以下のプロンプトで、認証機能を追加するコードを生成できるか確認します。 このアプリに対して、ユーザー名とパスワードでログインできる認証機能を追加したいです。必要なコードを生成して教えてください。 機能追加のためのコード生成 三浦 健斗 (記事一覧) クラウドソリューション部 2023年10月よりG-genにジョイン。元オンプレ中心のネットワークエンジニア。ネットワーク・セキュリティ・唐揚げ・辛いものが好き。
アバター
G-gen の高井(Peacock)です。Cloud Run のサイドカー機能と MailHog を利用し、アプリケーションからのメールを捕捉するダミーの SMTP サーバー環境を構築する方法を紹介します。 はじめに やりたいこと 実現方法 サイドカー機能とは 構成 ソースコード デプロイ 動作確認 はじめに やりたいこと Cloud Run services を使い、メール送信機能があるアプリケーションを開発しているケースを考えます。本番環境のアプリケーションでは SMTP サーバーを利用してメールを送信していますが、開発環境のアプリケーションではメールが外部に送信されないようにしたい場合があります。 当記事では、上記のようなケースにおいて、アプリケーションのコードは極力変更せずに、開発環境のみメールを MailHog で構築したダミー SMTP サーバーで受け取るようにします。 MailHog は、MIT ライセンスのもと配布されているオープンソースソフトウェアです。 参考 : GitHub - mailhog/MailHog 参考 : GitHub - mailhog/MailHog/LICENSE.md 実現方法 当記事では、前述の要件を Cloud Run の サイドカー (Sidecar)機能を利用して実現します。 アプリケーションコンテナのデプロイ時に、MailHog のコンテナをサイドカーとして同時にデプロイします。これにより、2つのコンテナは同一の Cloud Run サービスインスタンス内で起動し、 localhost を通じて通信できます。 アプリケーション側では、接続先 SMTP サーバーのホスト名を localhost に、ポートを MailHog が待機するポート(デフォルトで 1025 )に設定するだけで、メール送信の向き先を MailHog に変更できます。 サイドカー機能とは サイドカー とは、1つの Cloud Run サービスに、複数のコンテナをデプロイできる機能です。 メインのリクエストを処理するコンテナ(Ingress コンテナ)と、それを補助するサイドカーコンテナを組み合わせて使用します。サイドカーのユースケースとして、ログ転送エージェントや、サービスメッシュのプロキシ、そして今回のような補助的なサービスが挙げられます。 サイドカーとしてデプロイされたコンテナは、Ingress コンテナと同じネットワーク名前空間を共有するため、 localhost を使用して相互に通信できます。ただし、外部からの HTTP リクエストは Ingress コンテナのみが受信し、サイドカーコンテナのポートが直接外部に公開されることはありません。 参考 : Cloud Run へのコンテナ イメージのデプロイ - サービスに複数のコンテナをデプロイする(サイドカー) 構成 外部からのリクエストは、ポート 8080 で待機する FastAPI アプリケーションコンテナ(Ingress コンテナ)が受け取ります。 アプリケーションがメールを送信する際は、環境変数で指定された localhost:1025 に接続します。そこでは MailHog コンテナが SMTP サーバーとして待機しており、送信されたメールを捕捉します。 ソースコード まず、メール送信機能を持つ FastAPI アプリケーションを用意します。 重要な点は、SMTP サーバーの接続情報を環境変数( SMTP_HOST 、 SMTP_PORT など)から読み込むように実装することです。これにより、コンテナイメージを再ビルドすることなく、デプロイ時の設定だけで接続先を切り替えられます。 Dockerfile FROM python:3.13-bookworm COPY --from = ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ WORKDIR /app ADD . /app RUN uv sync --locked EXPOSE 8080 CMD [" /app/.venv/bin/fastapi " , " run " , " main.py " , " --host " , " 0.0.0.0 " , " --port " , " 8080 "] main.py from email.message import EmailMessage import smtplib import os from fastapi import FastAPI, HTTPException, Request, Response from pydantic import BaseModel, EmailStr app = FastAPI() # 環境変数からSMTPサーバーの接続情報を取得 SMTP_HOST = os.environ.get( "SMTP_HOST" ) SMTP_PORT = int (os.environ.get( "SMTP_PORT" , 587 )) SMTP_USER = os.environ.get( "SMTP_USER" ) SMTP_PASS = os.environ.get( "SMTP_PASS" ) class EmailModel (BaseModel): from_: EmailStr to: EmailStr subject: str body: str @ app.get ( "/" ) def root (): return { "message" : "ok" } @ app.post ( "/sendmail" ) def sendmail (email: EmailModel): if SMTP_HOST is None : raise HTTPException( status_code= 500 , detail= "SMTP_HOST environment variable is not set" ) # MailHogは認証不要なため、USER/PASSの有無で処理を分岐 if SMTP_USER and SMTP_PASS: server = smtplib.SMTP_SSL(SMTP_HOST, port=SMTP_PORT) server.set_debuglevel( 1 ) server.login(user=SMTP_USER, password=SMTP_PASS) else : server = smtplib.SMTP(SMTP_HOST, port=SMTP_PORT) server.set_debuglevel( 1 ) msg = EmailMessage() msg[ "Subject" ] = email.subject msg[ "From" ] = email.from_ msg[ "To" ] = email.to msg.set_content(email.body) server.send_message(msg) server.close() return { "ok" : True } pyproject.toml [project] name = "etude-mailhog" version = "0.1.0" description = "" readme = "README.md" requires-python = ">=3.13" dependencies = [ "fastapi[standard]>=0.115.12" , ] デプロイ gcloud コマンドで、アプリケーションと MailHog を Cloud Run にデプロイします。 まず、アプリケーションのコンテナイメージを Artifact Registry などにプッシュします。 # Cloud BuildでコンテナイメージをビルドしてArtifact Registryにプッシュ # (事前に gcloud artifacts repositories create ... でリポジトリ作成が必要) gcloud builds submit --tag asia-northeast1-docker.pkg.dev/ $( gcloud config get-value project ) /smtp-mocker/app:1. 0 次に、Cloud Run にサービスをデプロイします。 --container フラグを2つ指定することで、サイドカー構成を定義します。 gcloud run deploy mail-service \ --region asia-northeast1 \ --allow-unauthenticated \ --container " app " \ --image " asia-northeast1-docker.pkg.dev/ $( gcloud config get-value project ) /smtp-mocker/app:1.0 " \ --port 8080 \ --set-env-vars " SMTP_HOST=localhost,SMTP_PORT=1025 " \ --container " mailhog " \ --image " mailhog/mailhog " このコマンドの主要なフラグは以下の通りです。 フラグ 説明 --container "app" Ingress コンテナとなるアプリケーションを定義します。このフラグに続く --port 8080 で待ち受けポートを指定し、 --set-env-vars で SMTP の接続先を localhost:1025 に設定します。 --container "mailhog" サイドカーとなる MailHog コンテナを定義します。Docker Hub の公式イメージ mailhog/mailhog を指定します。 参考 : Docker Hub - mailhog/mailhog 動作確認 デプロイが完了したら、 curl コマンドでアプリケーションの /sendmail エンドポイントを呼び出し、テストメールを送信します。 # Cloud RunサービスのエンドポイントURLを取得 SERVICE_URL = $( gcloud run services describe mail-service --region asia-northeast1 --format ' value(status.url) ' ) # テストメールを送信 curl -X POST " ${SERVICE_URL} /sendmail " \ -H " Content-Type: application/json " \ -d ' { "from_": "from@example.com", "to": "to@example.com", "subject": "Test from Cloud Run", "body": "This is a test mail with a sidecar." } ' このように Cloud Run のサイドカー機能と環境変数を利用することで、アプリケーションコードを変更することなく、環境に応じた柔軟なシステム構成を実現できます。 Peacock (高井 陽一) (記事一覧) クラウドソリューション部 カスタマーサポート課 2022年12月より入社。普段は Google Cloud の技術サポートや Terraform などによる IaC の推進を行なっている。また、プライベートでは PyCon JP 2022, 2023(APAC) にて副座長など、カンファレンスのスタッフとしても活動している。趣味はカメラ・スキー・クラシック音楽など。 Follow @peacock0803sz
アバター
G-gen の山崎です。 当記事では、Cloud Run jobs を使用して Google Drive の差分を検知し、差分ファイルを Cloud Storage にアップロードする方法を解説します。 システム構成 前提知識 環境構築 API の有効化 サービスアカウントの構築 Cloud Run jobs 用サービスアカウントの作成 Cloud Scheduler 用サービスアカウントの作成 Cloud Storage の構築 ページトークン格納用バケットの作成 アップロードファイル格納用バケットの作成 Cloud Run jobs の構築 Artifact Registry の作成 アプリケーションの準備 環境変数の設定 コンテナイメージのビルド Cloud Run jobs のデプロイ Cloud Scheduler の構築 動作確認 Google Drive のフォルダに対して Cloud Run jobs 用サービスアカウントに参照権限を付与 Cloud Run jobs を実行し、現在のページトークンを取得 Google Drive のフォルダに対してファイルを配置し、Cloud Run jobs を実行 補足 : Google Drive Events API システム構成 今回構築したシステム構成は、以下のとおりです。 構成図 Cloud Scheduler を使って定期的に Cloud Run jobs を起動します。 起動した Cloud Run jobs は、以下の流れで前回処理を行った以降に発生した Google Drive の差分を検知し、その差分のファイルを Cloud Storage にアップロードします。 ページトークン取得 差分ファイル情報取得 ファイルアップロード ページトークン更新 ページトークン は、Google Drive API で変更を追跡する際の起点となる識別子です。 このトークンを保存・更新することで、前回処理を実行した時点からの差分のみを効率的に取得できます。 参考 : 変更を取得する 前提知識 今回使用する Google Cloud サービスの詳細は、以下の記事をご参照ください。 Cloud Storage blog.g-gen.co.jp Cloud Run jobs blog.g-gen.co.jp Cloud Scheduler blog.g-gen.co.jp 環境構築 以下の順序で環境を構築しました。 API の有効化 サービスアカウントの構築 Cloud Storage の構築 Cloud Run jobs の構築 Cloud Scheduler の構築 API の有効化 Google Cloud プロジェクトで、今回の構成に必要な Google Cloud サービスの API を有効化します。 gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com \ cloudscheduler.googleapis.com \ drive.googleapis.com サービスアカウントの構築 Cloud Run jobs、Cloud Scheduler 用のサービスアカウントを作成します。 Cloud Run jobs 用サービスアカウントの作成 Google Cloud コンソールのサービスアカウント画面で、[サービスアカウントを作成] を選択します。 任意のサービスアカウント名を入力し、[作成して続行] を選択します。 作成したサービスアカウントに「Storage オブジェクト管理者( roles/storage.objectAdmin )」「ログ書き込み( roles/logging.logWriter )」の権限を付与して[完了]を選択します。 Cloud Scheduler 用サービスアカウントの作成 再度[サービスアカウントを作成] を選択し、任意のサービスアカウント名の入力を行い、[作成して続行] を選択します。 作成したサービスアカウントに「Cloud Run ジョブ エグゼキュータ( roles/run.jobsExecutor )」の権限を付与して[完了]を選択します。 Cloud Storage の構築 ページトークン格納用、アップロードファイル格納用のバケットを作成します。 ページトークン格納用バケットの作成 Google Cloud コンソールのバケット画面で、[作成] を選択します。 グローバルに一意の名前を入力し、[続行] を選択します。 データの保存場所を選択し、[作成] を選択します。 「このバケットに対する公開アクセス禁止を適用する」にチェックがついていることを確認し、[確認] を選択します。 アップロードファイル格納用バケットの作成 再度バケット画面で、[作成] を選択し、グローバルに一意の名前を入力してアップロードファイル格納用バケットを作成します。(設定内容はページトークン格納用バケットと同様) Cloud Run jobs の構築 Artifact Registry の作成、アプリケーションの準備、環境変数の設定、コンテナイメージのビルド、Cloud Run jobs のデプロイを行います。 Artifact Registry の作成 Google Cloud コンソールのリポジトリ画面で、[リポジトリの作成] を選択します。 任意のリポジトリ名とリージョンを指定し、[作成] を選択します。 アプリケーションの準備 今回開発する Python アプリケーションのディレクトリ構成は以下のとおりです。 drive-to-gcs-demo-app |-- requirements.txt |-- Dockerfile |-- main.py requirements.txt google-api-python-client google-auth google-cloud-storage google-cloud-logging Dockerfile FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY main.py . CMD [ " python ", " main.py " ] main.py import base64 import binascii import io import os import sys import google.auth import google.cloud.logging import logging from googleapiclient.discovery import build from googleapiclient.errors import HttpError from googleapiclient.http import MediaIoBaseDownload from google.cloud import storage from google.api_core import exceptions # --- 環境変数から設定を読み込み --- # アップロード先のGCSバケット名 UPLOAD_BUCKET_NAME = os.environ.get( 'UPLOAD_BUCKET_NAME' ) # pageTokenを保存するためのGCSバケット名(UPLOAD_BUCKET_NAMEと同じでも可) START_BUCKET_NAME = os.environ.get( 'START_BUCKET_NAME' ) # ログの出力レベル LOG_LEVEL = int (os.environ.get( 'LOG_LEVEL' )) # ログレベル debug=10 / info=20 / warning=30 # pageTokenを保存するファイル名 PAGE_TOKEN_FILE = 'drive_page_token.txt' # Cloud Logging クライアントを初期化し、ロギングを設定 client = google.cloud.logging.Client() client.setup_logging() # 標準の logger を取得し、ログレベルを設定 logger = logging.getLogger() logger.setLevel(LOG_LEVEL) # Google Drive APIのスコープ(読み取り専用) DRIVE_SCOPES = [ 'https://www.googleapis.com/auth/drive.readonly' ] def get_drive_service (): """ 実行環境のデフォルト認証情報を取得する """ credentials, _ = google.auth.default(scopes=DRIVE_SCOPES) return build( 'drive' , 'v3' , credentials=credentials) def read_page_token_from_gcs (storage_client: storage.Client) -> str | None : """GCSから前回のpageTokenを読み込む""" try : bucket = storage_client.bucket(START_BUCKET_NAME) blob = bucket.blob(PAGE_TOKEN_FILE) return blob.download_as_text() except exceptions.NotFound: # ファイルが存在しない場合は初回実行とみなし、Noneを返す logger.info(f "'{PAGE_TOKEN_FILE}' not found in GCS. Assuming first run." ) return None except Exception as e: logger.critical( f "CRITICAL: Failed to read page token from GCS due to an unexpected error. " f "This will cause the job to fail. Error: {e}" ) raise def write_page_token_to_gcs (storage_client: storage.Client, token: str ): """次回の実行のために新しいpageTokenをGCSに保存する""" try : bucket = storage_client.bucket(START_BUCKET_NAME) blob = bucket.blob(PAGE_TOKEN_FILE) blob.upload_from_string(token) logger.info(f "Successfully saved new page token to GCS: {token}" ) except Exception as e: logger.critical(f "CRITICAL: Failed to save new page token to GCS. {e}" ) # ここで失敗すると次回実行時に変更が重複する可能性があるため、エラーを明示 raise def stream_drive_file_to_gcs (drive_service, storage_client, drive_file_id, drive_file_name, bucket_name): """ 特定のファイルをDriveからGCSへ、一時ファイルを使わずに直接ストリーミングコピーする """ # GCSのオブジェクトパスとして、Driveのファイル名をそのまま使用する object_path = drive_file_name logger.info(f "--- Starting copy for '{drive_file_name}' ({drive_file_id}) to gs://{bucket_name}/{object_path} ---" ) try : # 1. Google Driveからファイルのメタデータを取得 (サイズ、MIMEタイプ、チェックサム) file_metadata = drive_service.files().get( fileId=drive_file_id, supportsTeamDrives= True , fields= 'size, mimeType, md5Checksum' ).execute() total_size = int (file_metadata.get( 'size' , 0 )) content_type = file_metadata.get( 'mimeType' , 'application/octet-stream' ) source_md5_checksum = file_metadata.get( 'md5Checksum' ) if not source_md5_checksum: logger.warning(f "Warning: MD5 checksum not available for '{drive_file_name}'. Skipping verification." ) # 2. GCSのアップロードストリームを開く bucket = storage_client.bucket(bucket_name) destination_blob = bucket.blob(object_path) with destination_blob.open( 'wb' , content_type=content_type) as gcs_stream: # 3. Driveのダウンローダーを初期化し、GCSストリームに直接接続 request = drive_service.files().get_media(fileId=drive_file_id) downloader = MediaIoBaseDownload(fd=gcs_stream, request=request, chunksize= 10 * 1024 * 1024 ) # 4. ダウンロード(=アップロード)を開始 done = False while not done: status, done = downloader.next_chunk(num_retries= 3 ) if status: logger.info(f " Copy in progress: {int(status.progress() * 100)}%" ) logger.info( " Streaming finished." ) # 5. 整合性チェック (MD5チェックサムが取得できている場合のみ) if source_md5_checksum: destination_blob.reload() # GCSから最新のメタデータを取得 gcs_md5_b64 = destination_blob.md5_hash gcs_md5_hex = binascii.hexlify(base64.b64decode(gcs_md5_b64)).decode( 'utf-8' ) if source_md5_checksum == gcs_md5_hex: logger.info(f " Success! MD5 checksums match for '{drive_file_name}'." ) else : logger.error(f " ERROR: MD5 CHECKSUM MISMATCH for '{drive_file_name}'!" ) raise logger.info(f "--- Successfully copied '{drive_file_name}' ---" ) return True except HttpError as e: # 特にダウンロード権限がない(403)やファイルが見つからない(404)などの場合に発生 logger.error(f "ERROR: An HTTP error occurred while copying '{drive_file_name}': {e}" ) raise except Exception as e: logger.error(f "ERROR: An unexpected error occurred while copying '{drive_file_name}': {e}" ) raise def main (): """ Google Driveの変更を検知してGCSにファイルを同期するメインの処理 """ if not UPLOAD_BUCKET_NAME or not START_BUCKET_NAME or not LOG_LEVEL: logger.error( "Error: Environment variables 'UPLOAD_BUCKET_NAME' and 'START_BUCKET_NAME' and 'LOG_LEVEL' must be set." ) raise ValueError ( "Required environment variables are not set." ) drive_service = get_drive_service() storage_client = storage.Client() # 処理対象と対象外のファイル名を記録するためのリストを初期化 processed_files = [] skipped_files = [] page_token = read_page_token_from_gcs(storage_client) if page_token is None : # 初回実行時は、全ての変更を検知するための最初のトークンを取得する response = drive_service.changes().getStartPageToken().execute() page_token = response.get( 'startPageToken' ) logger.info(f "First run detected. Starting with token: {page_token}" ) logger.info(f "Processing changes starting from page token: {page_token}" ) while page_token is not None : response = drive_service.changes().list( pageToken=page_token, spaces= 'drive' , includeItemsFromAllDrives= True , supportsAllDrives= True , fields= 'nextPageToken, newStartPageToken, changes(fileId, file(id, name, trashed, mimeType))' ).execute() # 取得した差分情報の出力(debug) logger.debug(f "response info: {response}" ) for change in response.get( 'changes' , []): drive_file_id = change.get( 'fileId' ) drive_file_info = change.get( 'file' ) # ファイルが存在し、ゴミ箱になく、かつMIMEタイプが'application/pdf'である場合のみ処理を続行 if drive_file_info and not drive_file_info.get( 'trashed' ) and drive_file_info.get( 'mimeType' ) == 'application/pdf' : drive_file_name = drive_file_info.get( 'name' ) logger.info(f " \n PDF change detected, will process: '{drive_file_name}' (ID: {drive_file_id})" ) # 処理対象リストにファイル名を追加 processed_files.append(drive_file_name) # ストリーミングコピー関数を呼び出す stream_drive_file_to_gcs( drive_service=drive_service, storage_client=storage_client, drive_file_id=drive_file_id, drive_file_name=drive_file_name, bucket_name=UPLOAD_BUCKET_NAME ) else : # 処理対象外のファイルとして記録 if drive_file_info: file_name_to_skip = drive_file_info.get( 'name' , drive_file_id) skipped_files.append(file_name_to_skip) # スキップ理由をログに記録 reason = "" if drive_file_info.get( 'trashed' ): reason = "it is in trash" elif drive_file_info.get( 'mimeType' ) == 'application/vnd.google-apps.folder' : reason = "it is a folder" else : reason = f "its MIME type is not PDF ('{drive_file_info.get('mimeType')}')" logger.info(f "Skipping '{file_name_to_skip}' because {reason}." ) else : # ファイル情報自体がない場合 logger.info(f "Skipping change for file ID {drive_file_id} because file information could not be retrieved." ) # 次のページのトークンがあればループを継続、なければ終了 if 'nextPageToken' in response: page_token = response.get( 'nextPageToken' ) else : # ループ終了。次回の実行のために新しいStartPageTokenを保存 new_start_page_token = response.get( 'newStartPageToken' ) write_page_token_to_gcs(storage_client, new_start_page_token) logger.info( " \n Finished processing all changes." ) page_token = None # すべての処理ループが終わった後で、最終的な結果をINFOレベルでロギング logger.info( "--- Execution Summary ---" ) summary_processed = f "処理対象ファイル:{', '.join(processed_files)}" if processed_files else "処理対象ファイル:なし" summary_skipped = f "処理対象外ファイル:{', '.join(skipped_files)}" if skipped_files else "処理対象外ファイル:なし" logger.info(summary_processed) logger.info(summary_skipped) if __name__ == "__main__" : logger.info( "Cloud Run Job started." ) try : main() logger.info( "Cloud Run Job finished successfully." ) except Exception as e: logger.critical(f "Job failed with a critical error: {e}" , exc_info= True ) sys.exit( 1 ) finally : if 'client' in locals () and client: client.close() 環境変数の設定 以降の手順で繰り返し使用する Google Cloud プロジェクト ID やリージョンなどの情報を環境変数に設定します。 ご自身の環境に合わせて、以下のコマンドで環境変数を設定してください。 # Google Cloud プロジェクト ID export PROJECT_ID = " your-project-id " # プロジェクトのデフォルトリージョン export LOCATION = " asia-northeast1 " # Artifact Registry の名前 export REPO = " my-repo " # Image の名前 export IMAGE = " my-image " # Cloud Run jobs の名前 export JOB_NAME = " my-job " # Cloud Run jobs 用サービスアカウントの名前 export SERVICE_ACCOUNT_NAME = " cloud-run-jobs-sa " # アップロードファイル格納用のバケットの名前 export UPLOAD_BUCKET = " upload-drive-pdf " # ページトークン格納用のバケットの名前 export START_BUCKET = " pagetoken " コンテナイメージのビルド Dockerfile が存在するディレクトリで、以下の gcloud コマンドを実行します。 gcloud builds submit --tag ${LOCATION} -docker.pkg.dev/ ${PROJECT_ID} / ${REPO} / ${IMAGE} :latest Cloud Run jobs のデプロイ 作成したコンテナイメージを使用して、Cloud Run jobs をデプロイします。 gcloud run jobs deploy ${JOB_NAME} \ --image ${LOCATION} -docker.pkg.dev/ ${PROJECT_ID} / ${REPO} / ${IMAGE} :latest \ --region = ${LOCATION} \ --service-account =" ${SERVICE_ACCOUNT_NAME} @ $PROJECT_ID .iam.gserviceaccount.com " \ --set-env-vars =" UPLOAD_BUCKET_NAME= ${UPLOAD_BUCKET} " \ --set-env-vars =" START_BUCKET_NAME= ${START_BUCKET} " \ --set-env-vars =" LOG_LEVEL=20 " \ --tasks = 1 \ --max-retries = 3 \ --task-timeout = 1440m Cloud Scheduler の構築 Google Cloud コンソールのジョブ画面で、作成した Cloud Run jobs を選択します。 ジョブの詳細画面で、[トリガー]を選択し、[スケジューラトリガーを追加]を選択します。 任意の名前、リージョン、頻度、タイムゾーンを指定し、[続行] を選択します。 サービスアカウントに Cloud Scheduler 用サービスアカウントを設定し、[作成] を選択します。 動作確認 以下の順番で動作確認を行います。 Google Drive のフォルダに対して Cloud Run jobs 用サービスアカウントに参照権限を付与 Cloud Run jobs を実行し、現在のページトークンを取得 Google Drive のフォルダに対してファイルを配置し、Cloud Run jobs を実行 Google Drive のフォルダに対して Cloud Run jobs 用サービスアカウントに参照権限を付与 差分検知を行う Google Drive のフォルダ上で、共有アイコンを選択します。 Cloud Run jobs 用サービスアカウントに閲覧者権限を付与し、[共有]を選択します。 Cloud Run jobs を実行し、現在のページトークンを取得 今回は動作確認のため、Cloud Schduler による時刻起動は行わず、Google Cloud コンソールのジョブの詳細画面で、[実行] を選択します。 ページトークン格納用バケットにページトークンを保持するテキストファイルが配置されています。 Google Drive のフォルダに対してファイルを配置し、Cloud Run jobs を実行 差分検知を行う Google Drive のフォルダ上に PDF ファイルを配置します。 再度、Google Cloud コンソールのジョブの詳細画面で、[実行] を選択します。 アップロードファイル格納用のバケットに、Google Drive のフォルダに配置した PDF ファイルが配置されています。 補足 : Google Drive Events API 2025年7月7日に Google Drive Events API が Preview 公開されました。 Google ドライブのファイル変更通知を CloudEvent 仕様に従ってフォーマットされた Pub/Sub メッセージで受け取ることが可能 となるため、より活用の幅が広がることが期待されます。 参考 : Google ドライブのイベントを操作する 山崎 曜 (記事一覧) クラウドソリューション部 元は日系大手SIerにて金融の決済領域のお客様に対して、PM/APエンジニアとして、要件定義〜保守運用まで全工程に従事。 Google Cloud Partner Top Engineer 2025 選出。 Google Cloud 全 13 資格保有。 フルスタックな人材を目指し、日々邁進。 Follow @Akira_Yamasakit
アバター
G-gen の杉村です。 Agent Development Kit (ADK)は、Google Cloud が提供する、AI エージェント開発のためのフレームワークです。当記事では、ADK の中核をなす LLM Agent と Workflow Agents 、および Tools を解説します。 概要 Agent Development Kit(ADK)とは ADK のコンポーネント LLM Agent 概要 実装例 ソースコードの実行 Runner と非同期処理 Workflow Agents 概要 実装例 実行結果 詳細のロギング Tools 概要 関数の記述 要約のスキップ 概要 Agent Development Kit(ADK)とは Agent Development Kit(ADK) は、AI エージェントの開発、デプロイ、評価を効率化するために Google が開発したオープンソースのフレームワークです。2025年7月現在、Python および Java 向けのライブラリとして公開されています。 ADK を利用することで、開発者は通常のソフトウェア開発と同じような感覚で、モジュール化された再利用可能なコンポーネントを組み合わせて AI エージェントを開発できます。ADK は Google の生成 AI モデル Gemini や Vertex AI などのエコシステムに最適化されていますが、特定のモデルやデプロイ環境に依存しない設計思想を持っており、高い柔軟性と拡張性を備えています。 参考 : Agent Development Kit ADK のコンポーネント ADK でアプリを開発する際、以下のようなコンポーネントを記述します。 Agents タスクを実行する主体。LLM の推論能力を活用して自律的に動作する LLM Agent と、事前に定義された手順に従って動作する Workflow Agent がある。 Tools エージェントがタスクをこなすために利用するプログラム等。外部 API の呼び出しや計算、データベース検索など、特定の処理を行う。 参考 : Agents 参考 : Tools LLM Agent 概要 LLM Agent は、LLM の持つ推論能力を利用して、タスクを達成するために思考したり、どの Tool をどの順番で、どのようなパラメータで呼び出すかなどを自律的に判断するエージェントです。 ADK では基本的に、この LLM Agent を組み合わせて AI エージェントアプリケーションを開発しますので、最も基本的なコンポーネントであるといえます。 参考 : LLM Agent 実装例 LLM Agent を定義する際は、主に以下の要素を指定します。 属性 説明 instruction エージェントの役割、振る舞い、タスクの進め方などを自然言語で記述した指示書 model 使用するモデル(gemini-2.5-flash など) tools エージェントが利用可能なツール(道具)。Python の関数や他のエージェントなど 以下は、都市ごとの現在時刻を返す簡単な Tool を持つ LLM Agent の Python サンプルコードです。このエージェントに「東京の天気は?」と質問すると、LLM は get_weather ツールを city="東京" という引数で呼び出すべきだと判断(Reasoning)し、実行します。そして、Tool から返された「晴れです。」という結果(Observation)を元に、最終的な回答を生成します。 import asyncio import datetime from google.adk.agents import LlmAgent from google.adk.runners import Runner from google.adk.sessions import InMemorySessionService from google.genai import types def get_time (city: str ): ''' # 概要 指定された都市の現在時刻を取得します。 # 引数 city (str): 対象の都市名 (Tokyo / Los Angels / London) ''' print (f "--- Tool: get_weather (city: {city}) ---" ) if "Tokyo" in city: tz = datetime.timezone(datetime.timedelta(hours= 9 )) elif "Los Angels" in city: tz = datetime.timezone(datetime.timedelta(hours=- 7 )) elif "London" in city: tz = datetime.timezone(datetime.timedelta(hours= 0 )) else : tz = None if tz: now = datetime.datetime.now(tz) else : now = None message = { "city" : city, "datetime" : now } return message # LLM Agentの定義 time_agent = LlmAgent( model= "gemini-2.5-flash" , name= "time_agent" , instruction= """ あなたは時刻案内をするエージェントです。 ユーザーから尋ねられた都市の現在時刻を答えてください。 利用可能なツールを使って情報を取得し、最終的な回答を生成してください。 """ , tools=[get_time] ) # runner の定義 APP_NAME = "My Agent App" SESSION_SERVICE = InMemorySessionService() RUNNER = Runner( agent=time_agent, app_name=APP_NAME, session_service=SESSION_SERVICE, ) async def stream_agent_events (query: str , user_id: str , session_id: str ): ''' # 概要 エージェントを実行します。 # 引数 query (str): エージェントに投げかけるクエリ(プロンプト) user_id (str): ユーザー ID session_id (str): セッション ID ''' # 既存セッションがなければ新規作成 session = await SESSION_SERVICE.get_session(app_name=APP_NAME, user_id=user_id, session_id=session_id) if not session: await SESSION_SERVICE.create_session(app_name=APP_NAME, user_id=user_id, session_id=session_id) # ユーザークエリを所定の形式で格納 content = types.Content(role= 'user' , parts=[types.Part(text=query)]) # エージェントの実行 async for event in RUNNER.run_async(user_id=user_id, session_id=session_id, new_message=content): parts = event.content.parts message = event.content.parts[ 0 ].text if message: yield (f "--- Message: {message}" ) return async def main (): """ エージェントを実行し、ストリーミングされたメッセージを出力するメイン関数 """ user_id= "test_user" session_id= "test_session" query= "東京の現在時刻は?" # async for を使って非同期ジェネレータを処理 async for message in stream_agent_events(query=query, user_id=user_id, session_id=session_id): print (message) # スクリプトのエントリーポイント if __name__ == "__main__" : asyncio.run(main()) ソースコードの実行 ADK で記述したエージェントは、以下で紹介されているように、ADK に組み込まれた動作テスト用 Web UI を使って動作確認することができます。 参考 : Quickstart 参考 : ADKのSequential agentsを使って実装するマルチエージェント - G-gen Tech Blog ADK のテスト用 Web UI あるいは、以下の記事のように Vertex AI Agent Engine にデプロイして、リモートから呼び出して実行することもできます。 参考 : Agent Development Kitでエージェントを開発してAgent Engineにデプロイしてみた - G-gen Tech Blog しかし今回の記事では、Cloud Run などにホストされたアプリケーションに組み込むことを想定して、異なる方法で実行します。 まずは、前述のソースコードを main.py として保存します。 実行環境には、 pip install google-adk で ADK をインストールします。必要に応じて venv を用意してください。 さらに、以下のようなコマンドを実行して、環境変数を定義します。これらの環境変数は、ADK が Gemini モデルを呼び出す先の API エンドポイントを決めるのに必要です。 .env ファイルなどに書き込んでおき、実行前に source .env コマンドを実行する方法で変数を定義しても構いません。実際の動作環境では、Cloud Run service のリビジョンに環境変数で定義する想定です。 export GOOGLE_GENAI_USE_VERTEXAI = " TRUE " export GOOGLE_CLOUD_PROJECT = " my-project " export GOOGLE_CLOUD_LOCATION = " global " 上記を実施したうえで main.py を実行すると、以下のように出力されます。 $ python main.py --- Tool: get_weather ( city: Tokyo ) --- --- Message: 東京の現在時刻は 2025 年 7 月 21 日 9 時 36 分です。 Runner と非同期処理 前述のソースコードの関数 stream_agent_events は、 asyncio.run によって非同期実行されています。 asyncio は Python の標準ライブラリであり、並行処理を実現するための機能です。 参考 : Runtime 参考 : Build Your First Intelligent Agent Team: A Progressive Weather Bot with ADK Runner は、エージェントを動かすためのエンジンです。run_async でプロンプトを渡して実行すると、イベントを順次返します。このソースコードでは非同期関数 stream_agent_events の中で Runner を実行しており、エージェントにより生成された結果は yield によって順次、呼び出し元に返されて print されます。 これにより、複数のエージェントによって長い処理が行われる場合でも、処理の進行状況をユーザーに知らせることができます。 Workflow Agents 概要 Workflow Agents は、あらかじめ定義された順番でサブエージェント(子エージェント)を呼び出すためのエージェントです。Workflow Agents の動作は決定論的、つまり事前に定義したとおりに動くものであり、必ず指定した順番でサブエージェントが実行されます。モデルの指定も存在しません。 参考 : Workflow Agents Workflow Agents には以下の種類があります。 名称 説明 Sequential Agents サブエージェントを指定した順番で順次実行 Parallel Agents サブエージェントを並列で実行 Loop Agents サブエージェントを指定した順番で順次実行。指定条件が満たされるまで繰り返す Workflow Agents は、その制御性の高さから以下のようなユースケースに適しています。 顧客からの問い合わせを定型的なプロセスで処理する 例: 内容判断 → チケット起票 → 担当者割り当て 決まった手順で行われるデータ処理やバッチ処理の自動化 ビジネスプロセスオートメーション(BPA) 実装例 サブエージェントを順次実行する Sequential Agents の実装例を以下に示します。 import asyncio import datetime import logging from google.adk.agents import LlmAgent, SequentialAgent from google.adk.runners import Runner from google.adk.sessions import InMemorySessionService from google.adk.tools import google_search from google.genai import types def get_time (city: str ): ''' # 概要 指定された都市の現在時刻を取得します。 # 引数 city (str): 対象の都市名 (Tokyo / Los Angels / London) ''' print (f "--- Tool: get_weather (city: {city}) ---" ) if "Tokyo" in city: tz = datetime.timezone(datetime.timedelta(hours= 9 )) elif "Los Angels" in city: tz = datetime.timezone(datetime.timedelta(hours=- 7 )) elif "London" in city: tz = datetime.timezone(datetime.timedelta(hours= 0 )) else : tz = None if tz: now = datetime.datetime.now(tz) else : now = None message = { "city" : city, "datetime" : now } return message # 時刻案内エージェント time_agent = LlmAgent( model= "gemini-2.5-flash" , name= "time_agent" , instruction= """ あなたは時刻案内をするエージェントです。 tools を使ってユーザーが住んでいる都市の現在時刻を取得します。 """ , tools=[get_time], output_key = "city_and_datetime" ) # 雑学エージェント trivia_agent = LlmAgent( model= "gemini-2.5-flash" , name= "time_agent" , instruction= """ # 役割 あなたは雑学を披露するエージェントです。 ユーザーが住んでいる国にとって、今日がなんの日か(その国の祝日、記念日など)を調べて回答します。 どうしても特別な日でないときは、最も近い祝日や記念日などを返してください。 # ユーザーが住んでいる国と日付 {city_and_datetime} """ , tools=[google_search] ) # シーケンシャルエージェント root_agent = SequentialAgent( name= "root_agent" , sub_agents=[time_agent, trivia_agent], description= "本日日付を取得し、次にその日に関する雑学を披露する" , ) # runner の定義 APP_NAME = "My Agent App" SESSION_SERVICE = InMemorySessionService() RUNNER = Runner( agent=root_agent, app_name=APP_NAME, session_service=SESSION_SERVICE, ) async def stream_agent_events (query: str , user_id: str , session_id: str ): ''' # 概要 エージェントを実行します。 # 引数 query (str): エージェントに投げかけるクエリ(プロンプト) user_id (str): ユーザー ID session_id (str): セッション ID ''' # 既存セッションがなければ新規作成 session = await SESSION_SERVICE.get_session(app_name=APP_NAME, user_id=user_id, session_id=session_id) if not session: await SESSION_SERVICE.create_session(app_name=APP_NAME, user_id=user_id, session_id=session_id) # ユーザークエリを所定の形式で格納 content = types.Content(role= 'user' , parts=[types.Part(text=query)]) # エージェントの実行 async for event in RUNNER.run_async(user_id=user_id, session_id=session_id, new_message=content): parts = event.content.parts message = event.content.parts[ 0 ].text if message: yield (f "--- Message: {message}" ) return async def main (): """ エージェントを実行し、ストリーミングされたメッセージを出力するメイン関数 """ user_id= "test_user" session_id= "test_session" query= "私は東京在住です。" # async for を使って非同期ジェネレータを処理 async for message in stream_agent_events(query=query, user_id=user_id, session_id=session_id): print (message) # # ロギングを設定(必要に応じてコメントを外す) # logging.basicConfig( # level=logging.DEBUG, # format='%(asctime)s - %(levelname)s - %(name)s - %(message)s' # ) # スクリプトのエントリーポイント if __name__ == "__main__" : asyncio.run(main()) 実行結果 出力は以下のようになります。 $ python sequential.py --- Tool: get_weather ( city: Tokyo ) --- --- Message: 現在の時刻は、 2025 年 7 月 21 日 9 時 40 分です。 --- Message: 東京にお住まいのあなたにとって、 2025 年 7 月 21 日は「海の日」です。 海の日とは、海の恩恵に感謝し、海洋国家である日本の繁栄を願う国民の祝日です。 毎年 7 月の第 3 月曜日と定められており、 2025 年は 7 月 21 日がこれに当たります。 世界で唯一、「海の日」を国民の祝日としているのは日本だけです。 time_agent と trivia_agent の情報の受け渡しに使われている output_key については、以下の記事も参照してください。 参考 : ADKのSequential agentsを使って実装するマルチエージェント - G-gen Tech Blog 詳細のロギング 前述のソースコード内でコメントアウトしているロギング設定の行から # を削除してコメントでなくすると、ADK の処理の詳細が標準出力に出力されます。エージェントがどのような順番で呼び出され、またどのようなプロンプトで呼び出されたのかがわかるため、デバッグやチューニングのときに役立ちます。 以下は、一部を省略していますが、詳細なロギング出力の結果です。 2025-07-21 01:11:24,627 - DEBUG - asyncio - Using selector: EpollSelector 2025-07-21 01:11:24,926 - INFO - google_adk.google.adk.models.google_llm - Sending out request, model: gemini-2.5-flash, backend: GoogleLLMVariant.VERTEX_AI, stream: False 2025-07-21 01:11:24,926 - INFO - google_adk.google.adk.models.google_llm - LLM Request: ----------------------------------------------------------- System Instruction: あなたは時刻案内をするエージェントです。 tools を使ってユーザーが住んでいる都市の現在時刻を取得します。 You are an agent. Your internal name is "time_agent". ----------------------------------------------------------- Contents: {"parts":[{"text":"私は東京在住です。"}],"role":"user"} ----------------------------------------------------------- Functions: get_time: {'city': {'type': <Type.STRING: 'STRING'>}} ----------------------------------------------------------- 〜〜〜〜〜(略)〜〜〜〜〜 --- Tool: get_weather (city: Tokyo) --- 2025-07-21 01:11:27,100 - INFO - google_adk.google.adk.models.google_llm - Sending out request, model: gemini-2.5-flash, backend: GoogleLLMVariant.VERTEX_AI, stream: False 2025-07-21 01:11:27,101 - INFO - google_adk.google.adk.models.google_llm - LLM Request: ----------------------------------------------------------- System Instruction: あなたは時刻案内をするエージェントです。 tools を使ってユーザーが住んでいる都市の現在時刻を取得します。 You are an agent. Your internal name is "time_agent". ----------------------------------------------------------- Contents: {"parts":[{"text":"私は東京在住です。"}],"role":"user"} {"parts":[{"function_call":{"args":{"city":"Tokyo"},"name":"get_time"}}],"role":"model"} {"parts":[{"function_response":{"name":"get_time","response":{"city":"Tokyo","datetime":"2025-07-21T10:11:26.994246+09:00"}}}],"role":"user"} ----------------------------------------------------------- Functions: get_time: {'city': {'type': <Type.STRING: 'STRING'>}} ----------------------------------------------------------- 〜〜〜〜〜(略)〜〜〜〜〜 LLM Request: ----------------------------------------------------------- System Instruction: # 役割 あなたは雑学を披露するエージェントです。 ユーザーが住んでいる国にとって、今日がなんの日か(その国の祝日、記念日など)を調べて回答します。 どうしても特別な日でないときは、最も近い祝日や記念日などを返してください。 # ユーザーが住んでいる国と日付 東京の現在時刻は2025-07-21T10:11:26.994246+09:00です。 You are an agent. Your internal name is "time_agent". ----------------------------------------------------------- Contents: {"parts":[{"text":"私は東京在住です。"}],"role":"user"} {"parts":[{"function_call":{"args":{"city":"Tokyo"},"name":"get_time"}}],"role":"model"} {"parts":[{"function_response":{"name":"get_time","response":{"city":"Tokyo","datetime":"2025-07-21T10:11:26.994246+09:00"}}}],"role":"user"} {"parts":[{"text":"東京の現在時刻は2025-07-21T10:11:26.994246+09:00です。"}],"role":"model"} {"parts":[{"text":"Continue processing previous requests as instructed. Exit or provide a summary if no more outputs are needed."}],"role":"user"} ----------------------------------------------------------- Functions: ----------------------------------------------------------- シーケンシャルにエージェントが呼び出されており、またシステムインストラクションに指定した output_key である {city_and_datetime} が正しく反映されていることもわかります。 Tools 概要 Tools は、LLM Agent が道具として使うプログラムです。Tools には以下のような種類があります。 名称 説明 Function tools コーディングされた関数を実行する。外部処理を呼び出したり、計算処理を行わせる等。また Agent-as-a-Tool ではエージェントから他のエージェントを tool として呼び出し可能。 Build-in tools ADK に組み込みの Tool。Google 検索実行ツール、コード生成・実行ツール、Vertex AI Search での検索実行ツール、BigQuery ツールなど。例えば自然言語の指示に基づいて BigQuery へクエリするといった処理を、コードを書くことなく実現できる。 Third party tools CrewAI や LangChain などで定義された Tools を実行。 Google Cloud tools Apigee API Hub、Application Integration、MCP Toolbox for Database などを呼び出し。 MCP tools エージェントから MCP server を呼び出し。 LLM Agent は Tools を呼び出すかどうか、またどういったパラメータで呼び出すかを自律的に判断し、実行します。これにより、ADK アプリケーションは LLM が持つ能力を超えて、さまざまなタスクを行うことができます。 参考 : Tools 関数の記述 LLM が適切に Tools を呼び出すためには、例えば Function tools においては、適切な方法で関数を記述することが重要です。 参考 : Function tools - Best Practices わかりやすい関数名、引数名、Tool 名 LLM が適切に判断して Tools を呼び出すためには、関数名や引数名、Tool 名などを、LLM が理解しやすい 明確でわかりやすい名称 にする必要があります。一般的すぎる名称は避け、例えばその関数が何をするものなのか明確になるよう、 動詞_目的語() のような名称とします。 Docstring を記述する 関数の Docstring (関数の説明)を適切に記載することが重要です。LLM はこれらを読み取り、Tools を呼び出すべきかどうか、またどのような引数を与えるべきかを判断します。 引数はシンプルに Tools の関数の引数は少なめに、シンプルにします。複雑すぎると、LLM が関数を適切に使用できません。また、データ型もカスタムのものより str や int などシンプルなものが望ましいです。 戻り値は辞書型 Tools の実行結果を LLM が適切に使用できるよう、 戻り値のフォーマット も重要です。Python においては辞書型(dictionary)、Java においては Map 型で返すのが理想的です。 要約のスキップ 先程の2つのサンプルソースコードでは、簡単な Function tools を使って現在時刻を取得しました。 通常、Function tools 等が実行されると、tool の実行結果は LLM に渡され、LLM はそれを解釈して最終回答を生成します。しかし、例えば tool の実行結果をそのままユーザーに返したい場合や、あるいは処理時間短縮のために tool の実行結果を LLM に解釈させずに次のエージェントに渡したいケースもあります。 その場合、 要約をスキップ させることで、LLM による解釈をスキップして tool の実行結果をそのまま LLM Agent の最終回答とさせることができます。 先程の Sequential agents のサンプルコードの tool 関数定義を、以下のように修正します。変更点は、ToolContext を import した点と、関数の引数に tool_context: ToolContext を追加した点、また tool_context.actions.skip_summarization = True を追加した点です。 # 〜〜〜〜〜(略)〜〜〜〜〜 from google.adk.tools import google_search, ToolContext # 〜〜〜〜〜(略)〜〜〜〜〜 def get_time (city: str , tool_context: ToolContext): ''' # 概要 指定された都市の現在時刻を取得します。 # 引数 city (str): 対象の都市名 (Tokyo / Los Angels / London) ''' # ツールの結果は要約されずそのままアウトプットとして扱われる tool_context.actions.skip_summarization = True print (f "--- Tool: get_weather (city: {city}) ---" ) if "Tokyo" in city: tz = datetime.timezone(datetime.timedelta(hours= 9 )) elif "Los Angels" in city: tz = datetime.timezone(datetime.timedelta(hours=- 7 )) elif "London" in city: tz = datetime.timezone(datetime.timedelta(hours= 0 )) else : tz = None if tz: now = datetime.datetime.now(tz) else : now = None message = { "city" : city, "datetime" : now } return message これにより、関数が return した結果は LLM によって解釈されず、そのまま time_agent の最終回答として、次のエージェントに渡されます。 しかしこのとき、ロギングを詳細に出力していると、次に実行されたエージェント trivia_agent のシステムインストラクションで、output_key が反映されていないことに気が付きます。詳細ログは以下のようになりました。 ----------------------------------------------------------- System Instruction: # 役割 あなたは雑学を披露するエージェントです。 ユーザーが住んでいる国にとって、今日がなんの日か(その国の祝日、記念日など)を調べて回答します。 どうしても特別な日でないときは、最も近い祝日や記念日などを返してください。 # ユーザーが住んでいる国と日付 You are an agent. Your internal name is "time_agent". ----------------------------------------------------------- # ユーザーが住んでいる国と日付 の下には、本来 {city_and_datetime} があるため、tool が返した辞書型のデータ( city と datetime )が入っているべきです。しかし、要約をスキップした場合は、output_key が次のエージェントに渡されません。これは、output_key に値が代入されるのは LLM による最終回答生成後であるためであると考えられます。要約をスキップした場合は output_key に値が入りません。 しかしこのような状況でも、エージェント trivia_agent は以下のような回答を生成しました。 東京にお住まいのあなたにとって、2025年7月21日は「海の日」です。海の日とは、「海の恩恵に感謝するとともに、海洋国日本の繁栄を願う日」として制定された国民の祝日です。 この日は毎年7月の第3月曜日と定められており、2025年は7月21日がこれに当たります。 また、海の日以外にも、7月21日には「日本三景の日」、「神前結婚記念日」、「自然公園の日」、「烏骨鶏の日」といった様々な記念日があります。 これは、LLM Agent は output_key で情報を渡されなくても、これまで実行された LLM Agent や Tools の実行結果をコンテキストとして保持しており、そのコンテキストに基づいて生成を行っているためであると考えられます。詳細ロギングを確認すると、trivia_agent の実行時に以下のようなログが出力されていました。 2025-07-21 01:35:40,257 - INFO - google_adk.google.adk.models.google_llm - LLM Request: ----------------------------------------------------------- System Instruction: # 役割 あなたは雑学を披露するエージェントです。 ユーザーが住んでいる国にとって、今日がなんの日か(その国の祝日、記念日など)を調べて回答します。 どうしても特別な日でないときは、最も近い祝日や記念日などを返してください。 # ユーザーが住んでいる国と日付 You are an agent. Your internal name is "time_agent". ----------------------------------------------------------- Contents: {"parts":[{"text":"私は東京在住です。"}],"role":"user"} {"parts":[{"function_call":{"args":{"city":"Tokyo"},"name":"get_time"}}],"role":"model"} {"parts":[{"function_response":{"name":"get_time","response":{"city":"Tokyo","datetime":"2025-07-21T10:35:40.174769+09:00"}}}],"role":"user"} ----------------------------------------------------------- Functions: ----------------------------------------------------------- Contents: のブロックの中にある function_response という行が、関数の実行結果です。 # ユーザーが住んでいる国と日付 の直下にあるべき output_key は空文字列になっているものの、Contents として含まれている情報を LLM Agent がコンテキストとして使って生成を行っていることがわかります。output_key を使ったほうが、より複雑なプロンプトで役割やタスク、背景、フォーマットを指定する際に効果的であると考えられますが、output_key を使わなくても、ある程度の精度で他のエージェントや tools の出力結果がコンテキストとして使われることがわかります。 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-genの山田です。BigQueryの保存済みクエリ機能を使うと、クエリエディタで記述した SQL を保存して他のユーザーと共有することができます。SQL をプロジェクトにアップロードしようとした際に [プロジェクトにアップロードする] > [SQL クエリ] のメニューがグレーアウトして選択できない事象が起きました。この事象の原因と対処法を解説します。 事象 原因 対処法 概要 Dataform API の有効化 IAM ロールが正しく設定されていること クエリの移行 事象 BigQuery のコンソール画面でクエリエディタを開き、SQL クエリをプロジェクトにアップロードしようとしたところ、以下の図のように [プロジェクトにアップロードする] > [SQL クエリ] のメニューがグレーアウトし、選択できない状態でした。 原因 原因は、BigQuery の保存済みクエリの仕様変更にあります。 従来の保存済みクエリは、 Dataform を基盤とした新しい保存済みクエリへ移行される予定です。これは、2025年2月と6月に Google Cloud から「Transition from classic saved queries to new saved queries」という件名のメールで案内されています。この新しい保存済みクエリを利用するには、対象プロジェクトで Dataform API を有効化し、ユーザーに適切な IAM 権限 を付与する必要があります。 今回の事象は、この Dataform API が有効になっていなかったために発生しました。 2025年6月現在、2025年3月に予定されていた移行は延期されており、サポート終了時期は公開されていません。2025年末までに新たな情報が更新される予定です。 参考 : 保存済みクエリの概要 - 従来の保存したクエリ 対処法 概要 新しい保存済みクエリを使用するには以下の条件を満たしている必要があります。 Dataform API の有効化 IAM ロールが正しく設定されていること Dataform API の有効化 SQL クエリをアップロードしたいプロジェクトで Dataform API が有効になっていることを確認します。Google Cloud コンソールで [API とサービス] > [ライブラリ] へ移動し、「Dataform API」を検索して有効化してください。 参考 : Dataform で SQL ワークフローを作成して実行する - 始める前に IAM ロールが正しく設定されていること 新しい保存済みクエリの閲覧や編集には、適切な IAM ロールが必要です。クエリは Dataform のリソースとして保存されるため、Dataform 関連の権限が付与されているか確認してください。 BigQuery の新しい保存済みクエリを操作するには、操作者アカウントがプロジェクトに対して以下の IAM ロールを持っている必要があります。 操作内容 必要なIAMロール(いずれか一つ) クエリの作成 BigQuery ジョブユーザー( roles/bigquery.jobUser ) コード作成者 ( roles/dataform.codeCreator ) クエリの編集 BigQuery ジョブユーザー( roles/bigquery.jobUser ) コード編集者( roles/dataform.codeEditor ) クエリの表示 BigQuery ジョブユーザー( roles/bigquery.jobUser ) コード閲覧者( roles/dataform.codeViewer ) 参考 : 保存済みクエリを作成する - 必要な権限 クエリの移行 従来の保存済みクエリは、以下の公式ドキュメントを参考に、新しい保存済みクエリに移行することができます。2025年6月現在では、従来の保存済みクエリの廃止時期は未定ですが、早めの移行が推奨されます。 参考 : 保存済みクエリを管理する - 従来の保存済みクエリを移行する 山田 剛史 (記事一覧) クラウドソリューション部 クラウドサポート課 2025年6月にG-genに入社。IT基盤領域やグループウェアが得意。Google Workspace や Google Cloud を日々勉強中。
アバター
G-genの福井です。Cloud Storage バケットへのアクセスを送信元 IP アドレスに基づいて制御する IP フィルタリング機能の概要と設定方法、そして VPC Service Controls との違いについて解説します。 はじめに Cloud Storage の IP フィルタリングとは 機能の概要 ユースケース VPC Service Controls との違い 機能比較 使い分けのポイント 制限事項 設定方法 前提条件 必要な権限 IP フィルタリング設定用 JSON バケット作成時にフィルタリング設定 既存バケットにフィルタリング設定 フィルタリング ルールを取得 フィルタリング ルールを無効化 IPフィルタリングのバイパス設定 概要 ユースケース 設定方法 運用の注意点 はじめに Cloud Storage は、高い耐久性とスケーラビリティを持つオブジェクトストレージサービスであり、その用途は多岐にわたります。様々なネットワーク環境からアクセスが可能であるため、意図しないリクエストを防ぐためのアクセス制御が重要です。 Google Cloud は IAM や VPC Service Controls といった多様なセキュリティ機能を提供しています。その中でも、送信元のパブリック IP アドレスに基づいてアクセスをシンプルに制御したい、という要件に応えるのが当記事で解説する IP アドレスフィルタリング機能 です。 当記事では、IP アドレスフィルタリング機能の概要から、類似機能である VPC Service Controls との違い、使用上の注意点、そして具体的な設定手順までを解説します。 Cloud Storage の IP フィルタリングとは 機能の概要 Cloud Storage の IP フィルタリングは、バケットへのアクセスを 送信元の IP アドレスに基づいて制御する 機能です。 この機能を有効にすると、許可設定した IP アドレスからのリクエストのみが許可されます。許可設定していない IP アドレスからのリクエストは、ステータスコード 403 Forbidden で拒否されます。 このフィルタリングは、バケット単位で設定し、そのバケット内の全オブジェクトに適用されます。制御できるアクセス元は以下の通りです。 アクセス元の種類 説明 パブリック IP インターネット経由でのアクセスを、送信元のグローバル IP アドレスで制御します。 VPC ネットワーク VPC ネットワーク内からのアクセスを、その VPC ネットワークで予約された IP アドレスで制御します。 この機能の重要な点は、Cloud Storage の認証システムの前に評価されることです。つまり、たとえ有効な認証情報を持っていたとしても、許可されていない IP アドレスからのリクエストはバケットに到達する前にブロックされます。 参考 : IP アドレス フィルタリングの概要 ユースケース この機能は、特定のネットワーク環境からのアクセスのみに制限したい場合に有効です。 ユースケース 説明 特定の拠点からのアクセス制限 本社や支社のオフィス、あるいは特定のデータセンターの固定 IP アドレスからのみ、バケットへのアクセスを許可したい場合に使用します。 特定のアプリケーション環境からのアクセス制限 Google Cloud の VPC ネットワーク内で稼働するアプリケーションからのアクセスのみに限定したい場合に使用します。これにより、意図しない他のリソースからのアクセスをネットワークレベルで防ぐことができます。 多層的なセキュリティの実現 IAM による認証・認可に加え、ネットワークレベルでのアクセス制御を組み合わせることで、認証情報が万が一漏洩した際の情報流出リスクを低減し、より強固なセキュリティを実現します。 VPC Service Controls との違い Cloud Storage へのアクセスをネットワークレベルで制御する機能として、IP アドレスフィルタリングの他に VPC Service Controls があります。両者は似ているようで、その目的と機能は大きく異なります。 機能比較 特徴 IP アドレスフィルタリング VPC Service Controls 目的 送信元 IP に基づくシンプルなアクセス制御 サービス境界(Perimeter)を作成し、境界の外から中へのアクセスを防いだり、逆に境界の中から外へのデータ流出等を防ぐ 適用範囲 Cloud Storage のバケット単位 単一または複数のプロジェクトをサービス境界に含めることが可能。組織レベルでのデータガバナンスを実現する 主な制御要素 送信元のパブリック IP または VPC 送信元のネットワークロケーション(VPC, オンプレミス)、ID、デバイスなど、複数のコンテキスト 設定の複雑さ シンプル 。許可したい IP のリストを定義するのみ 高度 。サービス境界、アクセスレベル、ブリッジなどの設計が必要 使い分けのポイント どちらの機能を選択するかは、セキュリティ要件によって決まります。 セキュリティ要件 推奨される機能 「特定のオフィスの固定 IP からのみアクセスさせたい」など、要件が シンプル な場合 IP アドレスフィルタリング IP アドレスだけでなく、ユーザー ID やデバイス情報なども含めた 多角的なアクセス制御 が必要な場合 VPC Service Controls Cloud Storage だけでなく、BigQuery など他のサービスも含めて、組織として データ持ち出しを厳密に防ぎたい 場合 VPC Service Controls 基本的には、特定の IP アドレスからのアクセスをシンプルに制限したい場合は IP アドレスフィルタリングを、より広範で強力なデータ保護境界を構築したい場合は VPC Service Controls を選択します。 blog.g-gen.co.jp 制限事項 IP アドレスフィルタリング機能には、使用する上で制限があります。 制限事項 内容 許可される IP CIDR ブロックの最大数 パブリックネットワークと VPC ネットワークを合わせて、最大 200 個の IP CIDR ブロックを指定できます。 許可される VPC ネットワークの最大数 最大 25 個 の VPC ネットワークを指定できます。 リージョンエンドポイントのサポート リージョンエンドポイントは、Private Service Connect を使用する場合にのみサポートされます。 一部 Google Cloud サービスとの連携 BigQuery のように、データのインポート/エクスポートで Cloud Storage を使用するサービスからのアクセスが制限されます。サービスの中断を避けるため、これらのサービスがアクセスするバケットでは IP フィルタリングの使用は推奨されません。 App Engine からのアプリケーション App Engine アプリケーションが Cloud Storage のデータにアクセスする場合は、VPC を介して使用することが推奨されます。 Cloud Shell のサポート Cloud Shell からのアクセスはサポートされていません。 参考 : 制限事項 設定方法 ここからは、実際に IP アドレスフィルタリング機能を設定する手順を解説します。 2025年7月現在、Google Cloud コンソールからの設定には対応していません。 当記事では gcloud コマンドを使った手順を紹介します。 前提条件 IP フィルタリングの設定には、Google Cloud CLI バージョン 526.0.0 以降が必要です。古いバージョンの CLI を使用して、IP フィルタリングの設定を行うと、以下のエラーが発生します。 Found invalid JSON/YAML for the IP filter rule. エラーが発生した場合は、以下のコマンドでバージョンを確認し、必要に応じて更新してください。 # バージョン確認 gcloud version | head -n 1 # バージョン更新 gcloud components update --version = 526 . 0 . 0 必要な権限 IP アドレスフィルタリングの設定には、以下のIAM権限が必要です。 操作 権限 IP フィルタリング ルールを使用してバケットを作成 storage.buckets.create storage.buckets.setIpFilter バケットの IP フィルタリング ルールを更新 storage.buckets.update storage.buckets.setIpFilter バケットの IP フィルタリング ルールを取得 storage.buckets.get storage.buckets.getIpFilter バケット IP フィルタリングを無効 storage.buckets.update storage.buckets.setIpFilter これらの権限を取得する最も簡単な方法は、対象プロジェクトまたはバケットに対して ストレージ管理者 ( roles/storage.admin )のロールを付与することです。この事前定義ロールには、上記の権限が含まれています。また、これらの権限を持つカスタムロールを個別に作成することも可能です。 IP フィルタリング設定用 JSON IP フィルタリングの設定は、バケットの新規作成時、または既存のバケットに対して行います。いずれのシナリオでも、設定内容を記述した JSON ファイルをコマンドで読み込ませて設定します。 特定のパブリック IP 範囲 指定したパブリック IPv4 アドレス範囲からのアクセスを許可し、VPC からのアクセスをブロックする設定です。 { " mode ": " Enabled ", " publicNetworkSource ": { " allowedIpCidrRanges ": [ " 192.0.2.0/24 " ] } , " allowCrossOrgVpcs ": false , " allowAllServiceAgentAccess ": false } 特定の VPC ネットワーク範囲 指定した VPC の IPv4 アドレスからのアクセスを許可し、パブリック IP からのアクセスをブロックする設定です。 { " mode ": " Enabled ", " vpcNetworkSources ": [ { " network ": " projects/[PROJECT_ID]/global/networks/[NETWORK_NAME] ", " allowedIpCidrRanges ": [ " 192.0.2.0/24 " ] } , ] , " allowCrossOrgVpcs ": false , " allowAllServiceAgentAccess ": false } 設定項目の解説 項目 説明 mode フィルタリングのモードを指定します。 Enabled : IP フィルタリングを有効にし、設定されたルールに基づいてリクエストを評価します。 Disabled : フィルタリングを無効にし、すべてのリクエストを許可します(ルールは保持されます)。 publicNetworkSource パブリック IP アドレスからのアクセスに関するルールを定義するオブジェクトです。 allowedIpCidrRanges バケットへのアクセスを許可するパブリックな IPv4 または IPv6 の CIDR 範囲のリストです。(例: ["192.0.2.0/24", "2001:db8::/32"] ) vpcNetworkSources VPC ネットワークからのアクセスに関するルールを定義するオブジェクトのリストです。 network VPC ネットワークの名前です。 PROJECT_ID は、VPC ネットワークが存在するプロジェクト ID NETWORK_NAME は、バケットへのアクセスを許可する VPC ネットワークの名前 allowCrossOrgVpcs 組織(Organization)をまたいだ VPC ネットワークからのアクセスを許可するかどうかを指定します。 true : 組織をまたいだアクセスを許可します。 false : バケットと同じ組織内の VPC に限定します。(デフォルト) allowAllServiceAgentAccess Google Cloud のサービスエージェントからのアクセスを、IP フィルタリングの設定に関わらずすべて許可するかどうかを指定します。 true : 他の Google Cloud サービスがサービスエージェントを使ってバケットにアクセスすることを許可します。 false : 許可しません。 参考 : Create a bucket with IP filtering rules - Bucket IP filtering configurations バケット作成時にフィルタリング設定 gcloud alpha storage buckets create gs:// [ BUCKET_NAME ] --ip-filter-file =[ IP_FILTER_CONFIG_FILE ] BUCKET_NAME には新規に作成するバケット名、 IP_FILTER_CONFIG_FILE にはIPフィルタリング設定用JSONのファイルパスを指定します。 参考 : IP フィルタリング ルールのあるバケットを作成する 既存バケットにフィルタリング設定 gcloud alpha storage buckets update gs:// [ BUCKET_NAME ] --ip-filter-file =[ IP_FILTER_CONFIG_FILE ] BUCKET_NAME には IP フィルタリングを設定するバケット名、 IP_FILTER_CONFIG_FILE にはIPフィルタリング設定用JSONのファイルパスを指定します。 参考 : 既存のバケットで IP フィルタリング ルールを作成または更新する フィルタリング ルールを取得 gcloud alpha storage buckets describe gs:// [ BUCKET_NAME ] --format =" default(ip_filter_config) " BUCKET_NAME には IP フィルタリングを取得するバケット名を指定します。 参考 : バケット IP フィルタリング ルールを取得する フィルタリング ルールを無効化 gcloud alpha storage buckets update gs:// [ BUCKET_NAME ] --clear-ip-filter BUCKET_NAME には IP フィルタリングを無効にするバケット名を指定します。 参考 : バケット IP フィルタリング ルールを無効にする IPフィルタリングのバイパス設定 概要 Cloud Storage の IP アドレスフィルタリングにおいて バイパス設定 を行うと、特定の IAM プリンシパル(ユーザー、サービスアカウントなど)は、 送信元 IP アドレスに関わらず 、バケットの作成、削除、構成に関する IP フィルタリング制限の対象から除外されます。 ユースケース ユースケース 説明 バケット ロックアウト IP フィルタリングの設定を誤って追加し、バケットにアクセスできなくなった場合 予期しない IP 変更 ネットワークの変更により IP アドレスが予期せず変更され、ロックアウトされた場合 設定方法 IAM 権限 storage.buckets.exemptFromIpFilter をプリンシパルに付与します。この権限はカスタムロールを使用して権限を付与します。 カスタムロールの作成 gcloud iam roles create ip_filter_bypasser \ --project =[ PROJECT_ID ] \ --title =" Custom IP Filter Bypasser " \ --description =" Cloud Storage IPフィルタリングをバイパスする " \ --permissions = storage.buckets.exemptFromIpFilter PROJECT_ID には、Google Cloud プロジェクト ID を指定します。 IAM ポリシーへのバインディング 作成したカスタムロールを対象のプリンシパル(この例ではユーザーアカウント)に付与します。 gcloud projects add-iam-policy-binding [ PROJECT_ID ] \ --member =" user:[USER_EMAIL] " \ --role =" projects/[PROJECT_ID]/roles/ip_filter_bypasser " PROJECT_ID には、Google Cloud プロジェクト ID、 USER_EMAIL には、カスタムロールを付与するユーザーのメールアドレスを指定します。 運用の注意点 storage.buckets.exemptFromIpFilter 権限は非常に強力です。この権限を持つプリンシパルの認証情報が漏洩した場合、IP フィルタリングによる保護が無効化されてしまいます。 使用にあたっては 最小権限の原則 を遵守し、本当に必要なプリンシパルにのみ、必要最小限の期間だけ付与するようにしてください。恒久的な権限としてではなく、 Privileged Access Manager(PAM) を使用して、期間限定で付与する運用が理想的です。 参考 : IP フィルタリング ルールをバイパスする 参考 : Privileged Access Manager(PAM)を解説! 福井 達也 (記事一覧) カスタマーサクセス課 エンジニア 2024年2月 G-gen JOIN 元はアプリケーションエンジニア(インフラはAWS)として、PM/PL・上流工程を担当。G-genのGoogle Cloudへの熱量、Google Cloudの魅力を味わいながら日々精進
アバター
G-genの杉村です。当記事では、Google Workspace の便利なTipsを10個ご紹介します。これらの Tips を活用して、作業効率の向上に役立ててください。 Gemini サイドパネルを使う 進化した Gemini アプリを使いこなす ドキュメントは自動で版管理される ファイルが格納されている Google ドライブのフォルダへ瞬時に移動 「候補」でファイル移動を効率化 最短で共有リンクをコピー ドキュメントの任意の場所へのリンク Google ドキュメントにコードブロックを挿入 コネクテッドシートで BigQuery データを可視化 Looker Studio でリアルタイムにデータを可視化 Gemini サイドパネルを使う Google Workspace に統合された Gemini for Google Workspace の サイドパネル は、様々な業務をサポートする強力なアシスタントです。 Gemini サイドパネルを開くには、Google ドライブの操作画面や、Google ドキュメント、スプレッドシートなどの操作画面の右上にある 星型のマーク をクリックします。サイドパネルの下部分のテキストボックスに、Gemini への指示を入力します。 Gemini サイドパネルの開き方 例えば、Gmail で受信した英語の長文メールや、Google ドライブに保存された英語の契約書や利用規約の PDF(テキストデータとして認識可能な場合)の内容を把握したい場合、Gemini サイドパネルに「この内容を日本語で要約して」と指示するだけで、素早く概要を掴むことができます。 他にも、文章の作成支援、アイデアのブレインストーミング、情報検索など、多岐にわたるタスクをサイドパネルから直接実行できます。 英語の規約や契約書を日本語で要約 参考 : サイドパネルを使用して Gemini と共同作業を行う 進化した Gemini アプリを使いこなす スタンドアロンの Gemini アプリ (Web 版およびモバイルアプリ版)も非常に強力です。特に、最新モデルである Gemini 2.5 Pro や Gemini 2.5 Flash の登場により、日本語の処理能力が大幅に向上しました。 Google Workspace ユーザーであれば、誰でも Gemini アプリを利用できます(管理者によって禁止されている場合を除く)。 https://gemini.google.com にアクセスしてください。 Gemini アプリは以下のようなタスクで活用できます。 タスク 概要 文章作成 メール、ブログ記事、レポートなどの下書き作成 データ整備 表記揺れのあるデータの整備や突合(名寄せ、顧客リストのクレンジングなど) コーディング支援 コード生成、デバッグ、解説 文章レビュー 作成した文章が特定の基準(丁寧な言葉遣い、社内レビュー基準など)を満たしているかの確認 Google Workspace との連携 Google ドキュメントやスライドを読み込ませ、作業をさせる Gems(カスタム指示)の活用 特定の役割やタスクに特化した指示を保存し、再利用 Deep Research 複雑なトピックに関する情報を複数のソースから収集・分析し、詳細なレポートを生成 Canvas 作成させた文章を校正しながら再生成を繰り返す。文章作成やコーディングに便利。HTML/CSS/JavaScript のプレビューも可能 スケジュール実行 メールの要約、To Do リストのまとめなど定期的なアクションを実行してユーザーに通知する 日常的な情報収集から専門的な作業まで、Gemini アプリは幅広いシーンで生産性向上に貢献します。 参考 : Gemini アプリ ヘルプ Gemini による翻訳 スピーカーノートを Gemini アプリに生成させる Gemini アプリでウェブアプリを開発(Canvas 機能) また、Gemini アプリで使える Gems も強力です。あらかじめ「カスタム指示」として、Gemini の振る舞いや出力フォーマットを指示するプロンプトを登録して再利用できるので、繰り返し行う指示がある場合に、何度もプロンプトを入力する必要がなくなります。 blog.g-gen.co.jp Gems の編集画面 ドキュメントは自動で版管理される Google ドキュメント、スプレッドシート、スライドなどのドキュメントは、 自動で版管理 されます。 メニューから「ファイル > 変更履歴 > 変更履歴を表示」を選択することで、いつ・誰が・どの部分を変更したか、履歴を確認できます。過去の版から情報をコピー&ペーストしたり、ある版にファイルを巻き戻すこともできます。 これを使えば、ファイルを複製して過去の版を残しておく必要がありません。ファイル名に日付を付ける必要もありません。以下のようなファイルサーバーの状態とは無縁になります。 XXプロジェクト_説明資料.pptx XXプロジェクト_説明資料(最新).pptx XXプロジェクト_説明資料_20220602.pptx XXプロジェクト_説明資料_old.pptx XXプロジェクト_説明資料_old2.pptx 過去の履歴を確認 いつ、誰が、どのように変更したかがハイライト表示 参考 : ファイルの変更内容を確認する ファイルが格納されている Google ドライブのフォルダへ瞬時に移動 Google ドキュメントやスプレッドシート、スライドなどのファイル(以下、Google ドライブファイル)を開いているとき、「このファイルはどのフォルダに保存したかな?」と探した経験はないでしょうか。 画面左上のファイル名の右側にある フォルダアイコン をクリックして開くポップアップウインドウから、そのファイルが格納されているGoogle ドライブのフォルダへ簡単に移動できます。 ファイルが格納されているフォルダを開く方法 なお、Google ドライブの設計思想として、フォルダ構造を作ったディレクトリ型のファイル整理ではなく、検索によりファイルを見つけ出すことに重きが置かれています。Google ドライブの検索機能は非常に優れており、あいまいなキーワードでも検索にヒットします。しかし、フォルダ構成を正しく整理しておくことは、依然としてスムーズなコラボレーションのために重要です。 「候補」でファイル移動を効率化 Google ドライブでファイルを別のフォルダに移動する際、移動先のフォルダを探す手間を省く方法があります。 ファイルを移動しようとすると、「候補」として最近アクセスしたフォルダや、ファイルの内容に関連性の高いフォルダが表示されます。そのため、 あらかじめ移動先のフォルダを一度開いておく と、そのフォルダが「候補」の上位に表示されやすくなり、スムーズにファイルを移動できます。 ファイルを意図したフォルダに素早く移動 最短で共有リンクをコピー Google ドライブファイルの共有リンクを取得する際、画面右上の「共有」ボタンをクリックしてから「リンクをコピー」を選択するのが一般的です。 しかし、もっと手早くリンクをコピーする方法があります。「共有」ボタンの すぐ右にある下向きの三角アイコン をクリックし、表示されたメニューから「 リンクをコピー 」を選択します。これにより、ステップ数を減らして迅速に共有リンクを取得できます。 2回のクリックで共有リンクをコピー ドキュメントの任意の場所へのリンク Google ドキュメント 長文の Google ドキュメントや議事録を作成する際、構造を分かりやすくするために目次は不可欠です。 Google ドキュメントでは、テキストのスタイルを「見出し1」「見出し2」などに設定するだけで、画面左側に自動的に アウトライン (目次)が表示されます。このアウトラインをクリックすることで、ドキュメント内の該当箇所にすぐにジャンプできます。 アウトラインが表示されていない場合は、画面左上の目次アイコンをクリックするか、「表示」メニューから「タブと概要のサイドバーを開く」を選択してください。 設定した見出しに応じて、目次が表示される これは、定例会議など繰り返される会議の議事メモなどにも便利です。毎回、 議事メモを同じファイルに追記 していき、日付を見出しに設定しておけば、任意の日付の議事メモに瞬時にジャンプできます。 なお、テキストのスタイルを「見出し1」「見出し2」などに設定するショートカットも便利です。例えば、「見出し1」を設定する一般的なショートカットは Ctrl + Alt + 1 (Windows、Chromebook)または Command + Option + 1 (Mac)です。「見出し2」であれば、最後の数字を2に変えることで適用できます。これらのショートカットを指が覚えるまで意識的に使用することで、ドキュメントの構成を整える作業がスムーズになり、コンテンツ作成に集中できます。 参考 : ドキュメントにタイトル、見出し、概要を追加する また、この見出しをクリックしてジャンプした状態で ブラウザの URL 欄に表示される URL は、その見出しへの 直接のリンク となります。ドキュメントを人に共有する際は、このリンクを使用することができます。Google ドキュメントに複数タブを作っている場合、開いたタブの URL も同様に、そのタブへの直接のリンクとなります。この挙動は、 Google スプレッドシートや Google スライドなどでも同様 です。 ブックマーク 見出しを作らずにドキュメントの任意の場所にリンクを貼りたい場合、ブックマーク機能も便利です。メニュー「挿入」>「ブックマーク」をクリックすると、任意の場所にブックマークを挿入することができます。このブックマークから得られるリンクにアクセスすると、始めからその場所にスクロール済みの状態でウインドウが開きます。 ブックマークを挿入 ブックマークからリンク取得 Google スライド Google スライドでも、任意のスライドを開いた状態で、ブラウザの URL 欄から得られるリンクを他人に共有すれば、はじめからそのスライドが開いた状態でウインドウが開きます。 特定スライドへのリンク Google スプレッドシート スプレッドシートでは、特定のセルを右クリックして表示されるプルダウンメニューから「セルでの他の操作項目を表示」>「このセルへのリンクを取得」を選択することで、特定セルへのリンクが取得できます。このリンクを開くと、特定セルにカーソルがあった状態でウインドウが開きます。 このセルへのリンクを取得 Google ドキュメントにコードブロックを挿入 技術的なドキュメントを作成する際、ソースコードを色分けして表示したいケースがあります。Google ドキュメントでは、簡単に コードブロック を挿入できます。 コードブロックを挿入するには、以下の手順で行います。 「挿入」メニューを開きます。 「ビルディング ブロック」にカーソルを合わせます。 「コードブロック」を選択します。 表示されたコードブロック内にコードを記述または貼り付けて、言語を選択します。 ソースコードなどをハイライト表示 コネクテッドシートで BigQuery データを可視化 コネクテッドシート は、Google スプレッドシートから直接 BigQuery のデータにアクセスし、分析や操作を行える機能です。 BigQuery のデータを Excel で扱うには、一度 CSV などでエクスポートしてからシートにインポートする手間があります。しかしコネクテッドシートを利用すれば、Google スプレッドシート上で数万行といった大規模なデータセットを直接参照し、ピボットテーブルやグラフ作成、関数を利用した計算などが可能です。 データアナリストやマーケターなど、大量のデータを扱うユーザーにとって、データ活用のハードルを大きく下げる機能です。 参考 : コネクテッド シートを使用して BigQuery のデータを分析、可視化する 参考 : Google スプレッドシートで BigQuery のデータを使用する 以下の記事では、コネクテッドシートを駆使して、ブログサイトのアクセス数分析を行っている G-gen の事例を紹介しています。 blog.g-gen.co.jp Looker Studio でリアルタイムにデータを可視化 Looker Studio は、様々なデータソースに接続し、インタラクティブなダッシュボードやレポートを無料で作成できるビジネスインテリジェンスツールです。 Google アナリティクス、Google 広告、BigQuery、Google スプレッドシートなど、多くのGoogleサービスはもちろん、外部のデータベースやCSVファイルなど、多様なデータソースに対応しています。 ドラッグ&ドロップの簡単な操作でグラフや表を作成でき、リアルタイムでデータが更新されるダッシュボードを関係者と容易に共有できます。コネクテッドシートで BigQuery のデータをスプレッドシートに取り込み、それを Looker Studio で可視化するといった連携も強力です。 参考 : Looker Studio の概要 参考 : Looker Studio ヘルプセンター Looker Studio レポート(Google が公開するサンプル) 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の中川です。Google Workspace の管理者向け機能である メールログ検索 について、基本的な使い方からトラブルシューティングでの活用方法までを解説します。 メールログ検索とは 保持期間 使用方法 メールログ検索でできること 配信状況と配信後の状態の確認 メッセージ ID での正確な追跡 適用されたルールの特定 トラブルシューティングでの利用 ケース1 : ログに記録が存在しない ケース2 : 外部への送信が拒否された メールログ検索とは メールログ検索 (Email Log Search、ELS)は、Google Workspace の管理者が、組織で送受信されるメールの配信状況を追跡・監査するためのツールです。Google のサーバーを通過した全てのメールについて、「いつ」「誰から誰に」「正常に配信されたか」「どのようなルールが適用されたか」といった詳細な記録を確認できます。 ユーザーから「メールが届かない」「送ったメールが相手に届いていないようだ」といった問い合わせがあった際に、このメールログ検索を用いると、管理者は客観的なデータに基づいた迅速な原因調査ができます。 参考 : メールログ検索を使用してメールを検索する 保持期間 メールログ検索のデータ保持期間は 30 日間です。30 日を超えてデータを保持したい場合は、定期的にエクスポートし、Google スプレッドシートや CSV ファイルとして保存する必要があります。 参考 : データの保持期間とタイムラグ 参考 : メールログ検索の結果を理解する - ELS の結果を書き出す 使用方法 メールログ検索は、Google Workspace の管理コンソールから使用します。 左側のメニューから [レポート] > [メールログ検索] を選択します。 検索画面では、定義済み検索とカスタム検索の2つの方法が利用できます。 定義済み検索では、「今日のすべてのメール」など、あらかじめ用意された条件で簡単に検索できます。 カスタム検索では、期間を指定し、送信者や受信者のメールアドレス、件名、送信元 IP アドレスなど、より詳細な条件で絞り込むことができます。 「今日のすべてのメール」の検索結果 参考 : メールログ検索を使用してメールを検索する メールログ検索でできること 配信状況と配信後の状態の確認 検索結果から特定のメールを選択すると、そのメールのステータスや詳細な処理内容を確認できます。「配信済み」となっていてもユーザーがメールを見つけられない場合、配信後のメッセージの詳細を確認するのが有効です。 検索結果で対象のメールを選択し、「受信者の詳細」セクションを開くと配信ステップを確認できます。 「配信後のメッセージの詳細」では以下のような詳細な内容を確認できます。 受信トレイ、迷惑メール、ゴミ箱など、メールが現在どのフォルダにあるか どのラベルが付与されたか 既読か未読かなど 参考 : メールログ検索の結果を理解する 参考 : メールログ検索の配信ステータスの定義 メッセージ ID での正確な追跡 確実に特定のメールを調査したい場合は、 メッセージ ID を使った検索が最も効果的です。メッセージ ID は、メール1通1通に割り当てられる世界的に一意の識別子で、メールのヘッダー情報に含まれています。 ユーザーから調査依頼を受ける際に、対象メールのヘッダー情報( Message-ID フィールド)を提供してもらうことで、他の類似メールと混同することなく、目的のログをピンポイントで特定できます。 逆に、ユーザーから「メールが見つからない」という問い合わせを受けた際には、管理者がメールログ検索でメッセージ ID を取得し、ユーザーに提供することも有効です。 ユーザーは取得したメッセージ ID を Gmail の検索ボックスで rfc822msgid:<メッセージID> という形式の検索演算子を使うことで、目的のメールを正確に見つけ出せます。 参考 : メールログ検索を使用してメールを検索する 参考 : Gmail で検索を絞り込む 適用されたルールの特定 メールが意図せず迷惑メールに分類されたり、特定のユーザーに転送されたりした場合、どの設定が影響したのかを特定する必要があります。 メールログの詳細画面では、そのメールに適用されたGmailのポリシーやルーティング設定が一覧で表示されます。例えば、「コンテンツコンプライアンス」や「ルーティング」といった管理者が設定したルールがどのように評価・適用されたかを確認でき、設定不備の発見に役立ちます。 トラブルシューティングでの利用 ケース1 : ログに記録が存在しない ユーザーから「メールが届かない」と申告があり、メールログ検索で検索しても該当するログが一切見つからないことがあります。 これは、そのメールが Google のメールサーバーに到達していないことを意味します。つまり、問題の原因は Google Workspace 側ではなく、その手前の送信者側の環境にある可能性が極めて高いです。この場合、調査すべきは送信者側のメールサーバーの設定や送信ログです。 ケース2 : 外部への送信が拒否された メールログに「受信者ドメインのサーバーによって拒否されました」と記録された場合、相手方のサーバーが受信を拒否したことを示します。 原因は、相手側の IP アドレスブロックや迷惑メールフィルタ設定などが考えられます。また、自社の送信ドメイン認証( SPF 、 DKIM 、 DMARC )の不備が原因で「なりすましメール」と判定されている可能性もあります。 まずは自社の SPF・DKIM・DMARC 設定を Google が提供する Google Admin Toolbox などのツールを使って確認し、問題がない場合、ログ情報を添えて相手先のシステム管理者に調査を依頼するのが有効です。 参考 : Google Admin Toolbox (Check MX) 参考 : メールログ検索を使用したメール配信に関する問題のトラブルシューティング 送信ドメイン認証については、以下の記事もご参照ください。 blog.g-gen.co.jp blog.g-gen.co.jp 中川 涼介 (記事一覧) クラウドソリューション部 クラウドサポート課 2024年11月、G-genに入社。Google Cloudを日々勉強中。 最近は怪談の動画にハマってます。
アバター
G-genの福井です。Cloud Monitoring の SLO モニタリングの設定手順を紹介します。 はじめに SLO 設定の前提 Service の作成 SLO の作成 可用性 SLO の設定 レイテンシ SLO の設定 エラーバジェットのアラート設定 アラート設定の必要性 エラーバジェットのアラートの種類 アラートポリシーの作成手順 ダッシュボードの確認 はじめに 本記事では、Google Cloud の Cloud Monitoring を利用し、サービスの品質を定量的に管理するための SLO モニタリングを設定する手順を解説します。 サービス運用では、「システムの現在の状態は健全か」「ユーザーに快適な体験を提供できているか」という問いに、データに基づいて客観的に答えることが求められます。Google が提唱する SRE (Site Reliability Engineering)のプラクティスでは、これらの問いに答える判断基準として SLO (Service Level Objective)を用います。 SLO モニタリングは、「感覚的な運用」から脱却し、観測した数値に基づいてサービス品質の管理や改善活動の意思決定を行うための仕組みです。 具体的な設定手順に入る前に、SLO を理解する上で不可欠な3つの基本用語を解説します。 用語 概要 具体例 SLI(Service Level Indicator) サービスの健康状態を定量的に測る指標。良いサービスを定義する「物差し」の役割を果たす ・可用性(リクエストの成功率) ・レイテンシ(リクエストの応答時間) SLO(Service Level Objective) SLI で計測した値が達成すべき具体的な目標値。この目標の遵守状況が、サービスの信頼性を判断する基準となる ・月間の可用性が 99.9% であること ・リクエストの 95% が 500ms 以内に応答されること エラーバジェット(Error Budget) SLOで定めた目標を100%から引いた残り、つまり「使い切っても良いエラーの許容量」です。この予算内で新機能のリリースを行い、枯渇しそうなら品質改善に注力するなど、開発速度と信頼性のバランスを取るために利用される ・SLO が 99.9% の場合、0.1% がエラーバジェットになる ・この 0.1% の範囲内での品質低下は許容される SLO 設定の前提 今回の手順解説では、Google Cloud 上で稼働する、ごく一般的な Web アプリケーションを例に、設定手順を解説します。 今回の構成と利用するサービスは以下の通りです。 項目 内容 モニタリング対象サービス Cloud Run で稼働する Web アプリケーション アクセス経路 Cloud Run のサービス URL をインターネットに公開 モニタリングツール Cloud Monitoring SLO を設定する上での最も重要な前提条件は、 対象のサービスがすでに稼働しており、Cloud Monitoring 上で指標(メトリクス)が収集されていること です。 SLI / SLO は既存のメトリクスに基づいて定義されるため、まだデプロイされていないサービスや、全くトラフィックがないサービスに対して設定することはできません。本記事でも、すでに Cloud Run にアプリケーションがデプロイされ、サービス URL を通じてトラフィックが発生している状態から手順を開始します。 Service の作成 SLO モニタリングを開始するには、まずモニタリング対象となる「Service」を Cloud Monitoring に登録します。 ここでの「Service」とは、Cloud Run や GKE、特定の VM 群といった、アプリケーションやマイクロサービスの論理的な単位を指します。 Google Cloud コンソールの Cloud Monitoring 画面で、[検出] > [SLO] > [サービスを定義] を選択します。 サービスを定義を選択 モニタリング対象のサービスを一覧から選択し、[送信]を選択します。 サービスを定義 参考: サービスを定義する SLO の作成 作成した Service の信頼性を評価するための具体的な目標、SLO(Service Level Objective)を設定します。 今回は、代表的な SLO として「可用性」と「レイテンシ」の2種類を設定する手順を解説します。 可用性 SLO の設定 可用性は、サービスがリクエストに対して正常に応答しているかどうかを示す指標であり、最も基本的な SLO の一つです。ここでは「リクエスト総数のうち、正常なリクエストが占める割合」を目標として設定します。 Google Cloud コンソールの Cloud Monitoring 画面で、[検出] > [SLO] > 作成した Service を選択します。 作成したサービスを選択 [+ SLO を作成] を選択します。 SLO を作成を選択 SLI の設定 指標の選択に 可用性 、リクエスト ベースまたはウインドウ ベースの選択に リクエスト ベース を選択し、[続行] を選択します。 SLI の設定 [続行] を選択します。 SLI の詳細を定義する SLO の設定 直近30日間において、リクエストの99.9%が5xxエラー以外で応答されること を目標として定義するため、以下のように設定します。 期間の種類である「連続」は、現在から過去に遡った一定期間を評価対象とするため、継続的なサービスレベルの評価に適しています。設定後、[続行] を選択します。 項目 選択値 期間の種類 連続 期間の長さ 30 目標 99.9 SLO の設定 [SLO を作成] を選択します。 SLO を作成 参考: SLO の作成 レイテンシ SLO の設定 ユーザーの体感品質に直結するもう一つの重要な指標、レイテンシ(応答時間)に関する SLO を設定します。 ここでは「全リクエストのうち、一定時間内に応答が完了したリクエストの割合」を目標として定義します。 手順は可用性 SLO の設定とほぼ同じです。Service ダッシュボードの [+ SLO を作成] ボタンから開始します。 SLI の設定 指標の選択に レイテンシ 、リクエスト ベースまたはウインドウ ベースの選択に リクエスト ベース を選択し、[続行] を選択します。 SLI の設定 正常と判断する応答時間の上限値を設定します。 レイテンシのしきい値に 500 を入力し、[続行] を選択します。 SLI の詳細を定義する SLO の設定 直近30日間において、リクエストの95%が500ms以内に応答されること を目標として定義するため、以下を選択し、[続行] を選択します。 項目 選択値 期間の種類 連続 期間の長さ 30 目標 95 SLO の設定 [SLO を作成] を選択します。 SLO を作成 エラーバジェットのアラート設定 アラート設定の必要性 SLO を設定しただけでは、サービス品質の低下が自動的に通知されるわけではありません。そのため、エラーバジェットが危険な水準まで消費される前に通知を受け取る仕組みとして、アラートの設定は不可欠です。 Cloud Monitoring の SLO モニタリングでは、 エラーバジェットの消費速度(バーンレート) に基づいてアラートを発行することが推奨されています。 バーンレートとは、エラーバジェットを消費していくペースを指します。例えば、「この1時間のエラー発生ペースが続くと、SLO期間(30日間)で許容されるエラーバジェットを10日で使い切ってしまう」といった状況を検知するのがバーンレートアラートです。これにより、一時的なエラーの急増に過剰反応することなく、持続的かつ重大な品質低下を早期に警告できます。 エラーバジェットのアラートの種類 バーンレートに基づくアラートは、その緊急性に応じて、一般的に「高速バーン」と「低速バーン」の2種類を設定することが推奨されます。 アラートの種類 目的 推奨される設定(目安) 高速バーン 重大なレート変化の即時検知 サービスの致命的な障害など、エラーバジェットを急激に消費する事態を直ちに検知します。 ・バーンレートしきい値: 10 (30日間のSLO期間の場合、3日でバジェットを消費するペース) ・ルックバック期間: 1時間 ・用途:緊急対応(夜間・休日呼び出しなど) 低速バーン 長期的な品質低下の検知 緊急ではないが、このままでは期間終了までに目標を達成できない、緩やかな品質低下を検知します。 ・バーンレートしきい値: 2 (30日間のSLO期間の場合、15日でバジェットを消費するペース) ・ルックバック期間: 24時間 ・用途:計画的な日中対応(チケット発行など) このように複数のアラートを組み合わせることで、様々なパターンの品質低下に対応できます。 参考: エラー バジェットのアラートの種類 アラートポリシーの作成手順 アラートを設定したい SLO の行にある [アラートの起動アイコン] を選択します。 SLO アラートを作成を選択 ルックバック期間に 60 、バーンレートのしきい値に 10 を入力し、[次へ]を選択します。 SLO のアラート条件の設定 通知チャンネルの作成から行う場合は、通知チャンネルを選択し、[Manage Notification Channels] を選択します。 Manage Notification Channels を選択 Email 行の [Add New] を選択します。 Email Add New を選択 Email Address に 通知先のメールアドレス 、Display Name に 通知チャンネルの表示名 を入力し、[Save] を選択します。 通知チャンネルを作成 通知チャンネルに 作成した通知チャンネル を選択し、[次へ] を選択します。 通知チャンネルの選択 [Save] を選択します。 SLO のバーンレートに関するアラート ポリシーの作成 参考: アラート ポリシーの作成 ダッシュボードの確認 Service の定義、SLO の設定、アラートポリシーの作成が完了すると、SLO モニタリングの運用フェーズに入ります。その中心となるのが、各 Service ごとに自動で生成される専用のダッシュボードです。 このダッシュボードには、サービスの信頼性に関する様々な情報が集約されており、日々の健全性確認や問題発生時の状況把握に役立ちます。 今回は、アクセスすると 5xx エラー となる Cloud Run サービスに対して、SLO モニタリングの設定を追加しています。 モニタリングの設定を行った後、Cloud Run サービスに複数回アクセスした状態のダッシュボードです。 SLO ダッシュボード SLO アラートの設定で通知されたメールです。 SLO アラートで通知されたメール 参考: サービス ダッシュボードの使用 福井 達也 (記事一覧) カスタマーサクセス課 エンジニア 2024年2月 G-gen JOIN 元はアプリケーションエンジニア(インフラはAWS)として、PM/PL・上流工程を担当。G-genのGoogle Cloudへの熱量、Google Cloudの魅力を味わいながら日々精進
アバター
全国の G-gen ファンのみなさま、はじめまして。Cisco Systems のセキュリティ SE の稲澤です。今回、G-gen の Google Workspace 検証環境を使い、当社の Cisco Duo との連携テストを行う機会を得たため、内容を記事にまとめました。 当記事は、Cisco Systems と G-gen の共同企画で執筆されました。 はじめに Cisco Duo とは Duo と Google Workspace の連携 検証1. Google Directory-Sync 検証2. Duo Directory & 完全なパスワードレス認証 検証3. Duo Outbound SCIM Cisco Duo と Google の連携強化 はじめに Cisco Duo とは Cisco Duo は、多要素認証、ユーザの信頼性評価、デバイス信頼性評価により、あらゆるアプリケーションへの安全なアクセスをシームレスに、かつ最小の認証回数で実現するアイデンティティセキュリティソリューションです。 参考 : ユーザにセキュアなアクセスを提供 | Duo Security Duo を MFA 用ソリューションと捉えている方も多いかもしれません。しかし近年では、多様な IdP や HR システムと連携して ID の振る舞いを監視し、ID に関連したリスクの可視化と脅威の検出、およびそれら対応が可能な ITDR (Identity Threat Detection and Response)機能が実装されたり、2025年6月5日には Cisco Duo IAM が新たに発表され、Duo をプライマリの認証ソースとしてセキュアな ID 管理・アクセス管理を実現する、セキュリティファーストな IAM ソリューションに進化しています。 参考 : シスコ、アイデンティティ セキュリティを再定義する「Duo IAM」を発表 Cisco Duo Duo と Google Workspace の連携 近年、主な認証基盤として Google Workspace を使ったり、あるいは他の IdP と併用して利用するユースケースが増えています。 2025年6月5日に発表された Cisco Duo の新機能の中で、Google Workspace との連携が強化されたため、Cisco Systems と G-gen で協力して動作検証を行いました。 検証1. Google Directory-Sync Google Directory-Sync は、Google Workspace から Cisco Duo に対して、ユーザ、グループ、その他属性情報を自動同期できる新機能です。 IdP でのプライマリ認証に成功すると、ユーザ ID 情報が Duo に送信されます。Duo 内にこのユーザ ID とマッチする ID が存在すれば、Duo からエンドユーザに対して MFA リクエストが行われます。そのため、Google Workspace から Duo へのユーザ同期は必須です。 今回の検証では、Google Workspace のディレクトリに存在する以下のグループとユーザを同期の対象としました。 グループ : gws-group1 ユーザ : gwsuser1@ina.g-gen-trial.com 、 gwsuser2@ina.g-gen-trial.com (いずれのユーザも gws-group1 に所属) 1. Add External Directory Duo ダッシュボードから External Directories に移動して Add External Directory から Google を選択します。 2. Add new connection Add new connectionにチェックをして、 Continue をクリックします。 3. 承諾 Google のログインページに移動するため、管理者権限でログインします。Duo Directory Sync がアクセスする情報・権限一覧が表示されるため、すべてをチェックして承諾をクリックします。 5. その他の設定 その他、必要に応じて設定(今回はデフォルトのまま)して Save をクリックし、設定を保存します。その後、 Sync Now ボタンをクリックして同期を開始します。 上記のように、簡単な設定で同期が完了しました。 検証2. Duo Directory & 完全なパスワードレス認証 続いて、今回の目玉機能である Duo Directory の検証です。Duo Directory は、Duo が保持するユーザ ID にパスワードを付与し、Duo をプライマリ認証ソースとして利用することができる機能です。 検証 1. で Google Workspace から取得した ID を Duo でパスワードレス化して、Google Workspace にログイン可能かを検証します。ポイントは、認証ソースを Google ではなく Duo としている点です。Google へのログインであれば、認証ソースはそのまま Google で良いのではないかと考える方もいるかもしれませんが、Google Workspace を SP とし、かつ IdP も Duo により Google Workspace と SAML 連携してしまうと認証ループが発生してしまい、認証が成功しません。 これを回避するために Google Workspace アプリへのログオンのみ、Duo Directory を使って Duo でプライマリ認証とセカンダリ認証(MFA)を実施させます。 1. Enrollment Policy の作成 エンドユーザに、Duo での MFA デバイス登録の際にパスワードをセットさせるよう、 Enrollment Policy を作成します。はじめに、MFA の認証方式を設定します。ここではパスキー認証のみ許可し、パスワードレス認証を行わせるようにします。次に、Duo でのパスワード作成要求にチェックを入れます。 2. Enrollment Policy を使うグループの設定 作成した Enrollment Policy を使用するグループを指定します。ここでは、検証 1. で Google Workspace から同期した gws-group1 をセットします。 3. プライマリ認証ソースの設定 続いて、プライマリ認証ソースを Duo に設定します。Duo には SSO Routing Rules という機能があり、ドメインや宛先アプリケーションなどを条件として複数の IdP 認証ソースに振り分けが可能です。今回はデフォルトの認証ソースとして Duo をセットします。 4. MFA デバイス登録 次に、エンドユーザの MFA デバイス登録を実施します。ユーザ gwsuser1@ina.g-gen-trial.com をクリックして、 Generate an enrollment code をクリックし、テンポラリの登録コードを生成してテキストに保存します。 5. Enrollポータルの操作 Enrollポータルにアクセスします。 Get started をクリックすると、ユーザのデバイス登録が始まります。まず該当のユーザ ID と、先ほどコピーしたコードを入力します。続いてパスワードを作成し(パスワードレス認証となるため、ここで設定したパスワードは実際のアクセスには利用されません)、デバイスの追加で Windows Hello の登録を行います。これで、ユーザの事前のセットアップは完了です。 6. SP 設定 最後に、Google Workspace を SP として Duo と連携させます。この手順は少し長いため、ここでは省略します。以下の公式ガイドの通り設定してください。 参考 : Duo Single Sign-On for Google Workspace (Google G Suite) | Duo Security 7. 動作確認 実際に Google Workspace にログインしてみます。以下の図の通りパスワード不要で、シームレスに Google Workspace にログインすることができました。 検証3. Duo Outbound SCIM 新機能 Duo Outbound SCIM により、Duo が保有するユーザ、グループ、その他属性情報を、他のアプリケーションに SCIM 経由で渡す(プロビジョニングする)ことができるようになりました。 今回は、検証 1. で Google Workspace から Duo に取り込んだユーザ・グループ情報を、Cisco の SSE(Security Service Edge)ソリューションである Secure Access にプロビジョニングする検証を行いました。 1. トークンの取得 まずは Secure Access で Directories の設定を行い、連携に必要なトークンおよび URL 情報を取得します。 2. 認証関連設定 続いて Duo ダッシュボードにログインして、Applications から Generic SAML Service Provider -Single Sign-On を選択して Provisioning タブから、以下のように認証設定、属性マッピング設定、同期するグループを指定します。 なお現在は Seure Access アプリケーションが Duo に組み込まれており、Generic SAMLではなく、Secure Access アプリケーションを利用して設定することもできます。 設定後にすぐに同期が開始され、Secure Access 上に Duo から取得したユーザ、グループ情報がプロビジョニングされていることが確認できました。今回は当社の製品で試しましたが、もちろん Amazon Web Services(AWS)や Microsoft 365、Zoom、SAP、Workday など、様々なアプリケーションに対して簡単にプロビジョニングを設定できます。 Cisco Duo と Google の連携強化 Cisco Duo では、Google との連携機能が強化され、Google Workspace をご利用中のお客様にとってこれまで以上に使いやすくなりました。 Google 単体との連携はもちろんのこと、複数の IdP 環境を持つ複雑なユースケース(企業の統合・合併、離脱など)においても、Duo をハブとして、Duo で統一したセキュリティポリシーを適用することができます。また、定期メンテナンスや新規プロジェクト用途(社員用の IdP との分離)などでも、Duo Directory を利用できます。「かゆいところに手が届く」柔軟さが Duo 特長です。 上記のような課題がある場合、今すぐ Cisco Duo の 無料トライアル を検討してください。 signup.duo.com 稲澤 敏 シスコシステムズ合同会社 セキュリティ事業 Solutions Engineer -Cybersecurity セキュリティ製品全般のプリセールス活動に従事し、セキュリティアーキテクトの立場から、パートナー、お客様への技術的な支援を行っている。
アバター
G-gen の堂原です。本記事では、 Vertex AI SDK と Google Gen AI SDK のコードを比較しながら、 Gemini の基本的な機能を Google Gen AI SDK で呼び出す方法を紹介します。 はじめに セットアップ Vertex AI SDK Google Gen AI SDK テキスト生成 Vertex AI SDK Google Gen AI SDK チャット形式 Vertex AI SDK Google Gen AI SDK マルチモーダル Vertex AI SDK Google Gen AI SDK グラウンディング Vertex AI SDK Google Gen AI SDK はじめに 2025年7月現在、Vertex AI の生成 AI を利用するための SDK として、 Vertex AI SDK と Google Gen AI SDK が存在しています。 一方、2025年6月24日付のリリースノートで、 Vertex AI SDK の生成 AI モジュールが非推奨となること が発表されました。 また、 2026年6月24日に本モジュールは利用できなくなります 。 これに伴い、Vertex AI SDK から Google Gen AI SDK への移行が必要となります。 参考 : Vertex AI release notes  |  Google Cloud 参考 : Vertex AI SDK migration guide  |  Generative AI on Vertex AI  |  Google Cloud セットアップ Vertex AI SDK Vertex AI SDK では、google-cloud-aiplatform ライブラリをインストールし、 vertexai.init() で初期化を行います。その後、 generative_models.GenerativeModel() で利用するモデルの設定をします。 ※ 本記事では、サンプルコードは Google Cloud の Colab Enterprise 上で動作を確認しています。 # ライブラリのインストール !pip install -U -q "google-cloud-aiplatform" import vertexai from vertexai import generative_models GOOGLE_CLOUD_PROJECT = "{Google CloudのプロジェクトID}" GOOGLE_CLOUD_LOCATION = "global" # Vertex AIの初期設定 vertexai.init(project=GOOGLE_CLOUD_PROJECT, location=GOOGLE_CLOUD_LOCATION) # モデル設定 model = generative_models.GenerativeModel( "gemini-2.5-flash" , system_instruction=[ "お嬢様っぽく喋ってください" ] ) Google Gen AI SDK Google Gen AI SDK では、google-genai ライブラリをインストールし、 genai.Client() でクライアントを初期化します。 Google Gen AI SDK では、モデルやシステムインストラクションは、実際にリクエストを送信する際に指定します。 # ライブラリのインストール !pip install -U -q "google-genai" from google import genai from google.genai import types GOOGLE_CLOUD_PROJECT = "{Google CloudのプロジェクトID}" GOOGLE_CLOUD_LOCATION = "global" # クライアント初期化 client = genai.Client( vertexai= True , project=GOOGLE_CLOUD_PROJECT, location=GOOGLE_CLOUD_LOCATION ) Google Gen AI SDK は Gemini Developer API 経由で Gemini を利用することもできるため、クライアントの初期化の際に、Vertex AI を使うことを明記する必要があります。 また、環境変数を用いてクライアントを初期化することも可能です。 %env GOOGLE_GENAI_USE_VERTEXAI=true %env GOOGLE_CLOUD_PROJECT= "{Google CloudのプロジェクトID}" %env GOOGLE_CLOUD_LOCATION= "global" client = genai.Client() 環境変数が設定されていない、または引数が不足している場合は、以下のような ValueError が発生します。 ValueError: Missing key inputs argument! To use the Google AI API, provide (`api_key`) arguments. To use the Google Cloud API, provide (`vertexai`, `project` & `location`) arguments. また、Google Gen AI SDK は、デフォルトでプレビュー機能が利用可能なベータ版のエンドポイントを使用します。安定版のエンドポイントを明示的に使用したい場合は、クライアントの初期化時に http_options を指定します。 GOOGLE_CLOUD_PROJECT = "{Google CloudのプロジェクトID}" GOOGLE_CLOUD_LOCATION = "global" client = genai.Client( vertexai= True , project=GOOGLE_CLOUD_PROJECT, location=GOOGLE_CLOUD_LOCATION, http_options=types.HttpOptions(api_version= "v1" ) ) 参考 : Google Gen AI SDK documentation テキスト生成 Vertex AI SDK Vertex AI SDK では、 model.generate_content() メソッドを使用します。出力設定は generation_config で、セーフティフィルタの設定は safety_settings で指定します。 response = model.generate_content( contents= "日本で一番長い川はなんですか?" , generation_config=generative_models.GenerationConfig( temperature= 0 , max_output_tokens= 1024 ), safety_settings={ generative_models.HarmCategory.HARM_CATEGORY_HATE_SPEECH: generative_models.HarmBlockThreshold.BLOCK_ONLY_HIGH, generative_models.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: generative_models.HarmBlockThreshold.BLOCK_ONLY_HIGH, generative_models.HarmCategory.HARM_CATEGORY_HARASSMENT: generative_models.HarmBlockThreshold.BLOCK_ONLY_HIGH, generative_models.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: generative_models.HarmBlockThreshold.BLOCK_ONLY_HIGH } ) Google Gen AI SDK Google Gen AI SDK では、 client.models.generate_content() メソッドを使用します。モデルはここで指定します。また、システムインストラクション、出力設定、セーフティフィルタ設定などを、 config パラメータにまとめて types.GenerateContentConfig として渡します。 response = client.models.generate_content( model= "gemini-2.5-flash" , contents= "日本で一番長い川はなんですか?" , config=types.GenerateContentConfig( system_instruction= "お嬢様っぽく喋ってください" , temperature= 0 , max_output_tokens= 1024 , safety_settings=[ types.SafetySetting( category=types.HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold=types.HarmBlockThreshold.BLOCK_ONLY_HIGH ), types.SafetySetting( category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold=types.HarmBlockThreshold.BLOCK_ONLY_HIGH ), types.SafetySetting( category=types.HarmCategory.HARM_CATEGORY_HARASSMENT, threshold=types.HarmBlockThreshold.BLOCK_ONLY_HIGH ), types.SafetySetting( category=types.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold=types.HarmBlockThreshold.BLOCK_ONLY_HIGH ) ] ) ) 参考 : Safety settings  |  Gemini API  |  Google AI for Developers チャット形式 Vertex AI SDK Gemini ではマルチターンでの会話を行うこともできます。 Vertex AI SDK では、 model.start_chat() でチャットセッションを開始し、 chat.send_message() で対話を進めます。また、会話履歴は chat.history で確認できます。 chat = model.start_chat() # 一回目の会話 chat.send_message( "しりとりをしましょう。まず私から、「りんご」" ).text """ 返答 > あら、しりとりでございますのね! とても風流な遊びですわね。 > わたくしも喜んでご一緒させていただきますわ。 > > 「りんご」様の「ご」でございますもの…そうですね、わたくしからは**「ごちそう」**といたしましょう。 > > 「う」で終わりますわ。 > > さあ、次はあなた様の番でございますわよ? どのようなお言葉が飛び出しますかしら。うふふ。 """ # 二回目の会話 chat.send_message( "「うなぎ」" ).text """ 返答 > あら、うなぎでございますのね! 香ばしい良い香りがしてまいりそうでございますわね。 \n\n では、わたくしからは「ぎ」で始まります**「ぎんいろ」**といたしましょう。 \n\n 「ろ」でございますわね。 \n\n さあ、次はどんな素敵な言葉が紡がれるのでございますかしら。楽しみでございますわ。うふふ。 """ Google Gen AI SDK Google Gen AI SDK では、 client.chats.create() でチャットセッションを開始します。この際、モデルやシステムインストラクションを指定します。対話は chat.send_message() で行い、会話履歴は chat.get_history() メソッドで取得します。 chat = client.chats.create( model= "gemini-2.5-flash" , config=types.GenerateContentConfig( system_instruction= "お嬢様っぽく喋ってください" ) ) # 一回目の会話 chat.send_message( "しりとりをしましょう。まず私から、「りんご」" ).text """ 返答 > まあ、わたくしと遊んでくださるとは、光栄でございますわね! \n 「りんご」でございますわね。承知いたしましたわ。 \n\n では、わたくしからは……そうですね。 \n 「**ごきげんよう**」でございますわ。 \n\n 『う』で終わりましたから、どうぞ、お続けになってくださいましね。おほほ! """ # 二回目の会話 chat.send_message( "「うなぎ」" ).text """ 返答 > まあ、今度は「うなぎ」でいらっしゃいましたのね! \u3000 お上手でございますわ! \n\n では、わたくしからは……そうですね。 \n 「**ギター**」でございますわ。 \n\n 『た』で終わりましたから、どうぞ、お続けになってくださいましね。おほほ! """ また、 client.chats.create() の history パラメータに会話履歴を渡すことで、特定の文脈を引き継いだ状態でチャットを開始できます。 # 事前の会話内容設定 history = [ types.UserContent( parts=[ types.Part(text= "しりとりをしましょう。まず私から、「りんご」" ) ] ), types.Content( parts=[ types.Part(text= "わたくしからは「ごきげんよう」でございますわ。" ) ], role= "model" ) ] chat = client.chats.create( model= "gemini-2.5-flash" , config=types.GenerateContentConfig( system_instruction= "お嬢様っぽく喋ってください" ), history=history ) chat.send_message( "「うなぎ」" ).text マルチモーダル Vertex AI SDK Vertex AI SDK では、Cloud Storage に存在するファイルを入力に含める場合、 generative_models.Part.from_uri() を使用します。 # Cloud Storageにあらかじめ格納した画像を指定 image_part = generative_models.Part.from_uri( "gs://test-bucket/test.png" , mime_type= "image/png" ) response = model.generate_content( contents=[ "何が写っていますか?" , image_part], generation_config=generative_models.GenerationConfig( temperature= 0 , max_output_tokens= 1024 ) ) Google Gen AI SDK Google Gen AI SDK では、Cloud Storage に存在するファイルを入力に含める場合、 types.Part.from_uri() を使用します。 response = client.models.generate_content( model= "gemini-2.5-flash" , contents=[ "何が写っていますか?" , types.Part.from_uri( # Cloud Storageにあらかじめ格納した画像を指定 file_uri= "gs://test-bucket/test.png" , mime_type= "image/png" ) ], config=types.GenerateContentConfig( system_instruction= "お嬢様っぽく喋ってください" , temperature= 0 , max_output_tokens= 1024 ) ) グラウンディング Vertex AI SDK Vertex AI SDK について、移行ガイドでは generative_models.Tool.from_google_search_retrieval を使用する方法が案内されていますが、Gemini 2.0 以降でこの方法はサポートされておらず、以下のようなエラーが発生します。 BadRequest: 400 POST https://aiplatform.googleapis.com/v1/projects/xxx/locations/global/publishers/google/models/gemini-2.0-flash:generateContent?%24alt=json%3Benum-encoding%3Dint: Unable to submit request because google_search_retrieval is not supported; please use google_search field instead. Learn more: https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/gemini Google Gen AI SDK Google Gen AI SDK では、 tools パラメータに types.Tool(google_search=types.GoogleSearch()) を指定することで Grounding を有効にできます。 response = client.models.generate_content( model= "gemini-2.5-flash" , contents= "今年の「海の日」は何日ですか?" , config=types.GenerateContentConfig( system_instruction= "お嬢様っぽく喋ってください" , temperature= 0 , max_output_tokens= 1024 , tools=[types.Tool(google_search=types.GoogleSearch())] ), ) 堂原 竜希 (記事一覧) クラウドソリューション部クラウドエクスプローラ課。2023年4月より、G-genにジョイン。 Google Cloud Partner Top Engineer 2023, 2024, 2025に選出 (2024年はRookie of the year、2025年はFellowにも選出)。休みの日はだいたいゲームをしているか、時々自転車で遠出をしています。 Follow @ryu_dohara
アバター
G-genの杉村です。BigQuery テーブルのデータをスキャンして、AI がテーブルのメタデータ(テーブルとカラムの説明)を自動生成する メタデータ自動生成 機能を解説します。 はじめに メタデータの自動生成 テーブルのメタデータとは 仕様 分析情報からのメタデータ自動生成 料金 制限事項 手順 データ分析情報の生成 生成された説明を確認 テーブルへの保存 結果 日本語での生成 はじめに メタデータの自動生成 BigQuery には、テーブルのデータをスキャンして、AI がテーブルのメタデータ(テーブルとカラムの説明)を自動生成する メタデータ自動生成 機能があります。 この機能を用いることで、テーブルやカラムに人間が1つ1つ手作業でメタデータを付記する労力が改善されます。 なお2025年11月現在、当機能では追加の手順を行うことにより、日本語でのメタデータ生成が可能です。また2025年11月現在、当機能は API 経由での生成には対応していません。複数のテーブルに対して、API リクエストや SDK 経由で生成を実行する機能改善が期待されます。 参考 : Generate data insights in BigQuery - Generate table and column descriptions テーブルのメタデータとは データ分析基盤において、 メタデータ は非常に重要です。メタデータは可視化や分析のために必要なデータを人間が検索するために必要なほか、AI エージェントが自律的にデータを探し出したり、解釈するためにも利用されます。 メタデータが無いと、データが必要になったときに、過去の設計書を掘り起こしたり、システムの担当者に聞いて回ったり、あるいは Google Cloud の管理コンソールでプロジェクトを1つ1つ開き、BigQuery のテーブルや Cloud Storage のファイルをしらみつぶしに探したりといった、非常に手間のかかる作業が発生します。 BigQuery においては、テーブルやそのテーブルが持つ各カラム(列)に 説明 (Description)を追記することが可能です。この説明は ビジネスメタデータ として機能し、組織のメンバーが必要なデータを見つけ出すために役立ちます。BigQuery テーブルやカラムの説明は、 Dataplex Universal Catalog (旧称 Dataplex Catalog)に自動的に登録され、 データカタログ として利用することができます。 Dataplex Universal Catalog(旧称 Dataplex Catalog)については、以下の記事も参照してください。 blog.g-gen.co.jp 仕様 分析情報からのメタデータ自動生成 BigQuery のメタデータ自動生成は、 データ分析情報 (Data insights)機能の一部です。データ分析情報は Gemini in BigQuery の一部であり、生成 AI モデル Gemini を使ってテーブルの分析情報を得るための SQL クエリなどを生成する機能です。 プロジェクトで Dataplex API、BigQuery API、Gemini for Google Cloud API を有効化して、テーブルに対して分析情報の生成を指示するだけで、生成を行うことができます。 参考 : BigQuery でデータ分析情報を生成する 生成された分析クエリ このデータ分析情報の生成を指示すると、 メタデータ(説明)の自動生成 も同時に行われます。生成された説明は、テーブルに適用する前に目視で確認し、修正してから適用することができます。 生成された説明(Description) 料金 メタデータの自動生成は Gemini in BigQuery の一部であることから、Gemini in BigQuery の料金体系が適用されます。 2025年11月現在、メタデータの自動生成は 無料 で利用することができます。ただし、BigQuery Standard Edition を使っている場合は利用できません。デフォルト設定であるオンデマンド課金モードでは、利用可能です。 参考 : Gemini for Google Cloud pricing - Gemini in BigQuery Pricing Overview ただし、メタデータの生成を始めとする Gemini in BigQuery の利用回数には、1日あたりの制限(クォータ)があります。上限はスロットやスキャン量に応じて動的に決まります。詳細は以下を参照してください。 参考 : Quotas and limits - Quotas for Gemini in BigQuery 制限事項 当機能の制限事項は、以下のとおりです。 デフォルトでは 英語 の説明が生成される(日本語での生成手順は後述) BigQuery コンソール(BigQuery Studio)上からの操作のみ Geo 型、JSON 型の列には非対応 1テーブルにつき最大350カラムまで説明を生成可能 手順 データ分析情報の生成 まずは、テーブルのデータ分析情報(Data insights)を生成します。今回は、パブリックデータセット bigquery-public-data.samples.github_nested を自分のプロジェクトに複製して、このテーブルを対象とします。 BigQuery コンソール(BigQuery Studio)で対象テーブルを表示して、「分析情報」タブを選択します。 「分析情報」タブ プロジェクトで必要な API が有効化されていない場合、ここには API の有効化を促す表示がされます。表示に従い、API を有効化してください。 API を有効化されると、青いボタン「Generate insights for free」(無料で分析情報を生成)が表示されます。これをクリックします。 生成された説明を確認 数分後、生成された分析情報が表示されます。下部には分析のための SQL クエリが表示されています。 分析情報の生成結果 上部に表示されている「テーブルの説明」ブロックの中にあるリンク「列の説明を表示」をクリックすると、自動生成されたテーブルの説明とカラムの説明が表示されます。 生成された説明(Description) テーブルへの保存 「テーブルの説明」の下部にある「詳細に保存」をクリックすると、テーブルの説明を保存前に編集できます。任意の文章に編集したあと、「Save」ボタンを押下すると、テーブルに説明が保存されます。 テーブルの説明 「列の説明」の下部にある「スキーマに保存」を押下すると、同様に列の説明を編集できます。任意の文章に編集したあと、「保存」ボタンを押下すると、テーブルのカラムに説明が保存されます。 列の説明 結果 上記の手順では、パブリックデータセット bigquery-public-data.samples.github_nested を複製してメタデータ生成の対象にしました。同テーブルの仕様は、以下のとおりです。 スキーマ 列名 型 repository RECORD actor_attributes RECORD created_at STRING public BOOLEAN actor STRING payload RECORD url STRING type STRING 規模 項目 値 行数 2,541,639 合計論理バイト 1.58 GB 合計物理バイト数 471.78 MB 上記の表では省略していますが、RECORD 型の列の中には、多くのネストされた列があります。 このテーブルに対しては、以下のようなテーブルの説明が自動的に生成されました。 This table stores events from the GitHub platform. It captures actions performed by users, such as creating pull requests, commenting on commits, or pushing code. The table provides details about the actor performing the action, the type of event, and related data. It allows for analysis of activity trends, user contributions, and repository changes within the GitHub ecosystem. Gemini による日本語訳は、以下のとおりです。 このテーブルには、GitHubプラットフォームで発生したイベントが保存されています。ユーザーによるプルリクエストの作成、コミットへのコメント、コードのプッシュといったアクションを捉えます。テーブルには、アクションを実行したユーザー(アクター)、イベントの種類、関連データなどの詳細が含まれており、GitHubエコシステムにおける活動の傾向、ユーザーのコントリビューション、リポジトリの変更履歴などを分析できます。 この説明は概ね、データの内容を表しているといえます。 また、列の説明も概ね正しいものでした。なお、ネストされた列の説明もすべて生成されていました。 ネストされた列も説明が生成された 日本語での生成 BigQuery のメタデータの自動生成機能は、日本語を含む他言語に対応しています。ただし、デフォルトの出力は英語であり、他の言語で出力するには、 事前に テーブルの説明(Description)に「Generate table and column descriptions in Japanese.」のように プロンプトを埋め込んでおいてから 、データ分析情報(Data insights)の生成を実行する必要があります。 参考 : Generate data insights in BigQuery - Control generation language 以下のように、テーブルの説明(Description)に、日本語で説明を生成するように指示するプロンプトを事前に記述しておきます。 テーブルの説明(Description)にプロンプトを記述 その後、データ分析情報(Data insights)を生成します。既に実行済みの場合は、以下のボタンで再度、生成を指示できます。 データ分析情報(Data insights)を再度生成 以下のように、説明が日本語で生成されました。 日本語で生成された説明(Description) 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の横澤です。Gemini アプリの Google Workspace Apps を利用することで、Gemini アプリを Google カレンダーや Google ToDo リストと連携し、業務効率を高めることができます。 概要 Google Workspace Apps とは 有効化方法 Google カレンダーとの連携でできること 予定の検索・取得 予定の追加 時間の分析 Google ToDo リストとの連携でできること タスクの検索 タスクの追加 タスクの消化率の分析 Gems × Google Workspace Apps 概要 Google Workspace Apps とは Gemini アプリの Google Workspace Apps とは、Gemini アプリから Gmail、Google ドキュメント、Google ドライブ、カレンダー、ToDo リストといった Google サービスを呼び出し、一つの画面上で横断的に操作できる仕組みです。 作業の流れを中断することなく情報を取得したりタスクを追加したりできる点が特長です。 参考 : Gemini でのアプリの利用と管理 有効化方法 Google Workspace Apps を有効化するには、まず Gemini アプリのサイドバーを開き、「設定とアプリ」アイコンをクリックします。 設定メニューが表示されるので、その中から「アプリ」を選択すると 「Google Workspace」の ON / OFF スイッチが表示されます。初期設定ではオフになっている場合が多いため、スイッチをクリックして ON に切り替え機能を有効化します。 Google カレンダーとの連携でできること Gemini と Google カレンダーを連携することで、自然言語による指示で、カレンダー予定の確認や登録が可能です。 予定の検索・取得 プロンプト例 @Google Calendar 今日の予定を教えてください。 Gemini が Google カレンダーから予定を取得し、一覧で表示します。 予定の追加 プロンプト例 @Google Calendar 6月13日 に午後5時〜6時 で 「A社×G-gen」というタイトルで会議の予定を設定して。 また、「G-gen 東京本社-3F-小会議室 (8)」をあわせて予約して。 会議予定に含めたい日時とタイトルを入力することで Gemini が予定を作成します。あわせて、会議室を利用する場合には会議室名を指定することであわせて予約することができます。 時間の分析 プロンプト例 @Google カレンダー 今週あった会議の一覧を表示してください。また、どれくらい会議に対して時間を割いたか教えてください。 Gemini によりどのような予定にどの程度時間を使っているのかを分析することができます。また、どのようにすれば効率できるかなどそのまま Gemini に聞くことで時間分析後の次のアクションに繋げるといったこともできます。 このように Gemini 内のリサーチやドキュメント作成中に突然打ち合わせの連絡が入った場合でも、Gemini 上で迅速に予定を確認・追加できるため、画面遷移の必要がなく、作業に集中できます。 Google ToDo リストとの連携でできること Google カレンダーとは別に、日々のタスクを細かく管理している方には Google ToDo リストとの連携も効果的です。 タスクの検索 プロンプト例 @Google To Do リスト やるべきタスクを教えて 登録済みのタスク一覧を表示させることができます。 タスクの追加 プロンプト例 @Google To Do リスト 上記チェックリストの各項目を6月20日を期限にタスクとして登録して アイデア出しから生じたやるべきタスクを追加する操作をしています。このように、自然な会話の流れでGemini から Todo リストに直接タスクを追加することが可能です。 タスクの消化率の分析 プロンプト例 @Google ToDo リスト 今の時点でのタスクの消化率を教えて。 特定のタスクの完了状況や、全体的な進捗状況を問い合わせることで、現在のタスクの消化率を確認することができます。 現時点で登録しているタスクの確認や、Gemini チャットを利用したアイデア出しなどで生じたタスクの登録などを Gemini 画面上で抜け漏れなくタスク管理することが可能です。また、現時点でどの程度のタスクが完了しているかや消化率などを確認し、業務上でのタスクのステータス管理を徹底することができます。 Gems × Google Workspace Apps Gems は、自分専用のカスタム AI アシスタントを簡単に作成できる Gemini アプリの機能です。自然言語のプロンプトと拡張機能の設定だけで、日々の業務で特定の役割を担うAIアシスタントを作成できます。 たとえば、Google カレンダーと連携して「スケジュール調整を支援するアシスタント」を作成することもできます。以下のようなカスタム指示を設定することで、実用的なスケジュールアシスタントをGems上に実装できます。 カスタム指示の例 あなたは私のスケジュールを管理する秘書のような役割をもったアシスタントです。 **目的と目標:** * ユーザーのスケジュール管理を効率化し、時間管理をサポートします。 * ユーザーのニーズに合わせた最適な会議候補日時を提案します。 * スケジュール調整の負担を軽減し、生産性向上に貢献します。 **行動とルール:** 1) 初期対応と情報収集: a) ユーザーの要望を明確に理解するために、必要な情報を質問します(例:会議の目的、参加者、所要時間、希望日、場所など)。 b) 不明な点があれば、具体的な確認の質問を行い、曖昧さを解消します。 2) スケジュール確認と提案: a) @Google Calendar を参照し、ユーザーの空き時間を確認します。 b) 指定された期間内で会議の候補日時を3件提案します。 c) 相手が複数いる場合は、全員の @Google Calendar の空き状況を確認し、共通して空いている時間を優先して提案します。 d) 提案には、候補日・時間・所要時間(指定があれば)を含めてください。 e) 会議の種類(例:1on1、定例、チームミーティング、顧客との打ち合わせ)に応じて、最適な曜日や時間帯を優先してください。 f) カレンダーに「不在」「退勤後」などブロックされている時間がある場合は、その時間を避けて候補を提案します。 3) イベント作成とメール生成: a) 必要に応じて、@Google Calendar にイベントの下書きを作成します。 b) 会議招待のメール本文も生成します(敬語を使用)。 c) メール本文には、会議の目的、日時、場所、議題などの必要な情報を含めます。 4) 全体的なトーン: * 丁寧でプロフェッショナルな言葉遣いを心がけます。 * 親切で協力的な姿勢でユーザーをサポートします。 * 効率的かつ正確な情報提供に努めます。 * ユーザーのプライバシーに配慮し、機密情報を適切に扱います。 カスタム指示を設定したら、あとは通常どおりプロンプトで指示します。 プロンプト例 1 on 1をどこかで設定したいです。 このように、あらかじめカスタム指示に含めていた「会議の候補日を提案」「Google カレンダーへの下書き作成」「招待メール本文の自動生成」といった一連のスケジューリング業務を Gemini が自動で行います。 横澤 綜一 (記事一覧) 事業開発部カスタマーサクセス課 英文学科からITの世界へ。Google Workspace 専任サポートから Google Workspace のカスタマーサクセスへロールが代わり日々奮闘中。週5でジムに通う。
アバター
G-gen の高井(Peacock)です。Compute Engine (GCE) VM に Ops エージェントのインストールを試みた際、 gce_workload_cert_refresh というプロセスから HTTP 404 エラーがログに出力され Ops エージェントのインストールが失敗する事象について、その原因と対処法を解説します。本記事ではまず Ops エージェントについて簡単に触れ、その後に具体的なエラーと対処法を説明します。 Ops エージェントとは 事象 原因 対処法 Ops エージェントとは Ops エージェント (Ops Agent)は、Compute Engine インスタンスやオンプレミスサーバーからログと指標(メトリクス)を収集し、Google Cloud の Cloud Logging と Cloud Monitoring に送信するための統合エージェントです。主な機能は以下の通りです。 ログ収集 アプリケーションログ、システムログなど、様々なソースからログを収集し、Cloud Logging へ送信します。これにより、ログの一元管理、検索、分析、アラート設定などが可能になります。 指標収集 メモリ使用量、ディスク I/O といったシステム指標や、Apache、MySQL、Nginx などのサードパーティアプリケーションの指標を収集し、Cloud Monitoring へ送信します。これにより、システムのパフォーマンス監視、ダッシュボード作成、アラート設定などができます。 Ops エージェントを利用することで、オブザーバビリティ(可観測性)の向上に繋がり、システム運用における問題の早期発見や原因究明を効率化できます。 参考 : Ops エージェントの概要 事象 Compute Engine VM(Debian 系、2024 年 6 月当時の OS イメージ)に Ops エージェントのインストールを試みた際、以下のようなエラーログが繰り返し出力され、Ops エージェントのインストールが失敗しました。 gce_workload_cert_refresh[PID]: YYYY/MM/DD hh:mm:ss: Error getting config status, workload certificates may not be configured: HTTP 404 このエラーは、 ⁠gce_workload_cert_refresh というプロセスが、ワークロード証明書の設定ステータスを取得しようとして失敗していることを示しています。 原因 このエラーの原因は、Ops エージェントのインストール時に有効化される gce-workload-cert-refresh.timer という systemd ユニットが、VM 上で ワークロード間の認証機能 の設定状況を確認しようとすることにあります。 具体的には、このタイマーは定期的に(デフォルトでは 10分ごと)、インスタンスメタデータサーバーの特定のエンドポイント( http://metadata.google.internal/computeMetadata/v1/instance/gce-workload-certificates/config-status )にアクセスします。しかし、 ワークロード間の認証機能 が VM で有効になっていない場合、このメタデータエンドポイントは存在しません。そのため、メタデータサーバーは HTTP ステータスコード 404(Not Found)を返します。これがエラーログとして記録されます。 実際に、影響を受けている VM から以下のコマンドを実行すると、404 エラーが返されることが確認できます。 curl " http://metadata.google.internal/computeMetadata/v1/instance/gce-workload-certificates/config-status " -H " Metadata-Flavor: Google " レスポンス例 <!DOCTYPE html> < html lang = en > < meta charset = utf-8 > < meta name = viewport content = "initial-scale=1, minimum-scale=1, width=device-width" > < title > Error 404 (Not Found)!!1 </ title > < style ></ style > (中略) < a href = //www.google.com/ >< span id = logo aria-label = Google ></ span ></ a > < p >< b > 404. </ b > < ins > That’s an error. </ ins > < p > The requested URL < code > /computeMetadata/v1/instance/gce-workload-certificates/config-status </ code > was not found on this server. < ins > That’s all we know. </ ins > ワークロード間の認証機能 (正式には「Compute Engine 間の認証に mTLS を使用する」などと呼ばれる機能)は、VM インスタンス間で相互 TLS(mTLS)認証を確立するためのものです。 この機能は、記事執筆時点(2025年5月)では pre-GA ステージ(プレビュー)として提供されています。 そのため、明示的にこの機能を有効化していない限り、多くの環境ではこのエラーが発生する可能性があります。 参考 : ワークロード間の認証のトラブルシューティング 参考 : Compute Engine 間の認証に mTLS を使用する 対処法 ワークロード間の認証機能を利用する予定がない場合、エラー出力を停止するために、systemd ユニット gce-workload-cert-refresh.timer を停止し、無効化することが最も簡単な対処法です。具体的には、以下の systemctl コマンドを VM 上で実行します。 sudo systemctl stop gce-workload-cert-refresh.timer sudo systemctl disable gce-workload-cert-refresh.timer この対処により、 gce-workload-cert-refresh プロセスによる定期的なメタデータサーバーへのアクセスがなくなり、結果として HTTP 404 エラーログの出力も停止し、エージェントがインストールできるようになります。 前述の通りワークロード間の認証機能は pre-GA ステージであり、特定のユースケースでのみ利用される機能のため、このタイマーを無効化しても Ops エージェントの基本的な監視機能や他の VM の動作に影響はありません。 将来的にワークロード間の認証機能を利用する必要が生じた場合は、該当ユニットを再有効化できます。 sudo systemctl enable gce-workload-cert-refresh.timer sudo systemctl start gce-workload-cert-refresh.timer Peacock (高井 陽一) (記事一覧) クラウドソリューション部 カスタマーサポート課 2022年12月より入社。普段は Google Cloud の技術サポートや Terraform などによる IaC の推進を行なっている。また、プライベートでは PyCon JP 2022, 2023(APAC) にて副座長など、カンファレンスのスタッフとしても活動している。趣味はカメラ・スキー・クラシック音楽など。 Follow @peacock0803sz
アバター
G-genの杉村です。当記事では、AI エージェント時代に対応する次世代データ基盤アーキテクチャとして「メダリオンアーキテクチャ 2.0」と、その中核をなす「プラチナレイヤー」をGoogle Cloudで実現する方法を解説します。 はじめに 概要 メダリオンアーキテクチャとは AI エージェント時代のメダリオンアーキテクチャ アーキテクチャ メダリオンアーキテクチャ(従来) メダリオンアーキテクチャ 2.0 実装 プラチナレイヤー セマンティックレイヤー ナレッジグラフ マルチモーダルデータ 追加インターフェイス リアルタイムデータ 情報のシェア・販売 ガバナンス補強 メタデータ管理 データリネージ データのプロファイリング 自動データ品質 AI エージェント 4つのデータエージェント Data Engineering Agent Data Science Agent Data Governance Agent Conversational Analytics Agent 独自エージェントの実装 データの民主化へ ユーザーへのデータ解放 スプレッドシートと AI プラチナレイヤーとデータの民主化 はじめに 概要 当記事では、AI エージェント時代のデータ基盤の新たなあり方として、従来のメダリオンアーキテクチャを進化させた「 メダリオンアーキテクチャ 2.0 」というコンセプトについて、筆者の視点から再整理し、その具体的な実装方法と共に論じます。 そして、その中核となる「 プラチナレイヤー 」の概念と、Google Cloud でどのように実現するかを解説します。 メダリオンアーキテクチャ 2.0 は、Google Cloud Japan 公式の Zenn Publication(ブログ)の記事「AIエージェントが真価を発揮するデータ基盤へ -メダリオンアーキテクチャ 2.0 と "プラチナレイヤー" を考える」で提唱されました。当記事では、このアーキテクチャのうちリアルタイムデータやガバナンスなどの責務を分離して再定義したうえで紹介しています。 zenn.dev メダリオンアーキテクチャとは メダリオンアーキテクチャ は、データレイクハウス内のデータを3つの論理的な層(レイヤー)で段階的に処理し、品質と価値を高めていくアプローチです。 メダリオンアーキテクチャを提唱したのは米国の Databricks 社です。同社の製品である Databricks は、クラウド型の統合データプラットフォーム製品であり、データの変換・保存・管理・可視化・分析などを総合的に扱うことができます。2013年に Databricks 社が設立されて以降、データ分析基盤の構築にあたり高い存在感を持っています。 参考 : メダリオンアーキテクチャ (Medallion Architecture) このアーキテクチャでは、基盤に保存されるデータを3つの抽象的なレイヤーに分類します。 1. ブロンズレイヤー 未加工データを保存するレイヤー。ソースシステムのデータをそのまま保管する。後のレイヤーのためにデータを加工しても、ブロンズレイヤーには生のデータを保持しておく。 2. シルバーレイヤー ブロンズレイヤーのデータを変換・抽出してある程度の整備を施したもの。顧客マスタ、店舗マスタ、重複排除済みのトランザクションデータなど。アドホックな分析や機械学習への利用などが可能。 3. ゴールドレイヤー シルバーレイヤーのデータにさらに加工を施したもの。より非正規化され、キュレート(目的に応じて整備)されており、より多くのユーザーから利用される準備ができている。 レイヤーが進むごとにデータの価値が向上する様を、ブロンズ、シルバー、ゴールドといったメダルになぞらえていることから「メダリオン(Medallion)」アーキテクチャと名付けられています。 なおこれらのレイヤーは、書籍等では以下のように呼称されることもあります。呼び名が異なっても、ほとんど同じ概念と捉えることができます。 ブロンズレイヤー -> データレイク層 シルバーレイヤー -> データウェアハウス層 ゴールドレイヤー -> データマート層 Databricks では、Cloud Storage(Google Cloud)や Amazon S3(AWS)などのクラウドストレージサービスと連携しながら、Apache Spark 等を基盤技術として、上記のレイヤーを実現しています。 AI エージェント時代のメダリオンアーキテクチャ 2022年末ころに ChatGPT がブームになってから2025年7月の現在に至るまで、生成 AI は日常業務レベルにまで発展・普及しました。最近では、AI が人間の代わりにタスクを行う AI エージェント の活用が盛んに論じられるようになっています。AI エージェントは早晩、日常業務で人間を助けるようになっていくでしょう。 AI エージェントは人間の指示に基づき、データを読み込んでコンテキストとして利用したり、あるいは SQL や API リクエストを生成してデータを取得し、 自動で分析 したり、 人間にデータを提供 するようになっていきます。AI エージェントはデータ分析基盤に存在する前述の各レイヤーからデータを取得して、利用したり、人間のためにデータを提供することになります。 AI エージェントの発展に伴い、前掲の Google Cloud Japan 公式の Zenn Publication(ブログ)で公開された以下の記事では、AI が自律的にデータを活用しやすくなるよう、第4のレイヤーである プラチナレイヤー を提唱しています。 参考 : AIエージェントが真価を発揮するデータ基盤へ -メダリオンアーキテクチャ 2.0 と "プラチナレイヤー" を考える 今回は、このプラチナレイヤーを深堀りし、前述の記事が提唱する新しいアーキテクチャである「 メダリオンアーキテクチャ 2.0 」を論じます。 アーキテクチャ メダリオンアーキテクチャ(従来) まず、Google Cloud を主な基盤としてメダリオンアーキテクチャを実現した場合の一例を以下の図に示します。 メダリオンアーキテクチャ(従来) 多くの組織では、元データを持つシステムはオンプレミス、Amazon Web Services(AWS)、Google Cloud など、複数のプラットフォームに分散しています。よってブロンズレイヤーは、Amazon S3、Cloud Storage、BigQuery などに分散している可能性があります。これらの分散したデータを1つの抽象レイヤーとして管理するには、サードパーティ製品や、Dataplex Universal Catalog(旧称 Dataplex Data Catalog)でメタデータを管理しつつ、OIDC/SAML を用いた認証情報の連携などが必要になります。 シルバーレイヤーとゴールドレイヤーは、BigQuery で構成します。 各レイヤー間のデータ移送、変換は、Dataform と呼ばれる Google Cloud ネイティブな SQL ベースのワークフローツールや、サードパーティのワークフロー管理ツールなど、様々な候補が挙げられます。 また、Amazon S3 から Cloud Storage や BigQuery へのデータ移送には、BigQuery Data Transfer Service を用いたり、BigQuery Omni(ただし東京・大阪リージョンの Amazon S3・BigQuery には未対応)などを用いることができます。 参考 : BigQuery Data Transfer Service とは 参考 : BigQuery Omni の概要 このようなメダリオンアーキテクチャ型のデータ分析基盤は、2010年代以降、多くの組織で Google Cloud を使って実装されてきました。 メダリオンアーキテクチャ 2.0 前述の記事「AIエージェントが真価を発揮するデータ基盤へ -メダリオンアーキテクチャ 2.0 と "プラチナレイヤー" を考える」では、従来型のメダリオンアーキテクチャにプラチナレイヤーを加え、このレイヤーに以下のような機能を持たせています。 機能名 概要(前述記事からの引用) セマンティックレイヤー 「売上」「利益」「顧客数」といったビジネス指標とその計算方法、データ間の関係性を定義した「意味の辞書」 ナレッジグラフ(データの相関関係) データ同士の「関係性」をグラフ構造で表現したもの ガバナンス AI エージェントの自律的なデータ利用を、安全かつ透明性の高い形で実現するためのガードレール マルチモーダルデータ 契約書(PDF)、議事録(Docs)、画像、音声、動画などの非構造化・半構造化データ リアルタイムデータ 顧客の行動、IoTセンサー、ログデータといったストリーミングデータのリアルタイムな取り込み 上記は、AI エージェントからデータを利用するにあたり有用です。しかしながら当記事では、メダリオンアーキテクチャの各層の命名の意味合いに鑑みて、以下のように整理しなおしました。 セマンティックレイヤー 、 ナレッジグラフ 、 マルチモーダルデータ => プラチナレイヤー リアルタイムデータ => ブロンズレイヤー の 追加インターフェイス ガバナンス => 全レイヤーの ガバナンス補強 セマンティックレイヤー、ナレッジグラフ、マルチモーダルデータについては、ゴールドレイヤーのデータに価値を付加するという意味において、プラチナレイヤーと呼称するにふさわしいと考えます。 リアルタイムデータについては、加工前の生データとして最初にデータ基盤へ流入することが多いため、ブロンズレイヤーの責務としました。 ガバナンスはデータの発生から活用までのライフサイクル全体で一貫して適用されるべき原則であり、特定のレイヤーに限定されるものではないため、横断的な機能として捉え直しました。 当記事では上記の考えに基づき、先行記事で論じられたメダリオンアーキテクチャ 2.0 を捉え直します。 これを構成図に反映すると、以下のようになります。 メダリオンアーキテクチャ 2.0 図に掲載されているサービスを、かならずしもすべて実装する必要はありません。必要に応じて追加の実装を行い、データの入口を追加したり、プラチナレイヤーを実装すればよいことになります。 実装 プラチナレイヤー セマンティックレイヤー セマンティックレイヤーの実装に当たっては、Google Cloud のデータプラットフォームおよびデータ分析・可視化ツールである Looker を使うことができます。 Looker で定義されたディメンションやメジャー(指標)を、AI 等から利用できるようにします。Looker に付帯の Gemini for Looker では、自然言語の指示により、AI がデータを可視化したり、AI にデータを分析させることができます。 Looker の大きな特徴は、 LookML という仕組みにより共通のディメンションやメジャーを定義できる点です。「売上」「粗利」「営業利益」「顧客数」といった指標の意味を LookML で集中管理することで、データの解釈に齟齬がでないように統一できます。 参考 : GoogleのBIツール、LookerとLooker Studioを比較してみた - G-gen Tech Blog Looker のディメンションやメジャー、また Gemini in Looker には、API 経由でアクセスすることができます。これにより、AI エージェントから、セマンティックレイヤーを経由してデータにアクセスさせることが可能になります。 ナレッジグラフ ナレッジグラフは、データの相関関係を管理する仕組みです。Google Cloud サービスを使った、いくつかの実装が考えられます。 BigQuery Graph Analysis BigQuery Graph Analysis は、BigQuery 上のデータに対して GQL(Graph Query Language)と呼ばれるグラフクエリ言語を実行できる機能です。2025年7月現在、まだ利用可能になっておらず、将来リリースされる予定です。 これによりデータ間の関係性を可視化することができ、関係性の情報を保持しておくことで、AI がデータ間の関係性を理解して適切なインサイトを提供するのに役立ちます。 参考 : YouTube - Unleashing graph analytics in BigQuery BigQuery Contribution Analysis BigQuery では、簡単に 貢献度分析 (Contribution Analysis)が可能です。この機能では、BigQuery ML を使って貢献分析を行う機械学習モデルをトレーニングし、ある多次元データにおいて主要な指標が変化した際に、どういったデータがその変化に貢献したのかを分析することができます。 これによりデータ間因果関係という関係性を可視化するのに役立ち、ナレッジグラフの構成に繋がります。 参考 : 貢献度分析の概要 BigQuery Knowledge Engine BigQuery Knowledge Engine は2025年7月現在、未公開ですが、将来のリリースが予告されています。BigQuery knowledge engine は、複数テーブルにまたがるクエリの提案や、自然言語による質問への回答などにより、複数のデータセットやテーブルの間の関係性を可視化し、把握するための機能です。エンティティ間の関係性をグラフで表現し、データ間の繋がりを可視化したり、テーブルをまたいだクエリをサジェストできます。 この機能では、テーブル間の意味的な関係性を可視化し、ナレッジグラフを構成することに繋がります。 参考 : BigQueryの新発表を解説(Google Cloud Next '25速報) - G-gen Tech Blog - BigQuery knowledge engine マルチモーダルデータ BigQuery オブジェクトテーブル BigQuery にはオブジェクトテーブルと呼ばれるタイプのテーブルがあります。BigQuery のテーブルにあたかも動画、画像、音声などの非構造化データを格納したかのように扱い、分析したり、BigQuery ML で機械学習のトレーニングや推論に使うことができます。実際にはテーブルには非構造化オブジェクトのメタデータが格納されており、データの実体は Cloud Storage バケットに格納されます。 参考 : オブジェクト テーブルの概要 BigQuery multimodal tables BigQuery multimodal tables は、前述のオブジェクトテーブルよりもさらに構造化データと非構造化データの統合を推し進めたものです。 ObjectRefs 型の値をテーブルに持つことで、非構造化データを BigQuery の標準テーブルに持たせることができます。こちらも、データの実体は Cloud Storage に格納されます。標準テーブルに非構造化データを統合できるため、構造化データと組み合わせた分析や BigQuery ML からの利用、Python ライブラリである BigQuery DataFrames からの利用など、より分析の利便性が向上します。当機能は、2025年7月現在、Preview 公開です。 参考 : Analyze multimodal data in BigQuery BigQuery Auto Discovery BigQuery Auto Discovery は、Cloud Storage 上の非構造化データを自動で検出して、BigQuery オブジェクトテーブルを作成する機能です。バックエンドでは Dataplex が使われています。 参考 : Cloud Storage データを検出してカタログ化する 追加インターフェイス リアルタイムデータ Pub/Sub の BigQuery サブスクリプション Pub/Sub は、フルマネージドのメッセージキューサービスです。BigQuery サブスクリプション機能を使うと、Pub/Sub に発行(パブリッシュ)されたメッセージを、直接 BigQuery に書き込むことができます。メッセージを受け取って BigQuery に書き込むプログラムは必要ありません。 blog.g-gen.co.jp Pub/Sub の Cloud Storage サブスクリプション Pub/Sub の Cloud Storage サブスクリプション機能を使うと、Pub/Sub に発行(パブリッシュ)されたメッセージを、直接 Cloud Storage に書き込むことができます。こちらも、メッセージを受け取って Cloud Storage に書き込むプログラムを作成する必要はありません。 blog.g-gen.co.jp BigQuery の Continuous Queries(継続的クエリ) BigQuery の Continuous Queries(継続的クエリ)を使うと、BigQuery テーブルに到着したデータ(レコード)に対して決まった処理(SQL)を実行することができます。BigQuery ML を使った推論を行わせることもできます。これにより、スケジュール実行でクエリを実行するよりも少ない考慮事項(どこまで処理したか、バックフィルなど)で継続的処理を実装できます。 blog.g-gen.co.jp 情報のシェア・販売 BigQuery Sharing BigQuery Sharing(旧称 Analytics Hub)は、BigQuery のデータセットを、他の組織に安全に共有したり、販売して収益化するための機能です。従来は Analytics Hub と呼ばれていましたが、2025年4月に改名されました。データクリーンルーム機能により、きめ細かいアクセス制御を設定することができます。また Google Cloud Marketplace を通じて、データを販売して収益化することができます。 参考 : Analytics Hub の概要  |  BigQuery  |  Google Cloud Stream sharing with Pub/Sub Stream sharing with Pub/Sub は、Pub/Sub トピックを異組織間でシェアするための仕組みです。リアルタイムデータを別の組織に共有したり、逆に共有を受けることができます。基盤として BigQuery Sharing(旧称 Analytics Hub)の仕組みを利用しています。 参考 : Pub/Sub を使用したストリーム共有 ガバナンス補強 メタデータ管理 Dataplex Universal Catalog (旧称 Dataplex Catalog)は、BigQuery や Cloud Storage などの Google Cloud サービス、およびサードパーティのストレージに格納されたメタデータを管理するフルマネージドサービスです。 BigQuery のデータセットやテーブルの説明(Description)、Pub/Sub トピックの情報などは自動的に収集され、Dataplex Universal Catalog の画面から検索・表示可能です。 さらに Dataplex Universal Catalog は、Cloud Storage 内のデータを検出して外部テーブルや BigLake テーブル、オブジェクトテーブルなどとして定義する Data Discovery 機能も備えています。 blog.g-gen.co.jp メタデータの自動生成 を使うと、BigQuery テーブルやそのカラムに対して、AI によりメタデータを自動生成できます(ただし2025年7月現在、英語の生成のみ対応)。メタデータの整備は人間にとって重要であることに加えて、AI がデータを適切に取得して分析手法を確立するために必須です。 参考 : Generate data insights in BigQuery - Generate table and column descriptions BigQuery のメタデータ自動生成 データリネージ Google Cloud プロジェクトで所定の API を有効化するだけで、BigQuery の データリネージ を記録・可視化することができます。BigQuery テーブルに対して実行された COPY、CREATE、INSERT SELECT、MERGE、UPDATE などが自動的に記録され、リネージグラフとして表示可能です。 参考 : データリネージについて データリネージ データのプロファイリング Dataplex Universal Catalog を使って BigQuery のテーブルに対して データプロファイリング を行うと、null 値の割合、近似値の割合、平均値や標準偏差、最小値など、テーブルの統計的な情報を簡単に生成できます。 この情報は AI がデータの特性を把握するために重要になります。 参考 : データ プロファイリングについて データプロファイリング 自動データ品質 Dataplex Universal Catalog の自動データ品質機能は、定義済みのルールに基づきデータのスキャンを自動化し、データの品質要件を満たさない場合にはアラートを記録・発報する機能です。 AI が正しいデータに基づいて分析ができるよう、可能な限り品質担保を自動化することができます。 参考 : 自動データ品質の概要 AI エージェント 4つのデータエージェント メダリオンアーキテクチャ 2.0 は、AI エージェントがデータを活用できるように、従来型のメダリオンアーキテクチャに追加の実装を施したものです。 前述の記事では、データ基盤を利用する AI エージェントとして以下を紹介しています。 Data Engineering Agent Data Science Agent Data Governance Agent Conversational Analytics Agent これらは、2025年4月に米国ラスベガスで行われた Google Cloud Next '25 でもコンセプトが紹介されました。 メダリオンアーキテクチャ 2.0(再掲) Data Engineering Agent Data Engineering Agent は、データエンジニアのタスクを代替したり、支援したりするエージェントです。自然言語の指示に基づいて、データパイプラインを生成したり、開発を支援します。 この実装の1つとして、BigQuery data preparation があります。BigQuery data preparation では、GUI 操作と自然言語での AI への指示により、容易に ELT パイプラインを構築できます。 BigQuery data preparation 参考 : BigQuery データの準備の概要 Data Science Agent Data Science Agent は、データサイエンティストを支援したり、あるいはビジネスユーザーが容易にデータ分析を行えるように支援するエージェントです。 実装の1つとしては、BigQuery データキャンバスがあります。自然言語で AI に指示を出すと、AI が BigQuery データセットの中から必要なテーブルを結合してクエリし、可視化までを行います。 BigQuery データキャンバス 参考 : BigQuery データ キャンバスで分析する blog.g-gen.co.jp Data Governance Agent Data Governance Agent はデータガバナンスを強化するエージェントです。これに関しては Google Cloud ネイティブの機能としてはまだ実装途中です。実装済みのものとして、前述のメタデータ自動生成などが挙げられます(2025年7月現在、Preview 公開・英語のみ)。また、BigQuery のデータ分析情報(Data insights)の生成には、Gemini が使われています。 参考 : BigQuery でデータ分析情報を生成する Conversational Analytics Agent Conversational Analytics Agent は、AI との自然言語での対話を通じてデータを分析するエージェントです。 Looker や Looker Studio Pro に付帯する Gemini in Looker では Conversational Analytics 機能が使用可能です。対話的にエージェントに指示を出して、データの可視化や分析を行わせることができます。Gemini in Looker、Conversational Analytics はいずれも2025年7月現在、Preview 中の機能です。 参考 : Gemini in Looker 参考 : 会話分析: 自然言語でデータにクエリを実行する 独自エージェントの実装 前述の4つのデータエージェントは、Google Cloud Next などで繰り返し謳われているものの、まだいずれもコンセプチュアルなものです。また製品化しても、多くの場合でまずは英語版がリリースされ、日本語対応版は数カ月の遅れをもってリリースされます。 早期に日本語に対応した、あるいは自社特有の業務ドメインに対応した AI エージェントを実装したい場合、私たちユーザーは、以下のような Google Cloud サービスを利用することができます。 Vertex AI 経由で提供される Gemini や Claude などのサードパーティモデル マルチエージェント開発のための Python フレームワークである Agent Development Kit (ADK) エージェントをホストするフルマネージドプラットフォームである Vertex AI Agent Engine や Cloud Run 上記のようなサービスを使い、Google Cloud のエコシステムに閉じて AI データエージェント開発を行うことで、エージェントからデータへの認証機構がシンプルになるほか、データ転送料金やネットワークレイテンシを抑えることができます。以下の記事も参考にしてください。 参考 : 全Geminiプロダクトを徹底解説! - G-gen Tech Blog - Generative AI on Vertex AI 参考 : Agent Development Kitでエージェントを開発してAgent Engineにデプロイしてみた - G-gen Tech Blog 参考 : 入門!Cloud Runのススメ - G-gen Tech Blog データの民主化へ ユーザーへのデータ解放 生成 AI ブーム以前から、 データの民主化 というキーワードは謳われてきました。Google Cloud には、これを強力に後押しする機能が多数備わっています。 BigQuery(ゴールドレイヤー、プラチナレイヤー)に保存されているテーブルデータへの直接クエリはもちろん、今回プラチナレイヤーに分類した Looker の Explorer 機能を用いたオンデマンドなデータ探索は、データの民主化に繋がります。 また、Google Workspace のアプリの1つである Google スプレッドシートには、 コネクテッドシート と呼ばれる機能があります。これは、スプレッドシートと BigQuery を接続し、BigQuery テーブル内のデータをスプレッドシートに吸い上げ、処理可能にする機能です。SQL の知識がないビジネスユーザーでも、使い慣れた Excel ライクなインターフェイスでデータを可視化できます。 blog.g-gen.co.jp このように Google Workspace は、ゴールドレイヤーやプラチナレイヤーのデータへのユーザーインターフェイスになり得ます。 スプレッドシートと AI さらに、スプレッドシートに組み込みの AI 関数 を用いることで、スプレッドシート上のデータに対して 生成 AI モデル Gemini による推論・生成 を実行できます。 このように Google 製品を組み合わせることで、データの民主化や AI の民主化の助けになるといえます。 参考 : Use the AI function in Google Sheets 公式ドキュメント「 Google ドキュメント エディタ ヘルプ 」より引用 プラチナレイヤーとデータの民主化 プラチナレイヤーを整備することで、AI エージェントがデータを解釈しやすくなり、AI エージェントを利用する人間の利便性向上に繋がります。 当記事で解説したメダリオンアーキテクチャ 2.0、特にAIが意味を理解し自律的に活用できるプラチナレイヤーを整備したり、メタデータ整備を始めとするデータガバナンスを強化することで、単なるデータやツールの解放に留まらず、人と AI エージェントの協働による、進化したデータの民主化を実現する鍵となると考えられます。 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の向井です。当記事では、Google Cloud Marketplace のサードパーティ製ソフトウェアを、G-gen のような販売パートナー経由で購入できる Marketplace Channel Private Offer (MCPO)を解説します。 Google Cloud Marketplace とは プライベートな購入方法 プライベートオファーとは Marketplace Channel Private Offer とは 得られるメリット 請求の一元化 ディスカウント 付加価値 柔軟な契約 プロセス MCPO のプロセス オファーの承諾手順 Google Cloud Marketplace とは Google Cloud Marketplace とは、Google Cloud 上で利用できるサードパーティ製のソフトウェアやサービスを Google Cloud 上で購入できるオンラインストアです。 例えば、CDN / WAF サービスの Fastly、アプリケーション監視ツールの Datadog、運用データベースの Oracle Database など、多くのエンタープライズ向けソフトウェアが Google Cloud Marketplace で提供されています。これらを Marketplace から購入することで、Google Cloud の利用料金と請求を一本化できるなどのメリットがあります。 提供されるソリューションの形態は、Compute Engine VM イメージ、コンテナイメージ、SaaS、API など様々です。 参考 : Google Cloud Marketplace の概要 プライベートな購入方法 プライベートオファーとは Google Cloud Marketplace では、公開されている価格表通りに製品を購入するだけでなく、 プライベートオファー (Private Offer)という仕組みを利用できます。 これは、ソフトウェアを提供しているサービス提供ベンダー(ISV、独立系ソフトウェアベンダーとも呼ばれる)が、特定の顧客に対して、個別の価格や利用条件を提示できる機能です。お客様はベンダーと直接交渉し、合意した価格やカスタムのエンドユーザーライセンス契約(EULA)で製品を購入できます。 オファーは、特定の請求先アカウントに対して発行され、お客様は Google Cloud コンソール上でそのオファーを承諾または拒否します。 参考 : プライベート オファーについて Marketplace Channel Private Offer とは Marketplace Channel Private Offer (MCPO)は、前述のプライベートオファーを、G-gen のような販売パートナー(リセラー)を介して利用する仕組みです。MCPO は、単に Channel Private Offer と呼ばれる場合もあります。 通常のプライベートオファーがサービス提供ベンダーと顧客の2者間の取引であるのに対し、MCPO は、サービス提供ベンダー、販売パートナー、顧客の3者間で取引が行われます。 参考 : Google Cloud Marketplace now lets customers buy ISV solutions from channel partners 参考 : ISV から Cloud Marketplace プロダクトを再販する MCPO の仕組み この仕組みにより、顧客は日頃から取引のある販売パートナーを通じて、Marketplace の製品を有利な条件で購入できます。 Fastly、Datadog など、多くの Marketplace 製品が MCPO に対応しています。対応状況や詳細は、サービス提供ベンダーまたは販売パートナーにご確認ください。 得られるメリット 請求の一元化 Marketplace 製品の利用料を、普段の Google Cloud 利用料と合わせて、G-gen のような単一の販売パートナーから発行される請求書で支払うことができます。 これにより、外貨建てのクレジットカード払いを避けて、日本円での請求書払いができます。 ディスカウント 販売パートナーがサービス提供ベンダーと交渉することで、標準価格よりも有利な価格で購入できる可能性があります。 付加価値 販売パートナーが提供する導入支援、技術サポート、コンサルティングなどの付加価値サービスとセットで製品を契約できます。 柔軟な契約 契約期間や支払いサイトなど、企業の購買プロセスに合わせた柔軟な条件で契約できる場合があります。 プロセス MCPO のプロセス MCPO の基本的な流れは以下の通りです。 顧客は、購入したい Marketplace 製品と必要なライセンス数量などを販売パートナーに伝える 販売パートナーは、顧客の要望に基づき、サービス提供ベンダーと価格や条件を交渉する サービス提供ベンダーは、交渉結果に基づき、販売パートナーに対してプライベートオファーを作成する 販売パートナーは、サービス提供ベンダーから受け取ったオファーに、自社の利益や付加価値サービス分の価格を反映して、顧客向けの新しいプライベートオファーを作成して提示する 顧客は、販売パートナーから提示されたオファーの内容を確認して Google Cloud コンソール上で承諾する 承諾後、Marketplace 製品の利用料金は、Google Cloud の他のサービス利用料と同様に販売パートナーに請求される。販売パートナーは、顧客へ請求書を発行する このプロセスにより、お客様は直接サービス提供ベンダーとやり取りすることなく、販売パートナーを介してすべての手続きを完了できます。MCPO を利用することには、顧客にとってコストメリットや調達プロセスの簡略化などのメリットがあるといえます。 オファーの承諾手順 顧客が MCPO を承諾する際の具体的な手順は、以下の通りです。 販売パートナーが顧客向けにオファーを作成すると、顧客の担当者宛てにメールが発行される 顧客の担当者は、メール内のリンクまたは販売パートナーから共有されたプライベートリンクにアクセスする Google Cloud コンソール上に表示される、オファーの詳細(製品名、プラン、契約期間、価格など)を確認する 内容に問題がなければ、対象の請求先アカウントやプロジェクトを選択して「承諾」ボタンをクリックする 承諾が完了すると、契約が有効になり、Marketplace 製品が利用できるようになる 上記のように、プロセスは非常にシンプルであり数クリックで完了します。 向井 健二 (記事一覧) 事業開発部 カスタマーサクセス課 課長 2022年3月より、G-genにジョイン。 Google Cloud Partner Top Engineer 2024, 2025に選出。熊本在住。
アバター