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 실행 방법
invoke: 지정된 인수와 함께 도구를 실행한다.ainvoke: 비동기적으로 도구를 실행한다. async programming with langchain
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}
RunnableConfig:RunnableConfig객체를 도구에 전달InjectedState: LangGraph 의 전체 상태를 도구에 전달InjectedStore: LangGraph의 저장소 객체를 도구에 전달
Comments powered by Disqus.