Введение: зачем вашим AI-агентам наблюдаемость
Итак, вы научились создавать AI-агентов с Function Calling, строить RAG-пайплайны, собирать мульти-агентные системы и управлять их памятью. Всё здорово. Но рано или поздно возникает неудобный вопрос: а как вообще понять, что всё это работает правильно в production?
Классическое тестирование ПО тут не спасёт. AI-агенты — штука вероятностная: один и тот же запрос может выдать совершенно разные результаты, агент может выбрать не тот инструмент, начать «галлюцинировать» или зациклиться в бесконечных рассуждениях. По данным индустриальных исследований 2026 года, 89% организаций уже внедряют observability для своих агентных систем. А основной барьер при выводе агентов в production — проблемы с качеством, которые стоят за 32% всех инцидентов.
Честно говоря, это одна из тех тем, которые откладываешь «на потом» — пока не столкнёшься с реальной проблемой в production. Не надо так.
В этом руководстве мы разберём полный стек наблюдаемости и оценки AI-агентов: от базового трейсинга через OpenTelemetry до автоматической оценки качества с помощью LLM-as-a-Judge и фреймворка DeepEval. Все примеры — на Python, с рабочим кодом, который можно адаптировать под свои проекты.
Три кита наблюдаемости LLM-систем
Если вы знакомы с классической наблюдаемостью (Prometheus, Grafana, Jaeger), то для LLM-систем принцип тот же — три компонента. Но со своей спецификой.
Логи (Logs)
Можно назвать их «дневником агента» — атомарные записи о каждом событии. Только для LLM-систем это не просто текстовые строки, а структурированные записи:
- Входной промпт и системное сообщение
- Ответ модели (полный текст или structured output)
- Название вызванного инструмента и его параметры
- Результат выполнения инструмента
- Ошибки и исключения
Трейсы (Traces)
Трейсы показывают всю цепочку выполнения агентного запроса целиком. Один запрос пользователя может породить десятки шагов: LLM-вызов → выбор инструмента → API-запрос → повторный вызов LLM для обработки результата → генерация ответа. Трейс объединяет все эти шаги в единую timeline с вложенными span-ами и показывает причинно-следственные связи и узкие места.
По сути, это рентген вашего агента — без него вы просто гадаете, что пошло не так.
Метрики (Metrics)
Числовые показатели, агрегированные во времени:
- Латентность — время от запроса до ответа (p50, p95, p99)
- Потребление токенов — количество input/output токенов на запрос
- Стоимость — расчётная стоимость в долларах на запрос
- Частота ошибок — процент запросов с ошибками или таймаутами
- Task Success Rate — доля успешно завершённых задач
Трейсинг с OpenTelemetry: практическая реализация
OpenTelemetry (OTel) к 2026 году стал де-факто стандартом для инструментирования LLM-систем. Его главное преимущество — вендор-нейтральность: инструментируете код один раз, а потом подключаете любой бэкенд — Langfuse, LangSmith, Datadog, Jaeger или Grafana. Никакого vendor lock-in.
OpenLLMetry: OpenTelemetry для LLM
OpenLLMetry — набор расширений поверх стандартного OpenTelemetry, заточенных под LLM-провайдеры (OpenAI, Anthropic, Cohere) и векторные БД (Chroma, Pinecone, Qdrant). Он автоматически перехватывает вызовы к API моделей и формирует трейсы без модификации вашего кода. Звучит как магия, но работает на удивление надёжно.
Установка и настройка с Langfuse в качестве бэкенда:
# Установка зависимостей
pip install openai traceloop-sdk langfuse
import os
import base64
from traceloop.sdk import Traceloop
# Конфигурация Langfuse
LANGFUSE_PUBLIC_KEY = "pk-lf-..."
LANGFUSE_SECRET_KEY = "sk-lf-..."
LANGFUSE_AUTH = base64.b64encode(
f"{LANGFUSE_PUBLIC_KEY}:{LANGFUSE_SECRET_KEY}".encode()
).decode()
os.environ["TRACELOOP_BASE_URL"] = (
"https://cloud.langfuse.com/api/public/otel"
)
os.environ["TRACELOOP_HEADERS"] = (
f"Authorization=Basic {LANGFUSE_AUTH}"
)
os.environ["OPENAI_API_KEY"] = "sk-..."
# Инициализация — все вызовы OpenAI будут трейситься автоматически
Traceloop.init(disable_batch=True)
Теперь любой вызов OpenAI SDK автоматически отправляет трейсы в Langfuse:
from openai import OpenAI
client = OpenAI()
# Этот вызов будет автоматически оттрейсен
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "Ты — аналитик финансовых данных."},
{"role": "user", "content": "Какие основные риски инвестиций в AI-стартапы?"}
]
)
print(response.choices[0].message.content)
Вот и всё — три строчки настройки, и у вас полноценный трейсинг. Серьёзно, это одна из тех вещей, которые нужно было сделать ещё вчера.
Кастомные span-ы для агентных циклов
Для более сложных агентов вам понадобятся собственные span-ы — чтобы трейсить шаги рассуждений, вызовы инструментов и промежуточные результаты:
from opentelemetry import trace
from traceloop.sdk.decorators import workflow, task, agent
tracer = trace.get_tracer("ai-agent")
@workflow(name="customer_support_agent")
def handle_customer_query(query: str) -> str:
"""Основной workflow агента поддержки."""
# Шаг 1: Классификация запроса
category = classify_query(query)
# Шаг 2: Выбор и вызов инструмента
tool_result = execute_tool(category, query)
# Шаг 3: Генерация финального ответа
response = generate_response(query, tool_result)
return response
@task(name="classify_query")
def classify_query(query: str) -> str:
"""Классификация запроса пользователя."""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Классифицируй запрос: billing, technical, general"},
{"role": "user", "content": query}
]
)
return response.choices[0].message.content.strip()
@task(name="execute_tool")
def execute_tool(category: str, query: str) -> dict:
"""Выполнение инструмента на основе категории."""
with tracer.start_as_current_span("tool_selection") as span:
span.set_attribute("tool.category", category)
if category == "billing":
result = lookup_billing_info(query)
elif category == "technical":
result = search_knowledge_base(query)
else:
result = {"info": "Общая информация"}
span.set_attribute("tool.result_size", len(str(result)))
return result
@task(name="generate_response")
def generate_response(query: str, context: dict) -> str:
"""Генерация ответа на основе контекста."""
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": f"Контекст: {context}"},
{"role": "user", "content": query}
]
)
return response.choices[0].message.content
Каждый из декораторов @workflow, @task, @agent создаёт вложенный span в трейсе. В Langfuse (или любом другом OTel-совместимом бэкенде) вы увидите полную иерархию выполнения: какой инструмент был выбран, сколько времени занял каждый LLM-вызов, какие параметры были переданы.
Оценка AI-агентов: два уровня анализа
Наблюдаемость отвечает на вопрос «что происходит?». Но есть ещё один, не менее важный: «насколько хорошо это работает?». Тут на сцену выходит оценка (evaluation) — систематическое измерение качества работы агента.
Уровень 1: Чёрный ящик (End-to-End)
Смотрим только на вход и выход: получил ли пользователь то, что хотел?
- Task Success Rate — процент задач, которые агент реально решил
- User Satisfaction — оценка удовлетворённости (через обратную связь или косвенные метрики)
- Response Quality — точность, полнота, релевантность ответа
Уровень 2: Стеклянный ящик (Component-Level)
Когда end-to-end результат плохой, пора «открывать капот» и смотреть, что внутри:
- Слой рассуждений (Reasoning Layer) — правильно ли модель поняла задачу? Адекватен ли план?
- Слой действий (Action Layer) — вызван ли правильный инструмент? Корректны ли параметры?
- RAG-компонент (если есть) — релевантны ли извлечённые документы? Верен ли ответ относительно контекста?
Именно покомпонентная оценка помогает найти корневую причину проблемы. Агент вполне может выдать правильно выглядящий ответ, но при этом опираться не на тот источник данных. End-to-end тест такое не поймает, а проверка Tool Correctness — да.
LLM-as-a-Judge: автоматическая оценка качества
Ручная оценка не масштабируется — это факт. Если ваш агент обрабатывает тысячи запросов в день, нанять армию ревьюеров нереально. Решение — LLM-as-a-Judge: мощная модель (GPT-4o, Claude Sonnet) оценивает выходы другой модели по заданным критериям.
Как это работает
Модель-судья получает:
- Исходный запрос пользователя
- Ответ оцениваемого агента
- Критерии оценки (рубрику)
- Опционально — эталонный ответ или контекст
На выходе — числовая оценка и обоснование. Исследования показывают, что GPT-4 как судья достигает 80% согласия с оценками людей. Это, к слову, сопоставимо с согласием между двумя людьми-оценщиками — мы сами не так уж консистентны в оценках.
Три техники LLM-as-a-Judge
G-Eval — наиболее гибкая техника. Судье даётся набор критериев и пошаговая инструкция оценки (chain-of-thought). Отлично подходит для кастомных метрик: тон бренда, полезность, следование формату.
QAG (Question-Answer Generation) — разбивает ответ на атомарные утверждения, проверяет каждое отдельно, затем агрегирует результаты. Оценки получаются более детерминированными, чем у G-Eval.
DAG (Deep Acyclic Graph) — использует дерево решений, где каждый узел содержит проверку. Листовые узлы возвращают финальную оценку. Самый предсказуемый из трёх подходов.
Ограничения и подводные камни
LLM-as-a-Judge — мощный инструмент, но не без подводных камней:
- Предвзятость к многословным ответам — судьи часто предпочитают длинные ответы, даже если короткий точнее (знакомо, правда?)
- Позиционная предвзятость — при pairwise-сравнении первый вариант часто получает преимущество
- Дрифт судьи — обновления API могут изменить поведение модели-судьи, так что фиксируйте версии и проводите калибровку
- Падение точности в узких доменах — в специализированных областях согласие с экспертами падает на 10–15%
Практический совет: для критичных оценок стоит использовать мажоритарное голосование нескольких моделей-судей (GPT-4, Claude, Llama-3). Это снижает предвзятость на 30–40%, хотя и бьёт по кошельку.
DeepEval: практическая оценка на Python
DeepEval — open-source фреймворк для оценки LLM-систем, построенный по принципу Pytest. Более 50 метрик из коробки, поддержка агентов, RAG-пайплайнов и чат-ботов. По моему опыту, это один из самых удобных инструментов для старта.
Установка и базовая настройка
# Установка
pip install deepeval
# DeepEval использует LLM-as-a-Judge, нужен API-ключ
export OPENAI_API_KEY="sk-..."
# Можно использовать другие модели через переменные окружения:
# ANTHROPIC_API_KEY, AZURE_OPENAI_API_KEY и т.д.
Базовая оценка с G-Eval
Давайте создадим кастомную метрику для оценки полезности ответа:
from deepeval.metrics import GEval
from deepeval.test_case import LLMTestCase, LLMTestCaseParams
from deepeval import evaluate
# Определяем кастомную метрику
helpfulness_metric = GEval(
name="Helpfulness",
criteria="Определи, насколько ответ полезен и практичен для пользователя.",
evaluation_steps=[
"Проверь, отвечает ли ответ на конкретный вопрос пользователя",
"Оцени, содержит ли ответ практические шаги или примеры",
"Проверь, нет ли в ответе лишней информации, не относящейся к вопросу",
"Оцени, достаточно ли подробен ответ для выполнения задачи"
],
evaluation_params=[
LLMTestCaseParams.INPUT,
LLMTestCaseParams.ACTUAL_OUTPUT
],
threshold=0.7
)
# Создаём тест-кейс
test_case = LLMTestCase(
input="Как настроить мониторинг LLM-приложения?",
actual_output="Для мониторинга LLM-приложения используйте OpenTelemetry: "
"1) Установите traceloop-sdk, "
"2) Инициализируйте Traceloop.init(), "
"3) Все вызовы к OpenAI будут автоматически трейситься. "
"Подключите Langfuse или Datadog как бэкенд для визуализации."
)
# Запуск оценки
helpfulness_metric.measure(test_case)
print(f"Оценка: {helpfulness_metric.score}")
print(f"Обоснование: {helpfulness_metric.reason}")
Обратите внимание на evaluation_steps — это, по сути, chain-of-thought инструкция для модели-судьи. Чем конкретнее шаги, тем стабильнее оценки.
Метрика Tool Correctness для агентов
Одна из самых ценных метрик для агентных систем — проверка правильности вызовов инструментов. И вот что особенно приятно: эта метрика детерминированна и бесплатна (не требует LLM-вызова). Идеальный первый рубеж защиты.
from deepeval.metrics import ToolCorrectnessMetric
from deepeval.test_case import LLMTestCase, ToolCall
# Инструменты, которые агент фактически вызвал
tools_called = [
ToolCall(
name="search_knowledge_base",
input_parameters={"query": "настройка SSL-сертификата", "limit": 5},
output="Найдено 3 статьи о настройке SSL..."
),
ToolCall(
name="get_customer_info",
input_parameters={"customer_id": "C-12345"},
output="Клиент: ООО Рога и Копыта, тариф: Enterprise"
)
]
# Ожидаемые инструменты (эталон)
expected_tools = [
ToolCall(
name="search_knowledge_base",
input_parameters={"query": "настройка SSL-сертификата", "limit": 5}
),
ToolCall(
name="get_customer_info",
input_parameters={"customer_id": "C-12345"}
)
]
metric = ToolCorrectnessMetric(
should_consider_ordering=True, # порядок вызовов важен
should_exact_match=False # допускаем незначительные различия
)
test_case = LLMTestCase(
input="У клиента C-12345 проблемы с SSL-сертификатом",
actual_output="Для решения проблемы с SSL...",
tools_called=tools_called,
expected_tools=expected_tools
)
metric.measure(test_case)
print(f"Tool Correctness: {metric.score}") # 1.0 — все инструменты верны
Метрика Task Completion
Главная end-to-end метрика для агентов — завершение задачи. В DeepEval она работает через анализ LLM-трейса:
from deepeval.metrics import TaskCompletionMetric
from deepeval.tracing import observe, update_current_span
from deepeval.test_case import LLMTestCase
from deepeval.dataset import Golden
from deepeval import evaluate
task_completion = TaskCompletionMetric(threshold=0.7)
@observe(metrics=[task_completion])
def customer_support_agent(query: str) -> str:
"""Агент поддержки с трейсингом для оценки."""
# Шаг 1: Поиск в базе знаний
context = search_knowledge_base(query)
# Шаг 2: Генерация ответа
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": f"Контекст: {context}"},
{"role": "user", "content": query}
]
)
result = response.choices[0].message.content
update_current_span(
test_case=LLMTestCase(input=query, actual_output=result)
)
return result
# Запуск оценки с набором тестовых данных
goldens = [
Golden(input="Как сбросить пароль?"),
Golden(input="Какой у меня тариф?"),
Golden(input="Не работает API-ключ, помогите"),
]
results = evaluate(
observed_callback=customer_support_agent,
goldens=goldens
)
print(results)
Оценка RAG-компонента: Faithfulness и Answer Relevancy
Если ваш агент использует RAG, критически важно оценивать два аспекта: опирается ли ответ на извлечённый контекст (faithfulness) и отвечает ли он на заданный вопрос (answer relevancy). Пренебрегать этим — значит однажды обнаружить, что агент уверенно выдаёт ответы «из головы», полностью игнорируя базу знаний.
from deepeval.metrics import (
FaithfulnessMetric,
AnswerRelevancyMetric,
HallucinationMetric
)
from deepeval.test_case import LLMTestCase
from deepeval import evaluate
# Метрики для RAG-компонента
faithfulness = FaithfulnessMetric(threshold=0.7)
relevancy = AnswerRelevancyMetric(threshold=0.7)
hallucination = HallucinationMetric(threshold=0.5)
# Тест-кейс с контекстом (retrieval context)
test_case = LLMTestCase(
input="Какова максимальная длина контекста у GPT-4o?",
actual_output="Максимальная длина контекста у GPT-4o составляет "
"128 000 токенов. Это позволяет обрабатывать документы "
"объёмом до 300 страниц за один запрос.",
retrieval_context=[
"GPT-4o поддерживает контекстное окно размером 128 000 токенов. "
"Модель доступна через API OpenAI с ценой $2.50 за 1M input-токенов."
]
)
# Запуск всех метрик
evaluate(
test_cases=[test_case],
metrics=[faithfulness, relevancy, hallucination]
)
Мониторинг в production: собираем всё вместе
Ладно, теория — это хорошо. Давайте объединим трейсинг и оценку в единый production-пайплайн. Общая схема такая:
- Трейсинг — каждый запрос автоматически инструментируется через OpenTelemetry
- Асинхронная оценка — трейсы отправляются на бэкенд, где запускается оценка метрик
- Алертинг — при падении метрик ниже порога срабатывает уведомление
- Feedback loop — реальные провалы конвертируются в тестовые датасеты
Production-конфигурация с Langfuse + DeepEval
import os
from langfuse import Langfuse
from deepeval.metrics import GEval, FaithfulnessMetric
from deepeval.test_case import LLMTestCase, LLMTestCaseParams
# Инициализация Langfuse для трейсинга
langfuse = Langfuse(
public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
host="https://cloud.langfuse.com"
)
# Метрика качества ответа
quality_metric = GEval(
name="ResponseQuality",
criteria="Оцени качество ответа агента поддержки.",
evaluation_steps=[
"Ответ должен быть точным и соответствовать контексту",
"Ответ должен быть практичным и содержать конкретные шаги",
"Ответ не должен содержать галлюцинаций"
],
evaluation_params=[
LLMTestCaseParams.INPUT,
LLMTestCaseParams.ACTUAL_OUTPUT,
LLMTestCaseParams.RETRIEVAL_CONTEXT
],
threshold=0.7
)
def evaluate_agent_response(
query: str,
response: str,
context: list[str],
trace_id: str
) -> dict:
"""Оценка ответа агента с логированием в Langfuse."""
test_case = LLMTestCase(
input=query,
actual_output=response,
retrieval_context=context
)
quality_metric.measure(test_case)
# Логируем оценку в Langfuse
langfuse.score(
trace_id=trace_id,
name="response_quality",
value=quality_metric.score,
comment=quality_metric.reason
)
return {
"score": quality_metric.score,
"reason": quality_metric.reason,
"passed": quality_metric.score >= quality_metric.threshold
}
Ключевые метрики для дашборда
Вот минимальный набор метрик, который стоит вынести на production-дашборд AI-агента:
| Метрика | Тип | Порог алерта | Описание |
|---|---|---|---|
| Task Success Rate | End-to-end | < 85% | Доля успешных задач |
| Tool Correctness | Component | < 90% | Правильность вызовов инструментов |
| Faithfulness | RAG | < 0.7 | Верность ответа контексту |
| Hallucination Rate | RAG | > 0.3 | Частота галлюцинаций |
| p95 Latency | Инфраструктура | > 10s | Время ответа (95-й перцентиль) |
| Cost per Query | Бизнес | > $0.15 | Стоимость одного запроса |
| Token Usage | Инфраструктура | Аномалии | Потребление токенов |
Семь метрик — не так уж много, но этого хватает, чтобы покрыть все ключевые аспекты. Начните с этого набора, а дальше добавляйте по мере необходимости.
Инструменты наблюдаемости: сравнение платформ 2026
Выбор платформы зависит от ваших приоритетов. Вот краткий обзор основных решений.
Langfuse (Open Source)
Открытый исходный код, поддержка OpenTelemetry, встроенные evaluator-ы (Hallucination, Context-Relevance, Toxicity). Идеален для команд, которые хотят полный контроль и возможность self-hosted развёртывания. Бесплатный план покрывает до 50K наблюдений в месяц — для старта более чем достаточно.
LangSmith
Платформа от LangChain с глубокой интеграцией в экосистему LangChain/LangGraph. При этом фреймворк-агностична — работает и с OpenAI SDK, и с Anthropic SDK, и с LlamaIndex. Особенно сильна в трейсинге сложных агентных цепочек.
Datadog LLM Observability
Для enterprise-команд, которые уже живут в экосистеме Datadog. Полная интеграция с существующими дашбордами и алертингом. End-to-end трейсинг от HTTP-запроса до LLM-вызова — всё в одном окне.
Arize AI / Phoenix
Arize Phoenix — open-source инструмент с фокусом на embeddings-анализ и drift-detection. Enterprise-платформа обрабатывает более 1 триллиона инференсов в месяц. Построена на OpenTelemetry-стандартах.
DeepEval + Confident AI
Open-source фреймворк для оценки + облачная платформа для визуализации результатов. При каждом запуске агента автоматически экспортирует трейсы и запускает оценку метрик. Пожалуй, лучший выбор, если вам нужна глубокая интеграция тестирования в CI/CD.
Цикл надёжности агента: от трейса к улучшению
Лучшие практики 2026 года сводятся к концепции Agent Reliability Loop — замкнутого цикла улучшения. Идея проста, но дисциплина требуется железная:
- Трейсь каждый запрос — никаких «слепых зон» в production
- Конвертируй провалы в датасеты — каждый реальный инцидент становится тестовым кейсом
- Запускай оценку — автоматически через LLM-as-a-Judge и детерминированные метрики
- Блокируй регрессии — интегрируй оценку в CI/CD, не пропускай изменения, ухудшающие качество
- Продвигай только лучшие изменения — через версионированные релизы промптов и моделей
# Пример интеграции с CI/CD через deepeval CLI
# В файле test_agent.py:
from deepeval import assert_test
from deepeval.test_case import LLMTestCase
from deepeval.metrics import (
TaskCompletionMetric,
ToolCorrectnessMetric,
FaithfulnessMetric
)
def test_billing_query():
"""Тест: агент корректно обрабатывает запрос о биллинге."""
test_case = LLMTestCase(
input="Сколько стоит мой текущий тариф?",
actual_output=run_agent("Сколько стоит мой текущий тариф?"),
expected_tools=[
ToolCall(name="get_customer_info"),
ToolCall(name="get_pricing_plans")
],
tools_called=get_last_trace_tools()
)
assert_test(test_case, metrics=[
TaskCompletionMetric(threshold=0.8),
ToolCorrectnessMetric()
])
# Запуск в CI/CD:
# deepeval test run test_agent.py --verbose
Этот тест упадёт, если агент не выполнил задачу или вызвал не те инструменты. И вы узнаете об этом до деплоя, а не от разгневанных пользователей.
FAQ: часто задаваемые вопросы
Чем наблюдаемость LLM отличается от обычного мониторинга приложений?
Классический APM отслеживает латентность, ошибки и throughput. Наблюдаемость LLM добавляет специфичные для AI метрики: потребление токенов, стоимость вызовов, качество генерации (галлюцинации, faithfulness), корректность выбора инструментов и степень завершения задач. Ключевое отличие — вероятностная природа LLM: один и тот же запрос может дать разные результаты, и поэтому без специализированных метрик качества не обойтись.
Какой минимальный набор метрик нужен для production AI-агента?
Начните с трёх: Task Success Rate (end-to-end), Tool Correctness (компонентный уровень) и p95 Latency (инфраструктура). Если агент использует RAG — добавьте Faithfulness. Для контроля расходов — Cost per Query. Этих пяти метрик хватит, чтобы обнаружить 90% проблем на раннем этапе.
LLM-as-a-Judge — насколько можно доверять оценкам модели?
GPT-4 как судья показывает 80% согласия с оценками людей — что сопоставимо с согласием между двумя людьми-оценщиками. Но есть ограничения: предвзятость к длинным ответам, падение точности в узких доменах (на 10–15%) и дрифт при обновлениях модели. Используйте LLM-as-a-Judge для скрининга и масштабного тестирования, а человеческую оценку — для финальной валидации критичных сценариев.
Можно ли использовать open-source модели в качестве судьи вместо GPT-4?
Да, и в 2026 году это вполне реалистично. Llama 3 и Mistral Large показывают хорошие результаты в роли судей. DeepEval поддерживает любые модели через интерфейс DeepEvalBaseLLM или LiteLLM. Для критичных оценок рекомендуется мажоритарное голосование нескольких моделей — это снижает предвзятость на 30–40%.
Как интегрировать оценку AI-агентов в CI/CD-пайплайн?
DeepEval предоставляет CLI-команду deepeval test run, которая работает по аналогии с pytest. Создайте файлы с тестами, определите тест-кейсы с пороговыми значениями метрик и запускайте их в CI при каждом изменении промпта или конфигурации агента. Если метрики падают ниже порога — пайплайн блокирует деплой. Это так называемый «quality gate», и в 2026 году это уже стандартная практика для production AI-систем.