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

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

התרשים הבא ממחיש את תהליך קריאות הפונקציות עם 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 לניתוח נתוני המכירות שלכם:

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

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

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