많은 AI 애플리케이션은 자연어를 통해 사용자와 상호작용합니다. 그러나 일부 사용 사례에서는 모델이 API, 데이터베이스 또는 파일 시스템과 같은 외부 시스템과 구조화된 입력을 사용하여 직접 인터페이스해야 합니다.도구는 에이전트가 작업을 수행하기 위해 호출하는 구성 요소입니다. 도구는 잘 정의된 입력과 출력을 통해 모델이 외부 세계와 상호작용할 수 있도록 하여 모델의 기능을 확장합니다. 도구는 호출 가능한 함수와 해당 입력 스키마를 캡슐화합니다. 이러한 도구는 호환되는 챗 모델에 전달될 수 있으며, 모델이 도구를 호출할지 여부와 어떤 인수로 호출할지 결정할 수 있게 합니다. 이러한 시나리오에서 도구 호출은 모델이 지정된 입력 스키마에 부합하는 요청을 생성할 수 있도록 합니다.
서버 측 도구 사용일부 챗 모델(예: OpenAI, Anthropic, Gemini)은 웹 검색 및 코드 인터프리터와 같이 서버 측에서 실행되는 내장 도구를 제공합니다. 특정 챗 모델에서 이러한 도구에 액세스하는 방법을 알아보려면 프로바이더 개요를 참조하세요.
도구를 생성하는 가장 간단한 방법은 @tool 데코레이터를 사용하는 것입니다. 기본적으로 함수의 docstring이 모델이 도구를 언제 사용해야 하는지 이해하는 데 도움이 되는 도구 설명이 됩니다:
Copy
from langchain.tools import tool@tooldef search_database(query: str, limit: int = 10) -> str: """쿼리와 일치하는 레코드를 고객 데이터베이스에서 검색합니다. Args: query: 검색할 검색어 limit: 반환할 최대 결과 수 """ return f"Found {limit} results for '{query}'"
타입 힌트는 도구의 입력 스키마를 정의하므로 필수입니다. docstring은 모델이 도구의 목적을 이해하는 데 도움이 되도록 유익하고 간결해야 합니다.
@tool("calculator", description="Performs arithmetic calculations. Use this for any math problems.")def calc(expression: str) -> str: """수학 표현식을 평가합니다.""" return str(eval(expression))
상태 액세스:도구는 ToolRuntime을 사용하여 현재 그래프 상태에 액세스할 수 있습니다:
Copy
from langchain.tools import tool, ToolRuntime# 현재 대화 상태 액세스@tooldef summarize_conversation( runtime: ToolRuntime) -> str: """지금까지의 대화를 요약합니다.""" messages = runtime.state["messages"] human_msgs = sum(1 for m in messages if m.__class__.__name__ == "HumanMessage") ai_msgs = sum(1 for m in messages if m.__class__.__name__ == "AIMessage") tool_msgs = sum(1 for m in messages if m.__class__.__name__ == "ToolMessage") return f"Conversation has {human_msgs} user messages, {ai_msgs} AI responses, and {tool_msgs} tool results"# 사용자 정의 상태 필드 액세스@tooldef get_user_preference( pref_name: str, runtime: ToolRuntime # ToolRuntime 매개변수는 모델에 보이지 않습니다) -> str: """사용자 기본 설정 값을 가져옵니다.""" preferences = runtime.state.get("user_preferences", {}) return preferences.get(pref_name, "Not set")
tool_runtime 매개변수는 모델에서 숨겨집니다. 위 예제의 경우 모델은 도구 스키마에서 pref_name만 볼 수 있으며, tool_runtime은 요청에 포함되지 않습니다.
상태 업데이트:Command를 사용하여 에이전트의 상태를 업데이트하거나 그래프의 실행 흐름을 제어할 수 있습니다:
Copy
from langgraph.types import Commandfrom langchain.messages import RemoveMessagefrom langgraph.graph.message import REMOVE_ALL_MESSAGESfrom langchain.tools import tool, ToolRuntime# 모든 메시지를 제거하여 대화 기록 업데이트@tooldef clear_conversation() -> Command: """대화 기록을 지웁니다.""" return Command( update={ "messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES)], } )# 에이전트 상태에서 user_name 업데이트@tooldef update_user_name( new_name: str, runtime: ToolRuntime) -> Command: """사용자 이름을 업데이트합니다.""" return Command(update={"user_name": new_name})
store를 사용하여 대화 전반에 걸쳐 영구 데이터에 액세스할 수 있습니다. store는 runtime.store를 통해 액세스되며 사용자별 또는 애플리케이션별 데이터를 저장하고 검색할 수 있습니다.도구는 ToolRuntime을 통해 store에 액세스하고 업데이트할 수 있습니다:
Copy
from typing import Anyfrom langgraph.store.memory import InMemoryStorefrom langchain.agents import create_agentfrom langchain.tools import tool, ToolRuntime# 메모리 액세스@tooldef get_user_info(user_id: str, runtime: ToolRuntime) -> str: """사용자 정보를 조회합니다.""" store = runtime.store user_info = store.get(("users",), user_id) return str(user_info.value) if user_info else "Unknown user"# 메모리 업데이트@tooldef save_user_info(user_id: str, user_info: dict[str, Any], runtime: ToolRuntime) -> str: """사용자 정보를 저장합니다.""" store = runtime.store store.put(("users",), user_id, user_info) return "Successfully saved user info."store = InMemoryStore()agent = create_agent( model, tools=[get_user_info, save_user_info], store=store)# 첫 번째 세션: 사용자 정보 저장agent.invoke({ "messages": [{"role": "user", "content": "Save the following user: userid: abc123, name: Foo, age: 25, email: [email protected]"}]})# 두 번째 세션: 사용자 정보 가져오기agent.invoke({ "messages": [{"role": "user", "content": "Get user info for user with id 'abc123'"}]})# Here is the user info for user with ID "abc123":# - Name: Foo# - Age: 25# - Email: [email protected]
runtime.stream_writer를 사용하여 도구가 실행되는 동안 사용자 정의 업데이트를 스트리밍할 수 있습니다. 이는 도구가 수행하는 작업에 대한 실시간 피드백을 사용자에게 제공하는 데 유용합니다.
Copy
from langchain.tools import tool, ToolRuntime@tooldef get_weather(city: str, runtime: ToolRuntime) -> str: """주어진 도시의 날씨를 가져옵니다.""" writer = runtime.stream_writer # 도구가 실행되는 동안 사용자 정의 업데이트 스트리밍 writer(f"Looking up data for city: {city}") writer(f"Acquired data for city: {city}") return f"It's always sunny in {city}!"
도구 내에서 runtime.stream_writer를 사용하는 경우 도구는 LangGraph 실행 컨텍스트 내에서 호출되어야 합니다. 자세한 내용은 스트리밍을 참조하세요.