단순히 검색(Search)해서 보여주는 것을 넘어, AI가 규정을 이해하고 논리적으로 **추론(Reasoning/Thinking)**하여 복잡한 질문에 답하는 능력이 왜 필요한지 학습합니다.
RAG는 흔히 **"검색해서(Retrieval) 답변하기(Generation)"**라고 합니다. 하지만 현실의 질문은 단순히 문서의 한 문장을 찾는 것으로 끝나지 않습니다.
step4_reasoning.py학습 가이드의 일관성을 위해 3단계와 동일한 구조의 전체 코드를 사용합니다.
from langchain_classic.chains import RetrievalQA
from langchain_chroma import Chroma
from langchain_ollama import OllamaEmbeddings, ChatOllama
from langchain_core.documents import Document
from langchain_core.prompts import PromptTemplate
# 1. 데이터 준비 (3단계와 동일)
docs = [
Document(page_content="[인사규정] 신입사원 휴가 및 연차: 신입사원은 입사 후 처음 3년 동안은 법정 연차가 발생하지 않습니다. 대신 매월 1회의 유급 '리프레시 데이'를 휴가로 사용할 수 있습니다.", metadata={"source": "인사규정"}),
Document(page_content="[보안규정] 업무 보안: 모든 임직원은 회사에서 지급한 승인된 보안 USB만 사용해야 하며, 개인 USB나 외부 저장 매체 사용은 엄격히 금지됩니다.", metadata={"source": "보안규정"}),
Document(page_content="[복지규정] 식대 지원: 점심 식사는 무제한 법인카드로 지원하며, 저녁 식사는 오후 9시 이후 야근 시에만 사용이 가능합니다.", metadata={"source": "복지규정"}),
]
# 2. VectorDB 생성
print("문서를 학습(임베딩) 중입니다...")
try:
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vectorstore = Chroma.from_documents(documents=docs, embedding=embeddings)
# 3. 검색기(Retriever) 설정 (k=3으로 전체를 참고하도록 설정)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 4. 프롬프트 템플릿
template = """당신은 회사의 규정에 대해 설명해주는 AI 비서입니다.
아래의 참고 정보를 바탕으로 질문에 답하세요. 반드시 한국어로 답변해야 합니다.
참고 정보: {context}
질문: {question}
답변:"""
PROMPT = PromptTemplate(template=template, input_variables=["context", "question"])
# 5. RAG 체인 연결 (추론 모델 사용)
llm = ChatOllama(model="deepseek-r1:8b", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
return_source_documents=True,
chain_type_kwargs={"prompt": PROMPT}
)
# 6. 추론이 필요한 복잡한 질문 던지기
question = "입사 6개월차 신입인데 리프레시 데이 2번 썼어. 몇 번 남았는지 규정 기반으로 계산해줘."
print(f"\\\\n질문: {question}")
print("-" * 30)
result = qa_chain.invoke({"query": question})
print("\\\\n--- AI 답변 ---")
print(result['result'])
except Exception as e:
print(f"\\\\n❌ 에러 발생: {e}")