Partager via


Sélection contextuelle de fonctions avec des agents

Importante

Cette fonctionnalité est à l’étape expérimentale. Les fonctionnalités à ce stade sont en cours de développement et peuvent changer de manière significative avant de passer au stade de préversion ou de version candidate.

Aperçu

La sélection de fonction contextuelle est une fonctionnalité avancée dans l’infrastructure de l’agent de noyau sémantique qui permet aux agents de sélectionner et de publier dynamiquement les fonctions les plus pertinentes en fonction du contexte de conversation actuel. Au lieu d’exposer toutes les fonctions disponibles au modèle IA, cette fonctionnalité utilise Retrieval-Augmented Génération (RAG) pour filtrer et présenter uniquement ces fonctions les plus pertinentes à la demande de l’utilisateur.

Cette approche résout le défi de la sélection des fonctions lorsqu’il s’agit d’un grand nombre de fonctions disponibles, où les modèles IA peuvent autrement avoir du mal à choisir la fonction appropriée, ce qui entraîne une confusion et des performances non optimales.

Avertissement

Lorsque vous utilisez le ContextualFunctionProvider, le paramètre UseImmutableKernel sur l'agent doit être défini sur true, car cette fonctionnalité nécessite le clonage du noyau lors de l'appel de l'agent. Notez que le réglage de UseImmutableKernel sur true implique que toutes les modifications apportées aux données du noyau, effectuées lors de l'appel de l'agent, par exemple par des plug-ins, ne seront pas conservées une fois l'appel terminé.

Fonctionnement de la sélection des fonctions contextuelles

Lorsqu’un agent est configuré avec la sélection de fonction contextuelle, il tire parti d’un magasin vectoriel et d’un générateur d’incorporation pour correspondre sémantiquement au contexte de conversation actuel (y compris les messages précédents et les entrées utilisateur) avec les descriptions et les noms des fonctions disponibles. Les fonctions les plus pertinentes, jusqu’à la limite spécifiée, sont ensuite transmises au modèle IA pour exécution.

Ce mécanisme est particulièrement utile pour les agents qui ont accès à un large ensemble de plug-ins ou d’outils, ce qui garantit que seules les actions contextuellement appropriées sont prises en compte à chaque étape.

Exemple d’utilisation

L’exemple suivant montre comment un agent peut être configuré pour utiliser la sélection de fonction contextuelle. L’agent est configuré pour résumer les avis des clients, mais seules les fonctions les plus pertinentes sont publiées sur le modèle IA pour chaque appel. La GetAvailableFunctions méthode inclut intentionnellement des fonctions pertinentes et non pertinentes pour mettre en évidence les avantages de la sélection contextuelle.

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

Magasin de vecteurs

Le fournisseur est principalement conçu pour fonctionner avec des magasins vectoriels en mémoire, qui offrent une grande simplicité. Toutefois, si d’autres types de magasins de vecteurs sont utilisés, il est important de noter que la responsabilité de la gestion de la synchronisation et de la cohérence des données tombe sur l’application d’hébergement.

La synchronisation est nécessaire chaque fois que la liste des fonctions change ou lorsque la source des incorporations de fonctions est modifiée. Par exemple, si un agent a initialement trois fonctions (f1, f2, f3) qui sont vectorisées et stockées dans un magasin de vecteurs cloud, et que la version ultérieure f3 est supprimée de la liste des fonctions de l’agent, le magasin de vecteurs doit être mis à jour pour refléter uniquement les fonctions actuelles de l’agent (f1 et f2). L’échec de la mise à jour du magasin de vecteurs peut entraîner le retour de fonctions non pertinentes en tant que résultats. De même, si les données utilisées pour la vectorisation, telles que les noms de fonctions, les descriptions, etc., changent, le magasin vectoriel doit être vidé et rempli à nouveau avec de nouvelles intégrations basées sur les informations mises à jour.

La gestion de la synchronisation des données dans des magasins vectoriels externes ou distribués peut être complexe et sujette à des erreurs, en particulier dans les applications distribuées où différents services ou instances peuvent fonctionner indépendamment et nécessitent un accès cohérent aux mêmes données. En revanche, l’utilisation d’un magasin en mémoire simplifie ce processus : lorsque la source de liste de fonctions ou de vectorisation change, le magasin en mémoire peut être facilement recréé avec le nouvel ensemble de fonctions et leurs incorporations, garantissant ainsi la cohérence avec un effort minimal.

Spécification des fonctions

Le fournisseur de fonctions contextuelles doit être fourni avec une liste de fonctions à partir de laquelle elle peut sélectionner les fonctions les plus pertinentes en fonction du contexte actuel. Pour ce faire, fournissez une liste de fonctions au functions paramètre du ContextualFunctionProvider constructeur.

Outre les fonctions, vous devez également spécifier le nombre maximal de fonctions pertinentes à retourner à l’aide du maxNumberOfFunctions paramètre. Ce paramètre détermine le nombre de fonctions que le fournisseur prend en compte lors de la sélection des fonctions les plus pertinentes pour le contexte actuel. Le nombre spécifié n’est pas destiné à être précis ; elle sert plutôt de limite supérieure qui dépend du scénario spécifique.

La définition de cette valeur trop faible peut empêcher l’agent d’accéder à toutes les fonctions nécessaires pour un scénario, ce qui peut entraîner l’échec du scénario. À l'inverse, régler ce paramètre trop haut peut submerger l'agent avec trop de fonctions, ce qui peut provoquer des hallucinations, une utilisation excessive de jetons d'entrée, et des performances sous-optimales.

// 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
);

Options du fournisseur de fonctions contextuelles

Le fournisseur peut être configuré à l’aide de la ContextualFunctionProviderOptions classe, ce qui vous permet de personnaliser différents aspects du fonctionnement du fournisseur :

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

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

Taille du contexte

La taille du contexte détermine le nombre de messages récents des appels d’agent précédents inclus lors de la formation du contexte d’un nouvel appel. Le fournisseur collecte tous les messages des appels précédents, jusqu’au nombre spécifié, et les préfixe aux nouveaux messages pour former le contexte.

L’utilisation de messages récents avec de nouveaux messages est particulièrement utile pour les tâches qui nécessitent des informations provenant des étapes précédentes d’une conversation. Par exemple, si un agent provisionne une ressource dans un appel et le déploie dans la prochaine étape de déploiement, l’étape de déploiement peut accéder aux détails de l’étape d’approvisionnement pour obtenir des informations sur les ressources approvisionnées pour le déploiement.

La valeur par défaut du nombre de messages récents dans le contexte est 2, mais elle peut être configurée en fonction des besoins en spécifiant la NumberOfRecentMessagesInContext propriété dans le ContextualFunctionProviderOptions:

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

Valeur source d’intégration du contexte

Pour effectuer une sélection de fonction contextuelle, le fournisseur doit vectoriser le contexte actuel afin qu’il puisse être comparé aux fonctions disponibles dans le magasin vectoriel. Par défaut, le fournisseur crée ce contexte incorporé en concaténant tous les messages récents et nouveaux non vides dans une seule chaîne, qui est ensuite vectorisée et utilisée pour rechercher des fonctions pertinentes.

Dans certains scénarios, vous pouvez personnaliser ce comportement pour :

  • Concentrez-vous sur des types de messages spécifiques (par exemple, uniquement les messages utilisateur)
  • Exclure certaines informations du contexte
  • Préprocesser ou résumer le contexte avant la vectorisation (par exemple, appliquer la réécriture de requête)

Pour ce faire, vous pouvez affecter un délégué personnalisé à ContextEmbeddingValueProvider. Ce délégué reçoit les messages récents et nouveaux et retourne une valeur de chaîne à utiliser comme source pour l’incorporation de contexte :

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

La personnalisation de l’incorporation de contexte peut améliorer la pertinence de la sélection de fonction, en particulier dans les scénarios d’agent complexes ou hautement spécialisés.

Valeur source d’intégration de la fonction

Le fournisseur doit vectoriser chaque fonction disponible pour la comparer au contexte et sélectionner les fonctions les plus pertinentes. Par défaut, le fournisseur crée une fonction incorporée en concaténant le nom et la description de la fonction en une seule chaîne, qui est ensuite vectorisée et stockée dans le magasin vectoriel.

Vous pouvez personnaliser ce comportement à l’aide de la EmbeddingValueProvider propriété de ContextualFunctionProviderOptions. Cette propriété vous permet de spécifier un rappel qui reçoit la fonction et un jeton d’annulation et retourne une chaîne à utiliser comme source pour l’incorporation de la fonction. Cela est utile si vous souhaitez :

  • Ajouter des métadonnées de fonction supplémentaires à la source d’incorporation
  • Prétraiter, filtrer ou reformater les informations de fonction avant la vectorisation
ContextualFunctionProviderOptions options = new()
{
    EmbeddingValueProvider = async (function, cancellationToken) =>
    {
        // Example: Use only the function name for embedding
        return function.Name;
    }
};

La personnalisation de la valeur source incorporée de la fonction peut améliorer la précision de la sélection de fonction, en particulier lorsque vos fonctions ont des métadonnées riches, pertinentes dans le contexte ou lorsque vous souhaitez concentrer la recherche sur des aspects spécifiques de chaque fonction.

Étapes suivantes

Explorer les exemples de sélection de fonction contextuelle

Prochainement

Plus d’informations seront bientôt disponibles.

Prochainement

Plus d’informations seront bientôt disponibles.