RAG2026-5일13차시 · 프롬프트 최적화14 / 18← 이전목차다음 →MetaContents

13차시. 프롬프트 최적화

실습 1 — 프롬프트 최적화 실습 따라 하기

관련 수업 자료: 13차시 「4. 실습 ① — 프롬프트 파일 분리」(9~10쪽), 13차시 「5. 실습 ② — 프롬프트 A/B 비교」(11~12쪽), 13차시 「9. 오늘의 완성 코드」(17~18쪽) · 실습 코드 13/prompts.py, 13/compare_prompt.py, 13/validators.py, 13/rag_v3.py

이 실습은 교안 해설(13_프롬프트개선.md)의 실습 순서를 옮긴 것입니다. OpenAI 임베딩이나 채팅 모델을 부르는 파일은 .env 에 API 키가 있어야 돌아갑니다. 키가 없으면 실행 결과 샘플로 출력 모양을 확인합니다.

수업 자료와 이어지는 곳

실습 코드원본 PDF이어지는 내용
13/prompts.py9~10쪽13차시 「4. 실습 ① — 프롬프트 파일 분리」 아래에 실었습니다
13/compare_prompt.py11쪽13차시 「5. 실습 ② — 프롬프트 A/B 비교」 아래에 실었습니다
13/validators.py11쪽13차시 「5. 실습 ② — 프롬프트 A/B 비교」 아래에 실었습니다
13/rag_v3.py17~18쪽13차시 「9. 오늘의 완성 코드」 아래에 실었습니다

실행 흐름

출력
역할 → 규칙
규칙 → 자료
자료 → 질문
질문 → LLM
LLM → 인용 번호 검사

실습 순서

실습/src/13에서 prompts.py는 정의만 확인합니다. 키가 있으면 compare_prompt.py로 같은 질문을 V1–V3에 넣고, validators.py와 rag_v3.py로 인용 검사를 봅니다.

자료에 방법만 있고 수수료는 없는 질문으로, V2의 전체 거절과 V3의 부분 답변을 비교합니다.

스스로 확인

  • 4단 순서를 말할 수 있는가?
  • 과잉 거부가 무엇인지 예를 드는가?
  • 프롬프트로 고칠 수 없는 실패가 검색 실패라는 점을 아는가?

코드 설명

  • chain = prompt | llm | StrOutputParser() 는 틀에 값을 채우고, 모델에 보내고, 답 메시지에서 글자만 꺼내는 세 단계를 한 줄로 잇습니다. 마지막 StrOutputParser가 없으면 문자열이 아니라 메시지 객체가 돌아옵니다.
  • chain.invoke({"context": context, "question": question}) 의 키 이름은 틀 안의 {context}, {question} 칸 이름과 같아야 합니다. RETRY_PROMPT를 PROMPTS에 넣지 않은 까닭도 여기 있습니다. 그 틀에는 {reason} 칸이 하나 더 있어서, 두 값만 넣는 비교 코드에서 오류가 납니다.
  • re.findall(r"\[(\d+)\]", answer) 는 숫자를 문자열로 돌려줍니다. 그래서 int() 로 바꾼 뒤 1 이상, 조각 개수 이하인지 비교합니다. 근거가 2개인데 [3]이 나오면 없는 근거를 인용한 환각 신호입니다.
  • check_citation은 번호의 범위만 봅니다. [1]이 정말 1번 조각의 내용과 맞는지는 보지 않습니다. 내용까지 맞는지는 26차시 Verifier Node가 맡습니다.
  • JUDGE_PROMPT 의 {{"grounded": true, ...}} 처럼 중괄호를 두 번 쓰면 빈칸이 아니라 글자 그대로의 중괄호가 됩니다. 틀 안에 JSON 예시를 넣을 때 자주 틀리는 곳입니다.
  • rag_v3.py 의 ask는 검색에 성공하면 답을 출력하지 않고 딕셔너리로 돌려주기만 합니다. 실행 결과 샘플에 Q 줄만 보이는 까닭입니다. 답을 보려면 print(ask("...")["answer"]) 처럼 반환값을 찍으십시오.
← 이전 절13차시 · 체크리스트와 과제다음 절 →13차시 · 퀴즈 1 — 인용 번호가 조각 개수 안인지 검사