ساخت یک سیستم چندعاملی

۱. مقدمه

نمای کلی

در این آزمایشگاه، شما فراتر از چت‌بات‌های ساده خواهید رفت و یک سیستم چندعاملی توزیع‌شده خواهید ساخت.

در حالی که یک LLM به تنهایی می‌تواند به سوالات پاسخ دهد، پیچیدگی‌های دنیای واقعی اغلب به نقش‌های تخصصی نیاز دارند. شما از مهندس backend خود نمی‌خواهید که رابط کاربری را طراحی کند و از طراح خود نمی‌خواهید که پرس‌وجوهای پایگاه داده را بهینه کند. به طور مشابه، ما می‌توانیم عوامل هوش مصنوعی تخصصی ایجاد کنیم که بر روی یک کار تمرکز می‌کنند و برای حل مشکلات پیچیده با یکدیگر هماهنگ می‌شوند.

شما یک سیستم ایجاد دوره آموزشی خواهید ساخت که شامل موارد زیر است:

  1. نماینده محقق : استفاده از google_search برای یافتن اطلاعات به‌روز.
  2. قاضی نماینده : نقد تحقیق از نظر کیفیت و کامل بودن.
  3. عامل سازنده محتوا : تبدیل تحقیق به یک دوره آموزشی ساختارمند
  4. عامل هماهنگ‌کننده : مدیریت گردش کار و ارتباط بین این متخصصان.

پیش‌نیازها

  • دانش پایه پایتون.
  • آشنایی با کنسول ابری گوگل

کاری که انجام خواهید داد

  • یک عامل استفاده‌کننده از ابزار ( researcher ) تعریف کنید که بتواند وب را جستجو کند.
  • پیاده‌سازی خروجی ساختاریافته با Pydantic برای judge .
  • با استفاده از پروتکل Agent-to-Agent (A2A) به Agentهای راه دور متصل شوید.
  • یک LoopAgent بسازید تا یک حلقه بازخورد بین محقق و قاضی ایجاد شود.
  • سیستم توزیع‌شده را با استفاده از ADK به صورت محلی اجرا کنید.
  • سیستم چندعاملی را در Google Cloud Run مستقر کنید.

اصول معماری و ارکستراسیون

قبل از اینکه کد بنویسیم، بیایید بفهمیم که این عامل‌ها چگونه با هم کار می‌کنند. ما در حال ساخت یک خط تولید دوره (Course Creation Pipeline) هستیم.

طراحی سیستم

نمودار معماری

هماهنگی با نمایندگان

عامل‌های استاندارد (مانند Researcher) کار می‌کنند. عامل‌های هماهنگ‌کننده (مانند LoopAgent یا SequentialAgent ) عامل‌های دیگر را مدیریت می‌کنند. آن‌ها ابزار مخصوص به خود را ندارند؛ «ابزار» آن‌ها واگذاری اختیار است.

  1. LoopAgent : این حلقه مانند یک حلقه while در کد عمل می‌کند. این حلقه دنباله‌ای از عامل‌ها را تا زمانی که یک شرط برقرار شود (یا به حداکثر تکرار برسد) به طور مکرر اجرا می‌کند. ما از این حلقه برای حلقه تحقیق استفاده می‌کنیم:
    • محقق اطلاعات را پیدا می‌کند.
    • قاضی آن را نقد می‌کند.
    • اگر Judge بگوید «ناموفق»، EscalationChecker اجازه می‌دهد حلقه ادامه یابد.
    • اگر قاضی بگوید «قبول»، بررسی‌کننده‌ی تشدید، حلقه را می‌شکند.
  2. SequentialAgent : این مانند اجرای یک اسکریپت استاندارد عمل می‌کند. عامل‌ها را یکی پس از دیگری اجرا می‌کند. ما از این برای خط لوله سطح بالا استفاده می‌کنیم:
    • ابتدا، حلقه تحقیق را اجرا کنید (تا زمانی که با داده‌های خوب به پایان برسد).
    • سپس، سازنده محتوا را اجرا کنید (برای نوشتن دوره).

با ترکیب این موارد، ما یک سیستم قوی ایجاد می‌کنیم که می‌تواند قبل از تولید خروجی نهایی، خود را اصلاح کند.

۲. راه‌اندازی

تنظیمات محیط

باز کردن Cloud Shell : یک تب جدید باز کنید و shell.cloud.google.com را تایپ کنید.

کد شروع را دریافت کنید

  1. مخزن اولیه را در دایرکتوری خانگی خود کلون کنید:
    cd ~
    git clone https://github.com/amitkmaraj/prai-roadshow-lab-1-starter.git
    cd prai-roadshow-lab-1-starter
    
  2. اسکریپت init را اجرا کنید تا اعتبارات onramp را با صورتحساب مرتبط کنید.
    chmod +x ./init.sh
    ./init.sh
    
  3. این پوشه را در ویرایشگر خود باز کنید.

فعال کردن APIها

اکنون که یک پروژه جدید دارید، دستور زیر را برای فعال کردن سرویس‌های لازم Google Cloud اجرا کنید:

gcloud services enable \
    run.googleapis.com \
    artifactregistry.googleapis.com \
    cloudbuild.googleapis.com \
    aiplatform.googleapis.com \
    compute.googleapis.com

این ممکن است چند ثانیه طول بکشد.

نصب وابستگی‌ها

ما از uv برای مدیریت سریع وابستگی‌ها استفاده می‌کنیم.

  1. وابستگی‌های پروژه را نصب کنید:
    # Ensure you have uv installed: pip install uv
    uv sync
    
  2. شناسه پروژه گوگل کلود خود را تنظیم کنید.
    • نکته : می‌توانید شناسه پروژه خود را در داشبورد کنسول ابری یا با اجرای gcloud config get-value project پیدا کنید.
    export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
    
  3. متغیرهای محیطی باقی مانده را تنظیم کنید:
    export GOOGLE_CLOUD_LOCATION=us-central1
    export GOOGLE_GENAI_USE_VERTEXAI=true
    
    هشدار: متغیرهای محیطی در جلسات جدید ترمینال ذخیره نمی‌شوند . اگر یک برگه ترمینال جدید باز کنید، باید این دستورات export را دوباره اجرا کنید.

۳. 🕵️ نماینده محقق

نماینده محقق

محقق یک متخصص است. تنها وظیفه او یافتن اطلاعات است. برای انجام این کار، به ابزاری نیاز دارد: جستجوی گوگل.

چرا محقق را جدا کنیم؟

بررسی عمیق: چرا فقط یک عامل همه کارها را انجام نمی‌دهد؟

ارزیابی و اشکال‌زدایی عامل‌های کوچک و متمرکز آسان‌تر است. اگر تحقیق بد باشد، شما دستورالعمل محقق را تکرار می‌کنید. اگر قالب‌بندی دوره بد باشد، شما دستورالعمل سازنده محتوا را تکرار می‌کنید. در یک دستورالعمل یکپارچه «همه کاره»، اصلاح یک چیز اغلب باعث خرابی چیز دیگر می‌شود.

  1. اگر در Cloud Shell کار می‌کنید، دستور زیر را برای باز کردن ویرایشگر Cloud Shell اجرا کنید:
    cloudshell workspace .
    
    اگر در محیط محلی خود کار می‌کنید، IDE مورد علاقه خود را باز کنید.
  2. agents/researcher/agent.py را باز کنید.
  3. یک اسکلت با یک TODO خواهید دید.
  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.
        Use the `google_search` tool to find relevant information.
        Summarize your findings clearly.
        If you receive feedback that your research is insufficient, use the feedback to refine your next search.
        """,
        tools=[google_search],
    )
    
    root_agent = researcher
    

مفهوم کلیدی: استفاده از ابزار

توجه داشته باشید که ما tools=[google_search] را ارسال می‌کنیم. ADK پیچیدگی توصیف این ابزار را به LLM مدیریت می‌کند. وقتی مدل تصمیم می‌گیرد که به اطلاعات نیاز دارد، یک فراخوانی ساختاریافته ابزار ایجاد می‌کند، ADK تابع پایتون google_search اجرا می‌کند و نتیجه را به مدل بازمی‌گرداند.

۴. ⚖️ قاضی مامور

قاضی مامور

محقق سخت کار می‌کند، اما دانشجویان کارشناسی ارشد مدیریت بازرگانی می‌توانند تنبل باشند. ما به یک داور برای بررسی کار نیاز داریم. داور تحقیق را می‌پذیرد و یک ارزیابی ساختارمند از قبول/رد ارائه می‌دهد.

خروجی ساختاریافته

بررسی عمیق: برای خودکارسازی گردش‌های کاری، به خروجی‌های قابل پیش‌بینی نیاز داریم. تجزیه و تحلیل یک متن درهم و برهم از طریق برنامه‌نویسی دشوار است. با اجرای یک طرحواره 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 را تنظیم می‌کنیم. این کار Judge را مجبور می‌کند که فقط JudgeFeedback ساختاریافته را برگرداند. نمی‌تواند تصمیم بگیرد که با کاربر "چت" کند یا به عامل دیگری محول کند. این امر آن را به یک جزء قطعی در جریان منطقی ما تبدیل می‌کند.

۵. 🧪 آزمایش در انزوا

قبل از اتصال آنها، می‌توانیم تأیید کنیم که هر عامل کار می‌کند. ADK به شما امکان می‌دهد عامل‌ها را به صورت جداگانه اجرا کنید.

مفهوم کلیدی: زمان اجرای تعاملی

adk run یک محیط سبک را ایجاد می‌کند که در آن شما "کاربر" هستید. این به شما امکان می‌دهد دستورالعمل‌های عامل و نحوه‌ی استفاده از ابزار را به صورت جداگانه آزمایش کنید. اگر عامل در اینجا شکست بخورد (مثلاً نتواند از جستجوی گوگل استفاده کند)، قطعاً در هماهنگ‌سازی نیز شکست خواهد خورد.

  1. محقق را به صورت تعاملی اجرا کنید. توجه داشته باشید که ما به دایرکتوری عامل خاص اشاره می‌کنیم:
    # This runs the researcher agent in interactive mode
    uv run adk run agents/researcher
    
  2. در قسمت چت، تایپ کنید:
    Find the population of Tokyo in 2020
    
    باید از ابزار جستجوی گوگل استفاده کند و پاسخ را برگرداند. توجه: اگر خطایی مبنی بر عدم تنظیم پروژه، مکان و استفاده از رأس مشاهده کردید، مطمئن شوید که شناسه پروژه شما تنظیم شده است و موارد زیر را اجرا کنید:
    export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
    export GOOGLE_CLOUD_LOCATION=us-central1
    export GOOGLE_GENAI_USE_VERTEXAI=true
    
  3. از چت خارج شوید (Ctrl+C).
  4. قاضی را به صورت تعاملی اجرا کنید:
    uv run adk run agents/judge
    
  5. در پنجره چت، ورودی را شبیه‌سازی کنید:
    Topic: Tokyo. Findings: Tokyo is a city.
    
    باید status='fail' را برگرداند زیرا یافته‌ها خیلی مختصر هستند.

۶. ✍️ عامل سازنده محتوا

سازنده محتوا

سازنده محتوا ، نویسنده خلاق است. او تحقیقات تایید شده را می‌گیرد و آن را به یک دوره آموزشی تبدیل می‌کند.

  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، محقق و قاضی را پیکربندی می‌کنیم تا خروجی‌های خود را در این وضعیت مشترک ذخیره کنند. اعلان سازنده محتوا عملاً به این تاریخچه دسترسی دارد.

۷. 🎻 رهبر ارکستر

نماینده ارکستراسیون

هماهنگ‌کننده، مدیر تیم چندعاملی ما است. برخلاف عوامل متخصص (محقق، قاضی، سازنده محتوا) که وظایف خاصی را انجام می‌دهند، وظیفه هماهنگ‌کننده، هماهنگی گردش کار و اطمینان از جریان صحیح اطلاعات بین آنها است.

🌐 معماری: عامل به عامل (A2A)

معماری A2A

در این آزمایشگاه، ما در حال ساخت یک سیستم توزیع‌شده هستیم. به جای اجرای همه عامل‌ها در یک فرآیند پایتون واحد، آنها را به عنوان میکروسرویس‌های مستقل مستقر می‌کنیم. این به هر عامل اجازه می‌دهد تا به طور مستقل مقیاس‌بندی شود و بدون از کار افتادن کل سیستم، از کار بیفتد.

برای امکان‌پذیر کردن این امر، ما از پروتکل عامل به عامل (A2A) استفاده می‌کنیم.

پروتکل A2A

بررسی عمیق: در یک سیستم عملیاتی، عامل‌ها روی سرورهای مختلف (یا حتی ابرهای مختلف) اجرا می‌شوند. پروتکل A2A یک روش استاندارد برای آنها ایجاد می‌کند تا یکدیگر را از طریق HTTP کشف و با هم صحبت کنند. RemoteA2aAgent کلاینت ADK برای این پروتکل است.

  1. agents/orchestrator/agent.py را باز کنید.
  2. کامنت # TODO: Define Remote Agents یا بخش مربوط به تعاریف عامل از راه دور را پیدا کنید.
  3. کد زیر را برای تعریف اتصالات اضافه کنید. مطمئن شوید که این کد را بعد از importها و قبل از هرگونه تعریف عامل دیگر قرار می‌دهید.
    # ... 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)
    )
    

۸. 🛑 بررسی‌کننده‌ی افزایش سطح

یک حلقه به راهی برای متوقف شدن نیاز دارد. اگر قاضی بگوید «قبول»، می‌خواهیم فوراً از حلقه خارج شویم و به سازنده محتوا برویم.

منطق سفارشی با BaseAgent

بررسی عمیق: همه عامل‌ها از LLM استفاده نمی‌کنند. گاهی اوقات به منطق ساده پایتون نیاز دارید. 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 طوری برنامه‌ریزی شده است که این سیگنال را دریافت کرده و حلقه را خاتمه دهد.

۹. 🔁 حلقه تحقیق

حلقه تحقیقاتی

ما به یک حلقه بازخورد نیاز داریم: تحقیق -> قضاوت -> (شکست) -> تحقیق -> ...

  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 ) دوباره شروع می‌شود.

۱۰. 🔗 خط لوله نهایی

خط لوله نهایی

در نهایت، همه را به هم بدوزید.

  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 رفتار می‌کنیم. این قابلیت ترکیب به شما امکان می‌دهد با تودرتو کردن الگوهای ساده (حلقه‌ها درون توالی‌ها، توالی‌ها درون روترها و غیره) منطق پیچیده‌ای بسازید.

۱۱. 💻 اجرا به صورت محلی

قبل از اینکه همه چیز را اجرا کنیم، بیایید نگاهی به نحوه شبیه‌سازی محیط توزیع‌شده توسط ADK به صورت محلی بیندازیم.

بررسی عمیق: توسعه محلی چگونه کار می‌کند

در معماری میکروسرویس‌ها، هر عامل به عنوان سرور مخصوص به خود اجرا می‌شود. هنگام استقرار، ۴ سرویس Cloud Run مختلف خواهید داشت. شبیه‌سازی این امر به صورت محلی می‌تواند دشوار باشد اگر مجبور باشید ۴ تب ترمینال را باز کنید و ۴ دستور را اجرا کنید.

این اسکریپت، فرآیندهای uvicorn را برای Researcher (پورت ۸۰۰۱)، Judge (پورت ۸۰۰۲) و Content Builder (پورت ۸۰۰۳) آغاز می‌کند. این اسکریپت متغیرهای محیطی مانند RESEARCHER_AGENT_CARD_URL را تنظیم کرده و آنها را به Orchestrator (پورت ۸۰۰۴) ارسال می‌کند. این دقیقاً همان روشی است که بعداً آن را در فضای ابری پیکربندی خواهیم کرد!

اجرای برنامه

  1. اسکریپت ارکستراسیون را اجرا کنید:
    ./run_local.sh
    
    این ۴ فرآیند جداگانه را آغاز می‌کند.
  2. آن را آزمایش کنید:
    • اگر از Cloud Shell استفاده می‌کنید: روی دکمه پیش‌نمایش وب (بالا سمت راست ترمینال) کلیک کنید -> پیش‌نمایش روی پورت ۸۰۸۰ -> پورت را به 8000 تغییر دهید.
    • اگر به صورت محلی اجرا می‌شود: http://localhost:8000 را در مرورگر خود باز کنید.
    • پیشنهاد: «یک دوره آموزشی در مورد تاریخچه قهوه ایجاد کنید.»
    • مشاهده: ارکستراتور، محقق را فراخوانی می‌کند. خروجی به قاضی می‌رود. اگر قاضی در آن شکست بخورد، حلقه ادامه می‌یابد!
    عیب‌یابی:
    • «خطای داخلی سرور» / خطاهای احراز هویت: اگر خطاهای احراز هویت (مثلاً مربوط به google-auth ) را مشاهده کردید، مطمئن شوید که در صورت اجرا روی یک دستگاه محلی gcloud auth application-default login اجرا کرده‌اید. در Cloud Shell، مطمئن شوید که متغیر محیطی GOOGLE_CLOUD_PROJECT شما به درستی تنظیم شده است.
    • خطاهای ترمینال: اگر دستور در یک پنجره ترمینال جدید با شکست مواجه شد، به یاد داشته باشید که متغیرهای محیطی خود ( GOOGLE_CLOUD_PROJECT و غیره) را دوباره صادر کنید.
  3. آزمایش عامل‌ها به صورت ایزوله: حتی زمانی که کل سیستم در حال اجرا است، می‌توانید عامل‌های خاص را با هدف قرار دادن مستقیم پورت‌های آنها آزمایش کنید. این برای اشکال‌زدایی یک جزء خاص بدون فعال کردن کل زنجیره مفید است.
    • فقط برای محققین (پورت ۸۰۰۱): http://localhost:8001
    • فقط قاضی (پورت ۸۰۰۲): http://localhost:8002
    • فقط سازنده محتوا (پورت ۸۰۰۳): http://localhost:8003
    • ارکستراتور (پورت ۸۰۰۴): http://localhost:8004 (دسترسی مستقیم به منطق ارکستراتور)

۱۲. 🚀 استقرار در Cloud Run

اعتبارسنجی نهایی در فضای ابری اجرا می‌شود. ما هر عامل را به عنوان یک سرویس جداگانه مستقر خواهیم کرد.

درک پیکربندی استقرار

هنگام استقرار عامل‌ها در Cloud Run، چندین متغیر محیطی را برای پیکربندی رفتار و اتصال آنها ارسال می‌کنیم:

  • GOOGLE_CLOUD_PROJECT : تضمین می‌کند که عامل از پروژه صحیح Google Cloud برای ثبت وقایع و فراخوانی‌های Vertex AI استفاده می‌کند.
  • GOOGLE_GENAI_USE_VERTEXAI : به چارچوب عامل (ADK) می‌گوید که به جای فراخوانی مستقیم APIهای Gemini، از Vertex AI برای استنتاج مدل استفاده کند.
  • [AGENT]_AGENT_CARD_URL : این برای Orchestrator بسیار مهم است. این به Orchestrator می‌گوید که کجا می‌تواند Agentهای از راه دور را پیدا کند. با تنظیم این مورد روی Cloud Run URL مستقر شده (به طور خاص مسیر کارت Agent)، Orchestrator را قادر می‌سازیم تا محقق، قاضی و سازنده محتوا را از طریق اینترنت کشف و با آنها ارتباط برقرار کند.
  1. محقق را مستقر کنید:
    gcloud run deploy researcher \
      --source agents/researcher/ \
      --region us-central1 \
      --allow-unauthenticated \
      --labels dev-tutorial=prod-ready-1 \
      --set-env-vars GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT \
      --set-env-vars GOOGLE_GENAI_USE_VERTEXAI="true"
    
    آدرس اینترنتی (URL) را ضبط کنید:
    RESEARCHER_URL=$(gcloud run services describe researcher --region us-central1 --format='value(status.url)')
    echo $RESEARCHER_URL
    
  2. قاضی را مستقر کنید:
    gcloud run deploy judge \
      --source agents/judge/ \
      --region us-central1 \
      --allow-unauthenticated \
      --labels dev-tutorial=prod-ready-1 \
      --set-env-vars GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT \
      --set-env-vars GOOGLE_GENAI_USE_VERTEXAI="true"
    
    آدرس اینترنتی (URL) را ضبط کنید:
    JUDGE_URL=$(gcloud run services describe judge --region us-central1 --format='value(status.url)')
    echo $JUDGE_URL
    
  3. سازنده محتوا را مستقر کنید:
    gcloud run deploy content-builder \
      --source agents/content_builder/ \
      --region us-central1 \
      --allow-unauthenticated \
      --labels dev-tutorial=prod-ready-1 \
      --set-env-vars GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT \
      --set-env-vars GOOGLE_GENAI_USE_VERTEXAI="true"
    
    آدرس اینترنتی (URL) را ضبط کنید:
    CONTENT_BUILDER_URL=$(gcloud run services describe content-builder --region us-central1 --format='value(status.url)')
    echo $CONTENT_BUILDER_URL
    
  4. راه‌اندازی Orchestrator: از متغیرهای محیطی ثبت‌شده برای پیکربندی Orchestrator استفاده کنید.
    gcloud run deploy orchestrator \
      --source agents/orchestrator/ \
      --region us-central1 \
      --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_GENAI_USE_VERTEXAI="true"
    
    آدرس اینترنتی (URL) را ضبط کنید:
    ORCHESTRATOR_URL=$(gcloud run services describe orchestrator --region us-central1 --format='value(status.url)')
    echo $ORCHESTRATOR_URL
    
  5. استقرار فرانت‌اند:
    gcloud run deploy course-creator \
        --source app \
        --region us-central1 \
        --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
    
  6. تست استقرار از راه دور: URL مربوط به Orchestrator مستقر شده خود را باز کنید. اکنون کاملاً در فضای ابری اجرا می‌شود و از زیرساخت بدون سرور گوگل برای مقیاس‌بندی Agentهای شما استفاده می‌کند! نکته : تمام میکروسرویس‌ها و URLهای آنها را در رابط Cloud Run خواهید یافت.

۱۳. خلاصه

تبریک! شما با موفقیت یک سیستم چندعاملی توزیع‌شده و آماده برای اجرا ساختید و مستقر کردید.

آنچه ما انجام داده‌ایم

  • تجزیه یک وظیفه پیچیده : به جای یک کار بسیار بزرگ، ما کار را به نقش‌های تخصصی (محقق، داور، سازنده محتوا) تقسیم کردیم.
  • کنترل کیفیت پیاده‌سازی شده : ما از یک LoopAgent و یک Judge ساختاریافته استفاده کردیم تا اطمینان حاصل کنیم که فقط اطلاعات با کیفیت بالا به مرحله نهایی می‌رسند.
  • ساخته شده برای تولید : با استفاده از پروتکل عامل به عامل (A2A) و Cloud Run ، ما سیستمی ایجاد کردیم که در آن هر عامل یک میکروسرویس مستقل و مقیاس‌پذیر است. این بسیار قوی‌تر از اجرای همه چیز در یک اسکریپت پایتون است.
  • ارکستراسیون : ما SequentialAgent و LoopAgent برای تعریف الگوهای جریان کنترل واضح استفاده کردیم.

مراحل بعدی

حالا که پایه و اساس را دارید، می‌توانید این سیستم را گسترش دهید:

  • ابزارهای بیشتری اضافه کنید : به محقق دسترسی به اسناد داخلی یا APIها را بدهید.
  • بهبود قضاوت : معیارهای خاص‌تری اضافه کنید یا حتی یک مرحله «حضور انسان در حلقه» اضافه کنید.
  • مدل‌های جایگزین : سعی کنید از مدل‌های مختلف برای عوامل مختلف استفاده کنید (مثلاً یک مدل سریع‌تر برای قاضی، یک مدل قوی‌تر برای نویسنده محتوا).

اکنون آماده‌اید تا گردش‌های کاری پیچیده و قابل اعتماد مبتنی بر عامل را در Google Cloud بسازید!