AI Engineering Academy · درس

التنبيه بشأن تدهور زمن الاستجابة والتكلفة والجودة

حدّدوا عتبات تنبيه لزمن الاستجابة عند p99، وتكلفة كل طلب، ودرجات الجودة الآلية، ووجّهوا التنبيهات إلى Slack أو PagerDuty عند تدهور مسار LLM.

الدرس 4 من 413 خطوة

التنبيه بشأن تدهور زمن الاستجابة والتكلفة والجودة درس مجاني في AI Engineering Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Engineering Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.

لماذا تُعدّ التنبيهات مهمة لأنظمة LLM

تفشل تطبيقات LLM بطرق دقيقة وتدريجية. فقد تؤدي تغييرات المطالبة إلى زيادة متوسط زمن الاستجابة بنسبة 30%، وقد يؤدي تحسين الاسترجاع إلى خفض طفيف في جودة الإجابة، أو قد يؤدي ارتفاع الاستخدام إلى تجاوز التكاليف اليومية للميزانية بمقدار خمسة أضعاف. ومن دون تنبيهات استباقية، لن تكتشفوا هذه المشكلات إلا عندما يشتكي المستخدمون أو تصل الفاتورة الشهرية. تحوّل التنبيهات معالجة المشكلات بعد وقوعها إلى تشغيل استباقي.

فئات التنبيهات الثلاث

تنقسم تنبيهات تطبيقات LLM إلى ثلاث فئات. تُفعّل تنبيهات زمن الاستجابة عندما يتجاوز زمن الاستجابة حدًا يؤثر في تجربة المستخدم (مثل p99 > 10 ثوانٍ). وتُفعّل تنبيهات التكلفة عندما تتجاوز تكلفة الطلب أو الإنفاق اليومي حدود الميزانية، مما يمنع صدمة الفاتورة. أما تنبيهات الجودة فتُفعّل عندما تنخفض مقاييس الجودة التلقائية، مثل تقييمات LLM كمحكّم ومعدلات رضا المستخدمين وتقييمات الوفاء للمصدر، عن الحد الأدنى المقبول. وتتطلب كل فئة أدوات رصد وقنوات تنبيه مختلفة.

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()

جمع مقاييس زمن الاستجابة

لإطلاق تنبيهات بشأن زمن الاستجابة، تحتاجون أولًا إلى جمعه باستمرار. قيسوا ثلاثة مكونات لزمن الاستجابة بشكل منفصل: زمن الوصول إلى الرمز المميّز الأول (TTFT، وهو مهم لتجربة المستخدم أثناء البث)، وزمن الاستجابة الإجمالي، وأزمنة كل خطوة من خطوات الاسترجاع والتوليد. خزّنوا هذه البيانات كسلاسل زمنية (نقطة بيانات واحدة لكل طلب) حتى تتمكنوا من حساب المئينات والمتوسطات المتحركة خلال آخر N دقيقة أو ساعة.

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()

تتبّع التكلفة وإطلاق التنبيهات بشأنها

تتطلب مراقبة التكلفة تتبّع الإنفاق على مستويات متعددة من الدقة: تكلفة كل طلب (لاكتشاف الاستعلامات الشاذة مرتفعة التكلفة)، والإجماليات الساعية واليومية (لاكتشاف ارتفاعات الاستخدام)، وتكلفة كل ميزة (لتحديد الجزء الأعلى تكلفة في التطبيق). أطلقوا تنبيهًا فورًا عند اكتشاف حالات شاذة في تكلفة الطلب، واستخدموا عمليات فحص مجدولة لحدود الميزانية اليومية.

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()

التنبيه بشأن تقييمات الجودة

يُعدّ التنبيه بشأن الجودة الفئة الأكثر تعقيدًا، لأن الجودة لا يمكن قياسها من مقاييس البنية التحتية وحدها، بل تتطلب تقييمًا دلاليًا. ويتمثل النهج الأكثر قابلية للتوسع في التقييم التلقائي لعينات مختارة: اختاروا عينة عشوائية من طلبات الإنتاج (بنسبة 5-10%)، وشغّلوا مقيّمًا يعتمد على LLM كمحكّم بشكل غير متزامن، وخزّنوا التقييمات واحسبوا متوسطًا متحركًا. أطلقوا تنبيهًا عندما ينخفض المتوسط المتحرك عن الحد الأدنى للجودة.

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

المتوسطات المتحركة لاكتشاف الاتجاهات

لا تشير استجابة سيئة واحدة إلى وجود مشكلة عامة. استخدموا المتوسطات المتحركة على مدى زمني (مثل الساعة الأخيرة أو آخر 100 طلب) لاكتشاف الاتجاهات. يشير المتوسط المتحرك الذي يتجاوز حدًا معينًا ويظل فوقه لأكثر من 10 دقائق إلى مشكلة حقيقية، بينما قد تكون الزيادة القصيرة مجرد ضوضاء. تستجيب المتوسطات المتحركة الموزونة أُسّيًا (EWMA) للتغييرات الحديثة أسرع من المتوسطات المتحركة البسيطة.

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()

توجيه التنبيهات: Slack وPagerDuty

لا تكون التنبيهات مفيدة إلا إذا وصلت إلى الشخص المناسب عبر القناة المناسبة. وجّهوا التنبيهات حسب مستوى الخطورة: أرسلوا تنبيهات تدهور الجودة وتنبيهات تجاوز ميزانية التكلفة إلى قناة Slack التي يراقبها فريقكم خلال ساعات العمل. أما تنبيهات زمن الاستجابة التي تتجاوز الحدود الحرجة (مثل p99 > 30 ثانية) والارتفاعات المفاجئة في التكلفة (مثل تجاوز المعدل المعتاد بعشرة أضعاف خلال 5 دقائق)، فأرسلوها إلى PagerDuty لتصعيدها فورًا إلى المناوب.

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)

حلقة تقييم التنبيهات

ينبغي أن يعمل منطق التنبيهات ضمن حلقة مجدولة، لا بشكل مباشر مع معالجة الطلبات. فإجراء عمليات فحص التنبيهات بشكل غير متزامن يمنعها من إضافة زمن استجابة إلى طلبات الإنتاج. ويكفي لمعظم احتياجات التنبيه تشغيل خيط في الخلفية أو مهمة مجدولة كل 60 ثانية. اجمعوا المقاييس أثناء مسار الطلب، وقيّموا الحدود في حلقة الخلفية.

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()

إرهاق التنبيهات وضبط الحدود

يحدث إرهاق التنبيهات عندما تُطلق التنبيهات بوتيرة متكررة إلى حد يجعل الفريق يتجاهلها. امنعوا ذلك من خلال: البدء بحدود محافظة (مرتفعة) وتشديدها بعد فهم خط الأساس لديكم، واشتراط استمرار الحالة لعدة دورات تقييم قبل إطلاق التنبيه، وتجميع التنبيهات المرتبطة في إشعارات واحدة، ومراجعة التنبيهات التي لا تؤدي أبدًا إلى إجراء مفيد وإيقافها بانتظام.

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)

مراقبة حالات شذوذ التكلفة باستخدام الأساليب الإحصائية

تفشل التنبيهات ذات الحدود البسيطة في اكتشاف حالات شذوذ دقيقة في التكلفة، مثل زيادة تدريجية بنسبة 50% خلال يومين. استخدموا اكتشاف الحالات الشاذة إحصائيًا: احسبوا المتوسط المتحرك والانحراف المعياري للتكاليف الساعية، وأطلقوا تنبيهًا عندما تتجاوز تكلفة الساعة الحالية المتوسط بأكثر من N من الانحرافات المعيارية (التنبيه باستخدام درجة Z). ويتكيف ذلك تلقائيًا مع أنماط الاستخدام الطبيعية، مثل اختلاف حركة المرور بين أيام الأسبوع وعطلة نهاية الأسبوع.

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

إنشاء لوحة معلومات للعمليات

التنبيهات هي الطبقة التفاعلية، أما لوحة معلومات العمليات المباشرة فهي الطبقة الاستباقية. أنشئوا لوحة معلومات بسيطة تعرض المقاييس الآنية: زمن الاستجابة الحالي p50/p99، وعدد الطلبات في الدقيقة، وتقييم الجودة الحالي (EWMA متحرك)، والتكلفة اليومية حتى الآن مقارنةً بالميزانية، وأغلى 5 طلبات خلال الساعة الأخيرة. يمنح ذلك فريقكم رؤية سريعة عن حالة النظام دون انتظار إطلاق تنبيه.

فحص سريع

اختبروا مدى فهمكم للتنبيه بشأن مقاييس تطبيقات LLM من خلال هذا الدرس.

مراجعة الدرس

تعلمت في هذا الدرس أن ثلاث فئات من التنبيهات تغطي أنظمة LLM، وهي زمن الاستجابة والتكلفة والجودة، وتتطلب كل فئة منها أدوات قياس مختلفة، وأن المتوسطات المتحركة وEWMA تكشفان تدهور الجودة التدريجي بصورة أفضل من فحوصات العتبة المطبقة على الطلبات الفردية، وأن إزالة تكرار التنبيهات تمنع إرهاق التنبيهات من خلال اشتراط استمرار الظروف عبر دورات تقييم متعددة قبل إطلاق التنبيه. في الخطوة التالية، سنتعمق في هجمات حقن المطالبات وأمن الذكاء الاصطناعي.

البدء مجانًا

تعلم Python مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
30
الدروس
120

الأسئلة الشائعة

هل درس «التنبيه بشأن تدهور زمن الاستجابة والتكلفة والجودة» مجاني؟

نعم — نص درس «التنبيه بشأن تدهور زمن الاستجابة والتكلفة والجودة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Engineering Academy، انتقل إلى CoddyKit PRO. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.

ماذا ستتعلم في «التنبيه بشأن تدهور زمن الاستجابة والتكلفة والجودة»؟

حدّدوا عتبات تنبيه لزمن الاستجابة عند p99، وتكلفة كل طلب، ودرجات الجودة الآلية، ووجّهوا التنبيهات إلى Slack أو PagerDuty عند تدهور مسار LLM. تتمرن على AI Engineering Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Engineering Academy؟

لا تُشترط خبرة سابقة. AI Engineering Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «التنبيه بشأن تدهور زمن الاستجابة والتكلفة والجودة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Engineering Academy هذا؟

نعم. كل درس في AI Engineering Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. لماذا يصعب تصحيح تطبيقات LLM
  2. التتبع باستخدام LangSmith
  3. Langfuse للرصد المستقل عن النموذج
  4. التنبيه بشأن تدهور زمن الاستجابة والتكلفة والجودة
← العودة إلى AI Engineering Academy