Udostępnij przez


Uzyskiwanie dostępu do danych w funkcjach sztucznej inteligencji

Podczas tworzenia funkcji sztucznej inteligencji może być konieczne uzyskanie dostępu do danych kontekstowych poza parametrami dostarczonymi przez model AI. Biblioteka Microsoft.Extensions.AI udostępnia kilka mechanizmów przekazywania danych do delegatów funkcji.

Klasa AIFunction

Typ AIFunction reprezentuje funkcję, którą można opisać w usłudze sztucznej inteligencji i wywołać. Obiekty można tworzyć AIFunction , wywołując jedno z AIFunctionFactory.Create przeciążeń. Ale AIFunction jest również klasą bazową i można z niej pochodzić i zaimplementować własny typ funkcji sztucznej inteligencji. DelegatingAIFunction zapewnia łatwy sposób na opakowanie istniejącego AIFunction i dodanie dodatkowej funkcjonalności, w tym przechwytywania dodatkowych danych do użycia.

Przekaż dane

Możesz skojarzyć dane z funkcją w momencie jej utworzenia, za pomocą closure lub używając AdditionalProperties. Jeśli tworzysz własną funkcję, możesz wypełniać AdditionalProperties w dowolny sposób. Jeśli używasz AIFunctionFactory do utworzenia funkcji, możesz wypełnić dane przy użyciu AIFunctionFactoryOptions.AdditionalProperties.

Możesz również przechwycić wszelkie odwołania do danych jako część delegata przekazanego do AIFunctionFactory elementu. Oznacza to, że można zintegrować wszystko, do czego chcesz się odnosić, jako część samego AIFunction.

Uzyskiwanie dostępu do danych w delegatach funkcji

Możesz bezpośrednio wywołać AIFunction lub wywołać je pośrednio przy użyciu FunctionInvokingChatClient. W poniższych sekcjach opisano sposób uzyskiwania dostępu do danych argumentów przy użyciu obu metod.

Ręczne wywołanie funkcji

Jeśli ręcznie wywołasz AIFunction przez wywołanie AIFunction.InvokeAsync(AIFunctionArguments, CancellationToken), przekaż AIFunctionArguments. Typ AIFunctionArguments obejmuje:

Jeśli chcesz uzyskać dostęp do elementu AIFunctionArguments lub IServiceProvider z poziomu delegata AIFunctionFactory.Create, utwórz parametr typu IServiceProvider lub AIFunctionArguments. Dany parametr będzie powiązany z odpowiednimi danymi z AIFunctionArguments, które zostały przekazane do AIFunction.InvokeAsync().

Poniższy kod przedstawia przykład:

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 jest również traktowany w szczególny sposób: jeżeli delegat lub wyrażenie lambda ma parametr CancellationToken, zostanie powiązany z CancellationToken przekazanym do AIFunction.InvokeAsync().

Wywołanie za pośrednictwem FunctionInvokingChatClient

FunctionInvokingChatClient Publikuje informacje na temat bieżącego wywołania do FunctionInvokingChatClient.CurrentContext, w tym nie tylko argumenty, ale wszystkie obiekty wejściowe ChatMessage, ChatOptions, oraz szczegóły dotyczące wywoływanej funkcji (z ilu jest dostępnych). Możesz dodać dowolne dane do ChatOptions.AdditionalProperties, a następnie wyodrębnić je wewnątrz AIFunction z FunctionInvokingChatClient.CurrentContext.Options.AdditionalProperties.

Poniższy kod przedstawia przykład:

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}");

Wstrzykiwanie zależności

Jeśli używasz FunctionInvokingChatClient do automatycznego wywoływania funkcji, klient konfiguruje obiekt AIFunctionArguments, który przekazuje do AIFunction. Ze względu AIFunctionArguments na fakt, że IServiceProvider element FunctionInvokingChatClient został dostarczony, jeśli skonstruujesz klienta przy użyciu standardowego DI (Dependency Injection), to IServiceProvider jest on przekazywany bezpośrednio do elementu AIFunction. W tym momencie możesz wykonać zapytanie o dowolne elementy z DI.

Zaawansowane techniki

Jeśli chcesz uzyskać bardziej szczegółową kontrolę nad tym, jak parametry są powiązane, możesz użyć metody AIFunctionFactoryOptions.ConfigureParameterBinding, która kontroluje sposób wypełniania poszczególnych parametrów. Na przykład SDK C# MCP używa tej techniki do automatycznego powiązania parametrów z DI.

Jeśli używasz przeciążenia AIFunctionFactory.Create(MethodInfo, Func<AIFunctionArguments,Object>, AIFunctionFactoryOptions), możesz również za każdym razem uruchomić własną dowolną logikę podczas tworzenia obiektu docelowego, który będzie używany do wywoływania metody instancyjnej. Możesz skonfigurować to wystąpienie w dowolny sposób, jaki chcesz.