How to Evaluate Fine-Tuned LLMs: Metrics, Judges, and Human Review

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1All 1566 services
How to Evaluate Fine-Tuned LLMs: Metrics, Judges, and Human Review
Medium
from 1 day to 3 days
Frequently Asked Questions

AI Development Areas

AI Solution Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1317
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1226
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    925
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1156
  • image_logo-advance_0.webp
    B2B Advance company logo design
    620
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    894

After each fine-tuning iteration, the question arises: did it get better? Without a structured metrics system, it's easy to fall into a trap—the model may overfit, lose general knowledge, or degrade on edge cases. We've seen projects where teams did 15+ iterations "by eye" until they built an evaluation pipeline. Our approach—a hierarchy of metrics from fast automatic ones to expensive human evaluation—lets you stop at the right moment and guarantee quality.

Why comprehensive evaluation of a fine-tuned model matters?

One metric doesn't tell the whole story. BLEU may be high, but the model may hallucinate facts. Perplexity may drop, but response usefulness may decline. Only a combination of automatic metrics, LLM-as-judge, and human evaluation shows the true quality of a fine-tuned neural network. We've been using this approach in all projects for over 5 years—accumulating a portfolio of 50+ fine-tuning projects.

Hierarchy of evaluation metrics

Level 1: Automatic metrics

Fast, cheap, work without human. Provide rough assessment but are indispensable for rapid iterations.

Level 2: LLM-as-judge

A strong model (GPT-4o, Claude 3.5) evaluates the responses of the tested model. Correlates well with human judgment under the right prompt.

Level 3: Human evaluation

Gold standard. Expensive, but necessary for final validation and calibrating lower levels. Typically 200–500 examples suffice.

Comparison of metric types:

Metric Type Speed Cost Correlation with Human
Automatic (BLEU, ROUGE, perplexity) Instant Low 50-60%
LLM-as-judge 1-2 days per 1000 examples Medium 80-85%
Human evaluation Week per 200 examples High 95-100%

How LLM-as-judge complements automatic metrics?

Automatic metrics (BLEU, ROUGE) only measure surface overlap with a reference. LLM-as-judge evaluates semantics: factual accuracy, completeness, logic. In one case, base Llama 3.1 8B showed BLEU-4=0.18, and after fine-tuning—0.39, but the LLM judge revealed the model started inventing legal articles. Without the judge, this would have been missed. LLM-as-judge correlates with human evaluation at 85%, which is 1.5 times higher than automatic metrics. Also, LLM-as-judge is crucial for evaluating text generation where automatic metrics are powerless. Using an evaluation pipeline reduces iteration time by 3 times compared to ad-hoc testing.

Practical implementation of LLM-as-judge

Example implementation of LLM-as-judge
from openai import OpenAI

JUDGE_PROMPT = """You are a strict expert evaluating the quality of AI assistant responses.

Question: {question}

Assistant's answer: {answer}

Reference answer: {reference}

Evaluate the answer on the following criteria (each 1–5):
1. Factual accuracy
2. Completeness of coverage
3. Structuredness
4. Style appropriateness

Return JSON: {{"accuracy": X, "completeness": X, "structure": X, "style": X, "overall": X, "reasoning": "..."}}"""

def llm_judge(question: str, answer: str, reference: str, client: OpenAI) -> dict:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "user",
            "content": JUDGE_PROMPT.format(question=question, answer=answer, reference=reference)
        }],
        response_format={"type": "json_object"},
        temperature=0.1
    )
    return json.loads(response.choices[0].message.content)

Automatic metrics: implementation in code

Below is an example of computing BLEU and ROUGE for an evaluation pipeline. The code can be used as a template.

from nltk.translate.bleu_score import corpus_bleu, SmoothingFunction
from rouge_score import rouge_scorer

references = [[ref.split()] for ref in reference_list]
hypotheses = [hyp.split() for hyp in hypothesis_list]

bleu_4 = corpus_bleu(references, hypotheses,
    weights=(0.25, 0.25, 0.25, 0.25),
    smoothing_function=SmoothingFunction().method1)

scorer = rouge_scorer.RougeScorer(['rouge1','rouge2','rougeL'], use_stemmer=True)
rouge_scores = [scorer.score(ref, hyp) for ref, hyp in zip(reference_list, hypothesis_list)]

Perplexity—model confidence metric

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

def compute_perplexity(model, tokenizer, texts: list[str]) -> float:
    total_loss = 0
    total_tokens = 0
    model.eval()
    with torch.no_grad():
        for text in texts:
            encodings = tokenizer(text, return_tensors="pt").to(model.device)
            outputs = model(**encodings, labels=encodings["input_ids"])
            total_loss += outputs.loss.item() * encodings["input_ids"].shape[1]
            total_tokens += encodings["input_ids"].shape[1]
    avg_loss = total_loss / total_tokens
    return torch.exp(torch.tensor(avg_loss)).item()

Classification and extraction—evaluate via F1 and accuracy

from sklearn.metrics import classification_report, f1_score

def evaluate_classification(model_outputs: list, ground_truth: list) -> dict:
    predictions = []
    for output in model_outputs:
        try:
            pred = json.loads(output)["category"]
        except:
            pred = "parse_error"
        predictions.append(pred)
    report = classification_report(ground_truth, predictions, output_dict=True)
    return {
        "macro_f1": report["macro avg"]["f1-score"],
        "weighted_f1": report["weighted avg"]["f1-score"],
        "accuracy": report["accuracy"],
        "per_class": {k: v for k, v in report.items() if isinstance(v, dict) and k not in ["macro avg", "weighted avg"]}
    }

Practical example: comprehensive evaluation of a fine-tuned model

Base model: Llama 3.1 8B Instruct. Fine-tuning: QLoRA r=16, 2000 examples of legal documents.

Metric Base model Fine-tuned Change
ROUGE-L 0.41 0.67 +63%
BLEU-4 0.18 0.39 +117%
Perplexity (domain) 24.3 11.8 -51%
Perplexity (MMLU) 8.2 9.1 +11% (forgetting)
LLM-judge overall 3.1 4.3 +39%
F1 (NER category) 0.61 0.89 +46%

Perplexity on MMLU increased by 11%—moderate catastrophic forgetting, but for a narrow legal use case this is acceptable. Solution: add 10% general data in the next round. This fine-tuning benchmark helps quantify forgetting.

What our model evaluation work includes

  • Development of a custom evaluation pipeline for your task (including scripts, configs, and documentation)
  • Setup of automatic metrics (BLEU, ROUGE, perplexity, F1, accuracy)
  • Integration of LLM-as-judge with judge model selection and prompt calibration
  • Conducting human evaluation (engaging experts, collecting annotations)
  • Building a metrics dashboard and monitoring (MLflow, Weights & Biases)
  • Delivery of full documentation, access credentials, and a training session
  • Ongoing support and maintenance for 3 months post-deployment
  • Final report with recommendations for model improvement
  • Training your team to work with the pipeline

Investment: from $3,000 for a basic pipeline to $10,000 for a comprehensive system. Savings on unnecessary iterations can reach 40% of project budget.

Start with an evaluation pipeline—contact us for a model audit. Our method ensures reliable LLM quality assessment.

Timeline and evaluation process

  1. Task and metrics analysis—1–2 days
  2. Pipeline development and integration—3–5 days
  3. Automatic evaluation—a few hours
  4. LLM-as-judge (up to 1000 examples)—1–2 days
  5. Human evaluation—1 week
  6. Report and recommendations—1–2 days

Total for one fine-tuning iteration—1–2 weeks. For a comprehensive project with multiple rounds—from 3 weeks.

Post-deployment monitoring

import mlflow

def log_inference_quality(prompt, response, user_feedback):
    with mlflow.start_run(run_name="production-monitoring"):
        mlflow.log_metrics({
            "response_length": len(response.split()),
            "refusal_detected": int("I cannot" in response.lower()),
            "user_rating": user_feedback.get("rating", -1),
        })

Monitoring in production is mandatory—we guarantee the model doesn't degrade over time. Certified engineers from our team accompany the project throughout its lifecycle. Our team has 5+ years of experience in fine-tuning and has completed over 50 projects.

If you want to implement systematic evaluation, contact us. We'll help build a pipeline and save on unnecessary iterations. Request a consultation: we'll evaluate your project in 2 days.