langgraph / / 2024. 12. 2. 07:00

[langgraph] 도구에 구성(config) 전달하는 방법

LangGraph 공식문서를 번역한 내용입니다. 필요한 경우 부연 설명을 추가하였고 이해하기 쉽게 예제를 일부 변경하였습니다. 문제가 되면 삭제하겠습니다.

https://langchain-ai.github.io/langgraph/how-tos/recursion-limit/

런타임에서, 애플리케이션 로직에 의해 설정되어야 하는 값(예: 사용자 ID)을 도구에 전달해야 할 수 있다. 보안상의 이유로 LLM이 제어해서는 안된다. LLM은 오직 의도된 파라미터만 관리해야 한다.

LangChain 도구는 Runnable 인터페이스를 사용하며, invoke와 같은 메서드는 RunnableConfig 인수를 통해 런타임 정보를 받는다.

다음 예제에서는 사용자의 즐겨 찾는 애완동물을 관리하는 에이전트를 설정한다. 엔트리 추가, 읽기, 삭제 작업을 수행하며, 사용자 ID는 애플리케이션 로직을 통해 고정하고, 채팅 모델은 다른 파라미터를 제어하도록 한다.

준비

우선, 필요한 패키지를 설치하자.

pip install langgraph langchain_openai

도구와 모델 정의

from typing import List

from dotenv import load_dotenv
from langchain_core.runnables.config import RunnableConfig
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import ToolNode

user_to_pets = {}

load_dotenv()


@tool(parse_docstring=True)
def update_favorite_pets(
    # config는 함수 시그니처에 포함되지 않아야 하므로 docstring에 추가할 필요가 없다.
    pets: List[str],
    config: RunnableConfig,
) -> None:
    """Add the list of favorite pets.

    Args:
        pets: List of favorite pets to set.
    """
    user_id = config.get("configurable", {}).get("user_id")
    user_to_pets[user_id] = pets


@tool
def delete_favorite_pets(config: RunnableConfig) -> None:
    """Delete the list of favorite pets."""
    user_id = config.get("configurable", {}).get("user_id")
    if user_id in user_to_pets:
        del user_to_pets[user_id]


@tool
def list_favorite_pets(config: RunnableConfig) -> None:
    """List favorite pets if any."""
    user_id = config.get("configurable", {}).get("user_id")
    return ", ".join(user_to_pets.get(user_id, []))
tools = [update_favorite_pets, delete_favorite_pets, list_favorite_pets]
tool_node = ToolNode(tools)

도구 호출이 가능한 채팅 모델을 사용하려면 먼저 모델이 사용 가능한 도구들을 인식할 수 있도록 해야 한다. 이를 위해 ChatOpenAI 모델에서 .bind_tools 메서드를 호출한다.

from langchain_anthropic import ChatAnthropic
from langgraph.graph import StateGraph, MessagesState
from langgraph.prebuilt import ToolNode


model_with_tools = ChatOpenAI(model="gpt-4o-mini", temperature=0).bind_tools(tools)

ReAct Agent

ReAct 에이전트의 그래프 구현을 설정해 보자. 이 에이전트는 쿼리를 입력으로 받아들여, 쿼리를 해결할 수 있는 충분한 정보가 얻어질 때까지 도구를 반복적으로 호출한다. 우리는 방금 정의한 도구들과 함께 사전 구축된 ToolNode와 OpenAI 모델을 사용한다.

from langgraph.graph import StateGraph, MessagesState, START, END


def should_continue(state: MessagesState):
    messages = state["messages"]
    last_message = messages[-1]
    if last_message.tool_calls:
        return "tools"
    return END


def call_model(state: MessagesState):
    messages = state["messages"]
    response = model_with_tools.invoke(messages)
    return {"messages": [response]}


builder = StateGraph(MessagesState)

# Define the two nodes we will cycle between
builder.add_node("agent", call_model)
builder.add_node("tools", tool_node)

builder.add_edge(START, "agent")
builder.add_conditional_edges("agent", should_continue, ["tools", END])
builder.add_edge("tools", "agent")

graph = builder.compile()
from IPython.display import Image, display

try:
    display(
        Image(
            graph.get_graph().draw_mermaid_png(
                output_file_path="how-to-pass-config-to-tools.png"
            )
        )
    )
except Exception:
    pass

사용

from langchain_core.messages import HumanMessage

user_to_pets.clear()  # Clear the state

print(f"User information prior to run: {user_to_pets}")

inputs = {"messages": [HumanMessage(content="my favorite pets are cats and dogs")]}
for chunk in graph.stream(
    inputs, {"configurable": {"user_id": "123"}}, stream_mode="values"
):
    chunk["messages"][-1].pretty_print()

print(f"User information after the run: {user_to_pets}")
User information prior to run: {}
================================ Human Message =================================

my favorite pets are cats and dogs
================================== Ai Message ==================================
Tool Calls:
  update_favorite_pets (call_zYlpngJKNHBmeNHgMo6h58VK)
 Call ID: call_zYlpngJKNHBmeNHgMo6h58VK
  Args:
    pets: ['cats', 'dogs']
================================= Tool Message =================================
Name: update_favorite_pets

null
================================== Ai Message ==================================

Your favorite pets have been updated to cats and dogs!
User information after the run: {'123': ['cats', 'dogs']}
from langchain_core.messages import HumanMessage

print(f"User information prior to run: {user_to_pets}")

inputs = {"messages": [HumanMessage(content="what are my favorite pets")]}
for chunk in graph.stream(
    inputs, {"configurable": {"user_id": "123"}}, stream_mode="values"
):
    chunk["messages"][-1].pretty_print()

print(f"User information prior to run: {user_to_pets}")
User information prior to run: {'123': ['cats', 'dogs']}
================================ Human Message =================================

what are my favorite pets
================================== Ai Message ==================================
Tool Calls:
  list_favorite_pets (call_gzCGJanTSYTaqyTT1IkmRmZP)
 Call ID: call_gzCGJanTSYTaqyTT1IkmRmZP
  Args:
================================= Tool Message =================================
Name: list_favorite_pets

cats, dogs
================================== Ai Message ==================================

Your favorite pets are cats and dogs.
User information prior to run: {'123': ['cats', 'dogs']}
print(f"User information prior to run: {user_to_pets}")

inputs = {
    "messages": [
        HumanMessage(content="please forget what i told you about my favorite animals")
    ]
}
for chunk in graph.stream(
    inputs, {"configurable": {"user_id": "123"}}, stream_mode="values"
):
    chunk["messages"][-1].pretty_print()

print(f"User information prior to run: {user_to_pets}")
User information prior to run: {'123': ['cats', 'dogs']}
================================ Human Message =================================

please forget what i told you about my favorite animals
================================== Ai Message ==================================
Tool Calls:
  delete_favorite_pets (call_qaYhQYgaEqQzmI0XuCDYYWyF)
 Call ID: call_qaYhQYgaEqQzmI0XuCDYYWyF
  Args:
================================= Tool Message =================================
Name: delete_favorite_pets

null
================================== Ai Message ==================================

I've forgotten your favorite animals. If you need anything else, just let me know!
User information prior to run: {}

LangGraph 참고 자료

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유