(לחצו על התמונה למעלה לצפייה בסרטון של השיעור הזה)
כלים הם מעניינים מכיוון שהם מאפשרים לסוכני AI להרחיב את טווח היכולות שלהם. במקום שסוכן יהיה מוגבל למספר פעולות מצומצם, הוספת כלי מאפשרת לו לבצע מגוון רחב של פעולות. בפרק זה נבחן את תבנית העיצוב לשימוש בכלים, שמתארת כיצד סוכני AI יכולים להשתמש בכלים ספציפיים כדי להשיג את מטרותיהם.
בשיעור זה ננסה לענות על השאלות הבאות:
לאחר השלמת השיעור, תוכלו:
תבנית העיצוב לשימוש בכלים מתמקדת במתן יכולת ל-LLMs (מודלים לשפה גדולה) לתקשר עם כלים חיצוניים כדי להשיג מטרות ספציפיות. כלים הם קוד שניתן להריץ על ידי סוכן כדי לבצע פעולות. כלי יכול להיות פונקציה פשוטה כמו מחשבון, או קריאה ל-API של שירות צד שלישי כמו בדיקת מחירי מניות או תחזית מזג אוויר. בהקשר של סוכני AI, כלים מתוכננים להיות מופעלים על ידי סוכנים בתגובה לקריאות פונקציה שנוצרו על ידי המודל.
סוכני AI יכולים לנצל כלים כדי להשלים משימות מורכבות, לאחזר מידע או לקבל החלטות. תבנית העיצוב לשימוש בכלים משמשת לעיתים קרובות בתרחישים הדורשים אינטראקציה דינמית עם מערכות חיצוניות, כמו מסדי נתונים, שירותי רשת או מפרשי קוד. יכולת זו שימושית למגוון מקרים, כולל:
אבני בניין אלו מאפשרות לסוכן AI לבצע מגוון רחב של משימות. בואו נבחן את האלמנטים המרכזיים הנדרשים ליישום תבנית העיצוב לשימוש בכלים:
כעת, נבחן את נושא קריאות הפונקציות/כלים בפירוט.
קריאות פונקציות הן הדרך המרכזית שבה אנו מאפשרים ל-LLMs לתקשר עם כלים. לעיתים קרובות תראו את המונחים ‘פונקציה’ ו’כלי’ משמשים לסירוגין, מכיוון ש’פונקציות’ (בלוקים של קוד לשימוש חוזר) הן ה’כלים’ שבהם סוכנים משתמשים לביצוע משימות. כדי להפעיל את קוד הפונקציה, ה-LLM משווה את בקשת המשתמש לתיאור הפונקציה. לשם כך, סכימה המכילה את תיאורי כל הפונקציות הזמינות נשלחת ל-LLM. ה-LLM בוחר את הפונקציה המתאימה ביותר למשימה ומחזיר את שמה ואת הפרמטרים שלה. הפונקציה הנבחרת מופעלת, תגובתה נשלחת חזרה ל-LLM, שמשתמש במידע כדי להגיב לבקשת המשתמש.
כדי שמפתחים יוכלו ליישם קריאות פונקציות עבור סוכנים, תצטרכו:
בואו נשתמש בדוגמה של קבלת השעה הנוכחית בעיר כדי להמחיש:
אתחול 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"
)
יצירת סכמת פונקציה:
לאחר מכן נגדיר סכמת 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')])
הקוד של הפונקציה הנדרש לביצוע המשימה:
כעת, לאחר שה-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 היא מסגרת 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 היא מסגרת סוכנים חדשה יותר שנועדה לאפשר למפתחים לבנות, לפרוס ולהרחיב סוכני AI איכותיים ומותאמים אישית בצורה מאובטחת, מבלי לנהל את משאבי המחשוב והאחסון הבסיסיים. היא שימושית במיוחד ליישומים ארגוניים מכיוון שהיא שירות מנוהל לחלוטין עם אבטחה ברמה ארגונית.
בהשוואה לפיתוח ישיר עם API של LLM, Azure AI Agent Service מספקת כמה יתרונות, כולל:
הכלים הזמינים ב-Azure AI Agent Service מחולקים לשתי קטגוריות:
שירות הסוכנים מאפשר לנו להשתמש בכלים אלו יחד כ-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
)
דאגה נפוצה עם SQL שנוצר באופן דינמי על ידי LLMs היא אבטחה, במיוחד הסיכון להזרקת SQL או פעולות זדוניות, כמו מחיקת מסד הנתונים או שינויו. למרות שחששות אלו תקפים, ניתן להתמודד איתם ביעילות על ידי הגדרת הרשאות גישה למסד הנתונים בצורה נכונה. עבור רוב מסדי הנתונים, זה כולל הגדרת מסד הנתונים כקריאה בלבד. עבור שירותי מסדי נתונים כמו PostgreSQL או Azure SQL, יש להקצות לאפליקציה תפקיד קריאה בלבד (SELECT).
הרצת האפליקציה בסביבה מאובטחת משפרת עוד יותר את ההגנה. בתרחישים ארגוניים, נתונים בדרך כלל מופקים ומועברים ממערכות תפעוליות למסד נתונים לקריאה בלבד או למחסן נתונים עם סכימה ידידותית למשתמש. גישה זו מבטיחה שהנתונים מאובטחים, מותאמים לביצועים ונגישות, ושלאפליקציה יש גישה מוגבלת לקריאה בלבד.
הצטרפו ל-Azure AI Foundry Discord כדי לפגוש לומדים אחרים, להשתתף בשעות משרד ולקבל תשובות לשאלות שלכם על סוכני AI.
כתב ויתור:
מסמך זה תורגם באמצעות שירות תרגום מבוסס בינה מלאכותית Co-op Translator. בעוד שאנו שואפים לדיוק, יש להיות מודעים לכך שתרגומים אוטומטיים עשויים להכיל שגיאות או אי דיוקים. המסמך המקורי בשפתו המקורית צריך להיחשב כמקור הסמכותי. עבור מידע קריטי, מומלץ להשתמש בתרגום מקצועי על ידי אדם. איננו נושאים באחריות לאי הבנות או לפרשנויות שגויות הנובעות משימוש בתרגום זה.