RAG2026-5일22차시 · RAG를 Graph로 바꾸기16 / 20← 이전목차다음 →MetaContents

22차시. RAG를 Graph로 바꾸기

실습 1 — RAG를 Graph로 바꾸기 실습 따라 하기

관련 수업 자료: 22차시 「4. 실습 ② — 그래프 완성」(6~7쪽), 22차시 「7. 실습 ⑤ — 흐름 확인」(12쪽), 22차시 「6. 실습 ④ — 회귀 테스트」(10~11쪽) · 실습 코드 22/graph_step_by_step.py, 22/graph.py, 22/graph22.py, 22/app.py, 22/test_migration.py, 22/test_migration_stream.py

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

수업 자료와 이어지는 곳

실습 코드원본 PDF이어지는 내용
22/graph_step_by_step.py6~7쪽22차시 「4. 실습 ② — 그래프 완성」 아래에 실었습니다
22/graph.py6~7쪽22차시 「4. 실습 ② — 그래프 완성」 아래에 실었습니다
22/graph22.py6~7쪽22차시 「4. 실습 ② — 그래프 완성」 아래에 실었습니다
22/app.py12쪽22차시 「7. 실습 ⑤ — 흐름 확인」 › 7-1) app.py 연결 아래에 실었습니다
22/test_migration.py10~11쪽22차시 「6. 실습 ④ — 회귀 테스트」 아래에 실었습니다
22/test_migration_stream.py12쪽22차시 「7. 실습 ⑤ — 흐름 확인」 아래에 실었습니다

실행 흐름

출력
START → retrieve
retrieve → generate  (ok)
retrieve → fallback  (empty)
generate → END
fallback → END

실습 순서

키가 있으면 step by step 파일로 단계를 키운 뒤 graph.py의 ask를 15차시와 같은 질문으로 비교합니다. test_migration_stream.py로 실제로 탄 노드를 출력합니다.

스스로 확인

  • 이식이 기능 추가가 아니라는 점을 설명할 수 있는가?
  • app이 rag 함수 대신 graph.ask를 불러도 되는 이유를 아는가?
  • 답이 나빠지면 stream으로 어느 노드까지 갔는지 먼저 보는가?

코드 설명

  • sys.path.insert(0, os.path.join(CURRENT_DIR, "..", "18")) 는 18·19차시 폴더를 모듈 찾는 경로 맨 앞에 넣습니다. 그래야 from graph_state import RAGState, from retrieve import retrieve_node 가 다른 차시의 파일을 찾습니다. 폴더 위치를 옮기면 여기서 import 오류가 납니다.
  • graph_step_by_step.py 의 route_after_retrieve 는 "generate"/"fallback" 을, 원본 PDF 의 graph.py 는 "ok"/"empty" 를 돌려줍니다. 어느 쪽이든 괜찮지만 add_conditional_edges 의 경로맵 키와 글자 하나까지 같아야 합니다.
  • ask() 가 돌려주는 answer, sources, cited, log, ok 는 15차시 rag.ask() 와 같은 키입니다. 화면 코드는 이 키만 읽으므로 안쪽이 그래프로 바뀌어도 모릅니다. 이것이 app.py 를 import 한 줄만 고치는 이유입니다.
  • app.invoke(..., {"recursion_limit": 20}) 의 recursion_limit 은 노드 실행 횟수 상한입니다. 오늘 그래프에는 루프가 없어 닿을 일이 없지만, 3부에서 재생성 루프가 붙을 때를 대비해 미리 둡니다.
  • test_migration.py 는 두 답을 .strip() 한 뒤 글자 그대로 견줍니다. 그래서 temperature 가 0 이 아니면 같은 코드라도 매번 답이 달라져 비교가 무의미해집니다.
  • test_migration_stream.py 는 list(update.keys()) 로 노드가 바꾼 칸의 이름만 찍습니다. 정상 질문은 [retrieve] 다음 [generate], 문서에 없는 질문은 [retrieve] 다음 [fallback] 이 찍혀야 조건부 Edge 가 제대로 판단한 것입니다.
← 이전 절22차시 · 체크리스트와 과제다음 절 →22차시 · 퀴즈 1 — 예전과 같은 키를 돌려주는 그래프 ask