Partilhar via


Dados de acesso em funções de IA

Ao criar funções de IA, pode precisar de aceder a dados contextuais para além dos parâmetros fornecidos pelo modelo de IA. A Microsoft.Extensions.AI biblioteca fornece vários mecanismos para passar dados aos delegados de função.

AIFunction classe

O AIFunction tipo representa uma função que pode ser descrita a um serviço de IA e invocada. Podes criar AIFunction objetos chamando uma das AIFunctionFactory.Create sobrecargas. Mas AIFunction também é uma classe base, e podes derivar dela e implementar o teu próprio tipo de função de IA. DelegatingAIFunction proporciona uma forma fácil de envolver um existente AIFunction e adicionar funcionalidades adicionais, incluindo a captura de dados adicionais a serem utilizados.

Dados de passagem

Pode associar dados à função no momento em que é criada, seja via encerramento ou via AdditionalProperties. Se estiver a criar a sua própria função, pode preencher AdditionalProperties como quiser. Se usar AIFunctionFactory para criar a função, pode preencher dados usando AIFunctionFactoryOptions.AdditionalProperties.

Também pode incluir quaisquer referências a dados como parte do delegado fornecido a AIFunctionFactory. Ou seja, podes integrar tudo o que desejares referenciar como parte do AIFunction próprio.

Dados de acesso nos delegados de funções

Podes chamar o teu AIFunction diretamente, ou podes chamá-lo indiretamente usando FunctionInvokingChatClient. As secções seguintes descrevem como aceder a dados de argumentos usando qualquer uma das abordagens.

Invocação manual de funções

Se invocar manualmente um AIFunction ao chamar AIFunction.InvokeAsync(AIFunctionArguments, CancellationToken), você deve fornecer AIFunctionArguments. O AIFunctionArguments tipo inclui:

Se quiser aceder ao AIFunctionArguments ou ao IServiceProvider dentro do seu delegado AIFunctionFactory.Create, crie um parâmetro tipado como IServiceProvider ou AIFunctionArguments. Esse parâmetro estará ligado aos dados relevantes do AIFunctionArguments passado para AIFunction.InvokeAsync().

O código a seguir mostra um exemplo:

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 é também um caso especial: se o AIFunctionFactory.Create delegado ou lambda tiver um CancellationToken parâmetro, este estará vinculado ao CancellationToken que foi passado para AIFunction.InvokeAsync().

Invocação através de FunctionInvokingChatClient

FunctionInvokingChatClient publica o estado sobre a invocação atual para FunctionInvokingChatClient.CurrentContext, incluindo não só os argumentos, mas todos os objetos de entrada ChatMessage , o ChatOptions, e detalhes sobre qual função está a ser invocada (de quantas). Pode adicionar qualquer dado que quiser em ChatOptions.AdditionalProperties e extraí-los de dentro do seu AIFunction a partir de FunctionInvokingChatClient.CurrentContext.Options.AdditionalProperties.

O código a seguir mostra um exemplo:

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

Injeção de dependência

Se usar FunctionInvokingChatClient para invocar funções automaticamente, esse cliente configura um AIFunctionArguments objeto que passa para o AIFunction. Porque AIFunctionArguments inclui o IServiceProvider com o qual o FunctionInvokingChatClient foi equipado, ao construir o seu cliente usando meios padrão de DI, esse IServiceProvider é transmitido diretamente para o seu AIFunction. Nesse ponto, podes consultar o que quiseres do DI.

Técnicas avançadas

Se quiseres um controlo mais detalhado sobre como os parâmetros são ligados, podes usar AIFunctionFactoryOptions.ConfigureParameterBinding, que te dá controlo sobre como cada parâmetro é povoado. Por exemplo, o MCP C# SDK utiliza esta técnica para ligar automaticamente parâmetros a partir do DI.

Se utilizares a AIFunctionFactory.Create(MethodInfo, Func<AIFunctionArguments,Object>, AIFunctionFactoryOptions) sobrecarga, podes também executar a tua própria lógica arbitrária sempre que criares o objeto de destino em que o método de instância será chamado. E podes fazer o que quiseres para configurar essa instância.