メニューを閉じる

テクノデジタルグループ

メニューを開く

2024.06.24

開発環境・ツール

Flutter + Geminiで簡単なアプリケーションを作ってみた

はじめに

この記事では、以前にも記事を書いたFlutterと少し前に話題になった言語生成AIモデル、Geminiを使って簡単なアプリケーションを作成しようと思います。


完成イメージとしては、上記のようにメッセージをテキストフィールドに入力して「送信」ボタンを押下することでGeminiからのレスポンスを取得して表示させるチャットボットのようなものです。

Geminiとは …

2023年12月にGoogleから発表されたマルチモーダル生成AIです。
料金やモデルが適宜更新されているので、最新の情報は公式ドキュメントを参照してください。

Gemini APIの準備

APIキーの取得
まずGoogle AI StudioからAPIキーを取得します。
取得するにはGoogleアカウントが必要です。
Google AI Studioの「Create API Key」から簡単にAPIキーを取得できます。

Flutter側の準備

Gemini APIを呼び出すまでにいくつかFlutter側で準備を施しておきましょう。
まず、プロジェクトの構造は以下のようになります。

gemini_app/
 ├ .env
 ├ pubspec.yaml
 ├ lib /
 │ └ main.dart
 │ └ controllers /
 │   └ chat_controller.dart
 │ └ models /
 │   └ chat_message.dart
 │ └ views /
 │   └ chat_page.dart
 ├ その他ファイル

必要なパッケージをインストール

Flutterでは便利なパッケージがpub.devで公開されています。
今回は「google_generative_ai」というGoogleが公開しているパッケージを利用します。

まずpubspec.yamlファイルに以下を追加します。
pubspec.yamlはFlutterプロジェクトの管理ファイルで、アプリケーションの名前、説明、バージョン情報や、プロジェクトが依存するパッケージ情報を設定します。
パッケージのバージョンは適宜変更してください。

pubspec.yaml

dependencies:
  google_generative_ai: ^0.3.1 // 
  flutter_dotenv: ^5.1.0 // .env使用に必要

最後に下記コマンドでパッケージをインストールします。

flutter pub get

コードの作成

今回はFlutterのオーソドックスな状態管理パターンであるStateful Widget Patternを使用し、APIキーは.envで管理します。今回は簡単化のために.envの詳しい説明は割愛します。

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:gemini_app/views/chat_page.dart';

Future<void> main() async { // エントリーポイント
  WidgetsFlutterBinding.ensureInitialized();
  await dotenv.load(fileName: ".env"); // .envを読み込む
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp( // ルートウィジェット
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const ChatPage(), // アプリのホームとしてChatPageを設定
    );
  }
}

chat_controller.dart

import 'dart:developer';
import 'package:flutter_dotenv/flutter_dotenv.dart'; // .envを利用するために必要なパッケージ
import 'package:google_generative_ai/google_generative_ai.dart'; //Geminiを利用するために必要なパッケージ
import '../models/chat_message.dart'; //チャットメッセージモデル

class ChatController {
  late GenerativeModel _generativeModel;
  final List<ChatMessage> _messages = []; //メッセージを格納する配列

  ChatController() {
    _initializeGenerativeModel();
  }

  void _initializeGenerativeModel() async {
    try {
      final apiKey = dotenv.env['API_KEY'];// apiキーをenvから取得
      if (apiKey == null) {
        print('API_KEY is not set in .env');
        return;
      }

      _generativeModel = GenerativeModel(model: 'gemini-pro', apiKey: apiKey); // apiキーとモデルを指定してインスタンスを生成
    } catch (e) {
      print('Error initializing Generative Model: $e');
    }
  }

  Future<void> onSendPressed(setState, textController) async { // 送信ボタン押下時のメソッド
    final text = textController.text;
    sendMessage(text); // コントローラーでメッセージを送信
    setState(() {}); // UIを更新
    await fetchMessage(text); // メッセージ取得
    setState(() {}); // UIを更新
  }

  Future<void> sendMessage(String text) async { // メッセージ送信メソッド
    if (text.isEmpty) {
      return;
    }
    _messages.add(ChatMessage(sender: 'User', text: text)); // ユーザーのメッセージを追加
  }

  Future<void> fetchMessage(String text) async { // メッセージ受信メソッド
    if (text.isEmpty) {
      return;
    }
    try {
      final response = await _generativeModel.generateContent([Content.text(text)]);
      final geminiText = response.text ?? 'No response text';
      _messages.add(ChatMessage(sender: 'Gemini', text: geminiText)); // Geminiからのメッセージを追加
    } catch (e) {
      print('Error generating response: $e');
    }
  }

  List<ChatMessage> get messages => _messages; // メッセージのリストを取得
}

chat_page.dart

import 'package:flutter/material.dart';
import '../controllers/chat_controller.dart';

class ChatPage extends StatefulWidget {
  const ChatPage({super.key});

  @override
  State<ChatPage> createState() => _ChatPageState();
}

class _ChatPageState extends State<ChatPage> {
  final ChatController _chatController = ChatController();
  final TextEditingController _textController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Chat with Gemini'),
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              itemCount: _chatController.messages.length,
              itemBuilder: (context, index) {
                final message = _chatController.messages[index];
                return ListTile(
                  title: Text('${message.sender}: ${message.text}'),
                );
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField( // メッセージ入力フィールド
                    controller: _textController,
                    decoration: const InputDecoration(
                      labelText: 'Type a message...',
                    ),
                  ),
                ),
                IconButton( // 送信ボタン
                  icon: const Icon(Icons.send),
                  onPressed: ()=> _chatController.onSendPressed(setState, _textController), 
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

chat_message.dart

class ChatMessage { //チャットメッセージモデル
  final String sender;
  final String text;

  ChatMessage({required this.sender, required this.text});
}

ビルド&実行

今回は実行先プラットフォームをWindowsに指定して、Android Studioの「Run」ボタンをクリックして実行してみます。

実行結果

冒頭で説明した簡易的なアプリケーションを作成することができました。

まとめ

今回は、Geminiにリクエストを送信してレスポンスを表示させる簡単なアプリケーションを作成しました。DB等を利用すれば履歴を保存したり簡易的なチャットボットのような使い方も可能です。

また、今回作成したものは最低限なのでチャット風にするなどレイアウトを整えたりすると使いやすくなると思います。

最後に、たったこれだけで生成AIの導入ができてびっくりしているのが正直な所です。
みなさんもぜひ試してみてください。


【記事への感想募集中!】

記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!
  • こんな記事が読んでみたい、こんなことが知りたい、調べてほしい!という意見も募集中!
  • いただいた感想は今後の記事に活かしたいと思います!

感想フォームはこちら


【テクノデジタルではエンジニア/デザイナーを積極採用中です!】

下記項目に1つでも当てはまる方は是非、詳細ページへ!
  • 自分でアプリを作ってみたい
  • ITで世の中にワクワクを生み出したい
  • 使いやすさ、デザインにこだわったWebサイトを開発したい

採用情報の詳細はこちら


Qangaroo(カンガルー)

  • 徹底した見やすさと優れた操作性で、テストの「見える化」を実現。
  • テストの進捗が見える。開発がスマートに進む。
  • クラウド型テスト管理ツール『Qangaroo(カンガルー)』

【テクノデジタルのインフラサービス】

当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。

https://www.tcdigital.jp/infrastructure/

最近の記事