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

Disponível apenas quando você usa o Vertex AI Gemini API como seu provedor de API.

Ao chamar o Vertex AI Gemini API do seu app usando um SDK Firebase AI Logic, você pode pedir a um modelo do Gemini para gerar texto com base em uma entrada multimodal, como imagens, PDFs, vídeos e áudio.

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

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

  • Você especifica o tipo MIME do arquivo e o URL 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 Cloud Storage.

  • Use um tipo de arquivo e URL compatíveis.


Este guia de solução descreve como configurar o Cloud Storage for Firebase, fazer upload de um arquivo para um bucket do Cloud Storage for Firebase no seu app e incluir o tipo MIME e o URL do Cloud Storage for Firebase do arquivo na sua solicitação multimodal para o Gemini API.

Quer ver os exemplos de código? Ou você já configurou o Cloud Storage for Firebase e está pronto para usar com seus comandos 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 de cliente são criados especificamente para apps móveis e da Web.

Para SDKs Firebase AI Logic, o tamanho máximo da solicitação é de 20 MB. Você recebe 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 sua solicitação multimodal. No entanto, se um arquivo for pequeno, você poderá transmiti-lo diretamente como dados inline. Observe que 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. Depois, é possível incluir essas imagens nos comandos multimodais apenas especificando o tipo MIME 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, principalmente se a qualidade da rede for ruim ou instável.

    • Se um upload ou download de arquivo for interrompido, os SDKs 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 upload dele sempre que for necessário no app (como em uma nova solicitação multimodal).
  • É possível restringir o acesso do usuário final aos arquivos armazenados em Cloud Storage for Firebase usando Firebase Security Rules, que permite que apenas um usuário autorizado faça upload, download ou exclusão de arquivos.

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

Quais tipos de arquivos e URLs são aceitos?

Confira os requisitos para arquivos e URLs ao usar URLs Cloud Storage for Firebase com os SDKs 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 (ou seja, o bucket precisa estar acessível aos serviços do Firebase, como o Firebase Security Rules). Se você conseguir ver o bucket no console do Firebase, ele será um bucket do Cloud Storage for Firebase.

  • O bucket 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 que você encontra 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 feita com o URL fornecido.

Usar URLs Cloud Storage for Firebase com Firebase AI Logic

Disponível apenas quando você usa o Vertex AI Gemini API como seu provedor de API.

Etapa 1: configurar 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 Cloud Storage for Firebase no seu projeto do Firebase.

  2. Aplique Firebase Security Rules a este bucket. O Rules ajuda a proteger seus arquivos restringindo o acesso a usuários finais autorizados.

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

    Você pode pular essa tarefa, mas sempre inclua explicitamente os valores de tipo MIME e URL nas suas solicitações.

Etapa 2: fazer upload de um arquivo para um bucket

Na documentação do Cloud Storage, você pode aprender todas as maneiras diferentes 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). Vamos tentar detectar automaticamente o tipo MIME durante o upload e aplicar esses metadados ao objeto no bucket. No entanto, você pode 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. Estes 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 de armazenamento

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 incluir imediatamente o arquivo (por uma referência de armazenamento) na solicitação. A chamada exige 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

Para Kotlin, os métodos neste SDK são funções de suspensão e precisam ser chamados de 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 = 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

Para Java, os métodos neste 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 = { 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 Cloud Storage for Firebase e quiser incluí-los explicitamente na solicitação multimodal. A chamada exige 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

Para Kotlin, os métodos neste SDK são funções de suspensão e precisam ser chamados de 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 = generativeModel.generateContent(prompt)
println(response.text)

Java

Para Java, os métodos neste 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 = { 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.");