Uso di plug-in per la generazione aumentata di recupero (RAG)

Spesso, gli agenti di intelligenza artificiale devono recuperare dati da origini esterne per generare risposte a terra. 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.

Quando si considerano i plug-in per la generazione aumentata (RAG), è consigliabile porsi due domande:

  1. In che modo (o l'agente di intelligenza artificiale) "cercare" i dati necessari? È 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 si proteggeranno i dati e si impedirà l'oversharing delle informazioni riservate?

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 Ricerca intelligenza artificiale di Azure 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.

Suggerimento

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 ogni

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 Certamente. 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 prelettura

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:

Strategia Descrizione
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 è ora possibile basare gli agenti di intelligenza artificiale con i dati provenienti da origini esterne, è ora possibile imparare a usare gli agenti di intelligenza artificiale per automatizzare i processi aziendali. Per altre informazioni, vedere Uso delle funzioni di automazione delle attività.