Dela via


Så här använder du vektorlager med semantisk kerneltextsökning

Alla anslutningsprogram för Vector Store kan användas för textsökning.

  1. Använd anslutningsprogrammet för Vector Store för att hämta den postsamling som du vill söka i.
  2. Omslut postsamlingen med VectorStoreTextSearch.
  3. Konvertera till ett plugin-program för användning i scenarier med RAG- och/eller funktionsanrop.

Det är mycket troligt att du vill anpassa sökfunktionen för plugin-programmet så att beskrivningen visar vilken typ av data som är tillgängliga i postsamlingen. Om postsamlingen till exempel innehåller information om hotell bör beskrivningen av plugin-sökfunktionen nämna detta. På så sätt kan du registrera flera plugin-program, t.ex. ett för att söka efter hotell, ett annat för restauranger och ett annat för saker att göra.

Sammanfattningarna av textsökningen innehåller en funktion för att returnera ett normaliserat sökresultat, t.ex. en instans av TextSearchResult. Det här normaliserade sökresultatet innehåller ett värde och eventuellt ett namn och en länk. Sammanfattningarna av textsökningen innehåller en funktion för att returnera ett strängvärde, t.ex. en av datamodellegenskaperna returneras som sökresultat. För att textsökningen ska fungera korrekt måste du ange ett sätt att mappa från datamodellen Vector Store till en instans av TextSearchResult. I nästa avsnitt beskrivs de två alternativ som du kan använda för att utföra den här mappningen.

Dricks

Om du vill köra exemplen som visas på den här sidan går du till GettingStartedWithTextSearch/Step4_Search_With_VectorStore.cs.

Mappningen från en Vector Store-datamodell till en TextSearchResult kan utföras deklarativt med hjälp av attribut.

  1. [TextSearchResultValue] – Lägg till det här attributet till egenskapen för datamodellen som ska vara värdet för TextSearchResult, t.ex. de textdata som AI-modellen använder för att besvara frågor.
  2. [TextSearchResultName] – Lägg till det här attributet i egenskapen för datamodellen som ska vara namnet på TextSearchResult.
  3. [TextSearchResultLink] – Lägg till det här attributet i egenskapen för datamodellen som är länken till TextSearchResult.

Följande exempel visar en datamodell som har textsökresultatattributen tillämpade.

using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Data;

public sealed class DataModel
{
    [VectorStoreRecordKey]
    [TextSearchResultName]
    public Guid Key { get; init; }

    [VectorStoreRecordData]
    [TextSearchResultValue]
    public string Text { get; init; }

    [VectorStoreRecordData]
    [TextSearchResultLink]
    public string Link { get; init; }

    [VectorStoreRecordData(IsFilterable = true)]
    public required string Tag { get; init; }

    [VectorStoreRecordVector(1536)]
    public ReadOnlyMemory<float> Embedding { get; init; }
}

Mappningen från en Vector Store-datamodell till en string eller en TextSearchResult kan också göras genom att tillhandahålla implementeringar av ITextSearchResultMapper ITextSearchStringMapper respektive.

Du kan välja att skapa anpassade mappare för följande scenarier:

  1. Flera egenskaper från datamodellen måste kombineras, t.ex. om flera egenskaper behöver kombineras för att ange värdet.
  2. Ytterligare logik krävs för att generera en av egenskaperna, t.ex. om länkegenskapen behöver beräknas från datamodellegenskaperna.

Följande exempel visar en datamodell och två exempel på mappningsimplementeringar som kan användas med datamodellen.

using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Data;

protected sealed class DataModel
{
    [VectorStoreRecordKey]
    public Guid Key { get; init; }

    [VectorStoreRecordData]
    public required string Text { get; init; }

    [VectorStoreRecordData]
    public required string Link { get; init; }

    [VectorStoreRecordData(IsFilterable = true)]
    public required string Tag { get; init; }

    [VectorStoreRecordVector(1536)]
    public ReadOnlyMemory<float> Embedding { get; init; }
}

/// <summary>
/// String mapper which converts a DataModel to a string.
/// </summary>
protected sealed class DataModelTextSearchStringMapper : ITextSearchStringMapper
{
    /// <inheritdoc />
    public string MapFromResultToString(object result)
    {
        if (result is DataModel dataModel)
        {
            return dataModel.Text;
        }
        throw new ArgumentException("Invalid result type.");
    }
}

/// <summary>
/// Result mapper which converts a DataModel to a TextSearchResult.
/// </summary>
protected sealed class DataModelTextSearchResultMapper : ITextSearchResultMapper
{
    /// <inheritdoc />
    public TextSearchResult MapFromResultToTextSearchResult(object result)
    {
        if (result is DataModel dataModel)
        {
            return new TextSearchResult(value: dataModel.Text) { Name = dataModel.Key.ToString(), Link = dataModel.Link };
        }
        throw new ArgumentException("Invalid result type.");
    }
}

Mappningsimplementeringarna kan anges som parametrar när du skapar enligt VectorStoreTextSearch nedan:

using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Data;

// Create custom mapper to map a <see cref="DataModel"/> to a <see cref="string"/>
var stringMapper = new DataModelTextSearchStringMapper();

// Create custom mapper to map a <see cref="DataModel"/> to a <see cref="TextSearchResult"/>
var resultMapper = new DataModelTextSearchResultMapper();

// Add code to create instances of IVectorStoreRecordCollection and ITextEmbeddingGenerationService 

// Create a text search instance using the vector store record collection.
var result = new VectorStoreTextSearch<DataModel>(vectorStoreRecordCollection, textEmbeddingGeneration, stringMapper, resultMapper);

Exemplet nedan visar hur du skapar en instans av VectorStoreTextSearch att använda en Vector Store-postsamling.

Dricks

Följande exempel kräver instanser av IVectorStoreRecordCollection och ITextEmbeddingGenerationService. Om du vill skapa en instans av IVectorStoreRecordCollection läser du dokumentationen för varje anslutningsapp. Om du vill skapa en instans av ITextEmbeddingGenerationService väljer du den tjänst som du vill använda, t.ex. Azure OpenAI, OpenAI, ... eller använda en lokal modell ONNX, Ollama, ... och skapa en instans av motsvarande ITextEmbeddingGenerationService implementering.

Dricks

A VectorStoreTextSearch kan också konstrueras från en instans av IVectorizableTextSearch. I det här fallet behövs inget ITextEmbeddingGenerationService .

using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;

// Add code to create instances of IVectorStoreRecordCollection and ITextEmbeddingGenerationService 

// Create a text search instance using the vector store record collection.
var textSearch = new VectorStoreTextSearch<DataModel>(vectorStoreRecordCollection, textEmbeddingGeneration);

// Search and return results as TextSearchResult items
var query = "What is the Semantic Kernel?";
KernelSearchResults<TextSearchResult> textResults = await textSearch.GetTextSearchResultsAsync(query, new() { Top = 2, Skip = 0 });
Console.WriteLine("\n--- Text Search Results ---\n");
await foreach (TextSearchResult result in textResults.Results)
{
    Console.WriteLine($"Name:  {result.Name}");
    Console.WriteLine($"Value: {result.Value}");
    Console.WriteLine($"Link:  {result.Link}");
}

Skapa ett sök-plugin-program från ett vektorarkiv

Exemplet nedan visar hur du skapar ett plugin-program med namnet SearchPlugin från en instans av VectorStoreTextSearch. Genom att använda CreateWithGetTextSearchResults skapas ett nytt plugin-program med en enda GetTextSearchResults funktion som anropar implementeringen av den underliggande vektorlagringssamlingens sökning. SearchPlugin Läggs till i som gör den Kernel tillgänglig för att anropas under promptrendering. Promptmallen innehåller ett anrop som {{SearchPlugin.Search $query}} anropar SearchPlugin för att hämta resultat relaterade till den aktuella frågan. Resultatet infogas sedan i den renderade prompten innan den skickas till modellen.

using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;

// Create a kernel with OpenAI chat completion
IKernelBuilder kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddOpenAIChatCompletion(
        modelId: TestConfiguration.OpenAI.ChatModelId,
        apiKey: TestConfiguration.OpenAI.ApiKey);
Kernel kernel = kernelBuilder.Build();

// Add code to create instances of IVectorStoreRecordCollection and ITextEmbeddingGenerationService

// Create a text search instance using the vector store record collection.
var textSearch = new VectorStoreTextSearch<DataModel>(vectorStoreRecordCollection, textEmbeddingGeneration);

// Build a text search plugin with vector store search and add to the kernel
var searchPlugin = textSearch.CreateWithGetTextSearchResults("SearchPlugin");
kernel.Plugins.Add(searchPlugin);

// Invoke prompt and use text search plugin to provide grounding information
var query = "What is the Semantic Kernel?";
string promptTemplate = """
    {{#with (SearchPlugin-GetTextSearchResults query)}}  
        {{#each this}}  
        Name: {{Name}}
        Value: {{Value}}
        Link: {{Link}}
        -----------------
        {{/each}}  
    {{/with}}  

    {{query}}

    Include citations to the relevant information where it is referenced in the response.
    """;
KernelArguments arguments = new() { { "query", query } };
HandlebarsPromptTemplateFactory promptTemplateFactory = new();
Console.WriteLine(await kernel.InvokePromptAsync(
    promptTemplate,
    arguments,
    templateFormat: HandlebarsPromptTemplateFactory.HandlebarsTemplateFormat,
    promptTemplateFactory: promptTemplateFactory
));

Använda ett vektorlager med funktionsanrop

Exemplet nedan skapar också en SearchPlugin från en instans av VectorStoreTextSearch. Det här plugin-programmet kommer att annonseras till modellen för användning med automatiska funktionsanrop med hjälp av FunctionChoiceBehavior inställningarna för körning av fråga. När du kör det här exemplet anropar modellen sökfunktionen för att hämta ytterligare information för att svara på frågan. Den söker förmodligen bara efter "semantisk kernel" i stället för hela frågan.

using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;

// Create a kernel with OpenAI chat completion
IKernelBuilder kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddOpenAIChatCompletion(
        modelId: TestConfiguration.OpenAI.ChatModelId,
        apiKey: TestConfiguration.OpenAI.ApiKey);
Kernel kernel = kernelBuilder.Build();

// Add code to create instances of IVectorStoreRecordCollection and ITextEmbeddingGenerationService

// Create a text search instance using the vector store record collection.
var textSearch = new VectorStoreTextSearch<DataModel>(vectorStoreRecordCollection, textEmbeddingGeneration);

// Build a text search plugin with vector store search and add to the kernel
var searchPlugin = textSearch.CreateWithGetTextSearchResults("SearchPlugin");
kernel.Plugins.Add(searchPlugin);

// Invoke prompt and use text search plugin to provide grounding information
OpenAIPromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
KernelArguments arguments = new(settings);
Console.WriteLine(await kernel.InvokePromptAsync("What is the Semantic Kernel?", arguments));

Anpassa sökfunktionen

Exemplet nedan visar hur du anpassar beskrivningen av sökfunktionen som läggs till i SearchPlugin. Några saker du kanske vill göra är:

  1. Ändra namnet på sökfunktionen så att den återspeglar vad som finns i den associerade postsamlingen, t.ex. vill du kanske namnge funktionen SearchForHotels om postsamlingen innehåller hotellinformation.
  2. Ändra beskrivningen av funktionen. En korrekt funktionsbeskrivning hjälper AI-modellen att välja den bästa funktionen att anropa. Detta är särskilt viktigt om du lägger till flera sökfunktioner.
  3. Lägg till ytterligare en parameter i sökfunktionen. Om postsamlingen innehåller hotellinformation och en av egenskaperna är stadsnamnet kan du lägga till en egenskap i sökfunktionen för att ange staden. Ett filter läggs till automatiskt och sökresultaten filtreras efter stad.

Dricks

Exemplet nedan använder standardimplementeringen av sökningen. Du kan välja att tillhandahålla en egen implementering som anropar den underliggande Vector Store-postsamlingen med ytterligare alternativ för att finjustera dina sökningar.

using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;

// Create a kernel with OpenAI chat completion
IKernelBuilder kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddOpenAIChatCompletion(
        modelId: TestConfiguration.OpenAI.ChatModelId,
        apiKey: TestConfiguration.OpenAI.ApiKey);
Kernel kernel = kernelBuilder.Build();

// Add code to create instances of IVectorStoreRecordCollection and ITextEmbeddingGenerationService

// Create a text search instance using the vector store record collection.
var textSearch = new VectorStoreTextSearch<DataModel>(vectorStoreRecordCollection, textEmbeddingGeneration);

// Create options to describe the function I want to register.
var options = new KernelFunctionFromMethodOptions()
{
    FunctionName = "Search",
    Description = "Perform a search for content related to the specified query from a record collection.",
    Parameters =
    [
        new KernelParameterMetadata("query") { Description = "What to search for", IsRequired = true },
        new KernelParameterMetadata("top") { Description = "Number of results", IsRequired = false, DefaultValue = 2 },
        new KernelParameterMetadata("skip") { Description = "Number of results to skip", IsRequired = false, DefaultValue = 0 },
    ],
    ReturnParameter = new() { ParameterType = typeof(KernelSearchResults<string>) },
};

// Build a text search plugin with vector store search and add to the kernel
var searchPlugin = textSearch.CreateWithGetTextSearchResults("SearchPlugin", "Search a record collection", [textSearch.CreateSearch(options)]);
kernel.Plugins.Add(searchPlugin);

// Invoke prompt and use text search plugin to provide grounding information
OpenAIPromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
KernelArguments arguments = new(settings);
Console.WriteLine(await kernel.InvokePromptAsync("What is the Semantic Kernel?", arguments));

Kommer snart

Fler kommer snart.

Kommer snart

Fler kommer snart.

Nästa steg