Vertex AI in Firebase SDK를 사용하여 앱에서 Gemini API를 호출할 때 Gemini 모델에 멀티모달 입력을 기반으로 텍스트를 생성하라는 메시지를 표시할 수 있습니다. 멀티모달 프롬프트에는 이미지, PDF, 동영상, 오디오와 함께 텍스트와 같은 여러 모달(또는 입력 유형)이 포함될 수 있습니다.
입력의 텍스트가 아닌 부분(예: 미디어 파일)의 경우 원하는 경우 Cloud Storage for Firebase를 사용하여 요청에 파일을 포함할 수 있습니다. 이 기능에 대해 알아야 할 사항은 다음과 같습니다.
Cloud Storage for Firebase는 모든 멀티모달 요청 (예: 텍스트 생성 및 채팅)과 함께 사용할 수 있습니다. 이 가이드의 예에서는 기본 텍스트 및 이미지 입력을 보여줍니다.
요청 입력에서 파일의 MIME 유형과 Cloud Storage for Firebase URL(항상
gs://
로 시작)을 지정합니다. 이러한 값은 Cloud Storage 버킷에 업로드된 모든 파일에 자동으로 할당되는 메타데이터입니다.지원되는 파일 형식 및 URL을 사용해야 합니다.
이 솔루션 가이드에서는 Cloud Storage for Firebase를 설정하고 앱에서 Cloud Storage for Firebase 버킷에 파일을 업로드한 후 Gemini API에 대한 다중 모드 요청에 파일의 MIME 유형 및 Cloud Storage for Firebase URL을 포함하는 방법을 설명합니다.
코드 예시를 확인하고 싶으신가요? 아니면 이미 Cloud Storage for Firebase를 설정했고 멀티모달 요청에서 사용할 준비가 되셨나요?
앱에서 Cloud Storage for Firebase를 사용하는 이유는 무엇인가요?
Cloud Storage for Firebase는 Google Cloud Storage와 동일한 빠르고 안전하며 확장 가능한 인프라를 사용하여 blob과 파일을 저장하며 클라이언트 SDK는 모바일 및 웹 앱용으로 특별히 빌드되었습니다.
Vertex AI in Firebase SDK의 경우 최대 요청 크기는 20MB입니다. 요청이 너무 크면 HTTP 413 오류가 발생합니다. 파일 크기로 인해 총 요청 크기가 20MB를 초과하는 경우 Cloud Storage for Firebase URL을 사용하여 파일을 다중 모드 요청에 포함합니다. 하지만 파일이 작으면 인라인 데이터로 직접 전달할 수 있습니다. 단, 인라인 데이터로 제공된 파일은 전송 중에 base64로 인코딩되므로 요청 크기가 커집니다.
Cloud Storage for Firebase를 사용하면 다음과 같은 추가 이점이 있습니다.
최종 사용자가 앱에서 Cloud Storage for Firebase 버킷으로 직접 이미지를 업로드하도록 한 다음 파일의 MIME 유형과 Cloud Storage for Firebase URL (파일 식별자)을 지정하기만 하면 멀티모달 프롬프트에 이러한 이미지를 포함할 수 있습니다.
특히 네트워크 품질이 좋지 않거나 불안정한 경우 최종 사용자가 이미지를 제공해야 할 때 시간을 절약하고 대역폭을 줄일 수 있습니다.
- 파일 업로드 또는 다운로드가 중단되면 Cloud Storage for Firebase SDK가 중단된 지점부터 작업을 자동으로 다시 시작합니다.
- 업로드된 동일한 파일은 최종 사용자가 앱에 필요할 때마다 동일한 파일을 업로드하지 않아도 여러 번 사용할 수 있습니다(예: 새로운 다중 모드 요청).
승인된 사용자만 파일을 업로드, 다운로드 또는 삭제하도록 허용하는 Firebase Security Rules를 사용하여 Cloud Storage for Firebase에 저장된 파일에 대한 최종 사용자의 액세스를 제한할 수 있습니다.
Firebase 또는 Google Cloud에서 버킷의 파일에 액세스할 수 있으므로 Google Cloud Storage API를 사용하여 이미지 필터링이나 동영상 트랜스코딩과 같은 서버 측 처리를 유연하게 수행할 수 있습니다.
어떤 유형의 파일과 URL이 지원되나요?
Vertex AI in Firebase SDK에서 Cloud Storage for Firebase URL을 사용하려면 다음과 같은 파일 및 URL 요구사항이 적용됩니다.
이 파일은 Vertex AI in Firebase SDK를 사용할 때 다중 모드 요청의 입력 파일 요구사항을 충족해야 합니다. 여기에는 MIME 유형, 파일 크기와 같은 요구사항이 포함됩니다.
파일은 Cloud Storage for Firebase 버킷에 저장되어야 합니다. 즉, Firebase Security Rules와 같은 Firebase 서비스에서 버킷에 액세스할 수 있어야 합니다. Firebase 콘솔에서 버킷을 볼 수 있으면 Cloud Storage for Firebase 버킷입니다.
Cloud Storage for Firebase 버킷은 앱을 등록한 것과 동일한 Firebase 프로젝트에 있어야 합니다.
파일의 Cloud Storage for Firebase URL은 모든 Google Cloud Storage URL이 생성되는 방식인
gs://
로 시작해야 합니다.파일의 URL은 '브라우저' URL (예: 인터넷에서 찾은 이미지의 URL)이 될 수 없습니다.
또한 버킷의 Firebase Security Rules에서 파일에 적절한 액세스를 허용해야 합니다. 예를 들면 다음과 같습니다.
공개 규칙이 있는 경우 모든 사용자 또는 클라이언트가 파일에 액세스하고 Vertex AI in Firebase SDK를 사용하여 호출 시 URL을 제공할 수 있습니다. 이러한 유형의 규칙은 파일이 실제로 완전히 공개적으로 액세스할 수 있는 파일이 아닌 한 시작하고 초기 프로토타입을 만드는 데만 사용해야 합니다.
강력한 규칙 (적극 권장)이 있는 경우 Firebase는 제공된 URL을 통해 호출을 허용하기 전에 로그인한 사용자 또는 클라이언트가 파일에 충분한 액세스 권한이 있는지 확인합니다.
Cloud Storage for Firebase URL을 Vertex AI in Firebase와 함께 사용
1단계: Cloud Storage for Firebase 설정
Cloud Storage for Firebase 설정 및 사용에 관한 자세한 안내는 시작 가이드를 참고하세요.
Cloud Storage for Firebase 시작 가이드로 이동
다음은 해야 할 대략적인 작업입니다.
Firebase 프로젝트에 Cloud Storage for Firebase 버킷을 만듭니다.
Vertex AI in Firebase와 함께 사용하려는 Cloud Storage 버킷이 이미 Google Cloud 프로젝트에 있는 경우 버킷을 Firebase로 '가져와서' Firebase 서비스(Vertex AI in Firebase 포함)에서 액세스할 수 있도록 할 수 있습니다.
이 버킷에 Firebase Security Rules를 적용합니다. Firebase Security Rules를 사용하면 승인된 최종 사용자에게만 액세스 권한을 제한하여 파일을 보호할 수 있습니다.
앱에 Cloud Storage for Firebase용 클라이언트 라이브러리를 추가합니다.
이 작업을 건너뛰어도 되지만, 이 경우 항상 다중 모드 요청에 MIME 유형 및 Cloud Storage for Firebase URL 값을 명시적으로 포함해야 합니다.
2단계: 버킷에 파일 업로드
Cloud Storage for Firebase 문서에서 Cloud Storage for Firebase 버킷에 파일을 업로드하는 다양한 방법을 모두 알아볼 수 있습니다. 예를 들어 카메라의 사진 및 동영상과 같은 최종 사용자 기기의 로컬 파일을 업로드할 수 있습니다.
버킷에 파일을 업로드하면 Cloud Storage에서 다음 두 가지 정보를 파일에 자동으로 적용합니다. 이 값은 멀티모달 요청에 포함해야 합니다(이 가이드의 다음 단계 참고).
MIME 유형: 파일의 미디어 유형입니다 (예:
image/png
). Cloud Storage for Firebase는 업로드 중에 MIME 유형을 자동으로 감지하고 해당 메타데이터를 버킷의 객체에 적용하려고 시도합니다. 하지만 업로드 중에 MIME 유형을 지정할 수도 있습니다.Cloud Storage for Firebase URL: 파일의 고유 식별자입니다. URL은
gs://
로 시작해야 합니다.
3단계: 멀티모달 요청에 파일의 MIME 유형 및 URL 포함
Cloud Storage for Firebase 버킷에 파일을 저장한 후에는 MIME 유형과 Cloud Storage for Firebase URL을 다중 모드 요청에 포함할 수 있습니다.
이 예에서는 스트리밍이 아닌 generateContent
요청을 보여줍니다. 하지만 스트리밍 및 채팅과 함께 Cloud Storage for Firebase URL을 사용할 수도 있습니다.
요청에 파일을 포함하려면 다음 옵션 중 하나를 사용하세요.
옵션 2: MIME 유형 및 URL을 명시적으로 포함
옵션 1: 스토리지 참조를 사용하여 MIME 유형 및 URL 포함
파일을 버킷에 업로드한 직후 스토리지 참조를 통해 파일을 멀티모달 요청에 즉시 포함하려면 이 옵션을 사용하세요. 호출에는 MIME 유형과 Cloud Storage for Firebase URL이 모두 필요합니다.
Kotlin+KTX
Kotlin의 경우 이 SDK의 메서드는 정지 함수이므로 코루틴 범위에서 호출해야 합니다.// 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
Java의 경우 이 SDK의 메서드는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();
});
옵션 2: MIME 유형 및 URL을 명시적으로 포함
MIME 유형 및 Cloud Storage for Firebase URL의 값을 알고 있으며 이를 멀티모달 요청에 명시적으로 포함하려는 경우 이 옵션을 사용하세요. 호출에는 MIME 유형과 URL이 모두 필요합니다.
Kotlin+KTX
Kotlin의 경우 이 SDK의 메서드는 정지 함수이므로 코루틴 범위에서 호출해야 합니다.// 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
Java의 경우 이 SDK의 메서드는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);