KeiStory

반응형

streamlit 으로 나만의 GPT 채팅 서비스 제작하는 방법
 
먼저 OpenAPI 에서 Key 를 발급받아야 합니다.
2024.06.08 - [코딩/Python_AI] - Open API 사용을 위한 Key 발급 받기 및 요금

Open API 사용을 위한 Key 발급 받기 및 요금

Open API 사용을 위한 Key 발급받기 및 요금 Open API 키를 발급받는 방법을 알아봅니다. 아래 사이트에서 회원가입을 진행합니다.https://platform.openai.com/  회원 가입 후 Dashboard 로 이동하고 API keys 로

keistory.tistory.com

 
schat.py

import streamlit as st
from utils import print_messages, StreamHandler
from langchain_core.messages import ChatMessage
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# 메시지 기록
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

# API KEY 정보로드
import os
os.environ["OPENAI_API_KEY"] ="key"

st.set_page_config(page_title="S Chat", page_icon="💬")
st.title("💬Streamlit CHAT")

if "messages" not in st.session_state:
    st.session_state["messages"] = []

# 채팅 대화 기록을 저장하는 store 세션 상태 변우
if "store" not in st.session_state:
    st.session_state["store"] = dict()

with st.sidebar:
    session_Id = st.text_input("Session ID", "test_session")
    clear_button = st.button("대화기록 초기화")
    if clear_button:
        st.session_state["messages"] = [] #화면 상 대화 내용 삭제
        st.session_state["store"] = dict() #대화 저장 기록 제거
        st.experimental_rerun()

# 무조건 리프레시가 일어나 이전 대화내용 저장하고 출력해야 대화 내용이 유지됨
print_messages()

store = st.session_state["store"]  # 세션 기록을 저장할 딕셔너리

# 세션 ID를 기반으로 세션 기록을 가져오는 함수
def get_session_history(session_ids: str) -> BaseChatMessageHistory:
    print(session_ids)
    if session_ids not in store:  # 세션 ID가 store에 없는 경우
        # 새로운 ChatMessageHistory 객체를 생성하여 store에 저장
        store[session_ids] = ChatMessageHistory()
    return store[session_ids]  # 해당 세션 ID에 대한 세션 기록 반환


if user_input := st.chat_input("메시지를 입력해 주세요."):
    # 사용자가 입력한 내용
    st.chat_message("user").write(f"{user_input}")
    st.session_state["messages"].append(ChatMessage(role="user", content=user_input))

    # AI 가 답변한 내용
    with st.chat_message("assistant"):
        stream_handler = StreamHandler(st.empty())

        # 1. 모델 생성
        llm = ChatOpenAI(streaming=True, callbacks=[stream_handler])

        # 2. 프롬프트 생성
        prompt = ChatPromptTemplate.from_messages(
            [
                (
                    "system",
                    "질문에 대하여 간결하게 답변해 주세요",
                ),
                # 대화 기록을 변수로 사용, history 가 MessageHistory 의 key 가 됨
                MessagesPlaceholder(variable_name="history"),
                ("human", "{question}"),  # 사용자 입력을 변수로 사용
            ]
        )

        chain = prompt | llm  # 프롬프트와 모델을 연결하여 chain 객체 생성

        chain_with_memory = (
            RunnableWithMessageHistory(  # RunnableWithMessageHistory 객체 생성
                chain,  						# 실행할 chain 객체
                get_session_history,            # 세션 기록을 가져오는 함수
                input_messages_key="question",  # 사용자 질문의 키
                history_messages_key="history", # 기록 메시지의 키
            )
        )


        # 기록 기반
        response = chain_with_memory.invoke(
                        {"question": user_input},
                        config={"configurable": {"session_id": session_Id}})
        
        msg = response.content

        st.session_state["messages"].append(ChatMessage(role="assistant", content=msg))

 
utils.py

import streamlit as st

def print_messages() :
    # 이전 대화기록 출력
    if "messages" in st.session_state and len(st.session_state["messages"]) > 0 :
        #for role, message in st.session_state["messages"]:
        for chat_message in st.session_state["messages"]:
            #st.chat_message(role).write(message)
            st.chat_message(chat_message.role).write(chat_message.content)


from langchain.callbacks.base import BaseCallbackHandler

# 답변을 실시간으로 표시해 주기
class StreamHandler(BaseCallbackHandler):
    def __init__(self, container, initial_text=""):
        self.container = container
        self.text = initial_text

    def on_llm_new_token(self, token: str, **kwargs) -> None:
        self.text += token
        self.container.markdown(self.text)

 
실행

streamlit run schat.py

 
결과

왼쪽에 Session ID 를 변경하면 새로운 채팅창이 열린 것으로 인식하게 됩니다.
Session ID 가 동일하다면 대화 내용을 저장하고 저장된 대화 내용을 기반하여 대화할 수 있습니다.

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band