ai-agents-for-beginners

איך לעצב סוכני AI טובים

(לחצו על התמונה למעלה לצפייה בסרטון של השיעור הזה)

תבנית עיצוב שימוש בכלים

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

הקדמה

בשיעור זה, אנו מחפשים לענות על השאלות הבאות:

מטרות למידה

לאחר השלמת השיעור, תוכלו:

מהי תבנית עיצוב שימוש בכלים?

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

לאילו מקרי שימוש ניתן ליישם אותה?

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

מהם האלמנטים/אבני הבניין הדרושים ליישום תבנית עיצוב שימוש בכלים?

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

בהמשך, נבחן את קריאות הפונקציה/כלי בפירוט רב יותר.

קריאות פונקציה/כלי

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

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

  1. מודל LLM שתומך בקריאת פונקציות
  2. סכימה המכילה תיאורי פונקציות
  3. הקוד עבור כל פונקציה שמתוארת

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

  1. אתחול LLM שתומך בקריאת פונקציות:

    לא כל המודלים תומכים בקריאת פונקציות, לכן חשוב לבדוק שה-LLM שבו אתם משתמשים כן תומך. Azure OpenAI תומך בקריאת פונקציות. ניתן להתחיל על ידי אתחול לקוח Azure OpenAI.

     # Initialize the Azure OpenAI client
     client = AzureOpenAI(
         azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
         api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
         api_version="2024-05-01-preview"
     )
    
  2. יצירת סכימת פונקציה:

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

     # Function description for the model to read
     tools = [
         {
             "type": "function",
             "function": {
                 "name": "get_current_time",
                 "description": "Get the current time in a given location",
                 "parameters": {
                     "type": "object",
                     "properties": {
                         "location": {
                             "type": "string",
                             "description": "The city name, e.g. San Francisco",
                         },
                     },
                     "required": ["location"],
                 },
             }
         }
     ]
    
      
     # Initial user message
     messages = [{"role": "user", "content": "What's the current time in San Francisco"}] 
      
     # First API call: Ask the model to use the function
       response = client.chat.completions.create(
           model=deployment_name,
           messages=messages,
           tools=tools,
           tool_choice="auto",
       )
      
       # Process the model's response
       response_message = response.choices[0].message
       messages.append(response_message)
      
       print("Model's response:")  
    
       print(response_message)
      
    
     Model's response:
     ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
    
  3. הקוד של הפונקציה הנדרש לביצוע המשימה:

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

       def get_current_time(location):
         """Get the current time for a given location"""
         print(f"get_current_time called with location: {location}")  
         location_lower = location.lower()
            
         for key, timezone in TIMEZONE_DATA.items():
             if key in location_lower:
                 print(f"Timezone found for {key}")  
                 current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
                 return json.dumps({
                     "location": location,
                     "current_time": current_time
                 })
          
         print(f"No timezone data found for {location_lower}")  
         return json.dumps({"location": location, "current_time": "unknown"})
    
      # Handle function calls
       if response_message.tool_calls:
           for tool_call in response_message.tool_calls:
               if tool_call.function.name == "get_current_time":
         
                   function_args = json.loads(tool_call.function.arguments)
         
                   time_response = get_current_time(
                       location=function_args.get("location")
                   )
         
                   messages.append({
                       "tool_call_id": tool_call.id,
                       "role": "tool",
                       "name": "get_current_time",
                       "content": time_response,
                   })
       else:
           print("No tool calls were made by the model.")  
      
       # Second API call: Get the final response from the model
       final_response = client.chat.completions.create(
           model=deployment_name,
           messages=messages,
       )
      
       return final_response.choices[0].message.content
    
       get_current_time called with location: San Francisco
       Timezone found for san francisco
       The current time in San Francisco is 09:24 AM.
    

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

דוגמאות לשימוש בכלים עם מסגרות סוכנים

להלן כמה דוגמאות כיצד ניתן ליישם את תבנית עיצוב שימוש בכלים באמצעות מסגרות סוכנים שונות:

Semantic Kernel

Semantic Kernel היא מסגרת AI בקוד פתוח עבור מפתחים ב-.NET, פייתון וג’אווה העובדים עם מודלים שפתיים גדולים (LLMs). היא מפשטת את תהליך השימוש בקריאת פונקציות על ידי תיאור אוטומטי של הפונקציות והפרמטרים שלהן למודל באמצעות תהליך שנקרא serializing. היא גם מנהלת את התקשורת בין המודל לקוד שלכם. יתרון נוסף בשימוש במסגרת סוכנים כמו Semantic Kernel הוא שהיא מאפשרת לכם לגשת לכלים מוכנים מראש כמו File Search ו-Code Interpreter.

התרשים הבא ממחיש את תהליך קריאת הפונקציות עם Semantic Kernel:

קריאת פונקציות

ב-Semantic Kernel פונקציות/כלים נקראים Plugins. ניתן להמיר את פונקציית get_current_time שראינו קודם לפלאגין על ידי הפיכתה למחלקה עם הפונקציה בתוכה. ניתן גם לייבא את הדקורטור kernel_function, שמקבל את תיאור הפונקציה. כאשר יוצרים Kernel עם GetCurrentTimePlugin, ה-Kernel ייצור באופן אוטומטי את הסכימה לשליחה ל-LLM בתהליך.

from semantic_kernel.functions import kernel_function

class GetCurrentTimePlugin:
    async def __init__(self, location):
        self.location = location

    @kernel_function(
        description="Get the current time for a given location"
    )
    def get_current_time(location: str = ""):
        ...

from semantic_kernel import Kernel

# Create the kernel
kernel = Kernel()

# Create the plugin
get_current_time_plugin = GetCurrentTimePlugin(location)

# Add the plugin to the kernel
kernel.add_plugin(get_current_time_plugin)

Azure AI Agent Service

Azure AI Agent Service היא מסגרת סוכנים חדשה יותר שמיועדת להעצים מפתחים לבנות, לפרוס ולסקור סוכני AI איכותיים ומורחבים בצורה מאובטחת, מבלי לנהל את משאבי המחשוב והאחסון הבסיסיים. היא שימושית במיוחד ליישומים ארגוניים מכיוון שהיא שירות מנוהל לחלוטין עם אבטחה ברמה ארגונית.

בהשוואה לפיתוח ישיר עם API של LLM, Azure AI Agent Service מספקת כמה יתרונות, כולל:

הכלים הזמינים ב-Azure AI Agent Service יכולים להתחלק לשתי קטגוריות:

  1. כלים מבוססי ידע:
  2. כלים מבוססי פעולה:

שירות הסוכנים מאפשר לנו להשתמש בכלים אלו יחד כ-toolset. הוא גם משתמש ב-threads שעוקבים אחר היסטוריית ההודעות משיחה מסוימת.

דמיינו שאתם סוכן מכירות בחברה בשם Contoso. אתם רוצים לפתח סוכן שיחה שיכול לענות על שאלות לגבי נתוני המכירות שלכם.

התמונה הבאה ממחישה כיצד תוכלו להשתמש ב-Azure AI Agent Service לניתוח נתוני המכירות שלכם:

שירות סוכנים בפעולה

כדי להשתמש בכל אחד מהכלים הללו עם השירות, ניתן ליצור לקוח ולהגדיר כלי או קבוצת כלים. כדי ליישם זאת באופן מעשי, ניתן להשתמש בקוד פייתון הבא. ה-LLM יוכל להסתכל על קבוצת הכלים ולהחליט האם להשתמש בפונקציה שנוצרה על ידי המשתמש, fetch_sales_data_using_sqlite_query, או ב-Code Interpreter המוכן מראש, בהתאם לבקשת המשתמש.

import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # fetch_sales_data_using_sqlite_query function which can be found in a fetch_sales_data_functions.py file.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool

project_client = AIProjectClient.from_connection_string(
    credential=DefaultAzureCredential(),
    conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)

# Initialize function calling agent with the fetch_sales_data_using_sqlite_query function and adding it to the toolset
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset = ToolSet()
toolset.add(fetch_data_function)

# Initialize Code Interpreter tool and adding it to the toolset. 
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset = ToolSet()
toolset.add(code_interpreter)

agent = project_client.agents.create_agent(
    model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent", 
    toolset=toolset
)

מהם השיקולים המיוחדים לשימוש בתבנית עיצוב שימוש בכלים לבניית סוכני AI אמינים?

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

דוגמאות קוד

יש לכם עוד שאלות על דפוסי עיצוב לשימוש בכלי?

הצטרפו ל-Azure AI Foundry Discord כדי לפגוש לומדים אחרים, להשתתף בשעות קבלה ולקבל תשובות לשאלות שלכם על AI Agents.

משאבים נוספים

שיעור קודם

הבנת דפוסי עיצוב סוכנים

שיעור הבא

Agentic RAG


כתב ויתור:
מסמך זה תורגם באמצעות שירות תרגום מבוסס בינה מלאכותית Co-op Translator. למרות שאנו שואפים לדיוק, יש להיות מודעים לכך שתרגומים אוטומטיים עשויים להכיל שגיאות או אי-דיוקים. המסמך המקורי בשפתו המקורית צריך להיחשב כמקור הסמכותי. למידע קריטי, מומלץ להשתמש בתרגום מקצועי על ידי בני אדם. איננו נושאים באחריות לאי-הבנות או לפרשנויות שגויות הנובעות משימוש בתרגום זה.