中文翻译暂不可用,显示俄语原文。

Что такое «Tool Degradation with Availability Masking» и как ее обнаружить?

Краткий тезис

Tool Degradation with Availability Masking — это ситуация, когда внешний инструмент (tool) возвращает формально корректные, но по сути невалидные данные (устаревшие, неполные или синтаксически верные, но семантически ошибочные), при этом availability check (например, HTTP 200) сигнализирует, что инструмент работает нормально. Агент, доверяя этому сигналу, продолжает использовать испорченные данные, что ведёт к каскадным ошибкам. Обнаружение требует комбинации трекинга состояния вызовов, анализа доли частичных ответов и корреляции с задержками.


1. Термин: Tool Degradation with Availability Masking

Tool Degradation — это постепенное или внезапное ухудшение качества данных, возвращаемых инструментом, при сохранении его формальной работоспособности. Availability Masking — эффект, при котором стандартная проверка доступности (ping, HTTP 200, статус «healthy») не отражает реального состояния данных: инструмент отвечает, но ответ бесполезен.

Пример: API погоды возвращает {"temperature": 25, "unit": "C"} (schema-valid), но данные вчерашние (stale). Агент, получив HTTP 200, считает, что всё в порядке, и строит на этом рекомендации.


2. Почему это критично в Agentic RAG

В Agentic RAG агент принимает решения на основе данных от нескольких инструментов (поиск, калькулятор, база знаний). Если один инструмент тихо деградирует:

  • Каскад ошибок: неверные данные искажают последующие вызовы.
  • Потеря доверия: пользователь получает неверный ответ, но система не сигнализирует о проблеме.
  • Сложность отладки: стандартные метрики (uptime, latency) не показывают деградацию.

Термин «Agentic RAG»: архитектура, где LLM-агент динамически выбирает и вызывает инструменты для сбора информации перед генерацией ответа.


3. Типы деградации инструментов

ТипОписаниеПример
Stale (устаревшие)Данные не обновляются, но формат корректенAPI курса валют возвращает курс недельной давности
Partial (неполные)Ответ содержит только часть ожидаемых полейПоиск документов возвращает только заголовки, без текста
Schema-valid but wrongДанные соответствуют схеме, но семантически неверныКалькулятор возвращает 2+2=5, но в формате JSON
Silent failureИнструмент возвращает успех, но внутренняя ошибка не логируетсяБаза данных возвращает пустой массив вместо ошибки соединения

Availability Masking возникает, когда health check (HTTP 200, {"status": "ok"}) не различает эти состояния.


4. Как Availability Masking маскирует проблему

Стандартный availability check проверяет только:

  • Доступность эндпоинта (TCP-соединение)
  • HTTP-статус (200 vs 5xx)
  • Время ответа (не превышает таймаут)

Он не проверяет:

  • Актуальность данных (timestamp, версия)
  • Полноту ответа (наличие обязательных полей)
  • Семантическую корректность (логику вычислений)

Агент, получив {"status": "ok"}, считает инструмент здоровым и передаёт его ответ в следующий шаг. Это и есть masking — маскировка деградации под正常工作.


5. Детекция: трекинг состояния tool вызовов

Необходимо вести логи всех вызовов инструментов с метаданными:

  • Время запроса и ответа
  • HTTP-статус и заголовки
  • Полный payload запроса и ответа
  • Версия схемы ответа
  • Идентификатор сессии агента

На основе логов строятся метрики состояния:

# Пример структуры лога
tool_call = {
    "tool_name": "weather_api",
    "timestamp": "2025-03-15T10:30:00Z",
    "http_status": 200,
    "response_size": 512,
    "response_fields": ["temperature", "humidity"],
    "expected_fields": ["temperature", "humidity", "wind_speed"],
    "data_timestamp": "2025-03-14T12:00:00Z",  # stale?
    "latency_ms": 120
}

Трекинг позволяет выявить аномалии: например, поле wind_speed перестало приходить, хотя ожидается.


6. Детекция: partial-response rate

Partial-response rate — доля вызовов, где ответ содержит не все ожидаемые поля или данные урезаны.

Формула:

partial_rate = (число вызовов с неполным ответом) / (общее число вызовов) * 100%

Пороги тревоги:

  • >5% — жёлтый флаг (проверить)
  • >20% — красный флаг (остановить использование инструмента)

Реализация:

def check_partial(response, expected_schema):
    missing = [f for f in expected_schema if f not in response]
    if missing:
        return True, missing
    return False, []

Агент должен логировать partial и при превышении порога переключаться на резервный инструмент или запрашивать подтверждение у пользователя.


7. Детекция: корреляция с latency

Часто деградация сопровождается изменением задержки:

  • Stale данные: latency может быть подозрительно низкой (кэш не обновляется).
  • Partial ответы: latency может быть аномально высокой (инструмент пытается, но не может собрать все данные).
  • Schema-valid but wrong: latency может быть нормальной, но корреляция с другими метриками (например, частотой ошибок downstream) укажет на проблему.

Метод: построить скользящее среднее latency за окно (например, 10 минут) и сравнивать с baseline. Если latency выходит за 2 сигмы, а partial-rate растёт — высока вероятность Tool Degradation with Availability Masking.

import numpy as np

def detect_anomaly(latency_history, baseline_mean, baseline_std):
    z_score = (latency_history[-1] - baseline_mean) / baseline_std
    return abs(z_score) > 2

8. Инструменты и метрики для мониторинга

ИнструментНазначение
Prometheus + GrafanaСбор и визуализация метрик (latency, partial-rate, HTTP status)
OpenTelemetryТрассировка вызовов инструментов внутри агента
ELK / LokiЦентрализованное хранение логов с поиском по partial-ответам
Custom health checkРасширенный health endpoint, возвращающий не только статус, но и метаданные (версия данных, время последнего обновления)

Метрики для дашборда:

  • tool_partial_responses_total — счётчик неполных ответов
  • tool_staleness_seconds — разница между текущим временем и временем данных
  • tool_latency_seconds — гистограмма задержек
  • tool_availability_mask — 1 если HTTP 200, но partial > порога

9. Стратегии предотвращения и mitigation

  1. Расширенный health check: инструмент должен возвращать не только status: ok, но и data_freshness, schema_version, coverage.
  2. Валидация ответа на стороне агента: перед использованием проверять схему, свежесть, полноту.
  3. Graceful degradation: при обнаружении деградации агент переключается на резервный инструмент или сообщает пользователю о возможной неточности.
  4. Circuit breaker: если partial-rate превышает порог, временно отключать инструмент и уведомлять команду.
  5. Асинхронная верификация: периодически отправлять тестовые запросы с известным ответом и сравнивать.

10. Пример кода: детекция на стороне агента

import time
from typing import Dict, Any

class ToolMonitor:
    def __init__(self, tool_name: str, expected_schema: list, max_staleness: int = 3600):
        self.tool_name = tool_name
        self.expected_schema = expected_schema
        self.max_staleness = max_staleness
        self.partial_count = 0
        self.total_count = 0
        self.latency_history = []

    def check_response(self, response: Dict[str, Any], latency_ms: float) -> bool:
        self.total_count += 1
        self.latency_history.append(latency_ms)

        # 1. Проверка полноты
        missing = [f for f in self.expected_schema if f not in response]
        if missing:
            self.partial_count += 1
            print(f"WARNING: {self.tool_name} missing fields: {missing}")
            return False

        # 2. Проверка свежести (если есть timestamp)
        if "timestamp" in response:
            age = time.time() - response["timestamp"]
            if age > self.max_staleness:
                print(f"WARNING: {self.tool_name} data stale ({age}s old)")
                return False

        # 3. Проверка аномалии latency
        if len(self.latency_history) > 10:
            mean = sum(self.latency_history[-10:]) / 10
            if abs(latency_ms - mean) > 2 * (sum((x-mean)**2 for x in self.latency_history[-10:])/10)**0.5:
                print(f"WARNING: {self.tool_name} latency anomaly: {latency_ms}ms")
                # Не возвращаем False, но логируем

        return True

    @property
    def partial_rate(self) -> float:
        return self.partial_count / self.total_count if self.total_count else 0.0

Пет-проект для закрепления

Задача: Реализовать симулятор агента, который вызывает три инструмента (погода, курс валют, поиск новостей). Один из инструментов периодически деградирует (возвращает stale или partial данные), но health check всегда 200. Написать мониторинг, который обнаруживает маскировку и переключает агента на резервный источник.

Инструменты: Python, aiohttp для вызовов API, prometheus_client для метрик, asyncio для асинхронной работы.

Шаги:

  1. Создать три mock-API с возможностью включать деградацию (параметр degradation_mode).
  2. Реализовать агента, который последовательно вызывает инструменты и принимает решение.
  3. Внедрить ToolMonitor для каждого вызова.
  4. Настроить сбор метрик (partial-rate, latency, staleness) и вывод в консоль или Grafana.
  5. Написать скрипт, который включает деградацию на 30 секунд и проверяет, что агент переключился на резерв.

Ожидаемый результат: Дашборд с метриками, где видно, как partial-rate растёт, а latency падает (stale кэш). Агент логирует предупреждения и использует fallback.


Связь с другими вопросами

ВопросТема
165Что такое Agentic RAG и как он отличается от обычного RAG?
166Как проектировать систему tool use для агента?
167Что такое tool calling и как обрабатывать ошибки вызова?
169Как тестировать надёжность агента при сбоях инструментов?
170Какие метрики качества для Agentic RAG вы знаете?
151Как организовать observability в RAG-системе?

Навигация