このチュートリアルでは、Android 用の Google AI クライアント SDK を使用して、Android アプリから Gemini API に直接アクセスする方法について説明します。Android アプリで Gemini モデルにアクセスする際に REST API やサーバーサイド コード(Python など)を直接操作しない場合は、このクライアント SDK を使用できます。
このチュートリアルでは、次の方法を学習します。
- API キーを含めたプロジェクトをセットアップする
- テキストのみの入力からテキストを生成する
- テキストと画像の入力からテキストを生成する(マルチモーダル)
- マルチターンの会話を構築する(チャット)
- ストリーミングを使用して操作を高速化する
さらに、このチュートリアルには、高度なユースケース(トークンのカウントなど)と、コンテンツ生成の制御のオプションに関するセクションも含まれています。
デバイスでの Gemini の利用をご検討ください
このチュートリアルで説明する Android 用クライアント SDK を使用すると、Google のサーバーで実行される Gemini Pro モデルにアクセスできます。センシティブ データの処理やオフラインの可用性が含まれるユースケースや、頻繁に使用されるユーザーフローの費用削減が目的のユースケースでは、オンデバイスで実行される Gemini Nano へのアクセスを検討することをおすすめします。詳細については、Android(オンデバイス)チュートリアルをご覧ください。
前提条件
このチュートリアルは、Android Studio を使用して Android アプリを開発する方法に精通していることを前提としています。
このチュートリアルを最後まで進めるには、開発環境と Android アプリが次の要件を満たしていることを確認してください。
- Android Studio(最新バージョン)
- Android アプリは API レベル 21 以降を対象にする必要があります。
プロジェクトを設定する
Gemini API を呼び出す前に、API キーの設定、Android プロジェクトへの SDK 依存関係の追加、モデルの初期化など、Android プロジェクトをセットアップする必要があります。
API キーを設定する
Gemini API を使用するには API キーが必要です。キーがない場合は、Google AI Studio で作成します。
API キーを保護する
API キーをバージョン管理システムにチェックインしないことを強くおすすめします。代わりに、local.properties
ファイル(プロジェクトのルート ディレクトリにありますが、バージョン管理から除外されています)に保存して、ビルド構成変数として API キーを読み取るため、Android 用 Secrets Gradle プラグインを使用します。
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 のサンプルアプリを確認するか、Gemini API Starter テンプレート(開始用の local.properties
ファイルを含む)がある Android Studio Iguana の最新プレビューをご利用ください。
プロジェクトに SDK の依存関係を追加する
モジュール(アプリレベル)の Gradle 構成ファイル(
<project>/<app-module>/build.gradle.kts
など)に、Google AI SDK for Android の依存関係を追加します。Kotlin
dependencies { // ... other androidx dependencies // add the dependency for the Google AI client SDK for Android implementation("com.google.ai.client.generativeai:generativeai:0.9.0") }
Java
Java の場合、2 つのライブラリを追加する必要があります。
dependencies { // ... other androidx dependencies // add the dependency for the Google AI client SDK for Android implementation("com.google.ai.client.generativeai:generativeai:0.9.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") }
Android プロジェクトと Gradle ファイルを同期する。
生成モデルを初期化する
API 呼び出しを行う前に、生成モデルを初期化する必要があります。
Kotlin
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with most use cases
modelName = "gemini-1.5-flash",
// 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
// The Gemini 1.5 models are versatile and work with most use cases
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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-1.5-flash
はマルチモーダル入力用です)。このガイドでは、各実装の手順に、各ユースケースに推奨されるモデルを記載しています。
一般的なユースケースの実装
プロジェクトが設定されたので、Gemini API を使用してさまざまなユースケースを実装してみましょう。
テキストのみの入力からテキストを生成する
プロンプト入力にテキストのみが含まれている場合は、Gemini 1.5 モデルまたは Gemini 1.0 Pro モデルと generateContent
を使用して、テキスト出力を生成します。
Kotlin
generateContent()
は suspend 関数であり、コルーチンのスコープから呼び出す必要があります。コルーチンに慣れていない場合は、Android での Kotlin コルーチンをご覧ください。
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
modelName = "gemini-1.5-flash",
// 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
の使用をご覧ください。
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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 1.5 モデル)が用意されており、テキストと画像の両方を入力できます。プロンプトの画像の要件を必ず確認してください。
プロンプト入力にテキストと画像の両方が含まれている場合は、Gemini 1.5 モデルと generateContent
を使用してテキスト出力を生成します。
Kotlin
generateContent()
は suspend 関数であり、コルーチンのスコープから呼び出す必要があります。コルーチンに慣れていない場合は、Android での Kotlin コルーチンをご覧ください。
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
modelName = "gemini-1.5-flash",
// 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
の使用をご覧ください。
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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 1.5 モデルまたは Gemini 1.0 Pro モデルを使用して、startChat()
を呼び出してチャットを初期化します。次に、sendMessage()
を使用して新しいユーザー メッセージを送信します。これにより、メッセージとレスポンスもチャット履歴に追加されます。
会話のコンテンツに関連付けられた role
には、次の 2 つのオプションがあります。
user
: プロンプトを提供するロール。この値はsendMessage
呼び出しのデフォルトです。model
: レスポンスを提供するロール。このロールは、既存のhistory
でstartChat()
を呼び出す場合に使用できます。
Kotlin
generateContent()
は suspend 関数であり、コルーチンのスコープから呼び出す必要があります。コルーチンに慣れていない場合は、Android での Kotlin コルーチンをご覧ください。
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with multi-turn conversations (like chat)
modelName = "gemini-1.5-flash",
// 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
の使用をご覧ください。
// The Gemini 1.5 models are versatile and work with multi-turn conversations (like chat)
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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.Builder userMessageBuilder = new Content.Builder();
userMessageBuilder.setRole("user");
userMessageBuilder.addText("How many paws are in my house?");
Content userMessage = userMessageBuilder.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()
は suspend 関数であり、コルーチンのスコープから呼び出す必要があります。コルーチンに慣れていない場合は、Android での Kotlin コルーチンをご覧ください。
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
modelName = "gemini-1.5-flash",
// 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
型を返します。
// The Gemini 1.5 models are versatile and work with both text-only and multimodal prompts
GenerativeModel gm = new GenerativeModel(/* modelName */ "gemini-1.5-flash",
// 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);
StringBuilder outputContent = new StringBuilder();
streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
@Override
public void onNext(GenerateContentResponse generateContentResponse) {
String chunk = generateContentResponse.getText();
outputContent.append(chunk);
}
@Override
public void onComplete() {
System.out.println(outputContent);
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
});
テキストのみの入力とチャットのユースケースにも、同様のアプローチを使用できます。
Kotlin
generateContentStream()
は suspend 関数であり、コルーチンのスコープから呼び出す必要があります。コルーチンに慣れていない場合は、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);
StringBuilder outputContent = new StringBuilder();
streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
@Override
public void onNext(GenerateContentResponse generateContentResponse) {
String chunk = generateContentResponse.getText();
outputContent.append(chunk);
}
@Override
public void onComplete() {
System.out.println(outputContent);
}
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
// ... other methods omitted for brevity
});
// Use streaming with multi-turn conversations (like chat)
ChatFutures chat = model.startChat(history);
Publisher<GenerateContentResponse> streamingResponse =
chat.sendMessageStream(inputContent);
StringBuilder outputContent = new StringBuilder();
streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
@Override
public void onNext(GenerateContentResponse generateContentResponse) {
String chunk = generateContentResponse.getText();
outputContent.append(chunk);
}
@Override
public void onComplete() {
System.out.println(outputContent);
}
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
// ... other methods omitted for brevity
});
高度なユースケースの実装
このチュートリアルの前のセクションで説明した一般的なユースケースは、Gemini API の使用に慣れるのに役立ちます。このセクションでは、より高度なとみなされる可能性のあるユースケースについて説明します。
関数呼び出し
関数呼び出しを使用すると、生成モデルから構造化データの出力を簡単に取得できます。これらの出力を使用して他の API を呼び出し、関連するレスポンス データをモデルに返すことができます。つまり、関数呼び出しを使用すると、生成モデルを外部システムに接続し、生成されたコンテンツに最新で正確な情報を含めることができます。詳細については、関数呼び出しのチュートリアルをご覧ください。
トークンをカウントする
長いプロンプトを使用する場合は、コンテンツをモデルに送信する前にトークンをカウントすると便利です。次の例は、さまざまなユースケースで countTokens()
を使用する方法を示しています。
Kotlin
countTokens()
は suspend 関数であり、コルーチンのスコープから呼び出す必要があります。コルーチンに慣れていない場合は、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(
// The Gemini 1.5 models are versatile and work with most use cases
modelName = "gemini-1.5-flash",
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();
// The Gemini 1.5 models are versatile and work with most use cases
GenerativeModel gm = new GenerativeModel(
"gemini-1.5-flash",
BuildConfig.apiKey,
generationConfig
);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);
安全性設定を使用する
安全性設定を使用すると、有害とみなされる可能性のあるレスポンスを受け取る可能性を調整できます。デフォルトでは、安全性設定により、すべての次元で安全でないコンテンツである確率が中程度または高いコンテンツがブロックされます。詳しくは、安全性設定をご覧ください。
安全性設定を 1 つ設定する方法は次のとおりです。
Kotlin
val generativeModel = GenerativeModel(
// The Gemini 1.5 models are versatile and work with most use cases
modelName = "gemini-1.5-flash",
apiKey = BuildConfig.apiKey,
safetySettings = listOf(
SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)
)
)
Java
SafetySetting harassmentSafety = new SafetySetting(HarmCategory.HARASSMENT,
BlockThreshold.ONLY_HIGH);
// The Gemini 1.5 models are versatile and work with most use cases
GenerativeModel gm = new GenerativeModel(
"gemini-1.5-flash",
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(
// The Gemini 1.5 models are versatile and work with most use cases
modelName = "gemini-1.5-flash",
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);
// The Gemini 1.5 models are versatile and work with most use cases
GenerativeModel gm = new GenerativeModel(
"gemini-1.5-flash",
BuildConfig.apiKey,
null, // generation config is optional
Arrays.asList(harassmentSafety, hateSpeechSafety)
);
GenerativeModelFutures model = GenerativeModelFutures.from(gm);
次のステップ
プロンプト設計は、言語モデルから望ましいレスポンスを引き出すプロンプトを作成するプロセスです。適切に構造化されたプロンプトを作成することは、言語モデルからの正確で高品質なレスポンスを実現するために不可欠な要素です。プロンプト作成のベスト プラクティスについて確認する。
Gemini には、入力の種類や複雑さ、チャットやその他のダイアログ言語タスクの実装、サイズの制約など、さまざまなユースケースのニーズを満たすために複数のモデルのバリエーションが用意されています。利用可能な Gemini モデルについて学習する。
このチュートリアルで説明する Android 用クライアント SDK を使用すると、Google のサーバーで実行される Gemini Pro モデルにアクセスできます。センシティブ データの処理やオフラインの可用性が含まれるユースケースや、頻繁に使用されるユーザーフローの費用削減が目的のユースケースでは、オンデバイスで実行される Gemini Nano へのアクセスを検討することをおすすめします。詳細については、Android(オンデバイス)チュートリアルをご覧ください。