本文将向您展示如何创建一个简单的基于OpenAI GPT-3.5-turbo的聊天助手。我们将使用Python Flask作为后端服务器,以及Flutter构建跨平台的客户端应用程序。
准备工作
确保您已经安装了以下工具和库:
- Python(3.x版本)
- Flutter
- OpenAI Python库(v0.27.0)
- Flask
安装Python库:
pip install openai flask
安装Flutter依赖:
flutter pub add http
flutter pub add provider
创建服务端(Flask)
首先,我们将使用Python和Flask框架搭建一个简单的服务端。在app.py
文件中,粘贴以下代码:
import json
from flask import Flask, request, jsonify
import openai
app = Flask(__name__)
openai.api_key = "your_openai_api_key"
# Store session data in a dictionary.
sessions = {}
@app.route("/chat", methods=["POST"])
def chat():
data = request.get_json()
session_id = data.get("session_id", "default_session")
user_message = data.get("message", "")
if session_id not in sessions:
sessions[session_id] = [{"role": "system", "content": "You are a helpful assistant."}]
sessions[session_id].append({"role": "user", "content": user_message})
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=sessions[session_id],
)
assistant_message = response.choices[0].message["content"]
sessions[session_id].append({"role": "assistant", "content": assistant_message})
return jsonify({"message": assistant_message})
if __name__ == "__main__":
app.run(debug=True)
将your_openai_api_key
替换为您的实际OpenAI API密钥。
现在,运行Flask应用程序:
python app.py
创建客户端(Flutter)
接下来,我们将创建一个简单的跨平台客户端应用程序,使用Flutter框架。将以下代码复制到lib/main.dart
文件中:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => ChatModel(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: ChatPage(),
);
}
}
class ChatPage extends StatelessWidget {
const ChatPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('GPT Assistant')),
body: Column(
children: [
const Expanded(child: ChatMessagesList()),
ChatInput(),
],
),
);
}
}
class ChatMessagesList extends StatelessWidget {
const ChatMessagesList({super.key});
@override
Widget build(BuildContext context) {
return Consumer<ChatModel>(
builder: (context, chatModel, child) {
return ListView.builder(
itemCount: chatModel.messages.length,
itemBuilder: (context, index) {
final message = chatModel.messages[index];
final isUser = message['role'] == 'user';
final textAlign = isUser ? TextAlign.right : TextAlign.left;
final text = '${message['content']}';
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
alignment: isUser ? Alignment.topRight : Alignment.topLeft,
child: Text(text, textAlign: textAlign),
);
},
);
},
);
}
}
class ChatInput extends StatelessWidget {
final TextEditingController _controller = TextEditingController();
ChatInput({super.key});
void _sendMessage(BuildContext context) async {
if (_controller.text.isNotEmpty) {
context.read<ChatModel>().addMessage('user', _controller.text);
final response = await GptApi(sessionId: 'example_session')
.getAssistantResponse(_controller.text);
if (kDebugMode) {
print(response);
}
context.read<ChatModel>().addMessage('assistant', response);
_controller.clear();
}
}
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: const InputDecoration(hintText: 'Type your message'),
onSubmitted: (value) => _sendMessage(context),
),
),
IconButton(
icon: const Icon(Icons.send),
onPressed: () => _sendMessage(context),
),
],
),
);
}
}
class ChatModel extends ChangeNotifier {
final List<Map<String, String>> _messages = [];
List<Map<String, String>> get messages => _messages;
void addMessage(String role, String content) {
_messages.add({'role': role, 'content': content});
notifyListeners();
}
}
class GptApi {
final String sessionId;
GptApi({required this.sessionId});
Future<String> getAssistantResponse(String message) async {
try {
final response = await http
.post(
Uri.parse('http://127.0.0.1:5000/chat'),
headers: {'Content-Type': 'application/json'},
body: json.encode({
'session_id': sessionId,
'message': message,
}),
).timeout(
const Duration(minutes: 2), // 设置超时时间为5秒
onTimeout: () {
// 当请求超时时执行的操作
throw TimeoutException("请求超时,请稍后重试");
},
);
if (response.statusCode == 200) {
return json.decode(response.body)['message'];
} else {
throw Exception('Failed to get response from GPT assistant');
}
} on TimeoutException catch (e) {
if (kDebugMode) {
print(e.message);
}
return e.message.toString();
} catch (e) {
if (kDebugMode) {
print("发生错误: $e");
}
return e.toString();
}
}
}
请将<your_server_address>
替换为您的Flask服务端的实际地址。
运行Flutter应用程序:
flutter create gpt_assistant
cd gpt_assistant
flutter run
现在,您已经成功搭建了一个简单的基于OpenAI GPT-3.5-turbo的聊天助手。客户端应用程序支持与服务端进行连续会话。当您与聊天助手互动时,它将记住之前的消息并在上下文中提供更有意义的回答。请确保Flask服务端正在运行,并根据需要更改客户端代码中的服务器地址。
如果你是第一次运行 flutter web 程序,可能遇到 xhttp error 的错误,请根据以下步骤解决
1- Go to `flutter\bin\cache` and remove a file named: `flutter_tools.stamp`
2- Go to `flutter\packages\flutter_tools\lib\src\web` and open the file `chrome.dart`.
3- Find `'--disable-extensions'`
4- Add `'--disable-web-security'`