ChatGPTをflutterにシンプルに実装してみる　　

### 概要
flutterにchatgptを実装する記事があまりなかったので必要最低限で実装してまとめてみようと思います。

### どんなアプリにするか
　└テキストフィールドに質問を入力し、送信ボタンを押すと解答がchatgptより得られる。
 こんな簡単なアプリです！
 
 retrofitでAPI通信を実装したこともあるのですが、どうやらパッケージが既にあったのでせっかくということで下記を使用してみることに。
 https://pub.dev/packages/dart_openai


 まずは完成画面から↓
 <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618536/a6db726c-5b2d-c597-eba1-a2f4569c462d.png" width="300"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618536/a3f66fe3-6f7d-ea94-709b-86905e56a271.png" width="300">

日本語のルーツを聞いたのに結果は失われた物を見つけるためのいくつかの方法が書かれています。笑
精度や英語は今回無視していこうと思います。


 
まずは簡単にUIを作成する
というより、簡単にまとまりすぎたので1ページにまとめました
#### ※ファイル分けとかは気にせずまとめるので各自のアーキテクチャーに落とし込んでください
#### ※なぜか返信が英語のみなのでそこは今回は一旦流しておきます
``` 
import 'package:dart_openai/dart_openai.dart';
import 'package:flutter/material.dart';


void main() {
  OpenAI.apiKey = '各自のAPIキー';
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const ChatScreen(),
    );
  }
}

class ChatScreen extends StatefulWidget {
  const ChatScreen({Key? key}) : super(key: key);

  @override
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final TextEditingController _controller = TextEditingController();
  String _response = '';

  void _sendMessage() async {
    if (_controller.text.isNotEmpty) {

      final chatCompletion = await OpenAI.instance.chat.create(
        model: "gpt-3.5-turbo",
        messages: [
          const OpenAIChatCompletionChoiceMessageModel(
            content: [],
            role: OpenAIChatMessageRole.user,
          ),
        ],
      );
      setState(() {
        if (chatCompletion.choices.isNotEmpty && chatCompletion.choices.first.message.content != null) {
          _response = chatCompletion.choices.first.message.content!.map((item) => item.text).join('\n');
        }
      });
      _controller.clear();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ChatGPT Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            Expanded(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(_response),
              ),
            ),
            TextField(
              controller: _controller,
              decoration: InputDecoration(
                labelText: '質問を入力',
                suffixIcon: IconButton(
                  icon: const Icon(Icons.send),
                  onPressed: _sendMessage,
                ),
              ),
              onSubmitted: (value) => _sendMessage(),
            ),
          ],
        ),
      ),
    );
  }
}
````

大体難しいことはないのですが、注目すべきは下記かと思います。
```
void _sendMessage() async {
    if (_controller.text.isNotEmpty) {

      final chatCompletion = await OpenAI.instance.chat.create(
        model: "gpt-3.5-turbo",
        //chatgptのモデルを指定
        
        messages: [
          const OpenAIChatCompletionChoiceMessageModel(
            content: [],
            role: OpenAIChatMessageRole.user,

            //contentに送信したいメッセージ
            //rollにはchatgptに何者になってほしいかを指定する　
            //結構色々あるみたいだが今回は割愛,,
            
          ),
        ],
      );
    }
  }
  ````

retrofit, dio, あたりを使用してAPIの通信をしたサイト比べるとかなり簡略化されていますので基本はこのパッケージを使うのが良いかもです。。

また、冒頭にも書いた通り返答がなぜか英語なのでそこはパッケージまたはAPIドキュメントを読む必要があります。
APIを使用した際は言語の設定などはしておらず、トイアカけた言葉に応じて言語が変わっていたのでおそらくパッケージの仕様か設定がどこかにあるはずです、、、

## まとめ
パッケージを利用して作る場合のサンプルコードとして今回のコードをいじって各自作りたいもののベースとなれば本望です！

（シンプルにまとめたかったのにコードや記事が長くなり4回書き直しました㊙️）