DIVX テックブログ

catch-img

Google AI StudioのBuild機能(Vibe Code)でプロンプトからNano bananaを使った模様替えアプリのMVP開発を試してみました

はじめに

こんにちは、DIVX R&Dエンジニア兼広報室室長のyasunaです。

最近、Google AI Studioに「Build機能」、いわゆる「Vibe Code」が搭載されたことを知りました。「Prompt to Product(プロンプトからプロダクトへ)」というコンセプトが、まさに私が探求してきた領域と重なるため、早速試してみることにしました。今回は、この新機能を使って簡単なアプリケーションのプロトタイプを作ってみたのでその過程と所感を整理していきます。

この記事を読んで分かること

この記事では、Google AI Studioの「Build機能」がどのようなものか、そして実際にプロンプトからアプリケーションを生成するまでの流れを紹介します。また、生成されたコードの構造や、これが開発現場にどのような影響を与えそうかについての所感も共有します。

背景

今回試したAI Studioの「Build機能」は、自然言語でアイデアを記述するだけで、AIが機能的なアプリケーションのコード一式を生成してくれるものです。Google公式の資料によれば、この機能はGemini 2.5 Proを搭載しており、単なるコードスニペットではなく、デプロイ可能な共有アプリを構築することを目的としています。

AIを活用した迅速なプロトタイピング(MVP開発)は、私たちが業務で常に追求しているテーマでもあります。AIが設計の初期段階、つまりプロジェクトの「骨格」作りをどこまで自動化できるのか、とても興味があったので試してみようと思いました。

試したこと

まずGoogle AI Studioの「Build Mode」にアクセスし、作りたいアプリケーションのアイデアを入力してみました。今回私が試したのは「Nano banana powerd app」というテンプレートです。これを選択したのちに「部屋の模様替えができるアプリケーションを作りたい」というシンプルなプロンプトを入力して「Build」ボタンを押しました。プロンプトを入力すると、Gemini 2.5 Proが処理を開始しました。画面には「image_edit_auto」といったキーワードが表示され、AIが私の指示を「画像編集アプリケーション」として正しく解釈したことが分かります。数十秒後、アプリケーションのファイルが生成されました。

作ったのものを見てみると、単一のHTMLファイルではなく、ReactとTypeScriptに基づいたモダンなフロントエンドプロジェクトの構造をちゃんと持っていました。具体的には、以下のようなファイルが自動で生成されていました。

  • index.html (エントリーポイント)
  • index.tsx (Reactのルート)
  • App.tsx (メインのアプリケーションコンポーネント)
  • types.ts (型定義ファイル)
  • components/Header.tsx (ヘッダーコンポーネント)
  • components/ImageUploader.tsx (画像アップロード用コンポーネント)
  • components/ImageDisplay.tsx (画像表示用コンポーネント)
  • services/geminiService.ts (AI機能呼び出しのサービス)

特に大事だなと感じたのは、services/geminiService.ts です。AI機能の呼び出しロジックが、UIコンポーネントから適切に責務の分離されている部分です。

以下が、AI Studioによって実際に生成された geminiService.ts のコードです。

// GoogleGenAI と Modality を @google/genai からインポートします
import { GoogleGenAI, Modality } from "@google/genai";

// 環境変数から API キーを取得します
const API_KEY = process.env.API_KEY;

// API キーが設定されていない場合はエラーをスローします
if (!API_KEY) {
  throw new Error("API_KEY 環境変数が設定されていません");
}

// GoogleGenAI クライアントを初期化します
const ai = new GoogleGenAI({ apiKey: API_KEY });

/**
 * File オブジェクトを base64 エンコードされた文字列と MIME タイプに変換します。
 * @param file 変換するファイル。
 * @returns MIME タイプと base64 エンコードされたデータを含むオブジェクトで解決される Promise。
 */
function fileToGenerativePart(file: File): Promise<{mimeType: string, data: string}> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onloadend = () => {
      if (typeof reader.result !== 'string') {
        return reject(new Error("ファイルを base64 文字列として読み取れませんでした。"));
      }
      // 結果にはデータ URL プレフィックス (例: "data:image/jpeg;base64,") が含まれています。
      // API に送信する前に、このプレフィックスを削除する必要があります。
      const base64Data = reader.result.split(',')[1];
      resolve({
        mimeType: file.type,
        data: base64Data,
      });
    };
    reader.onerror = (error) => {
      reject(error);
    };
    // ファイルを Data URL として読み込みます
    reader.readAsDataURL(file);
  });
}

/**
 * プロンプトを使用して画像を編集します。
 * @param imageFile 編集する画像ファイル。
 * @param prompt 編集内容を指示するプロンプト。
 * @returns 編集後の画像を指す Data URL (base64) 文字列で解決される Promise。
 */
export async function editImageWithPrompt(
  imageFile: File,
  prompt: string
): Promise<string> {
  try {
    // ファイルを API が要求する形式に変換します
    const imagePart = await fileToGenerativePart(imageFile);

    // AI モデルにコンテンツ生成をリクエストします
    const response = await ai.models.generateContent({
      model: 'gemini-2.5-flash-image', // 特定のモデル(画像編集用)
      contents: {
        parts: [
          {
            // インラインデータとして画像を指定
            inlineData: {
              data: imagePart.data,
              mimeType: imagePart.mimeType,
            },
          },
          {
            // テキストプロンプトを指定
            text: prompt,
          },
        ],
      },
      config: {
        // レスポンスの形式として画像を要求
        responseModalities: [Modality.IMAGE], // 画像の出力を指定
      },
    });

    // レスポンスから画像データを抽出する
    for (const part of response.candidates?.[0]?.content?.parts || []) {
      if (part.inlineData) {
        const base64ImageBytes: string = part.inlineData.data;
        const mimeType = part.inlineData.mimeType;
        // Data URL 形式で返します
        return `data:${mimeType};base64,${base64ImageBytes}`;
      }
    }
    
    // レスポンスに画像データが見つからなかった場合
    throw new Error("API レスポンスに画像データが見つかりませんでした。");

  } catch (error) {
    console.error("Gemini での画像編集中にエラーが発生しました:", error);
    // エラーを処理し、呼び出し元に拒否された Promise を返します
    if (error instanceof Error) {
        return Promise.reject(error.message);
    }
    return Promise.reject("画像生成中に不明なエラーが発生しました。");
  }
}

このように、AI Studioは単にUIを作るだけでなく、AI機能を呼び出すサービス層の具体的な実装まで含めて生成してくれました。

できたものをプレビュー機能内で使ってみるとちゃんと希望通りに動作することが確認できました。

考察

AI Studioの「Build機能」は、AIがプロジェクト全体の構造を理解し、ReactやTypeScriptといったモダンな技術スタックを選定し、さらにコンポーネントとロジックを分離するという「設計」まで踏み込んでいる点に可能性を感じました。

特に、実際に生成された geminiService.ts を見ると

  • @google/genai SDKを正しくインポートして使用している
  • fileToGenerativePart という、ファイルをAPIが要求するBase64形式に変換する(そしてデータURLプレフィックスを適切に除去する)ヘルパー関数を自動で生成している
  • gemini-2.5-flash-image という、タスクに適した具体的なモデルを選定している
  • responseModalities: [Modality.IMAGE] を設定し、レスポンスとして画像データを期待する構成になっている
  • レスポンスから画像データを抽出し、ブラウザで表示可能な data: URL形式に再構築して返却する処理まで実装されている

これらは、ドキュメントを読み込まなければ分からないようなコードですよね。

もちろん、このまますぐに本番環境で使えるわけではなく、API_KEY の安全な管理(.envファイルなど)や、UIコンポーネント側でのエラーハンドリング、CSSの調整などはエンジニアの仕事として残ってはいます。

しかし、アイデアを即座に動く形(プロトタイプ)にし、そこからイテレーション(改善)を始める「最初の一歩」としては、とても強力ですね。AIがここまで具体的な「足場」を組んでくれることで、開発の初速は確実に上がるなと感じました。

まとめ

今回は、Google AI Studioの新しいBuild機能を使い、プロンプトから部屋の模様替えアプリの雛形を生成してみました。

アイデアが即座に、ここまで具体的な実装を伴った構造化プロジェクトになる体験は、とても魅力的に感じました。AIが設計の「足場」を高速かつ構造的に組んでくれることで、私たちエンジニアは、より本質的なロジックの実装や、ユーザー体験の向上に集中できるようになるのではないかと期待しています。

AI Studioの資料には、Cloud RunでのデプロイやRemix(既存アプリの改変)といった機能も言及されていて、今後さらに「Prompt to Product」が強化されていくのを感じられました。

ぜひ参考にしていただけると嬉しいです。

お気軽にご相談ください


ご不明な点はお気軽に
お問い合わせください

サービス資料や
お役立ち資料はこちら

DIVXブログ

テックブログ タグ一覧

人気記事ランキング

関連記事