RAG2026-5일16차시 · 1부 종합정리15 / 19← 이전목차다음 →MetaContents

16차시. 1부 종합정리

실습 1 — 1부 종합정리 실습 따라 하기

관련 수업 자료: 16차시 「7. 1부에서 남긴 자산 확인」(15쪽) · 실습 코드 rag_app/config.py, rag_app/indexer.py, rag_app/rag.py, rag_app/app.py

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

수업 자료와 이어지는 곳

실습 코드원본 PDF이어지는 내용
rag_app/config.py15쪽16차시 「7. 1부에서 남긴 자산 확인」 아래에 실었습니다
rag_app/indexer.py-원본 PDF 에 짝이 되는 쪽이 없어 이 페이지 아래에 실었습니다
rag_app/rag.py-원본 PDF 에 짝이 되는 쪽이 없어 이 페이지 아래에 실었습니다
rag_app/app.py-원본 PDF 에 짝이 되는 쪽이 없어 이 페이지 아래에 실었습니다

실행 흐름

출력
1에서8 일단 만든다 → 9에서14 측정한다
9에서14 측정한다 → 15에서16 나눈다
15에서16 나눈다 → 17 그래프

실습 순서

자료를 덮고 RAG 5단계를 그림으로 그린 뒤, rag_app의 네 파일이 어느 단계인지 화살표로 연결합니다. 막히면 해당 차시 교안으로 돌아갑니다.

스스로 확인

  • 5단계의 입출력을 자료 없이 말하는가?
  • 검색 문제와 생성 문제를 가르는 질문을 기억하는가?
  • 2부에서 if가 Edge로 바뀐다는 점을 예상하는가?

이어지는 실습 코드

실습 코드 · rag_app/indexer.py

실습 코드: 실습/src/rag_app/indexer.py · 원본 PDF 에 같은 이름의 쪽이 없어 여기에 실었습니다.

이 파일은 15차시 「4. 실습 ② — indexer.py」에 주석과 함께 전체가 실려 있습니다. 여기서는 이 차시에서 보는 부분의 해설과 실행 결과만 옮깁니다.

코드 해설

PDF를 잘라 FAISS 저장소를 만들거나, 이미 만든 인덱스를 읽어 Retriever 역할을 준비합니다.

코드 앞에서 고정해 두는 말입니다.

  • 읽는 키: 없음 (config 상수)
  • 쓰는 키: 반환: FAISS 저장소 객체. 새로 만들 때는 인덱스 파일을 디스크에 저장
  • 그래프:
  • get_store
  • |-- index.faiss 와 index.pkl 이 있고 rebuild가 아님 --> 로드
  • +-- 없음 --> PDF 로드 --> 청크 --> FAISS 생성 --> 저장
  • Retriever에 해당하는 준비 단계입니다. 질문 함수는 없고, 저장소 객체를 돌려줍니다.
  • 청크마다 metadata filename은 PDF 이름, page_no는 로더의 page에 1을 더한 값입니다.

함수와 클래스로 나누어 읽습니다.

  • get_store: 이름 그대로 한 가지 일만 합니다. 본문 주석을 같이 읽습니다.

파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.

실습 코드 · rag_app/rag.py

실습 코드: 실습/src/rag_app/rag.py · 원본 PDF 에 같은 이름의 쪽이 없어 여기에 실었습니다.

이 파일은 15차시 「5. 실습 ③ — rag.py (핵심)」에 주석과 함께 전체가 실려 있습니다. 여기서는 이 차시에서 보는 부분의 해설과 실행 결과만 옮깁니다.

코드 해설

한 함수 ask() 안에 검색(Retriever)과 답 생성(Generator), 인용 검사가 순서대로 들어 있습니다.

코드 앞에서 고정해 두는 말입니다.

  • 읽는 키: 인자 question, k. LangGraph State 키는 없습니다.
  • 쓰는 키: 반환 딕셔너리 answer, sources, cited, ok. 실패 시 sources는 빈 리스트
  • 그래프:
  • question
  • |
  • v
  • _search (FAISS, MIN_SCORE 이상만)
  • |-- 문서 없음 --> MSG_NO_DOC

함수와 클래스로 나누어 읽습니다.

  • _search: 이름 그대로 한 가지 일만 합니다. 본문 주석을 같이 읽습니다.
  • _build_context: 이름 그대로 한 가지 일만 합니다. 본문 주석을 같이 읽습니다.
  • ask: 이름 그대로 한 가지 일만 합니다. 본문 주석을 같이 읽습니다.

파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.

실습 코드 · rag_app/app.py

실습 코드: 실습/src/rag_app/app.py · 원본 PDF 에 같은 이름의 쪽이 없어 여기에 실었습니다.

이 파일은 15차시 「7. 실습 ④ — app.py (터미널 버전)」에 주석과 함께 전체가 실려 있습니다. 여기서는 이 차시에서 보는 부분의 해설과 실행 결과만 옮깁니다.

코드 해설

콘솔에서 질문을 반복 입력받아 rag.ask 결과에 답과 출처를 출력합니다.

코드 앞에서 고정해 두는 말입니다.

  • 읽는 키: ask() 반환의 answer, sources, cited
  • 쓰는 키: 화면 출력
  • 그래프:
  • 배너
  • |
  • v
  • 질문 입력 -- q/exit/quit/종료 --> 종료
  • |

함수와 클래스로 나누어 읽습니다.

  • main: 이름 그대로 한 가지 일만 합니다. 본문 주석을 같이 읽습니다.

파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.

코드 설명

  • TOP_K = 5 # 3→5: +10%p (k=8은 노이즈로 하락) 처럼 config.py 의 값 옆에는 그 값을 고른 근거를 적어 둡니다. 14차시 비교 실험의 결과가 이 한 줄에 남습니다.
  • EMBED_MODEL 옆의 ⚠ 변경 시 인덱스 재생성 은 임베딩 모델을 바꾸면 저장해 둔 인덱스를 다시 만들어야 한다는 뜻입니다. 모델이 다르면 좌표계가 달라져 검색이 엉뚱해집니다.
  • get_store 는 index.faiss 와 index.pkl 이 있으면 불러오고, 없을 때만 PDF를 잘라 새로 만듭니다. 미니과제 요건 1번 "두 번째 실행부터는 불러올 것"이 바로 이 부분입니다.
  • ask() 는 answer, sources, ok 키에, 답을 만들었을 때는 cited 까지 담은 딕셔너리를 돌려줍니다. 2부에서 State가 "지금 반환하는 딕셔너리"라고 하는 것이 이 모양입니다.
  • _search 가 MIN_SCORE 이상인 조각만 남기고, 하나도 없으면 ask() 가 MSG_NO_DOC 을 돌려줍니다. 앱이 멈추지 않고 안내 문장으로 끝납니다. 이 if 한 줄이 2부에서 조건부 Edge로 옮겨 갑니다.
← 이전 절16차시 · 체크리스트와 과제다음 절 →16차시 · 퀴즈 1 — 문서가 바뀔 때만 하는 준비 단계 고르기