الدرس 13 من 23

تصميم أنظمة الوكلاء المتعددين

أنماط هندسة الوكلاء

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

وكلاء الذكاء الاصطناعي هي أنظمة تستخدم LLMs للاستدلال والتخطيط واتخاذ الإجراءات. فهم أنماط الهندسة المختلفة ضروري لتصميم أنظمة وكلاء قابلة للتوسع.

نمط الوكيل الفردي

النمط الأبسط—وكيل واحد يتعامل مع المهمة بأكملها.

class SingleAgent:
    def __init__(self, llm, tools: list):
        self.llm = llm
        self.tools = {tool.name: tool for tool in tools}

    async def run(self, task: str) -> str:
        messages = [{"role": "user", "content": task}]

        while True:
            response = await self.llm.complete(
                messages=messages,
                tools=list(self.tools.values())
            )

            if response.tool_calls:
                # تنفيذ الأدوات
                for call in response.tool_calls:
                    result = await self.tools[call.name].execute(call.args)
                    messages.append({
                        "role": "tool",
                        "content": result,
                        "tool_call_id": call.id
                    })
            else:
                # الاستجابة النهائية
                return response.content

الأفضل لـ: المهام البسيطة، < 5 أدوات، حلول واضحة بمسار واحد.

أنماط الوكلاء المتعددين

1. نمط المنسق

منسق مركزي يفوض المهام للوكلاء المتخصصين.

┌─────────────────────────────────────────────────────────────┐
│                        وكيل المنسق                           │
│                                                              │
│   "تقسيم المهمة، التكليف للمتخصصين، تجميع النتائج"           │
│                                                              │
├─────────────┬─────────────┬─────────────┬──────────────────┤
│             │             │             │                   │
▼             ▼             ▼             ▼                   │
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐              │
│  وكيل  │ │  وكيل  │ │  وكيل  │ │  وكيل  │              │
│  البحث │ │  الكود │ │المراجعة │ │ الاختبار│              │
└─────────┘ └─────────┘ └─────────┘ └─────────┘              │
└──────────────── النتائج تعود للمنسق ─────────────────────────┘
class CoordinatorAgent:
    def __init__(self, llm, specialist_agents: dict):
        self.llm = llm
        self.specialists = specialist_agents

    async def run(self, task: str) -> str:
        # الخطوة 1: تخطيط المهمة
        plan = await self._create_plan(task)

        # الخطوة 2: تنفيذ كل خطوة مع المتخصص المناسب
        results = []
        for step in plan.steps:
            agent = self.specialists[step.agent_type]
            result = await agent.run(step.instruction)
            results.append({
                "step": step.name,
                "result": result
            })

        # الخطوة 3: تجميع النتائج
        return await self._synthesize(task, results)

    async def _create_plan(self, task: str) -> Plan:
        prompt = f"""قسّم هذه المهمة إلى خطوات.
لكل خطوة، حدد أي متخصص يجب أن يتعامل معها.

المتخصصون المتاحون: {list(self.specialists.keys())}

المهمة: {task}

أرجع خطة JSON."""

        response = await self.llm.complete(prompt)
        return Plan.parse(response)

2. نمط خط الأنابيب

الوكلاء يعالجون بالتتابع، كل منهم يبني على مخرجات السابق.

class PipelineAgent:
    def __init__(self, stages: list):
        self.stages = stages  # قائمة من (الوكيل، دالة_التحويل)

    async def run(self, initial_input: str) -> str:
        current_output = initial_input

        for agent, transform in self.stages:
            # تحويل المدخل لهذه المرحلة
            stage_input = transform(current_output)

            # تشغيل الوكيل
            current_output = await agent.run(stage_input)

        return current_output

# مثال: خط أنابيب معالجة المستندات
pipeline = PipelineAgent([
    (extraction_agent, lambda x: f"استخرج المعلومات الرئيسية: {x}"),
    (analysis_agent, lambda x: f"حلل هذه المعلومات: {x}"),
    (summary_agent, lambda x: f"لخّص التحليل: {x}")
])

3. نمط النقاش/الناقد

عدة وكلاء يناقشون ويحسنون الإجابات.

class DebateSystem:
    def __init__(self, proposer, critic, judge):
        self.proposer = proposer
        self.critic = critic
        self.judge = judge

    async def run(self, question: str, max_rounds: int = 3) -> str:
        # الاقتراح الأولي
        proposal = await self.proposer.run(question)

        for round in range(max_rounds):
            # مراجعة الناقد
            critique = await self.critic.run(
                f"السؤال: {question}\nالاقتراح: {proposal}\n"
                "حدد نقاط الضعف واقترح تحسينات."
            )

            # التحقق من رضا الناقد
            if "لا توجد مشاكل كبيرة" in critique.lower():
                break

            # المقترح يراجع
            proposal = await self.proposer.run(
                f"السؤال: {question}\n"
                f"الإجابة السابقة: {proposal}\n"
                f"النقد: {critique}\n"
                "راجع إجابتك معالجاً النقد."
            )

        # القاضي يتخذ القرار النهائي
        return await self.judge.run(
            f"السؤال: {question}\n"
            f"الاقتراح النهائي: {proposal}\n"
            "قدم الإجابة النهائية المصقولة."
        )

اختيار النمط الصحيح

النمط حالة الاستخدام التعقيد زمن الاستجابة
وكيل فردي مهام بسيطة، أدوات قليلة منخفض منخفض
منسق مهام معقدة، مجالات متعددة متوسط متوسط
خط أنابيب معالجة تتابعية منخفض عالي
نقاش قرارات عالية المخاطر عالي عالي جداً

نصيحة للمقابلة

عند تصميم أنظمة الوكلاء في المقابلات، دائماً اعتبر:

  1. تفكيك المهام - هل يمكن تقسيمها إلى مهام فرعية؟
  2. اختيار الأدوات - ما القدرات التي يحتاجها كل وكيل؟
  3. معالجة الفشل - ماذا لو فشل وكيل في منتصف المهمة؟
  4. ميزانية زمن الاستجابة - الوكلاء المتعددين يضيفون زمناً

بعد ذلك، سنستكشف تصميم سجل الأدوات لقدرات الوكيل الديناميكية. :::

اختبار

الوحدة 4: تصميم أنظمة الوكلاء المتعددين

خذ الاختبار