인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

이성규님의 프로필 이미지

작성한 질문수

AI 에이전트로 구현하는 RAG 시스템(w. LangGraph)

섹션 5, 사용자 정의 조건부 엣지 관련 질문입니다.

작성

·

70

·

수정됨

0

from langgraph.graph import MessagesState, StateGraph, START, END
from langchain_core.messages import HumanMessage, SystemMessage
from langgraph.prebuilt import ToolNode
from IPython.display import Image, display

# LangGraph MessagesState 사용
class GraphState(MessagesState):
    pass

# 노드 구성 
def call_model(state: GraphState):
    system_message = SystemMessage(content=system_prompt)
    messages = [system_message] + state['messages']
    response = llm_with_tools.invoke(messages)
    return {"messages": [response]}

def should_continue(state: GraphState):
    last_message = state["messages"][-1]
    # 도구 호출이 있으면 도구 실행 노드로 이동
    if last_message.tool_calls:
        return "execute_tools"
    # 도구 호출이 없으면 답변 생성하고 종료 
    return END

# 그래프 구성
builder = StateGraph(GraphState)
builder.add_node("call_model", call_model)
builder.add_node("execute_tools", ToolNode(tools))

builder.add_edge(START, "call_model")
builder.add_conditional_edges(
    "call_model", 
    should_continue,
    {
        "execute_tools": "execute_tools",
        END: END
    }
)
builder.add_edge("execute_tools", "call_model")

graph = builder.compile()

# 그래프 출력 
display(Image(graph.get_graph().draw_mermaid_png()))
# 그래프 실행
inputs = {"messages": [HumanMessage(content="스테이크 메뉴의 가격은 얼마인가요?")]}
messages = graph.invoke(inputs)

위 코드는 강사님께서 제공해주신 코드를 가져온 것입니다.

제가 궁금한 것은 Tool 노드를 사용하고 다시 call_model 노드로 왔을 때 SytemMessage가 중복되지 않을까? 라는 생각을 했습니다.

 

예를 들어 message : [유저 인풋] 가 처음으로 그래프에 들어오게된다면

def call_model(state: GraphState):
    system_message = SystemMessage(content=system_prompt)
    messages = [system_message] + state['messages']
    response = llm_with_tools.invoke(messages)
    return {"messages": [response]}

message : SystemMessage + [유저 인풋]

이 될것입니다.

그 이후 response를 호출하여

message : SystemMessage + [유저 인풋] + toolMessage

이 되어 상태를 업데이트 하고,

 

그리고 tool 콜이 있어서 툴노드를 마무리 한 이후 돌아왔을 땐 GraphState에 있는 message는 SystemMessage + [유저 인풋] + toolMessage + [툴이보낸 메세지] 일테니

call model 노드에서

SystemMessage + SystemMessage + [유저 인풋] + toolMessage + [툴이보낸 메세지]

가 적용되어 툴 콜 할때마다 SytemMessage가 쌓이는 구조가 되지 않을까 생각이 들었는데 맞을까요?

 

 

답변 1

0

판다스 스튜디오님의 프로필 이미지
판다스 스튜디오
지식공유자

안녕하세요! 좋은 질문입니다.

우려하신 부분은 이해가 됩니다. 그러나 이 코드에서는 시스템 메시지가 중복되어 쌓이지 않습니다.

  1. call_model 함수 내부를 보면:

    def call_model(state: GraphState):
        system_message = SystemMessage(content=system_prompt)
        messages = [system_message] + state['messages']
        response = llm_with_tools.invoke(messages)
        return {"messages": [response]}
    
  2. 중요한 부분은 return {"messages": [response]} 입니다. 이 부분이 상태를 어떻게 업데이트하는지가 중요합니다.

  3. MessagesState는 메시지 배열을 관리하는 특별한 상태 클래스인데, return {"messages": [response]} 코드는 기존 메시지를 대체하지 않고 추가합니다.

  4. 하지만 system_message는 매번 함수 호출시 새로 생성되어 임시로 메시지 목록에 추가되고, 상태에는 중복 저장되지 않습니다.

  5. 최종 상태에 저장된 messages 속성의 목록을 확인해보시면 됩니다.



    감사합니다.