Compartir a través de


Uso de Redis para el almacenamiento de memoria con el SDK de Semantic Kernel

En este artículo se muestra cómo integrar una base de datos de Redis con el módulo RediSearch en el SDK de Semantic Kernel y usarlo para el almacenamiento y la recuperación de memoria.

Los almacenes de vectores representan información de texto que se ha almacenado junto con un vector de incrustación precalculado para todo el texto. Cuando se solicita a un LLM que recupere una memoria, usa estas inserciones precalculadas para evaluar de forma eficaz si una memoria es relevante para la solicitud. Una vez que el LLM encuentra una memoria coincidente, usa la información del texto de la memoria como contexto para los pasos siguientes en la finalización de la solicitud.

El almacenamiento de memoria que se agrega al SDK de Semantic Kernel proporciona un contexto más amplio para las solicitudes. También le permite almacenar datos de la misma manera que una base de datos tradicional, pero consultarla mediante lenguaje natural.

Requisitos previos

Implementación del almacenamiento de memoria mediante una base de datos de Redis

Antes de integrar la base de datos de Redis en el SDK de Semantic Kernel, asegúrese de que tiene habilitado el módulo RediSearch. Para más información sobre el módulo de Azure Cache for Redis, consulte Uso de módulos de Redis con Azure Cache for Redis.

  1. Inicialice una conexión a la base de datos de Redis. Por ejemplo:

    // 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. Compile el Kernel incluyendo ITextEmbeddingGenerationService. Por ejemplo:

    // 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. Encapsule la base de datos de Redis en una instancia de RedisMemoryStore y, a continuación, inicialice un objeto SemanticTextMemory mediante el almacén de memoria y el servicio de generación de inserciones. Por ejemplo:

    // 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. Agregue la memoria de texto semántico a Kernel mediante la clase TextMemoryPlugin. Por ejemplo:

    // 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. Use el Kernel y el complemento para guardar, recuperar y llamar memorias. Por ejemplo:

    // 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. Use la recuperación de memoria como parte de una solicitud mediante la sintaxis de la plantilla de solicitudes {{...}}. Por ejemplo:

    // 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}");
    
  • [Uso de RAG con SQL]
  • [Ingesta de datos de SharePoint]
  • [Trabajo con bases de datos vectoriales]