Dart アプリまたは Flutter アプリで Gemini API を使ってみる

このチュートリアルでは、Google AI Dart SDK を使用して、Dart アプリケーションまたは Flutter アプリケーションの Gemini API にアクセスする方法を説明します。アプリで Gemini モデルにアクセスするために REST API を直接操作したくない場合は、この SDK を使用できます。

このチュートリアルでは、次の方法について学びます。

さらに、このチュートリアルには、高度なユースケース(エンベディングトークンのカウントなど)と、コンテンツ生成の制御のためのオプションに関するセクションも含まれています。

前提条件

このチュートリアルは、Dart を使用したアプリケーションの構築に精通していることを前提としています。

このチュートリアルを完了するには、開発環境が次の要件を満たしていることを確認してください。

  • Dart 3.2.0 以降

プロジェクトを設定する

Gemini API を呼び出す前に、プロジェクトをセットアップする必要があります。これには、API キーの設定、パブリッシャーの依存関係への SDK の追加、モデルの初期化が含まれます。

API キーを設定する

Gemini API を使用するには、API キーが必要です。まだ作成していない場合は、Google AI Studio でキーを作成します。

API キーを取得する

API キーを保護する

API キーのセキュリティを確保します。API キーをコードに直接含めないことや、キーを含むファイルをバージョン管理システムにチェックしないことを強くおすすめします。代わりに、API キーには Secret ストアを使用してください。

このチュートリアルのすべてのスニペットは、プロセス環境変数として API キーにアクセスすることを前提としています。Flutter アプリを開発している場合は、アプリの実行時にプロセス環境が異なるため、String.fromEnvironment を使用して --dart-define=API_KEY=$API_KEYflutter build または flutter run に渡して API キーでコンパイルできます。

SDK パッケージをインストールする

独自のアプリケーションで Gemini API を使用するには、Dart または Flutter アプリに google_generative_ai パッケージを add する必要があります。

Dart

dart pub add google_generative_ai

フラッター

flutter pub add google_generative_ai

生成モデルの初期化

API 呼び出しを行うには、生成モデルをインポートして初期化しておく必要があります。

import 'package:google_generative_ai/google_generative_ai.dart';

// Access your API key as an environment variable (see "Set up your API key" above)
final apiKey = Platform.environment['API_KEY'];
if (apiKey == null) {
  print('No \$API_KEY environment variable');
  exit(1);
}

final model = GenerativeModel(model: 'MODEL_NAME', apiKey: apiKey);

モデルを指定する際は、次の点に注意してください。

  • ユースケースに固有のモデルを使用します(たとえば、gemini-pro-vision はマルチモーダル入力に使用します)。このガイドでは、各実装の手順に、各ユースケースで推奨されるモデルを示します。

一般的なユースケースの実装

プロジェクトを設定したら、Gemini API を使用してさまざまなユースケースを実装してみましょう。

高度なユースケースのセクションでは、Gemini API とエンベディングに関する情報を確認できます。

テキストのみの入力からテキストを生成する

プロンプト入力にテキストのみが含まれている場合は、generateContent メソッドで gemini-pro モデルを使用して、テキスト出力を生成します。

import 'dart:io';

import 'package:google_generative_ai/google_generative_ai.dart';

void main() async {
  // Access your API key as an environment variable (see "Set up your API key" above)
  final apiKey = Platform.environment['API_KEY'];
  if (apiKey == null) {
    print('No \$API_KEY environment variable');
    exit(1);
  }
  // For text-only input, use the gemini-pro model
  final model = GenerativeModel(model: 'gemini-pro', apiKey: apiKey);
  final content = [Content.text('Write a story about a magic backpack.')];
  final response = await model.generateContent(content);
  print(response.text);
}

テキストと画像の入力からテキストを生成する(マルチモーダル)

Gemini にはマルチモーダル モデル(gemini-pro-vision)が用意されているため、テキストと画像の両方を入力できます。入力の画像の要件を確認してください。

プロンプト入力にテキストと画像の両方が含まれている場合は、generateContent メソッドで gemini-pro-vision モデルを使用して、テキスト出力を生成します。

import 'dart:io';

import 'package:google_generative_ai/google_generative_ai.dart';

void main() async {
  // Access your API key as an environment variable (see "Set up your API key" above)
  final apiKey = Platform.environment['API_KEY'];
  if (apiKey == null) {
    print('No \$API_KEY environment variable');
    exit(1);
  }
  // For text-and-image input (multimodal), use the gemini-pro-vision model
  final model = GenerativeModel(model: 'gemini-pro-vision', apiKey: apiKey);
  final (firstImage, secondImage) = await (
    File('image0.jpg').readAsBytes(),
    File('image1.jpg').readAsBytes()
  ).wait;
  final prompt = TextPart("What's different between these pictures?");
  final imageParts = [
    DataPart('image/jpeg', firstImage),
    DataPart('image/jpeg', secondImage),
  ];
  final response = await model.generateContent([
    Content.multi([prompt, ...imageParts])
  ]);
  print(response.text);
}

マルチターンの会話の構築(チャット)

Gemini を使用すると、複数のターンにわたる自由形式の会話を構築できます。SDK は会話の状態を管理することでプロセスを簡素化するため、generateContent とは異なり、会話履歴を自分で保存する必要はありません。

マルチターンの会話(チャットなど)を構築するには、gemini-pro モデルを使用し、startChat() を呼び出してチャットを初期化します。次に、sendMessage() を使用して新しいユーザー メッセージを送信します。これにより、メッセージとレスポンスもチャット履歴に追加されます。

会話のコンテンツに関連付けられた role には、次の 2 つのオプションがあります。

  • user: プロンプトを提供するロール。この値は sendMessage 呼び出しのデフォルトです。別のロールが渡されると、この関数は例外をスローします。

  • model: レスポンスを提供するロール。このロールは、既存の historystartChat() を呼び出すときに使用できます。

import 'dart:io';

import 'package:google_generative_ai/google_generative_ai.dart';

Future<void> main() async {
  // Access your API key as an environment variable (see "Set up your API key" above)
  final apiKey = Platform.environment['API_KEY'];
  if (apiKey == null) {
    print('No \$API_KEY environment variable');
    exit(1);
  }
  // For text-only input, use the gemini-pro model
  final model = GenerativeModel(
      model: 'gemini-pro',
      apiKey: apiKey,
      generationConfig: GenerationConfig(maxOutputTokens: 100));
  // Initialize the chat
  final chat = model.startChat(history: [
    Content.text('Hello, I have 2 dogs in my house.'),
    Content.model([TextPart('Great to meet you. What would you like to know?')])
  ]);
  var content = Content.text('How many paws are in my house?');
  var response = await chat.sendMessage(content);
  print(response.text);
}

ストリーミングを使用してインタラクションを高速化する

デフォルトでは、モデルは生成プロセス全体を完了するとレスポンスを返します。結果全体を待機するのではなく、ストリーミングを使用して部分的な結果を処理することで、より高速なインタラクションを実現できます。

次の例は、generateContentStream メソッドを使用してストリーミングを実装し、テキストと画像の入力プロンプトからテキストを生成する方法を示しています。

// ...

final response = model.generateContentStream([
  Content.multi([prompt, ...imageParts])
]);
await for (final chunk in response) {
  print(chunk.text);
}

// ...

テキストのみの入力とチャットのユースケースにも、同様のアプローチを使用できます。

// Use streaming with text-only input
final response = model.generateContentStream(content);
// Use streaming with multi-turn conversations (like chat)
final response = chat.sendMessageStream(content);

高度なユースケースの実装

このチュートリアルの前のセクションで説明した一般的なユースケースを習得することで、Gemini API を使いやすくなります。このセクションでは、より高度とみなされるユースケースについて説明します。

エンベディングを使用する

エンベディングは、情報を配列内の浮動小数点数のリストとして表すために使用される手法です。Gemini では、テキスト(単語、文、テキスト ブロック)をベクトル化された形式で表現できるため、エンベディングの比較や対比が容易になります。たとえば、類似した主題または感情を共有する 2 つのテキストは、エンベディングが類似している必要があります。エンベディングは、コサイン類似度などの数学的比較手法で識別できます。

embedding-001 モデルを embedContent メソッド(または batchEmbedContent メソッド)とともに使用して、エンベディングを生成します。次の例では、単一の文字列のエンベディングを生成します。

final model = GenerativeModel(model: 'embedding-001', apiKey: apiKey);
final content = Content.text('The quick brown fox jumps over the lazy dog.');
final result = await model.embedContent(content);
print(result.embedding.values);

トークンをカウントする

長いプロンプトを使用する場合は、コンテンツをモデルに送信する前にトークンをカウントすると便利な場合があります。次の例は、さまざまなユースケースで countTokens() を使用する方法を示しています。

// For text-only input
final tokenCount = await model.countTokens(Content.text(prompt));
print('Token count: ${tokenCount.totalTokens}');
// For text-and-image input (multimodal)
final tokenCount = await model.countTokens([
  Content.multi([prompt, ...imageParts])
]);
print('Token count: ${tokenCount.totalTokens}');
// For multi-turn conversations (like chat)
final prompt = Content.text(message);
final allContent = [...chat.history, prompt];
final tokenCount = await model.countTokens(allContent);
print('Token count: ${tokenCount.totalTokens}');

コンテンツ生成を制御するオプション

コンテンツの生成を制御するには、モデル パラメータを構成し、安全性設定を使用します。

generationConfig または safetySettings をモデル リクエストのメソッド(generateContent など)に渡すと、getGenerativeModel で渡された同じ名前の構成オブジェクトが完全にオーバーライドされます。

モデル パラメータを構成する

モデルに送信するすべてのプロンプトには、モデルがどのようにレスポンスを生成するかを制御するパラメータ値が含まれています。このモデルは、パラメータ値によって異なる結果を生成できます。詳細については、モデル パラメータをご覧ください。この構成は、モデル インスタンスの存続期間中は維持されます。

final generationConfig = GenerationConfig(
  stopSequences: ["red"],
  maxOutputTokens: 200,
  temperature: 0.9,
  topP: 0.1,
  topK: 16,
);
final model = GenerativeModel(
  model: 'MODEL_NAME',
  apiKey: apiKey,
  generationConfig: generationConfig,
);

安全性設定を使用する

安全性設定を使用して、有害とみなされる可能性のあるレスポンスを受け取る可能性を調整できます。デフォルトでは、安全性設定により、すべての次元において安全でないコンテンツである可能性が高いコンテンツが中程度または高い確率でブロックされます。詳しくは、安全性設定をご覧ください。

安全性に関する設定を 1 つ設定する方法は次のとおりです。

final safetySettings = [
  SafetySetting(HarmCategory.harassment, HarmBlockThreshold.high)
];
final model = GenerativeModel(
  model: 'MODEL_NAME',
  apiKey: apiKey,
  safetySettings: safetySettings,
);

複数の安全性設定を指定することもできます。

final safetySettings = [
  SafetySetting(HarmCategory.harassment, HarmBlockThreshold.high),
  SafetySetting(HarmCategory.hateSpeech, HarmBlockThreshold.high),
];

次のステップ

  • プロンプト設計は、言語モデルから望ましいレスポンスを引き出すプロンプトを作成するプロセスです。適切に構造化されたプロンプトを作成することは、言語モデルからの正確で高品質なレスポンスを実現するための不可欠な要素です。プロンプト作成のベスト プラクティスについて学習する。

  • Gemini には、入力タイプと複雑さ、チャットやその他のダイアログ言語タスクの実装、サイズの制約など、さまざまなユースケースのニーズを満たす複数のモデル バリエーションが用意されています。利用可能な Gemini モデルをご確認ください。

  • Gemini には、レート制限の引き上げをリクエストするオプションが用意されています。Genmini Pro モデルのレート制限は 60 リクエスト/分(RPM)です。