在多模式请求中包含大型文件,以及使用 Cloud Storage for Firebase 管理文件

仅在将 Vertex AI Gemini API 用作 API 提供方时可用。

当您使用 Firebase AI Logic SDK 从应用中调用 Vertex AI Gemini API 时,可以提示 Gemini 模型根据多模态输入(例如图片、PDF、视频和音频)生成文本。

对于输入中的非文本部分(例如媒体文件),您可以选择使用 Cloud Storage for Firebase 将文件包含在请求中。概括来讲,您需要了解以下有关此功能的信息:

  • 如果您使用的是 Vertex AI Gemini API,则可以将 Cloud Storage for Firebase 与任何多模态请求(例如文本生成和聊天)搭配使用。 本指南中的示例展示了基本的文本和图片输入。

  • 您可以在请求输入中指定文件的 MIME 类型及其 Cloud Storage for Firebase 网址(始终以 gs:// 开头)。这些值是自动分配给上传到 Cloud Storage 存储分区的任何文件的元数据。

  • 您需要使用受支持的文件类型和网址


本解决方案指南介绍了如何设置 Cloud Storage for Firebase、从应用向 Cloud Storage for Firebase 存储分区上传文件,然后在向 Gemini API 发送的多模态请求中包含文件的 MIME 类型和 Cloud Storage for Firebase 网址。

您想查看代码示例吗?或者,您是否已设置 Cloud Storage for Firebase,并准备好开始将其用于多模态请求?

跳转到代码示例

为什么要将 Cloud Storage for Firebase 与应用搭配使用?

Cloud Storage for Firebase 使用与 Google Cloud Storage 相同的快速、安全且可扩缩的基础架构来存储 Blob 和文件,并且其客户端 SDK 专门为移动应用和 Web 应用而构建。

对于 Firebase AI Logic SDK,请求大小上限为 20 MB。 如果请求过大,您会收到 HTTP 413 错误。如果某个文件的大小会导致请求总大小超过 20 MB,请使用 Cloud Storage for Firebase 网址将该文件纳入多模态请求中。 不过,如果文件较小,您通常可以直接将其作为内嵌数据传递(但请注意,以内嵌数据形式提供的文件在传输过程中会编码为 base64,这会增加请求的大小)。

使用 Cloud Storage for Firebase 的其他一些好处

  • 您可以让最终用户直接从您的应用中将图片上传到 Cloud Storage for Firebase 存储分区,然后只需指定文件的 MIME 类型和 Cloud Storage for Firebase 网址(即文件的标识符),即可在多模态提示中包含这些图片。

  • 如果最终用户需要提供图片,那么您可以使用此 API 来节省他们的时间和带宽,尤其是在他们网络质量不佳或不稳定时。

    • 如果文件上传或下载中断,Cloud Storage for Firebase SDK 会自动从中断处重新开始操作。
    • 同一上传文件可以多次使用,而无需最终用户每次在应用中需要该文件时(例如在新的多模态请求中)都上传同一文件。
  • 您可以使用 Firebase Security Rules 限制最终用户对 Cloud Storage for Firebase 中存储的文件的访问权限,这样只有经过授权的用户才能上传、下载或删除文件。

  • 您可以从 Firebase 或 Google Cloud 访问存储分区中的文件,从而灵活地使用 Google Cloud Storage API 执行服务器端处理,例如图片过滤或视频转码。

支持哪些类型的文件和网址?

如果您想将 Cloud Storage for Firebase 网址与 Firebase AI Logic SDK 搭配使用,则文件和网址必须满足以下要求:

  • 文件必须满足多模态请求的输入文件要求。这包括 MIME 类型和文件大小等要求。

  • 文件必须存储在 Cloud Storage for Firebase 存储分区中(这意味着 Firebase 服务(例如 Firebase Security Rules)可以访问该存储分区)。如果您可以在 Firebase 控制台中查看存储分区,则该存储分区为 Cloud Storage for Firebase 存储分区。

  • Cloud Storage for Firebase 存储分区必须位于您注册应用的 Firebase 项目中。

  • 文件的 Cloud Storage for Firebase 网址必须以 gs:// 开头,这是所有 Google Cloud Storage 网址的构建方式。

  • 文件网址不能是“浏览器”网址(例如,您在互联网上找到的图片的网址)。

此外,存储分区的 Firebase Security Rules 必须允许对文件进行适当的访问。例如:

  • 如果您有公开规则,则任何用户或客户端都可以访问该文件。

  • 如果您有完善的规则 (强烈建议),那么 Firebase 会先检查已登录的用户或客户端是否具有足够的访问权限来访问相应文件,然后再允许通过所提供的网址进行调用。

Cloud Storage for Firebase 网址与 Firebase AI Logic 搭配使用

仅在将 Vertex AI Gemini API 用作 API 提供方时可用。

第 1 步:设置 Cloud Storage for Firebase

您可以在 Cloud Storage for Firebase 的入门指南中找到有关如何设置 Cloud Storage for Firebase 的详细说明: iOS+ | Android | Web | Flutter | Unity

以下是您需要完成的高级任务:

  1. 在 Firebase 项目中创建或导入 Cloud Storage for Firebase 存储分区。

  2. Firebase Security Rules 应用于此存储分区。Rules有助于您通过限制对授权最终用户的访问来保护文件。

  3. Cloud Storage for Firebase 的客户端库添加到您的应用中。

    请注意,您可以跳过此任务,但之后必须始终 在请求中明确添加 MIME 类型和网址值

第 2 步:将文件上传到存储分区

Cloud Storage 文档中,您可以了解将文件上传到存储分区的所有不同方法。例如,您可以上传最终用户设备上的本地文件,如相机中的照片和视频。 了解详情: iOS+ | Android | Web | Flutter | Unity

当您将文件上传到存储分区时,Cloud Storage 会自动将以下两项信息应用于该文件。您需要在请求中添加这些值(如本指南的下一步所示)。

  • MIME 类型:这是文件的媒体类型(例如 image/png)。我们会在上传期间自动尝试检测 MIME 类型,并将该元数据应用于相应存储分区中的对象。不过,您也可以在上传期间指定 MIME 类型。

  • Cloud Storage for Firebase 网址:这是文件的唯一标识符。 网址必须以 gs:// 开头。

第 3 步:在多模态请求中包含文件的 MIME 类型和网址

将文件存储在存储分区中后,您可以在请求中添加该文件的 MIME 类型和网址。请注意,这些示例展示的是非流式 generateContent 请求,但您也可以使用包含流式传输和聊天功能的网址。

如需在请求中添加文件,您可以使用以下任一方式:

方法 1:使用 Storage 引用包含 MIME 类型和网址

在尝试此示例之前,请确保您已完成 Firebase AI Logic SDK 入门指南中的步骤。

如果您刚刚将文件上传到存储分区,并且想立即在请求中包含该文件(通过存储引用),请使用此选项。该调用需要 MIME 类型和 Cloud Storage for Firebase 网址。

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 中的方法是挂起函数,需要从协程范围调用。
// 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 = generativeModel.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 类型和网址

在尝试此示例之前,请确保您已完成 Firebase AI Logic SDK 入门指南中的步骤。

如果您知道 MIME 类型和 Cloud Storage for Firebase 网址的值,并且想要将它们明确包含在多模态请求中,请使用此选项。此调用需要 MIME 类型和网址。

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 中的方法是挂起函数,需要从协程范围调用。
// 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 = generativeModel.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.");