Skip to content
바람부는 자유
Go back
LLM Engineering

Tool Use (Function Calling)

LLM Engineering (13/21)

  1. LLM 토큰 기본 개념
  2. LLM Tokenizer 추가 학습
  3. LLM Inference 이해하기: 토큰 예측의 마법
  4. LLM API 기초 (Part 1/3)
  5. LLM API 중급 (Part 2/3)
  6. LLM API 고급 (Part 3/3)
  7. System Message 활용하기
  8. LLM을 활용한 회의록 자동 요약 시스템
  9. Multi-Modal AI 기초
  10. Gradio 기본 사용법
  11. Hugging Face 완전 정복: AI 모델의 GitHub
  12. Google Colab 사용해보기: 무료로 GPU 환경에서 AI 모델 실행하기
  13. Tool Use (Function Calling)
  14. LLM 벤치마크 완전 가이드: 모델 성능 평가의 모든 것
  15. Vector Embeddings와 RAG 기초
  16. LangChain vs LiteLLM 비교 가이드
  17. 고급 RAG: 벡터 데이터베이스를 활용한 문서 검색 시스템
  18. RAG 기반 고객 상담 챗봇 만들기
  19. RAG 시스템 평가 (RAG Evaluation)
  20. 고급 RAG 기법 (Advanced RAG Techniques)
  21. 08-1. 데이터셋 개념 정리

LLM에게 도구(Tool) 를 제공하면, AI가 외부 함수를 호출하여 실시간 정보를 가져오거나 작업을 수행할 수 있습니다.

Tool Use란?

Tool Use(또는 Function Calling)는 LLM이 직접 함수를 실행하는 것이 아니라, "이 함수를 이런 인자로 호출해달라" 고 요청하는 방식입니다.

사용자: "파이썬 코딩의 기술 책 가격이 얼마야?"
    ↓
LLM: "get_book_price('파이썬 코딩의 기술') 함수를 호출해주세요"
    ↓
우리 코드: 함수 실행 → 결과 반환
    ↓
LLM: "파이썬 코딩의 기술의 가격은 32,000원입니다."

활용 사례

분야Tool 예시
고객 지원주문 조회, 배송 추적, 환불 처리
정보 검색DB 조회, API 호출, 웹 검색
업무 자동화이메일 발송, 캘린더 등록, 문서 생성

Tool Use 동작 원리

중요: LLM은 Tool을 직접 실행하지 않습니다. LLM은 "이 함수를 호출해달라"고 요청만 하고, 실제 실행은 애플리케이션이 담당합니다.

┌─────────────────────────────────────────────────────────────────────────────┐
│                                애플리케이션                                  │
│  ┌───────────────────────────────────────────────────────────────────────┐  │
│  │                                                                       │  │
│  │   ┌─────────┐      1. 메시지 + tools 전송      ┌─────────────────┐   │  │
│  │   │         │ ─────────────────────────────▶  │                 │   │  │
│  │   │ 클라이언 │                                  │                 │   │  │
│  │   │ 트 코드 │      2. "이 함수 호출해줘"        │    LLM (API)    │   │  │
│  │   │         │ ◀─────────────────────────────  │                 │   │  │
│  │   │         │      (함수명 + 인자 반환)        │                 │   │  │
│  │   └────┬────┘                                  └─────────────────┘   │  │
│  │        │                                                              │  │
│  │        │ 3. 함수 직접 실행                                            │  │
│  │        ▼                                                              │  │
│  │   ┌─────────┐                                                         │  │
│  │   │  Tool   │  get_book_info("클린 코드")                             │  │
│  │   │  함수들  │  → "클린 코드 - 저자: 로버트 마틴, 가격: 33,000원"       │  │
│  │   └────┬────┘                                                         │  │
│  │        │                                                              │  │
│  │        │ 4. 실행 결과                                                 │  │
│  │        ▼                                                              │  │
│  │   ┌─────────┐      5. 결과 전송                ┌─────────────────┐   │  │
│  │   │ 클라이언 │ ─────────────────────────────▶  │                 │   │  │
│  │   │ 트 코드 │                                  │    LLM (API)    │   │  │
│  │   │         │      6. 최종 응답 생성            │                 │   │  │
│  │   │         │ ◀─────────────────────────────  │                 │   │  │
│  │   └─────────┘   "클린 코드는 33,000원입니다"   └─────────────────┘   │  │
│  │                                                                       │  │
│  └───────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────┘

핵심 포인트

단계주체역할
1클라이언트사용자 메시지와 사용 가능한 tools 목록을 LLM에 전송
2LLM메시지를 분석하고, 필요한 함수와 인자를 결정 (실행 X)
3클라이언트LLM이 요청한 함수를 직접 실행
4클라이언트함수 실행 결과를 받음
5클라이언트실행 결과를 LLM에 다시 전송
6LLM결과를 바탕으로 사용자에게 보여줄 최종 응답 생성

왜 이렇게 설계했을까?

  • 보안: LLM이 직접 코드를 실행하면 위험할 수 있음
  • 제어: 어떤 함수를 허용할지 개발자가 결정
  • 유연성: 어떤 언어, 어떤 시스템의 함수든 연결 가능
import os
import json
from openai import OpenAI
import gradio as gr

client = OpenAI()
MODEL = "gpt-4o-mini"

예제: 온라인 서점 도우미

도서 정보를 조회하고, 재고를 확인하는 온라인 서점 AI 어시스턴트를 만들어봅니다.

# 도서 데이터 (실제로는 DB나 API에서 가져옴)
books_db = {
    "파이썬 코딩의 기술": {
        "author": "브렛 슬라킨",
        "price": 32000,
        "stock": 15,
        "category": "프로그래밍"
    },
    "클린 코드": {
        "author": "로버트 마틴",
        "price": 33000,
        "stock": 8,
        "category": "프로그래밍"
    },
    "데이터 과학을 위한 통계": {
        "author": "피터 브루스",
        "price": 28000,
        "stock": 0,
        "category": "데이터 과학"
    },
    "딥러닝 입문": {
        "author": "사이토 고키",
        "price": 24000,
        "stock": 23,
        "category": "인공지능"
    }
}

1. Tool 함수 정의

LLM이 호출할 수 있는 함수들을 정의합니다.

def get_book_info(title: str) -> str:
    """도서 정보를 조회합니다."""
    print(f"[Tool 호출] get_book_info('{title}')")
    
    book = books_db.get(title)
    if book:
        return f"'{title}' - 저자: {book['author']}, 가격: {book['price']:,}원, 카테고리: {book['category']}"
    return f"'{title}' 도서를 찾을 수 없습니다."

def check_stock(title: str) -> str:
    """도서 재고를 확인합니다."""
    print(f"[Tool 호출] check_stock('{title}')")
    
    book = books_db.get(title)
    if book:
        stock = book['stock']
        if stock > 0:
            return f"'{title}' 재고: {stock}권 (구매 가능)"
        return f"'{title}' 현재 품절입니다. 입고 예정일을 확인해주세요."
    return f"'{title}' 도서를 찾을 수 없습니다."

def search_by_category(category: str) -> str:
    """카테고리별 도서를 검색합니다."""
    print(f"[Tool 호출] search_by_category('{category}')")
    
    results = [title for title, info in books_db.items() if info['category'] == category]
    if results:
        return f"{category} 카테고리 도서: {', '.join(results)}"
    return f"{category} 카테고리에 해당하는 도서가 없습니다."
# 함수 테스트
print(get_book_info("클린 코드"))
print(check_stock("데이터 과학을 위한 통계"))
print(search_by_category("프로그래밍"))
[Tool 호출] get_book_info('클린 코드')
'클린 코드' - 저자: 로버트 마틴, 가격: 33,000원, 카테고리: 프로그래밍
[Tool 호출] check_stock('데이터 과학을 위한 통계')
'데이터 과학을 위한 통계' 현재 품절입니다. 입고 예정일을 확인해주세요.
[Tool 호출] search_by_category('프로그래밍')
프로그래밍 카테고리 도서: 파이썬 코딩의 기술, 클린 코드

2. Tool 스키마 정의

LLM에게 함수의 이름, 설명, 파라미터를 알려주는 스키마를 정의합니다. JSON Schema 형식을 사용합니다.

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_book_info",
            "description": "도서의 상세 정보(저자, 가격, 카테고리)를 조회합니다.",
            "parameters": {
                "type": "object",
                "properties": {
                    "title": {
                        "type": "string",
                        "description": "조회할 도서의 제목"
                    }
                },
                "required": ["title"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "check_stock",
            "description": "도서의 재고 수량을 확인합니다.",
            "parameters": {
                "type": "object",
                "properties": {
                    "title": {
                        "type": "string",
                        "description": "재고를 확인할 도서의 제목"
                    }
                },
                "required": ["title"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "search_by_category",
            "description": "특정 카테고리의 도서 목록을 검색합니다. 카테고리: 프로그래밍, 데이터 과학, 인공지능",
            "parameters": {
                "type": "object",
                "properties": {
                    "category": {
                        "type": "string",
                        "description": "검색할 카테고리명"
                    }
                },
                "required": ["category"]
            }
        }
    }
]

3. Tool 호출 처리

LLM이 tool 호출을 요청하면, 해당 함수를 실행하고 결과를 반환하는 핸들러를 작성합니다.

LLM 응답 구조 이해하기

LLM이 Tool 호출이 필요하다고 판단하면, 다음과 같은 구조의 응답을 반환합니다:

# 전체 응답 구조
response.choices[0] = {
    "finish_reason": "tool_calls",  # ← Tool 호출이 필요함!
    "index": 0,
    "message": {
        "role": "assistant",
        "content": None,  # Tool 호출 시 content는 비어있음
        "tool_calls": [
            {
                "id": "call_abc123",           # 각 호출의 고유 ID
                "type": "function",
                "function": {
                    "name": "get_book_info",   # 호출할 함수 이름
                    "arguments": "{\"title\": \"클린 코드\"}"  # JSON 문자열로 된 인자
                }
            }
        ]
    }
}

finish_reason 값의 종류

finish_reason의미다음 행동
"tool_calls"Tool 호출이 필요함 (미완성)함수를 실행하고 결과를 다시 전송
"stop"정상적으로 응답 완료최종 응답을 사용자에게 반환
"length"최대 토큰 수 도달응답이 잘렸으므로 처리 필요
"content_filter"콘텐츠 필터에 차단됨에러 처리 필요

중요: finish_reasonmessage 객체가 아니라 choice 객체에 위치합니다!

# ✅ 올바른 접근
response.choices[0].finish_reason

# ❌ 잘못된 접근
response.choices[0].message.finish_reason  # 존재하지 않음!

Tool 응답 형식

함수 실행 결과를 LLM에 전달할 때는 반드시 다음 형식을 따라야 합니다:

{
    "role": "tool",                    # 반드시 "tool"
    "content": "함수 실행 결과 문자열",   # 결과는 문자열이어야 함
    "tool_call_id": "call_abc123"      # 어떤 호출에 대한 응답인지 매칭
}
# Tool 이름과 실제 함수를 매핑
available_tools = {
    "get_book_info": get_book_info,
    "check_stock": check_stock,
    "search_by_category": search_by_category
}

def handle_tool_calls(message):
    """LLM의 tool 호출 요청을 처리합니다."""
    responses = []
    
    for tool_call in message.tool_calls:
        function_name = tool_call.function.name
        arguments = json.loads(tool_call.function.arguments)
        
        # 해당 함수 실행
        if function_name in available_tools:
            result = available_tools[function_name](**arguments)
        else:
            result = f"Unknown function: {function_name}"
        
        # Tool 응답 형식으로 반환
        responses.append({
            "role": "tool",
            "content": result,
            "tool_call_id": tool_call.id
        })
    
    return responses

handle_tool_calls 코드 분석

def handle_tool_calls(message):
    responses = []
    
    for tool_call in message.tool_calls:      # ① 여러 Tool 호출을 순회
        function_name = tool_call.function.name        # ② 함수 이름 추출
        arguments = json.loads(tool_call.function.arguments)  # ③ JSON → dict 변환
        
        if function_name in available_tools:
            result = available_tools[function_name](**arguments)  # ④ 함수 실행
        else:
            result = f"Unknown function: {function_name}"
        
        responses.append({
            "role": "tool",
            "content": result,                 # ⑤ 결과는 문자열
            "tool_call_id": tool_call.id       # ⑥ 호출 ID 매칭 (필수!)
        })
    
    return responses
단계설명
LLM이 한 번에 여러 Tool을 호출할 수 있으므로 반복문으로 처리
tool_call.function.name에서 호출할 함수 이름 추출
arguments는 JSON 문자열이므로 json.loads()로 딕셔너리로 변환
**arguments로 딕셔너리를 함수 인자로 언패킹하여 실행
함수 실행 결과는 반드시 문자열이어야 함
tool_call_id는 어떤 호출에 대한 응답인지 LLM에게 알려주는 필수 값

[참고] **arguments 란?

Python의 딕셔너리 언패킹(unpacking) 문법입니다.

arguments = {"title": "클린 코드"}

# ** 없이 전달하면
get_book_info({"title": "클린 코드"})  # ❌ 딕셔너리 객체 하나가 전달됨

# ** 로 전달하면
get_book_info(**arguments)             # ✅ 아래와 동일
get_book_info(title="클린 코드")       # ✅ 키=값 형태로 풀려서 전달됨

LLM이 반환하는 arguments는 딕셔너리이고, 함수는 func(key=value) 형태로 인자를 받으므로 **로 풀어서 전달합니다.

주의: tool_call_id를 누락하면 LLM이 어떤 Tool 호출에 대한 결과인지 알 수 없어 오류가 발생합니다.


4. 채팅 함수 구현

Tool 호출을 포함한 전체 채팅 로직을 구현합니다.

system_message = """당신은 온라인 서점 '북스토어'의 AI 도우미입니다.

[역할]
- 도서 정보 안내
- 재고 확인
- 카테고리별 도서 추천

[응대 지침]
- 친절하고 간결하게 응답하세요
- 도서 정보가 필요하면 제공된 도구를 활용하세요
- 찾는 책이 없으면 비슷한 책을 추천해주세요"""

def chat(message, history):
    # 대화 히스토리 구성
    history = [{"role":h["role"], "content":h["content"]} for h in history]
    messages = [{"role": "system", "content": system_message}] + history + [{"role": "user", "content": message}]

    
    # LLM 호출 (tools 전달)
    response = client.chat.completions.create(
        model=MODEL,
        messages=messages,
        tools=tools
    )
    
    # Tool 호출이 필요한 경우 반복 처리
    while response.choices[0].finish_reason == "tool_calls":
        assistant_message = response.choices[0].message
        tool_responses = handle_tool_calls(assistant_message)
        
        # Tool 호출과 결과를 메시지에 추가
        messages.append(assistant_message)
        messages.extend(tool_responses)
        
        # 다시 LLM 호출
        response = client.chat.completions.create(
            model=MODEL,
            messages=messages,
            tools=tools
        )
    
    return response.choices[0].message.content

while 루프인가?

while response.choices[0].finish_reason == "tool_calls": 코드가 필요한 이유는 LLM이 여러 번 Tool을 호출할 수 있기 때문입니다.

finish_reason 값의 의미

finish_reason의미
"stop"최종 응답 완료, 더 이상 할 일 없음
"tool_calls"Tool 호출 필요, 아직 응답 미완성

단일 요청에 여러 Tool 호출

사용자: "클린 코드 책 정보랑 재고도 알려줘"
1차 LLM 호출 → finish_reason = "tool_calls"
               tool_calls = [get_book_info("클린 코드"), check_stock("클린 코드")]
               
Tool 실행 후 2차 LLM 호출 → finish_reason = "stop"
                            content = "클린 코드는 로버트 마틴 저자이며..."

연쇄적 Tool 호출 (Agentic 패턴)

사용자: "프로그래밍 책 중에서 재고 있는 거 알려줘"
1차: search_by_category("프로그래밍") 
     → 결과: "파이썬 코딩의 기술, 클린 코드"
     
2차: check_stock("파이썬 코딩의 기술"), check_stock("클린 코드")
     → 결과: 각 책의 재고 정보
     
3차: finish_reason = "stop" → 최종 응답 생성

LLM이 카테고리 검색 결과를 본 후 각 책의 재고를 확인하기로 스스로 결정합니다.

if vs while 비교

# ❌ if: 한 번만 처리 - 연쇄 호출 불가
if response.choices[0].finish_reason == "tool_calls":
    ...

# ✅ while: 반복 처리 - 연쇄 호출 가능
while response.choices[0].finish_reason == "tool_calls":
    ...

이 패턴이 Agentic AI의 기초입니다. LLM이 스스로 판단하여 필요한 만큼 Tool을 호출하고, 최종 응답을 생성합니다.

# Gradio 채팅 UI 실행
demo = gr.ChatInterface(
    fn=chat,
    title="북스토어 AI 도우미",
    description="도서 정보, 재고, 카테고리별 검색을 도와드립니다.",
    examples=[
        "클린 코드 책 정보 알려줘",
        "딥러닝 입문 재고 있어?",
        "프로그래밍 관련 책 추천해줘"
    ]
)

demo.launch()
* Running on local URL:  http://127.0.0.1:7864
* To create a public link, set `share=True` in `launch()`.
<IPython.core.display.HTML object>
[Tool 호출] get_book_info('클린 코드')

5. 실전: SQLite 연동

실제 서비스에서는 딕셔너리가 아닌 데이터베이스에서 정보를 조회합니다. SQLite를 사용하여 동일한 기능을 구현해봅니다.

import sqlite3

DB_PATH = "bookstore.db"

# 테이블 생성
with sqlite3.connect(DB_PATH) as conn:
    cursor = conn.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS books (
            title TEXT PRIMARY KEY,
            author TEXT,
            price INTEGER,
            stock INTEGER,
            category TEXT
        )
    ''')
    conn.commit()

# 초기 데이터 삽입
def init_db():
    books = [
        ("파이썬 코딩의 기술", "브렛 슬라킨", 32000, 15, "프로그래밍"),
        ("클린 코드", "로버트 마틴", 33000, 8, "프로그래밍"),
        ("데이터 과학을 위한 통계", "피터 브루스", 28000, 0, "데이터 과학"),
        ("딥러닝 입문", "사이토 고키", 24000, 23, "인공지능"),
    ]
    with sqlite3.connect(DB_PATH) as conn:
        cursor = conn.cursor()
        for book in books:
            cursor.execute('''
                INSERT OR REPLACE INTO books (title, author, price, stock, category)
                VALUES (?, ?, ?, ?, ?)
            ''', book)
        conn.commit()

init_db()
print("DB 초기화 완료!")
DB 초기화 완료!

DB 조회 함수

딕셔너리 대신 SQLite에서 데이터를 조회하는 함수들입니다.

def get_book_info_db(title: str) -> str:
    """DB에서 도서 정보를 조회합니다."""
    print(f"[DB Tool 호출] get_book_info_db('{title}')")
    
    with sqlite3.connect(DB_PATH) as conn:
        cursor = conn.cursor()
        cursor.execute(
            'SELECT author, price, category FROM books WHERE title = ?', 
            (title,)
        )
        result = cursor.fetchone()
    
    if result:
        author, price, category = result
        return f"'{title}' - 저자: {author}, 가격: {price:,}원, 카테고리: {category}"
    return f"'{title}' 도서를 찾을 수 없습니다."

def check_stock_db(title: str) -> str:
    """DB에서 도서 재고를 확인합니다."""
    print(f"[DB Tool 호출] check_stock_db('{title}')")
    
    with sqlite3.connect(DB_PATH) as conn:
        cursor = conn.cursor()
        cursor.execute('SELECT stock FROM books WHERE title = ?', (title,))
        result = cursor.fetchone()
    
    if result:
        stock = result[0]
        if stock > 0:
            return f"'{title}' 재고: {stock}권 (구매 가능)"
        return f"'{title}' 현재 품절입니다."
    return f"'{title}' 도서를 찾을 수 없습니다."

def search_by_category_db(category: str) -> str:
    """DB에서 카테고리별 도서를 검색합니다."""
    print(f"[DB Tool 호출] search_by_category_db('{category}')")
    
    with sqlite3.connect(DB_PATH) as conn:
        cursor = conn.cursor()
        cursor.execute('SELECT title FROM books WHERE category = ?', (category,))
        results = cursor.fetchall()
    
    if results:
        titles = [row[0] for row in results]
        return f"{category} 카테고리 도서: {', '.join(titles)}"
    return f"{category} 카테고리에 해당하는 도서가 없습니다."

# 함수 테스트
print(get_book_info_db("클린 코드"))
print(check_stock_db("데이터 과학을 위한 통계"))
print(search_by_category_db("프로그래밍"))
[DB Tool 호출] get_book_info_db('클린 코드')
'클린 코드' - 저자: 로버트 마틴, 가격: 33,000원, 카테고리: 프로그래밍
[DB Tool 호출] check_stock_db('데이터 과학을 위한 통계')
'데이터 과학을 위한 통계' 현재 품절입니다.
[DB Tool 호출] search_by_category_db('프로그래밍')
프로그래밍 카테고리 도서: 파이썬 코딩의 기술, 클린 코드

DB 버전 채팅 함수

Tool 매핑과 핸들러를 DB 함수로 교체합니다.

# DB 버전 Tool 매핑
available_tools_db = {
    "get_book_info": get_book_info_db,
    "check_stock": check_stock_db,
    "search_by_category": search_by_category_db
}

def handle_tool_calls_db(message):
    """DB 함수를 사용하는 Tool 호출 핸들러"""
    responses = []
    
    for tool_call in message.tool_calls:
        function_name = tool_call.function.name
        arguments = json.loads(tool_call.function.arguments)
        
        if function_name in available_tools_db:
            result = available_tools_db[function_name](**arguments)
        else:
            result = f"Unknown function: {function_name}"
        
        responses.append({
            "role": "tool",
            "content": result,
            "tool_call_id": tool_call.id
        })
    
    return responses

def chat_with_db(message, history):
    """SQLite DB를 사용하는 채팅 함수"""
    history = [{"role":h["role"], "content":h["content"]} for h in history]
    messages = [{"role": "system", "content": system_message}] + history + [{"role": "user", "content": message}]

    response = client.chat.completions.create(
        model=MODEL,
        messages=messages,
        tools=tools  # 기존 스키마 재사용
    )
    
    while response.choices[0].finish_reason == "tool_calls":
        assistant_message = response.choices[0].message
        tool_responses = handle_tool_calls_db(assistant_message)  # DB 핸들러 사용
        
        messages.append(assistant_message)
        messages.extend(tool_responses)
        
        response = client.chat.completions.create(
            model=MODEL,
            messages=messages,
            tools=tools
        )
    
    return response.choices[0].message.content
# SQLite 연동 버전 실행
demo_db = gr.ChatInterface(
    fn=chat_with_db,
    title="북스토어 AI 도우미 (SQLite 연동)",
    description="SQLite DB에서 도서 정보를 조회합니다.",
    examples=[
        "클린 코드 책 정보 알려줘",
        "인공지능 관련 책 있어?",
        "데이터 과학을 위한 통계 재고 확인해줘"
    ]
)

demo_db.launch()
* Running on local URL:  http://127.0.0.1:7865
* To create a public link, set `share=True` in `launch()`.
<IPython.core.display.HTML object>
[DB Tool 호출] get_book_info_db('클린 코드')

딕셔너리 vs SQLite 비교

구분딕셔너리SQLite
장점간단, 빠름영속성, 대용량 데이터, SQL 쿼리
단점메모리 한계, 프로그램 종료 시 소멸설정 필요
용도프로토타입, 테스트실제 서비스

핵심 포인트: Tool 함수 내부 구현만 변경하면 됩니다. LLM에게 전달하는 tools 스키마는 동일하게 유지됩니다.


Tool 호출 흐름 정리

1. 사용자 메시지 + tools 스키마 → LLM 호출
    ↓
2. LLM이 finish_reason="tool_calls" 반환
    ↓
3. tool_calls에서 함수명, 인자 추출
    ↓
4. 해당 함수 실행 → 결과 획득
    ↓
5. tool 응답을 messages에 추가
    ↓
6. 다시 LLM 호출 → 최종 응답 생성

주의사항


요약

이번 노트북에서는 LLM의 Tool Use(Function Calling) 기능을 알아보았습니다.

핵심 포인트

  1. Tool 정의: 함수와 JSON Schema 스키마 작성
  2. Tool 전달: tools 파라미터로 LLM에 전달
  3. 호출 감지: finish_reason == "tool_calls" 확인
  4. 결과 반환: role: "tool" 형식으로 결과 전달
  5. 반복 처리: 여러 Tool 호출을 while 루프로 처리

Share this post on:

Previous Post
LLM 벤치마크 완전 가이드: 모델 성능 평가의 모든 것
Next Post
Google Colab 사용해보기: 무료로 GPU 환경에서 AI 모델 실행하기