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
Llama 3.2 Vision 자동차 번호 인식 (0) | 2024.12.24 |
---|---|
Python에서 2차원 배열 중 특정 열의 값을 모두 바꾸기 (0) | 2024.10.27 |
FAISS 뷰어 (0) | 2024.10.22 |
BitNet - CPU에서 실행되는 LLM 테스트 하기 (0) | 2024.10.22 |
로컬에 streamlit 로 llama 3.2 Vision 채팅창 만들기 (0) | 2024.10.15 |