Alertas sobre latência, custo e degradação da qualidade
Defina limites de alerta para a latência p99, o custo por solicitação e as pontuações de qualidade automatizadas, e encaminhe os alertas para o Slack ou o PagerDuty quando seu pipeline de LLM sofrer degradação.
Alertas sobre latência, custo e degradação da qualidade é uma aula grátis de AI Engineering Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Engineering Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Engineering Academy inclui 4 aulas no total.
Por que os alertas são importantes para sistemas de LLM
As aplicações de LLM falham de maneiras sutis e graduais. Uma alteração no comando pode aumentar a latência média em 30%, uma melhoria na recuperação pode reduzir ligeiramente a qualidade das respostas ou um aumento no uso pode elevar os custos diários a cinco vezes o orçamento. Sem alertas proativos, você só descobre esses problemas quando os usuários reclamam ou a fatura mensal chega. Os alertas transformam o combate reativo a problemas em operações proativas.
As três categorias de alertas
Os alertas de aplicações de LLM se dividem em três categorias. Alertas de latência são acionados quando o tempo de resposta ultrapassa um limite da experiência do usuário (por exemplo, p99 > 10 segundos). Alertas de custo são acionados quando o custo por solicitação ou o gasto diário ultrapassa os limites do orçamento, evitando surpresas na fatura. Alertas de qualidade são acionados quando as métricas automatizadas de qualidade (pontuações de LLM como avaliador, índices de satisfação dos usuários e pontuações de fidelidade) ficam abaixo de um nível aceitável. Cada categoria exige uma instrumentação e canais 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()Coleta de métricas de latência
Para gerar alertas de latência, primeiro você precisa coletá-la de forma consistente. Meça separadamente três componentes da latência: tempo até o primeiro token (TTFT, essencial para a experiência de usuário em transmissões), tempo total de resposta e latências de cada etapa de recuperação e geração. Armazene esses dados como uma série temporal (um ponto de dados por solicitação) para poder calcular percentis e médias móveis dos últimos N minutos ou 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()Acompanhamento e alertas de custos
O monitoramento de custos exige acompanhar os gastos em vários níveis de detalhe: custo por solicitação (para detectar consultas atípicas dispendiosas), totais por hora e por dia (para detectar picos de uso) e custo por funcionalidade (para identificar qual parte da aplicação é mais cara). Gere alertas imediatamente para anomalias no custo por solicitação e use verificações programadas para os limites do orçamento diário.
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 de pontuação de qualidade
Os alertas de qualidade são a categoria mais complexa, porque a qualidade não pode ser medida apenas com métricas de infraestrutura — é necessária uma avaliação semântica. A abordagem mais escalável é a avaliação automatizada por amostragem: para uma amostra aleatória das solicitações em produção (5–10%), execute um avaliador de LLM como avaliador de forma assíncrona, armazene as pontuações e calcule uma média móvel. Gere um alerta quando a média móvel ficar abaixo do nível mínimo de qualidade.
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 NoneMédias móveis para detecção de tendências
Uma única resposta ruim não indica um problema sistêmico. Use médias móveis em uma janela de tempo (por exemplo, a última hora ou as últimas 100 solicitações) para detectar tendências. Uma média móvel que ultrapassa um limite e permanece acima dele por mais de 10 minutos indica um problema real, enquanto um pico breve pode ser apenas ruído. As médias móveis ponderadas exponencialmente (EWMA) reagem mais rapidamente a alterações recentes do que as médias móveis 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()Roteamento de alertas: Slack e PagerDuty
Os alertas só são úteis se chegarem à pessoa certa pelo canal certo. Encaminhe os alertas de acordo com a gravidade: alertas de degradação da qualidade e do orçamento de custos devem ir para um canal do Slack monitorado pela equipe durante o horário comercial. Alertas de latência acima de limites críticos (por exemplo, p99 > 30 segundos) e picos repentinos de custo (por exemplo, 10 vezes acima do normal em 5 minutos) devem ir para o PagerDuty, para escalonamento imediato à pessoa de plantão.
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)O ciclo de avaliação de alertas
A lógica de alertas deve ser executada em um ciclo programado, e não junto ao processamento das solicitações. Executar as verificações de alerta de forma assíncrona evita adicionar latência às solicitações de produção. Para a maioria das necessidades de alerta, uma thread em segundo plano ou um trabalho programado executado a cada 60 segundos é suficiente. Colete as métricas no caminho da solicitação e avalie os limites no ciclo em 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()Fadiga de alertas e ajuste de limites
A fadiga de alertas ocorre quando os alertas são acionados com tanta frequência que a equipe começa a ignorá-los. Evite isso: comece com limites conservadores (altos) e torne-os mais rigorosos à medida que compreender sua linha de base; exija que os alertas persistam por vários ciclos de avaliação antes de serem acionados; agrupe alertas relacionados em uma única notificação; e revise regularmente e desative os alertas que nunca levam a uma ação significativa.
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)Monitoramento de anomalias de custo com métodos estatísticos
Alertas baseados em limites simples não detectam anomalias de custo sutis, como um aumento gradual de 50% nos custos ao longo de dois dias. Use a detecção estatística de anomalias: calcule a média móvel e o desvio padrão dos custos por hora e gere um alerta quando o custo da hora atual estiver mais de N desvios padrão acima da média (alertas por pontuação Z). Isso se adapta automaticamente a padrões naturais de uso, como o tráfego dos dias úteis e dos fins 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 NoneConstrução de um painel de operações
Os alertas são a camada reativa; um painel de operações em tempo real é a camada proativa. Crie um painel simples que mostre métricas em tempo real: latência p50/p99 atual, solicitações por minuto, pontuação de qualidade atual (EWMA móvel), custo diário acumulado em comparação com o orçamento e as cinco solicitações mais caras da última hora. Isso oferece à sua equipe uma visão imediata da saúde do sistema, sem esperar que um alerta seja acionado.
Verificação rápida
Teste sua compreensão sobre alertas de métricas de aplicações de LLM nesta lição.
Recapitulação da lição
Nesta lição, você aprendeu: três categorias de alertas abrangem sistemas de LLM — latência, custo e qualidade — e cada uma exige uma instrumentação diferente; médias móveis e EWMA detectam a degradação gradual da qualidade melhor do que verificações de limite em solicitações individuais; e o debounce de alertas evita a fadiga causada por alertas ao exigir que as condições persistam por vários ciclos de avaliação antes de dispará-los. A seguir, exploraremos ataques de injeção de prompt e segurança de IA.
Aprenda Python com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 30
- Aulas
- 120
Perguntas Frequentes
A aula “Alertas sobre latência, custo e degradação da qualidade” é grátis?
Sim — o texto completo de “Alertas sobre latência, custo e degradação da qualidade” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Engineering Academy, atualize para CoddyKit PRO. O curso de AI Engineering Academy inclui 4 aulas no total.
O que vou aprender em “Alertas sobre latência, custo e degradação da qualidade”?
Defina limites de alerta para a latência p99, o custo por solicitação e as pontuações de qualidade automatizadas, e encaminhe os alertas para o Slack ou o PagerDuty quando seu pipeline de LLM sofrer… Você pratica AI Engineering Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Engineering Academy?
Nenhuma experiência prévia é necessária. AI Engineering Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Alertas sobre latência, custo e degradação da qualidade”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Engineering Academy?
Sim. Cada aula de AI Engineering Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que aplicações com LLM são difíceis de depurar
- Rastreamento com LangSmith
- Observabilidade independente de modelo com Langfuse
- Alertas sobre latência, custo e degradação da qualidade