Contextuele functieselectie met agents

Belangrijk

Deze functie bevindt zich in de experimentele fase. Functies in deze fase zijn in actieve ontwikkeling en kunnen aanzienlijk veranderen voordat u naar de preview- of releasekandidaatfase gaat.

Overzicht

Contextuele functieselectie is een geavanceerde functie in het Semantische Kernel Agent Framework waarmee agents dynamisch de meest relevante functies kunnen selecteren en adverteren op basis van de huidige gesprekscontext. In plaats van alle beschikbare functies beschikbaar te maken voor het AI-model, gebruikt deze functie Retrieval-Augmented Generation (RAG) om alleen die functies te filteren en weer te geven die het meest relevant zijn voor de aanvraag van de gebruiker.

Met deze aanpak wordt de uitdaging van functieselectie aangepakt bij het omgaan met een groot aantal beschikbare functies, waarbij AI-modellen anders moeite hebben om de juiste functie te kiezen, wat leidt tot verwarring en suboptimale prestaties.

Waarschuwing

Wanneer u de ContextualFunctionProvider gebruikt, moet de UseImmutableKernel instelling op de agent worden ingesteld op true, omdat de functie vereist dat de kernel wordt gekloond bij het aanroepen van de agent. Houd er rekening mee dat het instellen van UseImmutableKernel op true betekent dat eventuele wijzigingen in kernelgegevens, uitgevoerd door bijvoorbeeld plug-ins tijdens de aanroep van de agent, niet behouden blijven nadat de aanroep is voltooid.

Hoe contextuele functieselectie werkt

Wanneer een agent is geconfigureerd met contextuele functieselectie, maakt deze gebruik van een vectorarchief en een insluitgenerator om de huidige gesprekscontext (inclusief eerdere berichten en gebruikersinvoer) te vergelijken met de beschrijvingen en namen van beschikbare functies. De meest relevante functies, tot aan de opgegeven limiet, worden vervolgens aan het AI-model aangeboden voor gebruik.

Dit mechanisme is met name nuttig voor agents die toegang hebben tot een brede set invoegtoepassingen of hulpprogramma's, zodat alleen contextafhankelijke acties worden overwogen bij elke stap.

Gebruiksvoorbeeld

In het volgende voorbeeld ziet u hoe een agent kan worden geconfigureerd voor het gebruik van contextuele functieselectie. De agent is ingesteld om beoordelingen van klanten samen te vatten, maar alleen de meest relevante functies worden voor elke aanroep geadverteerd naar het AI-model. De GetAvailableFunctions methode omvat opzettelijk relevante en irrelevante functies om de voordelen van contextuele selectie te benadrukken.

// Create an embedding generator for function vectorization
var embeddingGenerator = new AzureOpenAIClient(new Uri("<endpoint>"), new ApiKeyCredential("<api-key>"))
    .GetEmbeddingClient("<deployment-name>")
    .AsIEmbeddingGenerator();

// Create kernel and register AzureOpenAI chat completion service
var kernel = Kernel.CreateBuilder()
    .AddAzureOpenAIChatCompletion("<deployment-name>", "<endpoint>", "<api-key>");
    .Build();

// Create a chat completion agent
ChatCompletionAgent agent = new()
{
    Name = "ReviewGuru",
    Instructions = "You are a friendly assistant that summarizes key points and sentiments from customer reviews. For each response, list available functions.",
    Kernel = kernel,
    Arguments = new(new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(options: new FunctionChoiceBehaviorOptions { RetainArgumentTypes = true }) }),
    // This setting must be set to true when using the ContextualFunctionProvider
    UseImmutableKernel = true
};

// Create the agent thread and register the contextual function provider
ChatHistoryAgentThread agentThread = new();

agentThread.AIContextProviders.Add(
    new ContextualFunctionProvider(
        vectorStore: new InMemoryVectorStore(new InMemoryVectorStoreOptions() { EmbeddingGenerator = embeddingGenerator }),
        vectorDimensions: 1536,
        functions: AvailableFunctions(),
        maxNumberOfFunctions: 3, // Only the top 3 relevant functions are advertised
        loggerFactory: LoggerFactory
    )
);


// Invoke the agent
ChatMessageContent message = await agent.InvokeAsync("Get and summarize customer review.", agentThread).FirstAsync();
Console.WriteLine(message.Content);

// Output
/*
    Customer Reviews:
    -----------------
    1. John D. - ★★★★★
       Comment: Great product and fast shipping!
       Date: 2023-10-01

    Summary:
    --------
    The reviews indicate high customer satisfaction,
    highlighting product quality and shipping speed.

    Available functions:
    --------------------
    - Tools-GetCustomerReviews
    - Tools-Summarize
    - Tools-CollectSentiments
*/

IReadOnlyList<AIFunction> GetAvailableFunctions()
{
    // Only a few functions are directly related to the prompt; the majority are unrelated to demonstrate the benefits of contextual filtering.
    return new List<AIFunction>
    {
        // Relevant functions
        AIFunctionFactory.Create(() => "[ { 'reviewer': 'John D.', 'date': '2023-10-01', 'rating': 5, 'comment': 'Great product and fast shipping!' } ]", "GetCustomerReviews"),
        AIFunctionFactory.Create((string text) => "Summary generated based on input data: key points include customer satisfaction.", "Summarize"),
        AIFunctionFactory.Create((string text) => "The collected sentiment is mostly positive.", "CollectSentiments"),

        // Irrelevant functions
        AIFunctionFactory.Create(() => "Current weather is sunny.", "GetWeather"),
        AIFunctionFactory.Create(() => "Email sent.", "SendEmail"),
        AIFunctionFactory.Create(() => "The current stock price is $123.45.", "GetStockPrice"),
        AIFunctionFactory.Create(() => "The time is 12:00 PM.", "GetCurrentTime")
    };
}

Vector Store

De provider is voornamelijk ontworpen om te werken met vectorarchieven in het geheugen, die eenvoud bieden. Als er echter andere typen vectorarchieven worden gebruikt, is het belangrijk te weten dat de verantwoordelijkheid voor het afhandelen van gegevenssynchronisatie en consistentie in de hostingtoepassing valt.

Synchronisatie is nodig wanneer de lijst met functies wordt gewijzigd of wanneer de bron van functie-insluitingen wordt gewijzigd. Als een agent in eerste instantie bijvoorbeeld drie functies (f1, f2, f3) heeft die zijn gevectoriseerd en opgeslagen in een cloudvectorarchief, en later f3 wordt verwijderd uit de lijst met functies van de agent, moet het vectorarchief worden bijgewerkt om alleen de huidige functies weer te geven die de agent heeft (f1 en f2). Als u het vectorarchief niet bijwerkt, kunnen er irrelevante functies worden geretourneerd als resultaten. Als de gegevens die worden gebruikt voor vectorisatie, zoals functienamen, beschrijvingen, enzovoort, worden gewijzigd, moet het vectorarchief worden opgeschoond en opnieuw gevuld met nieuwe insluitingen op basis van de bijgewerkte informatie.

Het beheren van gegevenssynchronisatie in externe of gedistribueerde vectorarchieven kan complex en gevoelig zijn voor fouten, met name in gedistribueerde toepassingen waarbij verschillende services of exemplaren onafhankelijk kunnen werken en consistente toegang tot dezelfde gegevens vereisen. Het gebruik van een in-memory archief vereenvoudigt dit proces daarentegen: wanneer de functielijst of vectorisatiebron verandert, kan het archief in het geheugen eenvoudig opnieuw worden gemaakt met de nieuwe set functies en de bijbehorende insluitingen, waardoor consistentie met minimale inspanning wordt gegarandeerd.

Functies specificeren

De contextuele functieprovider moet worden geleverd met een lijst met functies waaruit de meest relevante functies kunnen worden geselecteerd op basis van de huidige context. Dit wordt bereikt door een lijst met functies op te geven aan de functions parameter van de ContextualFunctionProvider constructor.

Naast de functies moet u ook het maximum aantal relevante functies opgeven dat moet worden geretourneerd met behulp van de maxNumberOfFunctions parameter. Met deze parameter wordt bepaald hoeveel functies de provider moet overwegen bij het selecteren van de meest relevante functies voor de huidige context. Het opgegeven getal is niet bedoeld om precies te zijn; in plaats daarvan dient het als een bovengrens die afhankelijk is van het specifieke scenario.

Als u deze waarde te laag instelt, wordt mogelijk voorkomen dat de agent toegang heeft tot alle benodigde functies voor een scenario, waardoor het scenario mogelijk mislukt. Omgekeerd kan het instellen ervan te hoog de agent overweldigen met te veel functies, wat kan leiden tot hallucinaties, overmatig invoertokenverbruik en suboptimale prestaties.

// Create the provider with a list of functions and a maximum number of functions to return
ContextualFunctionProvider provider = new (
    vectorStore: new InMemoryVectorStore(new InMemoryVectorStoreOptions { EmbeddingGenerator = embeddingGenerator }),
    vectorDimensions: 1536,
    functions: [AIFunctionFactory.Create((string text) => $"Echo: {text}", "Echo"), <other functions>]
    maxNumberOfFunctions: 3 // Only the top 3 relevant functions are advertised
);

Opties voor contextuele functieleverancier

De provider kan worden geconfigureerd met behulp van de ContextualFunctionProviderOptions klasse, waarmee u verschillende aspecten van de werking van de provider kunt aanpassen:

// Create options for the contextual function provider
ContextualFunctionProviderOptions options = new ()
{
    ...
};

// Create the provider with options
ContextualFunctionProvider provider = new (
    ...
    options: options // Pass the options
);

Contextgrootte

De contextgrootte bepaalt hoeveel recente berichten van eerdere agent-aanroepen worden opgenomen bij het vormen van de context voor een nieuwe aanroep. De provider verzamelt alle berichten van eerdere aanroepen, tot het opgegeven nummer en prependeert deze naar de nieuwe berichten om de context te vormen.

Het gebruik van recente berichten in combinatie met nieuwe berichten is vooral handig voor taken die informatie uit eerdere stappen in een gesprek vereisen. Als een agent bijvoorbeeld een resource in één aanroep inricht en in de volgende implementeert, heeft de implementatiestap toegang tot details uit de inrichtingsstap om ingerichte resourcegegevens voor de implementatie op te halen.

De standaardwaarde voor het aantal recente berichten in context is 2, maar dit kan naar wens worden geconfigureerd door de NumberOfRecentMessagesInContext eigenschap op te geven in het ContextualFunctionProviderOptionsvolgende:

ContextualFunctionProviderOptions options = new ()
{
    NumberOfRecentMessagesInContext = 1 // Only the last message will be included in the context
};

Waarde van de bron voor het inbedden van context

Als u contextuele functieselectie wilt uitvoeren, moet de provider de huidige context vectoriseren, zodat deze kan worden vergeleken met beschikbare functies in het vectorarchief. Standaard creëert de provider deze contextembedding door alle niet-lege recente en nieuwe berichten samen te voegen tot één string, die vervolgens wordt gevectoriseerd en gebruikt om naar relevante functies te zoeken.

In sommige scenario's kunt u dit gedrag aanpassen aan:

  • Richt u op specifieke berichttypen (bijvoorbeeld alleen gebruikersberichten)
  • Bepaalde informatie uitsluiten van context
  • De context vooraf verwerken of samenvatten vóór vectorisatie (bijvoorbeeld promptherschrijven toepassen)

Hiervoor kunt u een aangepaste gemachtigde toewijzen aan ContextEmbeddingValueProvider. Deze gemachtigde ontvangt de recente en nieuwe berichten en retourneert een tekenreekswaarde die moet worden gebruikt als bron voor het insluiten van context:

ContextualFunctionProviderOptions options = new()
{
    ContextEmbeddingValueProvider = async (recentMessages, newMessages, cancellationToken) =>
    {
        // Example: Only include user messages in the embedding
        var allUserMessages = recentMessages.Concat(newMessages)
            .Where(m => m.Role == "user")
            .Select(m => m.Content)
            .Where(content => !string.IsNullOrWhiteSpace(content));
        return string.Join("\n", allUserMessages);
    }
};

Door het insluiten van context aan te passen, kan de relevantie van functieselectie worden verbeterd, met name in complexe of zeer gespecialiseerde agentscenario's.

Functie Insluiten van bronwaarde

De provider moet elke beschikbare functie vectoriseren om deze te vergelijken met de context en de meest relevante functies te selecteren. Standaard maakt de provider een functie-embedding door de naam en beschrijving van de functie samen te voegen tot één tekenreeks, die vervolgens wordt gevectoriseerd en opgeslagen in de vectoropslag.

U kunt dit gedrag aanpassen met behulp van de EmbeddingValueProvider eigenschap van ContextualFunctionProviderOptions. Met deze eigenschap kunt u een callback opgeven die de functie en een annuleringstoken ontvangt en een tekenreeks retourneert die moet worden gebruikt als de bron voor het insluiten van de functie. Dit is handig als u het volgende wilt doen:

  • Aanvullende functiemetagegevens toevoegen aan de insluitbron
  • De functie-informatie vooraf verwerken, filteren of opnieuw opmaken vóór vectorisatie
ContextualFunctionProviderOptions options = new()
{
    EmbeddingValueProvider = async (function, cancellationToken) =>
    {
        // Example: Use only the function name for embedding
        return function.Name;
    }
};

Door de insluitwaarde van de functie aan te passen, kan de nauwkeurigheid van de functieselectie worden verbeterd, met name wanneer uw functies uitgebreide, contextgerelateerde metagegevens hebben of wanneer u de zoekopdracht wilt richten op specifieke aspecten van elke functie.

Volgende stappen

De contextuele selectievoorbeelden voor functies verkennen

Binnenkort beschikbaar

Meer informatie komt binnenkort beschikbaar.

Binnenkort beschikbaar

Meer informatie komt binnenkort beschikbaar.