포스트

LangChain 에서 Tools 이란

Agent 를 생성할때 Tools 를 LangChain 을 통해 정의하는 방법


Tool

Langchain 에서 도구(Tool) 은 Python 함수와 해당 함수의 스키마(schema) 를 연결하는 추상화 방식이다. 또한, 에이전트, 체인 또는 LLM 이 외부 세계와 상호작용하기 위한 인터페이스라고 생각하면 된다. Tool 은 특정 기능을 수행하는 함수, 이름, 설명, 입력 변수 등을 정의한 구조로, 이를 지원하는 Chat Models 에서 Tool Calling 을 통해 특정 기능을 실행할 수 있도록 한다.

핵심 개념

  • Tools 은 함수와 해당 스키마를 래핑하여 대화모델에 전달할 수 있도록 하는 방식이다.
  • Tool 을 생성할 때는 @tool 데코레이터를 사용하여 쉽게 만들 수 있다.
    • 자동으로 name, description, args 등을 추론하며, 사용자 지정도 가능하다.
    • image, dataframe 등의 artifacts 반환을 지원한다.
    • injected toll arguments 를 활용하여 특정 인수를 모델이 접근하지 못하도록 숨길 수 있다.

Tool Interface

Tool 은 BaseTool 클래스를 기반으로 하며, 이는 LangChain 의 Runnable Interface 를 상속받는다.

Tool Schema 의 주요 attribute

  • name : 도구의 이름
  • description : 도구의 역할 설명
  • args : JSON schema 로 정의된 도구의 입력 인수

Tool 실행 방법

Tool 생성 방법 (@tool)

함수를 정의한뒤, @tool 데코레이터를 붙여주기만 하면 된다.

1
2
3
4
5
6
from langchain_core.tools import tool

@tool
def multiply(a: int, b:int) -> int:
	"""Multiply two numbers"""
	return a * b
  • LangChain 에서는 BaseTool 을 상속하거나 StructuredTool 을 사용하는 다른 방법도 있지만, 대부분의 경우 @tool 데코레이터를 사용하는 것이 가장 쉽고 효과적이다.

Tool 직접 호출

1
multiply.invoke({'a' : 2, 'b': 3}) # results : 6

Tool 속성 확인

1
2
3
4
5
6
7
8
print(multiply.name) # multiply
print(multiply.description) # Multiply two numbers
print(multiply.args)
# {
#   'type': 'object',
#   'properties': {'a': {'type': 'integer'}, 'b': {'type': 'integer'}}, 
#   'required': ['a', 'b']
# }

LangGraph 의 create_react_agent 와 같은 prebuilt agent 를 사용할 경우, 도구를 직접 호출하지 않아도 된다. 그러나 디버깅 및 테스트 에서는 유용할 수 있다.

도구 스키마 설정

@tool 데코레이터는 name, description 등을 수정할 수 있다. 자세한 내용은 @tool API 문서how to create custom tools 를 확인해보면 된다.

Tool artifacts

도구 실행의 결과로 생성된 데이터프레임, 이미지 등의 아티팩트를 직접 모델에 전달하지 않고도, 체인의 후속 구성 요소에서 활용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
import random

from typing import List, Tuple

from langchain_core.tools import tool

@tool(response_format='content_and_artifact')
def generate_random_ints(min: int, max: int, size: int) -> Tuple[str, List[int]]:
    """Generate size random ints in the range [min, max]"""

    array = [random.randint(min, max) for _ in range(size)]
    content = f"Successfully generated array of {size} random ints in [{min}, {max}]"
    return content, array

이 함수는 langchain-core >= 0.2.19 부터 사용 가능하다.

실행 결과

  • 그냥 invoke 만 할 경우 content 부분 밖에 볼 수 있다.
1
generate_random_ints.invoke({'min' : 0, 'max' : 9, 'size' : 10})
1
'Successfully generated array of 10 random ints in [0, 9]'
  • ToolCall (ToolMessage 를 생성하기 위해 반드시 필요한 id, type 을 입력) 을 통해 content 와 artifacts 를 확인할 수 있다.
1
2
3
4
5
6
7
8
generate_random_ints.invoke(
    {
        "name": "generate_random_ints",
        "args": {"min": 0, "max": 9, "size": 10},
        "id": "123",  # required
        "type": "tool_call",  # required
    }
)
1
ToolMessage(content='Successfully generated array of 10 random ints in [0, 9]', name='generate_random_ints', tool_call_id='123', artifact=[7, 4, 5, 4, 2, 5, 8, 7, 3, 6])
  • 모델에 사용하는 법과 자세한 사항은 여기 를 참조하면 된다.

특수 타입 어노테이션

도구의 함수 시그니처에서 특정한 타입 annotation 을 사용할 수 있으며, 이는 도구의 실행 동작을 구성하는 데 도움을 준다.

다음 타입의 annotation 을 사용하면 해당 인수가 도구의 스키마에서 제거된다. 이는 모델이 제어해서는 안 되는 인수를 숨기기 위해 유용하다.

  • InjectedToolArg : .invoke 또는 .ainvoke 를 사용하여 런타임시 수동으로 값을 주입해야 하는 인수
    • 일부 인수는 모델이 직접 선정할 필요 없이 실행 시 자동으로 주입되어야 할 수도 있다. 이를 위해 InjectedToolArg 어노테이션을 사용할 수 있다.
1
2
3
4
5
6
from langchain_core.tools import tool, InjectedToolArg

@tool
def user_specific_tool(input_data:str , user_id: InjectedToolArg) -> str:
	"""Tool that processes input data."""
	return f"User {user_id} processed {input_data}

InectedToolArg 사용법

  • RunnableConfig : RunnableConfig 객체를 도구에 전달
  • InjectedState : LangGraph 의 전체 상태를 도구에 전달
  • InjectedStore : LangGraph의 저장소 객체를 도구에 전달

Code

코드 주소

Reference

Google AdSense — Post Ad
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

Comments powered by Disqus.