본문 바로가기

LangChain&LangGraph

디버깅 - #2 interrupt

 

interrupt :

LangGraph의 진행을 특정 단계에서 중지 기능

 

구성도

chatbot 역할 :  사전 llm.bind_tools 로 제공된 tools 을 사용할지 결정하는 역할

tools :  웹 검색 도구 제공,chatbot에서 tool_calls 호출시 사용되는 tools 를 가지고 있는 노

예제 코드

########## 1. 상태 정의 ##########
class State(TypedDict):
    # 메시지 목록 주석 추가
    messages: Annotated[list, add_messages]
########## 2. 노드 추가 ##########
def chatbot(state: State):
    # 메시지 호출 및 반환
    tavily_tool = get_tavily_tool()
    tools = [tavily_tool]
    # LLM 초기화
    llm = get_gemini()
    # 도구와 LLM 결합
    llm_with_tools = llm.bind_tools(tools)
    return {"messages": [llm_with_tools.invoke(state["messages"])]}

########## 3. 그래프 노드 생성 ##########
state_graph = StateGraph(State)
# 챗봇 노드 추가
state_graph.add_node("chatbot", chatbot)
# 도구 노드 생성 및 추가
tool_node = ToolNode(tools=[get_tavily_tool()])
# 도구 노드 추가
state_graph.add_node("tools", tool_node)

########## 4. 그래프 노드간 연결 ##########
state_graph.add_edge("tools", "chatbot")
state_graph.add_edge(START, "chatbot")
state_graph.add_edge("chatbot", END)
state_graph.add_conditional_edges(
    "chatbot",
    tools_condition,
)
########## 5. 메모리 추가 ##########
cp =get_check_pointer()
graph = state_graph.compile(checkpointer=cp)

question = "오늘 서울 날씨 검색"
config = get_runnable_config(recursion_limit=10,thread_id=get_random_uuid())

########## 6. 실행 ##########
for event in graph.stream(
    input={'messages':question},
    config=config,
    stream_mode="values",
    interrupt_before=["tools"],  # tools 실행 전 interrupt(tools 노드 실행 전 중단)
):
    for key, value in event.items():
        # key 는 노드 이름
        print(f"\n[{key}]\n")

        # value 는 노드의 출력값
        print(value)
       
        # value 에는 state 가 dict 형태로 저장(values 의 key 값)
        if "messages" in value:
            print(f"메시지 개수: {len(value['messages'])}")

결과


[HumanMessage(content='오늘 서울 날씨 검색', additional_kwargs={}, response_metadata={}, id='f1fea0d4-a3e4-43ad-bb74-320684ea177c'), AIMessage(content='', additional_kwargs={'function_call': {'name': 'tavily_web_search', 'arguments': '{"query": "\\uc624\\ub298 \\uc11c\\uc6b8 \\ub0a0\\uc528"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'model_name': 'gemini-2.5-flash-lite', 'safety_ratings': []}, id='run--6593c25c-7eb0-42b6-b381-9cae8725d365-0', tool_calls=[{'name': 'tavily_web_search', 'args': {'query': '오늘 서울 날씨'}, 'id': '4e34d783-ec95-4d5b-87fc-09607cfed81c', 'type': 'tool_call'}], usage_metadata={'input_tokens': 90, 'output_tokens': 22, 'total_tokens': 112, 'input_token_details': {'cache_read': 0}})]

 

HumanMessage  : 사용자 질의 

AIMessage : chatbot 의 판단 ( tavily_web_search 사용, query : 오늘 서울 날씨 )

즉 tools 를 실행하기전단계에서 interrupt 발생

interrupt_before, interrupt_after도 존재함

 

아래 코드를 통해 마지막 State 상태등 확인도 가능하여 디버깅시 매우 자주 활용됨

snapshot = graph.get_state(config)
last_messages= snapshot.values["messages"][-1]

 

 

log

https://smith.langchain.com/public/0b55085a-e6b1-4505-8ba0-76b06e24d32f/r

 

LangSmith

 

smith.langchain.com


 

자주 발생하는 시점의 전단계까지 interrupt 를 수행하여 flow 체크 가능 및 입력값 확인을 수행 할 수 있다

이어서 실행 및 리플래이등 추가로 학습 필요