Cook AI

Ollama와 Gemma3를 활용한 함수 호출

앤써니킴 2025. 5. 20. 19:25
728x90
이 글은 Arjun Prabhulal님의 동의 하에 그분의 깊이 있는 분석과 자료를 사용하여 작성했습니다. 원문은 [Function calling with Gemma3 using Ollama]에서 확인하실 수 있습니다. 독자 여러분께 더욱 유익한 정보를 전달할 수 있도록 귀한 내용을 공유해주신 Arjun Prabhulal님께 다시 한번 감사드립니다.


함수 호출(Function Calling)은 모델이 자연어와 실제 세계의 액션 및 데이터 사이의 다리 역할을 하도록 지원하는 기능입니다. 이번 글에서는 구글의 강력한 오픈소스 LLM인 Gemma 3와 Ollama를 사용하여 실시간 검색을 수행하는 함수 호출 기능을 활성화하는 방법을 자세히 살펴보겠습니다. 로컬 LLM 모델이 API나 파이썬 함수와 같은 외부 도구와 어떻게 상호작용할 수 있는지 실제 예제를 통해 보여드리겠습니다.

함수 호출이란 무엇일까요?

함수 호출은 모델이 단순히 텍스트를 생성하는 것을 넘어, 외부 도구, API 및 서비스와 상호작용하여 자연어를 실제 행동으로 변환할 수 있게 해주는 기능입니다. 마치 우리가 누군가에게 "오늘 날씨 어때?"라고 물으면 그 사람이 날씨 앱을 확인하고 답해주는 것처럼, LLM도 필요한 정보를 외부에서 가져오거나 특정 작업을 수행할 수 있게 되는 것이죠.

 

함수 호출의 주요 사용 사례는 다음과 같습니다:

  • 데이터 검색: API, 데이터베이스 또는 기타 소스에서 동적으로 정보를 가져옵니다 (예: 날씨, 주식 가격, 특정 문서 내용).
  • 도구 실행: 계산 수행, 작업 자동화 또는 장치 제어를 위해 파이썬 함수나 스크립트를 실행합니다.
  • 멀티 에이전트 협업: 에이전트 시스템이 작업을 서로에게 위임하고 필요할 때 전문 도구를 호출할 수 있도록 합니다.

Gemma3로 함수 호출 구현 가이드: 단계별 상세 설명

이제 Gemma3를 사용하여 함수 호출을 활성화하는 과정을 단계별로 자세히 살펴보겠습니다. 아래 결정 흐름도는 Ollama를 통해 실행되는 Gemma 3가 사용자의 프롬프트에 직접 응답할지, 아니면 외부 API(예: Serper)와 같은 함수 호출을 트리거할지 결정하는 방식을 보여줍니다.

사전 준비 사항

코드를 살펴보기 전에 로컬 컴퓨터에 다음 사전 준비 사항이 충족되었는지 확인해주세요.

  • Python 3.8 이상
  • Ollama 설치 (Gemma3–1B, 4B, 12B, 27B 모델 다운로드 - 이 데모에서는 27B 파라미터 모델 사용)
  • Google 검색을 위한 Serper.dev API 키

1단계: 환경 설정

먼저 가상 환경을 만들어 보겠습니다.

python -m venv venv
source venv/bin/activate

 

필요한 파이썬 패키지를 설치합니다.

pip install gradio ollama requests pydantic python-dotenv
import gradio as gr
import ollama
import requests
import json
import os
from dotenv import load_dotenv
from pydantic import BaseModel, Field
from typing import Optional, Dict, Any, List

2단계: 환경 변수 설정

SERPER_API_KEY를 위해 Serper 대시보드에서 비공개 키를 다운로드합니다. (월 100회 무료 검색 제공)

SERPER_API_KEY=your_serper_api_key_here

3단계: Ollama 및 Gemma 3 설정

  1. Ollama 공식 웹사이트에서 Ollama를 설치합니다.
  2. Gemma3 모델을 내려받습니다.
    ollama pull gemma3:27b

4단계: Pydantic을 사용한 데이터 모델 정의

Pydantic을 사용하여 검색 및 함수 호출을 위한 구조화된 입력 및 출력을 정의합니다.

from pydantic import BaseModel, Field
from typing import Optional, Dict, Any

class SearchParameters(BaseModel):
    query: str = Field(..., description="검색할 용어")

class FunctionCall(BaseModel):
    name: str
    parameters: Dict[str, Any]

class SearchResult(BaseModel):
    title: str
    link: str
    snippet: str

    def to_string(self) -> str:
        return f"제목: {self.title}\n링크: {self.link}\n요약: {self.snippet}"

5단계: Serper API를 사용한 Google 검색 함수 빌드

Gemma 3에 의해 함수 호출이 트리거되면, 챗봇은 Google Search 함수에 쿼리를 전달합니다. 이 함수는 Serper API를 사용하여 실시간 검색 결과를 가져오고 첫 번째 결과를 구조화된 형식으로 반환합니다.

def Google Search(query: str) -> SearchResult:
    url = "https://google.serper.dev/search"
    headers = {
        'X-API-KEY': SERPER_API_KEY,
        'Content-Type': 'application/json'
    }
    payload = json.dumps({"q": query})
    response = requests.post(url, headers=headers, data=payload)
    results = response.json()

    if not results.get('organic'):
        raise ValueError("검색 결과가 없습니다.")

    first = results['organic'][0]
    return SearchResult(
        title=first.get("title", "제목 없음"),
        link=first.get("link", "링크 없음"),
        snippet=first.get("snippet", "요약 없음")
    )

6단계: 시스템 프롬프트, 함수 호출 형식 및 검색 함수 정의

SYSTEM_MESSAGE는 Gemma 3 LLM을 위한 지침 가이드 역할을 합니다. 이는 모델의 의사 결정 과정, 즉 직접 답변할지 아니면 검색과 같은 함수 호출을 트리거할지에 대한 규칙 집합과 같습니다.

 

이 시스템 프롬프트는 모델이 다음을 수행하는 데 도움이 됩니다.

  • 내부 지식에 의존할 시기를 결정합니다.
  • 외부 검색 함수를 호출할 시기를 파악합니다.
  • 함수 호출 출력을 정확한 JSON 구조로 형식화합니다.
# 모델을 위한 시스템 메시지
SYSTEM_MESSAGE = """당신은 2023년까지의 학습 데이터를 가진 AI 어시스턴트입니다. 가능하면 질문에 직접 답변하고, 필요한 경우 검색을 사용하세요.

결정 과정:
1. 역사적 사건 (2023년 이전):
   → 학습 데이터에서 직접 답변

2. 2023년 사건:
   → 명확한 지식이 있는 경우 → 직접 답변
   → 세부 정보가 불확실한 경우 → 검색 사용

3. 현재 사건 (2023년 이후):
   → 항상 검색 사용

4. 시대를 초월하는 정보 (과학적 사실, 개념 등):
   → 학습 데이터에서 직접 답변


함수 호출 형식:
검색이 필요할 때, 다른 텍스트나 백틱 없이 JSON 객체만 응답하세요:
{
    "name": "Google Search",
    "parameters": {
        "query": "검색어"
    }
}

검색 함수:
{
    "name": "Google Search",
    "description": "실시간 정보 검색",
    "parameters": {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "검색어"
            }
        },
        "required": ["query"]
    }
}
"""

7단계: UI 인터페이스(Gradio)에서 LLM까지의 채팅 흐름

  1. 사용자 입력
  2. Gemma의 응답 또는 함수 호출 결정
  3. 검색 실행 및 응답 생성
# 모델 이름
MODEL_NAME = "gemma3:27b"

def process_message(user_input):
    """사용자 메시지를 처리하고 응답을 반환합니다."""
    try:
        response = ollama.chat(
            model=MODEL_NAME,
            messages=[
                {"role": "system", "content": SYSTEM_MESSAGE},
                {"role": "user", "content": user_input}
            ]
        )

        # 모델의 응답 가져오기
        model_response = response['message']['content']

        # 응답을 함수 호출로 구문 분석 시도
        function_call = parse_function_call(model_response)

        if function_call and function_call.name == "Google Search":
            search_params = SearchParameters(**function_call.parameters)
            search_query = search_params.query
             ..
             ...
             ....

8단계: Gradio UI 시작

python function-calling-gemma.py

9단계: 데모

  1. 사용자 쿼리 입력 → "Google Cloud Next 2025 날짜는 언제인가요?" → Gemma3 트리거함수 호출Google 검색
  2. 사용자 쿼리 입력 → "2019년 슈퍼볼 우승팀은 누구인가요?" → 학습 데이터에서 Gemma3 응답 [함수 호출 없음]

GitHub 저장소

전체 소스 코드는 GitHub Function-Calling-Gemma3에서 찾을 수 있습니다. 

결론

이 글에서는 Google의 오픈소스 LLM인 Gemma 3를 Ollama, Gradio 및 Serper API와 함께 사용하여 함수 호출 기능을 활용하는 방법을 시연했습니다. 동일한 방식을 파일 요약, 코드 실행, 작업 자동화로 확장하고, CrewAI 또는 AutoGen과 같은 멀티 에이전트 프레임워크로 더욱 발전시킬 수 있습니다. 이러한 함수 호출 기능은 LLM을 단순한 텍스트 생성 도구를 넘어, 실제 세계와 상호작용하는 강력한 문제 해결사로 만들어 줄 것입니다. 여러분도 직접 시도해보시고 LLM의 새로운 가능성을 경험해보시길 바랍니다!

728x90