LLM-as-judge нужен там, где строковое сравнение бессмысленно: ответ может быть верным в десяти формулировках. Но judge не превращает вкус в измерительный прибор. Это ещё одна модель, которую сначала проверяют.
Судья поставил релизу пятёрку
Команда просит модель оценивать ответы поддержки от 1 до 5. Новый prompt получает 4,6 против 4,3. После релиза растут эскалации: judge награждал длинные уверенные ответы, даже когда те обещали клиенту невозможное.
Проблема не в «плохой модели». У задачи не было операционного определения качества, контрольной человеческой разметки и цены ложного допуска.
Сначала rubric, затем prompt
Rubric должен позволять двум специалистам независимо прийти к сопоставимому решению. Не пишите «ответ хороший». Разложите качество:
criteria:
groundedness:
question: "Каждое проверяемое утверждение подтверждено CONTEXT?"
labels: [pass, fail, not_applicable]
policy:
question: "Нет обещаний, запрещённых POLICY?"
labels: [pass, fail]
critical: true
resolution:
question: "Ответ решает запрос или явно запрашивает недостающие данные?"
labels: [pass, partial, fail]
output:
schema: {verdict: string, criteria: object, evidence: array}Передавайте judge только необходимые поля, явно отделяя недоверенные INPUT, CONTEXT, ANSWER и RUBRIC. Требуйте structured output, решение по каждому критерию и цитату-доказательство. Объяснение полезно для аудита, но не делает verdict истинным.
Критические инварианты — отсутствие PII, валидность JSON, разрешение tool call — оставляйте детерминированным проверкам. Judge не должен подменять policy engine.
Pairwise лучше абсолютной шкалы
Шкала 1–10 создаёт ложную точность и плавает между прогонами. Для выбора между baseline и candidate используйте blind pairwise:
- Спрячьте имена моделей, версии и метаданные.
- Случайно назначьте ответы позициям A/B.
- Попросите выбрать
A,Bилиtieпо rubric. - Повторите часть примеров с переставленными позициями.
- Отмените решение, если победитель зависит от позиции чаще принятого бюджета нестабильности.
for case in calibration_or_holdout:
left, right = randomize(case.baseline, case.candidate)
verdict = judge(rubric, case.input, case.context, left, right)
save(case.id, mapping_hash, verdict, judge_manifest)Pairwise отвечает «что лучше», но не доказывает, что победитель приемлем. Сначала примените абсолютные safety/contract gates, затем сравнивайте прошедшие варианты.
Calibration set: экзамен для judge
Соберите отдельный набор, размеченный минимум двумя предметными экспертами независимо. Включите очевидные ответы, пограничные случаи, длинные и короткие формулировки, refusals, нарушения policy и правдоподобные галлюцинации. Разногласия не замазывайте большинством: обсудите их, уточните rubric, храните исходные голоса и итог adjudication.
Calibration set не должен совпадать с данными, по которым писали judge prompt. После настройки заморозьте test-часть. При смене judge model, prompt, rubric или контекста калибровку повторяют.
Для бинарного допуска посчитайте confusion matrix относительно adjudicated human label:
human reject human accept
judge reject TN FN
judge accept FP TP
false accept rate = FP / (FP + TN)
false reject rate = FN / (FN + TP)Здесь FP — опасная ошибка: judge пропустил плохой ответ. Если классы несбалансированы, одна accuracy бесполезна. Показывайте матрицу, false accept по критическим срезам и интервалы неопределённости. Порог выбирают по стоимости ошибок, не по максимуму общей accuracy.
Согласие — не истинность
Cohen’s kappa поправляет наблюдаемое согласие двух разметчиков на случайное:
κ = (p_o - p_e) / (1 - p_e)p_o — фактическое согласие, p_e — ожидаемое из маргинальных частот. Считайте κ между judge и adjudicated label, а также между людьми до обсуждения.
Ограничения существенны:
- высокая доля одного класса может дать высокий raw agreement и низкую κ;
- κ не показывает, насколько опасны конкретные false accepts;
- обычная κ не учитывает порядок категорий; для ordinal labels нужна заранее выбранная weighted κ;
- несколько разметчиков и пропуски требуют другой статистики;
- высокая κ двух систематически ошибающихся судей не означает корректность.
Поэтому κ — диагностическая метрика рядом с confusion matrix и разбором ошибок, не release gate в одиночку.
Полный контур
human rubric
-> independent labels -> adjudication
-> calibration/dev set -> настройка judge
-> locked judge test -> confusion matrix, FAR, slices, stability
-> frozen judge manifest
-> blind randomized evaluation
-> human review: critical fails + sample accepted
-> release decisionManifest judge фиксирует provider/model snapshot, prompt hash, rubric version, decoding parameters, output schema и calibration report. Судью нельзя незаметно обновлять вместе с оцениваемой системой.
Что ломается
- Position bias: A выигрывает независимо от содержания. Проверка — swap test.
- Verbosity/style bias: длинный polished ответ побеждает краткий верный. Добавьте контрпримеры равного содержания разного стиля.
- Self-preference: семейство модели предпочитает похожий стиль. Проверьте вторым judge и человеком.
- Reference leakage: reference содержит ответ или метку в явном виде. Разделите данные и инструкции.
- Injection: оцениваемый ответ командует judge. Обрамляйте как недоверенные данные; тестируйте атаками.
- Correlated error: candidate и judge разделяют одну слепую зону. Критические кейсы проверяет независимый механизм.
- Rubric drift: новая policy при старом judge. Версии должны быть связаны manifest-ом.
- Forced choice: judge вынужден выбрать при эквивалентности. Разрешите
tieиuncertain.
Практическая проверка перед релизом: повторно размеченная случайная выборка принятых ответов оценивает false accepts в реальном распределении; все критические judge-fail идут человеку; отдельно смотрят срезы языка, длины, tenant и типа задачи.
Правило главы
Judge — это измерительный сервис, а не источник истины. У него есть rubric, контрольная человеческая разметка, confusion matrix, бюджет false accept, тесты позиции и стабильности, версия и владелец. Без этого число judge — мнение модели с десятичной точкой.
Практикум
Постройте pairwise judge для ответов поддержки.
- Rubric содержит отдельный критический policy-критерий.
- Calibration set размечен независимо двумя людьми и adjudicated.
- Отчёт содержит confusion matrix, false accept по срезам, raw agreement и κ с оговорками.
- A/B рандомизированы; часть пар прогнана в обратном порядке.
- Настройка judge не касалась locked test; judge manifest сохранён.
- Ложные допуски разобраны вручную, а не спрятаны средней accuracy.
Первичные источники
- OpenAI Evals: framework и eval templates
- OpenAI Graders guide
- Cohen, 1960: A Coefficient of Agreement for Nominal Scales