Ana içeriğe geç

FunctionGemma’ya Nasıl İnce Ayar Yapılır: Adım Adım Kılavuz

Kaggle’ın ücretsiz GPU’larını kullanarak 10 dakikadan kısa sürede FunctionGemma’ya nasıl ince ayar yapacağınızı öğrenin: veri kümesi hazırlığı ve temel değerlendirmeden eğitime ve ince ayar sonrası doğrulamaya kadar.
· 13 dk. oku

Yapay Zeka ile Keşfedin

Bu eğitimde Google DeepMind’in hafif bir fonksiyon çağırma dil modeli olan FunctionGemma’yı keşfedeceğiz ve güvenilir, şema uyumlu araç kullanımı için neden ince ayarın kritik olduğunu açıklayacağım. 

GPU destekli bir Kaggle ortamı kurarak başlayacağız, ardından hem veri kümesini hem de temel FunctionGemma modelini yükleyip hazırlayacağız.

Sonrasında, araç seçimi ve fonksiyon çağrısı doğruluğu için bir temel seviye oluşturmak üzere ince ayar öncesi değerlendirmeler yapacağız. Ardından FunctionGemma’yı gözetimli eğitimle ince ayar yapacak ve eğitimin ardından performansını değerlendirerek ince ayarın doğru şekilde uygulandığını doğrulayacağız.

İnce ayarı öğrenmenize yardımcı olacak uygulamalı alıştırmalar arıyorsanız, Llama 3 ile İnce Ayar kursuna göz atmanızı öneririm. 

FunctionGemma Nedir? 

FunctionGemma, Google’ın Gemma 3 270M açık modelinin uzmanlaşmış bir sürümüdür; genel sohbet yerine özellikle fonksiyon çağırma ve araç kullanımı için tasarlanmıştır.

Gemma 3 ile aynı mimariyi kullanır ancak fonksiyon çağrılarını temsil eden yapılandırılmış çıktılar üretebilmesini sağlayan özel bir biçim ve eğitim odağı içerir.

FunctionGemma, geliştiricilerin belirli kullanım senaryoları için ince ayar yapabileceği bir temel model olarak yayınlanmıştır. Boyutu ve tasarımı sayesinde hafif, verimli ve dizüstü bilgisayarlar ile uç donanım gibi sınırlı kaynaklara sahip cihazlarda dağıtılabilir.

Neden FunctionGemma’ya İnce Ayar Yapmalı?

FunctionGemma fonksiyon çağırma için eğitilmiş olsa da, bu boyuttaki modeller görev özelinde verilerle ince ayar yapılarak uzmanlaştırıldığında en iyi performansı gösterir. 

İnce ayar, modelin bir araç kümesinden doğru fonksiyonu seçmek ve gerçek kullanım senaryoları için ilgili argümanları doğru biçimde üretmek üzere kararlı kalıplar öğrenmesine yardımcı olur. 

Bu süreç, daha tutarlı ve öngörülebilir yapılandırılmış çıktılara yol açar; bu da pratik iş akışlarında güvenilirliği artırır.

FunctionGemma’ya İnce Ayar: Adım Adım Kılavuz

FunctionGemma’ya ince ayar yapmak için gereken adımları birlikte inceleyelim. 

1. Kaggle ortamını kurma

Önce Kaggle’a gidin ve yeni bir defter oluşturun. Defter açıldıktan sonra sağ taraftaki Session options panelini bulun ve Accelerator ayarını GPU (T4 ×2) olarak seçin. 

Bu, oturum için GPU hızlandırmasını etkinleştirir ve Kaggle’ın ücretsiz hesaplama kaynaklarını kullanarak modele ince ayar yapmanıza olanak tanır.

Kaggle oturumunda GPU seçimi.

GPU’yu etkinleştirdikten sonra yeni bir kod hücresi oluşturun ve gerekli tüm Python bağımlılıklarını kurmak için aşağıdaki komutu çalıştırın. Çekirdek başlatılırken kısa bir süre bekleyebilir, ardından paketler otomatik olarak yüklenecektir.

%pip -q install -U datasets accelerate trl kagglehub sentencepiece huggingface_hub tqdm evaluate jiwer

Şimdi Hugging Face erişim jetonunuzu güvenli şekilde ekleyin. 

Üst menüden Add-ons → Secrets’ı açın, ardından Add Secret’a tıklayın. Gizli adını HUGGINGFACE_TOKEN olarak belirleyin ve Hugging Face API anahtarınızı değer olarak yapıştırın. 

Kaggle Secrets kullanmak, ortam değişkenlerini veya jetonları doğrudan deftere gömmekten daha güvenlidir.

Kaggle’da Hugging Face gizlisini ayarlama.

Gizli bilgi kaydedildikten sonra Kaggle, buna programatik erişim için bir kod parçası sağlayacaktır. 

Hugging Face Hub ile kimlik doğrulamak için aşağıdaki kodu kullanın:

from kaggle_secrets import UserSecretsClient
from huggingface_hub import login

hf_token = UserSecretsClient().get_secret("HUGGINGFACE_TOKEN")
if not hf_token:
    raise ValueError("HUGGINGFACE_TOKEN not found in Kaggle Secrets.")
login(token=hf_token)

Kimlik doğrulaması başarılı olduktan sonra kısıtlı modellere ve veri kümelerine erişebilecek, ayrıca ince ayar yapılmış FunctionGemma modelinizi paylaşım ve yeniden kullanım için Hugging Face Hub’a gönderebileceksiniz.

2. Hermes Reasoning Tool-Use veri kümesini yükleme

Hermes Reasoning Tool-Use veri kümesi; araç kullanımı akıl yürütme formatında yapılandırılmış örnekler içeren, araç seçimi ve JSON tarzı fonksiyon çağırma görevlerinde modelleri eğitmek ve değerlendirmek için tasarlanmış açık bir İngilizce veri kümesidir. 

Doğal dil istemleri ve araç şemalarıyla on binlerce araç kullanımı akıl yürütme örneği içerir ve gözetimli ince ayar için uygun bir formattadır.

Bu eğitimde, daha hızlı denemeler için veri kümesinin bir alt kümesini kullanacağız. 

Önce rastgele bir tohum ve kullanılacak toplam örnek sayısını tanımlayın. Ardından veriyi eğitim ve değerlendirme bölümlerine ayırın:

from datasets import load_dataset

SEED = 40
N_TOTAL = 3000
N_EVAL  = 300
N_TRAIN = N_TOTAL - N_EVAL

Ardından veri kümesini yükleyin, karıştırın ve eğitim ile değerlendirme alt kümelerini oluşturun:

raw = load_dataset("interstellarninja/hermes_reasoning_tool_use", split="train")
raw = raw.shuffle(seed=SEED).select(range(N_TOTAL))
train_ds = raw.select(range(N_TRAIN))
eval_ds  = raw.select(range(N_TRAIN, N_TOTAL))

print("train:", len(train_ds), "eval:", len(eval_ds))

Hugging Face’ten veri kümesi indiriliyor

Bu işlem, hesaplama gereksinimlerini yönetilebilir tutarken ince ayarı göstermek için yeterli olan 2.700 eğitim ve 300 değerlendirme örneği verir.

train: 2700 eval: 300

3. FunctionGemma modelini ve işlemcisini yükleme

Bu eğitimde FunctionGemma modelini doğrudan Kaggle defterine yüklemek için KaggleHub kullanıyoruz. 

KaggleHub, model konumunu otomatik olarak çözer ve defter ortamında kullanılabilir hale getirir; böylece Hugging Face’ten manuel indirme ihtiyacını ortadan kaldırır.

import kagglehub
from transformers import AutoProcessor, AutoModelForCausalLM

model_path = kagglehub.model_download("google/functiongemma/transformers/functiongemma-270m-it")

Yukarıdaki hücreyi çalıştırdıktan sonra model dosyaları Kaggle defterinin Input bölümünde görünecektir; bu da modelin başarıyla yüklendiğini ve yerelde kullanılabilir olduğunu doğrular.

Functiongemma modeline erişmek için Kaggle Hub kütüphanesini kullanma.

Model kullanılabilir hale geldiğinde hem işlemciyi hem de modeli GPU belleğine yüklüyoruz. 

İşlemci, sohbet şablonlarını ve araç şeması biçimlendirmesini yönetir; model ise yapılandırılmış fonksiyon çağrılarını üretmekten sorumludur. 

device_map="auto" ayarı modelin mevcut GPU’ya yerleştirilmesini, dtype="auto" ise donanımın desteklediği verimli bir hassasiyetin seçilmesini sağlar.

processor = AutoProcessor.from_pretrained(model_path, device_map="auto")
model = AutoModelForCausalLM.from_pretrained(model_path, dtype="auto", device_map="auto")
tokenizer = processor.tokenizer if hasattr(processor, "tokenizer") else processor

print("dtype:", model.dtype, "| device:", model.device)

Bu, FunctionGemma’nın doğru şekilde yüklendiğini, GPU’ya yerleştirildiğini ve değerlendirme ile ince ayar için hazır olduğunu doğrular.

dtype: torch.bfloat16 | device: cuda:1

4. Araç tanımlarını normalize etme ve altın fonksiyon çağrılarını çıkarma

FunctionGemma’ya ince ayar yapmadan önce, araçların nasıl temsil edildiğini standartlaştırmalı ve veri kümesinden doğru (altın) fonksiyon çağrılarını güvenilir biçimde çıkarmalıyız. 

Hermes Reasoning Tool-Use veri kümesi araç tanımlarını birden fazla formatta saklayabilir; bu adım tümünü gözetimli ince ayar için kullanabileceğimiz tutarlı bir yapıya dönüştürür.

Araçlar alanını normalize etme

Önce tools alanını normalize ediyoruz. Veri kümesinde tools bir Python listesi, bir JSON dizesi olarak görünebilir veya tamamen eksik olabilir. 

Aşağıdaki yardımcı işlev tüm geçerli gösterimleri temiz bir Python listesine dönüştürür ve hatalı ya da boş girdileri güvenle yok sayar.

import re, json

def normalize_tools_field(tools):
    if tools is None:
        return []
    if isinstance(tools, list):
        return tools
    if isinstance(tools, str):
        s = tools.strip()
        if not s:
            return []
        try:
            parsed = json.loads(s)
            return parsed if isinstance(parsed, list) else []
        except Exception:
            return []
    return []

Parametre türlerini normalize etme

Sırada parametre türlerini normalize etmek var. Hermes araç tanımları sıklıkla str,int gibi gayriresmî tür açıklamalarını veya List[str] gibi kapsayıcı türleri kullanır. Aşağıdaki işlev bunları Hugging Face fonksiyon çağırma ile uyumlu geçerli JSON Schema türlerine dönüştürür.

def _parse_hermes_type(t) -> dict:
    if t is None:
        return {"type": "string"}
    if isinstance(t, dict):
        return t if "type" in t else {"type": "object"}
    if isinstance(t, list):
        return {"type": "array"}
    if not isinstance(t, str):
        return {"type": "string"}

    t = t.strip()
    prim = {
        "str": "string", "string": "string",
        "int": "integer", "integer": "integer",
        "float": "number", "number": "number",
        "bool": "boolean", "boolean": "boolean",
        "dict": "object", "object": "object",
        "list": "array", "array": "array",
    }
    if t.lower() in prim:
        return {"type": prim[t.lower()]}

    m = re.match(r"List\[(.+)\]$", t)
    if m:
        return {"type": "array", "items": _parse_hermes_type(m.group(1).strip())}

    m = re.match(r"Dict\[(.+),\s*(.+)\]$", t)
    if m:
        return {"type": "object", "additionalProperties": _parse_hermes_type(m.group(2).strip())}

    return {"type": "string"}

Hermes tarzı aracı Hugging Face fonksiyon şemalarına dönüştürme

Bu yardımcıları kullanarak Hermes tarzı araç tanımlarını Hugging Face {"type": "function", "function": {...}} şemalarına dönüştürüyoruz. Bu işlev iki formatı destekler:

  • Hermes argüman başına stil (her parametrenin küçük bir özelliği olduğu durum)
  • JSON şemasına zaten benzeyen araçlar

Argüman başına format için, bu uygulama açıkça bir required listesi verilmemişse listelenen parametreleri gerekli sayar.

def hermes_tools_to_hf_schema(tools_field):
    """
    Handles both:
    - Hermes per-arg style: {"parameters": {"x":{"type":"str"}, ...}}
    - Already-JSON-schema style: {"parameters":{"type":"object","properties":...,"required":[...]}}
    """
    hermes_tools = normalize_tools_field(tools_field)
    out = []

    for tool in hermes_tools:
        if not isinstance(tool, dict):
            continue

        name = tool.get("name")
        desc = tool.get("description", "")
        params = tool.get("parameters", {}) or {}

        # If params already look like JSON schema (best case)
        if isinstance(params, dict) and "type" in params and "properties" in params:
            json_schema_params = params
            if "required" not in json_schema_params:
                json_schema_params["required"] = []
        else:
            props, req = {}, []
            if isinstance(params, dict):
                for p_name, p_spec in params.items():
                    p_spec = p_spec or {}
                    if isinstance(p_spec, dict):
                        p_desc = p_spec.get("description", "")
                        p_type = p_spec.get("type", "str")
                    else:
                        p_desc, p_type = "", "str"

                    frag = dict(_parse_hermes_type(p_type))
                    if p_desc:
                        frag["description"] = p_desc
                    props[p_name] = frag
                    req.append(p_name)

            json_schema_params = {"type": "object", "properties": props, "required": req}

        out.append({
            "type": "function",
            "function": {
                "name": name,
                "description": desc,
                "parameters": json_schema_params,
            }
        })

    return out

Yardımcı işlev

Her veri kümesi örneği için dönüştürülmüş araç şemalarını almak üzere küçük bir yardımcı tanımlıyoruz:

def get_tools_hf(ex):
    return hermes_tools_to_hf_schema(ex.get("tools"))

Altın fonksiyon çağrısını çıkarma

Ardından konuşmadan altın araç çağrısını çıkarıyoruz. Hermes konuşmaları birden çok tur içerebilir; bu nedenle <tool_call>{...}</tool_call> bloklarını ayrıştırır ve ilk geçerli araç çağrısı nesnesini (ad + argümanlar) çıkarırız. Bu, gözetimi basit ve tutarlı tutar.

TOOL_CALL_RE = re.compile(r"<tool_call>\s*(\{.*?\})\s*</tool_call>", re.DOTALL)

def extract_first_tool_call_obj(text: str):
    if not text:
        return None
    m = TOOL_CALL_RE.search(text)
    if not m:
        return None
    try:
        obj = json.loads(m.group(1))
        if isinstance(obj, dict) and "name" in obj and "arguments" in obj:
            return obj
    except Exception:
        return None
    return None

Araç çağrısını kullanıcı göreviyle hizalama

Araç çağrısını doğru kullanıcı göreviyle hizalamak için konuşma geçmişini tarar, veri kümesindeki task ile eşleşen kullanıcı mesajını bulur ve ardından hemen sonrasındaki asistan yanıtını alırız. Asistan yanıtı bir araç çağrısı içeriyorsa, bunu altın etiket olarak döndürürüz.

def _role(turn):
    return (turn.get("from") or "").lower().strip()

def get_gold_tool_call_task_aligned(ex):
    task = (ex.get("task") or "").strip()
    conv = ex.get("conversations") or []
    if not conv:
        return None

    idx = None
    if task:
        for i, t in enumerate(conv):
            if _role(t) in ["human", "user"]:
                val = (t.get("value") or "").strip()
                if val == task or task in val or val in task:
                    idx = i
                    break
    if idx is None:
        for i in range(len(conv)-1, -1, -1):
            if _role(conv[i]) in ["human", "user"]:
                idx = i
                break
    if idx is None:
        return None

    for j in range(idx+1, len(conv)):
        if _role(conv[j]) in ["gpt", "assistant", "model"]:
            gold = extract_first_tool_call_obj(conv[j].get("value", ""))
            if gold:
                return gold
        if _role(conv[j]) in ["human", "user"]:
            break
    return None

Bu adımın sonunda, kullanılabilir her veri kümesi örneğinde şunlar bulunur:

  • Normalize edilmiş bir araç şemaları seti (Hugging Face formatında)
  • Temiz, göreve hizalanmış bir altın fonksiyon çağrısı
  • Gözetimli ince ayar örnekleri oluşturmaya hazır tutarlı bir yapı.

6. Fonksiyon çağırma için gözetimli ince ayar örnekleri oluşturma

Şimdi bunları FunctionGemma’nın beklediği tam formatta Gözetimli İnce Ayar (SFT) eğitim örneklerine dönüştürmemiz gerekiyor; yukarıdaki yardımcı işlevleri kullanarak. 

Amaç, girdide şunların bulunduğu örnekler oluşturmaktır:

  • Fonksiyon çağırmayı etkinleştiren bir geliştirici mesajı
  • Kullanıcı görevi
  • Araç bildirimleri (şemalar)

Ve hedef, şu formatta tek bir, yapılandırılmış FunctionGemma çağrısıdır:

<start_function_call>call:TOOL_NAME{args:<escape>{...}<escape>}<end_function_call>

Adım 1: Temiz, kullanılabilir satırlar oluşturma

Veri kümesini yineleyerek eğitimde kullanılamayacak örnekleri filtreleyerek başlıyoruz.

Bu işlev yalnızca şu koşulları sağlayan örnekleri tutar:

  • Bir altın araç çağrısı mevcut
  • Geçerli bir araç listesi mevcut
  • Altın araç adı araç listesinde yer alıyor
  • Argümanlar geçerli bir sözlük
  • Araçta gerekli alan yoksa, hedefte gürültü ve tutarsızlığı önlemek için argümanlar {} olarak zorlanır
from datasets import Dataset

def build_simple_rows(ds, max_rows=None):
    rows = []
    for ex in ds:
        # 1) task-aligned gold tool call
        gold = get_gold_tool_call_task_aligned(ex)
        if not gold:
            continue

        # 2) tools -> HF schema
        hf_tools = get_tools_hf(ex)
        if not hf_tools:
            continue

        # 3) build required_map: tool_name -> required fields
        required_map = {}
        for t in hf_tools:
            if t.get("type") == "function":
                fn = t.get("function", {})
                name = fn.get("name")
                req = (fn.get("parameters", {}) or {}).get("required", []) or []
                if name:
                    required_map[name] = req

        # 4) guard: gold tool must be in tool list
        tool_names = set(required_map.keys())
        if gold["name"] not in tool_names:
            continue

        # 5) force {} when no required params
        gold_args = gold.get("arguments", {})
        if not isinstance(gold_args, dict):
            gold_args = {}

        req = required_map.get(gold["name"], [])
        if len(req) == 0:
            gold_args = {}  # key fix

        rows.append({
            "user_content": ex.get("task", ""),
            "tool_name": gold["name"],
            "tool_arguments": json.dumps(gold_args, ensure_ascii=False),
            "hf_tools": hf_tools,
        })

        if max_rows and len(rows) >= max_rows:
            break

    return rows

Şimdi eğitim ve değerlendirme satırlarını oluşturuyoruz:

simple_train = build_simple_rows(train_ds, max_rows=N_TRAIN)
simple_eval  = build_simple_rows(eval_ds,  max_rows=N_EVAL)
print("usable train:", len(simple_train), "usable eval:", len(simple_eval))

Bizim durumumuzda, orijinal 3.000 örnekten 961 eğitim ve 109 değerlendirme örneği elde ediyoruz. Bu düşüş beklenir; çünkü filtreleme katıdır. Araç çağrısı eksik olan, geçersiz araç tanımı içeren, araç adları uyuşmayan veya hatalı argümanları olan örnekleri kaldırır.

usable train: 961 usable eval: 109

Bu temizleme adımı çok önemlidir. Bunu uygulamadan önce veri kümesi gürültülü ve hizasız örnekler içeriyordu; bu da ince ayardan sonra bile istikrarsız fonksiyon çağırma davranışına ve zayıf sonuçlara yol açıyordu. Yalnızca yüksek kaliteli, göreve hizalanmış örneklerle filtreledikten sonra FunctionGemma çok daha tutarlı hale gelir ve ince ayar sonuçları belirgin ölçüde iyileşir.

Adım 2: Her satırı tek bir eğitim metni örneğine dönüştürme

Sonraki adımda, her satırı FunctionGemma’nın ihtiyaç duyduğu tam istem+hedef yapısına biçimlendiriyoruz. İşlemcinin apply_chat_template özelliğini kullanarak araç bildirimlerini doğru şekilde enjekte ediyor, ardından hedef olarak altın fonksiyon çağrısını ekliyoruz.

def format_row_as_text(row):
    messages = [
        {"role": "developer", "content": "You are a model that can do function calling with the following functions"},
        {"role": "user", "content": row["user_content"]},
    ]
    prompt = processor.apply_chat_template(
        messages,
        tools=row["hf_tools"],
        add_generation_prompt=True,
        tokenize=False,
    )
    target = (
        f"<start_function_call>call:{row['tool_name']}"
        f"{{args:<escape>{row['tool_arguments']}<escape>}}"
        f"<end_function_call>"
    )
    return prompt + target

Şimdi satırları Hugging Face Dataset nesnelerine dönüştürüyoruz:

train_text_ds = Dataset.from_list([{"text": format_row_as_text(r)} for r in simple_train])
eval_text_ds  = Dataset.from_list([{"text": format_row_as_text(r)} for r in simple_eval])

Adım 3: Her örneğin geçerli bir dize olduğundan emin olun

Bazı TRL sürümleri formatting_func’in bir dize döndürmesini gerektirir ve herhangi bir örnek liste ya da dize olmayan değere dönüşürse eğitim bozulabilir. Bu yardımcı, text’in her zaman temiz bir dize olmasını sağlar.

# ensure text is always a string
def force_text_string(ds):
    def fix(ex):
        t = ex.get("text", "")
        if isinstance(t, list):
            t = "\n".join(map(str, t))
        return {"text": str(t)}
    return ds.map(fix)

train_text_ds = force_text_string(train_text_ds)
eval_text_ds  = force_text_string(eval_text_ds)

Son olarak, biçimlendirmeyi doğrulamak için bir örnek yazdırın:

print(train_text_ds[0]["text"])

Araç bildirimlerini içeren tam oluşturulmuş bir istem ve ardından şu şekilde bir altın fonksiyon çağrısı görmelisiniz:

<bos><start_of_turn>developer
You are a model that can do function calling with the following functions<start_function_declaration>declaration:get_pollution_levels{description:<escape>Retrieve pollution levels information<escape>,parameters:{properties:{location:{description:<escape>The location for which you want to get the pollution levels (e.g., Beijing, London, New York)<escape>,type:<escape>STRING<escape>},pollutant:{description:<escape>Specify a pollutant for pollution levels (e.g., PM2.5, PM10, ozone)<escape>,type:<escape>STRING<escape>}},required:[<escape>location<escape>],type:<escape>DICT<escape>}}<end_function_declaration><start_function_declaration>declaration:get_water_quality{description:<escape>Retrieve water quality information<escape>,parameters:{properties:{location:{description:<escape>The location for which you want to get the water quality (e.g., river, lake, beach)<escape>,type:<escape>STRING<escape>}},required:[<escape>location<escape>],type:<escape>DICT<escape>}}<end_function_declaration><end_of_turn>
<start_of_turn>user
I'm planning a beach cleanup at Zuma Beach this weekend and need to ensure safety. Can you provide the current water quality and if it's poor, check the pollution level of PM2.5 there?<end_of_turn>
<start_of_turn>model
<start_function_call>call:get_water_quality{args:<escape>{"location": "Zuma Beach"}<escape>}<end_function_call>

7. İnce ayardan önce FunctionGemma’yı değerlendirme

Eğitimden önce, temel FunctionGemma modelinin fonksiyon çağırmada ne kadar iyi performans gösterdiğini ölçmelisiniz. Bu temel, ince ayarın gerçekten araç seçimini ve fonksiyon çağrısı biçimlendirmesini iyileştirip iyileştirmediğini doğrulamanıza yardımcı olur.

Bu bölümde iki şeyi değerlendiriyoruz:

  • Araç adı doğruluğu: modelin doğru fonksiyon adını seçip seçmediği
  • TC-CER (Tool-Call Character Error Rate): üretilen fonksiyon çağrısı bloğunun altın çağrı bloğuyla ne kadar yakından eşleştiği; daha düşük daha iyidir

Model çıktısından tahmin edilen araç adını ve tam fonksiyon çağrısı bloğunu çıkarmak için iki düzenli ifade kullanıyoruz ve ardından bunları altın etiketlerle karşılaştırıyoruz.

import re
import evaluate
import torch
from tqdm.auto import tqdm

cer_metric = evaluate.load("cer")

# Gemma / FunctionGemma-style only
FG_BLOCK_RE = re.compile(r"<start_function_call>.*?<end_function_call>", re.DOTALL)
FG_NAME_RE  = re.compile(r"call:([a-zA-Z0-9_]+)\{", re.DOTALL)

def extract_tool_name(gen: str):
    gen = gen or ""
    m = FG_NAME_RE.search(gen)
    return m.group(1) if m else None

def extract_call_block(gen: str):
    gen = gen or ""
    m = FG_BLOCK_RE.search(gen)
    return m.group(0) if m else ""

def gold_call_block(r):
    return (
        f"<start_function_call>call:{r['tool_name']}"
        f"{{args:<escape>{r['tool_arguments']}<escape>}}"
        f"<end_function_call>"
    )

Temel değerlendirme döngüsü

Aşağıdaki işlev, değerlendirme örneklerinin bir alt kümesinde çıkarım çalıştırır ve her iki metriği de hesaplar. Sonuçları belirleyici ve ince ayar öncesi-sonrası karşılaştırmasını kolay kılmak için örnekleme devre dışı bırakılmıştır (do_sample=False).

@torch.inference_mode()
def eval_tool_and_cer(proc, mdl, rows, n=50, max_new_tokens=128):
    mdl.eval()
    n = min(n, len(rows))
    tool_ok = 0
    preds, refs = [], []

    for i in tqdm(range(n)):
        r = rows[i]
        messages = [
            {"role": "developer", "content": "You are a model that can do function calling with the following functions"},
            {"role": "user", "content": r["user_content"]},
        ]

        inputs = proc.apply_chat_template(
            messages,
            tools=r["hf_tools"],
            add_generation_prompt=True,
            return_dict=True,
            return_tensors="pt",
        )
        inputs = {k: v.to(mdl.device) for k, v in inputs.items()}

        out = mdl.generate(
            **inputs,
            do_sample=False,
            max_new_tokens=max_new_tokens,
            pad_token_id=proc.eos_token_id,
        )

        gen = proc.decode(out[0][inputs["input_ids"].shape[-1]:], skip_special_tokens=True).strip()

        if extract_tool_name(gen) == r["tool_name"]:
            tool_ok += 1

        preds.append(extract_call_block(gen))
        refs.append(gold_call_block(r))

    return {
        "n_eval": n,
        "tool_accuracy": tool_ok / n,
        "TC-CER (lower is better)": cer_metric.compute(predictions=preds, references=refs),
    }

Temel değerlendirmeyi çalıştırın:

pre_metrics = eval_tool_and_cer(processor, model, simple_eval, n=50, max_new_tokens=128)
print("PRE metrics:", pre_metrics)

İnce ayardan önce bile FunctionGemma bu görevde güçlü bir temel performans gösterir. 

50 değerlendirme örneğinin bir alt kümesinde model, çoğu durumda doğru fonksiyonu seçtiği anlamına gelen yüzde 88 araç adı doğruluğu elde eder. 

Ayrıca, tam fonksiyon çağrısı bloğu için Araç Çağrısı Karakter Hata Oranı (TC-CER) yaklaşık yüzde 33’tür; bu da doğru aracın sıklıkla seçilmesine rağmen üretilen argümanların ve biçimlendirmenin altın hedeften hâlâ saptığını gösterir.

PRE metrics: {'n_eval': 50, 'tool_accuracy': 0.88, 'TC-CER (lower is better)': 0.33399307273626916}

Bu sonuçlar, temel FunctionGemma modelinin fonksiyon çağırmanın mekaniklerini zaten anladığını doğrular. 

Ancak nispeten yüksek karakter hata oranı, argüman bütünlüğünü, biçimlendirme tutarlılığını ve üretilen fonksiyon çağrılarının genel yapısal doğruluğunu artırmak için ince ayara ihtiyaç olduğunu vurgular.

Tek bir tahmini inceleme

Metikler faydalıdır ancak nitel çıktılara bakmak da önemlidir. Aşağıdaki yardımcı, tek bir örnek için çıkarım çalıştırır ve tahmin edilen fonksiyon çağrısını altın referansla birlikte yazdırır.

import torch

@torch.inference_mode()
def infer_one(proc, mdl, rows, idx=0, max_new_tokens=128):
    r = rows[idx]

    messages = [
        {"role": "developer", "content": "You are a model that can do function calling with the following functions"},
        {"role": "user", "content": r["user_content"]},
    ]

    inputs = proc.apply_chat_template(
        messages,
        tools=r["hf_tools"],
        add_generation_prompt=True,
        return_dict=True,
        return_tensors="pt",
    )
    inputs = {k: v.to(mdl.device) for k, v in inputs.items()}

    out = mdl.generate(
        **inputs,
        do_sample=False,
        max_new_tokens=max_new_tokens,
        pad_token_id=proc.eos_token_id,
    )

    gen = proc.decode(
        out[0][inputs["input_ids"].shape[-1]:],
        skip_special_tokens=True
    ).strip()

    pred_tool = extract_tool_name(gen)

    return {
        "task": r["user_content"],
        "tool_match": (pred_tool == r["tool_name"]),
        "predicted": extract_call_block(gen),
        "gold": gold_call_block(r),
    }

Bunu bir örnek üzerinde çalıştırın:

pre = infer_one(processor, model, simple_eval, idx=15)


print(f"""
TASK:
{pre['task']}

TOOL MATCH: {pre['tool_match']}

--- PREDICTED ---
{pre['predicted']}

--- GOLD ---
{pre['gold']}
""")

Çıktı:

TASK:
I'm reviewing the schedule in the surgical unit. Can you fetch the surgical nursing details for patient ID 12345 undergoing a 'Cardiac Bypass' today? If the procedure is handled by Nurse Ratched, let's record a post-operative care task for this evening.

TOOL MATCH: True

--- PREDICTED ---
<start_function_call>call:get_surgical_nursing_information{nurse_id:<escape>Ratched<escape>,patient_id:<escape>12345<escape>,procedure_type:<escape>Cardiac Bypass<escape>}<end_function_call>

--- GOLD ---
<start_function_call>call:get_surgical_nursing_information{args:<escape>{"patient_id": "12345", "procedure_type": "Cardiac Bypass"}<escape>}<end_function_call>

Bu örnekte model uygun fonksiyonu doğru seçti; bu nedenle araç eşleşmesi True’dur. 

Ancak üretilen çağrı fazladan argümanlar içeriyor ve eğitimde kullanılan tam hedef yapıyı izlemiyor. 

Bu argümanlar anlamsal olarak makul olsa da altın fonksiyon çağrısı formatıyla eşleşmez; bu da daha yüksek karakter hata oranına katkıda bulunur. Bu durum, yalnızca araç seçimini değil, yapısal tutarlılığı ve şema uyumluluğunu da geliştirmek için ince ayarın neden gerekli olduğunu gösterir.

8. İnce ayar için model eğiticisini kurma 

Artık temiz SFT veri kümelerine sahip olduğumuza göre, FunctionGemma’ya ince ayar yapacak eğiticiyi yapılandırma adımına geçiyoruz. TRL’nin SFTTrainer’ını kullanıyoruz; bu, sohbet tarzı modelleri metin örnekleri üzerinde ince ayar yapmak için hafif ve güvenilir bir yöntemdir.

Ayrıca, Kaggle’ın ince ayar kontrol noktasını kalıcı bir konuma kaydetmesi için bir çıktı dizini belirliyoruz.

from trl import SFTConfig, SFTTrainer

OUT_DIR = "/kaggle/working/functiongemma-hermes-ft"

Eğitim sırasında VRAM kullanımını azaltmak için gradyan kontrol noktalamasını etkinleştiriyor ve KV önbelleğini devre dışı bırakıyoruz.

# VRAM savings
model.gradient_checkpointing_enable()
model.config.use_cache = False

Eğitici yapılandırması

Eğitim yapılandırmasını SFTConfig ile tanımlıyoruz. Bu ayarlar, Kaggle GPU’larında kararlılık ve verimlilik arasında denge kurmak ve eğitim süresini kısa tutmak için seçilmiştir.

cfg = SFTConfig(
    output_dir=OUT_DIR,
    max_length=512,
    packing=False,
    num_train_epochs=1,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=8,
    learning_rate=5e-5,
    lr_scheduler_type="cosine",
    warmup_ratio=0.03,
    logging_steps=10,
    eval_strategy="steps",
    eval_steps=10,
    report_to="none",
    fp16=(model.dtype == torch.float16),
    bf16=(model.dtype == torch.bfloat16),
    optim="adamw_torch_fused",
)

Biçimlendirme işlevi, her eğitim örneğinin tek bir dize olarak döndürülmesini sağlar; bu, mevcut TRL sürümü için gereklidir.

def formatting_func(example):
    # MUST return a STRING (not list) for your TRL version
    t = example.get("text", "")
    if isinstance(t, list):
        t = "\n".join(map(str, t))
    return str(t)

Eğiticiyi başlatma

Son olarak, SFTTrainer’ı model, yapılandırma, veri kümeleri ve belirteçleyici ile başlatıyoruz.

trainer = SFTTrainer(
    model=model,
    args=cfg,
    train_dataset=train_text_ds,
    eval_dataset=eval_text_ds,
    processing_class=tokenizer,
    formatting_func=formatting_func,
)

9. FunctionGemma’ya ince ayar yapma

Eğitici yapılandırıldıktan sonra, şimdi modele ince ayar yapmaya başlayabiliriz. Bu adım, hazırlanan veri kümesi üzerinde gözetimli eğitimi çalıştırır ve eğitim sırasında modeli periyodik olarak değerlendirir.

trainer.train()
trainer.save_model(OUT_DIR)
processor.save_pretrained(OUT_DIR)
print("Saved to:", OUT_DIR)

Eğitim tamamlandıktan sonra, hem ince ayar yapılmış modeli hem de işlemciyi çıktı dizinine kaydediyoruz; böylece çıkarım için yeniden kullanılabilir veya Hugging Face Hub’a yüklenebilirler.

Model eğitimi ve doğrulama kaybı

Eğitim sırasında hem eğitim hem de doğrulama kaybı istikrarlı şekilde düşer. Ortalama belirteç doğruluğu da zamanla artar; bu da modelin daha doğru ve tutarlı fonksiyon çağrısı çıktıları üretmeyi başarıyla öğrendiğini gösterir.

İnce Ayarlı FunctionGemma Modelini Hugging Face’e Yayımlama

İnce ayar tamamlandığında, model yeniden kullanılabilmesi, paylaşılabilmesi veya kolayca dağıtılabilmesi için yayımlanabilir. Modeli Hugging Face Hub’a göndermek, başkalarının onu standart Transformers API’leriyle doğrudan yüklemesini sağlar.

HF_REPO_ID = "kingabzpro/functiongemma-hermes-3k-ft"
model.push_to_hub(HF_REPO_ID)
processor.push_to_hub(HF_REPO_ID)
print("Pushed to:", HF_REPO_ID)

Yükleme tamamlandıktan sonra, ince ayarlı model Hugging Face üzerinde herkese açıktır:

Pushed to: kingabzpro/functiongemma-hermes-3k-ft

İnce ayarlı model Hugging Face Hub’da yayımlandı.

Kaynak: kingabzpro/functiongemma-hermes-3k-ft · Hugging Face

İnce Ayar Sonrası Değerlendirme ve Hata Analizi

İnce ayar tamamlandıktan sonra, kaydedilen modeli ve işlemciyi diskten yeniden yüklüyor ve eğitim öncesinde kullandığımız aynı değerlendirme hattını çalıştırıyoruz. Bu, ince ayar öncesi ve sonrası performans karşılaştırmasının adil ve tutarlı olmasını sağlar.

from transformers import AutoProcessor, AutoModelForCausalLM

ft_processor = AutoProcessor.from_pretrained(OUT_DIR, device_map="auto")
ft_model = AutoModelForCausalLM.from_pretrained(OUT_DIR, dtype="auto", device_map="auto")

Ardından, ince ayarlı modeli değerlendirme kümesi üzerinde araç adı doğruluğu ve TC-CER kullanarak değerlendiriyoruz.

post_metrics = eval_tool_and_cer(ft_processor, ft_model, simple_eval, n=50, max_new_tokens=64)
print("POST metrics:", post_metrics)

Sonuçlar, temel duruma göre net bir iyileşme gösteriyor:

POST metrics: {'n_eval': 50, 'tool_accuracy': 0.98, 'TC-CER (lower is better)': 0.1454725383473528}

Araç adı doğruluğu yüzde 88’den yüzde 98’e yükselirken, tam fonksiyon çağrısı bloğu için karakter hata oranı yarıdan fazla azaldı. Bu, modelin yalnızca doğru aracı daha güvenilir biçimde seçmekle kalmayıp, aynı zamanda hedef şemayla daha yakından eşleşen çıktılar ürettiğini gösterir.

İyileştirmeleri daha iyi anlamak için tekil tahminleri inceliyoruz. Aşağıdaki örnekte model doğru fonksiyonu seçiyor ve daha eksiksiz argümanlarla iyi yapılandırılmış bir çağrı üretiyor.

post = infer_one(ft_processor, ft_model, simple_eval, idx=15)

print(f"""
TASK:
{post['task']}

TOOL MATCH: {pre['tool_match']}

--- PREDICTED ---
{post['predicted']}

--- GOLD ---
{post['gold']}
""")

Tahmin edilen çağrı altın hedefin ötesine geçen ek argümanlar içerebilse de, genel yapı ve argüman biçimlendirmesi ince ayardan önceye kıyasla belirgin ölçüde daha tutarlıdır. Bu, şema farkındalığının arttığını ve kullanıcı niyetiyle üretilen fonksiyon çağrıları arasındaki hizalamanın güçlendiğini yansıtır.

TASK:
I'm reviewing the schedule in the surgical unit. Can you fetch the surgical nursing details for patient ID 12345 undergoing a 'Cardiac Bypass' today? If the procedure is handled by Nurse Ratched, let's record a post-operative care task for this evening.

TOOL MATCH: True

--- PREDICTED ---
<start_function_call>call:get_surgical_nursing_information{args:<escape>{"patient_id": "12345", "procedure_type": "Cardiac Bypass", "nurse_id": "Ratched", "task": "Post-operative care"}<escape>}<end_function_call>

--- GOLD ---
<start_function_call>call:get_surgical_nursing_information{args:<escape>{"patient_id": "12345", "procedure_type": "Cardiac Bypass"}<escape>}<end_function_call>

Bir başka örneği inceleyelim.

post = infer_one(ft_processor, ft_model, simple_eval, idx=25)

print(f"""
TASK:
{post['task']}

TOOL MATCH: {pre['tool_match']}

--- PREDICTED ---
{post['predicted']}

--- GOLD ---
{post['gold']}
""")

İkinci örnek, bir URL çıkarma görevi için temiz ve doğru bir fonksiyon çağrısı gösterir; bu da ince ayarlı modelin farklı araçlar arasında iyi genelleştiğini kanıtlar.

TASK:
I would like to extract details from a LinkedIn company page. Could you assist me in fetching the information from this URL: https://www.linkedin.com/company/abc-corporation?

TOOL MATCH: True

--- PREDICTED ---
<start_function_call>call:extract{args:<escape>{"url": "https://www.linkedin.com/company/abc-corporation"}<escape>}<end_function_call>

--- GOLD ---
<start_function_call>call:extract{args:<escape>{"url": "https://www.linkedin.com/company/abc-corporation", "html": true}<escape>}<end_function_call>

Genel olarak, bu sonuçlar ince ayarın fonksiyon çağırma görevlerinde hem doğruluğu hem de yapısal doğruluğu başarıyla artırdığını doğrular.

Bu eğitime ait tam Kaggle defteri şu adreste mevcuttur:https://www.kaggle.com/code/kingabzpro/finetuning-functiongemma

Herhangi bir sorunla karşılaşırsanız, defteri klonlayabilir, Hugging Face gizlinizi ekleyebilir ve uçtan uca çalıştırabilirsiniz.

Son Düşünceler

FunctionGemma’yı genel amaçlı metin üretimi veri kümeleri üzerinde eğitmeye çalışıyorsanız, en iyisi erken durmaktır. FunctionGemma genel amaçlı bir dil modeli gibi davranmak üzere tasarlanmamıştır. 

Açık uçlu metin üretimi için Gemma 3 model ailesi daha iyi bir tercihtir. 

FunctionGemma, amaca yönelik bir fonksiyon çağırma modelidir; hedef, doğru aracı seçmek, şema uyumlu argümanlar üretmek ve API’ler, veritabanları ve servisler gibi harici sistemlerle güvenilir şekilde etkileşim kurmaktır.

FunctionGemma’nın küçük boyutu kasıtlı bir tasarım tercihidir. 270 milyon parametreyle, düşük gecikme ve kaynak verimliliği için optimize edilmiştir; yerel makineler, uç cihazlar ve özel altyapı dahil. Bu da onu, akıcılıktan çok doğruluk ve yapılandırmanın önemli olduğu gerçek zamanlı fonksiyon çağırma ve aracılık iş akışları için oldukça uygun kılar.

Bu eğitimde FunctionGemma’ya Hermes Reasoning Tool-Use veri kümesi üzerinde nasıl ince ayar yapacağımızı öğrendik. Temel çıkarım, veri hazırlığı ve değerlendirmenin, ham eğitim süresinden daha önemli olduğudur. 

Veri kümesini dikkatle temizleyerek, görevleri altın araç çağrılarıyla hizalayarak ve katı şema tutarlılığını zorunlu kılarak, nispeten az sayıda yüksek kaliteli örnekle model davranışını dramatik biçimde iyileştirebildik.

Sonuçlar, ince ayarın etkisini açıkça göstermektedir. Araç adı doğruluğu yüzde 88’den yüzde 98’e yükseldi ve tam fonksiyon çağrısı blokları için karakter hata oranı yarıdan fazla azaldı. Daha da önemlisi, model gerçek dünya kullanımıyla uyumlu, iyi yapılandırılmış ve öngörülebilir fonksiyon çağrılarını çok daha tutarlı şekilde üretir hale geldi.

FunctionGemma SSS

FunctionGemma nedir ve Gemma 3’ten nasıl farklıdır?

FunctionGemma, Gemma 3 270M açık modelinin uzmanlaşmış bir sürümüdür. Standart Gemma 3 metin üretimi için tasarlanmışken, FunctionGemma, doğal dili yapılandırılmış fonksiyon çağrılarına (API isteklerine) çevirmek üzere açıkça eğitilmiştir; bu da onu, sohbet botundan ziyade aracılık iş akışları için özel bir "yönlendirici" yapar.

FunctionGemma’yı çalıştırmak için ne tür donanıma ihtiyacım var?

270M parametreli bir model olduğundan FunctionGemma inanılmaz derecede hafiftir (~300MB quantized). Dizüstü bilgisayarlar, cep telefonları ve gömülü donanım (ör. NVIDIA Jetson Nano) gibi uç cihazlarda özel bir bulut GPU’su gerektirmeden verimli şekilde çalışabilir.

FunctionGemma zaten özelleşmişse neden ince ayara ihtiyacım var?

Temel model araç kullanımının kavramını anlıyor olsa da, onu belirli API şemalarınızı ve iş mantığınızı öğretmek için ince ayar yapmak gerekir. Google’ın kıyaslamaları, alan özelindeki görevlerde ince ayarın fonksiyon çağırma doğruluğunu yaklaşık %58 (temel) seviyesinden %85’in üzerine çıkarabildiğini gösteriyor.

FunctionGemma çok turlu konuşmaları yönetebilir mi?

FunctionGemma, öncelikle tek turlu komut yürütme (Kullanıcı Talimatı → Araç Çağrısı) için optimize edilmiştir. Karmaşık, çok turlu akıl yürütme veya uzun konuşma geçmişinin korunması için, zor sorguları daha büyük bir modele (ör. Gemma 3 27B) yönlendiren bir "trafik kontrolörü" olarak kullanılması en iyisidir; basit eylemleri ise yerelde ele alır.

Abid Ali Awan

Yazar

Abid Ali Awan

Sertifikalı bir veri bilimcisi olarak, yenilikçi makine öğrenimi uygulamaları oluşturmak için en son teknolojileri kullanmaya büyük ilgi duyuyorum. Konuşma tanıma, veri analizi ve raporlama, MLOps, konuşma yapay zekası ve NLP alanlarında güçlü bir geçmişe sahip olarak, gerçek bir etki yaratabilecek akıllı sistemler geliştirme becerilerimi geliştirdim. Teknik uzmanlığımın yanı sıra, karmaşık kavramları açık ve özlü bir dille ifade etme yeteneğine sahip, becerikli bir iletişimciyim. Sonuç olarak, veri bilimi konusunda aranan bir blog yazarı oldum ve giderek büyüyen veri profesyonelleri topluluğuyla görüşlerimi ve deneyimlerimi paylaşıyorum. Şu anda, içerik oluşturma ve düzenlemeye odaklanıyorum. Büyük dil modelleriyle çalışarak, hem işletmelerin hem de bireylerin verilerinden en iyi şekilde yararlanmalarına yardımcı olabilecek güçlü ve ilgi çekici içerikler geliştiriyorum.

Konular

İlgili