본문 바로가기
AI2024년 12월 18일8분 읽기

OpenAI Function Calling 실전 — AI에게 도구 사용 능력 부여

YS
김영삼
조회 171
OpenAI Function Calling 실전 — AI에게 도구 사용 능력 부여

Function Calling이란?

Function Calling은 LLM이 사용자 요청을 분석하여 적절한 함수(도구)를 선택하고, 필요한 인자를 JSON 형태로 생성하는 기능입니다. AI가 날씨 조회, DB 검색, 이메일 전송 등 외부 시스템과 상호작용할 수 있게 해주는 핵심 메커니즘입니다.

함수 정의와 호출 흐름

const OpenAI = require('openai');
const openai = new OpenAI();

const tools = [
  {
    type: "function",
    function: {
      name: "get_weather",
      description: "지정한 도시의 현재 날씨를 조회합니다",
      parameters: {
        type: "object",
        properties: {
          city: { type: "string", description: "도시명 (예: Seoul, Tokyo)" },
          unit: { type: "string", enum: ["celsius", "fahrenheit"], description: "온도 단위" }
        },
        required: ["city"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "search_products",
      description: "상품을 검색합니다",
      parameters: {
        type: "object",
        properties: {
          query: { type: "string", description: "검색어" },
          category: { type: "string", description: "카테고리" },
          max_price: { type: "number", description: "최대 가격" }
        },
        required: ["query"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "send_email",
      description: "이메일을 전송합니다",
      parameters: {
        type: "object",
        properties: {
          to: { type: "string", description: "수신자 이메일" },
          subject: { type: "string", description: "제목" },
          body: { type: "string", description: "본문" }
        },
        required: ["to", "subject", "body"]
      }
    }
  }
];

실제 함수 구현과 실행 루프

const functions = {
  get_weather: async ({ city, unit = "celsius" }) => {
    const data = await fetch(
      'https://api.weather.com/v1?city=' + city + '&unit=' + unit
    ).then(r => r.json());
    return JSON.stringify(data);
  },
  search_products: async ({ query, category, max_price }) => {
    const results = await db.products.findMany({
      where: { name: { contains: query }, category, price: { lte: max_price } },
      take: 5
    });
    return JSON.stringify(results);
  },
  send_email: async ({ to, subject, body }) => {
    await transporter.sendMail({ to, subject, text: body });
    return JSON.stringify({ success: true, message: "이메일 전송 완료" });
  }
};

async function runAgent(userMessage) {
  const messages = [
    { role: "system", content: "당신은 유능한 비서입니다. 필요 시 도구를 사용하세요." },
    { role: "user", content: userMessage }
  ];

  while (true) {
    const response = await openai.chat.completions.create({
      model: "gpt-4-turbo",
      messages,
      tools,
      tool_choice: "auto",
    });

    const msg = response.choices[0].message;
    messages.push(msg);

    if (!msg.tool_calls) return msg.content;

    const results = await Promise.all(
      msg.tool_calls.map(async (call) => {
        const fn = functions[call.function.name];
        const args = JSON.parse(call.function.arguments);
        const result = await fn(args);
        return {
          role: "tool",
          tool_call_id: call.id,
          content: result
        };
      })
    );
    messages.push(...results);
  }
}

const answer = await runAgent("서울 날씨 알려주고, 우산 검색해줘");
console.log(answer);

Parallel Function Calling

GPT-4 Turbo는 여러 함수를 동시에 호출할 수 있습니다. 위 예시에서 "서울 날씨 알려주고, 우산 검색해줘"라고 하면 get_weathersearch_products를 한 번의 응답에서 동시에 호출합니다.

핵심 포인트

  • 함수의 description을 명확하게 작성하면 모델이 적절한 함수를 더 정확하게 선택합니다
  • tool_choice: "auto"는 모델이 판단하고, "required"는 반드시 함수를 호출합니다
  • 함수 실행 결과는 role: "tool"로 반환하며, tool_call_id를 반드시 포함해야 합니다
  • 에러 발생 시에도 에러 메시지를 tool 응답으로 반환하면 모델이 적절히 처리합니다
  • 보안상 AI가 호출하는 함수에 반드시 권한 검증과 입력 검증을 적용하세요

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록