Flutter is a cross-platform mobile application development framework, and GetX is an easy-to-use state management and routing management tool in Flutter. In this article, we will use Flutter and GetX to implement a simple chat interface to interact with ChatGPT.
We need to import the GetX library in the Flutter project. pubspec.yaml
Add the following dependencies to the file :
dependencies:
flutter:
sdk: flutter
get:
main
Add the following code inside the function :
void main() {
//在main函数第一行添加这句话
WidgetsFlutterBinding.ensureInitialized();
runApp(GetMaterialApp(
home: ChatPage(),
));
}
Make sure Flutter Widgets
it's initialized and start the application's ChatPage
page.
Next, we need to create a ApiProvider
class for interacting with the OpenAI API. This class inherits from GetConnect
, GetConnect
and is a lightweight HTTP client that simplifies the communication process with the API. Here is ApiProvider
the code for the class:
class ApiProvider extends GetConnect {
/// 这里填写自己OpenAI API Key
final String apiKey = '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';
final String baseUrl = 'https://api.openai.com';
final Duration timeout = Duration(seconds: 30);
Map<String, String> _headers() {
return {
'Content-Type': 'application/json',
'Authorization': 'Bearer $apiKey',
};
}
ApiProvider() {
httpClient.baseUrl = baseUrl;
httpClient.timeout = timeout;
httpClient.addAuthenticator((request) {
request.headers.addAll(_headers());
return request;
});
}
Future<Response> completions(String body) {
return post('/v1/chat/completions', body);
}
}
In this class, we set the base URL and timeout of the API, and implement the authorization and authentication of HTTP requests. We also implemented completions
methods for sending requests to the OpenAI API and getting responses from the chatbot. Note that you need to set the API KEY of your own account here, address: https://platform.openai.com/account/api-keys
Next, we need to create a ChatLogic
class that will handle the chatbot logic. Here is ChatLogic类
the code for:
class ChatLogic extends GetxController {
final ChatState state = ChatState();
final ApiProvider provider = ApiProvider();
Future<void> sendMessage(String content) async {
state.requestStatus(content);
update();
final response = await provider.completions(json.encode({
"model": "gpt-3.5-turbo",
"messages": [{"role": "user", "content": "$content"}]
}));
try {
if(response.statusCode == 200) {
final data = response.body;
final text = data['choices'][0]['message']['content'];
state.responseStatus(text);
} else {
state.responseStatus(response.statusText ?? '请求错误,请稍后重试');
}
} catch(error) {
state.responseStatus(error.toString());
}
update();
}
}
In this class, we create a sendMessage
method that receives the user's message and sends it to the OpenAI API, and then waits for the API to return a response. After receiving the response, we will extract the content of the reply message from the JSON data returned by the API, update it to the list ChatState
of the status class messages
, and then display it in the UI.
Next, we need to create a ChatState
class to manage our application state. Here is ChatState
the code for the class:
class ChatState {
String message = '';
String sender = 'user';
bool isRequesting = false;
List<Map<String, dynamic>> messages = [];
void requestStatus(String content) {
messages.add({'text': content, 'sender': 'user'});
sender = 'bot';
messages.add({'text': '正在回复中...', 'sender': sender});
isRequesting = true;
message = '';
}
void responseStatus(String content) {
messages.removeLast(); // Remove "正在回复中..." 状态
messages.add({'text': content, 'sender': sender});
sender = 'user';
isRequesting = false;
}
}
In this class, the status information of the chat application is stored, including messages, senders, request status and history message list. requestStatus()
The method is used to update the state to reflect the state of the message being sent, and responseStatus()
the method is used to update the state to reflect the received message.
Finally, we define ChatPage
the class, which it inherits from StatelessWidget
, which will be used to display the chat dialog. Here is ChatPage
the code for the class:
class ChatPage extends StatelessWidget {
ChatPage({Key? key}) : super(key: key);
final logic = Get.put(ChatLogic());
final state = Get.find<ChatLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('你问我答'),
),
body: GetBuilder<ChatLogic>(
builder: (context) => Column(
children: [
Expanded(
child: ListView.builder(
itemCount: state.messages.length,
itemBuilder: (BuildContext context, int index) {
Map m = state.messages[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: m['sender'] == 'user'
? MainAxisAlignment.end
: MainAxisAlignment.start,
children: [
Flexible(
child: Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: m['sender'] == 'user'
? Colors.green[100]
: Colors.white,
),
child: Text(m['text']),
),
)
],
),
);
},
),
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.0),
topRight: Radius.circular(12.0),
),
),
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(
hintText: '请输入消息',
border: InputBorder.none,
),
controller:
TextEditingController(text: state.message),
onChanged: (value) {
state.message = value;
}),
),
),
IconButton(
icon: Icon(Icons.send),
onPressed: state.isRequesting
? null
: () {
logic.sendMessage(state.message);
},
),
],
),
),
],
),
),
);
}
}
The class contains an ChatLogic
instance and an ChatState
instance. In build()
the method, we wrap GetBuilder
the whole chat interface with . This interface consists of a message list and an input box where the user can enter a message and send it to the chatbot. ListView.builder
Used to display historical messages, TextField
and IconButton
to receive user input and send messages. Before sending a message, it is checked whether the current state is the request state to avoid sending the request repeatedly.
At this point, a simple chat function is completed, run it to see the effect:
To sum up, this article introduces a GPT-3 based chatbot implemented using Flutter and OpenAI API. With the implementation ApiProvider、ChatLogic
and ChatState
class, we were able to integrate the functionality of the OpenAI API into a Flutter application and implement a basic chat interface. Interested guys can try it out by themselves, Demo address: https://github.com/smallmarker/OpenAIChat