LangChain에서 커스텀 툴 정의하기: 완벽 가이드
LangChain에서 에이전트의 기능을 확장하기 위해 커스텀 툴(Tool)을 만드는 방법에 대해 알아보겠습니다. 이 글에서는 툴의 정의부터 효과적인 설명 작성 방법까지 실제 사례와 함께 상세히 다루겠습니다.
1. LangChain에서 툴(Tool)이란?
LangChain에서 툴은 언어 모델(LLM)과 에이전트가 외부 세계와 상호작용할 수 있게 해주는 함수나 클래스입니다. 특정 입력을 받아 처리하고 결과를 반환하는 형태로 작동합니다. 예를 들어, 검색 툴은 사용자의 쿼리를 받아 검색 결과를 반환합니다.
툴의 주요 구성 요소
속성 타입 설명
name | str | 필수 항목으로, 고유한 이름이어야 합니다. |
description | str | 툴의 기능을 설명합니다. 에이전트가 툴 사용을 결정하는 데 중요합니다. |
args_schema | Pydantic BaseModel | 선택 사항이지만 권장됩니다. 매개변수 검증과 추가 정보를 제공합니다. |
return_direct | boolean | True일 경우, 툴 호출 후 에이전트가 결과를 사용자에게 직접 반환합니다. (기본값: False) |
2. 커스텀 툴 정의 방법 (3가지)
LangChain에서는 다음 세 가지 방법으로 커스텀 툴을 정의할 수 있습니다:
1) @tool 데코레이터 사용
가장 간단한 방법으로, 함수에 데코레이터를 추가하여 툴로 변환합니다.
from langchain.pydantic_v1 import BaseModel, Field
class CalculatorInput(BaseModel):
a: int = Field(description="first number")
b: int = Field(description="second number")
@tool("multiplication-tool", args_schema=CalculatorInput, return_direct=True)
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
# 툴의 속성 확인
print(multiply.name) # multiplication-tool
print(multiply.description) # multiplication-tool(a: int, b: int) -> int - Multiply two numbers.
print(multiply.args) # {'a': {'title': 'A', 'description': 'first number', 'type': 'integer'}, ...}
print(multiply.return_direct) # True
2) StructuredTool.from_function 사용
데코레이터보다 더 많은 제어 옵션을 제공하면서도 간단하게 사용할 수 있습니다.
from langchain_core.tools import StructuredTool
calculator = StructuredTool.from_function(
func=multiply,
name="Calculator",
description="multiply numbers",
args_schema=CalculatorInput,
return_direct=True,
# coroutine= ... # 비동기 메서드도 지정 가능
)
print(calculator.invoke({"a": 2, "b": 3})) # 6
print(calculator.name) # Calculator
print(calculator.description) # Calculator(a: int, b: int) -> int - multiply numbers
3) BaseTool 상속
가장 유연한 방법으로, 최대한의 제어가 필요할 때 사용합니다.
from typing import Optional, Type
from langchain_core.callbacks import CallbackManagerForToolRun, AsyncCallbackManagerForToolRun
from langchain_core.tools import BaseTool
class CustomCalculatorTool(BaseTool):
name = "Calculator"
description = "useful for when you need to answer questions about math"
args_schema: Type[BaseModel] = CalculatorInput
return_direct: bool = True
def _run(
self, a: int, b: int, run_manager: Optional[CallbackManagerForToolRun] = None
) -> str:
"""Use the tool."""
return a * b
async def _arun(
self,
a: int,
b: int,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
# 동기 구현으로 위임 (또는 비동기 구현 작성)
return self._run(a, b, run_manager=run_manager.get_sync())
multiply = CustomCalculatorTool()
print(multiply.invoke({"a": 2, "b": 3})) # 6
3. 효과적인 툴 설명(description) 작성하기
툴 설명은 에이전트가 언제 어떤 툴을 사용할지 결정하는 데 매우 중요합니다. 잘 작성된 설명은 에이전트의 성능을 크게 향상시킬 수 있습니다.
툴 설명의 주요 구성 요소
- 도구 기능 설명: 툴이 무엇을 하는지 간략히 설명합니다.
- 예: "A wrapper around Bing Search."
- 사용 용도 설명: 언제 이 툴이 유용한지 설명합니다.
- 예: "Useful for when you need to answer questions about current events."
- 입력 요구사항: 툴 사용에 필요한 입력값을 명시합니다.
- 예: "Input should be a search query."
툴 설명 작성 팁
- 명시적이어야 합니다: 무엇을 하는지, 언제 사용해야 하는지, 언제 사용하지 말아야 하는지 명확히 합니다.
- 사용하지 말아야 할 경우도 포함: "when not to use it"을 추가하면 툴 남용을 방지할 수 있습니다.
- temperature=0 설정: 모델이 설명을 엄격하게 따르도록 랜덤성을 줄일 수 있습니다.
실제 예시
Wikipedia 툴 예시:
class WikipediaQueryRun(BaseTool):
name: str = "wikipedia"
description: str = (
"A wrapper around Wikipedia. "
"Useful for when you need to answer general questions about "
"people, places, companies, facts, historical events, or other subjects. "
"Input should be a search query."
)
Golden Query 툴 예시:
class GoldenQueryRun(BaseTool):
name: str = "golden_query"
description: str = (
"A wrapper around Golden Query API."
" Useful for getting entities that match"
" a natural language query from Golden's Knowledge Base."
"\nExample queries:"
"\n- companies in nanotech"
"\n- list of cloud providers starting in 2019"
"\nInput should be the natural language query."
"\nOutput is a paginated list of results or an error object"
" in JSON format."
)
4. 툴 우선순위 지정하기
여러 유사한 툴이 있을 때, 특정 상황에서 하나를 우선 사용하도록 지정할 수 있습니다.
우선순위 지정 방법
설명에 다음과 같은 문구를 포함합니다:
- "Use this tool more than regular search if you are asked factual information about a person, place, or thing"
- "Use this tool more than the Wikipedia tool if you are asked about current events, recent information, or news"
예시
tools = [
Tool(
name="Search",
func=search.run,
description="Ask the targeted prompts to get answers about recent affairs",
),
Tool(
name="Music Search",
func=lambda x: "Mariah Carey's song called All I Want For Christmas",
description="helpful in searching music and should be used more than the other tools for queries related to Music, like 'tell me the most viewed song in 2022' or 'about the singer of a song'",
),
]
agent.run("what is the most famous song of Christmas")
# 결과: All I Want For Christmas Is You
이 예시에서는 음악 관련 쿼리에 "Music Search" 툴이 일반 "Search" 툴보다 우선 사용되도록 설명에 명시했습니다.
결론
LangChain에서 커스텀 툴을 잘 정의하는 것은 에이전트의 기능을 확장하고 성능을 향상시키는 핵심입니다. 툴의 이름과 설명을 명확하게 작성하고, 용도와 입력 요구사항을 구체적으로 명시하면 에이전트가 더 정확하게 툴을 선택하고 활용할 수 있습니다.
https://python.langchain.com/v0.1/docs/modules/tools/custom_tools/
How to create tools | 🦜️🔗 LangChain
When constructing an agent, you will need to provide it with a list of Tools that it can use. Besides the actual function that is called, the Tool consists of several components:
python.langchain.com
https://python.langchain.com/v0.2/docs/how_to/custom_tools/
How to create tools | 🦜️🔗 LangChain
When constructing an agent, you will need to provide it with a list of Tools that it can use. Besides the actual function that is called, the Tool consists of several components:
python.langchain.com
'LLM' 카테고리의 다른 글
[LLM] 멀티 에이전트 시스템: 복잡한 문제 해결을 위한 AI 협업 프레임워크 (4) | 2025.03.04 |
---|---|
[논문리뷰] MatPlotAgent: Method and Evaluation for LLM-Based Agentic Scientific Data Visualization (0) | 2025.03.04 |
[LLM] 효과적인 프롬프트 엔지니어링 기법: 기본 구성요소부터 고급 전략까지 (1) | 2025.03.04 |
댓글