Đưa các tệp lớn vào các yêu cầu đa phương thức và quản lý các tệp bằng Cloud Storage cho Firebase

Chỉ dùng được khi bạn sử dụng Vertex AI Gemini API làm nhà cung cấp API.

Khi gọi Vertex AI Gemini API từ ứng dụng bằng Firebase AI Logic SDK, bạn có thể nhắc một mô hình Gemini tạo văn bản dựa trên một dữ liệu đầu vào đa phương thức, chẳng hạn như hình ảnh, tệp PDF, video và âm thanh.

Đối với các phần không phải là văn bản của dữ liệu đầu vào (chẳng hạn như tệp đa phương tiện), bạn có thể tuỳ ý sử dụng Cloud Storage for Firebase để đưa các tệp vào yêu cầu. Ở cấp độ cao, đây là những điều bạn cần biết về tính năng này:

  • Bạn có thể sử dụng Cloud Storage for Firebase với mọi yêu cầu đa phương thức (chẳng hạn như cả tính năng tạo văn bản và trò chuyện) nếu đang sử dụng Vertex AI Gemini API. Các ví dụ trong hướng dẫn này cho thấy một dữ liệu đầu vào cơ bản gồm văn bản và hình ảnh.

  • Bạn chỉ định loại MIME của tệp và URL Cloud Storage for Firebase của tệp (luôn bắt đầu bằng gs://) trong dữ liệu đầu vào của yêu cầu. Đây là các giá trị siêu dữ liệu được tự động gán cho mọi tệp được tải lên một Cloud Storage vùng chứa.

  • Bạn cần sử dụng một loại tệp và URL được hỗ trợ.


Hướng dẫn giải pháp này mô tả cách thiết lập Cloud Storage for Firebase, tải tệp lên một vùng chứa Cloud Storage for Firebase từ ứng dụng của bạn, sau đó đưa loại MIME của tệp và URL Cloud Storage for Firebase vào yêu cầu đa phương thức của bạn gửi đến Gemini API.

Bạn có muốn xem các ví dụ về mã? Hoặc bạn đã thiết lập Cloud Storage for Firebase và sẵn sàng bắt đầu sử dụng với các yêu cầu đa phương thức?

Chuyển đến các ví dụ về mã

Tại sao nên sử dụng Cloud Storage for Firebase với ứng dụng của bạn?

Cloud Storage for Firebase sử dụng cùng một cơ sở hạ tầng nhanh chóng, an toàn và có khả năng mở rộng như Google Cloud Storage để lưu trữ các blob và tệp, và SDK ứng dụng của dịch vụ này được xây dựng riêng cho các ứng dụng dành cho thiết bị di động và ứng dụng web.

Đối với Firebase AI Logic SDK, kích thước tối đa của yêu cầu là 20 MB. Bạn sẽ gặp lỗi HTTP 413 nếu yêu cầu quá lớn. Nếu kích thước của một tệp sẽ khiến tổng kích thước yêu cầu vượt quá 20 MB, thì hãy sử dụng URL Cloud Storage for Firebase để đưa tệp đó vào yêu cầu đa phương thức. Tuy nhiên, nếu tệp nhỏ, bạn thường có thể truyền trực tiếp tệp đó dưới dạng dữ liệu nội tuyến (xin lưu ý rằng tệp được cung cấp dưới dạng dữ liệu nội tuyến sẽ được mã hoá thành base64 trong quá trình truyền, điều này làm tăng kích thước của yêu cầu).

Dưới đây là một số lợi ích khác khi sử dụng Cloud Storage for Firebase:

  • Bạn có thể cho phép người dùng cuối tải hình ảnh trực tiếp từ ứng dụng của bạn lên một Cloud Storage for Firebase vùng chứa, sau đó đưa những hình ảnh đó vào lời nhắc đa phương thức chỉ bằng cách chỉ định loại MIME của tệp và Cloud Storage for Firebase URL (đây là giá trị nhận dạng cho tệp).

  • Bạn có thể tiết kiệm thời gian và băng thông cho người dùng cuối nếu họ cần cung cấp hình ảnh, đặc biệt là nếu họ có chất lượng mạng kém hoặc không ổn định.

    • Nếu quá trình tải tệp lên hoặc tải tệp xuống bị gián đoạn, thì Cloud Storage for Firebase SDK sẽ tự động khởi động lại thao tác ngay tại nơi bị gián đoạn.
    • Người dùng cuối có thể sử dụng cùng một tệp đã tải lên nhiều lần mà không cần phải tải lên cùng một tệp mỗi khi cần trong ứng dụng của bạn (chẳng hạn như trong một yêu cầu đa phương thức mới).
  • Bạn có thể hạn chế quyền truy cập của người dùng cuối vào các tệp được lưu trữ trong Cloud Storage for Firebase bằng cách sử dụng Firebase Security Rules, quy tắc này chỉ cho phép người dùng được uỷ quyền tải tệp lên, tải tệp xuống hoặc xoá tệp.

  • Bạn có thể truy cập vào các tệp trong vùng chứa của mình từ Firebase hoặc từ Google Cloud, giúp bạn linh hoạt xử lý phía máy chủ, chẳng hạn như lọc hình ảnh hoặc chuyển mã video bằng API Google Cloud Storage.

Những loại tệp và URL nào được hỗ trợ?

Dưới đây là các yêu cầu đối với tệp và URL khi bạn muốn sử dụng Cloud Storage for Firebase URL với Firebase AI Logic SDK:

  • Tệp phải đáp ứng các yêu cầu về tệp đầu vào cho yêu cầu đa phương thức. Điều này bao gồm các yêu cầu như loại MIME và kích thước tệp.

  • Tệp phải được lưu trữ trong một Cloud Storage for Firebase vùng chứa (nghĩa là các dịch vụ của Firebase có thể truy cập vào vùng chứa đó, chẳng hạn như Firebase Security Rules). Nếu bạn có thể xem vùng chứa của mình trong Firebase bảng điều khiển, thì đó là vùng chứa Cloud Storage for Firebase.

  • Vùng chứa Cloud Storage for Firebase phải nằm trong cùng một dự án Firebase mà bạn đã đăng ký ứng dụng.

  • URL Cloud Storage for Firebase của tệp phải bắt đầu bằng gs://. Đây là cách tạo tất cả URL Google Cloud Storage.

  • URL của tệp không thể là URL "trình duyệt" (ví dụ: URL của một hình ảnh mà bạn tìm thấy trên Internet).

Ngoài ra, Firebase Security Rules cho vùng chứa của bạn phải cho phép truy cập thích hợp vào tệp. Ví dụ:

  • Nếu bạn có quy tắc công khai, thì bất kỳ người dùng hoặc ứng dụng nào cũng có thể truy cập vào tệp.

  • Nếu bạn có các quy tắc mạnh mẽ (rất nên dùng), thì Firebase sẽ kiểm tra để đảm bảo rằng người dùng hoặc ứng dụng đã đăng nhập có đủ quyền truy cập vào tệp trước khi cho phép cuộc gọi tiếp tục bằng URL được cung cấp.

Sử dụng URL Cloud Storage for Firebase với Firebase AI Logic

Chỉ dùng được khi bạn sử dụng Vertex AI Gemini API làm nhà cung cấp API.

Bước 1: Thiết lập Cloud Storage for Firebase

Bạn có thể tìm thấy hướng dẫn chi tiết về cách thiết lập Cloud Storage for Firebase trong hướng dẫn bắt đầu sử dụng: iOS+ | Android | Web | Flutter | Unity

Dưới đây là các tác vụ cấp cao mà bạn cần thực hiện:

  1. Tạo hoặc nhập một vùng chứa Cloud Storage for Firebase trong dự án Firebase.

  2. Áp dụng Firebase Security Rules cho vùng chứa này. Security Rules giúp bạn bảo mật các tệp bằng cách hạn chế quyền truy cập đối với người dùng cuối được uỷ quyền.

  3. Thêm thư viện ứng dụng cho Cloud Storage for Firebase vào ứng dụng của bạn.

    Xin lưu ý rằng bạn có thể bỏ qua tác vụ này, nhưng sau đó, bạn phải luôn đưa các giá trị Loại MIME và URL vào yêu cầu một cách rõ ràng.

Bước 2: Tải một tệp lên một vùng chứa

Trong tài liệu về Cloud Storage, bạn có thể tìm hiểu tất cả các cách tải tệp lên một vùng chứa. Ví dụ: bạn có thể tải các tệp cục bộ lên từ thiết bị của người dùng cuối, chẳng hạn như ảnh và video từ máy ảnh. Tìm hiểu thêm: iOS+ | Android | Web | Flutter | Unity

Khi bạn tải một tệp lên một vùng chứa, Cloud Storage sẽ tự động áp dụng 2 phần thông tin sau đây cho tệp đó. Bạn cần đưa các giá trị này vào yêu cầu (như minh hoạ trong bước tiếp theo của hướng dẫn này).

  • Loại MIME: Đây là loại nội dung đa phương tiện của tệp (ví dụ: image/png). Chúng tôi sẽ tự động cố gắng phát hiện loại MIME trong quá trình tải lên và áp dụng siêu dữ liệu đó cho đối tượng trong vùng chứa. Tuy nhiên, bạn có thể tuỳ ý chỉ định loại MIME trong quá trình tải lên.

  • Cloud Storage for Firebase URL: Đây là giá trị nhận dạng duy nhất cho tệp. URL phải bắt đầu bằng gs://.

Bước 3: Đưa loại MIME và URL của tệp vào yêu cầu đa phương thức

Sau khi lưu trữ một tệp trong một vùng chứa, bạn có thể đưa loại MIME và URL của tệp đó vào một yêu cầu. Xin lưu ý rằng các ví dụ này cho thấy một yêu cầu generateContent không phát trực tuyến, nhưng bạn cũng có thể sử dụng URL với tính năng phát trực tuyến và trò chuyện.

Để đưa tệp vào yêu cầu, bạn có thể sử dụng một trong các lựa chọn sau:

Lựa chọn 1: Đưa loại MIME và URL vào bằng cách sử dụng tham chiếu Bộ nhớ

Trước khi thử ví dụ này, hãy đảm bảo bạn đã hoàn tất hướng dẫn bắt đầu sử dụng cho Firebase AI Logic SDK.

Hãy sử dụng lựa chọn này nếu bạn vừa tải tệp lên vùng chứa và muốn đưa tệp đó vào yêu cầu ngay lập tức (thông qua tham chiếu Bộ nhớ). Lệnh gọi này yêu cầu cả loại MIME và 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

Đối với Kotlin, các phương thức trong SDK này là các hàm tạm ngưng và cần được gọi từ phạm vi 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

Đối với Java, các phương thức trong SDK này trả về một 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.");

Lựa chọn 2: Đưa loại MIME và URL vào một cách rõ ràng

Trước khi thử ví dụ này, hãy đảm bảo bạn đã hoàn tất hướng dẫn bắt đầu sử dụng cho Firebase AI Logic SDK.

Hãy sử dụng lựa chọn này nếu bạn biết các giá trị cho loại MIME và Cloud Storage for Firebase URL, đồng thời muốn đưa các giá trị đó vào yêu cầu đa phương thức một cách rõ ràng. Lệnh gọi này yêu cầu cả loại MIME và 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

Đối với Kotlin, các phương thức trong SDK này là các hàm tạm ngưng và cần được gọi từ phạm vi 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

Đối với Java, các phương thức trong SDK này trả về một 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.");