32차시. 고도화된 Modular RAG
실습 1 — 고도화된 Modular RAG 실습 따라 하기
관련 수업 자료: 32차시 「2. 실습 ① — 통합 그래프 완성」(4쪽) · 실습 코드 32/graph32.py
이 실습은 교안 해설(32_고도화ModularRAG.md)의 실습 순서를 옮긴 것입니다. OpenAI 임베딩이나 채팅 모델을 부르는 파일은 .env 에 API 키가 있어야 돌아갑니다. 키가 없으면 실행 결과 샘플로 출력 모양을 확인합니다.
수업 자료와 이어지는 곳
| 실습 코드 | 원본 PDF | 이어지는 내용 |
|---|---|---|
32/graph32.py | 4쪽 | 32차시 「2. 실습 ① — 통합 그래프 완성」 아래에 실었습니다 |
실행 흐름
START → classify
classify → END (greeting_calc_scope)
classify → retrieve (document)
retrieve → generate (ok)
retrieve → rewrite (research)
retrieve → fallback (giveup)
generate → verify
verify → END (done)
verify → bump (regenerate)
bump → generate
verify → rewrite (research)
verify → fallback (giveup)
rewrite → retrieve
fallback → END실습 순서
자료를 덮고 최종 그래프를 그린 뒤, 노드마다 처음 만든 차시를 적습니다. 자기 미니프로젝트의 한계를 세 줄로 쓰고, 평가용 질문 중 아직 실패하는 것이 있으면 검색 문제인지 생성 문제인지 표시합니다.
스스로 확인
- 분류부터 fallback까지 경로를 말할 수 있는가?
- 점수를 올린 변경과 구조만 바꾼 변경을 구분하는가?
- 못 하는 일을 세 가지 말하는가?
코드 설명
getattr(config, "MAX_RETRY", 2)는 config 에 MAX_RETRY 가 있으면 그 값을, 없으면 2를 씁니다. 설정 파일에 값을 빠뜨려도 그래프가 멈추지 않게 하는 장치입니다.- 분기 함수는 "ok", "research" 같은 이름표만 돌려줍니다.
add_conditional_edges의 세 번째 인자 딕셔너리가 그 이름표를 실제 노드 이름으로 바꿉니다. 이름표가 딕셔너리에 없으면 오류가 나는데, 자주 겪는 문제 표의 "경로맵 KeyError" 가 이 경우입니다. route_after_retrieve는 search_error, no_result, empty_query 를 바로 giveup 으로 보냅니다. 검색어를 바꿔도 해결되지 않는 실패이기 때문입니다. 점수가 낮은 경우만 research 로 재작성에 보냅니다.- 재생성은 verify → bump → generate 순서로 돕니다.
bump_node가 retries 를 1 올려야route_after_verify의retries < MAX_RETRY가 언젠가 거짓이 됩니다. bump 를 빼면 카운터가 늘지 않아 같은 자리를 계속 돕니다. {"recursion_limit": 40}은 노드 실행 횟수의 상한입니다. 상한 로직이 어긋나도 그래프가 끝없이 돌지 않게 막는 마지막 안전장치이고, 넘으면 GraphRecursionError 가 납니다.- 헤더 주석대로 graph32.py 는 31차시의 safe_node 와 log_query 를 붙이지 않았습니다. 운영에 올릴 때는 31차시 graph31.py 처럼 감싼 노드를 등록하시면 됩니다.