안녕하세요! 오늘은 LangGraph를 사용하여 AI 답변의 퀄리티와 정확도를 평가하는 다양한 방법에 대해 알아보겠습니다. AI 시스템이 제대로 작동하는지 확인하는 건 정말 중요하죠? 함께 살펴볼게요!
LangGraph에서 평가가 왜 중요한가요? 🤔
레스토랑 셰프가 요리를 만들고 손님에게 내기 전에 맛을 보는 것처럼, AI 시스템도 사용자에게 전달하기 전에 품질을 확인해야 합니다. LangGraph에서는 이런 평가를 워크플로우 내에 자연스럽게 통합할 수 있어요!
기본 평가 노드 구현하기 🔨
평가 노드란?
LangGraph에서 평가 노드는 AI가 생성한 답변을 판단하는 특별한 단계예요. 마치 학교 선생님이 학생의 시험지를 채점하는 것과 비슷하죠!
def evaluate_response(state):
response = state["response"]
query = state["query"]
# LLM을 사용한 평가
evaluation_prompt = f"""
평가해야 할 질문과 답변이 있습니다:
질문: {query}
답변: {response}
다음 기준으로 1-10점 평가해주세요:
1. 정확성: 사실에 기반하나요?
2. 관련성: 질문과 관련 있나요?
3. 완전성: 모든 측면을 다루었나요?
4. 명확성: 이해하기 쉬운가요?
"""
evaluator = ChatOpenAI(temperature=0)
evaluation = evaluator.invoke(evaluation_prompt)
return {
"evaluation": evaluation,
"next": "feedback_decision"
}
# 그래프에 평가 노드 추가하기
workflow.add_node("evaluate", evaluate_response)
workflow.add_edge("generate_response", "evaluate")
평가 결과에 따른 분기 처리
def feedback_router(state):
# 간단한 점수 추출 (실제로는 더 정교한 파싱 필요)
if "7점 이상" in state["evaluation"]:
return "final_response"
else:
return "improve_response"
workflow.add_conditional_edges("evaluate", feedback_router)
workflow.add_edge("improve_response", "generate_response") # 다시 생성
이렇게 하면 품질이 낮은 응답은 개선 루프를 통해 다시 생성되고, 좋은 응답만 사용자에게 전달됩니다!
LLM 심사관: AI가 AI를 평가해요 👨⚖️
마치 요리 경연대회의 심사위원처럼, 다른 LLM을 '심사관'으로 활용할 수 있어요.
def judge_responses(state):
response_1 = state["response_model_a"]
response_2 = state["response_model_b"]
query = state["query"]
judge_prompt = f"""
다음 질문에 대한 두 응답을 비교해주세요:
질문: {query}
응답 A: {response_1}
응답 B: {response_2}
더 나은 응답은 어떤 것인지, 이유와 함께 선택해주세요.
"""
judge = ChatOpenAI(model="gpt-4")
judgment = judge.invoke(judge_prompt)
# 판정 결과에 따라 처리
if "응답 A가 더 낫습니다" in judgment:
better_response = response_1
else:
better_response = response_2
return {
"final_response": better_response,
"judgment": judgment
}
이 방법은 여러 모델이나 프롬프트 전략을 비교할 때 특히 유용해요!
인간 피드백 통합하기 👥
때로는 AI보다 사람의 판단이 더 중요합니다. 사용자 피드백을 워크플로우에 통합해 보세요:
def collect_human_feedback(state):
response = state["response"]
# 실제로는 UI를 통해 수집
print(f"응답: {response}")
score = input("품질 점수(1-5): ")
comments = input("개선 제안: ")
return {
"human_score": int(score),
"human_comments": comments,
"next": "process_feedback"
}
def improve_based_on_feedback(state):
if state["human_score"] <= 3: # 점수가 낮은 경우
# 피드백을 반영한 개선
improvement_prompt = f"""
다음 응답을 개선해주세요:
원본: {state["response"]}
사용자 피드백: {state["human_comments"]}
"""
llm = ChatOpenAI()
improved = llm.invoke(improvement_prompt)
return {"improved_response": improved}
else:
return {"final_response": state["response"]}
메트릭 기반 자동 평가 📊
숫자로 측정할 수 있는 객관적인 지표를 활용하면 더 일관된 평가가 가능합니다:
def calculate_metrics(state):
generated = state["response"]
reference = state["reference_answer"] # 정답
# 다양한 메트릭 계산
metrics = {}
# 1. ROUGE 점수 (텍스트 유사성)
from rouge import Rouge
rouge = Rouge()
metrics["rouge"] = rouge.get_scores(generated, reference)[0]
# 2. 의미적 유사도 (코사인 유사도)
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
gen_emb = model.encode([generated])
ref_emb = model.encode([reference])
from sklearn.metrics.pairwise import cosine_similarity
metrics["semantic_similarity"] = float(cosine_similarity(gen_emb, ref_emb)[0][0])
# 3. 종합 점수 계산
weighted_score = metrics["rouge"]["rouge-l"]["f"] * 0.5 + metrics["semantic_similarity"] * 0.5
metrics["overall_score"] = weighted_score
return {
"metrics": metrics,
"passed": weighted_score > 0.7 # 70% 이상이면 통과
}
테스트 케이스로 객관적 평가하기 ✅
마치 소프트웨어 테스트처럼, 미리 준비된 테스트 케이스로 AI 시스템을 평가할 수 있어요:
def run_test_cases(state):
# 테스트 케이스 정의
test_cases = [
{
"query": "파이썬 리스트 정렬 방법은?",
"keywords": ["sort()", "sorted()", "key 파라미터", "reverse"]
},
{
"query": "대한민국의 수도는?",
"exact_answer": "서울"
}
]
llm = ChatOpenAI()
test_results = []
for test in test_cases:
response = llm.invoke(test["query"])
if "keywords" in test:
# 키워드 포함 여부 검사
keywords_found = sum(1 for kw in test["keywords"] if kw.lower() in response.lower())
coverage = keywords_found / len(test["keywords"])
passed = coverage > 0.7 # 70% 이상 키워드 포함
elif "exact_answer" in test:
# 정확한 답변 검사
passed = test["exact_answer"].lower() in response.lower()
test_results.append({
"query": test["query"],
"response": response,
"passed": passed
})
# 전체 성공률 계산
pass_rate = sum(1 for r in test_results if r["passed"]) / len(test_results)
return {
"test_results": test_results,
"pass_rate": pass_rate
}
RAG 시스템 특화 평가 📚
검색 기반 시스템(RAG)은 검색과 생성 모두 평가해야 합니다:
def evaluate_rag(state):
query = state["query"]
docs = state["retrieved_documents"]
answer = state["response"]
# 1. 검색 품질 평가
retrieval_prompt = f"""
다음 질문과 검색된 문서의 관련성을 평가해주세요:
질문: {query}
문서: {docs}
1-10점으로 평가하고, 이유를 설명해주세요.
"""
# 2. 검색 결과 활용도 평가
utilization_prompt = f"""
검색된 문서의 정보가 답변에 얼마나 잘 활용되었는지 평가해주세요:
질문: {query}
문서: {docs}
답변: {answer}
1-10점으로 평가하고, 이유를 설명해주세요.
"""
evaluator = ChatOpenAI()
retrieval_score = evaluator.invoke(retrieval_prompt)
utilization_score = evaluator.invoke(utilization_prompt)
return {
"retrieval_score": retrieval_score,
"utilization_score": utilization_score
}
반사실적 평가: 강건성 테스트 🛡️
원래 질문을 의도적으로 변형해서 AI 시스템의 일관성을 테스트해 보세요:
def counterfactual_test(state):
original_query = state["query"]
original_response = state["response"]
# 원본 질문의 변형 버전 생성
variation_prompt = f"""
다음 질문의 변형 3가지를 만들어주세요:
{original_query}
1. 단어만 바꾸기
2. 질문 구조 변경하기
3. 추가 조건 넣기
"""
llm = ChatOpenAI()
variations = llm.invoke(variation_prompt)
# 변형 질문에 대한 응답 생성 및 비교
# ... (코드 생략)
return {
"consistency_score": consistency_score,
"variations": variations_with_responses
}
종합적인 평가 전략 수립하기 🏆
각 평가 방법은 장단점이 있으므로, 여러 방법을 조합하는 것이 가장 효과적입니다:
# 종합 평가 워크플로우 예시
evaluation_graph = StateGraph("comprehensive_evaluation")
# 다양한 평가 노드 추가
evaluation_graph.add_node("llm_judge", evaluate_with_llm)
evaluation_graph.add_node("metrics", calculate_metrics)
evaluation_graph.add_node("human_feedback", collect_human_feedback)
evaluation_graph.add_node("test_cases", run_test_cases)
# 평가 결과 집계 노드
def aggregate_results(state):
# 다양한 평가 결과 종합
llm_score = state.get("llm_score", 0)
metrics_score = state.get("metrics", {}).get("overall_score", 0)
human_score = state.get("human_score", 0)
test_pass_rate = state.get("pass_rate", 0)
# 가중치를 적용한 최종 점수 계산
final_score = (
llm_score * 0.3 +
metrics_score * 0.3 +
human_score/5 * 0.3 +
test_pass_rate * 0.1
)
return {
"final_score": final_score,
"verdict": "통과" if final_score > 0.7 else "개선 필요"
}
evaluation_graph.add_node("aggregate", aggregate_results)
실제 활용 예: 질문-답변 시스템 평가 💬
실제 질문-답변 시스템을 위한 평가 그래프를 만들어 보겠습니다:
# 기본 Q&A 시스템 구조
qa_workflow = StateGraph("qa_system")
# 기본 노드 추가
qa_workflow.add_node("process_query", process_user_query)
qa_workflow.add_node("retrieve_info", retrieve_information)
qa_workflow.add_node("generate_answer", generate_answer)
# 평가 노드 추가
qa_workflow.add_node("evaluate", evaluate_response)
# 개선 노드 추가
qa_workflow.add_node("improve", improve_response)
# 노드 연결
qa_workflow.add_edge("process_query", "retrieve_info")
qa_workflow.add_edge("retrieve_info", "generate_answer")
qa_workflow.add_edge("generate_answer", "evaluate")
# 평가 결과에 따른 분기
def quality_router(state):
score = parse_score(state["evaluation"])
if score < 7:
return "improve"
else:
return "final"
qa_workflow.add_conditional_edges("evaluate", quality_router)
qa_workflow.add_edge("improve", "generate_answer") # 개선 후 다시 응답 생성
qa_workflow.add_edge("final", END)
주의할 점 ⚠️
평가 기준의 명확성
- 평가 기준이 모호하면 결과도 일관성이 없어요
- 구체적이고 측정 가능한 기준을 설정하세요
- 예: "좋은 답변"보다는 "사실적 정확성, 관련성, 완전성, 명확성"처럼 세부 기준 사용
평가자 LLM의 한계
- LLM을 평가자로 사용할 때 평가자 자체의 편향이나 오류 가능성 주의
- 가능하면 더 강력한 모델(예: GPT-4)을 평가자로 사용하세요
- 평가 프롬프트를 신중하게 설계하고 테스트하세요
계산 비용 고려
- 모든 응답을 평가하면 API 호출 비용이 크게 증가할 수 있어요
- 샘플링 전략이나 중요한 단계에만 평가 적용 고려
- 개발 단계에서는 철저히 평가하고, 프로덕션에서는 샘플링 방식 고려
인간 피드백의 중요성
- 자동화된 평가만으로는 사용자 만족도를 완전히 측정할 수 없어요
- 정기적인 인간 평가자의 피드백을 수집하고 반영하세요
- A/B 테스트를 통해 실제 사용자 반응 측정하기
평가 결과의 해석
- 점수만 보지 말고 실패 패턴과 개선 가능성 분석하세요
- 특정 유형의 질문에서 성능이 낮은지 파악하세요
- 평가 결과를 바탕으로 시스템을 지속적으로 개선하세요
평가 체계의 진화
- 고정된 평가 체계보다 지속적으로 발전하는 평가 체계가 중요해요
- 새로운 평가 방법과 메트릭을 실험하고 통합하세요
- 사용자 피드백을 바탕으로 평가 기준도 함께 발전시키세요
마치며 🎁
LangGraph에서 답변 퀄리티와 정확도를 평가하는 것은 단순한 점검이 아니라, 시스템 개선을 위한 핵심 과정입니다. 다양한 평가 방법을 조합하여 여러분의 AI 시스템이 지속적으로 발전할 수 있는 토대를 마련하세요!
레스토랑 셰프가 끊임없이 맛을 개선하듯, AI 시스템도 지속적인 평가와 개선을 통해 더 나은 서비스를 제공할 수 있답니다. 평가는 끝이 아니라 더 나은 시작을 위한 과정이에요!
궁금한 점이 있으시면 댓글로 남겨주세요! 😊
참고 자료
'300===Dev Framework > Langgraph' 카테고리의 다른 글
LangGraph 쉽게 이해하기: 초보자를 위한 가이드 🌟 (0) | 2025.03.09 |
---|---|
Langgraph: LLM 기반 애플리케이션의 새로운 뇌 🧠 (0) | 2025.03.09 |