When to Fine-tune

Fine-tuning is powerful but not always the right tool. Before fine-tuning, try prompt engineering and few-shot examples — these are faster and cheaper. Fine-tune when you've exhausted prompt-based approaches.

Good candidates for fine-tuning
  • Consistent output format the model struggles with via prompting
  • Domain-specific terminology, jargon, or writing style
  • Tasks requiring behavior not easily described in a prompt
  • Reducing prompt length significantly to save cost
  • Improving reliability on narrow, well-defined tasks
  • Teaching the model your company's specific tone and brand voice
Try prompting first for these
  • General question answering and summarization
  • Tasks that work well with a detailed system prompt
  • Situations where behavior changes frequently
  • When you have fewer than 50 training examples
  • Tasks requiring up-to-date knowledge (use RAG instead)
  • Exploratory or prototype phases of development

Fine-tuning Methods

GlomaxGPT supports four fine-tuning paradigms, each suited to different goals and data types.

Most Common

Supervised Fine-tuning (SFT)

Train on input-output pairs. The model learns to produce specific outputs for given inputs. Best for format consistency, style, and domain adaptation.

Quality Optimization

Reinforcement Fine-tuning (RFT)

Train with a reward function or grader that evaluates output quality. The model learns to maximize the reward signal. Best for verifiable tasks like coding and math.

Preference Learning

Direct Preference Optimization (DPO)

Train on pairs of (preferred, rejected) responses. The model learns human preferences directly without a separate reward model. Best for alignment and tone.

Multimodal

Vision Fine-tuning

Fine-tune on image-text pairs. Teach the model to recognize domain-specific visual content, diagrams, charts, or follow precise visual instructions.

Dataset Preparation

Fine-tuning data is provided as a JSONL file — one JSON object per line. Each line represents one training example in chat message format.

jsonl
// Each line is a complete training example
{"messages": [{"role": "system", "content": "You are a customer support agent for Acme Corp. Always be polite, concise, and refer customers to support@acme.com for billing issues."}, {"role": "user", "content": "My order hasn't arrived yet, it's been 2 weeks."}, {"role": "assistant", "content": "I'm sorry to hear your order is delayed. I'd be happy to help investigate. Could you share your order number so I can look into the status for you?"}]}
{"messages": [{"role": "system", "content": "You are a customer support agent for Acme Corp. Always be polite, concise, and refer customers to support@acme.com for billing issues."}, {"role": "user", "content": "I want a refund for my subscription."}, {"role": "assistant", "content": "I understand you'd like to request a refund. For billing and subscription matters, please reach out to our billing team directly at support@acme.com — they can process refund requests and are available Monday through Friday, 9am-5pm EST."}]}
{"messages": [{"role": "system", "content": "You are a customer support agent for Acme Corp. Always be polite, concise, and refer customers to support@acme.com for billing issues."}, {"role": "user", "content": "How do I reset my password?"}, {"role": "assistant", "content": "You can reset your password by visiting acme.com/reset and entering your email address. You'll receive a reset link within 2 minutes. If you don't see it, please check your spam folder."}]}
Minimum dataset size: At least 10 examples are required, but 50–100+ are recommended for reliable improvements. For complex tasks, aim for 500+ examples. More diverse, high-quality examples always outperform more low-quality examples.
jsonl
// DPO format: preferred vs rejected response pairs
{"messages": [{"role": "system", "content": "You are a medical information assistant. Provide accurate information and always recommend consulting a doctor."}, {"role": "user", "content": "I have a headache and fever, what should I take?"}], "preferred": [{"role": "assistant", "content": "For a headache with fever, over-the-counter options like acetaminophen (Tylenol) or ibuprofen (Advil) can help manage symptoms. Follow the dosage on the label. If your fever exceeds 103°F, persists beyond 3 days, or is accompanied by a stiff neck or rash, please see a doctor promptly."}], "rejected": [{"role": "assistant", "content": "Just take some Tylenol and you'll be fine."}]}
{"messages": [{"role": "system", "content": "You are a medical information assistant."}, {"role": "user", "content": "What are the symptoms of diabetes?"}], "preferred": [{"role": "assistant", "content": "Common symptoms of Type 2 diabetes include frequent urination, excessive thirst, unexplained weight loss, fatigue, blurred vision, slow-healing sores, and frequent infections. Type 1 diabetes can also include nausea and fruity-smelling breath. These symptoms can develop gradually. If you're experiencing several of these, it's important to see a healthcare provider for proper testing."}], "rejected": [{"role": "assistant", "content": "Diabetes causes you to pee a lot and feel thirsty. See a doctor."}]}
jsonl
// Vision format: include image content in user messages
{"messages": [{"role": "system", "content": "You are an expert radiologist assistant. Describe what you observe in medical images accurately and professionally."}, {"role": "user", "content": [{"type": "image_url", "image_url": {"url": "https://storage.example.com/xray_001.jpg"}}, {"type": "text", "text": "What do you observe in this chest X-ray?"}]}, {"role": "assistant", "content": "This posteroanterior chest X-ray shows clear lung fields bilaterally. The cardiac silhouette is within normal limits, representing approximately 50% of the thoracic diameter. The costophrenic angles are sharp and well-defined. The bony thorax appears intact with no visible fractures. No pneumothorax, pleural effusion, or consolidation is identified."}]}
{"messages": [{"role": "system", "content": "You are an expert radiologist assistant."}, {"role": "user", "content": [{"type": "image_url", "image_url": {"url": "https://storage.example.com/xray_002.jpg"}}, {"type": "text", "text": "Describe the findings in this image."}]}, {"role": "assistant", "content": "This chest X-ray demonstrates increased opacity in the right lower lobe consistent with consolidation, which may represent pneumonia or atelectasis. The left lung field appears clear. Cardiac silhouette is normal in size and configuration."}]}

Validate Your Dataset

python
import json
from collections import defaultdict

def validate_dataset(filepath: str):
    errors = []
    warnings = []
    examples = []
    
    with open(filepath) as f:
        for i, line in enumerate(f, 1):
            try:
                example = json.loads(line.strip())
                examples.append(example)
            except json.JSONDecodeError as e:
                errors.append(f"Line {i}: Invalid JSON — {e}")
                continue
            
            if "messages" not in example:
                errors.append(f"Line {i}: Missing 'messages' key")
                continue
            
            messages = example["messages"]
            if not messages:
                errors.append(f"Line {i}: Empty messages array")
                continue
            
            # Check for assistant message
            roles = [m["role"] for m in messages]
            if "assistant" not in roles:
                errors.append(f"Line {i}: No assistant message")
            
            # Check for very short assistant responses
            for msg in messages:
                if msg["role"] == "assistant" and len(msg.get("content", "")) < 10:
                    warnings.append(f"Line {i}: Very short assistant response")
    
    print(f"Examples: {len(examples)}")
    print(f"Errors: {len(errors)}")
    print(f"Warnings: {len(warnings)}")
    
    if len(examples) < 10:
        warnings.append("Less than 10 examples — minimum is 10, recommend 50+")
    
    for e in errors: print(f"  ERROR: {e}")
    for w in warnings: print(f"  WARN:  {w}")
    
    return len(errors) == 0

validate_dataset("training_data.jsonl")

Creating a Fine-tuning Job

Upload your dataset and create a fine-tuning job in a few API calls. The job runs asynchronously and you'll receive a webhook or can poll for status.

1

Upload your training file

python
from GlomaxGPT import GlomaxGPT

client = GlomaxGPT()

# Upload training data
with open("training_data.jsonl", "rb") as f:
    training_file = client.files.create(
        file=f,
        purpose="fine-tune"
    )

print(f"Training file ID: {training_file.id}")

# Optional: upload validation data
with open("validation_data.jsonl", "rb") as f:
    validation_file = client.files.create(
        file=f,
        purpose="fine-tune"
    )

print(f"Validation file ID: {validation_file.id}")
2

Create the fine-tuning job

python
# Supervised Fine-tuning (SFT)
job = client.fine_tuning.jobs.create(
    training_file=training_file.id,
    validation_file=validation_file.id,
    model="glomaxgpt-mini-2025-04-14",
    method={
        "type": "supervised",
        "supervised": {
            "hyperparameters": {
                "n_epochs": 3,
                "batch_size": "auto",
                "learning_rate_multiplier": "auto"
            }
        }
    },
    suffix="customer-support-v1"  # Custom model name suffix
)

print(f"Job ID: {job.id}")
print(f"Status: {job.status}")

# DPO job
dpo_job = client.fine_tuning.jobs.create(
    training_file=training_file.id,
    model="glomaxgpt-mini-2025-04-14",
    method={
        "type": "dpo",
        "dpo": {
            "hyperparameters": {
                "n_epochs": 1,
                "beta": 0.1  # KL penalty coefficient
            }
        }
    }
)

# RFT job with a grader
rft_job = client.fine_tuning.jobs.create(
    training_file=training_file.id,
    model="glomaxgpt-mini-2025-04-14",
    method={
        "type": "reinforcement",
        "reinforcement": {
            "grader": {
                "type": "string_check",
                "operation": "eq"
            }
        }
    }
)
3

Monitor job status

python
import time

def wait_for_job(job_id: str, poll_interval: int = 60):
    while True:
        job = client.fine_tuning.jobs.retrieve(job_id)
        print(f"Status: {job.status} | Trained tokens: {job.trained_tokens}")
        
        if job.status == "succeeded":
            print(f"Fine-tuned model: {job.fine_tuned_model}")
            return job.fine_tuned_model
        
        elif job.status in ("failed", "cancelled"):
            print(f"Job failed: {job.error}")
            return None
        
        # Show recent events
        events = client.fine_tuning.jobs.list_events(job_id, limit=5)
        for event in reversed(events.data):
            print(f"  [{event.type}] {event.message}")
        
        time.sleep(poll_interval)

fine_tuned_model = wait_for_job(job.id)
4

Use your fine-tuned model

python
# Use exactly like any other model
response = client.responses.create(
    model="ft:glomaxgpt-mini-2025-04-14:my-org:customer-support-v1:abc123",
    input="My order arrived damaged, what should I do?"
)

print(response.output_text)

# List all your fine-tuned models
jobs = client.fine_tuning.jobs.list(limit=10)
for job in jobs.data:
    if job.status == "succeeded":
        print(f"{job.fine_tuned_model} — trained {job.trained_tokens:,} tokens")

Hyperparameters

The default hyperparameters work well for most cases. Use "auto" to let GlomaxGPT choose optimal values based on your dataset size. Tune these only if you observe overfitting or underfitting.

Parameter Default Range Effect
n_epochs auto (1–4) 1–50 How many times to train on the full dataset. More epochs → more memorization, risk of overfitting.
batch_size auto 1–256 Examples per gradient update. Larger batches → more stable training but slower convergence.
learning_rate_multiplier auto 0.02–20 Scales the base learning rate. Higher values → faster learning but risk of instability.
beta (DPO only) 0.1 0.0–2.0 KL divergence penalty. Higher values → stay closer to the base model.
Overfitting Signs: If training loss decreases but validation loss increases, you're overfitting. Try reducing n_epochs, increasing dataset diversity, or adding more examples.

En İyi Uygulamalar

Data Quality Over Quantity

100 high-quality, diverse examples will outperform 1,000 repetitive or low-quality ones. Every training example should represent the behavior you want at its best. Review examples manually before training.

Match Distribution to Production

Training data should mirror the inputs your model will see in production. If users will ask short questions, train on short questions. Mismatch between training and inference distribution is a common cause of poor fine-tune performance.

Use a Validation Split

Always hold out 10–20% of your data for validation. Monitor validation loss alongside training loss. The model checkpointed at lowest validation loss is your best model, not necessarily the final epoch.

Iterate Quickly

Start with a smaller model (glomaxgpt-mini) and fewer epochs to validate your approach before scaling up. A quick 3-epoch fine-tune on 100 examples will tell you if your data and approach are on the right track.

Keep System Prompts Consistent

If you use a system prompt in training, use the same one at inference time. The model learns the behavior conditioned on that exact prompt. Changing it can degrade fine-tuned performance.

Version Your Models

Use the suffix parameter to give your fine-tuned models meaningful names. Keep records of what training data, hyperparameters, and base model version each fine-tune used. This makes debugging and comparison much easier.