在前一天的盛宴中,我們見識了 Function Calling
這道令人驚豔的主菜,看著我們的 AI 廚師如何根據客人的點單(使用者請求),自動從他的刀具組 (Plugins) 中挑選合適的工具來完成料理。但有時候,作為餐廳的老闆(也就是開發者),我們可能想對廚師的出菜策略有更精準的控制。
有時候,你希望廚師能自由發揮,這叫「主廚特餐」(Chef's Choice)。
有時候,你又希望強制廚師必須使用你剛進貨的頂級松露來做菜,這叫「本日限定」。
還有時候,你只想讓廚師跟客人聊聊天,了解一下口味,暫時不需要動火,這叫「純聊天」。
在 Semantic Kernel 的世界裡,這種對廚師行為的微調,就是透過 FunctionChoiceBehavior
來實現的。它就像是我們給廚師的「出餐指令」,讓他知道這道菜到底該怎麼上。
Auto
, Required
, None
FunctionChoiceBehavior
提供了三種核心模式,讓我們來一一品嚐 :
Auto
(自動模式 - 主廚特餐**)**:
比喻:你對著廚房喊:「客人點了牛排,你看着辦!」
說明:這是最常用也最彈性的模式。AI 模型會根據對話的上下文,自行決定是否需要使用工具 (Function),以及要使用哪一個或哪幾個工具 。AI 會全權判斷,展現它最大的智慧與靈活性。
Required
(必要模式 - 本日限定**)**:
比喻:你對廚師下達死命令:「客人想知道天氣,你『必須』給我用那個天氣預報的工具,不准瞎猜!」
說明:這個模式會強制 AI 必須從你提供的工具清單中,選擇一個或多個來完成任務 。這在什麼時候很有用呢?當你知道某個問題的答案必須來自外部系統(例如:查詢訂單、確認庫存),而不是 AI 的內部知識時,這個模式就能確保 AI 不會「自由發揮」或「產生幻覺」,而是乖乖地使用你指定的工具。
None
(無工具模式 - 純聊天**)**:
比喻:你告訴廚師:「先放下鍋鏟,跟客人聊聊,問清楚他喜歡什麼,還不用開始做菜。」
說明:此模式會暫時禁止 AI 使用任何工具 。AI 仍然知道有哪些工具可以用,但這次請求它不會真的去呼叫。這很適合用在 dry run 的情境,例如,你可以問 AI:「如果要完成這個任務,你會需要用到哪些工具?」AI 會用純文字回覆它會如何規劃,但不會真的去執行,讓我們可以預覽它的思考路徑。
光說不練不是我們的風格,直接來看程式碼,看看這三種模式在實際的廚房裡是如何運作的。
首先,我們需要準備一些基本的工具,例如一個可以查詢天氣的 WeatherPlugin
。
using System.ComponentModel;
using Microsoft.SemanticKernel;
// 我們的天氣工具
public class WeatherPlugin
{
[KernelFunction, Description("取得指定城市的天氣")]
public string GetWeather(
[Description("城市名稱")] string city)
{
// 這裡為了範例簡單,我們回傳假資料
return $"天氣晴朗,溫度 25 度,很適合出門走走!";
}
}
接下來,讓我們看看三種模式的具體應用。
Auto
模式:讓 AI 自由發揮這是啟用 Function Calling 的預設行為。我們告訴 AI 客戶的需求,然後放手讓它自己決定怎麼做。
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
// 建立我們的廚房 (Kernel)
var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion("<model-id>", "<api-key>");
builder.Plugins.AddFromType<WeatherPlugin>();
var kernel = builder.Build();
// 設定出餐指令為 Auto 模式
var executionSettings = new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
// 客人點菜
var result = await kernel.InvokePromptAsync(
"請問波士頓現在天氣如何?",
new(executionSettings));
// AI 廚師會自動呼叫 GetWeather 函式
Console.WriteLine(result);
// 輸出: 天氣晴朗,溫度 25 度,很適合出門走走!
Required
模式:強制 AI 使用工具在這個情境下,我們明確要求 AI 必須使用
WeatherPlugin
裡的 GetWeather
函式來回答問題 。
// ... Kernel 和 Plugin 設定同上 ...
// 從 Kernel 中取得我們要強制使用的函式
var getWeatherFunction = kernel.Plugins.GetFunction("WeatherPlugin", "GetWeather");
// 設定出餐指令為 Required 模式,並指定必須使用 getWeatherFunction
var executionSettings = new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Required(
functions: [getWeatherFunction]
)
};
// 客人點菜,這次我們提供更多資訊,避免 AI 需要多輪對話
var result = await kernel.InvokePromptAsync(
"我需要知道波士頓的天氣,請幫我查詢。",
new(executionSettings));
Console.WriteLine(result);
// 輸出: 天氣晴朗,溫度 25 度,很適合出門走走!
在這個例子中,即使 AI 的訓練資料裡可能有關於波士頓天氣的舊資訊,Required
模式也會強制它去呼叫我們的工具,確保資訊的即時性與準確性。
None
模式:純粹的對話與規劃有時候,我們只想知道 AI 的「計畫」,而不是要它馬上動手。這時
None
模式就派上用場了 。
// ... Kernel 和 Plugin 設定同上 ...
// 設定出餐指令為 None 模式
var executionSettings = new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.None()
};
// 這次我們不問天氣,而是問 AI 它會如何處理這個請求
var result = await kernel.InvokePromptAsync(
"如果我想知道波士頓的天氣,你會使用哪個工具?",
new(executionSettings));
Console.WriteLine(result);
// AI 不會呼叫工具,而是用文字回覆它的計畫
// 輸出可能類似: 我會使用 WeatherPlugin 的 GetWeather 函式,並傳入「波士頓」作為城市參數。
今天我們學會了如何像個真正的餐廳總監一樣,精準地指導我們的 AI 廚師。透過 FunctionChoiceBehavior
的三種模式,我們可以在「完全信任」、「強制執行」和「只說不做」之間自由切換,讓 AI 的行為更貼近我們的業務需求。
Auto
是日常營運的首選,給予 AI 最大的自主權。Required
是確保關鍵任務被執行的金牌指令。None
則是我們在規劃與除錯時的觀察利器。掌握了點菜的藝術,就等於掌握了指揮 AI 大軍的權杖。下一篇文章,我們將探討更細緻的控制權:當 AI 決定要呼叫函式後,我們是否能「手動確認」?敬請期待 Day 10 的「手動還是自動?Function Invocation Modes 的抉擇」!