RAG2026-5일25차시 · Generator Node 분리10 / 19← 이전목차다음 →MetaContents

25차시. Generator Node 분리

7. 실습 ④ — 프롬프트 A/B 비교

출처: 원본 PDF 25차시_GeneratorNode분리.pdf 14~15쪽 · 쪽 그림 14쪽 15쪽

모듈로 분리했으니 이제 검색은 한 번만 하고 프롬프트만 바꿔 비교할 수 있습니다.

📝 src/ab_prompt.py

Python
from nodes.retriever import retriever_node
from nodes.generator import build_context, _llm
from prompts import PROMPTS
from langchain_core.output_parsers import StrOutputParser

def compare(question, versions=("v1", "v2", "v3")):
    s = {"question": question, "query": question}
    s.update(retriever_node(s))              # 검색 1회만!
    ctx = build_context(s["documents"])

    print(f"\n{'='*58}\nQ: {question}  (근거 {len(s['documents'])}건)")

    for v in versions:
        chain = PROMPTS[v] | _llm | StrOutputParser()
        ans = chain.invoke({"context": ctx, "question": question})
        print(f"\n[{v}] {ans[:150]}")

compare("환불 방법과 수수료를 알려주세요")

실행 결과 예시 (코드를 읽고 만든 예상 화면입니다. 실제 실행 결과, 특히 모델의 답은 다를 수 있습니다)

출력

==========================================================
Q: 환불 방법과 수수료를 알려주세요  (근거 2건)

[v1] 상품 수령 후 7일 이내에 환불을 신청할 수 있습니다. 단순 변심의 왕복 배송비는 고객 부담입니다.

[v2] 상품 수령 후 7일 이내에 환불을 신청할 수 있습니다. [1]
수수료 금액은 자료에서 확인할 수 없습니다. [1]

[v3] 환불은 상품 수령 후 7일 이내에 신청할 수 있습니다. [1]
단순 변심이면 왕복 배송비는 고객 부담입니다. [1]
수수료라는 항목의 금액은 자료에서 확인할 수 없습니다. [1]

💰 비용 비교
13차시 방식 (모듈 분리 전)
버전마다 검색 + 생성 → 검색 3회 + 생성 3회
25차시 방식 (모듈 분리 후)
검색 1회 + 생성 3회
검색은 임베딩 API를 부르므로 비용이 듭니다.
버전이 5개, 질문이 20개면 차이가 커집니다.
그리고 조건이 완전히 같아져서 비교가 정확해집니다.

7-1) 자동 채점 붙이기

Python
TESTS = [
    {"q": "환불은 며칠 이내인가요?", "keys": ["7일"]},
    {"q": "대표이사 이름은?",        "keys": ["확인할 수 없"]},
    # 12차시 질문 20개
]
def evaluate(version):
    hit = 0
    for t in TESTS:
        s = {"question": t["q"], "query": t["q"]}
        s.update(retriever_node(s))
        ctx = build_context(s["documents"]) if s["documents"] else ""
        chain = PROMPTS[version] | _llm | StrOutputParser()
        ans = chain.invoke({"context": ctx, "question": t["q"]}) \
              if ctx else "자료에서 확인할 수 없습니다"
        # 정답 키워드 중 하나라도 들어있으면 정답
        ok = False
        for k in t["keys"]:
            if k in ans:
                ok = True
                break
        if ok:
            hit += 1
    print(f"[{version}] {hit}/{len(TESTS)} = "
          f"{hit/len(TESTS)*100:.0f}%")
for v in ("v1", "v2", "v3"):
    evaluate(v)

실행 결과 예시 (코드를 읽고 만든 예상 화면입니다. 실제 실행 결과, 특히 모델의 답은 다를 수 있습니다)

출력
[v1] 2/2 = 100%
[v2] 2/2 = 100%
[v3] 2/2 = 100%
← 이전 절25차시 · 6. 실습 ③ — 재생성 시 피드백 반영다음 절 →25차시 · 8. 입출력 명세