0Pricing
AI Engineering Academy · Lección

Alertas sobre latencia, costes y degradación de la calidad

Defina umbrales de alerta para la latencia p99, el coste por solicitud y las puntuaciones de calidad automatizadas, y envíe las alertas a Slack o PagerDuty cuando su pipeline de LLM se degrade.

Alertas sobre latencia, costes y degradación de la calidad es una lección gratuita de AI Engineering Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Engineering Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Engineering Academy incluye 4 lecciones en total.

Por qué son importantes las alertas en los sistemas de LLM

Las aplicaciones de LLM fallan de formas sutiles y graduales. Un cambio en un prompt podría aumentar la latencia media un 30 %, una mejora en la recuperación podría reducir ligeramente la calidad de las respuestas o un aumento repentino del uso podría multiplicar por cinco los costes diarios con respecto al presupuesto. Sin alertas proactivas, descubrirá estos problemas únicamente cuando los usuarios se quejen o llegue la factura mensual. Las alertas transforman la resolución reactiva de problemas en operaciones proactivas.

Las tres categorías de alertas

Las alertas de las aplicaciones de LLM se dividen en tres categorías. Las alertas de latencia se activan cuando el tiempo de respuesta supera un umbral de experiencia de usuario (por ejemplo, p99 > 10 segundos). Las alertas de coste se activan cuando el coste por solicitud o el gasto diario supera los umbrales presupuestarios, evitando sorpresas en la factura. Las alertas de calidad se activan cuando las métricas de calidad automatizadas (puntuaciones de LLM-as-judge, índices de satisfacción de los usuarios y puntuaciones de fidelidad) caen por debajo del mínimo aceptable. Cada categoría requiere una instrumentación y unos canales de alerta diferentes.

from dataclasses import dataclass

@dataclass
class AlertThresholds:
    # Latency (milliseconds)
    p50_latency_ms: int = 2000    # median should be under 2s
    p99_latency_ms: int = 10000   # 99th percentile under 10s
    # Cost (USD)
    max_cost_per_request: float = 0.05  # alert if one request costs > 5 cents
    max_daily_spend: float = 50.00      # alert if daily spend exceeds $50
    # Quality (0.0 to 1.0 scale)
    min_quality_score: float = 0.75     # alert if rolling avg drops below 75%
    min_faithfulness: float = 0.80      # alert if RAGAS faithfulness drops below 80%

DEFAULT_THRESHOLDS = AlertThresholds()

Recopilación de métricas de latencia

Para crear alertas de latencia, primero debe recopilarla de forma coherente. Mida por separado tres componentes de latencia: el tiempo hasta el primer token (TTFT, fundamental para la experiencia de usuario en streaming), el tiempo total de respuesta y las latencias de cada paso de recuperación y generación. Almacene estos datos como series temporales (un punto de datos por solicitud) para poder calcular percentiles y medias móviles de los últimos N minutos u horas.

import time
from collections import deque
from statistics import quantiles

class LatencyTracker:
    def __init__(self, window_size=100):
        self.window = deque(maxlen=window_size)  # rolling window of latencies

    def record(self, latency_ms: float):
        self.window.append(latency_ms)

    def p50(self) -> float:
        if not self.window:
            return 0
        return quantiles(self.window, n=100)[49]

    def p99(self) -> float:
        if not self.window:
            return 0
        return quantiles(self.window, n=100)[98]

    def check_alert(self, thresholds: AlertThresholds) -> list[str]:
        alerts = []
        if self.p99() > thresholds.p99_latency_ms:
            alerts.append(f'p99 latency {self.p99():.0f}ms exceeds {thresholds.p99_latency_ms}ms')
        if self.p50() > thresholds.p50_latency_ms:
            alerts.append(f'p50 latency {self.p50():.0f}ms exceeds {thresholds.p50_latency_ms}ms')
        return alerts

latency_tracker = LatencyTracker()

Seguimiento y alertas de costes

La supervisión de costes requiere realizar un seguimiento del gasto con varios niveles de granularidad: coste por solicitud (para detectar consultas atípicas costosas), totales por hora y por día (para detectar picos de uso) y coste por funcionalidad (para identificar qué parte de la aplicación es más cara). Active alertas inmediatamente ante anomalías en el coste por solicitud y utilice comprobaciones programadas para los límites presupuestarios diarios.

from datetime import datetime, date
import threading

class CostTracker:
    def __init__(self):
        self._lock = threading.Lock()
        self._daily_spend = {}  # date -> total USD
        self._per_request = []  # list of (timestamp, cost)

    def record(self, cost_usd: float) -> list[str]:
        today = date.today().isoformat()
        alerts = []
        
        with self._lock:
            # Track daily spend
            self._daily_spend[today] = self._daily_spend.get(today, 0) + cost_usd
            self._per_request.append((datetime.now(), cost_usd))
        
        # Alert on expensive single requests
        if cost_usd > DEFAULT_THRESHOLDS.max_cost_per_request:
            alerts.append(f'Expensive request: ${cost_usd:.4f} (threshold: ${DEFAULT_THRESHOLDS.max_cost_per_request})')
        
        # Alert on daily budget exceeded
        daily_total = self._daily_spend[today]
        if daily_total > DEFAULT_THRESHOLDS.max_daily_spend:
            alerts.append(f'Daily budget exceeded: ${daily_total:.2f} > ${DEFAULT_THRESHOLDS.max_daily_spend}')
        
        return alerts

cost_tracker = CostTracker()

Alertas sobre puntuaciones de calidad

Las alertas de calidad son la categoría más compleja, porque la calidad no puede medirse únicamente con métricas de infraestructura: requiere una evaluación semántica. El enfoque más escalable es la evaluación automatizada mediante muestreo: para una muestra aleatoria de las solicitudes de producción (5-10 %), ejecute un evaluador LLM-as-judge de forma asíncrona, almacene las puntuaciones y calcule una media móvil. Active una alerta cuando la media móvil caiga por debajo del mínimo de calidad.

import random
from openai import OpenAI

client = OpenAI()

def evaluate_response_quality(question: str, answer: str) -> float:
    judge_prompt = f'''Rate the quality of this AI assistant response on a scale from 0 to 1.

Question: {question}
Answer: {answer}

Return only a JSON object: {{"score": 0.85, "reason": "brief reason"}}

Scoring guide:
1.0 = Perfect, accurate, helpful
0.75 = Good, minor issues
0.5 = Acceptable but incomplete
0.25 = Poor, major gaps
0.0 = Completely wrong or harmful'''
    
    response = client.chat.completions.create(
        model='gpt-4o-mini',  # cheaper model for evaluation
        messages=[{'role': 'user', 'content': judge_prompt}],
        response_format={'type': 'json_object'}
    )
    import json
    result = json.loads(response.choices[0].message.content)
    return float(result['score'])

def maybe_evaluate(question: str, answer: str, sample_rate=0.1):
    if random.random() < sample_rate:
        score = evaluate_response_quality(question, answer)
        quality_tracker.record(score)
        return score
    return None

Medias móviles para detectar tendencias

Una única respuesta incorrecta no indica un problema sistémico. Utilice medias móviles en una ventana temporal (por ejemplo, la última hora o las últimas 100 solicitudes) para detectar tendencias. Una media móvil que cruza un umbral y permanece por encima o por debajo durante más de 10 minutos indica un problema real, mientras que un pico breve podría ser ruido. Las medias móviles ponderadas exponencialmente (EWMA) reaccionan más rápido a los cambios recientes que las medias móviles simples.

class RollingQualityMonitor:
    def __init__(self, window=50, alert_threshold=0.75, ewma_alpha=0.1):
        self.scores = []
        self.window = window
        self.alert_threshold = alert_threshold
        self.alpha = ewma_alpha  # EWMA decay factor
        self.ewma_score = None

    def record(self, score: float):
        self.scores.append(score)
        if len(self.scores) > self.window:
            self.scores.pop(0)
        
        # Update exponentially weighted moving average
        if self.ewma_score is None:
            self.ewma_score = score
        else:
            self.ewma_score = self.alpha * score + (1 - self.alpha) * self.ewma_score

    def should_alert(self) -> bool:
        if len(self.scores) < 10:  # not enough data yet
            return False
        return self.ewma_score < self.alert_threshold

    def summary(self) -> dict:
        if not self.scores:
            return {}
        return {
            'rolling_avg': sum(self.scores) / len(self.scores),
            'ewma': self.ewma_score,
            'sample_count': len(self.scores),
            'alert': self.should_alert()
        }

quality_tracker = RollingQualityMonitor()

Enrutamiento de alertas: Slack y PagerDuty

Las alertas solo son útiles si llegan a la persona adecuada a través del canal adecuado. Enrute las alertas según su gravedad: las alertas de degradación de la calidad y de presupuesto de costes deben enviarse a un canal de Slack que su equipo supervise durante el horario laboral. Las alertas de latencia por encima de umbrales críticos (por ejemplo, p99 > 30 segundos) y los picos repentinos de costes (por ejemplo, 10 veces el nivel normal en 5 minutos) deben enviarse a PagerDuty para una escalación inmediata al equipo de guardia.

import requests

def send_slack_alert(message: str, severity: str, webhook_url: str):
    color = {'critical': '#ff0000', 'warning': '#ff9900', 'info': '#36a64f'}[severity]
    payload = {
        'attachments': [{
            'color': color,
            'title': f'LLM Alert [{severity.upper()}]',
            'text': message,
            'footer': 'AI Pipeline Monitor'
        }]
    }
    requests.post(webhook_url, json=payload)

def send_pagerduty_alert(title: str, details: str, routing_key: str):
    payload = {
        'routing_key': routing_key,
        'event_action': 'trigger',
        'payload': {
            'summary': title,
            'severity': 'critical',
            'source': 'ai-pipeline-monitor',
            'custom_details': {'details': details}
        }
    }
    requests.post('https://events.pagerduty.com/v2/enqueue', json=payload)

def route_alert(alert_text: str, severity: str):
    send_slack_alert(alert_text, severity, SLACK_WEBHOOK_URL)
    if severity == 'critical':
        send_pagerduty_alert(alert_text, alert_text, PAGERDUTY_ROUTING_KEY)

El ciclo de evaluación de alertas

La lógica de alertas debe ejecutarse en un ciclo programado, no de forma integrada en el procesamiento de solicitudes. Ejecutar las comprobaciones de alertas de forma asíncrona evita añadir latencia a las solicitudes de producción. Un hilo en segundo plano o un trabajo programado que se ejecute cada 60 segundos es suficiente para la mayoría de las necesidades de alertas. Recopile las métricas en la ruta de la solicitud y evalúe los umbrales en el ciclo en segundo plano.

import threading
import time

def alert_evaluation_loop(interval_seconds=60):
    while True:
        try:
            # Check latency
            latency_alerts = latency_tracker.check_alert(DEFAULT_THRESHOLDS)
            for alert in latency_alerts:
                route_alert(f'LATENCY: {alert}', 'warning')
            
            # Check quality
            quality_summary = quality_tracker.summary()
            if quality_summary.get('alert'):
                msg = f'QUALITY DEGRADATION: Rolling avg {quality_summary["ewma"]:.2f} below threshold {DEFAULT_THRESHOLDS.min_quality_score}'
                route_alert(msg, 'warning')
            
            print(f'Alert check complete. Quality: {quality_summary.get("ewma", "N/A")}')
        except Exception as e:
            print(f'Alert evaluation error: {e}')
        
        time.sleep(interval_seconds)

# Start in background thread
alert_thread = threading.Thread(target=alert_evaluation_loop, daemon=True)
alert_thread.start()

Fatiga por alertas y ajuste de umbrales

La fatiga por alertas se produce cuando las alertas se activan con tanta frecuencia que el equipo empieza a ignorarlas. Evítelo siguiendo estas prácticas: comience con umbrales conservadores (altos) y ajústelos a la baja a medida que comprenda su línea base; exija que las alertas se mantengan durante varios ciclos de evaluación antes de activarse; agrupe las alertas relacionadas en una sola notificación; y revise periódicamente las alertas que nunca dan lugar a una acción significativa para retirarlas.

class AlertDebouncer:
    def __init__(self, required_consecutive_fires=3):
        self.required = required_consecutive_fires
        self.fire_counts = {}  # alert_name -> consecutive fires
        self.already_firing = set()  # alert_names currently active

    def should_fire(self, alert_name: str, condition: bool) -> bool:
        if condition:
            self.fire_counts[alert_name] = self.fire_counts.get(alert_name, 0) + 1
            if self.fire_counts[alert_name] >= self.required and alert_name not in self.already_firing:
                self.already_firing.add(alert_name)
                return True  # fire the alert (first time condition sustained)
        else:
            if self.fire_counts.get(alert_name, 0) > 0:
                self.fire_counts[alert_name] = 0
                self.already_firing.discard(alert_name)  # condition cleared
        return False  # either not sustained or already firing (no duplicate alert)

debouncer = AlertDebouncer(required_consecutive_fires=3)

Supervisión de anomalías de costes con métodos estadísticos

Las alertas basadas en umbrales simples no detectan anomalías de costes más sutiles, como un aumento gradual del 50 % en dos días. Utilice la detección estadística de anomalías: calcule la media móvil y la desviación estándar de sus costes por hora, y active una alerta cuando el coste de la hora actual supere la media en más de N desviaciones estándar (alertas basadas en la puntuación Z). Esto se adapta automáticamente a los patrones naturales de uso, como el tráfico entre semana y el del fin de semana.

import statistics

def compute_z_score(recent_value: float, historical_values: list[float]) -> float:
    if len(historical_values) < 5:
        return 0  # not enough data
    mean = statistics.mean(historical_values)
    stdev = statistics.stdev(historical_values)
    if stdev == 0:
        return 0
    return (recent_value - mean) / stdev

def check_cost_anomaly(current_hour_cost: float, historical_hourly_costs: list[float]) -> str | None:
    z = compute_z_score(current_hour_cost, historical_hourly_costs)
    if z > 3.0:  # more than 3 standard deviations above mean
        mean = statistics.mean(historical_hourly_costs)
        return f'Cost anomaly: ${current_hour_cost:.2f} this hour (normal: ${mean:.2f}, z={z:.1f})'
    return None

Creación de un panel de operaciones

Las alertas son la capa reactiva; un panel de operaciones en tiempo real es la capa proactiva. Cree un panel sencillo que muestre métricas en tiempo real: la latencia p50/p99 actual, las solicitudes por minuto, la puntuación de calidad actual (EWMA móvil), el coste diario acumulado frente al presupuesto y las cinco solicitudes más costosas de la última hora. Esto proporciona a su equipo una visión inmediata del estado del sistema sin tener que esperar a que se active una alerta.

Comprobación rápida

Compruebe sus conocimientos sobre las alertas de métricas de aplicaciones de LLM en esta lección.

Resumen de la lección

En esta lección aprendió que: tres categorías de alertas cubren los sistemas LLM —latencia, costo y calidad—, y cada una requiere una instrumentación diferente; los promedios móviles y EWMA detectan mejor la degradación gradual de la calidad que las comprobaciones de umbrales en solicitudes individuales; y la desactivación de rebote de alertas evita la fatiga por alertas al exigir que las condiciones se mantengan durante varios ciclos de evaluación antes de activar una alerta. A continuación, profundizaremos en los ataques de inyección de prompts y la seguridad de la IA.

Preguntas frecuentes

¿La lección «Alertas sobre latencia, costes y degradación de la calidad» es gratis?

Sí — el texto completo de «Alertas sobre latencia, costes y degradación de la calidad» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Engineering Academy, actualiza a CoddyKit PRO. El curso de AI Engineering Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Alertas sobre latencia, costes y degradación de la calidad»?

Defina umbrales de alerta para la latencia p99, el coste por solicitud y las puntuaciones de calidad automatizadas, y envíe las alertas a Slack o PagerDuty cuando su pipeline de LLM se degrade. Practicas AI Engineering Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar AI Engineering Academy?

No se requiere experiencia previa. AI Engineering Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Alertas sobre latencia, costes y degradación de la calidad»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de AI Engineering Academy?

Sí. Cada lección de AI Engineering Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Por qué las aplicaciones con LLM son difíciles de depurar
  2. Trazas con LangSmith
  3. Observabilidad independiente del modelo con Langfuse
  4. Alertas sobre latencia, costes y degradación de la calidad
← Volver a AI Engineering Academy