AI

[15분 완성] AI 챗봇 만들기(Streamlit + OpenAI API) - 2) 챗봇 만들기

생각파워 2024. 8. 25. 17:09

 

2024.08.24 - [AI] - [15분 완성] AI 챗봇 만들기(streamlit + OpenAI API) - 1) 환경설정

2024.08.26 - [AI] - [15분 완성] AI 챗봇 만들기(Streamlit + OpenAI API) - 3) API 키 생성

2024.08.26 - [AI] - [15분 완성] AI 챗봇 만들기(Streamlit + OpenAI API) - 4) 챗봇 완성!!

 

 

 

1편에서 환경설정에 대해 알아보았습니다.

환경설정이 됐으면 절반은 끝났다고 봐야죠.

이제 잘 조합해서 사용하는 일만 남았습니다.

시작해보시죠.

 

챗봇을 만드려면 API키를 가져와서 통신이 가능하게 하고,

사용자와 AI가 주고받는 대화를 쌓아나가는 방법을 구현해 주는 것이 필요합니다.

우리는 가상데이터를 이용해서 최종 출력화면을 먼저 적절히 구성해주도록 하겠습니다.

이후 만들어진 화면을 조금씩 개선하여 프로그램을 완성하도록 하겠습니다.

 

1. 대화 출력

대화를 주고받을 때 사람이 한 말인지, AI가 한 말인지 구분이 돼야합니다.

if문을 사용해서 구분할 수 있겠지만 코드가 아주 지저분해지겠죠.

streamlit에는 이미 구분해서 사용할 수 있는 기능이 만들어져 있습니다.

import streamlit as st

with st.chat_message('user'):
    st.write("hi")

with st.chat_message('assistant'):
    st.write("hello")

 

chat_message에 'user'를 적으면 사람이 적은 것으로 나오고, 

'assistant'를 적으면 AI가 답변한 것으로 나옵니다.

이모티콘도 맞춰서 나오죠. 

내용은 여러줄을 적을 수 있고, 표와 같은 내용도 들어갈 수 있습니다.

import streamlit as st
import numpy as np

with st.chat_message('user'):
    st.write("hi")
    st.write("Nice to meet you")

with st.chat_message('AI'):
    st.write("hello")
    st.bar_chart("Nice to meet you, too")

 

 

2. 대화 쌓기

대화를 쌓을 때는 사용자와 AI가 대화를 시작한 시점에 대화를 쌓고, 이후에 순서대로 출력을 해주면 대화 순서대로 출력이 될 것입니다.

 

"user" : "hi"

"assistant" : "hello"

"user" : "지금 몇시야?"

"assistant" : "오전 11시 입니다."

 

위 모양은 파이썬 개발자들에게 익숙한 모양입니다. 딕셔너리 형태거든요.

대화 하나당 하나의 딕셔너리를 만들고, 배열에 쌓아주면 될 것 같습니다.

messages라는 변수에 내용을 할당해주면 아래와 같이 될 것입니다.

"user"와 "assistant"는 "role"이라는 키로 구분해주면 되고,

말하는 내용은 "content"로 넣어주면 될 것 같습니다.

messages = [
	{"role" : "user", "content":"hi"},
	{"role" : "assistant", "content" : "hello"},
	{"role" : "user", "content" : "지금 몇시야?"},
	{"role" : "assistant", "content" : "오전 11시 입니다."},
]

 

messages가 위와 같이 구성돼 있으면 간단한 출력문으로 대화를 출력할 수 있습니다.

import streamlit as st

messages = [
	{"role" : "user", "content":"hi"},
	{"role" : "assistant", "content" : "hello"},
	{"role" : "user", "content" : "지금 몇시야?"},
	{"role" : "assistant", "content" : "오전 11시 입니다."},
]

for m in messages:
    with st.chat_message(m["role"]):
        st.write(m["content"])

 

streamlit run streamlit_test.py로 실행시키면 아래와 같이 대화형태로 출력이 됩니다.

 

3. 질문 추가

이제 사람이 입력하는 부분을 추가해보겠습니다. 챗GPT를 쓸때 제일 하단에 나오는 입력창 말이죠.

입력창에 질문을 입력하고 엔터키를 치면 messages에 추가되게 만들겠습니다.

AI에게 질문이 가서 답변을 받아야 하지만, 답변을 받았다고 생각하고 답변도 추가해보겠습니다.

 

질문창은 st.chat_input을 이용해서 만듭니다.

질문 입력 박스를 화면 제일 아랫부분에 붙이는 것도 쉽지 않은 일인데,

st.chat_input을 이용하면 그냥 제일 하단에 붙습니다.

if문을 이용해서 질문내용이 들어오면 실행되게 만듭니다.

 

if query := st.chat_input("질문을 입력하세요."):
    messages.append({"role":"user", "content":query})
    st.chat_message("user").write(query)
    response = f"{query}질문에 대한 답변입니다."
    messages.append({"role":"assistant", "content":response})
    st.chat_message("assistant").write(response)

 

코드는 간단합니다.

"질문을 입력하세요"라는 입력 박스에 질문을 입력하면,

messages 객체에 "user" 역할로 질문을 저장하고,

st.chat_message를 이용해서 질문을 화면에 출력합니다.

 

질문에 대한 답변을 "response"에 받아서,

messages에 "assistant"의 답변을 저장하고,

st.chat_message를 이용해서 답변을 화면에 출력합니다.

 

streamlit run streamlit_test.py로 실행을 해보면 아래와 같은 화면이 출력됩니다.

 

chatGPT와 꽤 비슷한 화면이 나왔죠?

 

여기서 문제가 하나 있습니다. messages 객체에 새로운 질문을 추가하면 마지막에 질문한 내용은 사라지고, 새로운 질문이 추가됩니다.

 

스트림릿은 기본적으로 이벤트가 발생할때마다 새로 페이지를 로드합니다.

매번 messages가 초기화 되니까, 기존에 있는 4개의 질의응답과 마지막 질의응답만 출력되는거죠.

 

이걸 어떻게 처리할 수 있을까요?

역시나 스트림릿에서 미리 해결책을 만들어놨죠. st.session_state를 사용하면 됩니다.

st.session_state는 rerun을 했을때도 내용이 유지되고, 멀티앱간에도 내용이 유지됩니다.

 

messages를 st.session_state.messages로 변경해보겠습니다.

기존에 messages에 있었던 4개의 대화도 삭제하도록 하겠습니다.

 

import streamlit as st

if "messages" not in st.session_state:
    st.session_state.messages = [{"role":"assistant","content":"무엇을 도와드릴까요?"}]

for m in st.session_state.messages:
    with st.chat_message(m["role"]):
        st.write(m["content"])

if query := st.chat_input("질문을 입력하세요."):
    st.session_state.messages.append({"role":"user", "content":query})
    st.chat_message("user").write(query)
    response = f"{query}질문에 대한 답변입니다."
    st.session_state.messages.append({"role":"assistant", "content":response})
    st.chat_message("assistant").write(response)

 

제일 윗부분은 대화가 하나도 없어서 messages가 생성될때 체크되는 부분입니다. 

아무 대화내용이 없으면 처음 AI가 "무엇을 도와드릴까요?"라는 문구를 출력합니다.

 

이후 하단 입력창에 질문을 하면 질문과 답변이 화면에 출력되고,

st.session_state.messages에 저장됩니다.

 

다음 이벤트 발생 시 화면에 출력했던 내용은 사라지고,

st.session_state.messages에 저장됐던 대화가 출력된 후,

사용자의 질문을 기다리게 됩니다.

 

이제 질문을 AI에게 보내서 답변을 받아오는 부분만 처리하면 됩니다.

고지가 얼마남지 않았습니다.

 

 

반응형