KeiStory

LangChain 으로 RAG 기반 Wiki 데이터 활용한 채팅창 만들기

 

Streamlit을 사용하여 RAG (Retrieval-Augmented Generation) 기반 채팅 시스템을 구축하는 방법입니다.

OpenAI의 GPT 모델과 Wikipedia 데이터를 활용하여 사용자 질문에 대한 답변을 제공합니다.

설명은 소스의 주석으로 대신합니다.

import os
import streamlit as st
from langchain_community.document_loaders import WikipediaLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate

# OpenAI API 키 설정 (환경 변수로 설정)
os.environ["OPENAI_API_KEY"] = "sk-proj-*"

# 문서를 로드하는 함수
def load_docs(query):
    # WikipediaLoader를 사용하여 위키피디아 문서 로드
    loader = WikipediaLoader(query=query, load_max_docs=1)
    documents = loader.load()

    # 텍스트를 청크로 나누기 위해 텍스트 분할기 생성
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
    splits = text_splitter.split_documents(documents=documents)

    return splits

# 벡터 저장소를 생성하는 함수
def create_vectorstore(splits):
    # OpenAI 임베딩 생성
    embeddings = OpenAIEmbeddings()
    # Chroma 벡터 저장소 생성
    vectorstore = Chroma.from_documents(documents=splits, embedding=embeddings)
    return vectorstore

# RAG (Retrieval-Augmented Generation) 체인을 생성하는 함수
def create_rag_chain(vectorstore):
    # OpenAI GPT 모델 로드
    llm = ChatOpenAI(model_name="gpt-4", temperature=0)
    
    # 답변 생성을 위한 프롬프트 템플릿 정의
    prompt_template = """아래의 규칙을 지켜 질문에 답하세요
    만약 답을 모른다면, 모른다고 말하고 답을 지어내지 마세요.
    길지 않게 답하고 가능한 한 간결하게 답하세요.
    {context}
    질문: {question}
    유용한 답변:"""
    
    # 프롬프트 템플릿 구성
    PROMPT = PromptTemplate(
        template=prompt_template, input_variables=["context", "question"]
    )

    # 체인 생성 시 사용할 매개변수 설정
    chain_type_kwargs = {"prompt": PROMPT}
    
    # RetrievalQA 체인 생성
    qa_chain = RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=vectorstore.as_retriever(),
        chain_type_kwargs=chain_type_kwargs,
        return_source_documents=True
    )
    
    return qa_chain

# Streamlit 애플리케이션 제목 설정
st.title("RAG Q&A 시스템")

# 사용자로부터 위키피디아 주제 입력 받기
topic = st.text_input("위키피디아 주제 입력")
# 사용자로부터 질문 입력 받기
question = st.text_input("해당 주제에 대해 질문")

# 주제와 질문이 입력되었을 경우
if topic and question:
    if st.button("답변 받기"):  # 버튼 클릭 시
        with st.spinner("처리 중..."):  # 처리 중 스피너 표시
            # 문서 로드 및 분할
            splits = load_docs(topic)
            
            # 벡터 저장소 생성
            vectorstore = create_vectorstore(splits)
            
            # RAG 체인 생성
            qa_chain = create_rag_chain(vectorstore)
            
            # 질문에 대한 답변 생성
            result = qa_chain({"query": question})
            
            # 생성된 답변 출력
            st.subheader("답변:")
            st.write(result["result"])
            
            # 출처 문서 표시
            st.subheader("출처:")
            for doc in result["source_documents"]:
                st.write(doc.page_content)  # 출처 내용 출력
                st.write("---")  # 구분선 추가

# 사이드바 구성
st.sidebar.title("소개")
st.sidebar.info(
    "위키피디아를 소스로 사용하고 OpenAI의 GPT 모델을 통해 답변을 생성합니다."
)

 

결과

 

위키피디아의 주제란에 입력된 데이터 기준으로 Wiki 에서 데이터를 가져와 Vector 를 구성하고 질문항목에 대한 답변을 찾아 응답하게됩니다.

 

requirements.txt

aiohappyeyeballs==2.4.4
aiohttp==3.11.11
aiosignal==1.3.2
altair==5.5.0
annotated-types==0.7.0
anyio==4.7.0
asgiref==3.8.1
async-timeout==4.0.3
attrs==24.3.0
backoff==2.2.1
bcrypt==4.2.1
beautifulsoup4==4.12.3
blinker==1.9.0
build==1.2.2.post1
cachetools==5.5.0
certifi==2024.12.14
charset-normalizer==3.4.0
chroma-hnswlib==0.7.6
chromadb==0.5.23
click==8.1.8
colorama==0.4.6
coloredlogs==15.0.1
dataclasses-json==0.6.7
Deprecated==1.2.15
distro==1.9.0
durationpy==0.9
exceptiongroup==1.2.2
fastapi==0.115.6
filelock==3.16.1
flatbuffers==24.12.23
frozenlist==1.5.0
fsspec==2024.12.0
gitdb==4.0.11
GitPython==3.1.43
google-auth==2.37.0
googleapis-common-protos==1.66.0
greenlet==3.1.1
grpcio==1.68.1
h11==0.14.0
httpcore==1.0.7
httptools==0.6.4
httpx==0.28.1
httpx-sse==0.4.0
huggingface-hub==0.27.0
humanfriendly==10.0
idna==3.10
importlib_metadata==8.5.0
importlib_resources==6.4.5
Jinja2==3.1.5
jiter==0.8.2
jsonpatch==1.33
jsonpointer==3.0.0
jsonschema==4.23.0
jsonschema-specifications==2024.10.1
kubernetes==31.0.0
langchain==0.3.13
langchain-community==0.3.13
langchain-core==0.3.28
langchain-openai==0.2.14
langchain-text-splitters==0.3.4
langsmith==0.2.4
markdown-it-py==3.0.0
MarkupSafe==3.0.2
marshmallow==3.23.2
mdurl==0.1.2
mmh3==5.0.1
monotonic==1.6
mpmath==1.3.0
multidict==6.1.0
mypy-extensions==1.0.0
narwhals==1.19.1
numpy==1.26.4
oauthlib==3.2.2
onnxruntime==1.20.1
openai==1.58.1
opentelemetry-api==1.29.0
opentelemetry-exporter-otlp-proto-common==1.29.0
opentelemetry-exporter-otlp-proto-grpc==1.29.0
opentelemetry-instrumentation==0.50b0
opentelemetry-instrumentation-asgi==0.50b0
opentelemetry-instrumentation-fastapi==0.50b0
opentelemetry-proto==1.29.0
opentelemetry-sdk==1.29.0
opentelemetry-semantic-conventions==0.50b0
opentelemetry-util-http==0.50b0
orjson==3.10.12
overrides==7.7.0
packaging==24.2
pandas==2.2.3
pillow==11.0.0
posthog==3.7.4
propcache==0.2.1
protobuf==5.29.2
pyarrow==18.1.0
pyasn1==0.6.1
pyasn1_modules==0.4.1
pydantic==2.10.4
pydantic-settings==2.7.0
pydantic_core==2.27.2
pydeck==0.9.1
Pygments==2.18.0
PyPika==0.48.9
pyproject_hooks==1.2.0
pyreadline3==3.5.4
python-dateutil==2.9.0.post0
python-dotenv==1.0.1
pytz==2024.2
PyYAML==6.0.2
referencing==0.35.1
regex==2024.11.6
requests==2.32.3
requests-oauthlib==2.0.0
requests-toolbelt==1.0.0
rich==13.9.4
rpds-py==0.22.3
rsa==4.9
shellingham==1.5.4
six==1.17.0
smmap==5.0.1
sniffio==1.3.1
soupsieve==2.6
SQLAlchemy==2.0.36
starlette==0.41.3
streamlit==1.41.1
sympy==1.13.3
tenacity==9.0.0
tiktoken==0.8.0
tokenizers==0.20.3
toml==0.10.2
tomli==2.2.1
tornado==6.4.2
tqdm==4.67.1
typer==0.15.1
typing-inspect==0.9.0
typing_extensions==4.12.2
tzdata==2024.2
urllib3==2.3.0
uvicorn==0.34.0
watchdog==6.0.0
watchfiles==1.0.3
websocket-client==1.8.0
websockets==14.1
wikipedia==1.4.0
wrapt==1.17.0
yarl==1.18.3
zipp==3.21.0

 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band