LangGraph Self-RAG
검색 품질 판단과 재검색/재작성 분기
LangGraph Self-RAG
검색 품질 판단과 재검색/재작성 분기
그래프로 에이전트와 RAG를 제어한다
LCEL의 직선 한계를 넘어 — 조건 분기·루프·상태 관리·멀티에이전트
RAG 그래프 패턴
Self-RAG · CRAG · Query Router
RAG 그래프 패턴
검증과 재시도를 노드로 만드는 세 패턴
검증을 노드로 만든다
검색 전에는 라우팅, 검색 후에는 관련성 검증, 생성 후에는 근거 검증 — 순환 엣지가 재시도를 만듭니다.
- Self-RAG — 생성 후 근거 검증 → 불합격 시 재생성
- CRAG — 검색 후 관련성 검증 → 웹 검색 폴백
- Query Router — 질문 유형 분류 → 벡터/키워드/웹 분기
세 패턴의 공통분모는 "검증 → 불합격 시 다른 경로" — 직선 LCEL로는 만들 수 없는 구조입니다.
Self-RAG
생성 후 "답변이 문서에 근거하는가" 검증 → 불합격 시 재생성
합격이면 END로, 불합격이면 프롬프트를 수정해 재생성합니다 — 이 재시도 루프가 순환 엣지의 대표 사례입니다.
재시도 루프 안전장치
retry_count와 best effort — 무한 루프 없는 자기 교정
핵심 포인트
- relevance_score >= 0.7
- 합격선 — LLM이 매긴 관련성 점수로 생성 진행 여부 판정
- retry_count
- 재작성 횟수를 State에 기록 — 최대 2회로 제한해 무한 루프 차단
- best effort
- 한계 도달 시 현재 문서로 답변 생성 — 멈추지 않고 마무리
- 판단용 경량 모델
- 관련성 판정은 Haiku급 경량 모델로 — 추가 호출 비용 최소화
코드
# 조건 분기 함수 — 다음 노드 이름을 문자열로 반환
def decide_next(state: RAGState) -> str:
if state["relevance_score"] >= 0.7:
return "generate" # 충분 → 답변 생성
if state["retry_count"] >= 2:
return "generate" # 재시도 한계 → best effort
return "rewrite" # 부족 → 쿼리 재작성
# 재작성 노드가 카운터를 올린다 — 안전장치의 실체
def rewrite_query(state: RAGState):
new_query = rewrite_chain.invoke({"question": state["question"]})
return {"rewritten_query": new_query,
"retry_count": state["retry_count"] + 1}
CRAG + Query Router
검색 전 라우팅 + 검색 후 관련성 검증
-
1
Query Router
질문 분류 → 벡터/키워드/웹 검색 분기
-
2
Retrieve
선택된 경로로 문서 검색
-
3
Grade Docs
관련성 LLM 판정 — relevant / not relevant
-
4
분기
관련 문서 있음 → Generate, 없음 → Web Search 폴백
-
5
Generate
검증된 문서 기반 최종 답변 생성
검색 전에는 라우터가 경로를 고르고, 검색 후에는 LLM이 관련성을 판정합니다 — 관련 문서가 없으면 웹 검색으로 폴백합니다.
ReAct 에이전트
ToolNode · 순환 루프 · should_continue
ReAct 에이전트
추론→도구→관찰 순환의 구현
순환 루프가 에이전트다
추론→도구→관찰 순환을 StateGraph로 직접 구현합니다 — create_react_agent는 deprecated, 공식 대체는 langchain.agents의 create_agent입니다.
- LLM Node — tool_calls 또는 최종 답변 생성
- ToolNode — tool_calls 실행 빌트인 노드
- should_continue — 도구 루프 종료 조건 함수
도구 호출이 남아 있으면 ToolNode로, 없으면 END로 — should_continue 한 함수가 루프를 제어합니다.
ReAct = StateGraph + ToolNode
추론→도구→관찰을 그래프 순환으로 구현
ReAct 에이전트 코드
StateGraph로 도구 순환 루프 직접 구현
from langgraph.prebuilt import ToolNode
# tool_calls를 실행하고 결과를 messages에 추가하는 빌트인 노드
tool_node = ToolNode([get_weather, search])
def should_continue(state):
last = state["messages"][-1]
return "tools" if last.tool_calls else "end" # 도구 호출이 없으면 루프 종료
graph = StateGraph(MessagesState)
graph.add_node("agent", call_model)
graph.add_node("tools", tool_node)
graph.add_edge(START, "agent")
graph.add_conditional_edges("agent", should_continue,
{"tools": "tools", "end": END})
graph.add_edge("tools", "agent") # 순환!
create_agent vs 직접 구성
표준 루프는 한 줄로, 루프 안을 바꿔야 하면 StateGraph로
create_agent
langchain.agents — 공식 프리빌트
- 표준 ReAct 루프를 함수 호출 하나로
- LangGraph 위에서 동작 — 그래프 직접 작성 불필요
- middleware 시스템으로 실행 훅 확장
- deprecated된 create_react_agent의 공식 대체
StateGraph 직접 구성
세밀 제어
- should_continue 등 루프 조건 직접 정의
- 검증 · 요약 같은 커스텀 노드 자유 삽입
- Self-RAG처럼 표준을 벗어난 순환 구현
- 앞 슬라이드의 코드 패턴이 그 골격
표준 도구 루프면 create_agent 한 줄, 루프 구조 자체를 바꿔야 하면 StateGraph 직접 구성으로 내려갑니다.
멀티에이전트
Supervisor · Swarm · HITL · Checkpoint
멀티에이전트
협업 패턴과 사람의 개입 지점
협업 방식도 그래프로
여러 에이전트의 협업 방식을 그래프로 설계합니다 — 위험한 단계에는 사람의 승인 게이트를 끼워 넣습니다.
- Supervisor — 중앙 위임 · langgraph-supervisor
- Swarm — 자율 핸드오프 · 분산 의사결정
- HITL — interrupt() + Command(resume)
명확한 작업 분해가 있으면 Supervisor, 동적 워크플로우면 Swarm — 고위험 노드에는 HITL을 겁니다.
Supervisor vs Swarm
작업 분해 방식에 따라 패턴을 선택
Supervisor
중앙 위임
- 상위 LLM이 하위 에이전트에 태스크 배정
- 전체 상태를 Supervisor가 관리
- langgraph-supervisor로 빠르게 구축
- 명확한 작업 분해가 있을 때
Swarm
자율 핸드오프
- 에이전트가 스스로 다음에 전달
- 분산 의사결정 — 중앙 없음
- 핸드오프 함수로 전환 조건 정의
- 동적 워크플로우에 적합
작업 분해가 명확하면 Supervisor로 중앙에서 배정하고, 흐름이 동적이면 Swarm의 자율 핸드오프에 맡깁니다.
langgraph-supervisor로 구축
중앙 위임 패턴을 패키지 하나로 — 직접 구현 전에 먼저 검토
- pip install langgraph-supervisor
- 별도 패키지(0.0.31) — LangGraph 1.x 호환 공식 확인
- create_supervisor()
- 하위 에이전트 목록으로 Supervisor 그래프를 바로 생성
- 중앙 상태 관리
- 전체 상태는 Supervisor가 보유 — 하위 에이전트는 배정받은 태스크만
- 직접 구현 전환점
- 배정 로직이 특수해지면 StateGraph + 조건 엣지로 커스텀
표준 중앙 위임이면 패키지로 충분합니다 — 배정 로직이 특수해지는 순간이 직접 구현으로 내려가는 시점입니다.
HITL 승인 게이트
interrupt()로 그래프 일시 중지 → 사용자 확인 → Command(resume)로 재개
-
1
invoke()
사용자 요청으로 그래프 실행 시작
-
2
interrupt_before
위험 노드 진입 전 자동 중지 — Checkpointer에 저장
-
3
사용자 확인
"결제를 승인하시겠습니까?" 표시
-
4
Command(resume)
승인 → True로 그래프 재개, 거부 → 다른 경로
중단 시점의 상태는 Checkpointer에 저장됩니다 — 사용자가 승인하면 Command(resume)로 그 지점부터 재개합니다.
HITL 메시지 왕복
중단 · 저장 · 재개가 오가는 실제 순서 — 클라이언트 · 그래프 · Checkpointer · 승인자
재개가 가능한 이유는 중단 시점 상태가 Checkpointer에 남아 있기 때문입니다 — 프로세스가 기다리는 것이 아니라 상태가 기다립니다.
Deep Agents와 프로덕션
create_deep_agent · Checkpoint · LangSmith · 배포
Deep Agents와 프로덕션
추상화 선택과 배포 전 점검
빠르게 시작, 단단하게 배포
시작은 Deep Agents의 고수준 추상화로 빠르게, 세밀한 제어가 필요하면 StateGraph 직접 구성으로 — 배포 전 체크리스트까지 짚습니다.
- Deep Agents — create_deep_agent() 한 줄
- Checkpointer — MemorySaver → PostgresSaver
- LangSmith — 노드별 Trace 디버깅
- 배포 — AgentCore Runtime 또는 ECS/Lambda
개발용 MemorySaver를 프로덕션 PostgresSaver로 바꾸는 것이 배포 전 첫 번째 점검 항목입니다.
LangGraph vs Deep Agents
직접 구현 vs 고수준 추상화 — 시작은 Deep Agents, 제어는 LangGraph
| 항목 | LangGraph (직접) | Deep Agents (추상화) |
|---|---|---|
| 시작 | StateGraph 직접 구성 | create_deep_agent() 한 줄 |
| 유연성 | ✓ 모든 패턴 구현 가능 | 프리셋 패턴 내에서 |
| 빌트인 | 없음 — 직접 구현 | execute·eval(코드 실행), Harness Profiles |
| 배포 | AgentCore Runtime / 자체 | Managed Deep Agents (LangSmith) |
| 버전 | LangGraph 1.x (안정) | v0.6 (빠른 진화 중) |
시작은 create_deep_agent() 한 줄로 빠르게, 프리셋을 벗어나는 패턴이 필요하면 StateGraph 직접 구성으로 내려갑니다.
Checkpointer — 상태 영속화
스냅샷이 만드는 세 가지 능력 — HITL 재개 · 장애 복구 · 시간여행
MemorySaver
개발용 인메모리
- 설정 없이 바로 사용 — 빠른 실험
- 프로세스 종료 시 상태 소실
- 로컬 개발 · 단위 테스트에 적합
- 프로덕션 사용 금지
PostgresSaver
프로덕션 영속화
- DB에 상태 스냅샷 저장 — 재시작에도 유지
- HITL 재개와 장애 복구의 전제 조건
- 과거 체크포인트로 되돌리는 시간여행 디버깅
- DynamoDB 등은 커뮤니티 구현
Checkpointer는 편의 기능이 아니라 HITL과 장애 복구의 전제 조건입니다 — 배포 전 교체가 체크리스트 1번인 이유입니다.
AgentCore Runtime으로 배포
컴파일된 그래프를 관리형 런타임에 올리는 4단계
-
1
스캐폴드 생성
agentcore create --framework LangChain_LangGraph — 프레임워크 옵션으로 LangGraph 프로젝트 골격을 만듭니다.
-
2
그래프 컴파일
app = graph.compile(checkpointer=...) — 이때 Checkpointer는 프로덕션 백엔드로 교체합니다.
-
3
진입점 래핑
BedrockAgentCoreApp의 @app.entrypoint로 호출 진입점을 선언합니다. bedrock-agentcore 패키지는 langgraph extras를 제공합니다.
-
4
배포
agentcore deploy 한 번으로 패키징과 배포가 끝납니다. 오토스케일 · 내장 관측성 · 버전 관리는 Runtime이 제공합니다.
ECS/Lambda 자체 운영과 달리 스케일 · 관측성 · 버전 관리가 런타임에 내장됩니다 — LangGraph 코드는 그대로, 진입점만 래핑합니다.
프로덕션 체크리스트
LangGraph 에이전트를 프로덕션에 배포하기 전 확인
-
1
Checkpointer 교체
MemorySaver(개발) → PostgresSaver(프로덕션, DynamoDB는 커뮤니티 구현) — 상태 영속화 필수
-
2
LangSmith 연동
노드별 실행 시간·토큰·에러 시각화 — 병목 발견
-
3
interrupt 설계
고위험 노드에 interrupt_before 설정 — HITL 경로 확보
-
4
배포 선택
AgentCore Runtime(관리형) 또는 ECS/Lambda(자체 운영)
Checkpointer 교체·LangSmith 연동·interrupt 설계·배포 선택 — 네 가지를 확인한 뒤 프로덕션으로 내보냅니다.
에이전트의 두뇌 회로
State·Node·Edge 3요소 위의 Self-RAG·ReAct·Supervisor·HITL — 그래프가 곧 에이전트 설계
그래프로 에이전트와 RAG를 제어한다
State·Node·Edge 3요소 위에 Self-RAG·ReAct·Supervisor·HITL — LangGraph는 에이전트의 두뇌 회로를 설계하는 도구입니다.
StateGraph 위에 RAG 루프 · ReAct · Supervisor · HITL 패턴 구현