LiteLLM에서 함수 호출(Function Calling) 사용하기

LiteLLM에서 함수 호출(Function Calling) 사용하기

모델에게 '그냥 대답'만 시키는 게 아니라, 외부 도구나 함수를 불러서 실제 일을 시키고 싶을 때가 있어요. 예를 들어 날씨 API를 호출한다거나 DB를 조회하는 작업 말이죠. 이때 모델이 함수를 '호출하겠다'고 결정하는 것, 그리고 그 결과를 다시 모델에 돌려주는 전체 흐름을 LiteLLM에서는 어떻게 다루는지 살펴볼게요. Tools를 쓰는 '도구 호출(Tool Calling)'의 핵심이 바로 이 함수 호출 패턴이에요.

출처: 공식문서

모델이 함수 호출을 지원하는지 확인하기

함수 호출 기능은 모든 모델이 지원하는 게 아니에요. 먼저 litellm.supports_function_calling(model="")로 해당 모델이 함수 호출을 지원하는지 확인할 수 있어요. True면 지원, False면 지원하지 않는 거예요.

assert litellm.supports_function_calling(model="gpt-5.6-luna") == True
assert litellm.supports_function_calling(model="azure/gpt-5.6-terra") == True
assert litellm.supports_function_calling(model="palm/chat-bison") == False
assert litellm.supports_function_calling(model="xai/grok-2-latest") == True
assert litellm.supports_function_calling(model="ollama/llama2") == False

병렬 함수 호출 지원 확인하기

'한 번에 여러 함수를 함께 호출하는 능력'도 모델별로 달라요. litellm.supports_parallel_function_calling(model="")로 확인할 수 있어요. 병렬 함수 호출은 여러 함수 호출을 한 번에 수행하고, 그 결과들을 병렬로 해결할 수 있게 하는 모델의 능력이에요.

assert litellm.supports_parallel_function_calling(model="gpt-5.6-terra") == True
assert litellm.supports_parallel_function_calling(model="gpt-4") == False

병렬 함수 호출 — 전체 흐름

gpt-3.5-turbo-1106를 예로 들어 병렬 함수 호출이 어떻게 돌아가는지 볼게요. 아래 코드는 get_current_weather 함수 하나를 정의하고, 모델이 필요할 때 이 함수를 호출하도록 하는 3단계 흐름이에요.

Step 1: 사용자 질문과 함께 사용 가능한 함수를 모델에 보낸다. Step 2: 모델 응답을 파싱해서, 모델이 알려준 인자로 get_current_weather를 실행한다. Step 3: 함수 실행 결과를 다시 모델에 보내, 모델이 최종 답을 내린다.

전체 코드 — gpt-3.5-turbo-1106로 병렬 함수 호출하기

import litellm
import json
# set openai api key
import os
os.environ['OPENAI_API_KEY'] = "" # litellm reads OPENAI_API_KEY from .env and sends the request

# Example dummy function hard coded to return the same weather
# In production, this could be your backend API or an external API
def get_current_weather(location, unit="fahrenheit"):
    """Get the current weather in a given location"""
    if "tokyo" in location.lower():
        return json.dumps({"location": "Tokyo", "temperature": "10", "unit": "celsius"})
    elif "san francisco" in location.lower():
        return json.dumps({"location": "San Francisco", "temperature": "72", "unit": "fahrenheit"})
    elif "paris" in location.lower():
        return json.dumps({"location": "Paris", "temperature": "22", "unit": "celsius"})
    else:
        return json.dumps({"location": location, "temperature": "unknown"})


def test_parallel_function_call():
    try:
        # Step 1: send the conversation and available functions to the model
        messages = [{"role": "user", "content": "What's the weather like in San Francisco, Tokyo, and Paris?"}]
        tools = [
            {
                "type": "function",
                "function": {
                    "name": "get_current_weather",
                    "description": "Get the current weather in a given location",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "location": {
                                "type": "string",
                                "description": "The city and state, e.g. San Francisco, CA",
                            },
                            "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                        },
                        "required": ["location"],
                    },
                },
            }
        ]
        response = litellm.completion(
            model="gpt-5.6-luna",
            messages=messages,
            tools=tools,
            tool_choice="auto",  # auto is default, but we'll be explicit
        )
        print("\nFirst LLM Response:\n", response)
        response_message = response.choices[0].message
        tool_calls = response_message.tool_calls

        print("\nLength of tool calls", len(tool_calls))

        # Step 2: check if the model wanted to call a function
        if tool_calls:
            # Step 3: call the function
            # Note: the JSON response may not always be valid; be sure to handle errors
            available_functions = {
                "get_current_weather": get_current_weather,
            }  # only one function in this example, but you can have multiple
            messages.append(response_message)  # extend conversation with assistant's reply

            # Step 4: send the info for each function call and function response to the model
            for tool_call in tool_calls:
                function_name = tool_call.function.name
                function_to_call = available_functions[function_name]
                function_args = json.loads(tool_call.function.arguments)
                function_response = function_to_call(
                    location=function_args.get("location"),
                    unit=function_args.get("unit"),
                )
                messages.append(
                    {
                        "tool_call_id": tool_call.id,
                        "role": "tool",
                        "name": function_name,
                        "content": function_response,
                    }
                )  # extend conversation with function response
            second_response = litellm.completion(
                model="gpt-5.6-luna",
                messages=messages,
            )  # get a new response from the model where it can see the function response
            print("\nSecond LLM response:\n", second_response)
            return second_response
    except Exception as e:
      print(f"Error occurred: {e}")

test_parallel_function_call()

흐름 뜯어보기

1단계 — litellm.completion()tools 넘기기

tools 리스트에 함수 스키마(이름·설명·파라미터)를 정의하고, tool_choice="auto"로 넘겨요. auto가 기본값이지만 명시적으로 적어두면 의도가 드러나요. 모델은 응답의 response_message.tool_calls에 호출할 함수와 인자를 담아 돌려줘요.

2단계 — 함수 실행

tool_calls가 비어 있지 않으면, 각 함수 호출의 이름(tool_call.function.name)과 인자(json.loads(tool_call.function.arguments))를 꺼내 실제 함수를 실행해요. 이때 JSON 응답이 항상 유효한 건 아니니 에러 처리를 반드시 고려해야 해요.

3단계 — 결과를 대화에 추가하고 두 번째 요청

함수 실행 결과는 role: "tool" 메시지로 대화에 추가하고, tool_call_id로 어떤 호출의 결과인지 연결해요. 그리고 그 대화를 다시 litellm.completion()에 넘기면, 모델은 함수 결과를 보고 최종 답을 내려요.

더 알아보기

  • get_supported_openai_params()로 도구 관련 파라미터(tools, tool_choice)가 어떤 공급자에서 지원되는지 확인할 수 있어요.
  • 도구 호출의 스키마 정의와 제어에 대해 더 알고 싶다면 관련 도구 스키마 문서를 참고해요.