# LLM-as-Judge: автоматический quality gate для LLM в production

> Как использовать LLM-as-Judge для автоматической оценки качества LLM-выходов. Метрики, judge-промпты, DeepEval, Langfuse и интеграция в CI/CD pipeline.
> Author: Roman Belov · Published: 2026-03-13 · Source: https://futurecraft.pro/ru/blog/llm-as-judge-automated-quality-gate/

LLM-as-Judge — это паттерн, в котором одна языковая модель оценивает выходы другой по заданным критериям. Автоматический quality gate: каждый ответ проходит проверку до попадания к пользователю или после — для мониторинга. Стандартные метрики production-мониторинга (200 OK, latency 340ms, rate limits в норме) бесполезны для оценки качества: модель может галлюцинировать в заметной доле ответов, а HTTP-статусы об этом ничего не скажут.

Ручная проверка не масштабируется. При 100 запросах в день один человек справляется. При 10 000 уже нет. А деградация качества чаще всего происходит именно на масштабе: после обновления промпта, смены модели или тихого изменения на стороне провайдера.

Эта статья — о том, как устроен LLM-as-Judge, какие метрики оценивать и как интегрировать в production pipeline.

## Идея LLM-as-Judge и ограничения подхода

Модель-судья получает промпт с инструкциями, оцениваемый текст и возвращает оценку: числовой score, категорию или structured JSON. Судья не генерирует контент, а классифицирует и оценивает. Модели справляются с этим стабильнее, чем с генерацией.

```
Пользователь: "Порекомендуй кафе в центре Москвы"
          │
          ▼
┌──────────────────┐
│   LLM Generator  │ → "Вот 5 кафе: Кофемания на Патриарших..."
│   (GPT-5.4-mini)  │
└──────────────────┘
          │
          ▼
┌──────────────────┐
│   LLM Judge      │ → { relevance: 0.9, factuality: 0.7,
│   (Claude Sonnet) │     toxicity: 0.0, completeness: 0.8 }
└──────────────────┘
          │
          ▼
   Score < threshold? → Alert / Block / Log
```

Исследование Zheng et al. (2023, «Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena») показало, что GPT-4 в роли судьи совпадает с человеческими оценками в 80%+ случаев. Два человека-асессора совпадают между собой примерно в 81%. Разрыв между LLM-судьёй и человеком примерно равен разрыву между двумя людьми.

## Метрики качества LLM-выходов: что оценивать

Выбор метрик зависит от задачи. Основные категории ниже.

### Метрики для RAG-систем

| Метрика | Что проверяет | Когда нужна |
|---------|--------------|-------------|
| **Faithfulness** | Ответ основан на контексте, нет выдуманных фактов | Всегда для RAG |
| **Answer Relevance** | Ответ соответствует вопросу | Всегда |
| **Context Relevance** | Retriever вернул релевантные документы | Отладка retrieval |

### Метрики для генеративных задач

| Метрика | Что проверяет | Когда нужна |
|---------|--------------|-------------|
| **Correctness** | Фактическая точность | При наличии reference answer |
| **Completeness** | Ответ покрывает все аспекты запроса | Сложные запросы |
| **Toxicity** | Нет оскорблений, вредного контента | User-facing продукты |
| **Hallucination** | Модель не выдумывает факты | Всегда |

### Метрики для агентных пайплайнов

| Метрика | Что проверяет | Когда нужна |
|---------|--------------|-------------|
| **Tool Use Correctness** | Правильный инструмент с правильными аргументами | Агентные пайплайны |
| **Task Completion** | Конечный результат решает задачу | Всегда для агентов |

На практике достаточно начать с двух-трёх метрик. Для RAG: faithfulness + answer relevance. Для чат-бота: relevance + toxicity. Для агента: task completion. Добавлять по мере обнаружения конкретных проблем.

## Структура judge-промпта для оценки

Качество оценки определяется промптом. Рабочий шаблон для faithfulness:

```python
FAITHFULNESS_JUDGE_PROMPT = """You are an impartial judge evaluating the faithfulness
of an AI assistant's response.

Faithfulness means: every claim in the response is supported by the provided context.
Claims not found in context = unfaithful.

## Input
**User Question:** {question}
**Retrieved Context:** {context}
**AI Response:** {response}

## Task
1. Extract each factual claim from the AI Response
2. For each claim, check if it is supported by the Retrieved Context
3. A claim is SUPPORTED if the context contains evidence for it
4. A claim is UNSUPPORTED if the context does not mention it or contradicts it

## Output (JSON only)
{{
  "claims": [
    {{"claim": "...", "supported": true/false, "evidence": "..."}}
  ],
  "score": <float 0.0-1.0, ratio of supported claims to total claims>,
  "reasoning": "<one sentence summary>"
}}"""
```

Что здесь работает:

**Конкретные критерии.** «Оцени качество ответа» не работает. «Проверь, что каждый факт подтверждён контекстом» работает. Чем конкретнее инструкция, тем стабильнее оценки.

**Chain-of-thought.** Модель сначала извлекает claims, проверяет каждый, потом выставляет score. Без промежуточных шагов оценки нестабильны.

**Structured output.** JSON с фиксированной схемой, score от 0 до 1, reasoning в одно предложение. Упрощает парсинг и агрегацию.

## Реализация LLM-as-Judge: три подхода

### 1. Python + LLM API

Минимальная реализация без фреймворков:

```python
import json
from litellm import completion

def evaluate_faithfulness(question: str, context: str, response: str) -> dict:
    judge_response = completion(
        model="anthropic/claude-sonnet-4-6",
        messages=[{
            "role": "user",
            "content": FAITHFULNESS_JUDGE_PROMPT.format(
                question=question,
                context=context,
                response=response,
            )
        }],
        response_format={"type": "json_object"},
        temperature=0,
    )

    result = json.loads(judge_response.choices[0].message.content)
    return result

eval_result = evaluate_faithfulness(
    question="Какие кафе в центре Москвы?",
    context="Кофемания: Патриаршие пруды. Сёстры: Покровка 6.",
    response="Рекомендую Кофеманию на Патриарших и Пушкин на Тверском бульваре.",
)
# score: 0.5 (Кофемания подтверждена, Пушкин нет)
```

Плюсы: полный контроль, минимум зависимостей. Минусы: каждую метрику писать самостоятельно, нет батч-обработки. Если вы работаете с несколькими LLM-провайдерами, litellm позволяет переключаться между ними через единый интерфейс — подробнее об этом в статье о [мульти-провайдерной LLM-архитектуре](/ru/blog/multi-provider-llm-architecture/).

### 2. DeepEval

Open-source фреймворк со встроенными метриками. Работает как pytest для LLM-выходов.

```python
from deepeval import evaluate
from deepeval.test_case import LLMTestCase
from deepeval.metrics import (
    FaithfulnessMetric,
    AnswerRelevancyMetric,
    HallucinationMetric,
)

faithfulness = FaithfulnessMetric(threshold=0.7, model="gpt-5.4")
relevancy = AnswerRelevancyMetric(threshold=0.7, model="gpt-5.4")
hallucination = HallucinationMetric(threshold=0.5, model="gpt-5.4")

test_case = LLMTestCase(
    input="Какие кафе в центре Москвы?",
    actual_output="Рекомендую Кофеманию на Патриарших...",
    retrieval_context=["Кофемания: Патриаршие пруды. Сёстры: Покровка 6."],
)

results = evaluate([test_case], [faithfulness, relevancy, hallucination])
```

14+ встроенных метрик, интеграция с pytest. Тесты качества LLM запускаются вместе с юнит-тестами:

```python
# test_llm_quality.py
from deepeval import assert_test

def test_travel_recommendations():
    test_case = LLMTestCase(
        input="Кафе в Москве",
        actual_output=run_my_pipeline("Кафе в Москве"),
        retrieval_context=get_retrieved_docs("Кафе в Москве"),
    )
    assert_test(test_case, [faithfulness, relevancy])
```

### 3. Langfuse Evaluations

Если Langfuse уже используется для трейсинга, evaluations подключаются поверх. Judge-модель запускается по каждому трейсу, score привязывается к нему. Оценки можно привязывать как ко всему трейсу, так и к отдельным observations. Если вы ещё не настроили observability-стек, начните с [практического руководства по LLM observability с Langfuse](/ru/blog/llm-observability-langfuse/).

```python
langfuse.score(
    trace_id="trace-abc-123",
    name="faithfulness",
    value=0.85,
    comment="1 из 7 claims не подтверждён контекстом",
)
```

Для production-мониторинга Langfuse подходит лучше DeepEval: оценки привязаны к реальным трейсам, видны в дашборде, графики деградации качества по дням.

## Интеграция LLM-as-Judge в CI/CD и production pipeline

### Pre-deploy: регрессионное тестирование промптов

Изменился промпт? Прогнать dataset через judge-модель до деплоя. Score ниже порога, деплой заблокирован.

```yaml
# .github/workflows/llm-quality.yml
name: LLM Quality Gate
on: [pull_request]

jobs:
  eval:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install deepeval
      - run: deepeval test run test_llm_quality.py
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
```

### Runtime: gate перед ответом

Для критичных задач, оценка до отправки ответа:

```python
async def generate_with_quality_gate(question: str) -> str:
    response = await generate_response(question)

    eval_result = await evaluate_faithfulness(
        question=question,
        context=retrieved_context,
        response=response,
    )

    if eval_result["score"] < 0.7:
        return "Извините, я не уверен в точности ответа. Попробуйте переформулировать вопрос."

    return response
```

Дополнительный LLM-вызов на каждый запрос. GPT-5.4-mini в роли судьи стоит ~$0.15 за миллион входных токенов. На 10 000 запросов в день с промптом ~500 токенов: ~$0.75/день.

### Post-hoc: мониторинг по выборке

Самый распространённый сценарий. Оценка запускается асинхронно:

```python
import random

traces = langfuse.fetch_traces(limit=100)
sample = random.sample(traces.data, min(100, len(traces.data)))

scores = []
for trace in sample:
    result = evaluate_faithfulness(
        question=trace.input,
        context=trace.metadata.get("context", ""),
        response=trace.output,
    )
    scores.append(result["score"])
    langfuse.score(trace_id=trace.id, name="faithfulness", value=result["score"])

avg_score = sum(scores) / len(scores)
if avg_score < 0.75:
    send_alert(f"Faithfulness degraded: {avg_score:.2f}")
```

Дешевле runtime gate, зато ловит тренды. Средний faithfulness упал с 0.88 до 0.71 за неделю, значит что-то сломалось: промпт, retriever, обновление модели на стороне провайдера.

## Подводные камни LLM-as-Judge

### Position bias

Judge-модели систематически предпочитают ответ, стоящий первым при попарном сравнении. Zheng et al. (2023) зафиксировали сдвиг до 10-15%. Решение: запускать оценку дважды, меняя порядок, и усреднять. Или использовать pointwise scoring вместо pairwise.

### Verbosity bias

Длинные ответы получают более высокие оценки, даже если короткий ответ точнее. В judge-промпте явно указать «длина ответа не влияет на оценку» и добавить пример, где короткий ответ получает высший балл.

### Self-enhancement bias

GPT-4 ставит более высокие оценки текстам GPT-4. Claude предпочитает тексты Claude. Выход: judge-модель другого провайдера, чем generator. Генерация на GPT-5.4, оценка на Claude Sonnet. Или наоборот. Проблема доверия к LLM-выходам в целом — тема отдельного разговора, подробнее в статье [TruthGuard: когда AI-агенты врут](/ru/blog/truthguard-ai-agents-lie/).

### Стоимость

Каждая оценка это LLM-вызов. Для runtime gate на 10 000 запросов/день получается 10 000 дополнительных вызовов. Варианты: дешёвая модель как judge (GPT-5.4-mini, Claude Haiku), оценка по выборке, кеширование оценок для похожих пар.

### Judge тоже галлюцинирует

Judge-модель может поставить высокий score ответу с выдуманными фактами, если галлюцинация звучит правдоподобно. Частичное решение: chain-of-thought + structured output. Полного решения нет. Это фундаментальное ограничение подхода.

## Выбор модели-судьи для разных сценариев

| Сценарий | Judge-модель | Почему |
|----------|-------------|--------|
| Pre-deploy тесты | GPT-5.4 или Claude Sonnet 4.6 | Точность важнее скорости |
| Runtime gate | GPT-5.4-mini или Claude Haiku | Дёшево и быстро |
| Post-hoc мониторинг | GPT-5.4-mini | Массовая обработка |

Правило: judge-модель не слабее генератора. GPT-5.4-mini как judge для GPT-5.4-mini работает. GPT-5.4-mini как judge для Claude Opus ненадёжно.

`temperature=0` для judge-вызовов обязателен.

## Инструменты для LLM evaluation

| Инструмент | Фокус | LLM-as-Judge | Self-hosted | Цена |
|-----------|-------|-------------|-------------|------|
| **DeepEval** | Тестирование | 14+ метрик | Да (OSS) | Бесплатно |
| **Ragas** | RAG-оценка | Faithfulness, relevance | Да (OSS) | Бесплатно |
| **Langfuse** | Observability + evals | Evaluator templates | Да (OSS) | Бесплатно (self-hosted) |
| **Phoenix (Arize)** | Observability + evals | Hallucination, QA | Да (OSS) | Бесплатно |
| **Braintrust** | Evals + logging | Custom scorers | Cloud | Free tier |

Для стартапа: DeepEval для pre-deploy тестов + Langfuse для production мониторинга. Два open-source инструмента закрывают весь цикл.

## Production-сетап LLM-as-Judge

```
┌───────────────────────────────────────────────────┐
│                   CI/CD Pipeline                   │
│                                                    │
│  PR с изменением промпта                          │
│      │                                            │
│      ▼                                            │
│  DeepEval: dataset × new prompt → scores          │
│      │                                            │
│      ▼                                            │
│  Score < threshold? → Block merge                 │
└───────────────────────────────────────────────────┘

┌───────────────────────────────────────────────────┐
│                   Production                       │
│                                                    │
│  User request → LLM → Response → User             │
│                   │                                │
│                   ▼ (async)                        │
│              Langfuse trace                        │
│                   │                                │
│                   ▼ (cron, hourly)                 │
│         Judge evaluation (sample)                  │
│                   │                                │
│                   ▼                                │
│         Score dashboard + alerts                   │
└───────────────────────────────────────────────────┘
```

## С чего начать: пошаговый план

1. Выбрать одну метрику. Для RAG: faithfulness. Для чат-бота: answer relevance.
2. Собрать 20-30 примеров вручную: вопросы, ответы, оценки (хорошо/плохо). Golden dataset для калибровки.
3. Написать judge-промпт, прогнать по golden dataset. Совпадение с человеческими оценками ниже 70%? Править промпт.
4. Подключить DeepEval в CI для тестов при изменении промптов.
5. Настроить Langfuse evaluations для production мониторинга.

От нуля до рабочего quality gate: два-три дня. Golden dataset + judge-промпт: пара часов.

---

*Нужна помощь с настройкой quality gate для LLM в production? Я помогаю стартапам внедрять AI-решения и строить продукты — [belov.works](https://belov.works).*
