5장. Function Calling 원리
도구 선언 — 모델이 읽는 안내문
한 줄 요약
도구 선언(function declaration) 은 모델에게 주는 도구의 안내문입니다. 이름, 설명, 인자의 형식 세 가지를 적습니다. 모델은 함수의 코드를 보지 못하고 이 안내문만 보고 판단하므로, 설명은 주석이 아니라 프롬프트입니다.
1. 선언과 구현은 다른 것이다
도구 하나는 두 부분으로 이루어집니다.
| 조각 | 무엇인가 | 누가 읽나 |
|---|---|---|
| 선언 | 이름, 설명, 인자의 형식을 적은 안내문 | 모델 |
| 구현 | 실제로 실행되는 파이썬 함수 | 파이썬(우리 컴퓨터) |
모델에게 가는 것은 선언뿐입니다. 함수 안에서 무슨 일이 일어나는지 모델은 모릅니다. 그래서 이번 장처럼 구현이 가짜여도 왕복은 똑같이 돌아갑니다.
2. 선언의 모양
이번 장에서 쓰는 선언입니다.
get_order_status_decl = types.FunctionDeclaration(
name="get_order_status",
description="하루마켓 주문번호로 주문의 현재 상태(결제/배송준비/배송중/배송완료 등)와 "
"택배사·송장번호를 조회한다.",
parameters_json_schema={
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "하루마켓 주문번호. 'HR'로 시작하는 문자열",
}
},
"required": ["order_id"],
},
)
tool = types.Tool(function_declarations=[get_order_status_decl])
| 항목 | 적는 것 | 모델이 이것으로 하는 일 |
|---|---|---|
name |
도구의 이름 | 응답에서 이 이름으로 요청합니다 |
description |
무엇을 하는 도구인가 | 이 도구를 쓸지 말지 판단합니다 |
parameters_json_schema |
인자의 이름, 타입, 설명, 필수 여부 | 인자에 무엇을 넣을지 정합니다 |
parameters_json_schema에 적는 문법은 4장에서 본 JSON 스키마입니다. properties에 칸을 적고, required에 꼭 있어야 하는 칸을 적습니다. 구조화 출력과 도구 선언은 같은 언어를 씁니다.
마지막 줄의 types.Tool(...)은 선언들을 묶는 꾸러미입니다. 지금은 선언이 하나지만, 도구가 늘면 function_declarations=[...] 안에 나란히 넣습니다.
3. 설명이 판단의 전부다
모델이 도구를 고를 때 볼 수 있는 것은 이름과 설명뿐입니다.
# 모델이 언제 써야 할지 알 수 없는 선언
name="check", description="주문 확인"
# 하는 일과 돌려주는 것이 적힌 선언
name="get_order_status",
description="하루마켓 주문번호로 주문의 현재 상태(결제/배송준비/배송중/배송완료 등)와 "
"택배사·송장번호를 조회한다."
| 설명이 이러면 | 생기는 일 |
|---|---|
| 너무 짧거나 모호하다 | 도구가 있는데도 불리지 않습니다 |
| 다른 도구와 설명이 겹친다 | 엉뚱한 도구가 불립니다 |
| 인자의 형식이 없다 | 인자에 엉뚱한 값이 들어갑니다 |
인자 설명의 "'HR'로 시작하는 문자열"도 같은 이유로 적었습니다. 모델은 문장에서 주문번호를 찾을 때 이 설명을 단서로 씁니다.
4장에서 Pydantic의 Field(description=...)이 모델에게 주는 지시였던 것과 같은 원리입니다.
스키마의 설명은 언제나 모델을 향한 프롬프트입니다. 사람이 아니라 모델이 읽는다고 생각하고 씁니다.
도구가 하나일 때는 이 차이가 잘 드러나지 않습니다. 도구가 여러 개가 되면 설명이 곧 도구 선택의 정확도가 됩니다(7장).
4. 구현 — 지금은 가짜
def get_order_status(order_id: str) -> dict:
"""실제 실행되는 파이썬 함수 (오늘은 하드코딩, 6장에서 CSV 연동)."""
return {
"order_id": order_id,
"status": "배송중",
"courier": "CJ대한통운",
"tracking_no": "6889 1234 5678",
"eta": "내일 도착 예정",
}
어떤 주문번호를 넣어도 같은 값을 돌려주는 가짜 함수입니다. 값을 코드에 직접 적어 두는 것을 하드코딩(hard coding) 이라고 합니다.
선언의 이름(name="get_order_status")과 함수의 이름이 같다는 점을 봅니다. 모델이 이름으로 요청하면 우리 코드가 그 이름의 함수를 실행해야 하므로 둘을 맞춰 둡니다. 맞추는 것은 우리 책임입니다. 선언과 구현은 자동으로 이어지지 않습니다.
5. 자동으로 해 주는 방식도 있다
이번 장은 선언을 손으로 쓰고 왕복도 손으로 돌립니다. SDK에는 이 과정을 대신해 주는 방식도 있습니다.
| 선언 | 실행과 반환 | 이번 과정에서 | |
|---|---|---|---|
| 손으로 | FunctionDeclaration을 직접 씁니다 |
우리 코드가 합니다 | 5장 |
| 자동으로 | 파이썬 함수를 넘기면 SDK가 만듭니다 | SDK가 대신합니다 | 6장부터 |
자동 방식은 코드가 짧아지지만 왕복이 SDK 안으로 숨습니다. 모델의 결정이 어떤 모양으로 오고 결과를 어떻게 돌려주는지 한 번 본 뒤에 써야, 문제가 생겼을 때 어디를 볼지 압니다. 그래서 이번 장에서는 일부러 손으로 합니다.
핵심 정리
- 도구는 선언(모델이 읽는 안내문) 과 구현(실행되는 함수) 두 조각입니다.
- 선언에는 이름, 설명, 인자의 형식을 적습니다. 인자의 형식은 JSON 스키마로 씁니다.
- 모델은 코드를 보지 못합니다. 설명만 보고 쓸지 말지, 무엇을 넣을지 정합니다.
- 설명은 주석이 아니라 프롬프트입니다.
- 선언의 이름과 함수의 이름을 맞추는 것은 우리입니다.