Creative Code

Aurora-(14)최종 프로젝트 3 - web search, ai chat, talk 본문

Projects

Aurora-(14)최종 프로젝트 3 - web search, ai chat, talk

빛하루 2023. 11. 28. 18:35

웹 크롤링 검색결과, 실시간 검색어 기능

 

--> 키워드 입력시 구글, naver, kakao api를 활용한 웹 사이트 전체 크롤링 후 결과를 데이터프레임으로 제공하는 기능, 구글 trend에서 실시간 검색어 순위를 받아와 이를 표시하는 기능 

 

※web search 화면(front-end)를 구성하는 전체 코드 : pages/websearch.py

 

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

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

# 탭 버튼을 생성하는 함수
def tab_button(name, href):
    """A tab switcher button."""
    return rx.link(
        rx.icon(tag="star", mr=2),  # 별 모양 아이콘
        name,  # 버튼 텍스트
        display="inline-flex",
        align_items="center",
        py=3,
        px=6,
        href=href,  # 버튼 클릭 시 이동할 경로
        border="1px solid #eaeaea",
        font_weight="semibold",
        border_radius="full",
    )

# 왼쪽에 표시되는 탭 스위처
def tabs():
    """The tab switcher displayed on the left."""
    return rx.box(
        rx.vstack(
            rx.container(
                rx.hstack(
                    rx.icon(tag="moon", mr=2, color='yellow'),  # 달 모양 아이콘
                    rx.text(
                        "Aurora", 
                        style={
                            "fontSize": "25px",
                            "fontWeight": "bolder",
                            "fontFamily": "Open Sans,Sans-serif",
                            "background": "-webkit-linear-gradient(-45deg, #e04a3f, #4e8be6)",
                            "-webkit-background-clip": "text",
                            "color": "transparent",
                        },
                        center_content=True,
                    ),  # 앱 이름
                ),
            ),
            tab_button("Home", "/"),  # Home 탭 버튼
            tab_button("My Profile","/myprofile"),
            tab_button("Maps","/maps"),
            tab_button("video","/video"),
            tab_button("web search","/websearch"),
            tab_button("ai chat","/aichat"),
            tab_button("talk","/talk"),
            rx.button("Sign out", on_click=State.logout),  # 로그아웃 버튼
            rx.button(
                rx.icon(tag="moon"),
                on_click=rx.toggle_color_mode,
            ),
            rx.container(height='200px'),
            align_items="left",
            gap=4,
        ),
        py=4,
    )

def trend(key: str, value: str):
    return rx.vstack(
        rx.box(
            rx.container(
                rx.container(
                    rx.text(f'{key}위 : {value}'),
                ),
                align='start',
                width='250px',
            ),
        ),
        align='start',
        border='1px solid black',  # 테두리 스타일 지정
        border_radius='12px',  # 동그란 테두리를 위한 반지름 값 지정
        padding='5px',  # 테두리와 내용 사이의 여백 지정
    )

def sidebar(HomeState):
    HomeState.real_time_trend
    """The sidebar displayed on the right."""
    return rx.vstack(
        rx.container(
            rx.button(
                '실시간 검색어',
                on_click = HomeState.google_crawler,
                border_radius="1em",
                box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
                background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
                box_sizing="border-box",
                color="white",
                opacity="0.6",
                _hover={"opacity": 1},
            ),
            align_items="start",
            height='auto',
            py=4,
            margin_bottom='5px',

        ),
        rx.vstack(
            rx.foreach(
                HomeState.web_trend,
                lambda entry: trend(
                    entry[0],entry[1]
                ),
            ),
        ),
        align_items="start",
        gap=4,
        h="100%",
    )
    


# 피드의 헤더
def feed_header(HomeState):
    
    """The header of the feed."""
    return rx.hstack(
        rx.heading("Web Search", size="md"),  # 피드의 제목
        rx.input(on_blur=HomeState.set_web_search, placeholder="Search.."),  # 트윗 검색을 위한 입력 상자
        rx.button(
            "Search",
            on_click = HomeState.search_all,
            border_radius="1em",
            box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
            background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
            box_sizing="border-box",
            color="white",
            opacity="0.6",
            _hover={"opacity": 1},
        ),
        justify="space-between",
        p=4,
        border_bottom="3px solid #ededed",
    )

# 피드 영역
def feed(HomeState):
    HomeState.search_table
    return rx.box(
        feed_header(HomeState),
        rx.data_table(
            data=HomeState.search_df,
            font_size = '8px',
        ),
        border_x="3px solid #ededed",
        h="100%",
    )

# 홈 페이지
def websearch():
    State.check_login
    return container(
        rx.grid(
            tabs(),
            feed(HomeState),
            sidebar(HomeState),
            grid_template_columns="1fr 4fr 1fr",
            h="100vh",
            gap=4,
        ),
        max_width="1600px",
    )

 

 

kakao api를 활용한 koGPT 기능 제공

--> kakao api를 활용한 KoGPT 기능을 제공하며 질문한 내용들이 데이터 베이스에 저장된다. clear버튼 입력시 내역 초기화 가능, 본인이 질문한 내용은 노란색, KoGPT 가 대답한 내용은 파란색 박스에 담겨 대화형태로 저장된다.

 

※ai chat 화면(front-end)를 구성하는 전체 코드 : pages/aichat.py

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

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


color = "rgb(107,99,246)"
# 탭 버튼을 생성하는 함수
def tab_button(name, href):
    """A tab switcher button."""
    return rx.link(
        rx.icon(tag="star", mr=2),  # 별 모양 아이콘
        name,  # 버튼 텍스트
        display="inline-flex",
        align_items="center",
        py=3,
        px=6,
        href=href,  # 버튼 클릭 시 이동할 경로
        border="1px solid #eaeaea",
        font_weight="semibold",
        border_radius="full",
    )

# 왼쪽에 표시되는 탭 스위처
def tabs():
    """The tab switcher displayed on the left."""
    return rx.box(
        rx.vstack(
            rx.container(
                rx.hstack(
                    rx.icon(tag="moon", mr=2, color='yellow'),  # 달 모양 아이콘
                    rx.text(
                        "Aurora", 
                        style={
                            "fontSize": "25px",
                            "fontWeight": "bolder",
                            "fontFamily": "Open Sans,Sans-serif",
                            "background": "-webkit-linear-gradient(-45deg, #e04a3f, #4e8be6)",
                            "-webkit-background-clip": "text",
                            "color": "transparent",
                        },
                        center_content=True,
                    ),  # 앱 이름
                ),
            ),
            tab_button("Home", "/"),  # Home 탭 버튼
            tab_button("My Profile","/myprofile"),
            tab_button("Maps","/maps"),
            tab_button("video","/video"),
            tab_button("web search","/websearch"),
            tab_button("ai chat","aichat"),
            tab_button("talk","/talk"),
            rx.button("Sign out", on_click=State.logout),  # 로그아웃 버튼
            rx.button(
                rx.icon(tag="moon"),
                on_click=rx.toggle_color_mode,
            ),
            rx.container(height='200px'),
            align_items="left",
            gap=4,
        ),
        py=4,
    )

def sidebar():
    """The sidebar displayed on the right."""
    return rx.vstack(
        align_items="start",
        gap=4,
        h="100%",
        py=4,
    )

# 피드의 헤더
def feed_header(HomeState):
    
    """The header of the feed."""
    return rx.hstack(
        rx.heading("KoGPT", size="md"),  # 피드의 제목
        rx.input(on_blur=HomeState.set_chat_input, placeholder="Enter chat.."),  # 트윗 검색을 위한 입력 상자
        rx.button(
            "Enter",
            on_click = HomeState.kogptapi,
            border_radius="1em",
            box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
            background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
            box_sizing="border-box",
            color="white",
            opacity="0.6",
            _hover={"opacity": 1},
        ),
        rx.button(
            "Clear",
            on_click = HomeState.clear_gpt,
            border_radius="1em",
            box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
            background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
            box_sizing="border-box",
            color="white",
            opacity="0.6",
            _hover={"opacity": 1},
        ),
        justify="space-between",
        p=4,
        border_bottom="3px solid #ededed",
    )
    
# 개별 트윗을 표시하는 함수
def gpt(gpt):
    box_color = rx.cond(gpt.author == "KoGPT", "#99bed1", "#e2eb3b")
    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',
            background=box_color,
        ),
        rx.container(height='5px'),
        margin_left='10px',
        align_items='start',
        width='auto',
    )


# 피드 영역
def feed(HomeState):
    HomeState.kogpt_answer
    HomeState.saved_gpt
    return rx.box(
        feed_header(HomeState),
        rx.container(height='10px'),
        rx.cond(
            HomeState.gpts,
            rx.foreach(
                HomeState.gpts,
                gpt
            ),
            rx.vstack(
                rx.button(
                    rx.icon(
                        tag="repeat",
                        mr=1,
                    ),
                    rx.text("Click to load gpt"),
                    on_click=HomeState.get_gpt,
                ),  # 트윗을 불러오는 버튼
                p=4,
            ),
        ),
        border_x="3px solid #ededed",
        h="100%",
    )

# 홈 페이지
def aichat():
    State.check_login
    return container(
        rx.grid(
            tabs(),
            feed(HomeState),
            sidebar(),
            grid_template_columns="1fr 4fr 1fr",
            h="100vh",
            gap=4,
        ),
        max_width="1600px",
    )

 

 

지정한 사용자와 채팅 가능

--> 맨 위에 다른 사용자의 아이디를 입력후 select버튼을 누르면 해당 사용자와 채팅한 내역들을 확인가능, 내가 보낸 메시지는 노란색, 상대가 보낸 메시지는 파란색으로 표시된다, 밑에 메시지를 입력하고 send버튼을 클릭하면 상대에게 메시지가 보내진다.

 

※talk 화면(front-end)를 구성하는 전체 코드 : pages/talk.py

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

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


color = "rgb(107,99,246)"
# 탭 버튼을 생성하는 함수
def tab_button(name, href):
    """A tab switcher button."""
    return rx.link(
        rx.icon(tag="star", mr=2),  # 별 모양 아이콘
        name,  # 버튼 텍스트
        display="inline-flex",
        align_items="center",
        py=3,
        px=6,
        href=href,  # 버튼 클릭 시 이동할 경로
        border="1px solid #eaeaea",
        font_weight="semibold",
        border_radius="full",
    )

# 왼쪽에 표시되는 탭 스위처
def tabs():
    """The tab switcher displayed on the left."""
    return rx.box(
        rx.vstack(
            rx.container(
                rx.hstack(
                    rx.icon(tag="moon", mr=2, color='yellow'),  # 달 모양 아이콘
                    rx.text(
                        "Aurora", 
                        style={
                            "fontSize": "25px",
                            "fontWeight": "bolder",
                            "fontFamily": "Open Sans,Sans-serif",
                            "background": "-webkit-linear-gradient(-45deg, #e04a3f, #4e8be6)",
                            "-webkit-background-clip": "text",
                            "color": "transparent",
                        },
                        center_content=True,
                    ),  # 앱 이름
                ),
            ),
            tab_button("Home", "/"),  # Home 탭 버튼
            tab_button("My Profile","/myprofile"),
            tab_button("Maps","/maps"),
            tab_button("video","/video"),
            tab_button("web search","/websearch"),
            tab_button("ai chat","/aichat"),
            tab_button("talk","/talk"),
            rx.button("Sign out", on_click=State.logout),  # 로그아웃 버튼
            rx.button(
                rx.icon(tag="moon"),
                on_click=rx.toggle_color_mode,
            ),
            rx.container(height='200px'),
            align_items="left",
            gap=4,
        ),
        py=4,
    )

def sidebar():
    """The sidebar displayed on the right."""
    return rx.vstack(
        align_items="start",
        gap=4,
        h="100%",
        py=4,
    )

# 피드의 헤더
def feed_header(HomeState):
    
    """The header of the feed."""
    return rx.hstack(
        rx.heading("Chat", size="md"),  # 피드의 제목
        rx.input(on_blur=HomeState.set_receive_user, placeholder="Please enter the person you would like to send the message to!"),  # 트윗 검색을 위한 입력 상자
        rx.button(
            "select",
            on_click = HomeState.get_messages,
            border_radius="1em",
            box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
            background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
            box_sizing="border-box",
            color="white",
            opacity="0.6",
            _hover={"opacity": 1},
        ),
        justify="space-between",
        p=4,
        border_bottom="3px solid #ededed",
    )

# 개별 트윗을 표시하는 함수
def message(message):
    box_color = rx.cond(message.send_user == HomeState.user.username, "#e2eb3b","#99bed1")
    return rx.vstack(
        rx.box(
            rx.hstack(
                rx.hstack(
                    rx.container(width='2px'),
                    rx.avatar(name=message.send_user, size="sm"), 
                ),
                rx.box(
                    rx.hstack(
                        rx.text("@" + message.send_user, font_weight="bold"),  
                        rx.text("["+ message.created_at +"]"),
                    ),
                    rx.text(message.message, width="auto"),  
                    width = 'auto',
                ),
                py=4,
                gap=1,
                width='auto',
            ),
            align_items='start',
            width = '97%',
            margin_left='5px',
            border_radius='20px',
            background=box_color,
        ),
        rx.container(height='5px'),
        margin_left='10px',
        align_items='start',
        width='auto',
    )


# 피드 영역
def feed(HomeState):
    HomeState.syn_messages
    return rx.box(
        feed_header(HomeState),
        rx.container(height='10px'),
        rx.cond(
            HomeState.messages,
            rx.foreach(
                HomeState.messages,
                message
            ),
            rx.vstack(
                rx.button(
                    rx.icon(
                        tag="repeat",
                        mr=1,
                    ),
                    rx.text("Click to load chat"),
                    on_click=HomeState.get_messages,
                ),  # 트윗을 불러오는 버튼
                p=4,
            ),
        ),
        rx.hstack(
            rx.input(on_blur=HomeState.set_kakaotalk, placeholder="Write Message!"),
            rx.button(
                'send',
                on_click = HomeState.sending_message,
                border_radius="1em",
                box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
                background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
                box_sizing="border-box",
                color="white",
                opacity="0.6",
                _hover={"opacity": 1},
            )
        ),
        border_x="3px solid #ededed",
        h="100%",
    )

# 홈 페이지
def talk():
    State.check_login
    return container(
        rx.grid(
            tabs(),
            feed(HomeState),
            sidebar(),
            grid_template_columns="1fr 4fr 1fr",
            h="100vh",
            gap=4,
        ),
        max_width="1600px",
    )