LLM 기반 시스템에서 복잡한 작업 흐름을 상태(State) 기반으로 제어하고, 각 단계를 명시적으로 설계할 수 있게 해주는 구조
| 용어 | 설명 |
|---|---|
| LangGraph | LangChain의 실행 흐름을 상태 기반 그래프로 제어하는 확장 구조 |
| StateGraph | 상태 전이(State Transition) 기반으로 흐름을 구성하는 메인 구조 |
| State | 전체 그래프에서 공유되는 데이터, 작업의 현재 스냅샷 |
| Node | 상태를 입력받아 처리하고 새로운 상태를 반환하는 작업 단위 |
| Edge | 노드 간 실행 순서 정의, 조건부 분기도 가능 |
| compile | 그래프를 실행 가능 상태로 전환 |
| invoke | 초기 상태를 전달하여 그래프를 실행함 |
초기 상태 입력
↓
START → Node1 → Node2 → ... → END
(각 노드는 상태를 변형하여 반환)
예:
입력: {"text": "안녕하세요"}
→ Node: text = "반갑습니다"
→ 출력: {"text": "반갑습니다"}
from pydantic import BaseModel
class OverallState(BaseModel):
text: str
또는 TypedDict로도 정의 가능
def greet_node(state: OverallState):
return {"text": "반갑습니다"}
from langgraph.graph import StateGraph, START, END
builder = StateGraph(OverallState)
builder.add_node("greet", greet_node)
builder.add_edge(START, "greet")
builder.add_edge("greet", END)
graph = builder.compile()
graph.invoke({"text": "안녕하세요"})
# 출력: {"text": "반갑습니다"}
def decide_next_step(state):
if state["is_menu_related"]:
return "search_menu_info"
return "generate_general_response"
builder.add_conditional_edges(
"analyze_input",
decide_next_step,
{
"search_menu_info": "search_menu_info",
"generate_general_response": "generate_general_response"
}
)
의미: 조건에 따라 실행 경로를 분기시킴 → 의도 분류, 평가-재생성 루프 등에 사용
from typing import Annotated, List, TypedDict
from langgraph.graph.message import add_messages
class GraphState(TypedDict):
messages: Annotated[List[str], add_messages]
Annotated[... , add_messages]를 사용하면 메시지 누적 가능| 활용 사례 | 적용 위치 |
|---|---|
| RAG | 검색 → 평가 → 생성 노드 구성 |
| ReAct | 추론 → 도구 실행 → 재응답 흐름 구성 |
| Self-RAG | 응답 품질 평가 → 재질문 루프 구성 |
| 대화 시스템 | 메시지 누적, 응답 흐름 제어 |
| Adaptive Routing | 질문 분석 → 라우팅 분기 처리 |
| 장점 | 단점 |
|---|---|
| 흐름이 명확하여 디버깅 쉬움 | 초기 구성 복잡, 진입장벽 존재 |
| 상태 기반 처리 가능 | 모든 흐름을 수동으로 지정해야 함 |
| 조건, 반복, 병렬 처리 유연 | 노드/엣지가 많아지면 가독성 저하 |
| 다양한 에이전트 패턴 구현 가능 | 단순 작업에는 과한 구조 |
상태 기반 그래프 구조를 통해,
복잡한 LLM 실행 과정을 모듈화하고,
흐름을 분기·제어·반복할 수 있도록 만들어준다.