우선 flutter 에서 chat GPT 를 사용하려면 이 링크에 들어가서 API Key를 발급 받아야 한다. 사이트에 접속 후, 로그인/회원가입을 한 후 , 우측 상단의 Personal 클릭 , View API keys 클릭.
여기서 Create new secret key 를 누르고 발급 받으면 된다.
http 패키지가 필요하므로, 먼저 pubspec.yaml파일에 http 패키지를 추가해 주어야 한다.
Future<String> generateResponse(String input) async {
String token = "Bearer 네이티브 앱 키";
var response = await http.post(
Uri.parse(
"https://api.openai.com/v1/engines/text-davinci-003/completions"),
headers: {
"Content-Type": "application/json",
"Authorization": token,
},
body: jsonEncode({
"prompt": input,
"temperature": 0.5,
"max_tokens": 50,
"top_p": 1,
"frequency_penalty": 0,
"presence_penalty": 0
}));
if (response.statusCode == 200) {
Map<String, dynamic> data = jsonDecode(utf8.decode(response.bodyBytes));
String text = data["choices"][0]["text"].toString().trim();
return text;
} else {
throw Exception("Failed to generate response: ${response.statusCode}");
}
}
pub.dev 에 sdk 가 있지만 나는 그 라이브러리를 사용하지 않고 해보려고 한다.
( chat_gpt_sdk / pub.dev <= 라이브러리 사용방법을 볼 수 있음 )
prompt : ChatGPT에게 전달할 사용자 질문을 뜻한다.
temperature : 응답 생성 시 사용되는 온도 값으로, 온도가 높을수록 다양한 응답을 생성한다. 그만큼 불일치한 응답을 생성할 가능성도 높아진다고 한다. (기본값: 0.5)
max_tokens : 생성되는 응답의 최대 길이를 나타낸다. (기본값: 50)
top_p : 응답 생성 시 사용되는 확률 분포의 상위 p%를 사용한다. (기본값: 1)
frequency_penalty : 빈번한 단어나 구문을 생성하는 것을 방지하는데 사용된다. (기본값: 0)
presence_penalty : 특정 키워드를 포함하지 않는 응답을 생성하는 것을 방지하는 데 사용된다. (기본값: 0)
이러한 설정들은 본인이 사용하고자 하는 목적에 따라 조절하여 사용하면 될 것 같다!
import 'package:chat_gpt/model/message_model.dart';
import 'package:flutter/material.dart';
import 'chatMessage.dart';
import 'controller/gpt_controller.dart';
class ChatBotScreen extends StatefulWidget {
const ChatBotScreen({super.key});
@override
State<ChatBotScreen> createState() => _ChatBotScreenState();
}
class _ChatBotScreenState extends State<ChatBotScreen> {
final TextEditingController _controller = TextEditingController();
final List<MessageModel> _message = [];
void _sendMessage(String text) async {
setState(() {
_message.add(MessageModel(
userMessage: text, botMessage: '', messageType: MessageType.user));
isLoding = true;
});
String response = await generateResponse(text);
setState(() {
_message.add(MessageModel(
userMessage: '', botMessage: response, messageType: MessageType.bot));
isLoding = false;
});
_controller.clear();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xff343541),
appBar: AppBar(
backgroundColor: const Color(0xff444654),
title: const Text("chatGPT ChatBot"),
centerTitle: true,
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _message.length,
itemBuilder: (context, index) {
var message = _message[index];
return ChatMessageWidget(
userMessage: message.userMessage,
botMessage: message.botMessage,
messageType: message.messageType);
},
),
),
Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8),
child: TextField(
controller: _controller,
decoration: const InputDecoration(
hintText: "메세지를 입력하세요! ",
fillColor: Color(0xff444654),
filled: true,
border: InputBorder.none,
),
),
),
),
IconButton(
onPressed: () {
_sendMessage(_controller.text);
},
icon: const Icon(
Icons.send,
color: Color.fromRGBO(142, 142, 160, 1),
))
],
)
],
),
);
}
}
import 'package:chat_gpt/model/message_model.dart';
import 'package:flutter/material.dart';
class ChatMessageWidget extends StatelessWidget {
final String userMessage;
final String botMessage;
final MessageType messageType;
const ChatMessageWidget(
{required this.userMessage,
required this.botMessage,
required this.messageType,
super.key});
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 10),
padding: const EdgeInsets.all(16),
color: messageType == MessageType.user
? const Color(0xff343541)
: const Color(0xff444654),
child: Row(
children: [
messageType == MessageType.user
? Container(
margin: const EdgeInsets.only(right: 16),
child: const CircleAvatar(
child: Icon(Icons.person),
),
)
: const CircleAvatar(
backgroundColor: Color.fromRGBO(16, 163, 127, 1),
),
// Image.asset(
// '',
// color: Colors.white,
// scale: 1.5,
// ),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
child: messageType == MessageType.user
? Text(
userMessage,
style: Theme.of(context)
.textTheme
.bodyLarge
?.copyWith(color: Colors.white),
)
: Text(
botMessage,
style: Theme.of(context)
.textTheme
.bodyLarge
?.copyWith(color: Colors.white),
)),
],
))
],
),
);
}
}
enum MessageType { user, bot }
class MessageModel {
late String userMessage;
late String botMessage;
late MessageType messageType;
MessageModel(
{required this.userMessage,
required this.botMessage,
required this.messageType});
}
예를 들면 enum 변수를 만들어서 각 상황에 맞게 UI를 구성할 수 있는 것,
http를 이용한 api 통신에 대해 부족한 점을 공부 할 수 있었고, 제일 간단하게 생각했던 UI 그리기 에서도 각 decoration 기능에는 어떤것들이 있는지 자세하게 알게 해주는 등..