🤖

Firebase Genkitに惚れた話

はじめに

AIチャットボットを作りたくて、最初はGoogle AI SDKを使う予定だった。
最初はGoogle ADKで作っていたものを、途中でやめて、FirebaseGenkitに変えた。

Firebase Genkitを触ってみたら、想像以上に素晴らしくて完全に惚れ込んだ。

構築に1日、LLMチューニングに1日で作成できた。

Genkitに惚れた3つの理由

1. Zodスキーマによる構造化データ - これが本当にいい。

自分がGenkitで最も感動したのは、LLMとのやり取りを完全に型安全にできる点だ。

(ちなみに同じAIフレームワークのVercel SDKも同じような方式を採用している)

通常、LLMからの出力はただのテキストで、実際それをパースして使うのは面倒。
しかし、Genkitの場合

import { z } from "zod"
import { ai } from "@/lib/genkit"

// Zodでスキーマを定義
const UserProfileSchema = z.object({
  name: z.string(),
  age: z.number(),
  interests: z.array(z.string()),
  summary: z.string(),
})

// LLMに構造化データを返してもらう
const result = await ai.generate({
  prompt: "以下のテキストからユーザープロフィールを抽出してください:...",
  output: {
    schema: UserProfileSchema,
    format: "json",
  },
})

// result.outputは完全に型付けされている!
console.log(result.output.name) // string型として扱える
console.log(result.output.age)  // number型として扱える

これにより、フロントエンドでの表示が劇的に簡単。

2. ロギングがシームレス

例えば「LLMとのやり取り」をログに取りたい、というのは絶対出てくる。
FirebaseひいてはGoogle Cloudとインフラが直結していることもあり、Genkitのロギング機能は特別な設定なしで使える

import { logger } from "genkit/logging"
import { enableFirebaseTelemetry } from "@genkit-ai/firebase"

// これだけでセットアップ完了
logger.setLogLevel("debug")
enableFirebaseTelemetry()

// あとは普通にconsole.logするだけ
console.log("[Genkit] Processing request:", { 
  userId: "123",
  action: "generate_profile" 
})

ログレベルを設定するだけで、Google Cloudと自動的に連携して、Cloud Loggingで確認できます。

3. Cloud Run 1つで全部動く - インフラがシンプル

これも大きな魅力。
例えばNext.jsアプリにGenkitを組み込めば、フロントエンドもバックエンドも1つのCloud Runインスタンスで動く。
ログはGoogle Cloud Logに出力される。

AppRouterのAPIルートに簡単にエンドポイントを設定できる。

// app/api/[[...route]]/route.ts
import { Hono } from "hono"
import { ai } from "@/lib/genkit"

const app = new Hono()

app.post("/chat", async (c) => {
  const { message } = await c.req.json()
  
  const response = await ai.generate({
    prompt: message,
    // その他の設定...
  })
  
  return c.json({ reply: response.text })
})

export const { POST } = handle(app)

Google ADKだとバックエンドAPI処理メインだしロギングも自前で実装する必要がある。
(その代わり多機能)

複数のサービスを管理する必要がなく、デプロイも1回で済む。

これは非常に大きい。

ADKを途中でやめたのも、バックエンドインスタンス、フロントエンドインスタンス、ログなどのためのNoSQLなどが必要だと感じたからだ。

実際に使ってみて感じたこと

開発速度が爆速

単純なチャットシステムを作るだけなら、ほぼ一瞬でできる。

自前のアプリケーションで、LLMが人間の操作に応答してくれるのは今更だが感動した。

複数のAIプロバイダーを簡単に切り替え

別途プラグインが必要だが、Google のGeminiとOpenAIなど別のエージェントを簡単に切り替えられ流。

const plugins = []

// 環境変数でプロバイダーを切り替え
if (process.env.GOOGLE_AI_API_KEY) {
  plugins.push(googleAI({ apiKey: process.env.GOOGLE_AI_API_KEY }))
}

if (process.env.OPENAI_API_KEY) {
  plugins.push(openAI({ apiKey: process.env.OPENAI_API_KEY }))
}

export const ai = genkit({ plugins })

ストリーミングも簡単

これはもはやAIフレームワークにおいてはマストになりつつあるがSSE(Server-Sent Events)を使ったリアルタイム更新も簡単に実装できる。

今回の実装では、HonoのストリーミングAPIと組み合わせて使用

// Honoのストリーミングレスポンスと組み合わせて使用
app.post("/chat/stream", async (c) => {
  const { message } = await c.req.json()
  
  return streamSSE(c, async (stream) => {
    const { stream: aiStream, response } = await ai.generateStream({
      prompt: message,
    })
    
    for await (const chunk of aiStream) {
      await stream.writeSSE({
        data: JSON.stringify({ text: chunk.text }),
      })
    }
  })
})

使い分けの指針

Google ADKは多機能なので、Agent to Agentなどをやりたい時はADKの方がベターに感じている。

ただし言語はPythonでありPythonのエコシステムに慣れてる人ならいいが、

フロント構築やロギングも別途必要だし、

例えばORMパッケージで優秀なものを自分は知らないので、

フロントともシームレスに繋げられるフルTypeScirpt実装なのは個人的には、拡張性への安心感と立ち上げの瞬発力を感じる。

まとめ

Firebase Genkitは、AIアプリケーション開発のハードルを大幅に下げてくれるフレームワークです。

特に気に入っているのは:

  • 構造化データによる型安全性 - JSONパースで悩まない
  • シームレスなロギング - デバッグが楽
  • シンプルなインフラから始められる - Cloud Run 1つで完結。大きくなればスケーリングも楽。

「AIを使ったアプリを作りたいけど、複雑な処理は避けたい」という方には、本当におすすめです。

基本的な実装はシンプルでありながら、必要に応じて高度な機能も追加できる拡張性を持っています。

ぜひ一度触ってみてください。きっとあなたも惚れるはずです。

ちなみに作ったもの。

システム見積もりが分かりにくいのでLLMに出してもらうシステム。
https://estimation.en-gine.co/


参考リンク

株式会社en-gine

Discussion