在 Android 應用程式中開始使用 Gemini API (用戶端 SDK)

本教學課程說明如何使用 Android 專用的 Google AI 用戶端 SDK,直接從 Android 應用程式存取 Gemini API。如果您不想直接與 REST API 或伺服器端程式碼 (例如 Python) 搭配使用,以在 Android 應用程式中存取 Gemini 模型,可以使用這個用戶端 SDK。

在本教學課程中,您將瞭解如何執行下列操作:

此外,本教學課程包含進階用途的相關章節 (例如計算符記),以及控管內容產生功能的選項。

建議在裝置端存取 Gemini

本教學課程說明的 Android 專用用戶端 SDK 可讓您存取在 Google 伺服器上執行的 Gemini Pro 模型。如果是涉及處理機密資料、離線可用性,或為了節省常用使用者流程而節省費用的用途,您可能會想要存取在裝置端執行的 Gemini Nano。詳情請參閱 Android (裝置端) 教學課程

必要條件

本教學課程假設您已熟悉如何使用 Android Studio 開發 Android 應用程式。

如要完成本教學課程,請確認您的開發環境和 Android 應用程式符合下列需求:

  • Android Studio (最新版本)
  • 您的 Android 應用程式必須指定 API 級別 21 以上版本。

設定專案

呼叫 Gemini API 之前,您需要設定 Android 專案,包括設定 API 金鑰、將 SDK 依附元件新增至 Android 專案,以及初始化模型。

設定 API 金鑰

如要使用 Gemini API,您必須具備 API 金鑰。如果您還沒有金鑰 請在 Google AI Studio 中建立金鑰

取得 API 金鑰

保護 API 金鑰安全

強烈建議您「不要」將 API 金鑰登錄到版本管控系統中。而是應該將 API 金鑰儲存在 local.properties 檔案 (位於專案的根目錄中,但不在版本管控中),然後使用 Secrets Gradle Plugin for Android 將 API 金鑰讀取為建構設定變數。

Kotlin

// Access your API key as a Build Configuration variable
val apiKey = BuildConfig.apiKey

Java

// Access your API key as a Build Configuration variable
String apiKey = BuildConfig.apiKey;

本教學課程中的所有程式碼片段都採用這項最佳做法。此外,如果您想查看 Secrets Gradle 外掛程式的實作方式,可以查看這個 SDK 的範例應用程式,或使用 Android Studio Iguana 的最新預先發布版,當中提供了 Gemini API Starter 範本 (包含協助您開始使用的 local.properties 檔案)。

將 SDK 依附元件新增至專案

  1. 模組 (應用程式層級) Gradle 設定檔 (例如 <project>/<app-module>/build.gradle.kts) 中,新增 Android 版 Google AI SDK 的依附元件:

    Kotlin

    dependencies {
      // ... other androidx dependencies
    
      // add the dependency for the Google AI client SDK for Android
      implementation("com.google.ai.client.generativeai:generativeai:0.3.0")
    }
    

    Java

    如果是 Java,您需要新增兩個程式庫。

    dependencies {
        // ... other androidx dependencies
    
        // add the dependency for the Google AI client SDK for Android
        implementation("com.google.ai.client.generativeai:generativeai:0.3.0")
    
        // Required for one-shot operations (to use `ListenableFuture` from Guava Android)
        implementation("com.google.guava:guava:31.0.1-android")
    
        // Required for streaming operations (to use `Publisher` from Reactive Streams)
        implementation("org.reactivestreams:reactive-streams:1.0.4")
    }
    
  2. 將 Android 專案與 Gradle 檔案同步處理。

初始化生成模型

您必須先初始化 GenerativeModel 物件,才能進行 API 呼叫:

Kotlin

val generativeModel = GenerativeModel(
    // Use a model that's applicable for your use case (see "Implement basic use cases" below)
    modelName = "MODEL_NAME",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

Java

如果是 Java,您還需要初始化 GenerativeModelFutures 物件。

// Use a model that's applicable for your use case (see "Implement basic use cases" below)
GenerativeModel gm = new GenerativeModel(/* modelName */ "MODEL_NAME",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);

// Use the GenerativeModelFutures Java compatibility layer which offers
// support for ListenableFuture and Publisher APIs
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

指定模型時,請注意下列事項:

  • 使用特定用途專屬的模型 (例如,gemini-pro-vision 適用於多模態輸入)。在本指南中,每個實作項目的操作說明都會列出每個用途的建議模型。

實作常見用途

現在專案已設定完成,您可以使用 Gemini API 來實作不同的使用案例:

根據純文字產生文字

如果提示輸入內容只包含文字,請使用 gemini-pro 模型搭配 generateContent 來產生文字輸出:

Kotlin

請注意,generateContent() 是暫停函式,需要從協同程式範圍呼叫。如果您不熟悉協同程式,請參閱 Android 上的 Kotlin 協同程式

val generativeModel = GenerativeModel(
    // For text-only input, use the gemini-pro model
    modelName = "gemini-pro",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val prompt = "Write a story about a magic backpack."
val response = generativeModel.generateContent(prompt)
print(response.text)

Java

請注意,generateContent() 會傳回 ListenableFuture。如果您不熟悉這個 API,請參閱 Android 說明文件的使用 ListenableFuture 相關說明。

// For text-only input, use the gemini-pro model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Content content = new Content.Builder()
    .addText("Write a story about a magic backpack.")
    .build();

Executor executor = // ...

ListenableFuture<GenerateContentResponse> response = model.generateContent(content);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

依據文字和圖片輸入產生文字 (多模態)

Gemini 提供多模態模型 (gemini-pro-vision),因此您可以同時輸入文字和圖片。請務必詳閱提示的圖片規定

如果提示輸入內容包含文字和圖片,請使用 gemini-pro-vision 模型搭配 generateContent 來產生文字輸出:

Kotlin

請注意,generateContent() 是暫停函式,需要從協同程式範圍呼叫。如果您不熟悉協同程式,請參閱 Android 上的 Kotlin 協同程式

val generativeModel = GenerativeModel(
    // For text-and-images input (multimodal), use the gemini-pro-vision model
    modelName = "gemini-pro-vision",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val image1: Bitmap = // ...
val image2: Bitmap = // ...

val inputContent = content {
    image(image1)
    image(image2)
    text("What's different between these pictures?")
}

val response = generativeModel.generateContent(inputContent)
print(response.text)

Java

請注意,generateContent() 會傳回 ListenableFuture。如果您不熟悉這個 API,請參閱 Android 說明文件的使用 ListenableFuture 相關說明。

// For text-and-images input (multimodal), use the gemini-pro-vision model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro-vision",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Bitmap image1 = // ...
Bitmap image2 = // ...

Content content = new Content.Builder()
    .addText("What's different between these pictures?")
    .addImage(image1)
    .addImage(image2)
    .build();

Executor executor = // ...

ListenableFuture<GenerateContentResponse> response = model.generateContent(content);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

建立多輪對話 (即時通訊)

只要使用 Gemini,就能跨輪建立形式不限的對話。這個 SDK 可藉由管理對話狀態來簡化程序,因此與 generateContent 不同,您不必自行儲存對話記錄。

如要建構多輪對話 (例如即時通訊),請使用 gemini-pro 模型,並呼叫 startChat() 來初始化即時通訊。接著使用 sendMessage() 傳送新使用者訊息,這樣訊息和回應也會附加到即時通訊記錄中。

與對話中的內容相關聯的 role 有兩種可能的選項:

  • user:提供提示的角色。這個值是 sendMessage 呼叫的預設值。

  • model:提供回應的角色。使用現有的 history 呼叫 startChat() 時,可以使用這個角色。

Kotlin

請注意,generateContent() 是暫停函式,需要從協同程式範圍呼叫。如果您不熟悉協同程式,請參閱 Android 上的 Kotlin 協同程式

val generativeModel = GenerativeModel(
    // For text-only input, use the gemini-pro model
    modelName = "gemini-pro",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val chat = generativeModel.startChat(
    history = listOf(
        content(role = "user") { text("Hello, I have 2 dogs in my house.") },
        content(role = "model") { text("Great to meet you. What would you like to know?") }
    )
)

chat.sendMessage("How many paws are in my house?")

Java

請注意,generateContent() 會傳回 ListenableFuture。如果您不熟悉這個 API,請參閱 Android 說明文件的使用 ListenableFuture 相關說明。

// For text-only input, use the gemini-pro model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

// (optional) Create previous chat history for context
Content.Builder userContentBuilder = new Content.Builder();
userContentBuilder.setRole("user");
userContentBuilder.addText("Hello, I have 2 dogs in my house.");
Content userContent = userContentBuilder.build();

Content.Builder modelContentBuilder = new Content.Builder();
modelContentBuilder.setRole("model");
modelContentBuilder.addText("Great to meet you. What would you like to know?");
Content modelContent = userContentBuilder.build();

List<Content> history = Arrays.asList(userContent, modelContent);

// Initialize the chat
ChatFutures chat = model.startChat(history);

// Create a new user message
Content userMessage = new Content.Builder()
    .setRole("user")
    .addText("How many paws are in my house?")
    .build();

Executor executor = // ...

// Send the message
ListenableFuture<GenerateContentResponse> response = chat.sendMessage(userMessage);

Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

使用串流功能享受更便捷的互動體驗

根據預設,模型會在完成整個產生程序後傳回回應。您不必等待整個結果,就能以串流方式處理部分結果,藉此加快互動速度。

以下範例說明如何使用 generateContentStream 實作串流,以透過文字和圖片輸入提示產生文字。

Kotlin

請注意,generateContentStream() 是暫停函式,需要從協同程式範圍呼叫。如果您不熟悉協同程式,請參閱 Android 上的 Kotlin 協同程式

val generativeModel = GenerativeModel(
    // For text-and-image input (multimodal), use the gemini-pro-vision model
    modelName = "gemini-pro-vision",
    // Access your API key as a Build Configuration variable (see "Set up your API key" above)
    apiKey = BuildConfig.apiKey
)

val image1: Bitmap = // ...
val image2: Bitmap = // ...

val inputContent = content {
    image(image1)
    image(image2)
    text("What's the difference between these pictures?")
}

var fullResponse = ""
generativeModel.generateContentStream(inputContent).collect { chunk ->
    print(chunk.text)
    fullResponse += chunk.text
}

Java

這個 SDK 中的 Java 串流方法會從 Reactive Streams 程式庫傳回 Publisher 類型。

// For text-and-images input (multimodal), use the gemini-pro-vision model
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-pro-vision",
// Access your API key as a Build Configuration variable (see "Set up your API key" above)
    /* apiKey */ BuildConfig.apiKey);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);

Bitmap image1 = // ...
Bitmap image2 = // ...

Content content = new Content.Builder()
    .addText("What's different between these pictures?")
    .addImage(image1)
    .addImage(image2)
    .build();

Publisher<GenerateContentResponse> streamingResponse =
    model.generateContentStream(content);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    @Override
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    @Override
    public void onSubscribe(Subscription s) { }
});

您可以利用類似方式處理純文字輸入和即時通訊用途:

Kotlin

請注意,generateContentStream() 是暫停函式,需要從協同程式範圍呼叫。如果您不熟悉協同程式,請參閱 Android 上的 Kotlin 協同程式

// Use streaming with text-only input
generativeModel.generateContentStream(inputContent).collect { chunk ->
    print(chunk.text)
}
// Use streaming with multi-turn conversations (like chat)
val chat = generativeModel.startChat()
chat.sendMessageStream(inputContent).collect { chunk ->
    print(chunk.text)
}

Java

這個 SDK 中的 Java 串流方法會從 Reactive Streams 程式庫傳回 Publisher 類型。

// Use streaming with text-only input
Publisher<GenerateContentResponse> streamingResponse =
    model.generateContentStream(inputContent);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    // ... other methods omitted for brevity
});
// Use streaming with multi-turn conversations (like chat)
ChatFutures chat = model.startChat(history);

Publisher<GenerateContentResponse> streamingResponse =
    chat.sendMessageStream(inputContent);

final String[] fullResponse = {""};

streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
    @Override
    public void onNext(GenerateContentResponse generateContentResponse) {
        String chunk = generateContentResponse.getText();
        fullResponse[0] += chunk;
    }

    @Override
    public void onComplete() {
        System.out.println(fullResponse[0]);
    }

    // ... other methods omitted for brevity
});

實作進階用途

本教學課程前一節所述的常見用途,可協助您熟悉使用 Gemini API。本節說明部分可能更進階的用途。

計算符記

使用長提示時,建議先計算符記再傳送任何內容給模型。以下範例說明如何將 countTokens() 用於各種用途:

Kotlin

請注意,countTokens() 是暫停函式,需要從協同程式範圍呼叫。如果您不熟悉協同程式,請參閱 Android 上的 Kotlin 協同程式

// For text-only input
val (totalTokens) = generativeModel.countTokens("Write a story about a magic backpack.")

// For text-and-image input (multi-modal)
val multiModalContent = content {
    image(image1)
    image(image2)
    text("What's the difference between these pictures?")
}

val (totalTokens) = generativeModel.countTokens(multiModalContent)

// For multi-turn conversations (like chat)
val history = chat.history
val messageContent = content { text("This is the message I intend to send")}
val (totalTokens) = generativeModel.countTokens(*history.toTypedArray(), messageContent)

Java

請注意,countTokens() 會傳回 ListenableFuture。如果您不熟悉這個 API,請參閱 Android 說明文件的使用 ListenableFuture 相關說明。

Content text = new Content.Builder()
    .addText("Write a story about a magic backpack.")
    .build();

Executor executor = // ...

// For text-only input
ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(text);

Futures.addCallback(countTokensResponse, new FutureCallback<CountTokensResponse>() {
    @Override
    public void onSuccess(CountTokensResponse result) {
        int totalTokens = result.getTotalTokens();
        System.out.println("TotalTokens = " + totalTokens);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

// For text-and-image input
Bitmap image1 = // ...
Bitmap image2 = // ...

Content multiModalContent = new Content.Builder()
    .addImage(image1)
    .addImage(image2)
    .addText("What's different between these pictures?")
    .build();

ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(multiModalContent);

// For multi-turn conversations (like chat)
List<Content> history = chat.getChat().getHistory();

Content messageContent = new Content.Builder()
    .addText("This is the message I intend to send")
    .build();

Collections.addAll(history, messageContent);

ListenableFuture<CountTokensResponse> countTokensResponse = model.countTokens(history.toArray(new Content[0]));

控管內容產生功能的選項

您可以透過設定模型參數和安全設定來控制內容產生作業。

設定模型參數

您傳送至模型的每個提示都含有參數值,用來控制模型生成回覆的方式。模型可能會為不同參數值產生不同的結果。進一步瞭解模型參數

Kotlin

val config = generationConfig {
    temperature = 0.9f
    topK = 16
    topP = 0.1f
    maxOutputTokens = 200
    stopSequences = listOf("red")
}

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    generationConfig = config
)

Java

GenerationConfig.Builder configBuilder = new GenerationConfig.Builder();
configBuilder.temperature = 0.9f;
configBuilder.topK = 16;
configBuilder.topP = 0.1f;
configBuilder.maxOutputTokens = 200;
configBuilder.stopSequences = Arrays.asList("red");

GenerationConfig generationConfig = configBuilder.build();

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    generationConfig
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

使用安全性設定

您可以使用安全性設定,調整取得可能有害回應的機率。根據預設,安全設定會在所有維度中封鎖中度和/或極有可能為不安全的內容。進一步瞭解安全設定

以下說明如何設定一項安全性設定:

Kotlin

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    safetySettings = listOf(
        SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)
    )
)

Java

SafetySetting harassmentSafety = new SafetySetting(HarmCategory.HARASSMENT,
    BlockThreshold.ONLY_HIGH);

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    null, // generation config is optional
    Collections.singletonList(harassmentSafety)
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

您也可以設定多項安全性設定:

Kotlin

val harassmentSafety = SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)

val hateSpeechSafety = SafetySetting(HarmCategory.HATE_SPEECH, BlockThreshold.MEDIUM_AND_ABOVE)

val generativeModel = GenerativeModel(
    modelName = "MODEL_NAME",
    apiKey = BuildConfig.apiKey,
    safetySettings = listOf(harassmentSafety, hateSpeechSafety)
)

Java

SafetySetting harassmentSafety = new SafetySetting(HarmCategory.HARASSMENT,
    BlockThreshold.ONLY_HIGH);

SafetySetting hateSpeechSafety = new SafetySetting(HarmCategory.HATE_SPEECH,
    BlockThreshold.MEDIUM_AND_ABOVE);

GenerativeModel gm = new GenerativeModel(
    "MODEL_NAME",
    BuildConfig.apiKey,
    null, // generation config is optional
    Arrays.asList(harassmentSafety, hateSpeechSafety)
);

GenerativeModelFutures model = GenerativeModelFutures.from(gm);

後續步驟

  • 提示設計是指建立提示,從語言模型中提取所需回應的程序。編寫結構周全的提示,是確保語言模型提供準確優質回覆的關鍵。瞭解提示撰寫的最佳做法

  • Gemini 提供多種模型變化版本,以滿足不同用途的需求,例如輸入類型和複雜度、聊天或其他對話方塊語言工作的實作,以及大小限制。瞭解可用的 Gemini 模式

  • Gemini 提供要求提高頻率限制的選項。Genmini Pro 模型的頻率限制為每分鐘 60 次 (RPM)。

  • 本教學課程說明的 Android 專用用戶端 SDK 可讓您存取在 Google 伺服器上執行的 Gemini Pro 模型。如果是涉及處理機密資料、離線可用性,或為了節省常用使用者流程而節省費用的用途,您可能會想要存取在裝置端執行的 Gemini Nano。詳情請參閱 Android (裝置端) 教學課程