Uso dei plug-in per Retrieval Augmented Generation (RAG)

Spesso, i tuoi agenti di IA devono recuperare dati da fonti esterne per generare risposte fondate sui dati. Senza questo contesto aggiuntivo, gli agenti di intelligenza artificiale possono allucinare o fornire informazioni errate. Per risolvere questo problema, è possibile usare i plug-in per recuperare dati da origini esterne.

Nel valutare i plug-in per la Retrieval Augmented Generation (RAG), dovresti porti due domande:

  1. Come cercherai (o il tuo agente AI cercherà) i dati richiesti? È necessaria la ricerca semantica o la ricerca classica?
  2. Si conoscono già i dati necessari all'agente di intelligenza artificiale in anticipo (dati prelettura) o l'agente di intelligenza artificiale deve recuperare i dati in modo dinamico?
  3. Come proteggerai i tuoi dati ed eviterai la condivisione eccessiva di informazioni sensibili?

Quando si sviluppano plug-in per la generazione aumentata (RAG), è possibile usare due tipi di ricerca: ricerca semantica e ricerca classica.

La ricerca semantica usa i database vettoriali per comprendere e recuperare informazioni in base al significato e al contesto della query anziché solo alle parole chiave corrispondenti. Questo metodo consente al motore di ricerca di comprendere le sfumature del linguaggio, ad esempio sinonimi, concetti correlati e la finalità complessiva alla base di una query.

La ricerca semantica è eccellente negli ambienti in cui le query utente sono complesse, aperte o richiedono una comprensione più approfondita del contenuto. Ad esempio, la ricerca di "migliori smartphone per la fotografia" produrrebbe risultati che considerano il contesto delle caratteristiche di fotografia negli smartphone, piuttosto che corrispondere semplicemente alle parole "migliori", "smartphone" e "fotografia".

Quando si fornisce un LLM con una funzione di ricerca semantica, in genere è sufficiente definire una funzione con una singola query di ricerca. LLM userà quindi questa funzione per recuperare le informazioni necessarie. Di seguito è riportato un esempio di una funzione di ricerca semantica che usa Azure AI Search per trovare documenti simili a una determinata query.

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 ricerca classica, nota anche come ricerca basata su attributi o criteri, si basa sul filtro e sulla corrispondenza di termini o valori esatti all'interno di un set di dati. È particolarmente efficace per le query di database, le ricerche di inventario e qualsiasi situazione in cui è necessario filtrare in base a attributi specifici.

Ad esempio, se un utente vuole trovare tutti gli ordini effettuati da un ID cliente specifico o recuperare i prodotti all'interno di un intervallo di prezzi e una categoria specifici, la ricerca classica fornisce risultati precisi e affidabili. La ricerca classica, tuttavia, è limitata dall'impossibilità di comprendere il contesto o le variazioni nel linguaggio.

Tip

Nella maggior parte dei casi, i servizi esistenti supportano già la ricerca classica. Prima di implementare una ricerca semantica, valutare se i servizi esistenti possono fornire il contesto necessario per gli agenti di intelligenza artificiale.

Si supponga, ad esempio, un plug-in che recupera le informazioni dei clienti da un sistema CRM usando la ricerca classica. In questo caso, l'intelligenza artificiale deve semplicemente chiamare la GetCustomerInfoAsync funzione con un ID cliente per recuperare le informazioni necessarie.

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

Ottenere la stessa funzionalità di ricerca con la ricerca semantica probabilmente sarebbe impossibile o poco pratico a causa della natura non deterministica delle query semantiche.

Quando usare ciascuno

La scelta tra la ricerca semantica e quella classica dipende dalla natura della query. È ideale per ambienti con contenuto elevato, ad esempio knowledge base e supporto tecnico, in cui gli utenti potrebbero porre domande o cercare prodotti che usano il linguaggio naturale. La ricerca classica, d'altra parte, deve essere usata quando la precisione e le corrispondenze esatte sono importanti.

In alcuni scenari potrebbe essere necessario combinare entrambi gli approcci per offrire funzionalità di ricerca complete. Ad esempio, un chatbot che assiste i clienti in un negozio di e-commerce potrebbe usare la ricerca semantica per comprendere le query utente e la ricerca classica per filtrare i prodotti in base a attributi specifici, ad esempio prezzo, marchio o disponibilità.

Di seguito è riportato un esempio di plug-in che combina la ricerca semantica e classica per recuperare informazioni sui prodotti da un database di e-commerce.

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

Recupero di dati dinamiche e prelettura

Quando si sviluppano plug-in per la generazione aumentata (RAG), è necessario considerare anche se il processo di recupero dei dati è statico o dinamico. In questo modo è possibile ottimizzare le prestazioni degli agenti di intelligenza artificiale recuperando i dati solo quando necessario.

Recupero di dati dinamici

Nella maggior parte dei casi, la query utente determinerà i dati che l'agente di intelligenza artificiale deve recuperare. Ad esempio, un utente potrebbe chiedere la differenza tra due prodotti diversi. L'agente di intelligenza artificiale dovrà quindi recuperare dinamicamente le informazioni sul prodotto da un database o da un'API per generare una risposta usando la chiamata di funzione. Sarebbe poco pratico pre-recuperare tutte le informazioni sul prodotto possibili in anticipo e assegnargli all'agente di intelligenza artificiale.

Di seguito è riportato un esempio di chat back-and-forth tra un utente e un agente di intelligenza artificiale in cui è necessario il recupero di dati dinamici.

Ruolo Message
🔵 Utente Puoi dirmi dei migliori materassi?
🔴 Assistente (chiamata di funzione) Products.Search("mattresses")
🟢 Strumento [{"id": 25323, "name": "Cloud Nine"},{"id": 63633, "name": "Best Sleep"}]
🔴 Assistente Certo! Abbiamo sia Cloud Nine che Best Sleep
🔵 Utente Qual è la differenza tra i due tipi di soluzioni?
🔴 Assistente (chiamata di funzione) Products.GetDetails(25323) Products.GetDetails(63633)
🟢 Strumento { "id": 25323, "name": "Cloud Nine", "price": 1000, "material": "Memory foam" }
🟢 Strumento { "id": 63633, "name": "Best Sleep", "price": 1200, "material": "Latex" }
🔴 Assistente Cloud Nine è fatto di schiuma di memoria e costa $ 1000. Best Sleep è fatto di latex e costa $ 1200.

Recupero dei dati precaricati

Il recupero di dati statici comporta il recupero di dati da origini esterne e la fornitura sempre all'agente di intelligenza artificiale. Ciò è utile quando i dati sono necessari per ogni richiesta o quando i dati sono relativamente stabili e non cambiano di frequente.

Si supponga, ad esempio, che un agente risponda sempre alle domande sul meteo locale. Supponendo di avere un WeatherPlugin, è possibile pre-recuperare i dati meteo da un'API meteo e specificarli nella cronologia delle chat. Ciò consente all'agente di generare risposte sul meteo senza perdere tempo richiedendo i dati dall'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);

Garantire la sicurezza dei dati

Quando si recuperano dati da origini esterne, è importante assicurarsi che i dati siano sicuri e che le informazioni riservate non vengano esposte. Per evitare l'oversharing delle informazioni riservate, è possibile usare le strategie seguenti:

Strategy Description
Usare il token di autenticazione dell'utente Evitare di creare entità servizio usate dall'agente di intelligenza artificiale per recuperare informazioni per gli utenti. In questo modo è difficile verificare che un utente abbia accesso alle informazioni recuperate.
Evitare di ricreare i servizi di ricerca Prima di creare un nuovo servizio di ricerca con un database vettoriale, verificare se ne esiste già uno per il servizio con i dati necessari. Riutilizzando i servizi esistenti, è possibile evitare la duplicazione di contenuto sensibile, sfruttare i controlli di accesso esistenti e usare meccanismi di filtro esistenti che restituiscono solo i dati a cui l'utente ha accesso.
Archiviare i riferimenti nei database vettoriali invece del contenuto Anziché duplicare il contenuto sensibile ai database vettoriali, è possibile archiviare i riferimenti ai dati effettivi. Per consentire a un utente di accedere a queste informazioni, è necessario usare prima di tutto il token di autenticazione per recuperare i dati reali.

Passaggi successivi

Ora che sai come collegare i tuoi agenti IA ai dati provenienti da fonti esterne, puoi imparare a usare gli agenti IA per automatizzare i processi aziendali. Per altre informazioni, vedere Uso delle funzioni di automazione delle attività.