【Flutter】ChatGPTに質問する

Udemyで講座リリースしました!(←クーポン付きリンク)

対象者

  • Flutterの基礎ができている人
  • ChatGPTでQ&A形式のアプリが作りたい人

はじめに

ChatGPTは、OpenAIが2022年11月に発表したチャットボットです。OpenAIの大規模言語モデルGPT-3.5ファミリーの上に構築されており、教師あり学習と強化学習の両方の手法で細かく調整されています。
この記事では、FlutterからChatGPTのQ&A形式を実装する方法を紹介しています。Flutter用にChatGPTのパッケージが多数出ておりますが、今回は「chat_gpt_sdk 」を使用します。(前の記事とは別のパッケージです) 理由は、記事作成時点で35時間前にアップデートがあったので、一番更新されていそうだったからです。また、バージョンが2だったので、1回書き直したかな、きっと改善されたに違いないと思われるからです。

APIキーを取得する

  • https://openai.com/に行く
  • アカウントを作成する
  • 右上のアカウントのマークを押し、リストの中から「View API keys」を選択する
  • 「API Keys」にある「+ Create new secret key」を押す
  • API Keyが作られるので、コピーする(生成時にしか、コピーはできないと思われる)

実装

それでは実装していきます。

インストール

flutter pub add chat_gpt_sdk
flutter pub get

インスタンスの作成

OpenAPI接続用のインスタンスを作成します。
kOpenApiKey: APIキーを設定します
baseOption: 内部的にDioを使用しているので、Dioに関連しているbaseOptionsだと思います。receiveTimeoutで 制限時間を設定してます(今回は60秒)。
isLogger: trueにしておくとデバッグ欄に状況が出力されます

final openAI = OpenAI.instance.build(
    token: kOpenApiKey,
    baseOption: HttpSetup(receiveTimeout: 60 * 1000),
    isLogger: true,
);

ChatGPTに質問して、返信を取得

Q&A形式はCompleteTextを使います。
prompt: 質問する内容
model: AIのモデル
maxTokens: 一度にモデルに与えられる最大トークン数を指します。トークンとは、文章を構成する最小単位であり、一般的には単語や句読点などです。(←ChatGPT談) 長すぎる文章を渡すと時間が掛かりすぎるため、制限を掛けるそうです。

openApi.onCompleteTextで質問します。返信のchoices.first.textに回答が入ってます。
choicesが複数形なので、複数の回答がもらえるのかなと思ったのですが、1つしか入ってませんでした。

  Future<String> _sendMessage(String message) async {
    final request = CompleteText(
      prompt: message,
      model: kTranslateModelV3,
      maxTokens: 200,
    );

    final response = await openAI.onCompleteText(request: request);
    return response!.choices.first.text;
  }

全ソース

以下、だいたいコピペでいける全ソースです。
[writeYourOpenAPIKey]は書き換えてください。

import 'package:chat_gpt_sdk/chat_gpt_sdk.dart';
import 'package:flutter/material.dart';
import 'api_key.dart';

const kOpenApiKey = writeYourOpenAPIKey;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter ChatGPT Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _answer = '';
  var _isLoading = false;

  final _textEditingController =
      TextEditingController(text: 'What is Flutter?');

  final openAI = OpenAI.instance.build(
    token: kOpenApiKey,
    baseOption: HttpSetup(),
    isLog: true,
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          children: [
            Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _textEditingController,
                    decoration: const InputDecoration(
                      enabledBorder: OutlineInputBorder(),
                    ),
                  ),
                ),
                IconButton(
                  onPressed: () async {
                    setState(() {
                      _isLoading = true;
                    });
                    final answer = await _sendMessage(
                      _textEditingController.text,
                    );
                    setState(() {
                      _answer = answer;
                      _isLoading = false;
                    });
                    ;
                  },
                  icon: Icon(
                    _isLoading ? Icons.timer : Icons.send,
                  ),
                ),
              ],
            ),
            Text(_answer),
          ],
        ),
      ),
    );
  }

  Future<String> _sendMessage(String message) async {
    final request = CompleteText(
      prompt: message,
      model: Model.textDavinci3,
      maxTokens: 200,
    );

    final response = await openAI.onCompletion(
      request: request,
    );
    return response!.choices.first.text;
  }
}

まとめ

ChatGPTをFlutterで使用できるようにしました。今(2023年2月現在)の企業のチャットボットって、ユーザの入力に対して決まった質問の一覧を検索するだけで、役に立たないことが多いと感じてます。そういったチャットボットがChatGPTで一掃されるといいですね。

参考