الدرس 13 من 20

الإنتاج والمؤسسات

أُطر التقييم

4 دقيقة للقراءة

"يعمل على لابتوبي" لا يكفي لوكلاء الإنتاج. تحتاج تقييماً منهجياً قبل النشر ومراقبة مستمرة بعده.

تحدي التقييم

الوكلاء غير حتميين. نفس المدخل يمكن أن ينتج مخرجات مختلفة، تسلسلات أدوات مختلفة، ونتائج مختلفة. اختبارات الوحدة التقليدية تفشل.

# هذا الاختبار عديم الفائدة للوكلاء
def test_agent():
    result = agent.run("لخص هذه الوثيقة")
    assert result == "الملخص المتوقع"  # سيفشل عشوائياً

أبعاد التقييم

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

الاختبار المبني على النتائج

اختبر النتيجة، ليس المسار:

class AgentEvaluator:
    def __init__(self, agent, judge_model: str = "claude-sonnet-4-20250514"):
        self.agent = agent
        self.judge_model = judge_model

    async def evaluate_task(self, task: str, success_criteria: list[str]) -> dict:
        """شغل الوكيل وقيّم ضد المعايير."""

        # تنفيذ الوكيل
        start = time.time()
        result = await self.agent.run(task)
        duration = time.time() - start

        # استخدم LLM للحكم على النجاح
        judgments = []
        for criterion in success_criteria:
            judgment = await self.judge_criterion(result, criterion)
            judgments.append(judgment)

        return {
            "task": task,
            "result": result,
            "duration_seconds": duration,
            "token_count": result.usage.total_tokens,
            "criteria_results": judgments,
            "overall_success": all(j["passed"] for j in judgments)
        }

    async def judge_criterion(self, result: str, criterion: str) -> dict:
        """استخدم نموذج حكم لتقييم معيار واحد."""
        response = await llm.chat(
            model=self.judge_model,
            messages=[{
                "role": "user",
                "content": f"""قيّم إذا كان مخرج الوكيل هذا يلبي المعيار.

المخرج: {result}

المعيار: {criterion}

أجب بـ JSON: {{"passed": true/false, "reason": "التفسير"}}"""
            }]
        )
        return json.loads(response.content)

التقييم الإحصائي

شغّل عدة مرات لقياس الموثوقية:

async def evaluate_reliability(agent, task: str, num_runs: int = 10) -> dict:
    """شغل الوكيل عدة مرات وقِس الاتساق."""
    results = []

    for i in range(num_runs):
        result = await agent.run(task)
        results.append({
            "run": i,
            "output": result.content,
            "tokens": result.usage.total_tokens,
            "tool_calls": len(result.tool_calls)
        })

    # تحليل الاتساق
    outputs = [r["output"] for r in results]
    unique_outputs = len(set(outputs))

    return {
        "total_runs": num_runs,
        "unique_outputs": unique_outputs,
        "consistency_score": 1 - (unique_outputs - 1) / num_runs,
        "avg_tokens": sum(r["tokens"] for r in results) / num_runs,
        "token_variance": statistics.variance([r["tokens"] for r in results]),
        "results": results
    }

مجموعات المقارنة المعيارية

أنشئ مجموعات اختبار قابلة لإعادة الاستخدام:

# benchmarks/code_agent.yaml
name: "مقارنة معيارية لوكيل الكود"
version: "1.0"
tasks:
  - id: "simple_function"
    prompt: "اكتب دالة Python للتحقق إذا كان الرقم أولياً"
    criteria:
      - "الدالة صالحة نحوياً كـ Python"
      - "الدالة ترجع True لـ 2، 3، 5، 7، 11"
      - "الدالة ترجع False لـ 0، 1، 4، 6، 9"
    max_tokens: 500
    timeout_seconds: 30

  - id: "file_modification"
    prompt: "أضف معالجة أخطاء لدالة process_data في utils.py"
    criteria:
      - "الملف تم تعديله بنجاح"
      - "تمت إضافة كتلة try-except"
      - "الوظيفة الأصلية محفوظة"
    setup: "cp fixtures/utils_original.py utils.py"
    teardown: "rm utils.py"

المراقبة المستمرة

وكلاء الإنتاج يحتاجون تقييماً مستمراً:

class ProductionMonitor:
    def __init__(self, alert_threshold: float = 0.8):
        self.alert_threshold = alert_threshold
        self.metrics = []

    async def log_interaction(self, task: str, result: dict, user_feedback: int = None):
        """سجل كل تفاعل إنتاج."""
        metric = {
            "timestamp": datetime.now().isoformat(),
            "task_hash": hashlib.md5(task.encode()).hexdigest(),
            "success": result.get("success"),
            "tokens": result.get("tokens"),
            "latency_ms": result.get("latency_ms"),
            "user_feedback": user_feedback,  # تقييم 1-5 إذا متوفر
            "error": result.get("error")
        }
        self.metrics.append(metric)
        await self.check_alerts()

    async def check_alerts(self):
        """تنبيه إذا انخفضت المقاييس تحت العتبة."""
        recent = self.metrics[-100:]  # آخر 100 تفاعل
        if len(recent) < 10:
            return

        success_rate = sum(1 for m in recent if m["success"]) / len(recent)
        if success_rate < self.alert_threshold:
            await self.send_alert(f"معدل النجاح انخفض إلى {success_rate:.1%}")

ملاحظة نيردية: تقييمات OpenAI واختبار بطاقة نموذج Anthropic كلاهما يستخدمان LLM-كحكم للجودة الذاتية. ليس مثالياً، لكنه يتوسع.

التالي: تأمين وكلائك ضد سوء الاستخدام. :::

اختبار

الوحدة 4: الإنتاج والمؤسسات

خذ الاختبار