일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Binding
- Firebase
- React JS
- 리엑트
- AnimationController
- MS-SQL
- db
- 플러터
- 자바스크립트
- .NET
- 오류
- 함수
- 닷넷
- MVVM
- GitHub
- JavaScript
- page
- spring boot
- listview
- 애니메이션
- 깃허브
- HTML
- 마우이
- Maui
- Flutter
- MSSQL
- 파이어베이스
- Animation
- 바인딩
- typescript
- Today
- Total
개발노트
15. [Flutter] Chat GPT 챗봇 만들기 본문
Chat GPT SDK를 이용한다면 Flutter 앱에 Chat GPT를 연결하여 사용할 수 있습니다.
준비물.1
- 설치링크: https://pub.dev/packages/chat_gpt_sdk/install
준비물.2
ChatGPT API Key 받는 곳
- 링크: https://platform.openai.com/account/api-keys
소스 설명.1
MessageModel.dart (메세지 모델로 사용할 객체)
class MessageModel {
final bool isBot;
final String message;
MessageModel(this.isBot, this.message);
}
- isBoot: 봇이 보냈으면 true , User가 보냈으면 false 값을 갖습니다.
- message: 메세지 내용을 갖습니다.
main.dart (메인 화면)
import 'dart:collection';
import 'package:chat_gpt_sdk/chat_gpt_sdk.dart';
import 'package:flutter/material.dart';
import 'package:flutter_application_chatbotgpt/models/message_model.dart';
final List<MessageModel> _messages = [MessageModel(true, 'Hi')];
UnmodifiableListView<MessageModel> messages = UnmodifiableListView(_messages);
final txtMessage = TextEditingController();
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final openAI = OpenAI.instance.build(
token: '위 링크에서 생성한 챗GPT Open API를 입력해주세요.',
baseOption: HttpSetup(receiveTimeout: const Duration(seconds: 100)),
isLog: true);
void sendMessage(String message) async {
const maxTokens = 2048;
final promptLength = message.length;
final contextLength =
messages.fold<int>(0, (prev, m) => prev + m.message.length);
final remainingTokens = maxTokens - promptLength - contextLength;
final requests = CompleteText(
prompt: message,
model: Model.textDavinci3,
maxTokens: remainingTokens,
);
final res = await openAI.onCompletion(request: requests);
setState(() {
_messages.add(MessageModel(true, res?.choices.last.text ?? "Error"));
messages = UnmodifiableListView(_messages);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('ChatGPT'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(children: [
Column(
children: [
Expanded(
flex: 1,
child: ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 10),
itemCount: messages.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return messages[index].isBot
? BotCard(index: index)
: UserCard(index: index);
},
)),
const SizedBox(
height: 45,
)
],
),
SendMessage(
sendMessage: () => sendMessage(txtMessage.text),
)
]),
),
),
);
}
}
1) OpenAI 객체
- token: ChatGPT API Key 인증키를 입력합니다.
- baseOption: 대기할 최대 시간을 지정합니다. (100초)
- isLog: OpenAI의 API와 상호 작용하려면 HTTP 클라이언트를 설정해야하며, 디버깅 및 기록을 위해 로거도 true로 설정합니다.
2) sendMessage 메소드
유저가 메세지를 보내기 위해 버튼을 눌렀을 때 동작합니다.
2-1) CompleteText 위젯
ChatGPT API에 전달할 메세지 정보를 입력할 위젯
- prompt: 메시지 텍스트 값을 입력합니다.
- model: OpenAI API의 모델을 입력합니다.
- maxTokens: 완성된 텍스트의 최대 길이를 입력합니다.
2-2) OpenAI.onCompletion
- final res: CompleteText 위젯으로 요청 후, 완성된 텍스트를 반환하는 메소드를 호출하는 코드입니다.
*res에 값이 없다면 "Error" 문자를, Null이 아니면 받은 메시지를 Messages 리스트에 추가합니다.
3) ListView.builder (메시지를 노출할 위젯)
3-1)BouncingScrollPhysics 은 오버스크롤이 발생 했을 때 부드럽게 멈춰줍니다. (IOS 스크롤방식)
3-2) isBot 속성을 이용하여 true 일경우 BotCard, flase 일 경우 UserCard를 List Item에 빌드합니다.
소스 설명.2
SendMessage 위젯 (메세지 보내기 기능 위젯으로 분리시킴)
class SendMessage extends StatelessWidget {
final VoidCallback sendMessage;
const SendMessage({
required this.sendMessage,
super.key,
});
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.bottomCenter,
child: Container(
height: MediaQuery.of(context).size.height * .08,
width: double.maxFinite,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: TextField(
controller: txtMessage,
decoration: InputDecoration(
suffixIcon: GestureDetector(
onTap: () {
sendMessage();
_messages
.add(MessageModel(false, txtMessage.text.toString()));
txtMessage.clear();
},
child: const Icon(
Icons.send,
color: Colors.blue,
),
),
hintText: '...A',
disabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
borderRadius: BorderRadius.all(Radius.circular(20))),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
borderRadius: BorderRadius.all(Radius.circular(20)))),
),
),
);
}
}
1. TextField 위젯 (유저 메시지를 입력 받을 위젯)
- controller: TextEditionfController를 할당하면 입력된 값을 가져올 수 있습니다.
- suffixIcon: TextField에 아이콘을 추가할 수 있습니다.
- hintText: 입력창에 문자가 없을 때 보여지는 Text 값입니다.
소스 설명.3
botCard 위젯 (Chat GPT가 보내는 메시지)
//챗봇 카드 위젯
class BotCard extends StatelessWidget {
final int index;
const BotCard({
required this.index,
super.key,
});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CircleAvatar(
child: Icon(
Icons.person,
size: 35,
color: Colors.cyan,
),
),
Text('챗 봇'),
],
),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
),
width: 300,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(15)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.12),
offset: const Offset(2, 2))
]),
child: Transform.translate(
offset: const Offset(0, -15),
child: Text(
messages[index].message,
softWrap: true,
),
),
),
],
);
}
}
UserCard 위젯 (유저가 보내는 메시지)
//유저 카드 위젯
class UserCard extends StatelessWidget {
final int index;
const UserCard({
required this.index,
super.key,
});
@override
Widget build(BuildContext context) {
return Stack(
children: [
const Align(
alignment: Alignment.centerRight,
child: Column(
children: [
CircleAvatar(
child: Icon(
Icons.hail,
size: 30,
),
),
Text('구굴러')
],
),
),
Positioned(
right: 50,
bottom: 15,
child: Column(
children: [
Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: const BorderRadius.all(Radius.circular(10)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(.12),
offset: const Offset(-1, 1),
blurRadius: 2)
]),
child: Text(
messages[index].message,
softWrap: true,
style: const TextStyle(fontWeight: FontWeight.w500),
))
],
),
)
],
);
}
}
단순히 UI를 그리는 위젯이라 설명은 생략하겠습니다.
*Text 위젯 속성에 softWrap = true 로 두면 텍스트 길이에 따라 Text Widget 크기가 적용됩니다.
빌드된모습.
- 참고링크:
https://www.youtube.com/watch?v=qUEUMxGW_0Q
'앱 개발 > Flutter' 카테고리의 다른 글
17. [Flutter] font awesome 위젯으로 Icon 사용하기 (0) | 2023.06.15 |
---|---|
16. [Flutter] FractionallySizedBox 부모위젯 공간 비율로 자식위젯 너비, 높이 정하기 (0) | 2023.06.14 |
14. [Flutter] Expanded, Flexible 위젯 올바르게 사용하는 방법 (0) | 2023.04.14 |
13. [Flutter] 피아노 위젯 사용하기 (0) | 2023.04.12 |
12. [Flutter] 위젯 위치 이동시키기(with Transform) (0) | 2023.04.10 |