[Spring AI] Tool Calling이란? — 함수 호출, JSON 스펙, @Tool, @ToolParam
by 우와한개발자
1. Tool Calling (Function Calling,함수 호출)
- LLM이 단순히 텍스트를 생성하는 것을 넘어 외부 함수나 API를 호출할 수 있도록 하는 기능
- 개발자가 함수를 미리 정의해두면 AI가 대화 맥락을 보고 스스로 판단해서 적절한 함수를 선택하고 호출한다
- 개발자가 if/else로 직접 분기하지 않아도 된다
- LLM은 답변은 만들 수 있지만 메일 발송, 예약, DB 조회 같은 실제 행동은 직접 못한다
- 모델이 필요한 도구를 선택하고 정해진 JSON 형식으로 호출하게 하기 위해 등장했다
2. 동작 흐름
1) 전체 흐름
1. 개발자가 함수 정의 (JSON 스펙)
↓
2. 사용자 질문 + 함수 목록을 API에 전송
↓
3. AI가 판단: "이 질문엔 함수 호출이 필요한가?"
↓ (필요하다고 판단 시)
4. AI가 함수명 + 매개변수를 추출해서 반환
↓
5. 개발자 코드에서 실제 함수 실행
↓
6. 실행 결과를 다시 AI에 전달
↓
7. AI가 결과를 자연어로 최종 응답
2) AI가 판단하는 3가지 경우
| 상황 | AI의 행동 | 예시 |
| 함수 호출이 필요 없을 때 | 텍스트로 바로 답변 | "파이썬이 뭐야?" → 바로 설명 |
| 함수 호출이 필요할 때 | 함수명 + 인자를 반환 (직접 실행 X) | "서울 날씨 알려줘" → get_weather("Seoul") 호출 요청 |
| 여러 함수가 동시에 필요할 때 | 여러 함수를 한 번에 요청 (Parallel Tool Calling) | "서울이랑 도쿄 날씨 비교해줘" → get_weather("Seoul"), get_weather("Tokyo") 동시 호출 요청 |
- AI는 함수를 직접 실행하지 않는다.
- 어떤 함수를 어떤 값으로 호출할지 알려줄 뿐이고 실제 실행은 개발자 몫이다
3. 함수 정의
1) JSON 스펙
- Tool Calling은 함수를 JSON 형식으로 정의해서 AI에 전달한다
- AI는 name과 description을 읽고 언제 어떤 함수를 호출할지 판단한다
- parameters에는 함수 호출에 필요한 매개변수와 설명을 정의한다
{
"name": "get_weather",
"description": "특정 도시의 현재 날씨를 가져온다",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "날씨를 조회할 도시 이름"
}
},
"required": ["city"]
}
}
2) Spring AI — @Tool 어노테이션
- Spring AI에서는 JSON 스펙을 직접 작성하지 않고 @Tool, @ToolParam 어노테이션으로 대체한다
- Spring AI가 어노테이션을 읽어 JSON 스펙으로 자동 변환해서 AI에 전달한다
@Tool(name = "getWeather",
description = "도시의 이름을 기반으로 현재 날씨 정보를 조회합니다.")
public WeatherResponse getWeather(
@ToolParam(description = "날씨를 조회할 도시 이름을 영어로 작성하세요(예: Seoul, Tokyo)")
String city) {
// 외부 API 호출 로직
return new WeatherResponse(city, weather, temperature);
}
- @Tool : 메서드를 Tool로 등록. name과 description을 지정
- @ToolParam : 매개변수 설명을 지정. AI가 어떤 값을 넣어야 할지 판단하는 근거가 된다
3) ChatClient에 등록
- 정의한 Tool을 ChatClient에 등록하면 이후 모든 요청에서 AI가 Tool 호출 여부를 판단한다
ChatClient.builder(chatModel)
.defaultTools(weatherTool) // Tool 등록
.build();
4. 주의사항
1) AI는 함수를 직접 실행하지 않는다
- AI가 반환하는 것은 함수명과 매개변수뿐이다
- 실제 실행은 개발자 코드에서 처리하고 결과를 다시 AI에 전달해야 한다
2) Lombok @RequiredArgsConstructor와 @Qualifier 충돌
- @RequiredArgsConstructor는 Lombok이 생성자를 자동 생성할 때 필드에 붙은 @Qualifier를 생성자 파라미터에 복사하지 않는다
- @Primary가 붙은 Bean이 의도치 않게 주입될 수 있다
- 생성자를 직접 작성해서 @Qualifier를 명시해야 한다
public ChatService(
@Qualifier("openAiChatClient") ChatClient openAiChatClient,
@Qualifier("ollamaChatClient") ChatClient ollamaChatClient
) {
this.openAiChatClient = openAiChatClient;
this.ollamaChatClient = ollamaChatClient;
}
3) description 품질이 호출 정확도를 결정한다
- AI는 description을 읽고 함수 호출 여부를 판단한다
- 설명이 모호하면 불필요한 함수가 호출되거나 필요한 함수가 호출되지 않을 수 있다
4) 주요 활용 사례
- 실시간 데이터 조회 : 날씨, 주가, 환율 등 LLM이 모르는 최신 정보
- DB / API 연동 : 사용자 계정 조회, 주문 내역 검색
- 복잡한 계산 : 날짜 계산, 통계 처리 등 LLM이 잘 틀리는 수치 연산
- 외부 서비스 실행 : 이메일 발송, 캘린더 등록, 결제 처리
'AI > Spring AI' 카테고리의 다른 글
블로그의 정보
우와한개발자 님의 블로그
우와한개발자