Closed19

FlutterでAIアプリを作ってみる(google_generative_ai)

Yuta-KTDYuta-KTD

https://pub.dev/packages/google_generative_ai を使ったアプリを作ってみる
まずはサンプル動かすところまで
目標はポモドーロタイマーの休憩内容を提案する。みたいなことをやってみたい

Yuta-KTDYuta-KTD

公式の冒頭

なるほど、どんな手段でもGeminiAPIはサーバー側に隠蔽する方がいいと。

Yuta-KTDYuta-KTD

料金表
https://ai.google.dev/pricing?hl=ja

無料枠でGemini 1.5 Flashを使った時

  • 15 RPM(1 分あたりのリクエスト数)
  • 100 万 TPM(1 分あたりのトークン数)
  • 1,500 RPD(1 日あたりのリクエスト数)
Yuta-KTDYuta-KTD

[*] トークンは Gemini モデルで約 4 文字に相当します。100 トークンは約 60 ~ 80 英単語です。

[**] RPM: 1 分あたりのリクエスト数
TPM: 1 分あたりのトークン数
RPD: 1 日あたりのリクエスト数
TPD: 1 日あたりのトークン数

Yuta-KTDYuta-KTD
Yuta-KTDYuta-KTD

今回の目標では、前の会話のつながりとかは意識しなくてもいいから気にしないでおこうかな

Yuta-KTDYuta-KTD

サンプルアプリ上の構成について

  • GenerativeModel: モデルクラス。generateContent()でプロンプト送信が可能。画像とテキストをまとめて送ったりとかもできる
  • ChatSession: GenerativeModel.startChat() で返される。sendMessage()でテキストメッセージを送れる
    • sendMessage() で画像も送れないのか?
  • _generatedContent: ListViewで対話UIを表現するためのList、送信に使うものではない
Yuta-KTDYuta-KTD

ポモドーロタイマー簡単に作っちゃう

Yuta-KTDYuta-KTD

一旦こんな感じで Break Time のときに、そのタイミングで何をするかをGeminiに提案してもらう

Yuta-KTDYuta-KTD

作ってみた

  • 会話形式にしないと内容が被りがち
  • 3択もいらないかも(選ぶのが大変)
  • フォーマット揃えよう
  • (ローディングミスってる)
Yuta-KTDYuta-KTD
  • 会話形式にできるようにAsyncNotifierにして、更新時には前と違う内容を表示するように
  • 更新タイミングを休憩5秒前に裏で更新するようにして、ローディングを意識させないように

NotiferProviderの中身
break_idea_async_provider
import 'package:google_generative_ai/google_generative_ai.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../core/provider/gemini_model_provider.dart';

part 'break_idea_async_provider.g.dart';


class AsyncBreakIdea extends _$AsyncBreakIdea {
  late final ChatSession _chat;

  
  FutureOr<GenerateContentResponse> build() async {
    final GenerativeModel model = ref.read(geminiModelProvider);
    _chat = model.startChat();
    const message = '''
        ポモドーロタイマーの休憩のアイディアを1つ、30文字以内でください。
        5分以内にできることを考えてください。
        例: お茶を飲む
        ''';

    final response = await _chat.sendMessage(Content.text(message));
    return response;
  }

  Future<void> nextIdea() async {
    state = const AsyncLoading();
    state = await AsyncValue.guard(() async {
      final response = await _chat.sendMessage(Content.text('''
        ポモドーロタイマーの休憩のアイディアを1つ、30文字以内でください。
        先ほどとは異なるアイディアをお願いします。
        '''));
      return response;
    });
  }
}
Yuta-KTDYuta-KTD

一通り完了!

今後やりたいこと

  • サーバーサイドDartを介した呼び出し
  • ユーザーからのフィードバックを受けることで「専用の休憩提案」ができるようにする
    • 今の会話形式だと、会話を終了させた後、リセットさせる
    • 過去のデータをRAGみたいな感じで読み込ませることもきっとできるはず
このスクラップは5ヶ月前にクローズされました