chat_gpt_flutter 1.0.9 chat_gpt_flutter: ^1.0.9 copied to clipboard
ChatGPT API implemented in Flutter
import 'dart:async';
import 'dart:developer';
import 'package:chat_gpt_flutter/chat_gpt_flutter.dart';
import 'package:example/models/question_answer.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
inputDecorationTheme: InputDecorationTheme(
isDense: true,
fillColor: Colors.transparent,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: Colors.black, width: 2),
),
),
),
home: const MyHomePage(),
);
}
}
const apiKey = 'TEST API KEY';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String? answer;
final chatGpt = ChatGpt(apiKey: apiKey);
bool loading = false;
final testPrompt =
'Which Disney character famously leaves a glass slipper behind at a royal ball?';
final List<QuestionAnswer> questionAnswers = [];
late TextEditingController textEditingController;
StreamSubscription<StreamCompletionResponse>? streamSubscription;
@override
void initState() {
textEditingController = TextEditingController();
super.initState();
}
@override
void dispose() {
textEditingController.dispose();
streamSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("ChatGPT")),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Expanded(
child: ListView.separated(
itemCount: questionAnswers.length,
itemBuilder: (context, index) {
final questionAnswer = questionAnswers[index];
final answer = questionAnswer.answer.toString().trim();
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('Q: ${questionAnswer.question}'),
const SizedBox(height: 12),
if (answer.isEmpty && loading)
const Center(child: CircularProgressIndicator())
else
Text('A: $answer'),
],
);
},
separatorBuilder: (context, index) =>
const SizedBox(height: 12),
),
),
Row(
children: [
Expanded(
child: TextFormField(
controller: textEditingController,
decoration: const InputDecoration(hintText: 'Type in...'),
onFieldSubmitted: (_) => _sendMessage(),
),
),
const SizedBox(width: 12),
ClipOval(
child: Material(
color: Colors.blue, // Button color
child: InkWell(
onTap: _sendMessage,
child: const SizedBox(
width: 48,
height: 48,
child: Icon(
Icons.send_rounded,
color: Colors.white,
),
),
),
),
)
],
),
],
),
),
),
);
}
_sendMessage() async {
final question = textEditingController.text;
setState(() {
textEditingController.clear();
loading = true;
questionAnswers.add(
QuestionAnswer(
question: question,
answer: StringBuffer(),
),
);
});
final testRequest = CompletionRequest(
stream: true,
maxTokens: 4000,
messages: [Message(role: Role.user.name, content: question)],
);
await _streamResponse(testRequest);
setState(() => loading = false);
}
_streamResponse(CompletionRequest request) async {
streamSubscription?.cancel();
try {
final stream = await chatGpt.createChatCompletionStream(request);
streamSubscription = stream?.listen(
(event) => setState(
() {
if (event.streamMessageEnd) {
streamSubscription?.cancel();
} else {
return questionAnswers.last.answer.write(
event.choices?.first.delta?.content,
);
}
},
),
);
} catch (error) {
setState(() {
loading = false;
questionAnswers.last.answer.write("Error");
});
log("Error occurred: $error");
}
}
}