Partager via


Utilisation de plug-ins pour la récupération d’une génération augmentée (RAG)

Souvent, vos agents IA doivent récupérer des données à partir de sources externes pour générer des réponses ancrées. Sans ce contexte supplémentaire, vos agents IA peuvent halluciner ou fournir des informations incorrectes. Pour résoudre ce problème, vous pouvez utiliser des plug-ins pour récupérer des données à partir de sources externes.

Lorsque vous envisagez des plug-ins pour la récupération d’une génération augmentée (RAG), vous devez vous poser deux questions :

  1. Comment allez-vous (ou votre agent IA) « rechercher » les données requises ? Avez-vous besoin d’une recherche sémantique ou d’une recherche classique ?
  2. Connaissez-vous déjà les données dont l’agent IA a besoin à l’avance (données pré-extraites) ou l’agent IA doit-il récupérer les données dynamiquement ?
  3. Comment allez-vous sécuriser vos données et empêcher le surpartage des informations sensibles ?

Lors du développement de plug-ins pour la récupération d’une génération augmentée (RAG), vous pouvez utiliser deux types de recherche : la recherche sémantique et la recherche classique.

La recherche sémantique utilise des bases de données vectorielles pour comprendre et récupérer des informations en fonction de la signification et du contexte de la requête plutôt que de simplement correspondre à des mots clés. Cette méthode permet au moteur de recherche de saisir les nuances de langage, telles que les synonymes, les concepts connexes et l’intention globale derrière une requête.

La recherche sémantique excelle dans les environnements où les requêtes utilisateur sont complexes, ouvertes ou nécessitent une compréhension plus approfondie du contenu. Par exemple, la recherche de « meilleurs smartphones pour la photographie » donne des résultats qui considèrent le contexte des fonctionnalités de photographie dans les smartphones, plutôt que de simplement correspondre aux mots « best », « smartphones » et « photographie ».

Lorsque vous fournissez un LLM avec une fonction de recherche sémantique, vous devez généralement définir une fonction avec une seule requête de recherche. Le LLM utilise ensuite cette fonction pour récupérer les informations nécessaires. Vous trouverez ci-dessous un exemple de fonction de recherche sémantique qui utilise Azure AI Search pour rechercher des documents similaires à une requête donnée.

using System.ComponentModel;
using System.Text.Json.Serialization;
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Models;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Embeddings;

public class InternalDocumentsPlugin
{
    private readonly ITextEmbeddingGenerationService _textEmbeddingGenerationService;
    private readonly SearchIndexClient _indexClient;

    public AzureAISearchPlugin(ITextEmbeddingGenerationService textEmbeddingGenerationService, SearchIndexClient indexClient)
    {
        _textEmbeddingGenerationService = textEmbeddingGenerationService;
        _indexClient = indexClient;
    }

    [KernelFunction("Search")]
    [Description("Search for a document similar to the given query.")]
    public async Task<string> SearchAsync(string query)
    {
        // Convert string query to vector
        ReadOnlyMemory<float> embedding = await _textEmbeddingGenerationService.GenerateEmbeddingAsync(query);

        // Get client for search operations
        SearchClient searchClient = _indexClient.GetSearchClient("default-collection");

        // Configure request parameters
        VectorizedQuery vectorQuery = new(embedding);
        vectorQuery.Fields.Add("vector");

        SearchOptions searchOptions = new() { VectorSearch = new() { Queries = { vectorQuery } } };

        // Perform search request
        Response<SearchResults<IndexSchema>> response = await searchClient.SearchAsync<IndexSchema>(searchOptions);

        // Collect search results
        await foreach (SearchResult<IndexSchema> result in response.Value.GetResultsAsync())
        {
            return result.Document.Chunk; // Return text from first result
        }

        return string.Empty;
    }

    private sealed class IndexSchema
    {
        [JsonPropertyName("chunk")]
        public string Chunk { get; set; }

        [JsonPropertyName("vector")]
        public ReadOnlyMemory<float> Vector { get; set; }
    }
}

La recherche classique, également appelée recherche basée sur des attributs ou basée sur des critères, s’appuie sur le filtrage et la correspondance de termes ou de valeurs exacts au sein d’un jeu de données. Il est particulièrement efficace pour les requêtes de base de données, les recherches d’inventaire et toute situation où le filtrage par attributs spécifiques est nécessaire.

Par exemple, si un utilisateur souhaite rechercher toutes les commandes passées par un ID client particulier ou récupérer des produits dans une plage de prix et une catégorie spécifiques, la recherche classique fournit des résultats précis et fiables. Toutefois, la recherche classique est limitée par son incapacité à comprendre le contexte ou les variantes du langage.

Conseil

Dans la plupart des cas, vos services existants prennent déjà en charge la recherche classique. Avant d’implémenter une recherche sémantique, déterminez si vos services existants peuvent fournir le contexte nécessaire pour vos agents IA.

Prenons l’exemple d’un plug-in qui récupère les informations client à partir d’un système CRM à l’aide de la recherche classique. Ici, l’IA doit simplement appeler la GetCustomerInfoAsync fonction avec un ID client pour récupérer les informations nécessaires.

using System.ComponentModel;
using Microsoft.SemanticKernel;

public class CRMPlugin
{
    private readonly CRMService _crmService;

    public CRMPlugin(CRMService crmService)
    {
        _crmService = crmService;
    }

    [KernelFunction("GetCustomerInfo")]
    [Description("Retrieve customer information based on the given customer ID.")]
    public async Task<Customer> GetCustomerInfoAsync(string customerId)
    {
        return await _crmService.GetCustomerInfoAsync(customerId);
    }
}

L’obtention de la même fonctionnalité de recherche avec la recherche sémantique serait probablement impossible ou impossible en raison de la nature non déterministe des requêtes sémantiques.

Quand utiliser chaque

Le choix entre la recherche sémantique et la recherche classique dépend de la nature de la requête. Il est idéal pour les environnements lourds de contenu, tels que les base de connaissances et le support client, où les utilisateurs peuvent poser des questions ou rechercher des produits à l’aide du langage naturel. La recherche classique, en revanche, doit être utilisée lorsque la précision et les correspondances exactes sont importantes.

Dans certains scénarios, vous devrez peut-être combiner les deux approches pour fournir des fonctionnalités de recherche complètes. Par exemple, un chatbot aidant les clients dans un magasin de commerce électronique peut utiliser la recherche sémantique pour comprendre les requêtes utilisateur et la recherche classique pour filtrer les produits en fonction d’attributs spécifiques tels que le prix, la marque ou la disponibilité.

Vous trouverez ci-dessous un exemple de plug-in qui combine la recherche sémantique et classique pour récupérer des informations sur le produit à partir d’une base de données de commerce électronique.

using System.ComponentModel;
using Microsoft.SemanticKernel;

public class ECommercePlugin
{
    [KernelFunction("search_products")]
    [Description("Search for products based on the given query.")]
    public async Task<IEnumerable<Product>> SearchProductsAsync(string query, ProductCategories category = null, decimal? minPrice = null, decimal? maxPrice = null)
    {
        // Perform semantic and classic search with the given parameters
    }
}

Récupération dynamique et pré-extraite des données

Lors du développement de plug-ins pour la génération augmentée de récupération (RAG), vous devez également déterminer si le processus de récupération de données est statique ou dynamique. Cela vous permet d’optimiser les performances de vos agents IA en récupérant des données uniquement si nécessaire.

Récupération dynamique des données

Dans la plupart des cas, la requête utilisateur détermine les données que l’agent IA doit récupérer. Par exemple, un utilisateur peut demander la différence entre deux produits différents. L’agent IA doit ensuite récupérer dynamiquement les informations du produit à partir d’une base de données ou d’une API pour générer une réponse à l’aide de l’appel de fonction. Il serait impraticable de pré-extraire toutes les informations de produit possibles à l’avance et de le donner à l’agent IA.

Vous trouverez ci-dessous un exemple de conversation back-and-forth entre un utilisateur et un agent IA où la récupération dynamique des données est nécessaire.

Role Message
🔵Utilisateur Pouvez-vous me parler des meilleurs matelas ?
🔴Assistant (appel de fonction) Products.Search("mattresses")
🟢Outil [{"id": 25323, "name": "Cloud Nine"},{"id": 63633, "name": "Best Sleep"}]
🔴Assistant Bien sûr ! Nous avons à la fois Cloud Nine et Best Sleep
🔵Utilisateur Quelle est la différence entre ces actions ?
🔴Assistant (appel de fonction) Products.GetDetails(25323) Products.GetDetails(63633)
🟢Outil { "id": 25323, "name": "Cloud Nine", "price": 1000, "material": "Memory foam" }
🟢Outil { "id": 63633, "name": "Best Sleep", "price": 1200, "material": "Latex" }
🔴Assistant Cloud Nine est fait de mousse de mémoire et coûte 1 000 $. Best Sleep est fait de latex et coûte $1200.

Récupération des données pré-extraites

La récupération statique des données implique d’extraire des données à partir de sources externes et de les fournir toujours à l’agent IA. Cela est utile lorsque les données sont requises pour chaque requête ou lorsque les données sont relativement stables et ne changent pas fréquemment.

Prenons l’exemple d’un agent qui répond toujours aux questions sur la météo locale. En supposant que vous disposez d’un WeatherPlugin, vous pouvez pré-extraire des données météorologiques à partir d’une API météo et les fournir dans l’historique des conversations. Cela permet à l’agent de générer des réponses sur la météo sans perdre de temps en demandant les données de l’API.

using System.Text.Json;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

IKernelBuilder builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);
builder.Plugins.AddFromType<WeatherPlugin>();
Kernel kernel = builder.Build();

// Get the weather
var weather = await kernel.Plugins.GetFunction("WeatherPlugin", "get_weather").InvokeAsync(kernel);

// Initialize the chat history with the weather
ChatHistory chatHistory = new ChatHistory("The weather is:\n" + JsonSerializer.Serialize(weather));

// Simulate a user message
chatHistory.AddUserMessage("What is the weather like today?");

// Get the answer from the AI agent
IChatCompletionService chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory);

Sécuriser les données

Lors de la récupération de données à partir de sources externes, il est important de s’assurer que les données sont sécurisées et que les informations sensibles ne sont pas exposées. Pour éviter le sur-partage d’informations sensibles, vous pouvez utiliser les stratégies suivantes :

Stratégie Description
Utiliser le jeton d’authentification de l’utilisateur Évitez de créer des principaux de service utilisés par l’agent IA pour récupérer des informations pour les utilisateurs. Cela rend difficile la vérification qu’un utilisateur a accès aux informations récupérées.
Éviter de recréer des services de recherche Avant de créer un service de recherche avec une base de données vectorielle, vérifiez si un service existe déjà pour le service qui a les données requises. En réutilisant les services existants, vous pouvez éviter de dupliquer du contenu sensible, tirer parti des contrôles d’accès existants et utiliser des mécanismes de filtrage existants qui retournent uniquement les données auxquelles l’utilisateur a accès.
Stocker des références dans des bases de données vectorielles au lieu du contenu Au lieu de dupliquer du contenu sensible aux bases de données vectorielles, vous pouvez stocker des références aux données réelles. Pour qu’un utilisateur accède à ces informations, son jeton d’authentification doit d’abord être utilisé pour récupérer les données réelles.

Étapes suivantes

Maintenant que vous allez maintenant mettre en place vos agents IA avec des données provenant de sources externes, vous pouvez maintenant apprendre à utiliser des agents IA pour automatiser les processus métier. Pour en savoir plus, consultez l’utilisation des fonctions d’automatisation des tâches.