การสร้างระบบหลายเอเจนต์

1. บทนำ

ภาพรวม

ในแล็บนี้ คุณจะได้สร้างระบบแบบหลายเอเจนต์แบบกระจายที่ซับซ้อนกว่าแชทบอทแบบง่าย

แม้ว่า LLM เดียวจะตอบคำถามได้ แต่ความซับซ้อนในโลกแห่งความเป็นจริงมักต้องมีบทบาทเฉพาะทาง คุณจะไม่ขอให้วิศวกรแบ็กเอนด์ออกแบบ UI และจะไม่ขอให้นักออกแบบเพิ่มประสิทธิภาพการค้นหาฐานข้อมูล ในทำนองเดียวกัน เราสามารถสร้างเอเจนต์ AI เฉพาะทางที่มุ่งเน้นงานเดียวและประสานงานกันเพื่อแก้ปัญหาที่ซับซ้อนได้

คุณจะสร้างระบบการสร้างหลักสูตรซึ่งประกอบด้วย

  1. เอเจนต์นักวิจัย: ใช้ google_search เพื่อค้นหาข้อมูลล่าสุด
  2. ผู้ตัดสินที่เป็น Agent: วิจารณ์งานวิจัยเพื่อดูคุณภาพและความสมบูรณ์
  3. เอเจนต์ตัวสร้างเนื้อหา: เปลี่ยนงานวิจัยให้เป็นหลักสูตรที่มีโครงสร้าง
  4. Orchestrator Agent: จัดการเวิร์กโฟลว์และการสื่อสารระหว่างผู้เชี่ยวชาญเหล่านี้

ข้อกำหนดเบื้องต้น

  • มีความรู้พื้นฐานเกี่ยวกับ Python
  • คุ้นเคยกับ Google Cloud Console

สิ่งที่คุณต้องดำเนินการ

  • กำหนดเอเจนต์ที่ใช้เครื่องมือ (researcher) ซึ่งค้นหาในเว็บได้
  • ใช้เอาต์พุตที่มีโครงสร้างด้วย Pydantic สำหรับ judge
  • เชื่อมต่อกับ Agent ระยะไกลโดยใช้โปรโตคอล Agent-to-Agent (A2A)
  • สร้างLoopAgentเพื่อสร้างวงจรความคิดเห็นระหว่างนักวิจัยกับผู้ตัดสิน
  • เรียกใช้ระบบแบบกระจายในเครื่องโดยใช้ ADK
  • ติดตั้งใช้งานระบบแบบหลายเอเจนต์ใน Google Cloud Run

หลักการด้านสถาปัตยกรรมและการประสานงาน

ก่อนที่จะเขียนโค้ด เรามาทำความเข้าใจวิธีการทำงานร่วมกันของเอเจนต์เหล่านี้กันก่อน เรากำลังสร้างไปป์ไลน์การสร้างหลักสูตร

การออกแบบระบบ

แผนภาพสถาปัตยกรรม

การประสานงานด้วย Agent

เอเจนต์มาตรฐาน (เช่น นักวิจัย) จะทำงาน ตัวแทน Orchestrator (เช่น LoopAgent หรือ SequentialAgent) จะจัดการตัวแทนอื่นๆ โดยที่ผู้จัดการไม่ได้มีเครื่องมือของตัวเอง แต่ "เครื่องมือ" ของผู้จัดการคือการมอบหมายงาน

  1. LoopAgent: การดำเนินการนี้จะทำงานเหมือนลูป while ในโค้ด โดยจะเรียกใช้ลำดับของเอเจนต์ซ้ำๆ จนกว่าจะเป็นไปตามเงื่อนไข (หรือถึงการวนซ้ำสูงสุด) เราใช้ข้อมูลนี้สำหรับวงจรการวิจัย ดังนี้
    • นักวิจัยค้นหาข้อมูล
    • ผู้พิพากษาวิจารณ์
    • หาก Judge ระบุว่า "ไม่สำเร็จ" EscalationChecker จะทำให้ลูปดำเนินการต่อไป
    • หากผู้ตรวจสอบพูดว่า "ผ่าน" EscalationChecker จะหยุดการวนซ้ำ
  2. SequentialAgent: การดำเนินการนี้จะเหมือนกับการเรียกใช้สคริปต์มาตรฐาน โดยจะเรียกใช้ Agent ทีละตัว เราใช้ข้อมูลนี้สำหรับไปป์ไลน์ระดับสูง
    • ก่อนอื่น ให้เรียกใช้วงจรการวิจัย (จนกว่าจะเสร็จสิ้นด้วยข้อมูลที่ดี)
    • จากนั้นเรียกใช้เครื่องมือสร้างเนื้อหา (เพื่อเขียนหลักสูตร)

การรวมทั้ง 2 อย่างนี้เข้าด้วยกันทำให้เราสร้างระบบที่มีประสิทธิภาพซึ่งสามารถแก้ไขตัวเองได้ก่อนที่จะสร้างเอาต์พุตสุดท้าย

2. ตั้งค่า

การตั้งค่าสภาพแวดล้อม

เปิด 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 เพื่อเชื่อมโยงเครดิตการเริ่มต้นใช้งานกับระบบการเรียกเก็บเงิน
    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 เพื่อการจัดการทรัพยากร Dependency ที่รวดเร็ว

  1. ติดตั้งการอ้างอิงของโปรเจ็กต์ด้วยคำสั่งต่อไปนี้
    # Ensure you have uv installed: pip install uv
    uv sync
    
  2. ตั้งค่ารหัสโปรเจ็กต์ Google Cloud
    • เคล็ดลับ: คุณดูรหัสโปรเจ็กต์ได้ในแดชบอร์ด Cloud Console หรือโดยการเรียกใช้ 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
    
    คำเตือน: ตัวแปรสภาพแวดล้อมจะไม่คงอยู่เมื่อเปิดเซสชันเทอร์มินัลใหม่ หากเปิดแท็บเทอร์มินัลใหม่ คุณต้องเรียกใช้คำสั่งส่งออกเหล่านี้อีกครั้ง

3. 🕵️ Agent ผู้ช่วยค้นคว้าวิจัย

Agent นักวิจัย

นักวิจัยคือผู้เชี่ยวชาญ หน้าที่ของเครื่องมือนี้มีเพียงการค้นหาข้อมูล โดยต้องมีสิทธิ์เข้าถึงเครื่องมือ Google Search

เหตุใดจึงแยก Researcher

เจาะลึก: ทำไมไม่ให้เอเจนต์คนเดียวทำทุกอย่าง

เอเจนต์ขนาดเล็กที่มุ่งเน้นเฉพาะทางจะประเมินและแก้ไขข้อบกพร่องได้ง่ายกว่า หากการค้นหาไม่ดี ให้ทำซ้ำพรอมต์ของนักวิจัย หากการจัดรูปแบบหลักสูตรไม่ดี คุณจะทำซ้ำในเครื่องมือสร้างเนื้อหา ในพรอมต์แบบโมโนลิธที่ "ทำทุกอย่าง" การแก้ไขสิ่งหนึ่งมักจะทำให้สิ่งอื่นเสีย

  1. หากคุณทำงานใน Cloud Shell ให้เรียกใช้คำสั่งต่อไปนี้เพื่อเปิด Cloud Shell Editor
    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 จะเรียกใช้ฟังก์ชัน Python google_search และส่งผลลัพธ์กลับไปยังโมเดล

4. ⚖️ ตัวแทนผู้พิพากษา

Agent ผู้ตัดสิน

แม้ว่า Researcher จะทำงานอย่างหนัก แต่ LLM อาจขี้เกียจได้ เราต้องการผู้พิพากษาเพื่อตรวจสอบผลงาน กรรมการยอมรับการวิจัยและส่งคืนการประเมินแบบผ่าน/ไม่ผ่านที่มีโครงสร้าง

เอาต์พุตที่มีโครงสร้าง

เจาะลึก: เราต้องมีเอาต์พุตที่คาดการณ์ได้เพื่อทำให้เวิร์กโฟลว์เป็นอัตโนมัติ การรีวิวแบบข้อความที่ยาวเหยียดจะแยกวิเคราะห์โดยอัตโนมัติได้ยาก การบังคับใช้สคีมา JSON (โดยใช้ Pydantic) ช่วยให้มั่นใจได้ว่า Judge จะแสดงผลบูลีน pass หรือ fail ที่โค้ดของเราสามารถดำเนินการได้อย่างน่าเชื่อถือ

  1. เปิด agents/judge/agent.py
  2. กำหนดสคีมา JudgeFeedback และ Agent 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 ช่วยให้คุณเรียกใช้เอเจนต์แต่ละตัวได้

แนวคิดหลัก: รันไทม์แบบอินเทอร์แอกทีฟ

adk run จะสร้างสภาพแวดล้อมที่มีน้ำหนักเบาซึ่งคุณเป็น "ผู้ใช้" ซึ่งช่วยให้คุณทดสอบวิธีการของเอเจนต์และการใช้เครื่องมือแยกกันได้ หากเอเจนต์ทำงานไม่สำเร็จในขั้นตอนนี้ (เช่น ใช้ Google Search ไม่ได้) ก็จะทำงานไม่สำเร็จในการจัดระเบียบอย่างแน่นอน

  1. เรียกใช้ Researcher แบบอินเทอร์แอกทีฟ โปรดทราบว่าเราจะชี้ไปยังไดเรกทอรีของเอเจนต์ที่เฉพาะเจาะจง
    # 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=us-central1
    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 Agent
    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. 🎻 The Orchestrator

Orchestrator Agent

Orchestrator เป็นผู้จัดการทีมแบบหลายเอเจนต์ของเรา ต่างจากตัวแทนผู้เชี่ยวชาญ (นักวิจัย ผู้ตัดสิน ผู้สร้างเนื้อหา) ที่ทำงานเฉพาะอย่าง งานของ Orchestrator คือการประสานงานเวิร์กโฟลว์และตรวจสอบว่าข้อมูลไหลเวียนระหว่างตัวแทนอย่างถูกต้อง

🌐 สถาปัตยกรรม: Agent-to-Agent (A2A)

สถาปัตยกรรม A2A

ใน Lab นี้ เราจะสร้างระบบแบบกระจาย เราจะทำให้เอเจนต์ทำงานเป็นไมโครเซอร์วิสอิสระแทนที่จะให้เอเจนต์ทั้งหมดทำงานในกระบวนการ Python เดียว ซึ่งช่วยให้แต่ละเอเจนต์ปรับขนาดได้อย่างอิสระและล้มเหลวได้โดยไม่ทำให้ระบบทั้งหมดล่ม

เราใช้โปรโตคอลAgent-to-Agent (A2A) เพื่อให้การดำเนินการนี้เป็นไปได้

โปรโตคอล A2A

เจาะลึก: ในระบบที่ใช้งานจริง เอเจนต์จะทำงานบนเซิร์ฟเวอร์ที่แตกต่างกัน (หรือแม้แต่ในระบบคลาวด์ที่แตกต่างกัน) โปรโตคอล A2A สร้างวิธีมาตรฐานให้แอปค้นพบและสื่อสารกันผ่าน HTTP RemoteA2aAgent เป็นไคลเอ็นต์ ADK สำหรับโปรโตคอลนี้

  1. เปิด agents/orchestrator/agent.py
  2. ค้นหาความคิดเห็น # TODO: Define 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

เจาะลึก: ตัวแทนบางรายไม่ได้ใช้ LLM บางครั้งคุณก็ต้องการตรรกะ Python ที่เรียบง่าย BaseAgent ช่วยให้คุณกำหนด Agent ที่เรียกใช้โค้ดเท่านั้นได้ ในกรณีนี้ เราจะตรวจสอบสถานะเซสชันและใช้ 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. 🔁 วงจรการวิจัย

วงจรการวิจัย

เราต้องการวงจรความคิดเห็น: การวิจัย -> การตัดสิน -> (ล้มเหลว) -> การวิจัย -> ...

  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) เราจะถือว่า research_loop เป็นเหมือนเอเจนต์ย่อยอื่นๆ ใน SequentialAgent ความสามารถในการประกอบนี้ช่วยให้คุณสร้างตรรกะที่ซับซ้อนได้โดยการซ้อนรูปแบบที่เรียบง่าย (ลูปภายในลำดับ ลำดับภายในเราเตอร์ ฯลฯ)

11. 💻 เรียกใช้ในเครื่อง

ก่อนที่จะเรียกใช้ทุกอย่าง มาดูวิธีที่ ADK จำลองสภาพแวดล้อมแบบกระจายในเครื่องกันก่อน

เจาะลึก: วิธีการทำงานของการพัฒนาในพื้นที่

ในสถาปัตยกรรมแบบไมโครเซอร์วิส เอเจนต์ทุกตัวจะทำงานเป็นเซิร์ฟเวอร์ของตัวเอง เมื่อทำการติดตั้งใช้งาน คุณจะมีบริการ Cloud Run 4 รายการที่แตกต่างกัน การจำลองนี้ในเครื่องอาจเป็นเรื่องยากหากคุณต้องเปิดแท็บเทอร์มินัล 4 แท็บและเรียกใช้คำสั่ง 4 คำสั่ง

สคริปต์นี้จะเริ่มกระบวนการ uvicorn สำหรับ Researcher (พอร์ต 8001), Judge (8002) และ Content Builder (8003) โดยจะตั้งค่าตัวแปรสภาพแวดล้อม เช่น RESEARCHER_AGENT_CARD_URL และส่งไปยัง Orchestrator (พอร์ต 8004) นี่คือวิธีที่เราจะกำหนดค่าในระบบคลาวด์ในภายหลัง

แอปที่ทำงานอยู่

  1. เรียกใช้สคริปต์การจัดกลุ่ม
    ./run_local.sh
    
    คำสั่งนี้จะเริ่มกระบวนการแยกกัน 4 รายการ
  2. ทดสอบ
    • หากใช้ Cloud Shell: คลิกปุ่มตัวอย่างเว็บ (ด้านขวาบนของเทอร์มินัล) -> แสดงตัวอย่างบนพอร์ต 8080 -> เปลี่ยนพอร์ตเป็น 8000
    • หากเรียกใช้ในเครื่อง: เปิด http://localhost:8000 ในเบราว์เซอร์
    • พรอมต์: "สร้างหลักสูตรเกี่ยวกับประวัติศาสตร์ของกาแฟ"
    • สังเกต: Orchestrator จะโทรหานักวิจัย โดยผลลัพธ์จะส่งไปยังผู้พิพากษา หากกรรมการไม่เห็นด้วย วงจรก็จะดำเนินต่อไป
    การแก้ปัญหา:
    • "ข้อผิดพลาดเกี่ยวกับเซิร์ฟเวอร์ภายใน" / ข้อผิดพลาดในการตรวจสอบสิทธิ์: หากคุณเห็นข้อผิดพลาดในการตรวจสอบสิทธิ์ (เช่น เกี่ยวข้องกับ google-auth) โปรดตรวจสอบว่าคุณได้เรียกใช้ gcloud auth application-default login หากเรียกใช้ในเครื่อง ใน Cloud Shell ให้ตรวจสอบว่าได้ตั้งค่าGOOGLE_CLOUD_PROJECTตัวแปรสภาพแวดล้อมอย่างถูกต้อง
    • ข้อผิดพลาดของเทอร์มินัล: หากคำสั่งล้มเหลวในหน้าต่างเทอร์มินัลใหม่ อย่าลืมส่งออกตัวแปรสภาพแวดล้อมอีกครั้ง (GOOGLE_CLOUD_PROJECT ฯลฯ)
  3. การทดสอบเอเจนต์แบบแยกกัน: แม้ว่าระบบทั้งหมดจะทำงานอยู่ คุณก็ทดสอบเอเจนต์ที่เฉพาะเจาะจงได้โดยกำหนดเป้าหมายไปยังพอร์ตของเอเจนต์โดยตรง ซึ่งมีประโยชน์สำหรับการแก้ไขข้อบกพร่องของคอมโพเนนต์ที่เฉพาะเจาะจงโดยไม่ต้องเรียกใช้ทั้งเชน
    • นักวิจัยเท่านั้น (พอร์ต 8001): http://localhost:8001
    • ผู้พิพากษาเท่านั้น (พอร์ต 8002): http://localhost:8002
    • Content Builder เท่านั้น (พอร์ต 8003): http://localhost:8003
    • Orchestrator (พอร์ต 8004): http://localhost:8004 (การเข้าถึงตรรกะของ Orchestrator โดยตรง)

12. 🚀 ทำให้ใช้งานได้กับ Cloud Run

การตรวจสอบขั้นสุดท้ายจะทำงานในระบบคลาวด์ เราจะติดตั้งใช้งานเอเจนต์แต่ละตัวเป็นบริการแยกกัน

ทำความเข้าใจการกำหนดค่าการทำให้ใช้งานได้

เมื่อติดตั้งใช้งาน Agent ใน Cloud Run เราจะส่งตัวแปรสภาพแวดล้อมหลายรายการเพื่อกำหนดค่าลักษณะการทำงานและการเชื่อมต่อของ Agent ดังนี้

  • GOOGLE_CLOUD_PROJECT: ตรวจสอบว่าเอเจนต์ใช้โปรเจ็กต์ Google Cloud ที่ถูกต้องสำหรับการบันทึกและการเรียก Vertex AI
  • GOOGLE_GENAI_USE_VERTEXAI: บอกให้เฟรมเวิร์กของ Agent (ADK) ใช้ Vertex AI สำหรับการอนุมานโมเดลแทนการเรียกใช้ Gemini API โดยตรง
  • [AGENT]_AGENT_CARD_URL: ข้อมูลนี้มีความสำคัญอย่างยิ่งสำหรับ Orchestrator ซึ่งจะบอก Orchestrator ว่าจะค้นหา Agent ระยะไกลได้ที่ไหน การตั้งค่านี้เป็น URL ของ Cloud Run ที่ใช้งานจริง (โดยเฉพาะเส้นทางการ์ดเอเจนต์) จะช่วยให้ Orchestrator ค้นพบและสื่อสารกับ Researcher, Judge และ Content Builder ผ่านอินเทอร์เน็ตได้
  1. ติดตั้งใช้งาน Researcher:
    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. ติดตั้งใช้งาน Judge:
    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. ติดตั้งใช้งาน Content Builder:
    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 ที่ติดตั้งใช้งาน ตอนนี้ระบบทำงานในระบบคลาวด์ทั้งหมด โดยใช้โครงสร้างพื้นฐานแบบไม่มีเซิร์ฟเวอร์ของ Google เพื่อปรับขนาดเอเจนต์เคล็ดลับ: คุณจะเห็นไมโครเซอร์วิสทั้งหมดและ URL ของไมโครเซอร์วิสเหล่านั้นในอินเทอร์เฟซ Cloud Run

13. สรุป

ยินดีด้วย คุณสร้างและติดตั้งใช้งานระบบแบบหลายเอเจนต์แบบกระจายที่พร้อมใช้งานจริงเรียบร้อยแล้ว

สิ่งที่เราทำสำเร็จ

  • แยกย่อยงานที่ซับซ้อน: เราแบ่งงานออกเป็นบทบาทเฉพาะทาง (นักวิจัย ผู้ตัดสิน ผู้สร้างเนื้อหา) แทนที่จะใช้พรอมต์ขนาดใหญ่เพียงรายการเดียว
  • การควบคุมคุณภาพที่ใช้: เราใช้LoopAgentและJudgeที่มีโครงสร้างเพื่อให้แน่ใจว่ามีเพียงข้อมูลคุณภาพสูงเท่านั้นที่จะไปถึงขั้นตอนสุดท้าย
  • สร้างขึ้นเพื่อการผลิต: เราใช้โปรโตคอล Agent-to-Agent (A2A) และ Cloud Run เพื่อสร้างระบบที่แต่ละ Agent เป็นไมโครเซอร์วิสแบบอิสระที่ปรับขนาดได้ ซึ่งมีความเสถียรกว่าการเรียกใช้ทุกอย่างในสคริปต์ Python เดียวมาก
  • การประสานงาน: เราใช้ SequentialAgent และ LoopAgent เพื่อกำหนดรูปแบบโฟลว์การควบคุมที่ชัดเจน

ขั้นตอนถัดไป

ตอนนี้คุณมีพื้นฐานแล้ว จึงขยายระบบนี้ได้โดยทำดังนี้

  • เพิ่มเครื่องมืออื่นๆ: ให้สิทธิ์เข้าถึงเอกสารภายในหรือ API แก่นักวิจัย
  • ปรับปรุงผู้ประเมิน: เพิ่มเกณฑ์ที่เฉพาะเจาะจงมากขึ้น หรือแม้แต่ขั้นตอน "มนุษย์ในวงจร"
  • สลับโมเดล: ลองใช้โมเดลอื่นสำหรับเอเจนต์ต่างๆ (เช่น โมเดลที่เร็วกว่าสำหรับผู้พิพากษา โมเดลที่แข็งแกร่งกว่าสำหรับผู้เขียนเนื้อหา)

ตอนนี้คุณพร้อมที่จะสร้างเวิร์กโฟลว์เอเจนต์ที่ซับซ้อนและเชื่อถือได้ใน Google Cloud แล้ว