Condividi tramite


Usare Redis per l'archiviazione di memoria con l’SDK del kernel semantico

Questo articolo illustra come integrare un database Redis con il modulo RediSearch nell’SDK del kernel semantico e usarlo per l'archiviazione e il recupero della memoria.

Gli archivi vettoriali rappresentano informazioni di testo che sono state archiviate insieme a un vettore di incorporamento precalcolato per l'intero testo. Quando viene richiesto di richiamare una memoria, un modello linguistico di grandi dimensioni (LLM) usa questi incorporamenti precalcolati per valutare in modo efficiente se tale memoria è rilevante per la richiesta. Dopo aver trovato la memoria corrispondente, l’LLM usa le informazioni sul testo della memoria come contesto per i passaggi successivi del completamento della richiesta.

L'archiviazione di memoria aggiunta all'SDK del kernel semantico offre un contesto più ampio per le richieste. Consente inoltre di archiviare i dati nello stesso modo in cui si archivia un database tradizionale, ma di eseguirne query usando il linguaggio naturale.

Prerequisiti

Implementare l'archiviazione di memoria usando un database Redis

Prima di integrare il database Redis nell’SDK del kernel semantico, assicurarsi di avere abilitato il modulo RediSearch. Per informazioni sul modulo per Cache di Azure per Redis, vedere Usare moduli Redis con Cache di Azure per Redis.

  1. Inizializzare una connessione al database Redis. Ad esempio:

    // Retrieve the Redis connection config.
    IConfigurationRoot config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
    string redisConfig = config["REDIS_CONFIG"]!;
    
    // Initialize a connection to the Redis database.
    ConnectionMultiplexer connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(
        redisConfig
    );
    IDatabase database = connectionMultiplexer.GetDatabase();
    
  2. Compilare il Kernel includendo ITextEmbeddingGenerationService. Ad esempio:

    // Retrieve the Azure OpenAI config and secrets saved during deployment.
    string endpoint = config["AZURE_OPENAI_ENDPOINT"]!;
    string embeddingModel = config["AZURE_OPENAI_EMBEDDING_NAME"]!;
    string completionModel = config["AZURE_OPENAI_GPT_NAME"]!;
    string key = config["AZURE_OPENAI_KEY"]!;
    
    // Build the Kernel; must add an embedding generation service.
    Kernel kernel = Kernel
        .CreateBuilder()
        .AddAzureOpenAITextEmbeddingGeneration(embeddingModel, endpoint, key)
        .AddAzureOpenAIChatCompletion(completionModel, endpoint, key)
        .Build();
    
  3. Eseguire il wrapping del database Redis in un'istanza RedisMemoryStore e quindi inizializzare un oggetto SemanticTextMemory usando l'archivio di memoria e il servizio di generazione di incorporamento. Ad esempio:

    // Retrieve the desired vector size for the memory store.
    // If unspecified, the default vector size is 1536.
    int vectorSize = int.Parse(config["REDIS_MEMORY_VECTOR_SIZE"]!);
    
    // Initialize a memory store using the redis database
    IMemoryStore memoryStore = new RedisMemoryStore(database, vectorSize);
    
    // Retrieve the embedding service from the Kernel.
    ITextEmbeddingGenerationService embeddingService =
        kernel.Services.GetRequiredService<ITextEmbeddingGenerationService>();
    
    // Initialize a SemanticTextMemory using the memory store and embedding generation service.
    SemanticTextMemory textMemory = new(memoryStore, embeddingService);
    
  4. Aggiungere la memoria del testo semantico a Kernel usando la classe TextMemoryPlugin. Ad esempio:

    // Initialize a TextMemoryPlugin using the text memory.
    TextMemoryPlugin memoryPlugin = new(textMemory);
    
    // Import the text memory plugin into the Kernel.
    KernelPlugin memory = kernel.ImportPluginFromObject(memoryPlugin);
    
  5. Usare il Kernel e il plug-in per salvare, recuperare e richiamare le memorie. Ad esempio:

    // Retrieve the desired memory collection name.
    string memoryCollectionName = config["REDIS_MEMORY_COLLECTION_NAME"]!;
    
    // Save a memory with the Kernel.
    await kernel.InvokeAsync(
        memory["Save"],
        new()
        {
            [TextMemoryPlugin.InputParam] = "My family is from New York",
            [TextMemoryPlugin.CollectionParam] = memoryCollectionName,
            [TextMemoryPlugin.KeyParam] = "info1",
        }
    );
    
    // Retrieve a memory with the Kernel.
    FunctionResult result = await kernel.InvokeAsync(
        memory["Retrieve"],
        new()
        {
            [TextMemoryPlugin.CollectionParam] = memoryCollectionName,
            [TextMemoryPlugin.KeyParam] = "info1",
        }
    );
    
    // Get the memory string from the function result; returns a null value if no memory is found.
    Console.WriteLine(
        $"Retrieved memory: {result.GetValue<string>() ?? "ERROR: memory not found"}"
    );
    
    // Alternatively, recall similar memories with the Kernel.
    // Can configure the memory collection, number of memories to recall, and relevance score.
    result = await kernel.InvokeAsync(
        memory["Recall"],
        new()
        {
            [TextMemoryPlugin.InputParam] = "Ask: where do I live?",
            [TextMemoryPlugin.CollectionParam] = memoryCollectionName,
            [TextMemoryPlugin.LimitParam] = "2",
            [TextMemoryPlugin.RelevanceParam] = "0.79",
        }
    );
    
    // If memories are recalled, the function result can be deserialized as a string[].
    string? resultStr = result.GetValue<string>();
    string[]? parsedResult = string.IsNullOrEmpty(resultStr)
        ? null
        : JsonSerializer.Deserialize<string[]>(resultStr);
    Console.WriteLine(
        $"Recalled memories: {(parsedResult?.Length > 0 ? resultStr : "ERROR: memory not found")}"
    );
    
  6. Usare il richiamo della memoria come parte di una richiesta tramite la sintassi del modello di richiesta{{...}}. Ad esempio:

    // Create a prompt that includes memory recall.
    // The {{...}} syntax represents an expression to Semantic Kernel.
    // For more information on this syntax see:
    // https://learn.microsoft.com/semantic-kernel/prompts/prompt-template-syntax
    string memoryRecallPrompt = """ 
        Consider only the facts below when answering questions:
    
        BEGIN FACTS
        About me: {{recall 'where did I grow up?'}}
        END FACTS
    
        Question: What are some fun facts about my home state?
        """;
    
    // Invoke the prompt with the Kernel.
    // Must configure the memory collection, number of memories to recall, and relevance score.
    resultStr = await kernel.InvokePromptAsync<string>(
        memoryRecallPrompt,
        new()
        {
            [TextMemoryPlugin.CollectionParam] = memoryCollectionName,
            [TextMemoryPlugin.LimitParam] = "2",
            [TextMemoryPlugin.RelevanceParam] = "0.79",
        }
    );
    
    // If the memory recall fails, the model will indicate it has missing information in its output.
    // Otherwise the output will incorporate your memory as context.
    Console.WriteLine($"Output: {resultStr}");
    
  • [Usare RAG con SQL]
  • [Inserimento dati da SharePoint]
  • [Uso dei database vettoriali]