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 בחר איזו פונקציה יש להפעיל, יש ליישם ולהפעיל את הקוד שמבצע את המשימה. ניתן ליישם את הקוד לקבלת השעה הנוכחית בפייתון. כמו כן, נצטרך לכתוב את הקוד שמוציא את שם הפונקציה והפרמטרים מתגובת ההודעה כדי לקבל את התוצאה הסופית.

       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.

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

שיעור קודם

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

שיעור הבא

Agentic RAG


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