Notice
Recent Posts
Recent Comments
Link
250x250
«   2025/01   »
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
Tags more
Archives
Today
Total
관리 메뉴

혼자서 앱 만드는 개발자 함께하는 AI 세상

flutter chatGTP3 챗봇 기능 추가(SQLITE 저장 /삭제 추가) 본문

마이봇 chat GPT 오픈 프로젝트

flutter chatGTP3 챗봇 기능 추가(SQLITE 저장 /삭제 추가)

혼앱사 2023. 2. 16. 22:42
반응형
  • 챗봇과 데화중 다시 로드될때 기록을 남겨서 다시 확인할수있다.
  • 각 문답에 대해 삭제 기능 Dismissible 기능을 추가햐여 삭제 하도록 했다.
  • 문답기록은 sqlite 를 통해 저장하고 초기 로딩시 불러오게 만들었다.
  • 그리고 기본 200자를 최대 4000자까지 허용하게 옵션을 수정했다.

 

 

Dismissible 기능을 추가 하여 삭제하는 기능 과 소스 

 

삭제 와 리스트를 저장하는 기능 구현

  • 4000자까지 받아올수있도록 옵션수정(한글은 절반정도될듯)

  •  
  • 데이터베이스를 초기화하고 메세지를 받아서  sqlite 저장 

  • 전체 화면 소스
import 'dart:async';
import 'dart:math';
import 'package:chat_gpt_sdk/chat_gpt_sdk.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_chatgpt_api/flutter_chatgpt_api.dart';
import 'package:intl/intl.dart';
import 'package:material_buttonx/materialButtonX.dart';
import 'package:openchat/providers/memo_provider.dart';
import 'package:openchat/utils/database_memo.dart';
import 'package:provider/provider.dart';
import 'constants.dart';
import 'models/message_memo.dart';
import 'providers/auth_provider.dart';

const backgroundColor = Color(0xff343541);
const botBackgroundColor = Color(0xff444654);

class ChatPage3 extends StatefulWidget {
  const ChatPage3({super.key});

  @override
  State<ChatPage3> createState() => _ChatPageState();
}

class _ChatPageState extends State<ChatPage3> {
  final _textController = TextEditingController();
  final _scrollController = ScrollController();
  List<MessageMemo> _messages = [];
  late MemoProvider memoProvider;

  late OpenAI openAI;
  String oldText = "";
  String? _parentMessageId;
  String? _conversationId;
  late bool isLoading;
  late Future<List<MessageMemo>> memoList;
  @override
  void initState() {
    memoProvider = context.read<MemoProvider>();
    DatabaseMemo().initializedDB().then((value) => {});
    getAllDatas();

    openAI = OpenAI.instance.build(
        token: token,
        baseOption: HttpSetup(receiveTimeout: 30000),
        isLogger: true);

    super.initState();

    isLoading = false;
  }

  void _translateEngToThai() async {
    final request = CompleteText(
        prompt: _textController.text,
        maxTokens: 4000,
        model: kTranslateModelV3);
    onSendMessage(_textController.text, ChatMessageType.user, '');
    openAI
        .onCompleteStream(request: request)
        .listen((response) => addMessage(response))
        .onError((err) {
      setState(() {
        isLoading = false;
        _messages.add(
          MessageMemo(
            content: '답변을 들을수 없어요 ㅠㅠ',
            chatMessageType: ChatMessageType.bot,
            etc1: '',
            idFrom: '',
            idTo: '',
            timestamp: DateTime.now().millisecondsSinceEpoch.toString(),
          ),
        );
      });

      print("$err");
    });
  }

  addMessage(response) {
    if (response.choices.last.text != '') {
      if (response.choices.last.text != oldText) {
        oldText = response.choices.last.text;
        var timestemp = DateTime.now().millisecondsSinceEpoch.toString();

        onSendMessage(oldText, ChatMessageType.bot, timestemp);
        setState(() {
          isLoading = false;
          _messages.add(
            MessageMemo(
              content: response.choices.last.text,
              chatMessageType: ChatMessageType.bot,
              etc1: '',
              idFrom: '',
              idTo: '',
              timestamp: timestemp,
            ),
          );
        });
      }
    }
  }

  void onSendMessage(String content, ChatMessageType type, String timestemp) {
    memoProvider
        .sendMessage(content, type, timestemp, 'currentUserId',
            'widget.arguments.peerId', 'etc1')
        .then((value) {
      setState(() {
        //getAllDatas();
      });
    });
  }

  void getAllDatas() async {
    _messages = await DatabaseMemo().getAllDatas();
    setState(() {
      _scrollDown();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: Image.asset(
          'assets/bot.png',
          color: Colors.white,
          scale: 1.5,
        ),
        toolbarHeight: 50,
        title: const Padding(
          padding: EdgeInsets.all(1.0),
          child: Text(
            'GPT3 bot과 대화',
            maxLines: 1,
            textAlign: TextAlign.center,
          ),
        ),
        backgroundColor: botBackgroundColor,
      ),
      backgroundColor: backgroundColor,
      body: SafeArea(
        child: Column(
          children: [
            Expanded(
              child: _buildList(),
            ),
            Visibility(
              visible: isLoading,
              child: const Padding(
                padding: EdgeInsets.all(8.0),
                child: CircularProgressIndicator(
                  color: Colors.white,
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Row(
                children: [
                  _buildInput(),
                  _buildSubmit(),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildSubmit() {
    return Visibility(
      visible: !isLoading,
      child: Container(
        color: botBackgroundColor,
        child: IconButton(
          icon: const Icon(
            Icons.send_rounded,
            color: Color.fromRGBO(142, 142, 160, 1),
          ),
          onPressed: () async {
            _translateEngToThai();

            setState(
              () {
                _messages.add(
                  MessageMemo(
                    content: _textController.text,
                    chatMessageType: ChatMessageType.user,
                    etc1: '',
                    idFrom: '',
                    idTo: '',
                    timestamp: DateTime.now().millisecondsSinceEpoch.toString(),
                  ),
                );
                isLoading = true;
              },
            );
            var input = _textController.text;
            _textController.clear();
            Future.delayed(const Duration(milliseconds: 50))
                .then((_) => _scrollDown());

            setState(() {});
            _textController.clear();
            Future.delayed(const Duration(milliseconds: 50))
                .then((_) => _scrollDown());
          },
        ),
      ),
    );
  }

  Expanded _buildInput() {
    return Expanded(
      child: TextField(
        textCapitalization: TextCapitalization.sentences,
        style: const TextStyle(color: Colors.white),
        controller: _textController,
        decoration: const InputDecoration(
          hintText: 'GPT3 bot 에게 물어보세요',
          hintStyle: TextStyle(
            color: Colors.grey,
          ),
          fillColor: botBackgroundColor,
          filled: true,
          border: InputBorder.none,
          focusedBorder: InputBorder.none,
          enabledBorder: InputBorder.none,
          errorBorder: InputBorder.none,
          disabledBorder: InputBorder.none,
        ),
      ),
    );
  }

  ListView _buildList() {
    return ListView.builder(
      controller: _scrollController,
      itemCount: _messages.length,
      itemBuilder: (context, index) {
        var message = _messages[index];

        return Dismissible(
            key: UniqueKey(),
            onDismissed: (direction) {
              setState(() {
                DatabaseMemo().deleteData(message.timestamp);
                _messages.removeAt(index);
              });
            },
            child: ChatMessageWidget(
              text: message.content,
              chatMessageType: message.chatMessageType,
              timestamp: message.timestamp,
              remove: () {
                setState(() {
                  _messages.removeAt(index);
                });
              },
            ));
      },
    );
  }

  void _scrollDown() {
    _scrollController.animateTo(
      _scrollController.position.maxScrollExtent,
      duration: const Duration(milliseconds: 300),
      curve: Curves.easeOut,
    );
  }
}

class ChatMessageWidget extends StatelessWidget {
  const ChatMessageWidget({
    super.key,
    required this.text,
    required this.chatMessageType,
    required this.timestamp,
    required this.remove,
  });

  final String text;
  final String timestamp;
  final ChatMessageType chatMessageType;
  final Function remove;
  @override
  Widget build(BuildContext context) {
    var date = DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp));
    var time = DateFormat('MM/dd hh:mm').format(date);

    return Container(
      margin: const EdgeInsets.symmetric(vertical: 10.0),
      padding: const EdgeInsets.all(16),
      color: chatMessageType == ChatMessageType.bot
          ? botBackgroundColor
          : backgroundColor,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          chatMessageType == ChatMessageType.bot
              ? Container(
                  margin: const EdgeInsets.only(right: 16.0),
                  child: CircleAvatar(
                    backgroundColor: const Color.fromRGBO(16, 163, 127, 1),
                    child: Image.asset(
                      'assets/bot.png',
                      color: Colors.white,
                      scale: 1.5,
                    ),
                  ),
                )
              : Container(
                  margin: const EdgeInsets.only(right: 16.0),
                  child: const CircleAvatar(
                    child: Icon(
                      Icons.person,
                    ),
                  ),
                ),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                Container(
                    decoration: const BoxDecoration(
                      borderRadius: BorderRadius.all(Radius.circular(1.0)),
                    ),
                    child: Text(
                      text,
                      style: Theme.of(context)
                          .textTheme
                          .bodyLarge
                          ?.copyWith(color: Colors.white),
                    )),
                SizedBox(
                  height: 10,
                ),
                Text(
                  time,
                  style: Theme.of(context)
                      .textTheme
                      .bodyLarge
                      ?.copyWith(color: Colors.white),
                )
              ],
            ),
          ),
          Column(
            children: [
              CupertinoButton(
                minSize: 0.0,
                child: Icon(
                  Icons.copy,
                  size: 20,
                ),
                padding: EdgeInsets.zero,
                color: Colors.black,
                onPressed: () {
                  Clipboard.setData(ClipboardData(text: text));
                },
              ),
              SizedBox(height: 10),
              CupertinoButton(
                minSize: 0.0,
                child: Icon(
                  Icons.delete,
                  size: 20,
                ),
                padding: EdgeInsets.zero,
                color: Colors.black,
                onPressed: () {
                  DatabaseMemo().deleteData(timestamp);
                  remove();
                },
              )
            ],
          )
        ],
      ),
    );
  }
}
728x90
반응형
Comments