Шаблон «LLM в роли судьи»
Разберитесь, как задавать сильной LLM инструкции для оценки или сравнения выводов по таким критериям, как корректность, полезность и тон, и почему этот подход масштабируется лучше человеческой оценки.
«Шаблон «LLM в роли судьи»» — бесплатный урок AI Engineering Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Engineering Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Engineering Academy содержит 4 уроков всего.
Части этого урока еще не переведены и отображаются на английском.
Why Automated Evaluation Is Necessary
Manually evaluating LLM outputs is slow and expensive. A team of human raters can evaluate a few hundred outputs per week, but a production system generates thousands per day. LLM-as-judge uses a powerful language model to evaluate the quality of other LLM outputs at scale, enabling automated regression testing and continuous quality monitoring without hiring an army of annotators.
The Core Idea: One LLM Evaluates Another
In LLM-as-judge, you send a system prompt defining evaluation criteria, the original question, the model's answer, and optionally a reference answer to a judge model (typically GPT-4o or Claude). The judge returns a numerical score, a label, or a ranking. This works because state-of-the-art models have sufficient understanding of quality concepts like correctness, helpfulness, and coherence.
JUDGE_SYSTEM_PROMPT = '''
You are an expert evaluator of AI-generated responses.
Given a question and an AI-generated answer, score the answer on:
- Correctness (0-5): Is the information factually accurate?
- Completeness (0-5): Does it fully address the question?
- Clarity (0-5): Is it easy to understand?
Return a JSON object with scores and a brief rationale.
'''Writing a Judge Prompt
A good judge prompt specifies explicit rubrics with score definitions rather than vague terms like 'good' or 'bad'. Define what a score of 5 vs 3 vs 1 means concretely for each criterion. Provide the question, the answer being judged, and optionally a reference answer. Ask for reasoning before the score (chain-of-thought) to reduce arbitrary scoring.
def build_judge_prompt(question: str, answer: str, reference: str = None) -> str:
ref_section = f'Reference answer:\n{reference}\n\n' if reference else ''
return f'''
Question: {question}
{ref_section}Answer to evaluate:
{answer}
Score this answer on correctness (1-5) where:
5 = Completely accurate, no factual errors
3 = Mostly accurate with minor errors
1 = Contains significant factual errors
First explain your reasoning, then provide the score as JSON:
{{"correctness": <1-5>, "rationale": "..."}}
'''Calling the Judge Model
Call the judge model with your evaluation prompt. Parse the JSON response to extract scores. Always use structured outputs or JSON mode to ensure the judge returns parseable data. Using the same model as both the system under test and the judge can introduce bias — prefer a different model or at least a different configuration for the judge.
from pydantic import BaseModel
import instructor
from openai import OpenAI
class JudgeScore(BaseModel):
correctness: int
completeness: int
clarity: int
rationale: str
judge_client = instructor.from_openai(OpenAI())
def judge(question: str, answer: str) -> JudgeScore:
return judge_client.chat.completions.create(
model='gpt-4o', # Use stronger judge than the model being tested
response_model=JudgeScore,
messages=[
{'role': 'system', 'content': JUDGE_SYSTEM_PROMPT},
{'role': 'user', 'content': build_judge_prompt(question, answer)}
]
)Reference-Free vs Reference-Based Judging
There are two modes of LLM judging. Reference-free judging asks the judge to evaluate quality without a ground truth answer — useful when ground truth does not exist, like in open-ended chat. Reference-based judging provides a gold-standard answer and asks whether the model's answer matches it — better for factual question answering where a correct answer is known. Use reference-based when you have a labeled test set.
# Reference-free: good for open-ended generation
judge_result = judge(question='What is machine learning?', answer=model_answer)
# Reference-based: better for factual QA
judge_result = judge(
question='What year was Python created?',
answer=model_answer,
reference='Python was created by Guido van Rossum and released in 1991.'
)Controlling Judge Bias
LLM judges have known biases: they prefer longer answers (verbosity bias), answers that sound confident, and answers that match the style of their training data. Mitigate verbosity bias by explicitly penalizing unnecessary length in your rubric. Reduce position bias in pairwise comparison by randomizing which answer appears first and averaging the scores from both orderings.
# Anti-verbosity note in rubric:
ANTI_VERBOSITY_CLAUSE = '''
Note: A concise, accurate answer should score higher than a long,
rambling answer that happens to contain the correct information.
Do not reward length for its own sake.
'''
# Position-debiasing for pairwise comparison:
async def debiased_pairwise(q, a, b):
score_ab = await compare(q, answer_a=a, answer_b=b)
score_ba = await compare(q, answer_a=b, answer_b=a)
# A wins if it wins in both orderings
a_wins = (score_ab == 'A' and score_ba == 'B')
return 'A' if a_wins else 'B' if (score_ab == 'B' and score_ba == 'A') else 'tie'Batching Evaluations for Speed
Run judge evaluations in parallel to evaluate large test sets quickly. With asyncio and a semaphore, you can evaluate hundreds of outputs per minute. Keep a separate rate limit budget for judge calls (they use tokens too) and consider using a smaller but still capable judge model like GPT-4o-mini for criteria that do not require deep reasoning, saving GPT-4o for the most critical criteria.
import asyncio
async def batch_judge(qa_pairs: list, concurrency: int = 20) -> list:
sem = asyncio.Semaphore(concurrency)
async def judge_one(item):
async with sem:
return await async_judge(item['question'], item['answer'])
return await asyncio.gather(
*[judge_one(item) for item in qa_pairs],
return_exceptions=True
)Aggregating Judge Scores
After evaluating a test set, aggregate scores into summary statistics: mean, median, and the percentage of responses scoring above a quality threshold (such as correctness ≥ 4). Compare these aggregates between model versions or prompt variations. A drop of more than 5% in the above-threshold rate should trigger a review before deploying the new version.
import statistics
def summarize_judge_results(scores: list) -> dict:
correctness = [s.correctness for s in scores if isinstance(s, JudgeScore)]
return {
'n': len(correctness),
'mean_correctness': round(statistics.mean(correctness), 2),
'median_correctness': statistics.median(correctness),
'pct_above_4': round(100 * sum(1 for s in correctness if s >= 4) / len(correctness), 1)
}Comparing LLM Versions with Judge
Use LLM-as-judge to compare two versions of your system — for example, before and after a prompt change. Run both versions on the same set of test questions, judge all outputs, and compute the win rate: the percentage of cases where version B outscores version A. A win rate above 55% on 100+ samples is typically statistically significant enough to justify shipping the new version.
async def ab_compare(test_questions: list, version_a, version_b) -> dict:
a_wins = b_wins = ties = 0
for q in test_questions:
answer_a = await version_a.answer(q)
answer_b = await version_b.answer(q)
winner = await debiased_pairwise(q, answer_a, answer_b)
if winner == 'A': a_wins += 1
elif winner == 'B': b_wins += 1
else: ties += 1
total = len(test_questions)
return {'a_win_rate': a_wins/total, 'b_win_rate': b_wins/total, 'tie_rate': ties/total}Calibrating Judge Scores Against Humans
Validate your judge by comparing its scores to human judgments on a calibration set of 50-200 examples. Compute Pearson correlation between judge and human scores. A correlation above 0.7 indicates the judge is reliable. If correlation is low, audit the judge prompt to see where it disagrees with humans and add examples or clarifications to the rubric. Never deploy a judge without calibration.
from scipy.stats import pearsonr
def calibrate_judge(human_scores: list, judge_scores: list) -> dict:
corr, p_value = pearsonr(human_scores, judge_scores)
mean_abs_error = sum(abs(h - j) for h, j in zip(human_scores, judge_scores)) / len(human_scores)
return {
'pearson_r': round(corr, 3),
'p_value': round(p_value, 4),
'mean_abs_error': round(mean_abs_error, 2),
'reliable': corr >= 0.7
}When Not to Use LLM-as-Judge
LLM-as-judge is not appropriate for every evaluation scenario. Avoid it when: the criterion requires domain expertise the judge model lacks (medical diagnosis accuracy, legal compliance), when you need legally defensible evaluation (human review is required), when evaluating a model stronger than the judge (the judge cannot reliably score output it could not produce), or when the evaluation budget is too tight for the additional API cost. In these cases, use human evaluation or deterministic metrics.
# Appropriate uses of LLM-as-judge:
# YES: General helpfulness, clarity, tone, factual accuracy (general knowledge)
# YES: Code correctness for common languages
# YES: Translation quality comparison
# YES: Content safety classification
#
# NOT appropriate:
# NO: Medical/legal/financial accuracy (needs domain expert)
# NO: Evaluating GPT-4o with GPT-4o (same capability ceiling)
# NO: Formal compliance audits (non-deterministic judge)
# NO: Streaming quality at individual token levelQuick Check
Test your understanding of the LLM-as-judge evaluation pattern.
Lesson Recap
In this lesson you learned: LLM-as-judge uses a strong model to evaluate quality at scale with explicit rubrics, reference-free and reference-based modes suit different evaluation scenarios, and calibration against human judgments validates that your judge is reliable before using it in production. Next up we implement pointwise and pairwise evaluation strategies.
Часто задаваемые вопросы
Урок «Шаблон «LLM в роли судьи»» бесплатный?
Да — полный текст урока «Шаблон «LLM в роли судьи»» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Engineering Academy, подпишись на CoddyKit PRO. Курс AI Engineering Academy содержит 4 уроков всего.
Чему я научусь в уроке «Шаблон «LLM в роли судьи»»?
Разберитесь, как задавать сильной LLM инструкции для оценки или сравнения выводов по таким критериям, как корректность, полезность и тон, и почему этот подход масштабируется лучше человеческой оценки. Ты практикуешь AI Engineering Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать AI Engineering Academy?
Предыдущий опыт не требуется. AI Engineering Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Шаблон «LLM в роли судьи»»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке AI Engineering Academy?
Да. Каждый урок AI Engineering Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Шаблон «LLM в роли судьи»
- Поточечная и попарная оценка
- Калибровка моделей-судей по оценкам людей
- Создание конвейера непрерывной оценки