קריאה לכלי, שנקראת גם קריאה לפונקציה, היא דרך מובנית לתת ל-LLMs את היכולת לשלוח בקשות חזרה לאפליקציה שהפעילה אותם. אתם מגדירים את הכלים שרוצים להפוך לזמינים למודל, והמודל ישלח לאפליקציה בקשות לשימוש בכלים לפי הצורך כדי לבצע את ההנחיות שתספקו לו.
תרחישי השימוש של קריאה לכלים מתחלקים בדרך כלל לכמה נושאים:
מתן גישה של LLM למידע שלא אומן עליו
- מידע שמשתנה לעיתים קרובות, כמו מחיר מניה או מזג האוויר הנוכחי.
- מידע ספציפי לדומיין של האפליקציה, כמו פרטי מוצרים או פרופילים של משתמשים.
שימו לב לחפיפה עם יצירה משופרת של טקסטים (RAG), שהיא גם דרך לאפשר ל-LLM לשלב מידע עובדתי ביצירה של טקסטים. RAG הוא פתרון כבד יותר שמתאים במיוחד כשיש כמות גדולה של מידע או כשהמידע הרלוונטי ביותר להנחיה הוא לא ברור. לעומת זאת, אם קריאה לפונקציה או חיפוש במסד נתונים הם כל מה שדרוש כדי לאחזר את המידע ש-LLM צריך, קריאה לכלי מתאימה יותר.
הוספת מידה מסוימת של דטרמיניזם לתהליך עבודה של LLM
- ביצוע חישובים ש-LLM לא יכול להשלים בעצמו באופן מהימן.
- איך מאלצים LLM ליצור טקסט מילה במילה בנסיבות מסוימות, למשל כאשר עונים על שאלה לגבי התנאים וההגבלות של אפליקציה.
ביצוע פעולה כשהיא מופעלת על ידי LLM
- הפעלה והשבתה של אורות בעזרת עוזרת בית מבוססת-LLM
- הזמנת שולחן בסוכנות מסעדות שמבוססת על LLM
לפני שמתחילים
כדי להריץ את דוגמאות הקוד בדף הזה, צריך לבצע קודם את השלבים שמפורטים במדריך תחילת השימוש. כל הדוגמאות מבוססות על ההנחה שכבר הגדרתם פרויקט עם יחסי התלות של Genkit מותקנים.
בדף הזה מוסבר על אחת מהתכונות המתקדמות של הפשטת המודלים ב-Genkit, לכן לפני שתעמיקו מדי, כדאי שתכירו את התוכן בדף יצירת תוכן באמצעות מודלים של AI. כדאי גם להכיר את המערכת של Genkit להגדרת סכימות קלט ופלט. המערכת הזו מפורטת בדף תהליכים.
סקירה כללית על קריאה לכלי
באופן כללי, כך נראית אינטראקציה טיפוסית של קריאה לכלי עם LLM:
- אפליקציית הקריאה שולחת בקשה ל-LLM, ומצרפת להנחיה גם רשימה של כלים שבהם ה-LLM יכול להשתמש כדי ליצור תשובה.
- ה-LLM יוצר תשובה מלאה או בקשה לקריאה לכלי בפורמט ספציפי.
- אם הגורם הקורא מקבל תשובה מלאה, הבקשה מתמלאת והאינטראקציה מסתיימת. לעומת זאת, אם הגורם הקורא מקבל קריאה לכלי, הוא מבצע את הלוגיקה המתאימה ושולח בקשה חדשה ל-LLM שמכילה את ההנחיה המקורית או וריאציה כלשהי שלה, וגם את התוצאה של הקריאה לכלי.
- ה-LLM מטפל בהנחיה החדשה כמו בשלב 2.
כדי שהתכונה הזו תפעל, צריך לעמוד בכמה דרישות:
- צריך לאמן את המודל לבקש כלים כשצריך כדי להשלים הנחיה. רוב המודלים הגדולים יותר שזמינים דרך ממשקי API לאינטרנט, כמו Gemini, יכולים לעשות זאת, אבל לרוב מודלים קטנים יותר ומודלים ייעודיים יותר לא יכולים. אם תנסו לספק כלים למודל שלא תומך בהם, תופיע הודעת שגיאה ב-Genkit.
- האפליקציה הקוראת חייבת לספק הגדרות של כלים למודל בפורמט שהוא מצפה לו.
- האפליקציה הקוראת צריכה להנחות את המודל ליצור בקשות לקריאה לכלי בפורמט שהאפליקציה מצפה לו.
שימוש בכלי ליצירת שיחות עם Genkit
Genkit מספק ממשק יחיד לקריאה של כלים במודלים שתומכים בכך.
כל פלאגין של מודל מוודא שהשניים האחרונים מהקריטריונים שצוינו בקטע הקודם מתקיימים, והפונקציה genkit.Generate()
מבצעת באופן אוטומטי את הלולאה של קריאת הכלי שתיארנו קודם.
תמיכה במודלים
התמיכה בקריאה לכלי תלויה בדגם, ב-API של הדגם ובפלאגין של Genkit. כדאי לעיין במסמכי התיעוד הרלוונטיים כדי לבדוק אם יש סיכוי שהכלי יתמוך בקריאה. בנוסף:
- אם תנסו לספק כלים למודל שלא תומך בהם, תופיע הודעת שגיאה ב-Genkit.
- אם הפלאגין מייצא הפניות לדגמים, המאפיין
ModelInfo.Supports.Tools
יציין אם הוא תומך בקריאה לכלי.
הגדרת כלים
משתמשים בפונקציה genkit.DefineTool()
כדי לכתוב הגדרות של כלים:
import (
"context"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
ctx := context.Background()
g, err := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-2.0-flash"),
)
if err != nil {
log.Fatal(err)
}
getWeatherTool := genkit.DefineTool(
g, "getWeather", "Gets the current weather in a given location",
func(ctx *ai.ToolContext, location string) (string, error) {
// Here, we would typically make an API call or database query. For this
// example, we just return a fixed value.
return fmt.Sprintf("The current weather in %s is 63°F and sunny.", location);
})
}
התחביר כאן נראה בדיוק כמו התחביר של genkit.DefineFlow()
, אבל צריך לכתוב תיאור. חשוב להקפיד במיוחד על הניסוח והתיאור של התג, כי הוא חיוני להחלטה של ה-LLM אם להשתמש בו בצורה מתאימה.
שימוש בכלים
כדאי לכלול כלים מוגדרים בהנחיות ליצירת תוכן.
יצירה
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("What is the weather in San Francisco?"),
ai.WithTools(getWeatherTool),
)
DefinePrompt
weatherPrompt, err := genkit.DefinePrompt(g, "weatherPrompt",
ai.WithPrompt("What is the weather in {{location}}?"),
ai.WithTools(getWeatherTool),
)
if err != nil {
log.Fatal(err)
}
resp, err := weatherPrompt.Execute(ctx,
with.Input(map[string]any{"location": "San Francisco"}),
)
קובץ ההנחיה
---
system: "Answer questions using the tools you have."
tools: [getWeather]
input:
schema:
location: string
---
What is the weather in {{location}}?
לאחר מכן תוכלו להריץ את ההנחיה בקוד באופן הבא:
// Assuming prompt file named weatherPrompt.prompt exists in ./prompts dir.
weatherPrompt := genkit.LookupPrompt("weatherPrompt")
if weatherPrompt == nil {
log.Fatal("no prompt named 'weatherPrompt' found")
}
resp, err := weatherPrompt.Execute(ctx,
ai.WithInput(map[string]any{"location": "San Francisco"}),
)
Genkit יטפל באופן אוטומטי בקריאה לכלי אם ה-LLM צריך להשתמש בכלי getWeather
כדי לענות להנחיה.
טיפול מפורש בקריאות לכלי
אם רוצים שליטה מלאה על הלולאה של קריאת הכלים, למשל כדי להחיל לוגיקה מורכבת יותר, מגדירים את האפשרות WithReturnToolRequests()
לערך true
. עכשיו באחריותכם לוודא שכל הבקשות לשימוש בכלים יתקבלו:
getWeatherTool := genkit.DefineTool(
g, "getWeather", "Gets the current weather in a given location",
func(ctx *ai.ToolContext, location string) (string, error) {
// Tool implementation...
})
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("What is the weather in San Francisco?"),
ai.WithTools(getWeatherTool),
ai.WithReturnToolRequests(true),
)
if err != nil {
log.Fatal(err)
}
parts := []*Part{}
for _, req := range resp.ToolRequests() {
tool := genkit.LookupTool(g, req.Name)
if tool == nil {
log.Fatalf("tool %q not found", req.Name)
}
output, err := tool.RunRaw(ctx, req.Input)
if err != nil {
log.Fatalf("tool %q execution failed: %v", err)
}
parts = append(parts,
ai.NewToolResponsePart(&ai.ToolResponse{
Name: req.Name,
Ref: req.Ref,
Output: output,
}))
}
resp, err = genkit.Generate(ctx, g,
ai.WithMessages(resp.History()..., NewMessage(ai.RoleTool, nil, parts...)),
)
if err != nil {
log.Fatal(err)
}