LLM(거대 언어 모델)이 단순히 채팅만 하는 것을 넘어, 계산기나 검색 엔진, 데이터베이스 조회 같은 실제 '도구(Tool)'를 사용할 수 있다면 어떨까요? LangChain의 툴 호출(Tool Calling) 기능은 바로 이 상상을 현실로 만들어 줍니다. 이 가이드에서는 AI가 특정 도구를 사용하도록 설정하고, 그 결과를 받아보는 방법을 단계별로 알아봅니다.
⚠️ 가장 중요한 핵심: AI는 도구를 '실행'하지 않습니다!
'툴 호출'이라는 이름 때문에 AI가 직접 함수를 실행한다고 오해하기 쉽지만, 사실은 그렇지 않습니다. AI는 어떤 도구를 어떤 값(arguments)으로 호출해야 하는지에 대한 '명령서(instruction)' 📝만 생성할 뿐입니다. 이 명령서를 받아 실제로 도구를 실행하는 것은 우리 파이썬 코드의 몫입니다. 이 기능은 단순히 도구를 쓰는 것을 넘어, AI로부터 원하는 형식의 구조화된 데이터를 안정적으로 추출하는 데에도 매우 유용하게 사용됩니다.
1단계: AI에게 알려줄 도구 정의하기
AI가 도구를 사용하려면, 먼저 어떤 도구들이 있는지 그 명세, 즉 **스키마(Schema)**를 알려주어야 합니다. 스키마는 "이 도구는 이런 일을 하고, 이런 인자들이 필요해"라고 설명하는 역할을 합니다. 스키마는 여러 방식으로 정의할 수 있습니다.
방법 1: Python 함수로 정의하기 (가장 직관적인 방법)
가장 간단하고 직관적인 방법은 일반 파이썬 함수를 만드는 것입니다. 함수 이름, 타입 힌트, 그리고 **설명(docstring)**은 모두 AI에게 전달되는 중요한 정보가 됩니다. 좋은 설명을 다는 것은 훌륭한 프롬프트 엔지니어링의 연장선입니다.
# 함수 이름, 타입 힌트, 설명(docstring) 모두가 AI에게 전달되는 스키마의 일부가 됩니다.
def add(a: int, b: int) -> int:
"""두 정수를 더합니다.
Args:
a: 첫 번째 정수
b: 두 번째 정수
"""
return a + b
def multiply(a: int, b: int) -> int:
"""두 정수를 곱합니다.
Args:
a: 첫 번째 정수
b: 두 번째 정수
"""
return a * b
방법 2: Pydantic 클래스로 정의하기
실행할 함수 로직 없이, 오직 스키마(데이터 구조)만 정의하고 싶을 때는 Pydantic 클래스를 사용할 수 있습니다.
from pydantic import BaseModel, Field
class add(BaseModel):
"""두 정수를 더합니다."""
a: int = Field(..., description="첫 번째 정수")
b: int = Field(..., description="두 번째 정수")
class multiply(BaseModel):
"""두 정수를 곱합니다."""
a: int = Field(..., description="첫 번째 정수")
b: int = Field(..., description="두 번째 정수")
TypedDict를 사용하는 방법도 있습니다.
2단계: 모델에 도구 연결(Bind)하고 호출하기
이제 정의한 도구들을 모델에 연결할 차례입니다. .bind_tools() 메소드를 사용하면 우리가 만든 함수나 Pydantic 클래스가 모델이 이해할 수 있는 올바른 포맷으로 변환되어 전달됩니다.
from langchain_google_genai import ChatGoogleGenerativeAI
# 1. 사용할 도구들을 리스트로 묶습니다.
tools = [add, multiply]
# 2. LLM을 준비합니다.
llm = ChatGoogleGenerativeAI(model="gemini-pro")
# 3. .bind_tools()를 사용해 모델에 도구를 연결합니다.
llm_with_tools = llm.bind_tools(tools)
# 4. 이제 모델을 호출하면, 모델이 상황에 맞는 도구를 선택하여 호출 명령을 내립니다.
query = "3 곱하기 12는 몇이야?"
ai_message = llm_with_tools.invoke(query)
print(ai_message)
출력 결과:
AIMessage(
...
tool_calls=[
{
'name': 'multiply', # 호출할 도구 이름
'args': {'a': 3, 'b': 12}, # 전달할 인자
'id': 'call_...'
}
]
)
보시다시피, AI 메시지(.AIMessage) 안에 tool_calls라는 속성이 생겼습니다. 이 속성에는 모델이 어떤 도구를(multiply), 어떤 인자(a=3, b=12)로 호출해야 하는지에 대한 정보가 담겨 있습니다.
3단계: 출력 결과 활용하기
여러 도구 동시 호출
AI는 똑똑하게도 한 번의 질문에 여러 도구가 필요하다고 판단되면 동시에 여러 개를 호출할 수 있습니다.
query = "3 곱하기 12는 몇이고, 11 더하기 49는 몇이야?"
tool_calls = llm_with_tools.invoke(query).tool_calls
print(tool_calls)
출력 결과:
[
{'name': 'multiply', 'args': {'a': 3, 'b': 12}, ...},
{'name': 'add', 'args': {'a': 11, 'b': 49}, ...}
]
출력 파싱하기
tool_calls에 담긴 딕셔너리를 직접 사용하는 것보다, 우리가 정의했던 Pydantic 클래스 객체로 변환하면 더 편리하겠죠? 이때 PydanticToolsParser를 사용합니다.
from langchain_core.output_parsers import PydanticToolsParser
# ... multiply, add Pydantic 클래스 정의 ...
# 체인 마지막에 파서를 연결합니다.
chain = llm_with_tools | PydanticToolsParser(tools=[add, multiply])
# 체인을 실행하면 바로 Pydantic 객체 리스트를 얻을 수 있습니다.
result = chain.invoke(query)
print(result)
출력 결과:
[multiply(a=3, b=12), add(a=11, b=49)]
이제 result[0].a 와 같은 방식으로 데이터에 깔끔하게 접근할 수 있습니다.
다음 단계
지금까지 AI가 도구를 '호출'하도록 명령서를 만드는 방법을 배웠습니다.
다음 단계는 이 명령서를 받아 실제로 add나 multiply 함수를 실행하고, 그 결과를 다시 AI에게 전달하여 최종 답변을 얻는 과정입니다. 이 과정을 통해 AI는 자신이 요청한 계산 결과를 바탕으로 사용자에게 자연스러운 문장으로 대답할 수 있게 됩니다.
'개발 이야기 > [스터디] LLM' 카테고리의 다른 글
| GPT-5-Codex 업그레이드 (1) | 2025.09.16 |
|---|---|
| How People Use ChatGPT (0) | 2025.09.16 |
| LangChain Key Features: Structured Data (4) | 2025.08.08 |
| 랭체인(LangChain) 설치: 패키지 완벽 가이드 (0) | 2025.08.08 |
| 🤖 LangChain으로 나만의 AI 만들기 1탄: 초간단 번역 챗봇 (10) | 2025.08.07 |