🐨
FlutterアプリでGPTからのレスポンスをリアルタイムに表示する方法
やりたいこと
Flutterで作っているChatアプリを作成しています。
MicrosoftのBing Chatみたいに、GPTからのレスポンスをストリーミングで表示させたいので、方法を調べてみました。
前提
1. API側について
API側は既にストリーミングでレスポンスをするように処理をしています。
こちらの記事で実装してますので参考までに。
2. アプリの基礎実装
実装はこちらの記事で作ったチャットアプリをベースにやっていきます。
実装
httpのPOSTリクエストで送った後にlisten
でレスポンスをリアルタイムで受け取るようにします。
先に全体
main.dart
Future<void> requestMessageToGPTApi(requestMessage) async {
setState(() {
messageList.add({
'role': 'user',
'message': requestMessage,
});
});
_textController.clear();
final client = http.Client();
final url = Uri.parse("<your endpoint>");
var request = http.Request(
'POST',
url,
);
Map<String, String> headers = {
'content-type': 'application/json; charset=UTF-8',
'accept': 'text/event-stream',
};
final body = json.encode({'message': requestMessage});
request.headers.addAll(header);
request.body = json.encode(body);
setState(() {
messageList.add({
"role": "copilot",
"message": "",
});
});
final http.StreamedResponse response = await client.send(request);
response.stream.transform(const Utf8Decoder()).listen((data) {
setState(() {
messageList.last["message"] = messageList.last["message"] + data;
});
});
}
1. Clientをインスタンス化
http.post
でリクエストを送っていましたが、Clientをインスタンス化して、そこから送るように修正します。
また、header情報として新たに「'accept' : 'text/event-stream'」を追加します。
main.dart
final client = http.Client();
final url = Uri.parse("<your endpoint>");
var request = http.Request(
'POST',
url,
);
Map<String, String> headers = {
'content-type': 'application/json; charset=UTF-8',
// 追加
'accept': 'text/event-stream',
};
final body = json.encode({'message': requestMessage});
request.headers.addAll(header);
request.body = json.encode(body);
2. APIに送信
先にmessageListに空文字で追加して、後から文字を足していくようにします。
受け取る方は「http.StreamedResponse」にしてください。
main.dart
setState(() {
messageList.add({
"role": "copilot",
"message": "",
});
});
final http.StreamedResponse response = await client.send(request);
3. レスポンスを受け取る
レスポンスの情報をlisten
することでリアルタイムにデータが返ってきます。
返ってきたテキストを先ほど追加したmessageListのmessageにどんどん追加していきます。
この辺りはもっと最適な実装でやったほうがいいですが、今回はデモなのでこれでいきます。
main.dart
response.stream.transform(const Utf8Decoder()).listen((data) {
setState(() {
messageList.last["message"] = messageList.last["message"] + data;
});
});
検証
上手くできました。
Discussion