PA-RAG는 생성 모델이 검색된 문서를 충실하게 활용하도록 선호도 정렬(Preference Alignment)을 적용하는 RAG 아키텍처입니다. DPO(Direct Preference Optimization) 방식으로 검색 결과에 근거한 답변을 선호하고 환각된 답변을 비선호하도록 학습하여, 검색-생성 간의 정렬을 최적화합니다.
# 후보 생성용 LLM (다양한 답변을 위해 temperature 사용)candidate_llm = init_chat_model("gpt-4o-mini", temperature=0.7)def generate_candidates(state: PARAGState) -> PARAGState: """검색된 문서를 기반으로 다수의 후보 답변을 생성합니다.""" question = state["question"] documents = state["documents"] context = "\n\n".join(doc.page_content for doc in documents) prompt = ChatPromptTemplate.from_messages([ ("system", ( "다음 컨텍스트를 참고하여 질문에 답변하세요.\n" "컨텍스트에 포함된 정보만 사용하세요.\n\n{context}" )), ("human", "{question}"), ]) chain = prompt | candidate_llm | StrOutputParser() # 다수 후보 생성 candidates = [] for _ in range(3): answer = chain.invoke({"context": context, "question": question}) candidates.append(answer) return {"candidate_answers": candidates}
Copy
# 충실도 평가용 LLM (정확한 평가를 위해 상위 모델 사용)evaluator_llm = init_chat_model("gpt-4o", temperature=0)def score_faithfulness(state: PARAGState) -> PARAGState: """각 후보 답변이 검색 문서에 얼마나 충실한지 평가합니다.""" documents = state["documents"] candidates = state["candidate_answers"] docs_text = "\n\n".join(doc.page_content for doc in documents) prompt = ChatPromptTemplate.from_messages([ ("system", ( "답변이 주어진 문서에 얼마나 충실한지 1~5점으로 평가하세요.\n" "- 5점: 모든 내용이 문서에 근거함\n" "- 3점: 일부 내용이 문서에 없음\n" "- 1점: 대부분 문서와 무관한 내용\n" "숫자만 출력하세요." )), ("human", "문서:\n{documents}\n\n답변:\n{answer}"), ]) chain = prompt | evaluator_llm | StrOutputParser() scores = [] for candidate in candidates: result = chain.invoke({"documents": docs_text, "answer": candidate}) try: score = float(result.strip()) except ValueError: score = 1.0 scores.append(score) return {"faithfulness_scores": scores}