إنشاء نظام متعدد الوكلاء

1. مقدمة

نظرة عامة

في هذا الدرس التطبيقي، ستتجاوز روبوتات المحادثة البسيطة وتنشئ نظامًا موزّعًا يستند إلى عدّة وكلاء.

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

ستنشئ نظام إنشاء دورات تدريبية يتألف من:

  1. وكيل الباحث: استخدام google_search للعثور على معلومات محدّثة
  2. الوكيل الحَكَم: ينتقد البحث للتأكّد من جودته واكتماله.
  3. وكيل "أداة إنشاء المحتوى": تحويل البحث إلى دورة تدريبية منظَّمة
  4. وكيل التنسيق: إدارة سير العمل والتواصل بين هؤلاء المتخصصين

المتطلبات الأساسية

  • الإلمام بأساسيات لغة Python
  • الإلمام بوحدة تحكّم Google Cloud

الإجراءات التي ستنفذّها

  • تحديد وكيل يستخدم الأدوات (researcher) ويمكنه البحث على الويب
  • تنفيذ ناتج منظَّم باستخدام Pydantic لـ judge
  • الاتصال بوكلاء بعيدين باستخدام بروتوكول Agent-to-Agent (A2A)
  • أنشئ LoopAgent لإنشاء حلقة ملاحظات وآراء بين الباحث والحكم.
  • تشغيل النظام الموزّع محليًا باستخدام "حزمة تطوير التطبيقات" (ADK)
  • انشر النظام المتعدد الوكلاء على Google Cloud Run.

مبادئ التصميم والتنسيق

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

تصميم النظام

المخطَّط البياني للبنية

تنظيم العمل باستخدام الوكلاء

تعمل الوكلاء العاديون (مثل "الباحث"). تتولّى وكلاء التنسيق (مثل LoopAgent أو SequentialAgent) إدارة الوكلاء الآخرين. ليس لديهم أدواتهم الخاصة، بل "أداتهم" هي التفويض.

  1. LoopAgent: تعمل هذه السمة مثل حلقة while في الرمز. يتم تشغيل سلسلة من الوكلاء بشكل متكرر إلى أن يتم استيفاء شرط معيّن (أو يتم الوصول إلى الحد الأقصى لعدد التكرارات). نستخدم هذه الميزة في حلقة البحث:
    • الباحث يعثر على المعلومات.
    • يقدم القاضي نقدًا لها.
    • إذا عرضت Judge الحالة "تعذّر"، ستسمح EscalationChecker باستمرار التكرار.
    • إذا قال Judge "اجتياز"، سيوقف EscalationChecker التكرار.
  2. SequentialAgent: يعمل هذا الخيار مثل تنفيذ نص برمجي عادي. يتم تشغيل البرامج الوكيلة واحدًا تلو الآخر. نستخدم هذه المعلومات في المسار عالي المستوى:
    • أولاً، شغِّل حلقة البحث (إلى أن تنتهي ببيانات جيدة).
    • بعد ذلك، شغِّل أداة إنشاء المحتوى (لكتابة الدورة التدريبية).

ومن خلال الجمع بين هذه العناصر، ننشئ نظامًا قويًا يمكنه تصحيح نفسه قبل إنشاء الناتج النهائي.

2. الإعداد

إعداد البيئة

  1. فتح Cloud Shell: انقر على رمز تفعيل Cloud Shell في أعلى يسار Google Cloud Console.

الحصول على الرمز المُعد مسبقًا للمبتدئين

  1. أنشئ نسخة طبق الأصل من مستودع الرموز الأولية في الدليل الرئيسي:
    cd ~
    git clone --depth 1 --filter=blob:none --sparse https://github.com/GoogleCloudPlatform/devrel-demos.git temp-repo && cd temp-repo && git sparse-checkout set agents/build-with-ai/production-ready-ai/prai-roadshow-lab-1-starter && cd .. && mv temp-repo/agents/build-with-ai/production-ready-ai/prai-roadshow-lab-1-starter . && rm -rf temp-repo
    cd prai-roadshow-lab-1-starter
    
  2. تفعيل واجهات برمجة التطبيقات: نفِّذ الأمر التالي لتفعيل خدمات Google Cloud اللازمة:
    gcloud services enable \
        run.googleapis.com \
        artifactregistry.googleapis.com \
        cloudbuild.googleapis.com \
        aiplatform.googleapis.com \
        compute.googleapis.com
    
  3. افتح هذا المجلد في المحرِّر.

تثبيت الحِزم التابعة

نستخدم uv لإدارة التبعيات بسرعة.

  1. ثبِّت تبعيات المشروع:
    # Ensure you have uv installed: pip install uv
    uv sync
    
  2. إعداد متغيرات البيئة
    • ملاحظة: يمكنك العثور على رقم تعريف مشروعك في لوحة بيانات Cloud Console، أو من خلال تنفيذ gcloud config get-value project.
    سننشئ ملف .env لتخزين هذه المتغيرات حتى تتمكّن من إعادة تحميلها بسهولة في حال انقطاع اتصال جلستك.
    cat <<EOF > .env
    export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
    export GOOGLE_CLOUD_LOCATION=global
    export GOOGLE_GENAI_USE_VERTEXAI=true
    EOF
    
  3. تحديد مصدر متغيرات البيئة:
    source .env
    
    تحذير: لا يتم الاحتفاظ بمتغيرات البيئة في جلسات طرفية جديدة. إذا فتحت علامة تبويب جديدة في الوحدة الطرفية، شغِّل source .env لاستعادة هذه الملفات.

3- ‫🕵️ وكيل الباحث

وكيل الباحث

الباحث هو شخص متخصص. مهمتها الوحيدة هي العثور على المعلومات. ولإجراء ذلك، يحتاج إلى الوصول إلى أداة، وهي "بحث Google".

لماذا يتم فصل حساب الباحث؟

نظرة تفصيلية: لماذا لا نستخدم وكيلاً واحدًا لإنجاز كل المهام؟

يسهل تقييم وتصحيح الأخطاء في العملاء الصغار والمحدّدين. إذا كان البحث سيئًا، يمكنك تكرار طلب Researcher. إذا كان تنسيق الدورة التدريبية سيئًا، يمكنك تكرار عملية إنشاء المحتوى باستخدام "أداة إنشاء المحتوى". في الطلب الموحّد "الذي ينجز كل شيء"، غالبًا ما يؤدي إصلاح مشكلة واحدة إلى حدوث مشكلة أخرى.

  1. إذا كنت تعمل في Cloud Shell، نفِّذ الأمر التالي لفتح محرِّر Cloud Shell:
    cloudshell workspace .
    
    إذا كنت تعمل في بيئتك المحلية، افتح بيئة التطوير المتكاملة المفضّلة لديك.
  2. فتح "agents/researcher/agent.py"
  3. سيظهر لك هيكل مع قائمة مهام.
  4. أضِف الرمز التالي لتحديد researcher الوكيل:
    # ... existing imports ...
    
    # Define the Researcher Agent
    researcher = Agent(
        name="researcher",
        model=MODEL,
        description="Gathers information on a topic using Google Search.",
        instruction="""
        You are an expert researcher. Your goal is to find comprehensive and accurate information on the user's topic.
        Summarize your findings clearly.
        If you receive feedback that your research is insufficient, use the feedback to refine your next search.
        DO NOT output any function calls. Provide your research directly as text.
        """,
    )
    
    root_agent = researcher
    

المفهوم الأساسي: استخدام الأدوات

عند استخدام Gemini 3، تتوفّر أداة "بحث Google" تلقائيًا. إذا كنت تستخدم نموذجًا مختلفًا، مثل Gemini 2.5، عليك تمرير tools=[google_search] كمعلَمة إضافية إلى الدالة الإنشائية Agent(). تتولّى "حزمة تطوير التطبيقات" التعامل مع تعقيد وصف هذه الأداة للنموذج اللغوي الكبير. عندما يقرّر النموذج أنّه بحاجة إلى معلومات، ينشئ طلبًا منظَّمًا لاستخدام الأداة، وتنفّذ حزمة ADK دالة Python google_search، ثم تعيد النتيجة إلى النموذج.

4. ‫⚖️ Judge Agent

Judge Agent

يبذل الباحث جهدًا كبيرًا، ولكن يمكن أن تكون النماذج اللغوية الكبيرة كسولة. نحتاج إلى حكم لمراجعة العمل. يقبل القاضي البحث ويعرض تقييمًا منظَّمًا بنتيجة "اجتياز" أو "عدم اجتياز".

الناتج المنظَّم

نظرة تفصيلية: لأتمتة مهام سير العمل، نحتاج إلى مخرجات يمكن توقّعها. من الصعب تحليل مراجعة نصية طويلة بشكل آلي. من خلال فرض مخطط JSON (باستخدام Pydantic)، نضمن أن تعرض أداة Judge القيمة المنطقية pass أو fail التي يمكن أن يستند إليها الرمز البرمجي بشكل موثوق.

  1. فتح "agents/judge/agent.py"
  2. حدِّد مخطط JudgeFeedback ووكيل judge.
    # 1. Define the Schema
    class JudgeFeedback(BaseModel):
        """Structured feedback from the Judge agent."""
        status: Literal["pass", "fail"] = Field(
            description="Whether the research is sufficient ('pass') or needs more work ('fail')."
        )
        feedback: str = Field(
            description="Detailed feedback on what is missing. If 'pass', a brief confirmation."
        )
    
    # 2. Define the Agent
    judge = Agent(
        name="judge",
        model=MODEL,
        description="Evaluates research findings for completeness and accuracy.",
        instruction="""
        You are a strict editor.
        Evaluate the 'research_findings' against the user's original request.
        If the findings are missing key info, return status='fail'.
        If they are comprehensive, return status='pass'.
        """,
        output_schema=JudgeFeedback,
        # Disallow delegation because it should only output the schema
        disallow_transfer_to_parent=True,
        disallow_transfer_to_peers=True,
    )
    
    root_agent = judge
    

المفهوم الأساسي: تقييد سلوك الوكيل

نضبط disallow_transfer_to_parent=True وdisallow_transfer_to_peers=True. يفرض ذلك على القاضي فقط عرض JudgeFeedback المنظَّمة. ولا يمكنه اتّخاذ قرار "المحادثة" مع المستخدم أو تفويض وكيل آخر. وهذا يجعلها عنصرًا حتميًا في مسار المنطق.

5- 🧪 الاختبار في بيئة معزولة

قبل ربطها، يمكننا التأكّد من أنّ كل وكيل يعمل. تتيح لك "حزمة تطوير البرامج" تشغيل الوكلاء بشكل فردي.

المفهوم الأساسي: وقت التشغيل التفاعلي

تنشئ adk run بيئة بسيطة تكون فيها أنت "المستخدم". يتيح لك ذلك اختبار تعليمات الوكيل واستخدام الأدوات بشكل منفصل. إذا تعذّر على الوكيل تنفيذ هذه الخطوة (على سبيل المثال، تعذّر عليه استخدام "بحث Google")، سيتعذّر عليه بالتأكيد تنفيذ عملية التنسيق.

  1. تشغيل "الباحث" بشكل تفاعلي يُرجى العِلم أنّنا نشير إلى دليل الوكلاء المحدّد:
    # This runs the researcher agent in interactive mode
    uv run adk run agents/researcher
    
  2. في طلب المحادثة، اكتب:
    Find the population of Tokyo in 2020
    
    يجب أن تستخدم الأداة "بحث Google" وتعرض الإجابة.ملاحظة: إذا ظهرت لك رسالة خطأ تشير إلى عدم ضبط المشروع والموقع الجغرافي واستخدام Vertex، تأكَّد من ضبط رقم تعريف مشروعك ونفِّذ ما يلي:
    export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
    export GOOGLE_CLOUD_LOCATION=global
    export GOOGLE_GENAI_USE_VERTEXAI=true
    
  3. الخروج من المحادثة (Ctrl+C)
  4. نفِّذ Judge بشكل تفاعلي:
    uv run adk run agents/judge
    
  5. في طلب المحادثة، حاكِ إدخال ما يلي:
    Topic: Tokyo. Findings: Tokyo is a city.
    
    من المفترض أن تعرض status='fail' لأنّ النتائج موجزة جدًا.

6. ✍️ "أداة إنشاء المحتوى"

أداة إنشاء المحتوى

أداة إنشاء المحتوى هي الكاتب الإبداعي. تأخذ هذه الأداة الأبحاث التي تمت الموافقة عليها وتحوّلها إلى دورة تدريبية.

  1. فتح "agents/content_builder/agent.py"
  2. حدِّد وكيل content_builder.
    content_builder = Agent(
        name="content_builder",
        model=MODEL,
        description="Transforms research findings into a structured course.",
        instruction="""
        You are an expert course creator.
        Take the approved 'research_findings' and transform them into a well-structured, engaging course module.
    
        **Formatting Rules:**
        1. Start with a main title using a single `#` (H1).
        2. Use `##` (H2) for main section headings.
        3. Use bullet points and clear paragraphs.
        4. Maintain a professional but engaging tone.
    
        Ensure the content directly addresses the user's original request.
        """,
    )
    root_agent = content_builder
    

المفهوم الأساسي: نقل السياق

قد تتساءل: "كيف يعرف "منشئ المحتوى" ما عثر عليه "الباحث"؟" في حزمة تطوير التطبيقات (ADK)، تشترك الوكلاء في مسار معالجة في session.state. لاحقًا، في Orchestrator، سنضبط Researcher وJudge لحفظ نواتجهما في هذه الحالة المشترَكة. يمكن لأداة "إنشاء المحتوى" الوصول إلى هذا السجلّ.

7. 🎻 أداة Orchestrator

وكيل Orchestrator

المنسّق هو مدير فريقنا المتعدّد الوكلاء. على عكس الوكلاء المتخصّصين (الباحث، والحكم، وصانع المحتوى) الذين ينفّذون مهام محددة، تتمثل مهمة "المنسّق" في تنسيق سير العمل وضمان تدفّق المعلومات بشكل صحيح بين الوكلاء.

‫🌐 البنية: من وكيل إلى وكيل (A2A)

بنية A2A

في هذا الدرس التطبيقي، سننشئ نظامًا موزّعًا. بدلاً من تشغيل جميع البرامج في عملية Python واحدة، ننشرها كخدمات مصغّرة مستقلة. يتيح ذلك لكل وكيل توسيع نطاقه بشكل مستقل وتعطُّله بدون تعطُّل النظام بأكمله.

ولتحقيق ذلك، نستخدم بروتوكول Agent-to-Agent (A2A).

بروتوكول A2A

نظرة تفصيلية: في نظام الإنتاج، تعمل البرامج على خوادم مختلفة (أو حتى على سُحب مختلفة). يوفّر بروتوكول A2A طريقة موحّدة لتتمكّن هذه الأجهزة من العثور على بعضها البعض والتواصل معها عبر HTTP. ‫RemoteA2aAgent هو برنامج ADK للعميل لهذا البروتوكول.

  1. فتح "agents/orchestrator/agent.py"
  2. ابحث عن التعليق # TODO: Define connections to remote agents أو القسم الخاص بتعريفات الوكيل البعيد.
  3. أضِف الرمز التالي لتحديد عمليات الربط. احرص على وضع هذا السطر بعد عمليات الاستيراد وقبل أي تعريفات أخرى للوكيل.
    # ... existing code ...
    
    # Connect to the Researcher (Localhost port 8001)
    researcher_url = os.environ.get("RESEARCHER_AGENT_CARD_URL", "http://localhost:8001/a2a/agent/.well-known/agent-card.json")
    researcher = RemoteA2aAgent(
        name="researcher",
        agent_card=researcher_url,
        description="Gathers information using Google Search.",
        # IMPORTANT: Save the output to state for the Judge to see
        after_agent_callback=create_save_output_callback("research_findings"),
        # IMPORTANT: Use authenticated client for communication
        httpx_client=create_authenticated_client(researcher_url)
    )
    
    # Connect to the Judge (Localhost port 8002)
    judge_url = os.environ.get("JUDGE_AGENT_CARD_URL", "http://localhost:8002/a2a/agent/.well-known/agent-card.json")
    judge = RemoteA2aAgent(
        name="judge",
        agent_card=judge_url,
        description="Evaluates research.",
        after_agent_callback=create_save_output_callback("judge_feedback"),
        httpx_client=create_authenticated_client(judge_url)
    )
    
    # Content Builder (Localhost port 8003)
    content_builder_url = os.environ.get("CONTENT_BUILDER_AGENT_CARD_URL", "http://localhost:8003/a2a/agent/.well-known/agent-card.json")
    content_builder = RemoteA2aAgent(
        name="content_builder",
        agent_card=content_builder_url,
        description="Builds the course.",
        httpx_client=create_authenticated_client(content_builder_url)
    )
    

8. 🛑 أداة التحقّق من حالة التصعيد

يجب أن تتضمّن الحلقة طريقة لإيقافها. إذا قال القاضي "مقبول"، نريد الخروج من الحلقة على الفور والانتقال إلى "أداة إنشاء المحتوى".

المنطق المخصّص باستخدام BaseAgent

نظرة تفصيلية: لا تستخدم بعض البرامج الآلية نماذج اللغات الكبيرة. في بعض الأحيان، تحتاج إلى منطق بسيط في Python. تتيح لك BaseAgent تحديد وكيل ينفّذ الرمز فقط. في هذه الحالة، نتحقّق من حالة الجلسة ونستخدم EventActions(escalate=True) للإشارة إلى LoopAgent بالتوقّف.

  1. لا يزال في agents/orchestrator/agent.py.
  2. ابحث عن العنصر النائب EscalationChecker TODO.
  3. استبدِلها بالتنفيذ التالي:
    class EscalationChecker(BaseAgent):
        """Checks the judge's feedback and escalates (breaks the loop) if it passed."""
    
        async def _run_async_impl(
            self, ctx: InvocationContext
        ) -> AsyncGenerator[Event, None]:
            # Retrieve the feedback saved by the Judge
            feedback = ctx.session.state.get("judge_feedback")
            print(f"[EscalationChecker] Feedback: {feedback}")
    
            # Check for 'pass' status
            is_pass = False
            if isinstance(feedback, dict) and feedback.get("status") == "pass":
                is_pass = True
            # Handle string fallback if JSON parsing failed
            elif isinstance(feedback, str) and '"status": "pass"' in feedback:
                is_pass = True
    
            if is_pass:
                # 'escalate=True' tells the parent LoopAgent to stop looping
                yield Event(author=self.name, actions=EventActions(escalate=True))
            else:
                # Continue the loop
                yield Event(author=self.name)
    
    escalation_checker = EscalationChecker(name="escalation_checker")
    

المفهوم الأساسي: التحكّم في تدفّق البيانات من خلال الأحداث

لا تتواصل البرامج الآلية باستخدام النصوص فقط، بل باستخدام الأحداث. من خلال عرض حدث باستخدام escalate=True، يرسل هذا العامل إشارة إلى العنصر الرئيسي (LoopAgent). تمت برمجة LoopAgent لتلقّي هذه الإشارة وإنهاء الحلقة.

9. 🔁 حلقة البحث

Research Loop

نحتاج إلى حلقة ملاحظات: البحث -> التقييم -> (فشل) -> البحث -> ...

  1. لا يزال في agents/orchestrator/agent.py.
  2. أضِف تعريف research_loop. ضَع هذا بعد الفئة EscalationChecker والمثيل escalation_checker.
    research_loop = LoopAgent(
        name="research_loop",
        description="Iteratively researches and judges until quality standards are met.",
        sub_agents=[researcher, judge, escalation_checker],
        max_iterations=3,
    )
    

المفهوم الأساسي: LoopAgent

يتنقّل LoopAgent بين sub_agents بالترتيب.

  1. researcher: للبحث عن البيانات
  2. judge: لتقييم البيانات.
  3. escalation_checker: تحدّد ما إذا كان سيتم yield Event(escalate=True). في حال حدوث escalate=True، يتم إيقاف التكرار مبكرًا. وفي حال عدم توفّرها، ستبدأ من الباحث (بحد أقصى max_iterations).

10. 🔗 مسار العرض النهائي

المسار النهائي

أخيرًا، اجمع كل ذلك معًا.

  1. لا يزال في agents/orchestrator/agent.py.
  2. حدِّد root_agent في أسفل الملف. تأكَّد من أنّ هذا العنصر النائب يحلّ محلّ أي عنصر نائب حالي root_agent = None.
    root_agent = SequentialAgent(
        name="course_creation_pipeline",
        description="A pipeline that researches a topic and then builds a course from it.",
        sub_agents=[research_loop, content_builder],
    )
    

المفهوم الأساسي: التركيب الهرمي

يُرجى العِلم أنّ research_loop هو نفسه وكيل (LoopAgent)، ونعامله مثل أي وكيل فرعي آخر في SequentialAgent. تتيح لك إمكانية التركيب هذه إنشاء منطق معقّد من خلال دمج أنماط بسيطة (حلقات داخل تسلسلات، وتسلسلات داخل أجهزة توجيه، وما إلى ذلك).

‫11. 💻 التشغيل محليًا

قبل تشغيل كل شيء، دعونا نلقي نظرة على كيفية محاكاة حزمة تطوير التطبيقات (ADK) للبيئة الموزّعة محليًا.

نظرة متعمّقة: طريقة عمل التطوير المحلي

في بنية الخدمات المصغّرة، يعمل كل وكيل كخادم مستقل. عند النشر، ستحصل على 4 خدمات مختلفة من Cloud Run. يمكن أن تكون محاكاة ذلك محليًا أمرًا صعبًا إذا كان عليك فتح 4 علامات تبويب في الوحدة الطرفية وتنفيذ 4 أوامر.

يبدأ هذا النص البرمجي uvicorn عملية لكل من Researcher (المنفذ 8001) وJudge (المنفذ 8002) وContent Builder (المنفذ 8003). يضبط هذا البرنامج متغيّرات البيئة، مثل RESEARCHER_AGENT_CARD_URL، ويمررها إلى Orchestrator (المنفذ 8004). هذه هي الطريقة التي سنضبط بها الإعدادات في السحابة الإلكترونية لاحقًا.

التطبيق قيد التشغيل

  1. شغِّل نص التنسيق البرمجي:
    perl -pi -e 's/us-central1/global/g' run_local.sh
    ./run_local.sh
    
    يبدأ هذا الإجراء 4 عمليات منفصلة.
  2. اختبارها:
    • في حال استخدام Cloud Shell: انقر على الزر معاينة الويب (أعلى يسار نافذة الوحدة الطرفية) -> المعاينة على المنفذ 8080 -> تغيير المنفذ إلى 8000.
    • في حال التشغيل محليًا: افتح http://localhost:8000 في المتصفّح.
    • الطلب: "أنشئ دورة تدريبية حول تاريخ القهوة".
    • المراقبة: سيتصل Orchestrator بـ Researcher. يتم إرسال الناتج إلى "القاضي". إذا لم ينجح القاضي في ذلك، تستمر الحلقة.
    تحديد المشاكل وحلّها:
    • "خطأ في الخادم الداخلي" / أخطاء المصادقة: إذا ظهرت لك أخطاء في المصادقة (مثل الأخطاء المتعلقة بـ google-auth)، تأكَّد من تنفيذ gcloud auth application-default login إذا كنت تستخدم جهازًا محليًا. في Cloud Shell، تأكَّد من ضبط متغيّر البيئة GOOGLE_CLOUD_PROJECT بشكل صحيح.
    • أخطاء في نافذة Terminal: إذا تعذّر تنفيذ الأمر في نافذة Terminal جديدة، تذكَّر إعادة تصدير متغيّرات البيئة (GOOGLE_CLOUD_PROJECT وما إلى ذلك).
  3. اختبار الوكلاء بشكل منفصل: حتى عند تشغيل النظام الكامل، يمكنك اختبار وكلاء معيّنين من خلال استهداف منافذهم مباشرةً. ويكون ذلك مفيدًا لتصحيح خطأ في مكوّن معيّن بدون تشغيل السلسلة بأكملها.ملاحظة: هذه نقاط نهاية لواجهة برمجة التطبيقات وليست صفحات ويب. ولا يمكنك الوصول إليها من خلال متصفّح. بدلاً من ذلك، استخدِم curl للتأكّد من أنّها تعمل (على سبيل المثال، من خلال استرداد بطاقة الوكيل).
    • الباحثون فقط (المنفذ 8001):
      • التحقّق من الحالة (والعثور على نقطة النهاية url):
        curl http://localhost:8001/a2a/agent/.well-known/agent-card.json
        
      • إرسال طلب بحث (باستخدام بروتوكول A2A JSON-RPC):
        curl -X POST http://localhost:8001/a2a/agent \
          -H "Content-Type: application/json" \
          -d '{
            "jsonrpc": "2.0",
            "method": "message/send",
            "id": 1,
            "params": {
              "message": {
                "message_id": "test-1",
                "role": "user",
                "parts": [
                  {
                    "text": "What is the capital of France?",
                    "kind": "text"
                  }
                ]
              }
            }
          }'
        
    • التقييم فقط (المنفذ 8002):
      • التحقّق من الحالة:
        curl http://localhost:8002/a2a/agent/.well-known/agent-card.json
        
      • إرسال طلب بحث:
        curl -X POST http://localhost:8002/a2a/agent \
          -H "Content-Type: application/json" \
          -d '{
            "jsonrpc": "2.0",
            "method": "message/send",
            "id": 1,
            "params": {
              "message": {
                "message_id": "test-2",
                "role": "user",
                "parts": [
                  {
                    "text": "Topic: Tokyo. Findings: Tokyo is the capital of Japan.",
                    "kind": "text"
                  }
                ]
              }
            }
          }'
        
    • أداة إنشاء المحتوى فقط (المنفذ 8003):
      curl http://localhost:8003/a2a/agent/.well-known/agent-card.json
      
    • المنسّق (المنفذ 8004):
      curl http://localhost:8004/a2a/agent/.well-known/agent-card.json
      

‫12. 🚀 النشر على Cloud Run

تتم عملية التحقّق النهائية في السحابة الإلكترونية. سننفّذ كل وكيل كخدمة منفصلة.

التعرّف على إعدادات النشر

عند نشر الوكلاء على Cloud Run، نمرّر العديد من متغيرات البيئة لضبط سلوكهم واتصالهم:

  • استبدِل GOOGLE_CLOUD_PROJECT بما يلي: يضمن هذا الخيار أنّ الوكيل يستخدم مشروع Google Cloud الصحيح لتسجيل البيانات واستدعاء Vertex AI.
  • استبدِل GOOGLE_GENAI_USE_VERTEXAI بما يلي: يطلب هذا الخيار من إطار عمل الوكيل (ADK) استخدام Vertex AI لاستنتاج النموذج بدلاً من استدعاء واجهات Gemini API مباشرةً.
  • GOOGLE_CLOUD_LOCATION: يحدّد إطار عمل الوكيل (ADK) نقطة النهاية التي سيتم استخدامها.
  • [AGENT]_AGENT_CARD_URL: هذه السمة ضرورية لخدمة Orchestrator. يخبر هذا الحقل Orchestrator بمكان العثور على الوكلاء البعيدين. من خلال ضبط هذه السمة على عنوان URL الذي تم نشره على Cloud Run (وتحديدًا مسار بطاقة الوكيل)، نتيح لخدمة Orchestrator إمكانية العثور على Researcher وJudge وContent Builder والتواصل معها عبر الإنترنت.
  1. نشر الوكلاء الفرعيين (بالتوازي):لتوفير الوقت، سننشر "الباحث" و"المقيّم" و"صانع المحتوى" في الوقت نفسه.افتح ثلاث علامات تبويب جديدة في نافذة الأوامر. في كل علامة تبويب جديدة، نفِّذ ما يلي لإعداد بيئتك:
    cd ~/prai-roadshow-lab-1-starter
    source .env
    
    علامة التبويب 1: تنفيذ عملية نشر Researcher:
    gcloud run deploy researcher \
      --source agents/researcher/ \
      --region us-west1 \
      --allow-unauthenticated \
      --labels dev-tutorial=prod-ready-1 \
      --set-env-vars GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT \
      --set-env-vars GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION \
      --set-env-vars GOOGLE_GENAI_USE_VERTEXAI="true"
    
    علامة التبويب 2: تنفيذ عملية نشر Judge:
    gcloud run deploy judge \
      --source agents/judge/ \
      --region us-west1 \
      --allow-unauthenticated \
      --labels dev-tutorial=prod-ready-1 \
      --set-env-vars GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT \
      --set-env-vars GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION \
      --set-env-vars GOOGLE_GENAI_USE_VERTEXAI="true"
    
    علامة التبويب 3: تشغيل عملية نشر "أداة إنشاء المحتوى":
    gcloud run deploy content-builder \
      --source agents/content_builder/ \
      --region us-west1 \
      --allow-unauthenticated \
      --labels dev-tutorial=prod-ready-1 \
      --set-env-vars GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT \
      --set-env-vars GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION \
      --set-env-vars GOOGLE_GENAI_USE_VERTEXAI="true"
    
  2. التقاط عناوين URL:بعد انتهاء عمليات النشر الثلاث، ارجع إلى الوحدة الطرفية الأصلية (حيث ستنشر Orchestrator). نفِّذ الأوامر التالية لالتقاط عناوين URL الخاصة بالخدمة:
    RESEARCHER_URL=$(gcloud run services describe researcher --region us-west1 --format='value(status.url)')
    JUDGE_URL=$(gcloud run services describe judge --region us-west1 --format='value(status.url)')
    CONTENT_BUILDER_URL=$(gcloud run services describe content-builder --region us-west1 --format='value(status.url)')
    
    echo "Researcher: $RESEARCHER_URL"
    echo "Judge: $JUDGE_URL"
    echo "Content Builder: $CONTENT_BUILDER_URL"
    
  3. نشر Orchestrator: استخدِم متغيرات البيئة التي تم الحصول عليها لضبط Orchestrator.
    gcloud run deploy orchestrator \
      --source agents/orchestrator/ \
      --region us-west1 \
      --allow-unauthenticated \
      --labels dev-tutorial=prod-ready-1 \
      --set-env-vars RESEARCHER_AGENT_CARD_URL=$RESEARCHER_URL/a2a/agent/.well-known/agent-card.json \
      --set-env-vars JUDGE_AGENT_CARD_URL=$JUDGE_URL/a2a/agent/.well-known/agent-card.json \
      --set-env-vars CONTENT_BUILDER_AGENT_CARD_URL=$CONTENT_BUILDER_URL/a2a/agent/.well-known/agent-card.json \
      --set-env-vars GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT \
      --set-env-vars GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION \
      --set-env-vars GOOGLE_GENAI_USE_VERTEXAI="true"
    
    تسجيل عنوان URL:
    ORCHESTRATOR_URL=$(gcloud run services describe orchestrator --region us-west1 --format='value(status.url)')
    echo $ORCHESTRATOR_URL
    
  4. نشر الواجهة الأمامية:
    gcloud run deploy course-creator \
        --source app \
        --region us-west1 \
        --allow-unauthenticated \
        --labels dev-tutorial=prod-ready-1 \
        --set-env-vars AGENT_SERVER_URL=$ORCHESTRATOR_URL \
        --set-env-vars GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT
    
  5. اختبار النشر عن بُعد: افتح عنوان URL الخاص بـ Orchestrator الذي تم نشره. تعمل هذه الخدمة الآن بالكامل على السحابة الإلكترونية، وتستفيد من البنية الأساسية بدون خادم من Google لتوسيع نطاق عملائك.تلميح: ستجد جميع الخدمات المصغّرة وعناوين URL الخاصة بها في واجهة Cloud Run.

13. ملخّص

تهانينا! لقد أنشأت ونشرت بنجاح نظامًا موزّعًا يستند إلى عدّة وكلاء وجاهزًا للاستخدام في مرحلة الإنتاج.

إنجازاتنا

  • تقسيم مهمة معقّدة: بدلاً من تقديم طلب كبير واحد، قسّمنا العمل إلى أدوار متخصصة (باحث، وحكم، ومنشئ محتوى).
  • تنفيذ مراقبة الجودة: استخدمنا LoopAgent وJudge منظَّمًا لضمان وصول المعلومات العالية الجودة فقط إلى الخطوة النهائية.
  • مصمَّم للإنتاج: باستخدام بروتوكول التواصل بين الوكلاء (A2A) وCloud Run، أنشأنا نظامًا يكون فيه كل وكيل عبارة عن خدمة مصغّرة مستقلة وقابلة للتوسيع. وهذا أكثر فعالية من تنفيذ كل شيء في نص برمجي واحد بلغة Python.
  • التنسيق: استخدمنا SequentialAgent وLoopAgent لتحديد أنماط واضحة لسير التحكّم.

الخطوات التالية

بعد أن أصبحت لديك الأساسيات، يمكنك توسيع نطاق هذا النظام باتّباع الخطوات التالية:

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

أنت الآن جاهز لإنشاء مهام سير عمل معقّدة وموثوقة مستندة إلى وكلاء على Google Cloud.