스마티지와 글 읽기 – LangGraph 01

Lang Graph

 

LangGraph

제어 가능한 AI 에이전트(Agent)를 구축하기 위한 로우 레벨(low-level) 오케스트레이션 프레임워크입니다. 개발자가 강력하고 적응성 높은 AI 에이전트를 구축하도록 지원하는 것을 목표로 합니다.

에이전트 오케스트레이션에 특화되어 사용자 정의 아키텍처, 장기 기억(long-term memory), 인간 개입(human-in-the-loop) 등을 통해 복잡한 작업을 안정적으로 처리할 수 있도록 지원합니다.

저스틴) 장기 기억할 것은 검색 엔진에서 얻은 데이터와 사용자가 제공한 데이터여야 합니다. LLM이 갖고 있는 데이터는 필요 없고, 검색 엔진에서 얻은 것은 다시 검색 엔진에서 얻으면 되니, 결국 장기 기억할 것은 사용자 데이터만이 됩니다. 사용자 데이터도 LLM 이 보유한 데이터에서 가능한 것은 장기 기억할 필요 없습니다.

 

 

LangGraph 퀵스타트

이 튜토리얼은 LangGraph를 사용하여 지원 챗봇(support chatbot)을 구축하는 과정을 단계별로 안내합니다. 목표는 기본적인 챗봇부터 시작하여 점진적으로 다음과 같은 고급 기능을 추가하는 것입니다.

  • 웹 검색을 통한 일반적인 질문 답변
  • 대화 상태 유지 (메모리 기능)   저스틴) 챗 이력 수준이 아니다. 
  • 복잡한 질문에 대한 인간 검토 요청 (Human-in-the-loop) 저스틴) 사람은 대화 방식보다 UI 방식을 편해할 수 있습니다.
    • 실행 중단 및 재개 메커니즘은 상호작용적이고 신뢰성 있는 에이전트 구축에 중요합니다.
  • 챗봇 행동 제어를 위한 사용자 정의 상태(Custom State) 사용
    • 기본 메시지 목록 외에 애플리케이션별 상태를 정의하고 관리하는 방법은 복잡한 로직 구현에 필요합니다. 
  • 대화 경로 되감기 및 탐색 (시간 여행, Time Travel)
    • 체크포인트 기록을 사용하여 그래프의 이전 상태로 돌아가 실행을 재개하는 방법. 단순한 대화 기록 저장을 넘어, LangGraph의 상태 지속성 및 메모리 관리의 핵심 원리입니다.
    • 체크포인팅을 활용한 고급 기능으로, 디버깅, 실험, 사용자 경험 향상에 유용합니다.

 

LangGraph를 사용하여 지원 챗봇(support chatbot)을 만드는 방법을 배웁니다. 이 튜토리얼을 통해 챗봇에 다음과 같은 기능을 단계별로 추가하게 됩니다.

  • ✅ 웹 검색: 챗봇이 모르는 질문에 답하기 위해 웹을 검색하는 기능.
  • ✅ 대화 상태 유지: 이전 대화 내용을 기억하여 자연스러운 대화를 이어가는 기능 (메모리).
  • ✅ 인간 검토: 챗봇이 스스로 처리하기 어렵거나 중요한 결정이 필요한 경우, 사람에게 검토를 요청하는 기능 (Human-in-the-loop).
  • ✅ 사용자 정의 상태: 챗봇의 동작을 세밀하게 제어하기 위해 기본 대화 기록 외에 추가적인 정보를 상태에 저장하고 사용하는 기능.
  • ✅ 시간 여행: 대화의 특정 시점으로 돌아가서 다른 경로를 탐색하거나 수정하는 기능.

 

 Setup (설정)

이 섹션은 튜토리얼 코드를 실행하기 전에 필요한 사전 준비 작업을 안내합니다.

 

LangSmith 설정 안내:

  • LangSmith 가입 권장: 튜토리얼 중간중간 LangSmith 링크가 제공되는데, LangSmith에 가입하면 LangGraph 애플리케이션의 실행 과정(Trace)을 시각적으로 확인하고, 문제가 발생했을 때 원인을 찾거나(디버깅), 성능을 테스트하고 개선하는 데 매우 유용합니다. LangSmith는 LangGraph 개발 경험을 향상시키는 데 도움을 줍니다.

 

Part 1: Build a Basic Chatbot (기본 챗봇 구축)

 섹션을 설명드리겠습니다. 이 섹션에서는 LangGraph의 가장 기본적인 구성 요소들을 사용하여 간단한 챗봇을 만듭니다.

목표:

  • LangGraph를 이용해 간단한 챗봇 구조를 정의하고 실행하는 방법을 배웁니다.
  • LangGraph의 핵심 개념인 StateGraphStateNodeEdgeSTARTEND를 이해합니다. 저스틴) 워크플로어이니 UML의 액티비티 다이어그램이나 플로어 차트를 생각하면 됩니다. 상태라는 단어가 나오듯이 상태를 중심으로 하는 UML 상태머신을 생각하면 더 도움이 됩니다.  그런데 이런 것들은 절차가 정해진 것들인데 절차보다 단일 단계를 실행하는 ReAct와 어떻게 연결할 지 궁급해집니다. 

코드 설명:

  1. State 정의 (State 클래스):

    • State: 그래프의 상태(state)를 정의하는 파이썬 딕셔너리 형태의 클래스입니다. 그래프의 각 노드는 이 State 객체를 입력받고, 처리 결과를 이 State 형태로 반환하여 그래프의 상태를 업데이트합니다.
    • TypedDict: 파이썬의 타입 힌트를 사용하여 딕셔너리의 키와 값 타입을 명시적으로 정의합니다.
    • Annotated: 타입 힌트에 추가적인 메타데이터(여기서는 상태 업데이트 방식인 add_messages)를 붙일 수 있게 합니다.
  1. StateGraph 생성 (graph_builder = StateGraph(State)): 

    • StateGraph: LangGraph에서 그래프 구조를 정의하고 관리하는 핵심 클래스입니다. 그래프를 상태 머신(state machine)으로 간주합니다. 저스틴) 상태를 표현하려면 여러 변수들 값이 필요할 수 있으니 Dictionary가 적당합니다. 
  2. 챗봇 노드 정의 (chatbot 함수 및 add_node):

    • Node: 그래프 내에서 특정 작업을 수행하는 단위입니다. 주로 파이썬 함수로 정의됩니다. 입력으로 현재 상태(State)를 받고, 상태를 업데이트할 딕셔너리를 반환합니다.
  3. 진입점(Entry Point) 설정 (add_edge(START, "chatbot")):

    • Edge: 노드 간의 전환(transition) 또는 흐름을 정의합니다.
    • START: 그래프 실행의 시작을 나타내는 특수 노드 이름입니다. 저스틴) 사용자가 에이전트에게 지시하면서 에이전트가 할 일을 시작합니다. 
  4. 종료점(Finish Point) 설정 (add_edge("chatbot", END)):

    • END: 그래프 실행의 종료를 나타내는 특수 노드 이름입니다. 특정 노드가 실행된 후 END로 엣지가 연결되면, 더 이상 진행할 작업이 없으면 그래프 실행이 멈춥니다. 저스틴) 사용자 지시(목표)를 달성하고 마치거나 목표 달성하지 못하고 마치거나 중간에 사용자가 멈추라고 할 수 있습니다.
  5. 그래프 컴파일 (graph = graph_builder.compile()):

    • compile()StateGraph에 정의된 노드와 엣지 구성을 바탕으로 실제 실행 가능한 객체를 만듭니다.
  6. 그래프 시각화 (선택 사항):

    • 이 시각화를 통해 START에서 chatbot 노드로, 그리고 chatbot 노드에서 END로 이어지는 단순한 흐름을 확인할 수 있습니다.
  7. 챗봇 실행 루프:

    • graph.stream(): 그래프를 실행하고 각 단계(노드 실행)의 결과를 스트리밍으로 받아볼 수 있습니다. 사용자에게 실시간 응답을 보여주는 데 유용합니다.
    • 입력 형식: 그래프를 실행할 때는 항상 State에서 정의한 키(messages)를 포함하는 딕셔너리 형태로 초기 상태를 전달해야 합니다.

 

Part 2: 🛠️ Enhancing the Chatbot with Tools (도구로 챗봇 강화) – 웹 검색 도구
  1. 도구 사용을 위한 사전 준비 (Requirements):

    • Tavily는 LLM 애플리케이션에 최적화된 검색 API입니다. 저스틴) Tavily는 My AI Smateasy에서 AI 검색엔진으로 채택한 것입니다. 
  2. 도구 정의 및 테스트 (TavilySearchResults):

    • TavilySearchResults: LangChain에서 제공하는 Tavily 검색 도구 클래스입니다.
    • tools: 에이전트(챗봇)가 사용할 수 있는 도구들의 목록입니다. 이 목록을 나중에 LLM과 그래프 노드에 전달합니다.
  3. State 및 GraphBuilder 재정의 (도구 연동 준비):

    • bind_tools(tools): LLM이 tools 리스트에 있는 도구들의 존재와 사용법(이름, 설명, 필요한 인자 등)을 알게 합니다. LLM은 이제 단순히 텍스트 응답뿐만 아니라, “이 도구를 이런 인자로 호출해야 해”라는 형식의 응답(AIMessage 내 tool_calls 속성)을 생성할 수 있습니다.
  4. 도구 실행 노드 정의 (BasicToolNode – 직접 구현 예시):

    • 튜토리얼에서는 이해를 돕기 위해 먼저 ToolNode의 기능을 직접 구현하는 BasicToolNode 클래스를 보여줍니다. (나중에는 LangGraph의 내장 ToolNode를 사용합니다.)
    • ToolNode의 역할: LLM이 도구 사용을 요청하면(즉, 마지막 메시지에 tool_calls가 있으면), 해당 도구를 실제로 실행하고 그 결과를 ToolMessage 형태로 상태에 추가하는 역할을 합니다. 저스틴) 도구는 자체적으로 구현해야 하는 내부 도구들과 MCP 같은 표준을 지키는 외부 도구들을 사용합니다. MCP도 LLM에 사용되려면 여기서 도구를 정의할 때 필요한 정보들을 제공해야 합니다. 
  5. 조건부 엣지 정의 (route_tools 함수 및 add_conditional_edges):

    • LLM의 응답에 따라 다음 단계를 결정하는 라우터 함수를 정의합니다.
    • Conditional Edges: 특정 노드 실행 후, 현재 상태(State)를 바탕으로 다음에 실행할 노드를 동적으로 결정하는 엣지입니다. 조건 함수(여기서는 route_tools)의 반환값에 따라 다른 노드로 분기할 수 있습니다. 저스틴) 조건문은 절차를 계획해서 실행하는 에이전트에 필요한 것입니다. ReAct는 한 단계만 계획해서 실행하고 변화를 보고 다음 상태를 결정하는 것입니다. 아직까지 ReAct를 어떻게 연결할지는 안 나왔네요.
  6. 엣지 추가 및 그래프 컴파일:

    • 이제 그래프는 다음과 같은 루프(Loop) 구조를 가집니다:
      • START -> chatbot
      • chatbot -> (조건 검사)
        • 도구 호출 O -> tools -> chatbot (다시 LLM에게)
        • 도구 호출 X -> END (종료)
  7. 그래프 시각화 및 실행:

    • 그래프 시각화를 통해 새로 추가된 tools 노드와 chatbot 노드 사이의 양방향 흐름(조건부 엣지 포함)을 확인할 수 있습니다.
    • 챗봇 실행 코드는 Part 1과 동일한 stream_graph_updates 함수를 사용합니다. 이제 챗봇에게 학습 데이터에 없는 질문(예: “LangGraph에 대해 무엇을 아나요?”)을 하면, LLM이 tavily_search_results_json 도구를 호출하고(tool_calls 생성), tools 노드가 실행되어 검색 결과를 ToolMessage로 반환하며, 다시 chatbot 노드가 이 결과를 바탕으로 최종 답변을 생성하는 과정을 볼 수 있습니다.

 

Part 3: Adding Memory to the Chatbot (챗봇에 메모리 추가) – 체크포인팅(Checkpointing) 

체크포인팅 (Checkpointing)

  • LangGraph에서 ‘메모리’는 단순히 이전 메시지를 저장하는 것 이상입니다. 그래프의 전체 상태(State)를 각 단계(노드 실행 후)마다 저장하는 것을 의미합니다.이렇게 저장된 상태를 체크포인트(Checkpoint)라고 합니다.
  • 체크포인트를 사용하면, 나중에 동일한 대화(식별자 사용)를 다시 시작할 때 마지막 체크포인트부터 이어서 실행할 수 있습니다. 이를 통해 챗봇은 이전 대화 내용을 ‘기억’하는 것처럼 보이게 됩니다. 저스틴) 기억하지 않고 기억하는 것처럼 보이게만 하네요.  장기기억하는게 아닙니다. 
  • 체크포인팅은 단순히 대화 기록뿐만 아니라, Part 5에서 배울 사용자 정의 상태(custom state) 등 그래프의 모든 상태 정보를 저장하므로 매우 강력합니다.
  1. 체크포인터 생성 (MemorySaver):

    • Checkpointer: 그래프의 상태를 저장하고 불러오는 역할을 담당하는 객체입니다. 다양한 종류(인메모리, SQLite, PostgreSQL 등)가 있습니다. 저스틴) 장기 기억한다는 것은 영속성을 제공하는 데이터베이스에 체크포인트를 저장하는 것으로 하네요. 시맨틱 커널의 context variables가 state에 해당하고 그 상태를 저장해 놓는게 checkpointer게 되겠네요.  장기 기억도 중요하지만 어떤 맥락에서의 기억 체인도 중요함을 보여주네요. 
  2. 그래프 정의 (Part 2 코드 재사용 + Prebuilt 컴포넌트 사용):

    • 이 파트에서는 Part 2에서 직접 구현했던 BasicToolNode와 route_tools 대신, LangGraph에서 제공하는 ToolNode와 tools_condition을 사용합니다. 기능은 동일하지만 코드가 더 간결해지고, ToolNode는 병렬 도구 실행 같은 추가적인 최적화 기능을 제공할 수 있습니다.
  3. 체크포인터와 함께 그래프 컴파일:

    • compile() 메서드에 checkpointer를 전달하는 것이 핵심입니다. 이제 이 graph 객체는 상태 저장 및 로드 기능을 갖게 됩니다.
  4. 그래프 시각화 (선택 사항):

    • 그래프 구조 자체는 Part 2와 동일합니다. 체크포인터 추가는 그래프의 노드나 엣지 구조를 바꾸지 않고, 실행 시 상태 저장 방식을 변경하는 것입니다.
  5. 메모리 기능 테스트 (config 와 thread_id 사용):

    • 핵심invoke나 stream 메서드를 호출할 때 두 번째 인자로 config 딕셔너리를 전달하는 것입니다. 이 config 안에 있는 thread_id를 기준으로 체크포인터가 해당 대화의 마지막 상태를 불러와서 실행을 이어갑니다.
    • 따라서 두 번째 호출에서 챗봇은 첫 번째 호출의 내용(“My name is Will”)을 기억하고 “Will”이라는 이름을 사용하여 응답할 수 있습니다.
  6. 다른 스레드 ID로 테스트:

    • thread_id를 “1”이 아닌 “2”로 변경하여 실행하면, 체크포인터는 thread_id="2"에 해당하는 저장된 상태를 찾으려 하지만 없으므로, 처음부터 대화를 시작합니다. 따라서 챗봇은 이름을 기억하지 못합니다. 이는 thread_id가 대화 세션을 구분하는 역할을 한다는 것을 보여줍니다.
  7. 저장된 상태 확인 (get_state):

    • get_state(config): 특정 대화 스레드의 현재 상태를 직접 확인하고 싶을 때 유용합니다.

 

 

Part 4: Human-in-the-loop (인간 개입)

이 파트에서는 에이전트(챗봇)의 실행 흐름 중간에 사람의 입력이나 승인을 받을 수 있도록 하는 방법을 배웁니다.  저스틴)  사람과 계속 상호작용해야 합니다. 필요에 따라 대화나 UI로 상호작용해야 합니다. My AI Smarteasy의 파일럿 에이전트인 “My AI”가 중간 중간에 사용자 의견을 묻는 팝업 화면이 나오는 이유입니다. 

핵심 개념: Human-in-the-loop (HITL)

  • AI 에이전트는 때때로 부정확하거나 예상치 못한 행동을 할 수 있습니다. 중요한 작업을 수행하기 전에 사람의 검토를 받거나, 에이전트가 막혔을 때 사람에게 도움을 요청하는 기능은 신뢰성을 높이는 데 중요합니다.
  • LangGraph는 체크포인팅 시스템을 기반으로 이러한 HITL 워크플로우를 자연스럽게 지원합니다. 실행이 중단되면 현재 상태가 체크포인트에 저장되고, 나중에 사람의 입력과 함께 실행을 재개할 수 있습니다.

코드 설명:

  1. HITL을 위한 도구 정의 (human_assistance):

    • @tool: 함수를 LangChain 도구로 쉽게 만들어주는 데코레이터입니다. 함수의 독스트링(docstring)이 도구의 설명으로 사용됩니다.
    • interrupt(payload): 이 함수가 호출되면 LangGraph 실행이 즉시 멈춥니다. payload(여기서는 {"query": query})는 실행을 멈춘 이유나 필요한 정보를 외부에 전달하는 데 사용됩니다. 그래프의 현재 상태는 체크포인터에 저장됩니다.
    • 반환 값interrupt 함수는 실행이 재개될 때 외부에서 Command(resume=...) 객체를 통해 전달된 값을 반환합니다.
  2. 그래프 설정 (Part 3 기반 + 새 도구 추가):

    • 핵심 변경 사항은 tools 리스트에 human_assistance 도구를 추가하고, ToolNode에도 이 도구를 포함시킨 것입니다.
    • 병렬 도구 호출 관련 주의사항은 interrupt 사용 시 고려해야 할 중요한 점입니다.
  3. 그래프 시각화:

    • 구조는 Part 2, 3과 동일하게 보이지만, tools 노드는 이제 human_assistance 도구도 처리할 수 있습니다.
  4. Human-in-the-loop 실행 테스트:

    • 사용자가 명시적으로 “assistance”를 요청했으므로, LLM은 human_assistance 도구를 호출하는 tool_calls를 생성할 가능성이 높습니다.
    • ToolNode가 human_assistance 도구를 실행하면, 그 안의 interrupt() 함수가 호출되어 그래프 실행이 일시 중지됩니다. 터미널이나 노트북 출력에는 LLM이 human_assistance 도구를 호출했다는 메시지까지만 나오고 더 이상 진행되지 않습니다.
  5. 중단 상태 확인:

    • get_state()를 통해 현재 상태를 확인하면, 다음에 실행될 노드가 tools임을 알 수 있습니다. 즉, tools 노드 내부의 human_assistance 함수 안에서 interrupt가 발생하여 멈춘 것입니다.
  6. 실행 재개 및 사람 입력 전달 (Command 사용):

    • Command(resume=...): 중단된 그래프 실행을 재개시키는 데 사용됩니다. resume 키에 전달된 값은 interrupt 함수가 반환할 값이 됩니다.
    • 그래프의 stream 또는 invoke 메서드에 입력 데이터 대신 Command 객체를 전달하고, **동일한 config**를 사용하면, LangGraph는 체크포인트에서 상태를 로드하고 중단된 지점부터 실행을 재개합니다.
    • 재개 후 실행 흐름:
      1. human_assistance 함수 내 interrupt가 human_command의 resume 값({"data": ...})을 반환합니다.
      2. human_assistance 함수는 "data" 키의 값을 반환합니다.
      3. ToolNode는 이 반환값을 ToolMessage로 만들어 상태에 추가합니다.
      4. 제어는 다시 chatbot 노드로 넘어가고, LLM은 ToolMessage 내용을 바탕으로 최종 응답을 생성합니다.

 

Part 5: Customizing State (상태 사용자 정의)

애플리케이션의 특정 요구에 맞는 추가적인 정보(필드)를 그래프의 상태(State)에 정의하고 활용하는 방법을 배웁니다.

목표:

  • TypedDict를 사용하여 그래프의 State에 사용자 정의 필드를 추가하는 방법을 배웁니다.
  • 도구(Tool) 내에서 이러한 사용자 정의 상태 필드를 업데이트하는 방법을 배웁니다 (Command(update=...) 사용).
  • 상태에 저장된 추가 정보가 그래프 내 다른 노드나 외부 시스템에서 어떻게 활용될 수 있는지 이해합니다.
  • graph.update_state()를 사용하여 외부에서 직접 상태를 수정하는 방법을 알아봅니다.

핵심 개념: 사용자 정의 상태 (Custom State)

  • 지금까지 State에는 messages 필드만 있었습니다. 하지만 더 복잡한 애플리케이션에서는 대화 기록 외에도 다양한 정보를 그래프의 상태로 관리해야 할 수 있습니다. 예를 들어, 사용자의 이름, 특정 작업의 진행 상태, 검색 결과에서 추출한 구조화된 데이터 등이 필요할 수 있습니다.
  • LangGraph에서는 TypedDict를 확장하여 필요한 만큼 필드를 State에 추가할 수 있습니다.
  • 이렇게 추가된 상태 필드도 체크포인팅 시스템에 의해 자동으로 저장되고 관리됩니다.

코드 설명:

  1. 사용자 정의 필드가 추가된 State 정의:

    • 기존 State 클래스에 name과 birthday라는 두 개의 str 타입 필드를 추가했습니다. 이제 이 그래프의 상태는 messagesnamebirthday 세 가지 정보를 포함하게 됩니다.
  2. 상태 업데이트 기능이 포함된 도구 재정의 (human_assistance):

    • 이전 파트의 human_assistance 도구를 수정하여, 사람의 검토를 받은 후 name과 birthday 상태 필드를 직접 업데이트하도록 변경합니다.
    • Command(update=...): 도구 실행 결과로 단순히 문자열이나 객체를 반환하는 대신, Command 객체를 반환하면서 update 키에 상태를 업데이트할 내용을 딕셔너리로 전달할 수 있습니다. LangGraph는 이 Command를 받으면 해당 내용을 현재 상태에 병합(merge)하여 업데이트합니다. (messages는 add_messages 리듀서에 의해 추가되고, name과 birthday는 새 값으로 덮어쓰기됩니다.)
    • InjectedToolCallIdToolMessage를 생성할 때 원본 tool_call과 연결하기 위한 ID가 필요합니다. 이 ID를 LLM이 직접 생성하거나 알 필요는 없으므로, @tool 데코레이터와 InjectedToolCallId 어노테이션을 함께 사용하면 LangChain이 실행 시점에 해당 ID를 함수 인자로 자동으로 주입해 줍니다.
  3. 그래프 설정 및 컴파일 (나머지는 동일):

    • State 정의만 변경되었고, 나머지 그래프 구성(노드, 엣지, 체크포인터)은 이전과 동일하게 설정하고 컴파일합니다.
  4. 사용자 정의 상태 활용 테스트:

    • 사용자는 LangGraph 출시일을 찾아보고, 찾으면 human_assistance 도구를 사용하여 검토해달라고 요청합니다.
    • LLM은 먼저 tavily_search를 호출하여 정보를 찾고, 그 결과를 바탕으로 human_assistance 도구를 호출할 때 name과 birthday 인자를 채워서 호출할 것입니다. (LLM이 잘못된 정보를 찾거나 추측할 수도 있습니다.)
    • human_assistance 도구 내에서 interrupt가 발생하여 실행이 멈춥니다.
  5. 사람의 개입 및 상태 업데이트 확인:

    • 사람이 Command(resume=...)으로 올바른 이름과 생일 정보를 전달하며 실행을 재개합니다.
    • human_assistance 도구는 이 정보를 받아 Command(update=...)를 반환합니다.
    • LangGraph는 이 update 내용을 상태에 반영합니다.
    • get_state()를 통해 확인하면 name과 birthday 필드가 사람에 의해 수정된 값으로 업데이트된 것을 볼 수 있습니다.
  6. 외부에서 상태 수동 업데이트 (graph.update_state):

    • update_state(config, values): 특정 대화 스레드(config)의 상태(values 딕셔너리에 지정된 필드)를 강제로 업데이트합니다. 이는 디버깅이나 특정 시나리오에서 상태를 직접 조작해야 할 때 유용합니다. 이 업데이트도 LangSmith 추적에 기록됩니다.

 

 

Part 6: Time Travel (시간 여행)

체크포인팅 시스템을 활용하여 과거의 특정 시점으로 돌아가 실행을 재개하는 방법을 배웁니다.

LangGraph의 체크포인팅이 단순히 마지막 상태만 저장하는 것이 아니라, 실행 히스토리 전체를 기록한다는 것을 이해합니다.

이 “시간 여행” 기능이 디버깅, 실험, 사용자 경험 개선(예: 실수 되돌리기, 다른 경로 탐색) 등에 어떻게 활용될 수 있는지 이해합니다.

저스틴) 꽤 오랜 기간 대화한 내용이라면 이렇게 기억하는 것은 너무 많은 양을 기억하는거 아닌가?

  1. 기본 그래프 설정 (Part 3의 도구 + 메모리 챗봇 재사용):

    • 이 파트에서는 시간 여행 기능을 명확히 보여주기 위해, Part 3에서 만들었던 비교적 간단한 도구 사용 및 메모리 기능이 있는 챗봇 그래프 코드를 다시 사용합니다. (State에는 messages 필드만 있음)
  2. 여러 단계의 대화 실행 (히스토리 생성):

    • 챗봇과 여러 턴에 걸쳐 대화를 진행하여 체크포인트 히스토리를 만듭니다.
    • thread_id="1"에 대해 두 번의 stream 호출을 통해 여러 노드가 실행되었고, 각 노드 실행 후의 상태가 memory 체크포인터에 순서대로 기록되었습니다.
  3. 상태 히스토리 조회 (get_state_history):

    • graph.get_state_history(config): 특정 config(주로 thread_id 기준)에 대한 모든 과거 체크포인트(StateSnapshot 객체)를 최신순으로 반환합니다.
    • StateSnapshot 객체에는 해당 시점의 상태 값(values), 다음에 실행될 노드(next), 그리고 해당 스냅샷을 식별하는 config(여기에는 고유한 checkpoint_id 포함) 정보가 들어있습니다.
    • 튜토리얼에서는 임의의 조건(메시지 6개)을 만족하는 과거 상태(to_replay)를 선택합니다. 이 상태는 두 번째 stream 호출 중 chatbot 노드가 도구 호출(tool_calls)을 생성한 직후, tools 노드가 실행되기 전의 상태입니다. (Next: ('tools',) 로 확인 가능)
  4. 선택한 과거 시점 정보 확인:

    • to_replay.config에 포함된 checkpoint_id는 우리가 돌아가고 싶은 정확한 과거 시점을 가리킵니다.
  5. 과거 시점에서 실행 재개 (시간 여행!):

    • 핵심stream (또는 invoke) 메서드의 두 번째 인자로 특정 checkpoint_id가 포함된 config 객체를 전달하는 것입니다.
    • LangGraph는 이 checkpoint_id를 보고 해당 시점의 상태를 체크포인터에서 로드합니다.
    • 그리고 to_replay.next에 지정된 노드(tools 노드)부터 실행을 재개합니다.
    • 실행 결과 출력: 첫 번째로 출력되는 것이 Tool Message (검색 결과)인 것을 볼 수 있습니다. 이는 chatbot 노드를 건너뛰고 바로 tools 노드가 실행되었음을 의미합니다. 즉, 성공적으로 과거 시점에서 실행을 재개한 것입니다.
About the Author
(주)뉴테크프라임 대표 김현남입니다. 저에 대해 좀 더 알기를 원하시는 분은 아래 링크를 참조하세요. http://www.umlcert.com/kimhn/

Leave a Reply

*