Đư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

Khi gọi Gemini API từ ứng dụng bằng SDK Vertex AI in Firebase, bạn có thể nhắc mô hình Gemini tạo văn bản dựa trên dữ liệu đầu vào đa phương thức. Lời nhắc đa phương thức có thể bao gồm nhiều phương thức (hoặc loại dữ liệu đầu vào), chẳng hạn như văn bản cùng với hình ảnh, tệp PDF, video và âm thanh.

Đối với các phần không phải văn bản của dữ liệu đầu vào (chẳng hạn như tệp 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. Dưới đâ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 bất kỳ yêu cầu đa phương thức nào (chẳng hạn như cả việc tạo văn bản và trò chuyện). Các ví dụ trong hướng dẫn này cho thấy dữ liệu đầu vào cơ bản là 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 yêu cầu. Các giá trị này là siêu dữ liệu được tự động chỉ định cho mọi tệp được tải lên bộ chứa Cloud Storage.

  • Bạn cần sử dụng 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 một tệp lên bộ chứa Cloud Storage for Firebase từ ứng dụng, 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 đến Gemini API.

Bạn có muốn xem các ví dụ về mã không? Hoặc bạn đã thiết lập Cloud Storage for Firebase và sẵn sàng bắt đầu sử dụng Cloud Storage for Firebase 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, an toàn và có thể mở rộng như Google Cloud Storage để lưu trữ các blob và tệp, đồng thời SDK ứng dụng của nó được xây dựng riêng cho các ứng dụng web và di động.

Đối với SDK Vertex AI in Firebase, kích thước yêu cầu tối đa 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 khiến tổng kích thước yêu cầu vượt quá 20 MB, 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 có kích thước nhỏ, bạn thường có thể truyền tệp đó trực tiếp dưới dạng dữ liệu nội tuyến (tuy nhiên, hãy 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, làm tăng kích thước của yêu cầu).

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

  • Bạn có thể yêu cầu người dùng cuối tải hình ảnh lên trực tiếp từ ứng dụng của bạn vào một bộ chứa Cloud Storage for Firebase, sau đó bạn có thể đưa các 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à URL Cloud Storage for Firebase (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à khi chất lượng mạng của họ kém hoặc không ổn định.

    • Nếu quá trình tải lên hoặc tải xuống tệp bị gián đoạn, SDK Cloud Storage for Firebase sẽ tự động khởi động lại thao tác ngay tại vị trí bị gián đoạn.
    • Bạn có thể sử dụng cùng một tệp đã tải lên nhiều lần mà người dùng cuối không cần phải tải cùng một tệp lên 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. Phương thức này chỉ cho phép người dùng được uỷ quyền tải lên, tải xuống hoặc xoá tệp.

  • Bạn có thể truy cập vào các tệp trong bộ chứa 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ợ?

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

  • Tệp phải đáp ứng các yêu cầu của tệp đầu vào cho các yêu cầu đa phương thức khi sử dụng SDK Vertex AI in Firebase. 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 bộ chứa Cloud Storage for Firebase (tức là các dịch vụ Firebase, chẳng hạn như Firebase Security Rules, có thể truy cập vào bộ chứa đó). Nếu bạn có thể xem bộ chứa trong bảng điều khiển Firebase, thì đó là bộ chứa Cloud Storage for Firebase.

  • Bộ 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 được là URL "trình duyệt" (ví dụ: URL của hình ảnh mà bạn tìm thấy trên Internet).

Ngoài ra, Firebase Security Rules cho bộ 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 và cung cấp URL của tệp đó trong lệnh gọi bằng SDK Vertex AI in Firebase. Bạn chỉ nên sử dụng các loại quy tắc này để bắt đầu và trong quá trình tạo nguyên mẫu ban đầu (trừ phi các tệp thực sự được dùng để truy cập công khai).

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

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

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 và sử dụng Cloud Storage for Firebase trong hướng dẫn bắt đầu sử dụng.

Truy cập vào hướng dẫn bắt đầu sử dụng Cloud Storage for Firebase

Sau đây là các nhiệm vụ cấp cao mà bạn cần thực hiện:

  1. Tạo một bộ chứa Cloud Storage for Firebase trong dự án Firebase.

    Nếu đã có một bộ chứa Cloud Storage trong dự án Google Cloud mà bạn muốn sử dụng với Vertex AI in Firebase, thì bạn có thể cho phép các dịch vụ Firebase (bao gồm cả Vertex AI in Firebase) truy cập vào bộ chứa đó bằng cách "nhập" bộ chứa vào Firebase.

  2. Áp dụng Firebase Security Rules cho bộ chứa này. Firebase Security Rules giúp bạn bảo mật tệp bằng cách hạn chế quyền truy cập của 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 nhiệm vụ này, nhưng sau đó, bạn phải luôn thêm rõ ràng loại MIME và giá trị URL Cloud Storage for Firebase vào các yêu cầu đa phương thức.

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

Trong tài liệu về Cloud Storage for Firebase, bạn có thể tìm hiểu tất cả các cách để tải tệp lên bộ chứa Cloud Storage for Firebase. Ví dụ: bạn có thể tải tệp trên máy 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.

Khi bạn tải một tệp lên một bộ chứa, Cloud Storage sẽ tự động áp dụng hai thông tin sau cho tệp đó. Bạn cần đưa các giá trị này vào yêu cầu đa phương thức (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). Cloud Storage for Firebase 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 bộ chứa. Tuy nhiên, bạn có thể chỉ định loại MIME trong quá trình tải lên.

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

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

Sau khi lưu trữ một tệp trong bộ chứa Cloud Storage for Firebase, bạn có thể đưa loại MIME và URL Cloud Storage for Firebase của tệp đó vào một yêu cầu đa phương thức. 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 Cloud Storage for Firebase có 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 tuỳ chọn sau:

Cách 1: Thêm loại MIME và URL bằng tệp tham chiếu Bộ nhớ

Sử dụng tuỳ chọn này nếu bạn vừa tải tệp lên bộ chứa và muốn đưa tệp đó vào ngay (thông qua tham chiếu Bộ nhớ) trong yêu cầu đa phương thức. Lệnh gọi này yêu cầu cả loại MIME và URL Cloud Storage for Firebase.

Kotlin+KTX

Đối với Kotlin, các phương thức trong SDK này là 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 = 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

Đố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();
});

Cách 2: Thêm loại MIME và URL một cách rõ ràng

Sử dụng tuỳ chọn này nếu bạn biết các giá trị cho loại MIME và URL Cloud Storage for Firebase, đồng thời bạn 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.

Kotlin+KTX

Đối với Kotlin, các phương thức trong SDK này là 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 = generativeModel.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);