다양한 활동/대회 참가

[대회/데이콘-새싹톤🌱] pre. 챗봇 만들기 학습(6) : 스트림릿을 활용한 LLM 모델 실행 - LLM모델과 스트림릿(Streamlit)

토끼개발자 조르디 2024. 7. 19. 21:39

👾 목표 👾

LLM 기능을 활용한 웹페이지를 제작

Langchain 을 이용해 언어모델에 필요한 여러 도구들을 불러오고,
이것을 웹 화면애 적용해 서비스 형태로 만들자.

1. 환경 변수

1.1. 환경 변수 셋팅 하기 (윈도우)

 

**참고**

윈도우의 경우 환경변수를 새로 만들어 줍니다.

LANGCHAIN_TRACING_V2, LANGCHAIN_ENDPOINT, LANGCHAIN_API_KEY, LANGCHAIN_PROJECT, OPENAI_API_KEY

다섯가지 환경 변수를 만들어 줍니다.

 

1.2. 환경 변수 셋팅 하기 (리눅스, Mac OS)

 

**참고**

리눅스의 경우 아래 내용을 
~/.bashrc     에 추가해 주세요.

MacOS의 경우     ~/.bashrc    또는     ~/.zshrc     에 추가해 주세요.
export LANGCHAIN_TRACING_V2='true'
export LANGCHAIN_ENDPOINT='https://api.smith.langchain.com'
export LANGCHAIN_API_KEY=''
export LANGCHAIN_PROJECT=''
export OPENAI_API_KEY=''

 

1.3. 환경 변수 파이참에서 적용하기

환경 변수를 적용해준 이후, 파이참을 완전히 종료하고 다시 실행

 

 

2. 라이브러리 불러오기

LLM과 Streamlit 이용에 필요한 라이브러리를 불러온다

import streamlit as st
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser

 

  • streamlit : 스트림릿 라이브러리
  • langchain_openai : ChatGPT 를 langchain 에서 사용하기 위한 라이브러리
  • langchain)core : 랭체인 라이브러리

 

3. 문구 데이터

웹페이지에서 사용할 문구들을 만들어 준다.

그리고 LLM에 들어갈 프롬프트도 함께 만들어 준다.

message = {
    'title': '물어보세요, 채팅로봇!',
    'input': '도시의 이름을 입력하세요: ',
    'fail': '응답을 받지 못했어요.',
    'prompt': "{city}의 대표적인 자랑거리는 뭐야?"
}

 

 

4. 체인 만들기

4.1. 인스턴스 변수 설명

  • user_input_text : 유저가 입력한 텍스트를 인스턴스 변수에 저장
  • prompt_template : 프롬프트 탬플릿 객체
  • chain : 체인 객체. 프롬프트, LLM 모델, 출력 파서를 연결
  • chat_history : 전체 대화 내용을 기록

4.2. 유저 입력

  • set_user_input : LLM에 입력으로 들어갈 유저의 입력을 받아 인스턴스 변수에 저장
  • get_response : 유저의 질문에 대답하는 로직. chain을 실행해 결과를 반환한다. 만약 대답을 가져오는데 실패하면, 실패 메시지를 반환.

4.3. 파이썬 코드 실행

파이썬 코드

class LLM:
    def __init__(self):
        self.user_input_text = None
        self.prompt_template = PromptTemplate.from_template(message['prompt'])
        self.llm = ChatOpenAI()
        self.chain = self.prompt_template | self.llm | StrOutputParser()
        self.chat_history = []

    def set_user_input(self, user_input_text):
        # 유저의 입력 받기
        self.user_input_text = user_input_text

    def get_response(self):
        # GPT 대답
        if self.user_input_text:
            response = self.chain.invoke(self.user_input_text)
            self.chat_history.append({"question": self.user_input_text, "answer": response})
            return response
        else:
            return message['fail']

 

 

5. 메인 함수 정의

5.1. 세션 관리

메인 함수에서는 LLM을 관리하는 인스턴스가 존재

이 인스턴스에서는 대화 히스토리를 담고 있다.

따라서 main 함수가 실행될 때마다 인스턴스가 초기화 되어서는 안된다.

인스턴스를 보존하기 위해서는 인스턴스를 세션에 담아 관리할 수 있다.

 

st.session_state

: Streamlit에서 세션 간의 상태를 관리하기 위해 사용되는 객체

- 이를 통해 사용자는 특정 변수나 상태를 여러 사용자 인터랙션에 걸쳐 지속적으로 유지 가능

- 예 : 사용자가 입력한 데이터를 유지, 체크박스 상태를 기억, 계산된 값을 저장 등

 

if 'llm' not in st.session_state

: 구문을 사용해, 'llm'이름의 객체가 있으면, 새롭게 초기화 하지 않도록 한다.

 

st.session_state.llm = LLM()

: LLM 객체를 세션에 'llm' 이라는 이름으로 저장하도록 한다.

 

5.2. 사용자의 질문 받기

st.text_input 함수를 이용해,  LLM에게 질문할 내용을 받는다.

 

5.3. 대답 받기

if문과 st.button() 함수의 조합으로,

버튼을 누르면 사용자에게 받을 질문을 llm 객체로 전달하고 모델을 실행해 대답을 받아오도록 한다.

 

5.4. 채팅 히스토리 출력

chat_history를 불러와 그동안 대화했던 전체 내용을 불러와 출력을 한다.

최신 질문과 대답이 가장 상단에 올라가도록 한다.

[ : : -1 ] 을 붙여주면 for문을 역순으로 실행하게 된다.

 

for문 내부에 st.write를 실행해주면, 반복해서 문구를 출력

 

5.5. 파이썬 코드 실행

파이썬 코드

def main():
    # 세션 관리
    if 'llm' not in st.session_state:
        st.session_state.llm = LLM() # UseCase 인스턴스를 세션 상태에 저장

    # 사용자의 질문 받기
    st.title(message['title'])
    user_input_text = st.text_input(message['input'], key="user_input")
    
    # 대답 받기
    if st.button('대답 받기', key="submit"):
        st.session_state.llm.set_user_input(user_input_text)
        st.session_state.llm.get_response()
        
    if st.session_state.llm.chat_history:
        for chat in st.session_state.llm.chat_history[::-1]:
            st.write(f"Q: {chat['question']}")
            st.write(f"A: {chat['answer']}")
            st.markdown("---")

 

 

6. 메인 함수 실행

5.1. 세션 관리

메인 함수를 실행해 코드를 완성

실행 버튼을 눌러 웹 서버를 실행

if __name__ == '__main__':
    main()