Creative Code

Lunar-(17)ai-chat 날짜별 대화기록 조회 및 삭제 기능 본문

Projects

Lunar-(17)ai-chat 날짜별 대화기록 조회 및 삭제 기능

빛하루 2024. 1. 26. 23:40

2월 3일 다음 업데이트 예정!

pages/aichat.py

 

 

sql 문에 오류가 계속 생겨서 해결하는데 어려웠지만 어쨌든 날짜별로 대화내용을 조회하고 삭제할 수 있는 기능도 추가하는데 성공했다..  sql좀 다시 봐야겠다.. 내일부터는 message기능..!

 

※pages/aichat.py 전체 코드

# lunar.state.home 모듈에서 필요한 State 및 HomeState를 가져옵니다.
import reflex as rx
from lunar.state.base import State
from lunar.state.home import HomeState

# 컴포넌트를 가져옵니다.
from ..components import container

color = "rgb(107,99,246)"
# 탭 버튼을 생성하는 함수
def tab_button(imagepath, href):
    """A tab switcher button."""
    return rx.link(
        rx.image(
            src=imagepath,
            height='40px',
            width='40px',
        ),
        display="inline-flex",
        align_items="center",
        py=3,
        px=2,
        href=href,  # 버튼 클릭 시 이동할 경로
    )

def chat_day(chat_day):
    return rx.box(
        rx.hstack(
            rx.button(
                chat_day,
                on_click = HomeState.get_day_chat(chat_day),
                width='90%',
                border = '2px solid #000000',
                border_radius='10px',
            ),
            rx.button(
                rx.icon(tag = 'close', size ='md'),
                on_click = HomeState.delete_day_chat(chat_day),
                width='10%',
            )
        ),
        rx.container(height='5px'),
        width = '100%',
    )

# 왼쪽에 표시되는 탭 스위처
def tabs():
    """The tab switcher displayed on the left."""
    return rx.box(
        rx.container(
            rx.hstack(
                rx.image(
                    src='/moon.png',
                    height='60px',
                    width='60px',         
                ),
                rx.text(
                    "Lunar", 
                    style={
                        "fontSize": "40px",
                        "fontWeight": "bolder",
                        "fontFamily": "Calibri, Calibri",
                        "background": "-webkit-linear-gradient(-45deg, #e04a3f, #4e8be6)",
                        "-webkit-background-clip": "text",
                        "color": "transparent",
                    },
                    center_content=True,
                ),  # 앱 이름
            ),
        ),
        rx.container(height='30px'),
        rx.vstack(
            rx.vstack(
                rx.text(
                    'Conversation history',
                    font_Size='25px',
                    font_Weight='bold',
                    color = '#000000',
                ),
                rx.vstack(
                    rx.container(height='10px'),
                    rx.foreach(
                        HomeState.gpt_chat_daylist,
                        chat_day
                    ),
                    rx.container(height='10px'),
                    width='100%',
                    align_items='start',
                ),
                width = '100%',
                align_items='start',
            ),
            rx.container(height='10px'),
            rx.button(
                rx.text('Delete all conversations',font_weight='bold',font_Size = '20px'),
                on_click = HomeState.clear_gpt,
                bg = 'red.300',
                width = '100%',
            ),
            align_items='start',
            width = '100%',
        ),
        py=4,
        overflow = 'auto',
    )

def gpt(gpt):
    box_color = rx.cond(gpt.author == "Gemini", "#b2d5eb", "#f5ec76")
    return rx.vstack(
        rx.box(
            rx.hstack(
                rx.hstack(
                    rx.container(width='2px'),
                    rx.avatar(name=gpt.author, size="sm"), 
                ),
                rx.box(
                    rx.hstack(
                        rx.text("@" + gpt.author, font_weight="bold"),
                        rx.text("["+ gpt.created_at +"]"),  
                    ),
                    rx.text(gpt.content, width="auto"),  
                    width = 'auto',
                ),
                py=4,
                gap=1,
                width='auto',
            ),
            align_items='start',
            width = '97%',
            margin_left='5px',
            border_radius='20px',
            border = '2px solid #000000',
            background=box_color,
        ),
        rx.container(height='5px'),
        margin_left='10px',
        align_items='start',
        width='auto',
    )
                
def feed_header(HomeState):
    return rx.box(
        rx.vstack(
            rx.container(height='10px'),
            rx.hstack(
                rx.image(src = '/chattingai.png',height='100%',width='80px'),
                rx.text_area(
                    value=HomeState.user_input_chat,
                    w='100%',
                    border=2,
                    placeholder="Talk to Gemini!",  # 트윗을 작성하는 입력 상자
                    resize="none",
                    py=4,
                    px=0,
                    _focus={"border": 0, "outline": 0, "boxShadow": "none"},
                    on_change=HomeState.set_user_input_chat,
                ),
                rx.button(
                    rx.image(src = '/aichatload.png',height='100%',width='100%'),
                    on_click = HomeState.get_gpt,
                    border_radius="1em",
                    box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
                    box_sizing="border-box",
                    color="white",
                    opacity="0.6",
                    _hover={"opacity": 1},
                ),
                rx.button(
                    rx.image(src = '/aimessagesend.png',height='100%',width='100%'),
                    on_click = HomeState.chatai,
                    border_radius="1em",
                    box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
                    box_sizing="border-box",
                    color="white",
                    opacity="0.6",
                    _hover={"opacity": 1},
                ),
                justify="space-between",
                p=4,
                width = '97%',
                border_radius = '20px',
                border = '2px solid #000000',
                box_shadow = '10px 10px 5px #706666',
                align_items='start',
            ),
            rx.container(height='10px'),
        ),
    )

# 피드 영역
def feed(HomeState):
    return rx.box(
        rx.container(height='10px'),
        feed_header(HomeState),
        rx.cond(
            HomeState.aichatting,
            rx.foreach(
                HomeState.aichatting,
                gpt
            ),
        ),
        h="100%",
        overflow='auto'
    )

# 홈 페이지
def aichat():
    State.check_login
    return rx.vstack(
        rx.grid(
            tabs(),
            feed(HomeState),
            grid_template_columns="2fr 7fr",

            width='97%',
            h="90vh",
            gap=4,
        ),
        rx.grid(
            rx.vstack(
                rx.container(height='5px'),
                rx.button(
                    rx.icon(tag="moon"),
                    on_click=rx.toggle_color_mode,
                    width = '80%',
                    _hover={"bg": "orange.400"},
                ),
                width = '100%',
            ),
            rx.vstack(
                rx.hstack(
                    tab_button('/Home.png','/'),
                    tab_button('/profile.png','/profile'),
                    tab_button('/map.png','/map'),
                    tab_button('/chat.png','/chat'),
                    tab_button('/Aichat.png','/aichat'),
                    tab_button('/diary.png','/diary'),
                    tab_button('/video.png','/video'),
                    tab_button('/game.png','/game'),
                    tab_button('/music.png','/music'),
                    tab_button('/weather.png','/weather'),
                    tab_button('/setting.png','/setting'),
                    margin_right='5px',
                    border="1px solid #000000",
                    border_radius="full",
                    box_Shadow = '10px 10px 5px #3083f0',
                ),
                width = '100%',
            ),
            rx.vstack(
                rx.container(height='5px'),
                rx.button(
                    "Sign out",
                    on_click=State.logout,
                    bg="#212963",
                    color="white",
                    _hover={"bg": "blue.600"},
                    width = '80%',
                ),
                width = '100%',
            ),
            width='97%',
            grid_template_columns="2fr 5fr 2fr",
        ),
    )

 

※state/home.py의 aichat 페이지를 담당하는 함수 전체 코드

# Gemini기능
    def chatai(self):
        if not self.logged_in:                                                            # 로그인되어 있지 않은 경우 알림
            return rx.window_alert("Please log in first")
        with open('googlegeminiapikey.json','r')as f:                                               
            key = json.load(f)
        googlegeminiapikey = key['key']
        genai.configure(api_key=googlegeminiapikey)
        model = genai.GenerativeModel('gemini-pro')
        gpt_response = model.generate_content(self.user_input_chat)
        with rx.session() as session:                                                     # 대화 내용을 데이터베이스에 저장
            gpt = GPT(
                user_id = self.user.username,
                author=self.user.username,
                content=self.user_input_chat,
                created_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            )
            session.add(gpt)
            session.commit()
            self.user_input_chat= ""

        with rx.session() as session:                                                     # KoGPT의 응답을 데이터베이스에 저장
            gpt = GPT(
                user_id = self.user.username,
                author = 'Gemini',
                content=gpt_response.text,
                created_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            )
            session.add(gpt)
            session.commit()
            
        return self.get_gpt() 
    
    # 데이터베이스에서 GPT 대화내역 가져오기
    def get_gpt(self):
        if not self.logged_in:                                                            # 로그인되어 있지 않은 경우 알림
            return rx.window_alert("Please log in first")
        with rx.session() as session:
            self.aichatting = session.query(GPT).filter_by(user_id = self.user.username).all()[::-1]
        daylist = []
        for i in range(0,len(self.aichatting)):
            chatday = datetime.strptime(self.aichatting[i].created_at, "%Y-%m-%d %H:%M:%S")
            date_only = chatday.strftime("%Y-%m-%d")
            daylist.append(date_only)
        daylist_set = set(daylist)
        self.gpt_chat_daylist = list(daylist_set)

    # gpt 대화내용 전체삭제
    def clear_gpt(self):
        self.aichatting = []
        with rx.session() as session:
            session.query(GPT).filter_by(user_id = self.user.username).delete()
            session.commit()
        return self.get_gpt()
    
    # gpt 특정날짜 대화내역 불러오기
    def get_day_chat(self,chat_day):
        if not self.logged_in:
            return rx.window_alert("Please log in first")
        with rx.session() as session:
            self.aichatting = session.query(GPT).filter(GPT.user_id == self.user.username,func.date(GPT.created_at)==chat_day).all()[::-1]

    # gpt 특정날짜 대화내역 삭제하기
    def delete_day_chat(self,chat_day):
        if not self.logged_in:
            return rx.window_alert("Please log in first")
        with rx.session() as session:
            delete_chat = session.query(GPT).filter(GPT.user_id == self.user.username,func.date(GPT.created_at)==chat_day).all()[::-1]
            if delete_chat:
                for i in range(0,len(delete_chat)):
                    session.delete(delete_chat[i])
                session.commit()
        return self.get_gpt()