NovuSpark
All articles
AIMay 25, 2026 · NovuSpark Team

Fine-Tuning vs. Prompting: When Each Approach Makes Sense

This is the fifth and final post in our OpenAI API fundamentals series, building on everything from your first completion through function calling, context management, and RAG.

Fine-tuning sounds like the more serious, production-grade option — training a model on your own data feels like it should outperform "just writing a better prompt." In practice, it solves a narrower set of problems than that instinct suggests, and reaching for it before exhausting what prompting (with the techniques covered throughout this series) can do is one of the more common, avoidable expenses in real applications.

What fine-tuning actually changes

Fine-tuning trains the model further on examples you provide — pairs of input and desired output — nudging its behavior toward matching that pattern going forward.

{"messages": [{"role": "system", "content": "You are a customer support agent for NovuSpark."}, {"role": "user", "content": "Do you offer refunds?"}, {"role": "assistant", "content": "Yes, we offer full refunds within 30 days of purchase for any training program."}]}
{"messages": [{"role": "system", "content": "You are a customer support agent for NovuSpark."}, {"role": "user", "content": "Can I reschedule my session?"}, {"role": "assistant", "content": "Absolutely — sessions can be rescheduled up to 48 hours in advance at no charge."}]}
client.fine_tuning.jobs.create(
    training_file="file-abc123",
    model="gpt-4o-mini-2024-07-18",
)

What this actually teaches the model is closer to style, tone, and response format consistency than new factual knowledge. Feed it hundreds of examples of your support team's actual tone and typical response structure, and the fine-tuned model produces new responses matching that pattern more consistently than prompting alone reliably achieves — a genuinely narrower, more specific outcome than "the model now knows things it didn't know before."

what's the actual problem?tone/formatinconsistentdoesn't knowyour specific factsneeds to act orreturn structured datafew-shot prompting first,then fine-tuning if neededRAGfunction calling /structured outputs
Fig. 1 — three different symptoms lead to three different fixes; fine-tuning is the answer to only one of them, and only after prompting is exhausted

What fine-tuning does not do well

It is a poor mechanism for adding new factual knowledge. Fine-tuning on a set of documents does not reliably teach a model to accurately recall specific facts from them on demand — it's closer to influencing style than installing a queryable knowledge base. This is precisely the job Retrieval-Augmented Generation, covered in the previous post in this series, actually does well: retrieving the exact relevant passage and handing it to the model as context, rather than hoping a fact survived training and can be accurately recalled later. A remarkably common, expensive mistake is fine-tuning to try to teach a model facts, when RAG was the appropriate tool for that specific problem the entire time.

What prompting alone can already do, before reaching for fine-tuning

  • Few-shot examples directly in the prompt — showing 2-3 examples of desired input/output pairs, in the system or user message itself, often gets a model most of the way to a fine-tuned model's consistency, with zero training cost and no separate deployment step:
messages = [
    {"role": "system", "content": "Respond in the style of these examples:\n\n"
        "Q: Do you offer refunds?\nA: Yes, full refunds within 30 days.\n\n"
        "Q: Can I reschedule?\nA: Yes, up to 48 hours in advance, no charge."},
    {"role": "user", "content": "What if I need to cancel entirely?"},
]
  • A well-structured system prompt, defining tone, constraints, and format explicitly, resolves a large share of the "responses are inconsistent" complaints that first prompt people toward fine-tuning.
  • RAG, as covered in the previous post, resolves the "the model doesn't know our specific facts" problem — a distinctly different complaint from "the responses don't sound consistent," and one fine-tuning doesn't actually address.

A rough decision framework

  • Inconsistent tone or format, few-shot prompting hasn't fully fixed it → fine-tuning is a reasonable next step.
  • The model doesn't know your specific facts, documents, or current data → RAG, not fine-tuning.
  • The model needs to take actions or return structured data reliably → function calling and structured outputs, covered earlier in this series, not fine-tuning.
  • Nothing has actually been tried on the prompting side yet → start there. It's dramatically cheaper to iterate on, requires no training pipeline or evaluation dataset to maintain, and resolves a genuinely large share of real problems people initially assume need fine-tuning.

Evaluating whether a fine-tune actually helped

Once fine-tuning is genuinely the right tool, the harder part is often confirming it actually improved anything, rather than just assuming a training job that completed successfully produced a better model. This needs a held-out evaluation set — examples the model wasn't trained on — scored consistently before and after:

def evaluate(model_id, eval_examples):
    correct = 0
    for example in eval_examples:
        response = client.chat.completions.create(
            model=model_id,
            messages=example["messages"][:-1],  # everything except the expected reply
        )
        if matches_expected(response.choices[0].message.content, example["expected"]):
            correct += 1
    return correct / len(eval_examples)
 
base_score = evaluate("gpt-4o-mini", eval_examples)
fine_tuned_score = evaluate("ft:gpt-4o-mini:novuspark::abc123", eval_examples)

Comparing scores this way — base model against fine-tuned model, on the same held-out examples — is what actually confirms whether the fine-tune improved behavior on genuinely new inputs, rather than just memorizing the training examples themselves. A fine-tune that scores well on its own training data but no better than the base model on held-out examples is a sign of overfitting, not genuine improvement, and worth revisiting the training data's size and diversity rather than deploying it as-is.

The real cost most teams underweight

Fine-tuning isn't just a one-time training cost — it's an ongoing commitment: a new base model version means re-evaluating whether the fine-tune should be redone, evaluating fine-tuned output quality requires its own held-out test set maintained deliberately over time, and every fine-tuned model version is one more artifact someone has to track, version, and eventually retire. That ongoing maintenance burden is the actual reason most teams should treat fine-tuning as a considered, occasionally-necessary decision — not a default reached for before confirming prompting genuinely can't solve the specific problem at hand.

Parameter-efficient fine-tuning: a lighter-weight middle ground

Full fine-tuning updates a model's entire set of weights, which is part of why it's costly to train and maintain across model version updates. Parameter-efficient fine-tuning techniques (LoRA — Low-Rank Adaptation — being the most common) instead train a small set of additional parameters layered on top of the frozen base model:

# Conceptually, via a fine-tuning provider or open-source tooling supporting LoRA
config = {
    "method": "lora",
    "rank": 8,
    "target_modules": ["q_proj", "v_proj"],
}

A LoRA adapter is dramatically smaller and cheaper to train than a fully fine-tuned model, and — because the base model's own weights never change — multiple LoRA adapters for different tasks can be swapped in against the same underlying base model without needing a fully separate fine-tuned copy per task. This is worth knowing as a real middle ground between "prompting alone" and "full fine-tuning," particularly relevant for open-weight models where LoRA tooling is broadly supported, even though the specific fine-tuning options available through OpenAI's own API may differ.

Combining fine-tuning with the other techniques from this series

These approaches aren't mutually exclusive. A production system commonly combines a fine-tuned model (for consistent tone) with RAG (for current, specific facts) and function calling (for taking real actions) — each technique addressing the distinct problem it's actually suited for, layered together rather than treated as competing alternatives to pick exactly one from.

What to actually remember from this series

  • Fine-tuning primarily influences style and format consistency — it is not a reliable mechanism for teaching new facts.
  • RAG is the right tool for "the model doesn't know our specific information" — a genuinely different problem than tone consistency.
  • Few-shot prompting and a well-structured system prompt solve a large share of consistency problems before fine-tuning becomes necessary at all.
  • Evaluate a fine-tune against a held-out set, comparing it to the base model — a fine-tune that only improves on its own training examples is overfitting, not genuine progress.
  • Fine-tuning carries real ongoing maintenance cost — evaluation datasets, re-training as base models update — not just a one-time training expense.

That closes out our OpenAI API fundamentals series — from your first completion through function calling, context and cost management, RAG, and now fine-tuning. If your team is building real production AI applications, this is exactly the kind of hands-on work we build our AI & Generative AI training around.

Ready when you are

Want training built around your team's real work?

Tell us about your team and what you're trying to solve — we'll recommend a program that fits.