當你建立 AI 函式時,可能需要存取超出 AI 模型參數範圍的上下文資料。 函式庫 Microsoft.Extensions.AI 提供多種機制將資料傳遞給函數委派。
AIFunction 類別
該 AIFunction 型別代表一個可以描述給 AI 服務並呼叫的函式。 你可以透過呼叫其中一個AIFunctionFactory.Create過載來建立AIFunction物件。 但它 AIFunction 也是一個基底類別,你可以從它衍生出來,並實作你自己的 AI 函式類型。
DelegatingAIFunction 提供一種簡單的方法,將現有 AIFunction 資料包裝並附加功能,包括擷取更多資料以供使用。
傳送資料
你可以在函數建立的同時,將資料透過閉包或 AdditionalProperties 與該函數關聯。 如果你自己創建函式,可以隨意填充 AdditionalProperties 。 如果你用來 AIFunctionFactory 建立這個函式,你可以用 AIFunctionFactoryOptions.AdditionalProperties來填充資料。
你也可以擷取與資料相關的任何引用,作為提供給 AIFunctionFactory 的委派的一部分。 也就是說,你可以將你想參考的任何內容嵌入到AIFunction本身的一部分。
功能代理中的存取資料
你可以直接調用你的AIFunction,也可以透過使用FunctionInvokingChatClient來間接調用。 以下章節說明如何利用任一方法存取參數資料。
手動函式調用
如果你手動呼叫 AIFunction,AIFunction.InvokeAsync(AIFunctionArguments, CancellationToken)則會傳入 AIFunctionArguments。 該 AIFunctionArguments 類型包括:
- 一本命名論證詞典。
-
Context:一個任意的函數
IDictionary<object, object>,用於傳遞額外的環境資料到函數中。 -
Services:一個 IServiceProvider,允許
AIFunction從 依賴注入(DI) 容器中解析任意狀態。
如果你想在 AIFunctionFactory.Create 代理中存取 AIFunctionArguments 或 IServiceProvider,請建立一個參數,類型為 IServiceProvider 或 AIFunctionArguments。 該參數會綁定到從AIFunctionArguments傳遞到AIFunction.InvokeAsync()的相關資料。
下列程式代碼顯示範例:
Delegate getWeatherDelegate = (AIFunctionArguments args) =>
{
// Access named parameters from the arguments dictionary.
string? location = args.TryGetValue("location", out object? loc) ? loc.ToString() : "Unknown";
string? units = args.TryGetValue("units", out object? u) ? u.ToString() : "celsius";
return $"Weather in {location}: 35°{units}";
};
// Create the AIFunction.
AIFunction getWeather = AIFunctionFactory.Create(getWeatherDelegate);
// Call the function manually.
var result = await getWeather.InvokeAsync(new AIFunctionArguments
{
{ "location", "Seattle" },
{ "units", "F" }
});
Console.WriteLine($"Function result: {result}");
CancellationToken 也具有特殊情況:若 AIFunctionFactory.Create 代理或 lambda 有 CancellationToken 參數,則該參數會綁定於 CancellationToken 傳遞給 AIFunction.InvokeAsync()的參數。
透過 FunctionInvokingChatClient
FunctionInvokingChatClient 發佈關於目前調用的狀態, FunctionInvokingChatClient.CurrentContext不僅包含參數,還包含所有輸入 ChatMessage 物件、、 ChatOptions以及被調用的函式細節(共計多少個)。 你可以將任何你想要的資料加入ChatOptions.AdditionalProperties,並從FunctionInvokingChatClient.CurrentContext.Options.AdditionalProperties中在AIFunction內提取這些資料。
下列程式代碼顯示範例:
FunctionInvokingChatClient client = new FunctionInvokingChatClient(
new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(apiKey))
.GetChatClient(model).AsIChatClient());
AIFunction getWeather = AIFunctionFactory.Create(() =>
{
// Access named parameters from the arguments dictionary.
AdditionalPropertiesDictionary props =
FunctionInvokingChatClient.CurrentContext.Options.AdditionalProperties;
string location = props["location"].ToString();
string units = props["units"].ToString();
return $"Weather in {location}: 35°{units}";
});
var chatOptions = new ChatOptions
{
Tools = [getWeather],
AdditionalProperties = new AdditionalPropertiesDictionary {
["location"] = "Seattle",
["units"] = "F"
},
};
List<ChatMessage> chatHistory = [
new(ChatRole.System, "You're a helpful weather assistant.")
];
chatHistory.Add(new ChatMessage(ChatRole.User, "What's the weather like?"));
ChatResponse response = await client.GetResponseAsync(chatHistory, chatOptions);
Console.WriteLine($"Response: {response.Text}");
相依性插入
如果你用 FunctionInvokingChatClient 來自動調用函式,那個客戶端會設定一個 AIFunctionArguments 物件,然後傳入 AIFunction。 因為 AIFunctionArguments 包含 IServiceProvider,且該 IServiceProvider 是由 FunctionInvokingChatClient 所提供的,如果你使用標準 DI 方法來建置你的用戶端,那麼 IServiceProvider 會直接傳遞到你的 AIFunction。 當下,你可以查詢任何你在 DI 中想要的資料。
進階技巧
如果你想要更細緻的參數綁定控制,可以使用 AIFunctionFactoryOptions.ConfigureParameterBinding,這樣你就能控制每個參數的填充方式。 例如, MCP C# SDK 採用此技術 自動綁定 DI 參數。
如果你使用 overload AIFunctionFactory.Create(MethodInfo, Func<AIFunctionArguments,Object>, AIFunctionFactoryOptions) ,也可以在建立目標物件時執行任意邏輯,每次都呼叫該實例方法。 你可以隨意設定那個實例。