12. Streamlit을 활용한 RAG 챗봇 구현

2024. 11. 26. 00:30· Chatbot 프로젝트/RAG
목차
  1. 0. Streamlit 이란?
  2. 1. 필요한 라이브러리 설치
  3. 1. 1. vs 터미널 접속
  4. 1.2. 파이썬 파일 만들기
  5. 1.3. 소스 코드
  6. 2. 대화 이력 관리와 메모리구현
  7. 2.1. 파일 경로 설정 및 경로에 파일 업로드 (윈도우 기준)
  8. 2.2. 대화 이력 구현 코드
  9. 3. 결과 
  10. 3.1. vector store에 파일들 임베딩해서 저장
  11. 3.2  rag와 메모리 구현 결과
728x90

0. Streamlit 이란?

Streamlit은 파이썬 코드만으로 웹 앱의 프론트(화면)을 아주 쉽게 만들 수 있게 도와주는 프레임워크이다. 

👉 데이터 분석 결과나 머신러닝 모델을 웹으로 바로 보여주고 싶을 때 유용하다.
👉 복잡한 HTML/CSS/JS 없이 터미널에  "streamlit run app.py"만 입력하면 프로그램을 실행한다.

예시 코드:

# app.py

import streamlit as st

st.title("Hello, Streamlit!")
st.write("이건 정말 간단한 웹앱입니다.")
 

1. 필요한 라이브러리 설치

 pip install streamlit 

pip install langchain_openai

pip install langchain

pip install -U langchain-community

pip install PyPDF2

pip install chromadb



1. 1. vs 터미널 접속

아래 3개의 명령어를 터미널에 복붙해서 필요 라이브러리 설치

pip install streamlit

streamlit hello 

pip install langchain_openai

 

1.2. 파이썬 파일 만들기

import streamlit as st

st.write("안녕하세요")

앱 실행: streamlit run test.py

 

앱 실행

 

 

1.3. 소스 코드

import streamlit as st
import os
from langchain_openai import ChatOpenAI


os.environ["OPENAI_API_KEY"] = (
    "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"
)

st.title("CHATbot")


# session_state에 messages Key값 지정 및 Streamlit 화면 진입 시, AI의 인사말을 기록하기
if "messages" not in st.session_state:
    st.session_state["messages"] = [
        {"role": "assistant", "content": "안녕하세요 무엇을 도와드릴까요?"}
    ]

# 사용자나 AI가 질문/답변을 주고받을 시, 이를 기록하는 session_state
for msg in st.session_state.messages:
    st.chat_message(msg["role"]).write(msg["content"])


# 챗봇으로 활용할 AI 모델 선언
chat = ChatOpenAI(model="gpt-4o", temperature=0)

# chat_input()에 입력값이 있는 경우,
if prompt := st.chat_input():
    # messages라는 session_state에 역할은 사용자, 컨텐츠는 프롬프트를 각각 저장
    st.session_state.messages.append({"role": "user", "content": prompt})
    # chat_message()함수로 사용자 채팅 버블에 prompt 메시지를 기록
    st.chat_message("user").write(prompt)

    response = chat.invoke(prompt)
    msg = response.content

    # messages라는 session_state에 역할은 AI, 컨텐츠는 API답변을 각각 저장
    st.session_state.messages.append({"role": "assistant", "content": msg})
    # chat_message()함수로 AI 채팅 버블에 API 답변을 기록
    st.chat_message("assistant").write(msg)

 

 

2. 대화 이력 관리와 메모리구현

2.1. 파일 경로 설정 및 경로에 파일 업로드 (윈도우 기준)

  file_path = r"C:\Users\PC2309\Desktop\24-2\rag인강\streamlit\test\Constitution_of_Korea.pdf"

경로 앞에 r을 붙여서 한국어의 폴더 구조에서도 오류가 안나게 할 수 있다. 이때 파일명은 영어로 작성해야 한다.

2.2. 대화 이력 구현 코드

import os
import streamlit as st

from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores import Chroma
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from chromadb.config import Settings
from chromadb import Client

## 메모리 구현을 위한 라이브러리
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains import create_history_aware_retriever, create_retrieval_chain
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories.streamlit import (
    StreamlitChatMessageHistory,
)

# Set the OpenAI API key
os.environ["OPENAI_API_KEY"] = (
    "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"
)


# Streamlit에서는 @st.cache_resource를 통해 한번 실행한 자원을 리로드 시에 재실행하지 않도록 캐시메모리에 저장할 수 있습니다.
@st.cache_resource
def load_and_split_pdf(file_path):
    loader = PyPDFLoader(file_path)
    return loader.load_and_split()  # chunking이 아니라 쪽별로 갖고옴


# Create a vector store from the document chunks
@st.cache_resource
def create_vector_store(_docs):
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
    split_docs = text_splitter.split_documents(_docs)

    # Chroma DB 설정 (사용자가 원하는 경로에 저장)
    persist_directory = r"C:\Users\PC2309\Desktop\24-2\rag인강\streamlit\test\chroma_db"

    # Chroma DB 생성
    vectorstore = Chroma.from_documents(
        documents=split_docs,
        embedding=OpenAIEmbeddings(model="text-embedding-ada-002"),
        persist_directory=persist_directory,  # 새로운 방식의 persist_directory 사용
    )
    return vectorstore


# Initialize the LangChain components
@st.cache_resource
def initialize_components(selected_model):
    file_path = (
        r"C:\Users\PC2309\Desktop\24-2\rag인강\streamlit\test\Constitution_of_Korea.pdf"
    )
    pages = load_and_split_pdf(file_path)
    vectorstore = create_vector_store(pages)
    retriever = vectorstore.as_retriever()

    # Define the contextualize question prompt
    contextualize_q_system_prompt = """Given a chat history and the latest user question \
    which might reference context in the chat history, formulate a standalone question \
    which can be understood without the chat history. Do NOT answer the question, \
    just reformulate it if needed and otherwise return it as is."""
    contextualize_q_prompt = ChatPromptTemplate.from_messages(
        [
            ("system", contextualize_q_system_prompt),
            MessagesPlaceholder("history"),
            ("human", "{input}"),
        ]
    )

    # Define the answer question prompt
    qa_system_prompt = """You are an assistant for question-answering tasks. \
    Use the following pieces of retrieved context to answer the question. \
    If you don't know the answer, just say that you don't know. \
    Keep the answer perfect. please use imogi with the answer.
    대답은 한국어로 하고, 존댓말을 써줘.\

    {context}"""
    qa_prompt = ChatPromptTemplate.from_messages(
        [
            ("system", qa_system_prompt),
            MessagesPlaceholder("history"),
            ("human", "{input}"),
        ]
    )

    llm = ChatOpenAI(model=selected_model)
    history_aware_retriever = create_history_aware_retriever(
        llm, retriever, contextualize_q_prompt
    )
    question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
    rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
    return rag_chain


# Streamlit UI
st.header("헌법 Q&A 챗봇 💬 📚")
option = st.selectbox("Select GPT Model", ("gpt-4o", "gpt-3.5-turbo-0125"))
rag_chain = initialize_components(option)
chat_history = StreamlitChatMessageHistory(key="chat_messages")

conversational_rag_chain = RunnableWithMessageHistory(
    rag_chain,
    lambda session_id: chat_history,
    input_messages_key="input",
    history_messages_key="history",
    output_messages_key="answer",
)


if "messages" not in st.session_state:
    st.session_state["messages"] = [
        {"role": "assistant", "content": "헌법에 대해 무엇이든 물어보세요!"}
    ]

for msg in chat_history.messages:
    st.chat_message(msg.type).write(msg.content)


if prompt_message := st.chat_input("Your question"):
    st.chat_message("human").write(prompt_message)
    with st.chat_message("ai"):
        with st.spinner("Thinking..."):
            config = {"configurable": {"session_id": "any"}}
            response = conversational_rag_chain.invoke(
                {"input": prompt_message}, config
            )

            answer = response["answer"]
            st.write(answer)
            with st.expander("참고 문서 확인"):
                for doc in response["context"]:
                    st.markdown(doc.metadata["source"], help=doc.page_content)

 

3. 결과 

3.1. vector store에 파일들 임베딩해서 저장

3.2  rag와 메모리 구현 결과

728x90

'Chatbot 프로젝트 > RAG' 카테고리의 다른 글

RAG 기초 FAST API  (0) 2024.11.26
1. RAG 기초와 파이프라인  (8) 2024.10.31
  1. 0. Streamlit 이란?
  2. 1. 필요한 라이브러리 설치
  3. 1. 1. vs 터미널 접속
  4. 1.2. 파이썬 파일 만들기
  5. 1.3. 소스 코드
  6. 2. 대화 이력 관리와 메모리구현
  7. 2.1. 파일 경로 설정 및 경로에 파일 업로드 (윈도우 기준)
  8. 2.2. 대화 이력 구현 코드
  9. 3. 결과 
  10. 3.1. vector store에 파일들 임베딩해서 저장
  11. 3.2  rag와 메모리 구현 결과
'Chatbot 프로젝트/RAG' 카테고리의 다른 글
  • RAG 기초 FAST API
  • 1. RAG 기초와 파이프라인
조찬국
조찬국
개발자가 되기위해 매일매일 체득하며 배우는 학생입니다.
조찬국
changuk.log
조찬국
전체
오늘
어제
  • 분류 전체보기 (68)
    • Spring Boot (30)
      • Spring Boot 입문 강의 정리(김영한) (8)
      • Spring Boot JPA-기본편 강의 정리(.. (8)
      • Spring Boot JPA-활용편1 강의 정리 (7)
      • Spring Boot JPA-활용편2 강의 정리 (5)
      • Spring Boot 블로그(Blog) 만들기 프.. (2)
      • Spring Boot -Project 정리(Bac.. (0)
    • SQLD (2)
      • 데이터 모델링 (1)
      • 데이터 모델과 SQL (1)
    • 프로젝트 (1)
      • 플러터 (1)
      • 안드로이드 스튜디오 (0)
    • 캡스톤디자인 (2)
      • IoT 및 하드웨어 (1)
      • 모바일 프론트엔드 (1)
      • 백엔드 (0)
    • CS스터디 (5)
    • 수업자료 (13)
      • sw공학 (5)
      • database (8)
    • Chatbot 프로젝트 (13)
      • RAG (3)
      • LangChain (9)
      • FastAPI (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 김영한
  • document loader
  • Spring
  • Blog
  • Spirng Boot
  • lanchain
  • 관계
  • computer sience
  • 오블완
  • CS
  • SQL
  • spring boot
  • LLM
  • Chat bot
  • text splitter
  • 비선형 자료 구조
  • 티스토리챌린지
  • uvicorn
  • RAG
  • retrievers
  • langchain
  • vector store
  • chatbot
  • SQLD
  • prompt tempate
  • LCEL
  • ese32
  • restapi
  • embeddings
  • 선형 자료 구조

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
조찬국
12. Streamlit을 활용한 RAG 챗봇 구현
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.