함수 호출
함수 호출 (Function Calling)
함수 호출(Function Calling)은 언어 모델이 사용자 입력에 따라 구조화된 함수 호출을 생성해서 외부 도구·API와 상호작용하게 해 주는 기능이에요. 이 능력으로 실시간 데이터 조회, 계산, 외부 서비스 연동 같은 작업을 수행하는 AI 에이전트를 만들 수 있어요.
도구 사용에 맞게 파인튜닝된 모델에 함수 설명을 제공하면, 모델이 사용자 요청에 따라 언제 함수를 호출할지 결정하고, 실행하고, 그 결과를 자연어 응답에 녹여낼 수 있어요. 예를 들어 실시간 날씨를 가져와 정확한 응답을 주는 어시스턴트를 만들 수 있죠.
💡 이 가이드는 Hugging Face 계정과 액세스 토큰이 있다고 가정해요. huggingface.co에서 무료 계정을 만들고, 설정 페이지에서 토큰을 얻을 수 있어요.
함수 정의하기
첫 단계는 모델이 호출할 함수를 구현하는 거예요. 주어진 위치의 현재 날씨를 반환하는 간단한 날씨 함수 예시를 쓸 거예요.
언제나처럼, inference 클라이언트를 초기화하는 것부터 시작해요.
OpenAI 클라이언트에서는 base_url 파라미터로 요청에 사용할 제공자를 지정해요.
import json
import os
from openai import OpenAI
# Initialize client
client = OpenAI(
base_url="https://router.huggingface.co/v1",
api_key=os.environ["HF_TOKEN"],
)
Hugging Face Hub 클라이언트에서는 provider 파라미터로 요청에 사용할 제공자를 지정해요. 기본값은 "auto"예요.
import json
import os
from huggingface_hub import InferenceClient
# Initialize client
client = InferenceClient(token=os.environ["HF_TOKEN"], provider="novita")
함수는 간단한 작업을 수행하는 파이썬 함수로 정의할 수 있어요. 이 경우 함수는 위치·온도·날씨 상태를 담은 사전으로 현재 날씨를 반환할 거예요.
# Define the function
def get_current_weather(location: str) -> dict:
"""Get weather information for a location."""
# In production, this would call a real weather API
weather_data = {
"San Francisco": {"temperature": "22°C", "condition": "Sunny"},
"New York": {"temperature": "18°C", "condition": "Cloudy"},
"London": {"temperature": "15°C", "condition": "Rainy"},
}
return weather_data.get(location, {
"location": location,
"error": "Weather data not available"
})
이제 언어 모델에게 날씨 함수를 설명해 주는 함수 스키마를 정의해야 해요. 이 스키마는 모델에게 함수가 어떤 파라미터를 기대하고 무엇을 하는지 알려줍니다:
# Define the function schema
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name"
},
},
"required": ["location"],
},
},
},
]
스키마는 함수가 무엇을 하는지, 파라미터는 무엇인지, 어떤 파라미터가 필수인지를 설명하는 JSON Schema 형식이에요. description은 모델이 언제·어떻게 함수를 호출해야 하는지 이해하는 데 도움을 줍니다.
채팅에서 함수 다루기
함수는 일반적인 채팅 완성 대화 안에서 동작해요. 모델이 사용자 입력에 따라 언제 호출할지 결정합니다.
user_message = "What's the weather like in San Francisco?"
messages = [
{
"role": "system",
"content": "You are a helpful assistant with access to weather data."
},
{"role": "user", "content": user_message}
]
# Initial API call with tools
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-R1-0528",
messages=messages,
tools=tools,
tool_choice="auto" # Let the model decide when to call functions
)
response_message = response.choices[0].message
💡
tool_choice파라미터는 모델이 함수를 언제 호출할지 제어하는 데 써요. 여기선auto를 쓰면 모델이 함수 호출 여부(0회 이상)를 스스로 결정해요. 아래에서tool_choice와 다른 파라미터에 대해 더 자세히 다룰게요.
다음으로, 모델 응답에서 함수를 호출할지 결정했는지 확인해야 해요. 호출했다면 함수를 실행하고 결과를 대화에 추가한 뒤, 최종 응답을 사용자에게 보내야 합니다.
# Check if model wants to call functions
if response_message.tool_calls:
# Add assistant's response to messages
messages.append(response_message)
# Process each tool call
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
# Execute the function
if function_name == "get_current_weather":
result = get_current_weather(function_args["location"])
# Add function result to messages
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": json.dumps(result),
})
# Get final response with function results
final_response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-R1-0528",
messages=messages,
)
return final_response.choices[0].message.content
else:
return response_message.content
워크플로는 간단해요: 도구와 함께 초기 API 호출 → 모델이 함수를 호출할지 확인 → 필요하면 실행 → 결과를 대화에 추가 → 사용자에게 최종 응답.
⚠️ 우리는 모델이 실제로 존재하는 함수를 호출하려 하는 경우를 처리했어요. 하지만 모델이 존재하지 않는 함수를 호출하려 할 수도 있는데, 그 경우도 대비해야 합니다. 이건 아래에서 다룰
strict모드로도 처리할 수 있어요.
여러 함수
더 복잡한 어시스턴트를 위해 여러 함수를 정의할 수 있어요:
# Define multiple functions
def get_current_weather(location: str) -> dict:
"""Get current weather for a location."""
return {"location": location, "temperature": "22°C", "condition": "Sunny"}
def get_weather_forecast(location: str, date: str) -> dict:
"""Get weather forecast for a location."""
return {
"location": location,
"date": date,
"forecast": "Sunny with chance of rain",
"temperature": "20°C"
}
# Function registry
AVAILABLE_FUNCTIONS = {
"get_current_weather": get_current_weather,
"get_weather_forecast": get_weather_forecast,
}
# Multiple tool schemas
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"}
},
"required": ["location"],
},
},
},
{
"type": "function",
"function": {
"name": "get_weather_forecast",
"description": "Get weather forecast for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
"date": {"type": "string", "description": "Date in YYYY-MM-DD format"},
},
"required": ["location", "date"],
},
},
},
]
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-R1-0528",
messages=messages,
tools=tools,
tool_choice="auto"
)
여러 함수를 정의해 tools 목록에 추가했어요. 모델이 사용자 입력에 따라 이 함수들을 언제 호출할지 결정합니다. tool_choice 파라미터로 모델에게 특정 함수를 호출하도록 강제할 수도 있어요.
함수 실행은 단일 함수 예시와 비슷하게 처리하는데, 이번엔 elif 문으로 각 함수를 구분해요.
# execute the response
response_message = response.choices[0].message
# check if the model wants to call functions
if response_message.tool_calls:
# process the tool calls
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
# execute the function
if function_name == "get_current_weather":
result = get_current_weather(function_args["location"])
elif function_name == "get_weather_forecast":
result = get_weather_forecast(function_args["location"], function_args["date"])
# add the result to the conversation
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": json.dumps(result),
})
# get the final response with function results
final_response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-R1-0528",
messages=messages,
)
return final_response.choices[0].message.content
else:
return response_message.content
🎉 여러 함수를 호출해서 날씨 데이터를 얻는 동작하는 어시스턴트를 만들었어요!
추가 설정
Inference Providers에서 함수 호출을 최대한 활용하기 위한 추가 설정 옵션을 살펴볼게요.
제공자 선택
성능과 비용을 더 제어하려면 사용할 inference 제공자를 지정할 수 있어요. 함수 호출에서는 모델 응답의 변동성을 줄여주므로 특히 효과적이에요.
OpenAI 클라이언트에서는 model 파라미터에 제공자 ID를 붙여서 지정할 수 있어요:
# The OpenAI client automatically routes through Inference Providers
# You can specify provider preferences in your HF settings
client = OpenAI(
base_url="https://router.huggingface.co/v1",
api_key=os.environ["HF_TOKEN"],
)
client.chat.completions.create(
- model="deepseek-ai/DeepSeek-R1-0528", # automatically selects the fastest available provider
+ model="deepseek-ai/DeepSeek-R1-0528:novita", # manually select Novita
...
)
Hugging Face Hub 클라이언트에서는 provider 파라미터로 지정할 수 있어요.
# Specify a provider directly
client = InferenceClient(
token=os.environ["HF_TOKEN"]
+ provider="auto" # automatically select provider based on hf.co/settings/inference-providers
- provider="together" # manually select Together AI
- provider="novita" # manually select Novita
)
제공자를 바꾸면 모델 응답이 달라지는 걸 볼 수 있어요. 각 제공자가 모델을 다르게 구성하기 때문이에요.
⚠️ 각 inference 제공자는 기능과 성능 특성이 달라요. 각 제공자에 대한 자세한 정보는 Inference Providers 섹션에서 찾을 수 있어요.
Tool Choice 옵션
tool_choice 파라미터로 언제·어떤 함수를 호출할지 제어할 수 있어요.
tool_choice 파라미터는 모델이 함수를 호출하는 시점을 제어해요. 대부분의 경우 auto를 쓰는데, 모델이 함수 호출 여부(0회 이상)를 스스로 결정하게 하는 거예요.
# Let the model decide (default)
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-R1-0528",
messages=messages,
tools=tools,
tool_choice="auto" # Model decides when to call functions
)
하지만 어떤 경우엔 모델이 자기 지식만으로 답하지 않고 항상 함수 호출 결과에 기반해서만 답하도록 강제하고 싶을 수 있어요.
# Force the model to call at least one function
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-R1-0528",
messages=messages,
tools=tools,
tool_choice="required" # Must call at least one function
)
함수가 간단하면 이렇게 처리해도 좋지만, 함수가 복잡하다면 tool_choice 파라미터로 모델이 특정 함수를 최소한 한 번 호출하도록 강제하고 싶을 거예요.
예를 들어 어시스턴트의 유일한 임무가 주어진 위치의 날씨를 알려주는 것이라면, get_current_weather 함수만 호출하고 다른 함수는 호출하지 않도록 강제하고 싶을 거예요.
# Force a specific function call
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-R1-0528",
messages=messages,
tools=tools,
tool_choice={
"type": "function",
"function": {"name": "get_current_weather"}
}
)
여기서는 모델이 get_current_weather 함수를 호출하고 다른 함수는 부르지 않도록 강제하고 있어요.
⚠️ 현재
huggingface_hub.InferenceClient는 호출할 함수를 지정하는tool_choice파라미터를 지원하지 않아요.
Strict 모드
함수 호출이 스키마와 정확히 일치하도록 하려면 strict 모드를 사용하세요. 모델이 예상치 못한 인자로 함수를 호출하거나, 존재하지 않는 함수를 호출하는 것을 막는 데 유용해요.
# Define tools with strict mode
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
},
"required": ["location"],
+ "additionalProperties": False, # Strict mode requirement
},
+ "strict": True, # Enable strict mode
},
},
]
Strict 모드는 함수 인자가 스키마와 정확히 일치하도록 보장해요: 추가 속성은 허용되지 않고, 모든 필수 파라미터는 제공되며, 데이터 타입은 엄격히 강제됩니다.
⚠️ strict 모드는 모든 제공자가 지원하는 건 아니에요. 제공자 문서에서 지원 여부를 확인하세요.
스트리밍 응답
실시간 응답을 위해 함수 호출과 함께 스트리밍을 활성화할 수 있어요. 모델의 진행 상황을 사용자에게 보여주거나, 오래 걸리는 함수 호출을 더 효율적으로 처리할 때 유용해요.
# Enable streaming with function calls
stream = client.chat.completions.create(
model="deepseek-ai/DeepSeek-R1-0528",
messages=messages,
tools=tools,
tool_choice="auto",
stream=True # Enable streaming
)
# Process the stream
for chunk in stream:
if chunk.choices[0].delta.tool_calls:
# Handle tool call chunks
tool_calls = chunk.choices[0].delta.tool_calls
if chunk.choices[0].delta.content:
# Handle content chunks
content = chunk.choices[0].delta.content
스트리밍은 응답이 도착하는 대로 처리하고, 사용자에게 실시간 진행 상황을 보여주며, 오래 걸리는 함수 호출을 더 효율적으로 다룰 수 있게 해 줍니다.
⚠️ 스트리밍도 모든 제공자가 지원하는 건 아니에요. 제공자 문서에서 지원 여부를 확인하거나 동적 모델 호환성 표를 참고하세요.
다음 단계
Inference Providers에서 함수 호출을 쓰는 법을 봤으니, 이제 나만의 에이전트·어시스턴트를 만들어 볼 수 있어요! 이런 아이디어를 시도해 보세요:
- 더 빠른 응답·낮은 비용을 위해 더 작은 모델 시도
- 실시간 데이터를 가져오는 에이전트 만들기
- 추론 모델로 외부 도구와 함께 추론할 수 있는 에이전트 구축
더 알아보기 (Learn more)
출처: 공식문서