개발관련/AI 이야기

PDF 문서 기반 Q&A 시스템 구축: LlamaIndex, ChromaDB, Ollama 활용 2부

후니의 개발이야기 2025. 5. 27. 09:38
728x90
반응형

오전에 올린 포스팅의 2부 마지막부입니다.

 terminal 에서 질의를 한다는 것은 어찌보면 사용자측면에서는 좋은 것이 아니라 이 부분도 어떻게 할지 고민하다가 역시나 AI와 같이 협업을 통해서 성과물을 만들어 보았습니다.

Streamlit으로 Q&A 인터페이스 구축

이 UI 는 인덱스를 로드하고 mistral 모델로 한국어 답변을 하는 것을 만들어 본 소스입니다.

from llama_index.core import StorageContext, load_index_from_storage
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.core.prompts import PromptTemplate
import chromadb
import streamlit as st
import os

CHROMA_DIR = "./chroma_index"
COLLECTION_NAME = "my_index"

def load_index():
    embed_model = OllamaEmbedding(model_name="nomic-embed-text")
    chroma_client = chromadb.HttpClient(host="localhost", port=8000)
    chroma_collection = chroma_client.get_or_create_collection(
        name=COLLECTION_NAME, metadata={"hnsw:space": "cosine"}
    )
    chroma_store = ChromaVectorStore(chroma_collection=chroma_collection, chroma_client=chroma_client)
    storage_context = StorageContext.from_defaults(vector_store=chroma_store, persist_dir=CHROMA_DIR)

    index = load_index_from_storage(storage_context, embed_model=embed_model)
    return index

st.set_page_config(page_title="📖 PDF 문서 기반 Q&A 시스템")
st.title("📖 PDF 문서 기반 Q&A")
st.markdown("🤖 PDF 내용을 바탕으로 질문에 답변합니다.")

question = st.text_input("질문을 입력하세요:", placeholder="예: 부자가 되는 방법")
if question:
    index = load_index()
    if index:
        qa_prompt = PromptTemplate(
            "질문: {query_str}\n컨텍스트: {context_str}\n답변: 한국어로만 답변해 주세요."
        )
        query_engine = index.as_query_engine(
            llm=Ollama(model="mistral"), text_qa_template=qa_prompt
        )
        with st.spinner("🔍 답변 생성 중..."):
            response = query_engine.query(question)
            st.markdown("### 🤖 답변")
            st.success(response.response)

이 소스는 

1. ./chroma_index에서 인덱스 로드
2. 한국어로 답변 시키도록 프롬프트 적용 
  => PromptTemplate 한국어로만 답변해주세요 라고 해야 한국어로 나와요 
       아니면 영어로 나오니 주의하세요 <- 저도 사실 이 부분이 제일 이해가 안되는 부분 
3. Streamlit 웹 에서 질문과 답변 표시 

실행 방법 

uv run streamlit run query_index.py

저는 이번 프로젝트에 사용한 pdf 파일은 세이노의 가르침 을 사용했습니다.

링크 주소는 아래와 같습니다.

https://blog.naver.com/dayonepress/223515971889

 

📚세이노의 가르침-무료 전자책과 오디오북 안내 (2025. 04. 23 update)

"세이노의 가르침-피보다 진하게 살아라" 데이원 운영 공식 블로그와 카페 ‘세이노의 가르침-피...

blog.naver.com

 

겪은 문제와 해결법

1. 인덱스로드 실패 :   persist_dir 를 지정하지 않아 에러 발생 
StorageContext.from_defaults(persist_dir=CHROMA_DIR) 로 해결
2. 영어로 답변 문제 : PromptTemplate 에 한국어로 답변 지시 추가 
3. ChromaDB 연결 문제 : ./chroma_index 초기화 및 서버 재시작 

chroma run --path ./chroma_index

4. ChromaDB 가 구동중인지 확인 방법

http://localhost:8000/api/v1/heartbeat

이렇게 해서 작은 토이프로젝트를 하루만에 끝냈습니다. 
역시 이번 기회에 AI 활용하는 것이 얼마나 중요한지 그리고 제가 만약에 혼자 했다면 이것은 한 1주 이상은 걸릴것 같았는데라는 생각이 들더군요. 

4. 팁

디버깅: 스크립트에 logging.basicConfig(level=logging.DEBUG) 추가 

회고

이 프로젝트를 통해서 AI 와 벡터 데이터베이스에 대해서 약간에 대한 감을 가지게 되었답니다.  LlamaIndex 를 이용해서 PDF 인덱싱, ChromaDB 에 저장하며 Ollama Mistral 모델로 질문에 답변하는 시스템 구축은 정말 좋은 경험이고 앞으로 나아갈 수 있는 한걸음이었습니다. 

즐거운 코딩되세요.

 

728x90
반응형