Inclua arquivos grandes em solicitações multimodais e gerencie arquivos usando o Cloud Storage para Firebase

Disponível apenas ao usar o Agent Platform Gemini API (formerly Vertex AI) como seu provedor de API.

Ao chamar o Agent Platform Gemini API (formerly Vertex AI) do seu app usando um SDK do Firebase AI Logic, você pode pedir que um modelo do Gemini gere texto com base em uma entrada multimodal, como imagens, PDFs, vídeos e áudios.

Para as partes não textuais da entrada (como arquivos de mídia), use Cloud Storage for Firebase para incluir arquivos na solicitação. Em linhas gerais, veja o que você precisa saber sobre esse recurso:

  • É possível usar o Cloud Storage for Firebase com qualquer solicitação multimodal (como geração de texto e chat) se você estiver usando o Agent Platform Gemini API (formerly Vertex AI). Os exemplos neste guia mostram uma entrada básica de texto e imagem.

  • Especifique o tipo MIME do arquivo e o URL do Cloud Storage for Firebase (que sempre começa com gs://) na entrada da solicitação. Esses valores são metadados atribuídos automaticamente a qualquer arquivo enviado para um bucket do Cloud Storage.

  • É necessário usar um tipo de arquivo e um URL compatíveis.


Neste guia de soluções, descrevemos como configurar o Cloud Storage for Firebase, fazer upload de um arquivo para um bucket do Cloud Storage for Firebase pelo app e incluir o tipo MIME do arquivo e o URL do Cloud Storage for Firebase na solicitação multimodal para a Gemini API.

Quer ver os exemplos de código? Ou você já configurou o Cloud Storage for Firebase e está tudo pronto para começar a usá-lo com suas solicitações multimodais?

Ir para os exemplos de código

Por que usar a Cloud Storage for Firebase com seu app?

O Cloud Storage for Firebase usa a mesma infraestrutura rápida, segura e escalonável do Google Cloud Storage para armazenar blobs e arquivos, e os SDKs do cliente são criados especificamente para apps da Web e para dispositivos móveis.

Para SDKs do Firebase AI Logic, o tamanho máximo da solicitação é de 20 MB. Você vai receber um erro HTTP 413 se uma solicitação for muito grande. Se o tamanho de um arquivo fizer com que o tamanho total da solicitação exceda 20 MB, use um URL Cloud Storage for Firebase para incluir o arquivo na solicitação multimodal. No entanto, se um arquivo for pequeno, geralmente é possível transmiti-lo diretamente como dados inline. No entanto, um arquivo fornecido como dados inline é codificado em base64 em trânsito, o que aumenta o tamanho da solicitação.

Confira outros benefícios de usar o Cloud Storage for Firebase:

  • Os usuários finais podem fazer upload de imagens diretamente do seu app para um bucket do Cloud Storage for Firebase e, em seguida, incluir essas imagens nos seus comandos multimodais, especificando o tipo MIME do arquivo e o URL do Cloud Storage for Firebase (que é um identificador do arquivo).

  • Você pode economizar tempo e largura de banda dos usuários finais se eles precisarem fornecer imagens, especialmente se tiverem uma qualidade de rede ruim ou instável.

    • Se o upload ou download de um arquivo for interrompido, os SDKs do Cloud Storage for Firebase vão reiniciar automaticamente a operação de onde ela parou.
    • O mesmo arquivo enviado pode ser usado várias vezes sem que o usuário final precise fazer o upload do mesmo arquivo sempre que ele for necessário no app (como em uma nova solicitação multimodal).
  • É possível restringir o acesso do usuário final aos arquivos armazenados no Cloud Storage for Firebase usando o Firebase Security Rules, que permite que apenas um usuário autorizado faça upload, download ou exclusão de arquivos.

  • É possível acessar os arquivos no bucket pelo Firebase ou pelo Google Cloud, o que oferece a flexibilidade de realizar processamento do lado do servidor, como filtragem de imagens ou transcodificação de vídeo usando as APIs do Google Cloud Storage.

Quais tipos de arquivos e URLs são aceitos?

Confira os requisitos para arquivos e URLs quando você quiser usar URLs do Cloud Storage for Firebase com os SDKs do Firebase AI Logic:

  • O arquivo precisa atender aos requisitos de arquivos de entrada para solicitações multimodais. Isso inclui requisitos como tipo MIME e tamanho do arquivo.

  • O arquivo precisa ser armazenado em um bucket do Cloud Storage for Firebase, o que significa que o bucket pode ser acessado por serviços do Firebase, como o Firebase Security Rules. Se você conseguir visualizar seu bucket no console do Firebase, então ele é um bucket do Cloud Storage for Firebase.

  • O bucket do Cloud Storage for Firebase precisa estar no mesmo projeto do Firebase em que você registrou o app.

  • O URL Cloud Storage for Firebase do arquivo precisa começar com gs://, que é a maneira como todos os URLs Google Cloud Storage são construídos.

  • O URL do arquivo não pode ser um URL de "navegador" (por exemplo, o URL de uma imagem encontrada na Internet).

Além disso, a Firebase Security Rules do bucket precisa permitir o acesso adequado ao arquivo. Exemplo:

  • Se você tiver regras públicas, qualquer usuário ou cliente poderá acessar o arquivo.

  • Se você tiver regras robustas (altamente recomendado), o Firebase vai verificar se o usuário ou cliente conectado tem acesso suficiente ao arquivo antes de permitir que a chamada seja realizada com o URL fornecido.

Usar URLs Cloud Storage for Firebase com Firebase AI Logic

Disponível apenas ao usar o Agent Platform Gemini API (formerly Vertex AI) como seu provedor de API.

Etapa 1: configurar o Cloud Storage for Firebase

Confira instruções detalhadas para configurar o Cloud Storage for Firebase no guia para iniciantes: iOS+ | Android | Web | Flutter | Unity

Estas são as tarefas gerais que você precisa realizar:

  1. Crie ou importe um bucket do Cloud Storage for Firebase no seu projeto do Firebase.

  2. Aplique Firebase Security Rules a esse bucket. Security Rules ajudam a proteger seus arquivos restringindo o acesso a usuários finais autorizados.

  3. Adicione a biblioteca de cliente do Cloud Storage for Firebase ao app.

    É possível pular essa tarefa, mas você precisará sempre incluir explicitamente o tipo MIME e os valores de URL nas solicitações.

Etapa 2: fazer upload de um arquivo para um bucket

Na documentação do Cloud Storage, você encontra todas as maneiras de fazer upload de arquivos para um bucket. Por exemplo, é possível fazer upload de arquivos locais do dispositivo do usuário final, como fotos e vídeos da câmera. Saiba mais: iOS+ | Android | Web | Flutter | Unity

Quando você faz upload de um arquivo para um bucket, o Cloud Storage aplica automaticamente as duas informações a seguir ao arquivo. Você precisará incluir esses valores na solicitação (conforme mostrado na próxima etapa deste guia).

  • Tipo MIME: é o tipo de mídia do arquivo (por exemplo, image/png). Tentaremos detectar automaticamente o tipo MIME durante o upload e aplicar esses metadados ao objeto no bucket. No entanto, é possível especificar o tipo MIME durante o upload.

  • URL do Cloud Storage for Firebase: é um identificador exclusivo do arquivo. O URL precisa começar com gs://.

Etapa 3: incluir o tipo MIME e o URL do arquivo em uma solicitação multimodal

Depois de armazenar um arquivo em um bucket, você pode incluir o tipo MIME e o URL dele em uma solicitação. Esses exemplos mostram uma solicitação generateContent sem streaming, mas também é possível usar URLs com streaming e chat.

Para incluir o arquivo na solicitação, use uma das seguintes opções:

Opção 1: incluir o tipo MIME e o URL usando uma referência do Storage

Antes de testar este exemplo, confira se você concluiu o guia para iniciantes dos SDKs do Firebase AI Logic.

Use essa opção se você acabou de fazer upload do arquivo para o bucket e quer incluí-lo imediatamente (usando uma referência do Storage) na solicitação. A chamada requer o tipo MIME e o URL 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

No Kotlin, os métodos desse SDK são funções de suspensão e precisam ser chamados em um escopo de corrotina.
// 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

Para Java, os métodos nesse SDK retornam um 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 = { type: "fileData", 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.");

Opção 2: incluir o tipo MIME e o URL explicitamente

Antes de testar este exemplo, confira se você concluiu o guia para iniciantes dos SDKs do Firebase AI Logic.

Use essa opção se você souber os valores do tipo MIME e do URL do Cloud Storage for Firebase e quiser incluí-los explicitamente na solicitação multimodal. A chamada requer o tipo MIME e o 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

No Kotlin, os métodos desse SDK são funções de suspensão e precisam ser chamados em um escopo de corrotina.
// 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

Para Java, os métodos nesse SDK retornam um 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 = { type: "fileData", 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.");