Firebase AI Logicで爆速なAIを実現する。Server Prompt Templatesを添えて。

この記事は Goodpatch Advent Calendar 2025 の8日目の記事です。

こんにちは!エンジニアの古家です。

普段はオンラインホワイトボード「Strap」の開発をしています。 世は大AI時代。息をするようにプロダクトにLLMが組み込まれているのが日常の風景になりましたね。

StrapでもAI機能の強化を進めていますが、今回はその裏側で「いかにユーザーを待たせずにAIを動かすか」という課題に向き合った話をしてみます。

はじめに: 爆速レスポンスのAIを実現したい

StrapはFirebase上に構築しており、これまでStrapのAI機能はCloud Functionsで実行していました。 しかし、今回検討していた機能では、ユーザーのアクションに対して、これまでよりもさらに早くレスポンスする必要がありました。

生成AIを使うと、どうしても待たされることが多いです。 待ち時間が長いと、思考も途切れてしまいますしね。 今回はこの待ち時間を極力避けるにはというお話です。

実現技術の比較検討

「速さ」を最優先事項として、まずはAIへの通信リクエストについて3つのアーキテクチャを比較検討しました。*1

1. Cloud Functions (従来)

バックエンドでAIを実行し、結果を待ってから返すパターンです。

セキュアで実装も枯れていますが、共通の認可処理を挟むことやAIの生成完了を待つ必要があるため、体感速度はどうしても遅くなります。*2

Cloud Functionsでの実装例

2. Cloud Functions + Streaming Response

2nd GenのResponse Streamingを利用して、生成されたトークンから順次クライアントに返す方法です。

よくあるチャットAIツールのように、クライアント側も受信したデータを順次表示するように実装することで、従来の方式よりは初速が出ます。

しかし、それでも従来と同様にAIリクエストまでの前処理によるオーバーヘッドは避けられません。 実測としては数百ミリ秒〜1秒強程度の世界ですが、ユーザーにとっては「ワンテンポ遅れる」感覚は残ります。

3. Firebase AI Logic

今年、Firebaseに追加された Firebase AI Logic (旧 Vertex AI for Firebase) です。 クライアント(ブラウザ)から直接Googleのゲートウェイを経由してGemini APIを叩きます。 クライアント認証はApp Checkが担保することで、従来は難しかったクライアントからのAI APIの直接実行を実現しています。

自社バックエンドを経由しないため、その分のオーバーヘッドを省略できる反面、プロンプトやロジックがクライアントサイドに露出するリスクがあります。

今回は「爆速」を実現するため、AI Logicを採用してみることにしました。

Firebase AI Logicでの実装例

「プロンプト漏洩」の課題と、Server Prompt Templates

クライアント実行を選ぶ上で最大の懸念は、やはりセキュリティです。 App Checkを利用することで、不正なクライアントからのAPIアクセスは防げます。

しかし、JSバンドルの中に「あなたはプロのPMです。以下の形式で回答してください...」といったシステムプロンプトを含める必要がある点は大きな課題です。

プロンプトはAI機能でも重要な要素です。クライアント実行を行う場合はブラウザからの通信にこれらの情報が載ることになります。例えばブラウザのDevToolsで簡単に内容が見られてしまうのは、懸念が残るところです。

AI Logicの導入は本当に簡単なので、一般的な要約やちょっとした文章修正のような機能であれば導入の手軽さが勝る場面もあるでしょうが、場合によっては避けたい問題点です。

今後、この問題を解消できそうなのが、つい先日リリースされた Firebase Server Prompt Templates です。

Server Prompt Templates とは

これまでクライアントコードにハードコードしていたシステムプロンプトやモデルパラメータを、Firebase側で管理できる機能です。 クライアントからは、具体的な指示内容の代わりに「テンプレートID」を指定するだけでAIを実行できます。 *3

イメージとしてはこんな感じです:

const ai = getAI(app, { backend: new VertexAIBackend() });

// テンプレート実行用のモデルを取得
const model = getTemplateGenerativeModel(ai);

const customerName = 'Jane';

const result = await model.generateContent(
  // テンプレートIDを指定する
  'my-first-template-v1-0-0',
  // プロンプト内の変数をパラメーターとして送信
  {
    customerName: customerName,
  }
);

const response = result.response;
const text = response.text();

これにより、爆速レスポンスを享受しつつ、プロンプトの秘匿化を実現することができます。 また、簡単なプロンプトの調整はFirebaseコンソールのGUI上で完結できるのも嬉しい副産物です。

プロンプトの外部テンプレート化は他社AIサービスでも提供されていますが、クライアントから直接AIを実行できるAI Logicと合わさることで、より利便性が高まっているのではないでしょうか。*4

実際の開発チームで運用するには、このテンプレートをGitなどでバージョン管理しデプロイフローを整備したいところですが、REST APIが用意されているのでこちらで実現ができそうです。

Manage templates

注意点として、現在のServer Prompt TemplatesはPreview版であり、一部のサポートされていない機能があります。 例としては、function callingやgoogle searchによるGrounding、thinkingに関連する設定などがあります。 随時追加されていくことは明言されているため、今後の状況を追っていきたいところです。

Not-yet-supported features

クライアント実行の嬉しい点と、コンテキストの話

クライアントサイド実行に舵を切ったことで、実は速度以外にもう一つ、うれしい誤算がありました。それはコンテキスト取得の効率化です。

DB負荷の低減

サーバーサイドでAIを実行する際、多くの場合、AIに渡すためのデータをFirestoreなどのDBから都度fetchする必要があります。 しかし、StrapのようなSPAの場合、ユーザーが見ている最新のデータは既にブラウザのメモリ上にあります。

クライアント実行であれば、手元にあるデータをそのままAIに渡せるケースも多いため、無駄なDBアクセスを減らすことができます。これはレスポンス速度だけでなく、DBのReadコスト削減にも繋がります。

コンテキストエンジニアリング

一方で、メモリにあるデータを全部AIに投げると、生成コンテンツの品質低下を招いたり、コンテキストウィンドウ(トークン数)が溢れる懸念があります。もちろん課金額も心配です。

そのため、現在は「いかに効率よく、賢くコンテキストを渡すか」というテーマに対し、以下のようなアプローチで取り組んでいます。

  • 情報の選別 : ボード上の要素のクラスタリングや、関連性の高いデータの抽出
  • データの構造化 : ボードならではの視覚的・位置的な情報の効率的な表現
  • コンテキストのキャッシュ : コンテキストデータやボード情報を再利用する仕組みの検討や、AIサービスのContext Cachingの活用

まとめ

SaaSのAI機能において、UX(速度)を追求するために、あえてクライアントサイド実行(Firebase AI Logic)を選択した経緯を紹介しました。

プロンプトの秘匿化などの課題はまだ残りますが、登場したばかりの Server Prompt Templates によって、セキュアな運用への道筋も見えてきています。

それでは、来年も引き続きStrapをご贔屓に。

Goodpatchではデザイン好きなエンジニアの仲間を募集しています。 少しでもご興味を持たれた方は、ぜひ一度カジュアルにお話ししましょう!

*1:パフォーマンスチューニングでは、レスポンスJSONスキーマの構造やプロンプトの工夫など他の観点もありますが、この記事では割愛しています。

*2:すでに最小インスタンス設定などは行なっており、コールドスタートによるロスは回避しています。

*3:これまでもRemote Config経由でリモートからプロンプトやパラメーターを注入する方法は存在しましたが、リクエスト時に露呈する点は変わりません。

*4:とはいえ、パラメーターとレスポンスデータが露呈する点は変わらずなので、引き続き用途の厳選は必要だと思います。