בניית מערכות עם סוכנים מרובים

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

לפניכם כמה קטעים מנציג שירות לקוחות פשוט מאוד שנוצר באמצעות הנחיה אחת וכמה כלים:

const menuLookupTool = ai.defineTool(
  {
    name: 'menuLookupTool',
    description: 'use this tool to look up the menu for a given date',
    inputSchema: z.object({
      date: z.string().describe('the date to look up the menu for'),
    }),
    outputSchema: z.string().describe('the menu for a given date'),
  },
  async (input) => {
    // Retrieve the menu from a database, website, etc.
    // ...
  }
);

const reservationTool = ai.defineTool(
  {
    name: 'reservationTool',
    description: 'use this tool to try to book a reservation',
    inputSchema: z.object({
      partySize: z.coerce.number().describe('the number of guests'),
      date: z.string().describe('the date to book for'),
    }),
    outputSchema: z
      .string()
      .describe(
        "true if the reservation was successfully booked and false if there's" +
          ' no table available for the requested time'
      ),
  },
  async (input) => {
    // Access your database to try to make the reservation.
    // ...
  }
);
const chat = ai.chat({
  model: gemini15Pro,
  system:
    "You are an AI customer service agent for Pavel's Cafe. Use the tools " +
    'available to you to help the customer. If you cannot help the ' +
    'customer with the available tools, politely explain so.',
  tools: [menuLookupTool, reservationTool],
});

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

  • ככל שמוסיפים יותר כלים, כך המודל יכול להשתמש בכלי הנכון למשימה בצורה עקבית ומדויקת יותר.
  • לפעמים עדיף לבצע משימות מסוימות באמצעות שיחה מתמשכת בין המשתמש לנציג התמיכה, במקום באמצעות קריאה אחת לכלי.
  • לחלק מהמשימות כדאי להשתמש בהנחיה ספציפית. לדוגמה, אם הנציג עונה ללקוח לא מרוצה, כדאי שהסגנון שלו יהיה רשמי יותר, ואילו הנציג שמקבל את הלקוח בהתחלה יכול להשתמש בסגנון ידידותי וקליל יותר.

אחת מהגישות לטיפול בבעיות האלה שעולות כשיוצרים סוכנים מורכבים היא ליצור הרבה סוכנים מיוחדים ולהשתמש בסוכנות למטרות כלליות כדי להקצות להם משימות. Genkit תומך בארכיטקטורה הזו ומאפשר לציין הנחיות ככלים. כל הנחיה מייצגת סוכן יעודי אחד, עם קבוצת כלים משלו שזמינה לו. הסוכנים האלה זמינים בתור כלים לסוכן התזמור היחיד, שהוא הממשק הראשי עם המשתמש.

כך עשויה להיראות גרסה מורחבת של הדוגמה הקודמת כמערכת עם כמה סוכנים:

// Define a prompt that represents a specialist agent
const reservationAgent = ai.definePrompt(
  {
    name: 'reservationAgent',
    description: 'Reservation Agent can help manage guest reservations',
    tools: [reservationTool, reservationCancelationTool, reservationListTool],
  },
  '{{role "system"}} Help guests make and manage reservations'
);

// Or load agents from .prompt files
const menuInfoAgent = ai.prompt('menuInfoAgent');
const complaintAgent = ai.prompt('complaintAgent');

// The triage agent is the agent that users interact with initially
const triageAgent = ai.definePrompt(
  {
    name: 'triageAgent',
    description: 'Triage Agent',
    tools: [reservationAgent, menuInfoAgent, complaintAgent],
  },
  `{{role "system"}} You are an AI customer service agent for Pavel's Cafe.
  Greet the user and ask them how you can help. If appropriate, transfer to an
  agent that can better handle the request. If you cannot help the customer with
  the available tools, politely explain so.`
);
// Start a chat session, initially with the triage agent
const chat = ai.chat(triageAgent);