1. מבוא
סקירה כללית
בשיעור ה-Lab הזה תלמדו איך ליצור מערכת מבוזרת מרובת סוכנים, ולא רק צ'אטבוטים פשוטים.
מודל LLM יחיד יכול לענות על שאלות, אבל המורכבות של העולם האמיתי דורשת לרוב תפקידים מיוחדים. אתם לא מבקשים ממהנדס ה-Backend לעצב את ממשק המשתמש, ואתם לא מבקשים מהמעצב לבצע אופטימיזציה של שאילתות במסד הנתונים. באופן דומה, אנחנו יכולים ליצור סוכני AI מיוחדים שמתמקדים במשימה אחת ומתואמים ביניהם כדי לפתור בעיות מורכבות.
תבנו מערכת ליצירת קורסים שתכלול:
- סוכן מחקר: שימוש ב-
google_searchכדי למצוא מידע עדכני. - סוכן שופט: מבקר את המחקר כדי לבדוק את האיכות והשלמות שלו.
- סוכן ליצירת תוכן: הופך את המחקר לקורס מובנה.
- Orchestrator Agent: ניהול תהליך העבודה והתקשורת בין המומחים האלה.
דרישות מוקדמות
- ידע בסיסי ב-Python.
- היכרות עם מסוף Google Cloud.
הפעולות שתבצעו:
- הגדרת סוכן לשימוש בכלי (
researcher) שיכול לחפש באינטרנט. - הטמעת פלט מובנה באמצעות Pydantic עבור
judge. - התחברות לסוכנים מרוחקים באמצעות פרוטוקול Agent-to-Agent (A2A).
- בונים
LoopAgentכדי ליצור לולאת משוב בין החוקר לבין השופט. - מריצים את המערכת המבוזרת באופן מקומי באמצעות ה-ADK.
- פריסת מערכת מרובת סוכנים ב-Google Cloud Run.
עקרונות של ארכיטקטורה ותזמור
לפני שכותבים קוד, חשוב להבין איך הסוכנים האלה פועלים יחד. אנחנו מפתחים צינור ליצירת קורסים.
עיצוב המערכת

תזמור באמצעות סוכנים
סוכנים רגילים (כמו חוקר) מבצעים עבודה. סוכני תזמור (כמו LoopAgent או SequentialAgent) מנהלים סוכנים אחרים. אין להם כלים משלהם, והכלי שלהם הוא הקצאת הרשאות.
-
LoopAgent: הפעולה הזו דומה ללולאתwhileבקוד. הוא מריץ רצף של סוכנים שוב ושוב עד שתנאי מסוים מתקיים (או עד שמגיעים למספר המקסימלי של איטרציות). אנחנו משתמשים בזה בלולאת המחקר:- החוקר מוצא מידע.
- Judge (שופט) נותן ביקורת על התוצאה.
- אם Judge אומר 'Fail', EscalationChecker מאפשר ללולאה להמשיך.
- אם Judge אומר 'Pass', EscalationChecker מפסיק את הלולאה.
-
SequentialAgent: הפעולה הזו דומה להרצת סקריפט רגיל. הוא מפעיל סוכנים אחד אחרי השני. אנחנו משתמשים בזה בצינור עיבוד הנתונים ברמה גבוהה:- קודם מריצים את Research Loop (עד שהוא מסתיים עם נתונים טובים).
- לאחר מכן, מפעילים את כלי יצירת התוכן (כדי לכתוב את הקורס).
השילוב של כל אלה מאפשר לנו ליצור מערכת חזקה שיכולה לתקן את עצמה לפני יצירת הפלט הסופי.
2. הגדרה
הגדרת הסביבה
פותחים את Cloud Shell: פותחים כרטיסייה חדשה ומקלידים shell.cloud.google.com
קבלת קוד לתחילת הדרך
- משכפלים את מאגר המתחילים לספריית הבית:
cd ~ git clone https://github.com/amitkmaraj/prai-roadshow-lab-1-starter.git cd prai-roadshow-lab-1-starter - מריצים את סקריפט ההגדרה כדי לשייך את הקרדיטים להצטרפות לחיוב.
chmod +x ./init.sh ./init.sh - פותחים את התיקייה הזו בכלי העריכה.
הפעלת ממשקי API
אחרי שיצרתם פרויקט חדש, מריצים את הפקודה הבאה כדי להפעיל את השירותים הנדרשים של Google Cloud:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
aiplatform.googleapis.com \
compute.googleapis.com
התהליך יכול להימשך כמה שניות.
התקנת יחסי תלות
אנחנו משתמשים ב-uv לניהול מהיר של יחסי תלות.
- מתקינים את יחסי התלות של הפרויקט:
# Ensure you have uv installed: pip install uv uv sync - מגדירים את מזהה הפרויקט ב-Google Cloud.
- טיפ: אפשר למצוא את מזהה הפרויקט בלוח הבקרה של Cloud Console או על ידי הפעלת הפקודה
gcloud config get-value project.
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project) - טיפ: אפשר למצוא את מזהה הפרויקט בלוח הבקרה של Cloud Console או על ידי הפעלת הפקודה
- מגדירים את שאר משתני הסביבה:
אזהרה: משתני סביבה לא נשמרים בין הפעלות שונות של הטרמינל. אם פותחים כרטיסיית טרמינל חדשה, חובה להריץ מחדש את פקודות הייצוא האלה.export GOOGLE_CLOUD_LOCATION=us-central1 export GOOGLE_GENAI_USE_VERTEXAI=true
3. 🕵️ סוכן המחקר

החוקר הוא מומחה. התפקיד היחיד שלו הוא למצוא מידע. כדי לעשות את זה, היא צריכה גישה לכלי: חיפוש Google.
למה כדאי להפריד את הכלי 'חוקר'?
ניתוח מעמיק: למה לא להשתמש רק בסוכן אחד שיעשה הכול?
קל יותר להעריך ולנפות באגים בסוכנים קטנים וממוקדים. אם המחקר לא טוב, משפרים את ההנחיה לחוקר. אם הפורמט של הקורס לא טוב, אפשר לחזור על התהליך בכלי ליצירת תוכן. בפרומפט מונוליטי שכולל את כל הפעולות, תיקון של דבר אחד גורם לרוב לבעיה בדבר אחר.
- אם אתם עובדים ב-Cloud Shell, מריצים את הפקודה הבאה כדי לפתוח את Cloud Shell Editor:
אם אתם עובדים בסביבה המקומית, פותחים את סביבת הפיתוח המשולבת (IDE) המועדפת עליכם.cloudshell workspace . - פתיחת
agents/researcher/agent.py. - יוצג שלד עם הערה מסוג TODO.
- מוסיפים את הקוד הבא כדי להגדיר את סוכן
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. ⚖️ סוכן השופט

החוקר עובד קשה, אבל מודלים גדולים של שפה יכולים להיות עצלנים. אנחנו צריכים שופט שיבדוק את העבודה. השופט מקבל את המחקר ומחזיר הערכה מובנית של הצלחה או כישלון.
פלט מובנה
מידע נוסף: כדי להפוך תהליכי עבודה לאוטומטיים, אנחנו צריכים פלט צפוי. קשה לנתח ביקורת טקסט ארוכה ומבולבלת באופן אוטומטי. על ידי אכיפה של סכימת JSON (באמצעות Pydantic), אנחנו מוודאים שהרכיב Judge מחזיר ערך בוליאני pass או fail שהקוד שלנו יכול לפעול על פיו באופן מהימן.
- פתיחת
agents/judge/agent.py. - מגדירים את סכימת
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. הוא לא יכול להחליט 'לשוחח' עם המשתמש או להעביר את הטיפול לסוכן אחר. כך הוא הופך לרכיב דטרמיניסטי בתהליך הלוגי שלנו.
5. 🧪 בדיקה בבידוד
לפני שמקשרים אותם, אפשר לוודא שכל נציג עובד. ה-ADK מאפשר להפעיל סוכנים בנפרד.
מושג מרכזי: סביבת זמן הריצה האינטראקטיבית
adk run מפעיל סביבה קלה שבה אתם ה "משתמשים". כך תוכלו לבדוק את ההוראות של הסוכן ואת השימוש בכלי בנפרד. אם הסוכן נכשל כאן (למשל, אם הוא לא יכול להשתמש בחיפוש Google), הוא ייכשל בוודאות בתיאום.
- מריצים את הכלי 'חוקר' באופן אינטראקטיבי. שימו לב שאנחנו מציינים את ספריית הסוכן הספציפית:
# This runs the researcher agent in interactive mode uv run adk run agents/researcher - בהנחיה בצ'אט, מקלידים:
הוא צריך להשתמש בכלי של חיפוש Google ולהחזיר את התשובה.הערה: אם מוצגת שגיאה שמציינת שהפרויקט, המיקום והשימוש ב-Vertex לא מוגדרים, צריך לוודא שמזהה הפרויקט מוגדר ולהריץ את הפקודה הבאה:Find the population of Tokyo in 2020export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project) export GOOGLE_CLOUD_LOCATION=us-central1 export GOOGLE_GENAI_USE_VERTEXAI=true - יוצאים מהצ'אט (Ctrl+C).
- מריצים את Judge באופן אינטראקטיבי:
uv run adk run agents/judge - בהנחיה לצ'אט, מדמים את הקלט:
התשובה צריכה להיותTopic: Tokyo. Findings: Tokyo is a city.status='fail'כי הממצאים קצרים מדי.
6. ✍️ סוכן ליצירת תוכן

כלי יצירת התוכן הוא הכותב היצירתי. הוא לוקח את המחקר שאושר והופך אותו לקורס.
- פתיחת
agents/content_builder/agent.py. - מגדירים את הסוכן
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

המתזמר הוא המנהל של צוות המולטי-אייג'נט שלנו. בניגוד לסוכנים המומחים (חוקר, שופט, יוצר תוכן) שמבצעים משימות ספציפיות, התפקיד של המנהל הוא לתאם את תהליך העבודה ולוודא שהמידע זורם ביניהם בצורה נכונה.
🌐 הארכיטקטורה: תקשורת בין סוכנים (A2A)

בשיעור ה-Lab הזה נבנה מערכת מבוזרת. במקום להריץ את כל הסוכנים בתהליך Python יחיד, אנחנו פורסים אותם כמיקרו-שירותים עצמאיים. כך כל סוכן יכול להתרחב באופן עצמאי ולהיכשל בלי לגרום לקריסה של המערכת כולה.
כדי לאפשר את זה, אנחנו משתמשים בפרוטוקול Agent-to-Agent (A2A).
פרוטוקול A2A
מידע נוסף: במערכת ייצור, הסוכנים פועלים בשרתים שונים (או אפילו בעננים שונים). פרוטוקול A2A יוצר דרך סטנדרטית לחיפוש ולתקשורת ביניהם באמצעות HTTP. RemoteA2aAgent הוא לקוח ה-ADK של הפרוטוקול הזה.
- פתיחת
agents/orchestrator/agent.py. - מאתרים את התגובה
# TODO: Define Remote Agentsאו את הקטע של הגדרות הסוכן המרוחק. - מוסיפים את הקוד הבא כדי להגדיר את החיבורים. חשוב למקם את הקוד הזה אחרי הייבוא ולפני הגדרות אחרות של סוכנים.
# ... 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 מאפשר להגדיר סוכן שמריץ רק קוד. במקרה הזה, אנחנו בודקים את מצב הסשן ומשתמשים ב-EventActions(escalate=True) כדי לסמן ל-LoopAgent להפסיק.
- עדיין ב-
agents/orchestrator/agent.py. - מחפשים את הפלייסהולדר
EscalationCheckerTODO. - מחליפים אותו בהטמעה הבאה:
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. 🔁 מחזור המחקר

אנחנו צריכים לולאת משוב: מחקר -> שיפוט -> (כישלון) -> מחקר -> ...
- עדיין ב-
agents/orchestrator/agent.py. - מוסיפים את ההגדרה
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 לפי הסדר.
-
researcher: חיפוש נתונים. -
judge: הערכת נתונים. escalation_checker: קובע אםyield Event(escalate=True). אם מתרחשescalate=True, הלולאה נשברת מוקדם. אחרת, הוא יופעל מחדש אצל החוקר (עדmax_iterations).
10. 🔗 צינור עיבוד הנתונים הסופי

לבסוף, מחברים את כל החלקים.
- עדיין ב-
agents/orchestrator/agent.py. - מגדירים את
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). כך בדיוק נגדיר את זה בענן בהמשך!

- מריצים את סקריפט התזמור:
הפקודה הזו מפעילה 4 תהליכים נפרדים../run_local.sh - כדי לבדוק את זה:
- אם משתמשים ב-Cloud Shell: לוחצים על הלחצן Web Preview (בפינה השמאלית העליונה של הטרמינל) -> Preview on port 8080 -> Change port ל-
8000. - אם מריצים באופן מקומי: פותחים את
http://localhost:8000בדפדפן. - הנחיה: "צור קורס על ההיסטוריה של הקפה".
- התבוננות: המארגן יתקשר לחוקר. הפלט עובר לשופט. אם השופט נכשל, הלולאה ממשיכה!
- שגיאת שרת פנימית / שגיאות אימות: אם מופיעות שגיאות אימות (למשל, שגיאות שקשורות ל-
google-auth), צריך לוודא שהפעלתם אתgcloud auth application-default loginאם אתם מריצים את הפקודה במחשב מקומי. ב-Cloud Shell, מוודאים שמשתנה הסביבהGOOGLE_CLOUD_PROJECTמוגדר בצורה נכונה. - שגיאות בטרמינל: אם הפקודה נכשלת בחלון טרמינל חדש, צריך לייצא מחדש את משתני הסביבה (
GOOGLE_CLOUD_PROJECTוכו').
- אם משתמשים ב-Cloud Shell: לוחצים על הלחצן Web Preview (בפינה השמאלית העליונה של הטרמינל) -> Preview on port 8080 -> Change port ל-
- בדיקת סוכנים בבידוד: גם כשהמערכת המלאה פועלת, אפשר לבדוק סוכנים ספציפיים על ידי טירגוט היציאות שלהם ישירות. האפשרות הזו שימושית לניפוי באגים ברכיב ספציפי בלי להפעיל את כל השרשרת.
- חוקרים בלבד (יציאה 8001):
http://localhost:8001 - Judge Only (Port 8002):
http://localhost:8002 - Content Builder Only (Port 8003):
http://localhost:8003 - Orchestrator (יציאה 8004):
http://localhost:8004(גישה ישירה ללוגיקה של Orchestrator)
- חוקרים בלבד (יציאה 8001):
12. 🚀 פריסה ב-Cloud Run
האימות הסופי מתבצע בענן. נפרוס כל סוכן כשירות נפרד.
הסבר על הגדרת התצורה של פריסה
כשפורסים סוכנים ב-Cloud Run, אנחנו מעבירים כמה משתני סביבה כדי להגדיר את ההתנהגות והקישוריות שלהם:
-
GOOGLE_CLOUD_PROJECT: מוודא שהנציג משתמש בפרויקט הנכון ב-Google Cloud לרישום ביומן ולקריאות ל-Vertex AI. -
GOOGLE_GENAI_USE_VERTEXAI: מציין ל-ADK להשתמש ב-Vertex AI להסקת מסקנות ממודלים במקום לקרוא ישירות ל-Gemini API. -
[AGENT]_AGENT_CARD_URL: זה קריטי ל-Orchestrator. הוא מציין ל-Orchestrator איפה נמצאים הסוכנים המרוחקים. אם מגדירים את כתובת ה-URL הזו לכתובת ה-URL של Cloud Run שנפרסה (במיוחד הנתיב של כרטיס הסוכן), אנחנו מאפשרים ל-Orchestrator לגלות את Researcher, Judge ו-Content Builder ולתקשר איתם באינטרנט.
- פריסת הכלי 'חוקר':
מצלמים את כתובת ה-URL: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"RESEARCHER_URL=$(gcloud run services describe researcher --region us-central1 --format='value(status.url)') echo $RESEARCHER_URL - פריסת השופט:
מצלמים את כתובת ה-URL: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"JUDGE_URL=$(gcloud run services describe judge --region us-central1 --format='value(status.url)') echo $JUDGE_URL - פריסת הכלי ליצירת תוכן:
מצלמים את כתובת ה-URL: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"CONTENT_BUILDER_URL=$(gcloud run services describe content-builder --region us-central1 --format='value(status.url)') echo $CONTENT_BUILDER_URL - פריסת Orchestrator: משתמשים במשתני הסביבה שתועדו כדי להגדיר את Orchestrator.
מצלמים את כתובת ה-URL: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"ORCHESTRATOR_URL=$(gcloud run services describe orchestrator --region us-central1 --format='value(status.url)') echo $ORCHESTRATOR_URL - פריסת חזית האתר:
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 - בדיקת פריסה מרחוק: פותחים את כתובת ה-URL של Orchestrator שנפרס. היא פועלת עכשיו באופן מלא בענן, ומנצלת את התשתית ללא שרת של Google כדי להרחיב את הסוכנים שלכם!הערה: כל המיקרו-שירותים וכתובות ה-URL שלהם נמצאים בממשק Cloud Run.
13. סיכום
מעולה! יצרתם ופרסתם בהצלחה מערכת מבוזרת מרובת סוכנים שמוכנה לייצור.
מה השגנו
- פירוק משימה מורכבת: במקום הנחיה אחת גדולה, פיצלנו את העבודה לתפקידים ייעודיים (חוקר, שופט, יוצר תוכן).
- הטמענו בקרת איכות: השתמשנו ב
LoopAgentובJudgeמובנה כדי להבטיח שרק מידע באיכות גבוהה יגיע לשלב הסופי. - מיועד לשימוש בסביבת ייצור: באמצעות פרוטוקול Agent-to-Agent (A2A) ו-Cloud Run, יצרנו מערכת שבה כל סוכן הוא מיקרו-שירות עצמאי שניתן להתאמה לעומס. השיטה הזו הרבה יותר חזקה מאשר הפעלה של הכול בסקריפט Python יחיד.
- תזמור: השתמשנו ב-
SequentialAgentוב-LoopAgentכדי להגדיר דפוסי זרימת בקרה ברורים.
השלבים הבאים
עכשיו שיש לכם את הבסיס, אתם יכולים להרחיב את המערכת הזו:
- הוספת כלים נוספים: נותנים לחוקר גישה למסמכים פנימיים או לממשקי API.
- שיפור השופט: מוסיפים קריטריונים ספציפיים יותר או אפילו שלב של "התערבות אנושית".
- החלפת מודלים: אפשר לנסות להשתמש במודלים שונים לסוכנים שונים (למשל, מודל מהיר יותר לשופט ומודל חזק יותר לכותב התוכן).
עכשיו אתם מוכנים לבנות תהליכי עבודה מורכבים ואמינים מבוססי-סוכנים ב-Google Cloud.