Đư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ỉ có khi bạn dùng Vertex AI Gemini API làm trình cung cấp API.

Khi gọi Vertex AI Gemini API từ ứng dụng bằng SDK Firebase AI Logic, bạn có thể nhắc một 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, 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 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 tệp vào yêu cầu. Nhìn chung, sau đâ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 dùng Vertex AI Gemini API. Các ví dụ trong hướng dẫn này cho thấy một đầ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 (luôn bắt đầu bằng gs://) trong dữ liệu đầu vào của yêu cầu. Đây là siêu dữ liệu được tự động chỉ định cho mọi tệp được tải lên một vùng chứa Cloud Storage.

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


Hướng dẫn này mô tả cách thiết lập Cloud Storage for Firebase, tải một 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 và URL Cloud Storage for Firebase của tệp vào yêu cầu đa phương thức của bạn đối với Gemini API.

Bạn có muốn xem các đoạn mã ví dụ 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 tính năng này 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 cơ sở hạ tầng nhanh, an toàn và có khả năng 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 dịch vụ này được xây dựng dành riêng cho ứng dụng di động và ứng dụng web.

Đối với SDK Firebase AI Logic, 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 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 trực tiếp tệp đó dưới dạng dữ liệu nội tuyến (mặc dù 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).

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

  • Người dùng cuối có thể tải hình ảnh trực tiếp từ ứng dụng của bạn lên một vùng chứa Cloud Storage for Firebase, sau đó bạn có thể đưa những hình ảnh đó vào câu lệnh đa phương thức chỉ bằng cách chỉ định loại MIME và URL Cloud Storage for Firebase của tệp (đây là một 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 lên hoặc tải xuống tệp bị gián đoạn, các SDK Cloud Storage for Firebase sẽ tự động khởi động lại thao tác ngay tại nơi 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à không cần người dùng cuối phải tải lên 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. Thao tá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 nhóm 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 cách sử dụ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 Firebase AI Logic:

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

  • Thùng 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 một hình ảnh mà bạn tìm thấy trên Internet).

Ngoài ra, Firebase Security Rules cho nhóm 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ó cá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 đã đă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 được cung cấp.

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

Chỉ có khi bạn dùng Vertex AI Gemini API làm trình cung cấp API.

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

Bạn có thể xem 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 của Cloud Storage for Firebase: iOS+ | Android | Web | Flutter | Unity

Sau đây là những việc bạn cần làm:

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

  2. Áp dụng Firebase Security Rules cho nhóm này. Rules giúp bạn bảo mật 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 nhiệm vụ này, nhưng sau đó bạn phải luôn đưa rõ các giá trị loại MIME và URL vào yêu cầu của mình.

Bước 2: Tải tệp lên một vùng lưu trữ

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 lưu trữ. 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ừ camera. 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 lưu trữ, Cloud Storage sẽ tự động áp dụng 2 thông tin sau cho tệp đó. Bạn sẽ cần phải thêm 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ể chọn 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: 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 một nhóm, bạn có thể thêm loại MIME và URL của tệp đó vào một yêu cầu. Xin lưu ý rằng những 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 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 hai lựa chọn sau:

Cách 1: Thêm loại MIME và URL bằng cách sử dụng một tham chiếu đến Bộ nhớ

Trước khi thử ví dụ này, hãy đảm bảo rằng bạn đã hoàn tất hướng dẫn bắt đầu 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 lưu trữ và muốn đưa tệp đó vào yêu cầu ngay lập tức (thông qua một tham chiếu đến 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à hàm tạm ngưng và cần được gọi qua 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 sẽ trả về 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.");

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

Trước khi thử ví dụ này, hãy đảm bảo rằng bạn đã hoàn tất hướng dẫn bắt đầu 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à URL Cloud Storage for Firebase, đồng thời muốn đưa các giá trị đó một cách rõ ràng vào 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.

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à hàm tạm ngưng và cần được gọi qua 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 sẽ trả về 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.");