3강 Agentic RAG 구현하기 | 만들면서 배우는 AI 에이전트 개발 입문+실전
저자 직강. RAG 개념부터 LangGraph 기반 Agentic RAG 구현까지. 검색 필요성 판단 → 쿼리 재작성 → 관련성 평가 → 환각 검사의 4단계 피드백 루프를 갖춘 에이전트 구성.
채널: 공원나연 | 영상길이: 46분 39초 | 업로드: 2026-05-18
IDEAS
- RAG는 외부 문서를 검색해 LLM의 컨텍스트를 증강하는 기법으로, 벡터 데이터베이스와 임베딩 모델이 핵심 구성 요소다.
- 임베딩은 자연어 문장을 의미를 담은 숫자 벡터로 변환하며, 유사한 의미의 문장은 벡터 공간에서 가까운 위치에 존재한다.
- PDF 문서 로딩에는 LangChain의
PyPDFLoader를 사용하며, 페이지별 텍스트와 메타데이터를 추출한다. RecursiveCharacterTextSplitter는 단락→문장→단어 순서로 재귀적으로 텍스트를 분할해 의미 경계를 보존하면서 청킹한다.- ChromaDB는 로컬 파일(SQLite) 형태로 벡터를 저장할 수 있어 실습 환경에 적합한 벡터 데이터베이스다.
- Agentic RAG는 단방향 검색-응답이 아닌, 검색 필요성 판단 → 쿼리 재작성 → 관련성 평가 → 환각 검사의 피드백 루프를 갖는다.
- 검색 필요성 판단: “안녕하세요” 같은 일상 질문은 벡터 DB 조회 없이 바로 답변해 불필요한 리소스 소모를 방지한다.
- 쿼리 재작성(Transform Query): 질문이 모호하거나 간결할 때 벡터 검색에 최적화된 형태로 변환한다.
- 관련성 평가(Decide to Generate): 검색된 문서가 질문과 관련 있는지 LLM이 binary score(yes/no)로 판정한다.
- 환각 검사(Check Hallucination): 생성된 답변이 검색된 사실에 잘 근거하는지 평가해 환각 시 재생성한다.
- LangGraph 상태(State)에
question,context,answer,retry_num을 정의해 에이전트의 내부 흐름을 제어한다. - retry_num은 무한 루프를 방지하기 위해 재시도 횟수를 추적하며, 3회 초과 시 컨텍스트 부족 안내 메시지를 생성한다.
- Context Organizer 노드는 PDF에서 추출된 날것의 텍스트를 LLM이 정리해 불필요한 공백과 오류를 제거한다.
- LangChain의
create_retriever_tool로 리트리버를 도구(tool)로 래핑하면, LLM이 검색 필요성을 스스로 판단해 호출한다. - LangGraph Studio(
langgraph dev)로 그래프 워크플로우를 시각적으로 확인하고 쿼리를 직접 실행해볼 수 있다. with_structured_output을 사용하면 LLM의 출력을 Pydantic 스키마로 강제해 binary score 등 구조화된 평가를 안정적으로 수행한다.- 벡터 DB에 저장 시 사용한 임베딩 모델과 검색 시 사용하는 임베딩 모델은 반드시 동일해야 한다.
- Jupyter 노트북에서 LangChain을 사용하려면 가상환경을 VS Code 커널로 등록해야 한다(
ipykernel install --user).
INSIGHTS
- Agentic RAG는 검색-생성 파이프라인에 여러 자기평가(self-evaluation) 루프를 추가해 단순 RAG의 품질 한계를 극복한다. 검색 결과가 부적절하면 질문을 재작성하고, 답변이 환각이면 재생성하는 구조는 에이전트가 자율적으로 품질을 보증하게 만든다.
- retry_num 같은 안전장치는 LLM 기반 평가 루프가 무한 반복될 수 있는 위험을 실용적으로 방지한다. 이론적 완벽함보다 운영 안정성을 선택한 설계 결정이다.
- LangGraph에서 State를 명시적으로 정의하는 것은 에이전트 워크플로우의 모든 중간 결과물을 추적 가능하게 만들어, 디버깅과 평가 지점을 명확히 한다.
- PDF 원본 텍스트를 Context Organizer로 한 번 더 정제하는 것은 downstream LLM의 답변 품질에 영향을 미친다. 쓰레기 입력은 쓰레기 출력을 낳는다는 원칙의 실용적 구현이다.
QUOTES
- “레그는 문서에서 정보를 검색해서 LLM의 응답 정확도를 높이는 기법이고요. 말 그대로 필요한 문서를 검색하고 LLM이 참고할 수 있는 컨텍스트를 증강해서 답변을 생성하는 기법을 의미하는 거고요.”
- “임베딩 벡터들을 어떤 의미 공간에 위치시켜 보았을 때 비슷한 의미를 가지는 것끼리는 비슷한 위치에 가까운 위치에 존재할 수 있도록 표현되는 것이 바로 임베딩입니다.”
- “에이전틱한 래그를 구현하기 위해서 갖출 수 있는 기능들 — 검색 필요 여부 판단, 검색 쿼리 재작성, 관련성 평가, 환각 검사.”
- “리트라이넘을 둔 이유는 무한 반복되지 않도록 반복 횟수가 일정 횟수를 넘기지 않도록 제어하기 위해서입니다.”
- “PDF 문서가 텍스트 추출만 했고 따로 정리되지는 않은 원본 형태를 가지고 있습니다. 그래서 이걸 LLM이 좀 더 읽기 쉬운 형태로 정리해 주는 역할을 여기서 할 거고요.”
REFERENCES
- 책: 『만들면서 배우는 AI 에이전트 개발 입문+실전』(한빛미디어) — 랭그래프로 완성하는 단계별 싱글·멀티 에이전트 시스템
- 저자: 공원나연 (박나연)
- 도구: LangChain, LangGraph, ChromaDB, PyPDF, RecursiveCharacterTextSplitter
- 개념: Agentic-RAG, RAG, Embedding, Vector-Search
FACTS
- 실습 데이터: 국립국어원 한글 맞춤법 표준어 규정 해설 PDF (264페이지)
- 텍스트 청킹: chunk_size=500, chunk_overlap=50, 총 약 500개 청크 생성
- 관련성·환각 평가: binary score (yes/no) + Pydantic
with_structured_output - LangGraph Studio 실행:
uv run langgraph dev또는langgraph dev - 책 챕터: 6.5절 (6.5.1 RAG 개념, 6.5.2 벡터DB, 6.5.4 Agentic RAG)
구현 코드 구조
rag_agent/
├── state.py # AgentState (messages, question, context, answer, retry_num)
├── agent.py # 그래프 정의 (노드·엣지 연결, 컴파일)
├── node.py # chatbot, retrieve, context_organizer, generate, transform_query
├── edge.py # decide_to_generate, check_hallucination (조건 함수)
├── retriever.py # ChromaDB 리트리버 + create_retriever_tool
└── datasets/ # 한글 맞춤법 표준어 규정 해설.pdf
워크플로우
사용자 질문
↓
chatbot 노드 (검색 필요 여부 판단)
├─ 불필요 → END (일반 답변)
└─ 필요 → retrieve 노드
↓
context_organizer (검색 결과 정제)
↓
decide_to_generate (관련성 평가)
├─ no → transform_query → retrieve (재검색, retry_num+1)
└─ yes → generate 노드
↓
check_hallucination (환각 검사)
├─ not_supported → generate (재생성)
└─ supported → END (최종 답변)