マルチモーダル リクエストにサイズの大きいファイルを含め、Cloud Storage for Firebase を使用してファイルを管理する

API プロバイダとして Vertex AI Gemini API を使用している場合にのみ使用できます。

Vertex AI Gemini API を使用してアプリから Firebase AI Logic SDK を呼び出すと、Gemini モデルに、画像、PDF、動画、音声などのマルチモーダル入力に基づいてテキストを生成させることができます。

入力のテキスト以外の部分(メディア ファイルなど)については、必要に応じて Cloud Storage for Firebaseを使用して、リクエストにファイルを含めることができます。大まかに言うと、この機能について知っておくべきことは次のとおりです。

  • Cloud Storage for Firebase は、Vertex AI Gemini API を使用している場合、マルチモーダル リクエスト( テキスト生成とチャットの両方など)で使用できます。 このガイドのでは、基本的な テキストと画像の入力を示しています。

  • リクエスト入力で、ファイルの MIME タイプと Cloud Storage for Firebase URL (常に gs:// で始まる)を指定します。これらの値は 、Cloud Storage バケットにアップロードされたファイルに自動的に割り当てられるメタデータです。

  • サポートされている ファイルタイプと URL を使用する必要があります。


このソリューション ガイドでは、Cloud Storage for Firebase を設定し、アプリから Cloud Storage for Firebase バケットにファイルをアップロードしてから、Gemini API へのマルチモーダル リクエストにファイルの MIME タイプと Cloud Storage for Firebase URL を含める方法について説明します。

コード例を確認したいですか?または、 Cloud Storage for Firebaseをすでに設定済みで、 マルチモーダル リクエストで使用する準備ができていますか?

コード例に移動

アプリで Cloud Storage for Firebase を使用する理由

Cloud Storage for Firebase は、Google Cloud Storage と同じ高速で安全かつ スケーラブルなインフラストラクチャを使用して BLOB とファイルを保存します。 また、クライアント SDK はモバイルアプリとウェブアプリ専用に構築されています。

Firebase AI Logic SDK の場合、最大リクエスト サイズは 20 MB です。 リクエストが大きすぎると、HTTP 413 エラーが発生します。ファイルのサイズが原因でリクエストの合計サイズが 20 MB を超える場合は、 Cloud Storage for Firebase URL を使用して、マルチモーダル リクエストにファイルを含めます。 ただし、ファイルが小さい場合は、インライン データとして直接渡すことができます(インライン データとして提供されるファイルは転送中に base64 にエンコードされるため、リクエストのサイズが大きくなります)。

Cloud Storage for Firebase を使用するその他のメリットは次のとおりです。

サポートされているファイルと URL のタイプ

Cloud Storage for Firebase URL を Firebase AI Logic SDK で使用する場合のファイルと URL の要件は次のとおりです。

  • ファイルは、マルチモーダル リクエストの入力ファイルの要件を満たしている必要があります。これには、MIME タイプやファイルサイズなどの要件が含まれます。

  • ファイルは Cloud Storage for Firebase バケット に保存する必要があります(つまり、バケットは Firebase Security Rules などの Firebase サービスからアクセスできる必要があります)。 Firebase コンソールでバケットを表示できる場合は、Cloud Storage for Firebase バケットです。

  • Cloud Storage for Firebase バケットは、アプリを登録した Firebase プロジェクトと同じ Firebase プロジェクトに存在する必要があります。

  • ファイルの Cloud Storage for Firebase URL は gs:// で始まる必要があります。これは、すべての Google Cloud Storage URL の構成方法です。

  • ファイルの URL は「ブラウザ」URL(インターネットで見つけた画像の URL など)にすることはできません。

また、バケットの Firebase Security Rules で、ファイルへの 適切なアクセスが許可されている必要があります。例:

Cloud Storage for Firebase URL を Firebase AI Logic で使用する

API プロバイダとして Vertex AI Gemini API を使用している場合にのみ使用できます。

ステップ 1: Cloud Storage for Firebaseを設定する

Cloud Storage for Firebase の設定手順については、 スタートガイド( iOS+ | Android | ウェブ | Flutter | Unity)をご覧ください。

行う必要のある大まかなタスクは次のとおりです。

  1. Firebase プロジェクトで Cloud Storage for Firebase バケットを作成またはインポートします。

  2. このバケットに Firebase Security Rules を適用します。Security Rules 承認されたエンドユーザーへのアクセスを制限することでファイルを保護できます。

  3. Cloud Storage for Firebase のクライアント ライブラリをアプリに追加します。

    このタスクはスキップできますが、リクエストに 常に MIME タイプと URL の値を明示的に含める必要があります

ステップ 2: バケットにファイルをアップロードする

Cloud Storage のドキュメントでは、バケットにファイルをアップロードするさまざまな 方法について説明しています。たとえば、エンドユーザーのデバイスからローカル ファイル(カメラの写真や動画など)をアップロードできます。 詳細: iOS+ | Android | ウェブ | Flutter | Unity

バケットにファイルをアップロードすると、Cloud Storage はファイルに次の 2 つの情報を自動的に適用します。これらの値は、リクエストに含める必要があります(このガイドの次のステップで説明します)。

  • MIME タイプ: これはファイルのメディアタイプです(例: image/png)。 アップロード時に MIME タイプを自動的に検出し、その メタデータをバケット内のオブジェクトに適用します。ただし、アップロード時に MIME タイプを指定することもできます。

  • Cloud Storage for Firebase URL: これはファイルの固有の識別子です。 URL は gs:// で始まる必要があります。

ステップ 3: マルチモーダル リクエストにファイルの MIME タイプと URL を含める

バケットにファイルが保存されたら、リクエストにその MIME タイプと URL を含めることができます。これらの例では、ストリーミング以外の generateContent リクエストを示していますが、ストリーミングとチャットで URL を使用することもできます。

ファイルと URL の タイプを確認してください。

リクエストにファイルを含めるには、次のいずれかのオプションを使用します。

オプション 1: Storage 参照を使用して MIME タイプと URL を含める

この例を試す前に、 Firebase AI Logic SDK のスタートガイドの手順を完了していることを確認してください。

このオプションは、ファイルをバケットにアップロードしたばかりで、リクエストにファイル(Storage 参照経由)をすぐに含める場合に便利です。この呼び出しには、MIME タイプと Cloud Storage for Firebase URL の両方が必要です。

Swift

// Upload an image file using Cloud Storage for Firebase.
let storageRef = Storage.storage().reference(withPath: "images/image.jpg")
guard let imageURL = Bundle.main.url(forResource: "image", withExtension: "jpg") else {
  fatalError("File 'image.jpg' not found in main bundle.")
}
let metadata = try await storageRef.putFileAsync(from: imageURL)

// Get the MIME type and Cloud Storage for Firebase URL.
guard let mimeType = metadata.contentType else {
  fatalError("The MIME type of the uploaded image is nil.")
}
// Construct a URL in the required format.
let storageURL = "gs://\(storageRef.bucket)/\(storageRef.fullPath)"

let prompt = "What's in this picture?"
// Construct the imagePart with the MIME type and the URL.
let imagePart = FileDataPart(uri: storageURL, mimeType: mimeType)

// To generate text output, call generateContent with the prompt and the imagePart.
let result = try await model.generateContent(prompt, imagePart)
if let text = result.text {
  print(text)
}

Kotlin

Kotlin の場合、この SDK のメソッドは suspend 関数であり、 Coroutine スコープから呼び出す必要があります。
// Upload an image file using Cloud Storage for Firebase.
val storageRef = Firebase.storage.reference.child("images/image.jpg")
val fileUri = Uri.fromFile(File("image.jpg"))
try {
    val taskSnapshot = storageRef.putFile(fileUri).await()
    // Get the MIME type and Cloud Storage for Firebase file path.
    val mimeType = taskSnapshot.metadata?.contentType
    val bucket = taskSnapshot.metadata?.bucket
    val filePath = taskSnapshot.metadata?.path

    if (mimeType != null && bucket != null) {
        // Construct a URL in the required format.
        val storageUrl = "gs://$bucket/$filePath"
        // Construct a prompt that includes text, the MIME type, and the URL.
        val prompt = content {
            fileData(mimeType = mimeType, uri = storageUrl)
            text("What's in this picture?")
        }
        // To generate text output, call generateContent with the prompt.
        val response = model.generateContent(prompt)
        println(response.text)
    }
} catch (e: StorageException) {
    // An error occurred while uploading the file.
} catch (e: GoogleGenerativeAIException) {
    // An error occurred while generating text.
}

Java

Java の場合、この SDK のメソッドは ListenableFutureを返します。
// Upload an image file using Cloud Storage for Firebase.
StorageReference storage = FirebaseStorage.getInstance().getReference("images/image.jpg");
Uri fileUri = Uri.fromFile(new File("images/image.jpg"));

storage.putFile(fileUri).addOnSuccessListener(taskSnapshot -> {
    // Get the MIME type and Cloud Storage for Firebase file path.
    String mimeType = taskSnapshot.getMetadata().getContentType();
    String bucket = taskSnapshot.getMetadata().getBucket();
    String filePath = taskSnapshot.getMetadata().getPath();

    if (mimeType != null && bucket != null) {
        // Construct a URL in the required format.
        String storageUrl = "gs://" + bucket + "/" + filePath;
        // Create a prompt that includes text, the MIME type, and the URL.
        Content prompt = new Content.Builder()
                .addFileData(storageUrl, mimeType)
                .addText("What's in this picture?")
                .build();

        // To generate text output, call generateContent with the prompt.
        GenerativeModelFutures modelFutures = GenerativeModelFutures.from(model);
        ListenableFuture<GenerateContentResponse> response = modelFutures.generateContent(prompt);
        Futures.addCallback(response, new FutureCallback<>() {
            @Override
            public void onSuccess(GenerateContentResponse result) {
                String resultText = result.getText();
                System.out.println(resultText);
            }

            @Override
            public void onFailure(@NonNull Throwable t) {
                t.printStackTrace();
            }
        }, executor);
    }
}).addOnFailureListener(e -> {
    // An error occurred while uploading the file.
    e.printStackTrace();
});

Web

// Upload an image file using Cloud Storage for Firebase.
const storageRef = ref(storage, "image.jpg");
const uploadResult = await uploadBytes(storageRef, file);

// Get the MIME type and Cloud Storage for Firebase URL.
// toString() is the simplest way to construct the Cloud Storage for Firebase URL
// in the required format.
const mimeType = uploadResult.metadata.contentType;
const storageUrl = uploadResult.ref.toString();

// Construct the imagePart with the MIME type and the URL.
const imagePart = { fileData: { mimeType, fileUri: storageUrl }};

// To generate text output, call generateContent with the prompt and imagePart.
const result = await model.generateContent([prompt, imagePart]);
console.log(result.response.text());

Dart

// Upload an image file using Cloud Storage for Firebase.
final storageRef = FirebaseStorage.instance.ref();
final imageRef = storageRef.child("images/image.jpg");
await imageRef.putData(data);

// Get the MIME type and Cloud Storage for Firebase file path.
final metadata = await imageRef.getMetadata();
final mimeType = metadata.contentType;
final bucket = imageRef.bucket;
final fullPath = imageRef.fullPath;

final prompt = TextPart("What's in the picture?");
// Construct a URL in the required format.
final storageUrl = 'gs://$bucket/$fullPath';
// Construct the filePart with the MIME type and the URL.
final filePart = FileData(mimeType, storageUrl);
// To generate text output, call generateContent with the text and the filePart.
final response = await model.generateContent([
  Content.multi([prompt, filePart])
]);
print(response.text);

Unity

var storageRef = FirebaseStorage.DefaultInstance.GetReference("images/image.jpg");
var metadata = await storageRef.PutFileAsync(filePathToJpg);

// Get the MIME type and Cloud Storage for Firebase URL.
var mimeType = metadata.ContentType;
// Construct a URL in the required format.
var storageURL = new Uri($"gs://{storageRef.Bucket}/{storageRef.Path}");

var prompt = ModelContent.Text("What's in this picture?");
// Construct a FileData that explicitly includes the MIME type and
// Cloud Storage for Firebase URL values.
var fileData = ModelContent.FileData(mimeType, storageURL);

// To generate text output, call GenerateContentAsync with the prompt and fileData.
var response = await model.GenerateContentAsync(new [] { prompt, fileData });
UnityEngine.Debug.Log(response.Text ?? "No text in response.");

オプション 2: MIME タイプと URL を明示的に含める

この例を試す前に、 Firebase AI Logic SDK のスタートガイドの手順を完了していることを確認してください。

このオプションは、MIME タイプと Cloud Storage for Firebase URL の値がわかっていて、 マルチモーダル リクエストに明示的に含める場合に便利です。この呼び出しには、MIME タイプと URL の両方が必要です。

Swift

let prompt = "What's in this picture?"
// Construct an imagePart that explicitly includes the MIME type and
// Cloud Storage for Firebase URL values.
let imagePart = FileDataPart(uri: "gs://bucket-name/path/image.jpg", mimeType: "image/jpeg")

// To generate text output, call generateContent with the prompt and imagePart.
let result = try await model.generateContent(prompt, imagePart)
if let text = result.text {
  print(text)
}

Kotlin

Kotlin の場合、この SDK のメソッドは suspend 関数であり、 Coroutine スコープから呼び出す必要があります。
// Construct a prompt that explicitly includes the MIME type and Cloud Storage for Firebase URL values.
val prompt = content {
    fileData(mimeType = "image/jpeg", uri = "gs://bucket-name/path/image.jpg")
    text("What's in this picture?")
}
// To generate text output, call generateContent with the prompt.
val response = model.generateContent(prompt)
println(response.text)

Java

Java の場合、この SDK のメソッドは ListenableFutureを返します。
// Construct a prompt that explicitly includes the MIME type and Cloud Storage for Firebase URL values.
Content prompt = new Content.Builder()
        .addFilePart("gs://bucket-name/path/image.jpg", "image/jpeg")
        .addText("What's in this picture?")
        .build();

// To generate text output, call generateContent with the prompt
GenerativeModelFutures modelFutures = GenerativeModelFutures.from(model);
ListenableFuture<GenerateContentResponse> response = modelFutures.generateContent(prompt);
Futures.addCallback(response, new FutureCallback<>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(@NonNull Throwable t) {
        t.printStackTrace();
    }
}, executor);

Web

const prompt = "What's in this picture?";
// Construct an imagePart that explicitly includes the MIME type and Cloud Storage for Firebase URL values.
const imagePart = { fileData: { mimeType: "image/jpeg", fileUri: "gs://bucket-name/path/image.jpg" }};

// To generate text output, call generateContent with the prompt and imagePart.
const result = await model.generateContent([prompt, imagePart]);
console.log(result.response.text());

Dart

final prompt = TextPart("What's in the picture?");
// Construct a filePart that explicitly includes the MIME type and Cloud Storage for Firebase URL values.
final filePart = FileData('image/jpeg', 'gs://bucket-name/path/image.jpg'),
// To generate text output, call generateContent with the prompt and filePart.
final response = await model.generateContent([
  Content.multi([prompt, filePart])
]);
print(response.text);

Unity

var prompt = ModelContent.Text("What's in this picture?");
// Construct a FileData that explicitly includes the MIME type and
// Cloud Storage for Firebase URL values.
var fileData = ModelContent.FileData(
  mimeType: "image/jpeg",
  uri: new Uri("gs://bucket-name/path/image.jpg")
);

// To generate text output, call GenerateContentAsync with the prompt and fileData.
var response = await model.GenerateContentAsync(new [] { prompt, fileData });
UnityEngine.Debug.Log(response.Text ?? "No text in response.");