Sdílet prostřednictvím


Použití vektorových úložišť s sémantickým vyhledáváním textu jádra

Všechny konektory vektorového úložiště je možné použít pro vyhledávání textu.

  1. Pomocí konektoru Vector Store načtěte kolekci záznamů, kterou chcete prohledat.
  2. Zabalte kolekci záznamů pomocí VectorStoreTextSearch.
  3. Převeďte na modul plug-in pro použití ve scénářích volání rag a/nebo funkcí.

Je velmi pravděpodobné, že budete chtít přizpůsobit funkci vyhledávání modulu plug-in tak, aby její popis odrážel typ dat dostupných v kolekci záznamů. Pokud například kolekce záznamů obsahuje informace o hotelech, měl by se o tom zmínit popis funkce vyhledávání modulu plug-in. To vám umožní zaregistrovat více modulů plug-in, například jeden pro vyhledávání hotelů, jiný pro restaurace a další věci, které je potřeba udělat.

Abstrakce hledání textu zahrnují funkci pro vrácení normalizovaného výsledku hledání, tj. instance TextSearchResult. Tento normalizovaný výsledek hledání obsahuje hodnotu a volitelně název a odkaz. Abstrakce hledání textu zahrnují funkci, která vrátí řetězcovou hodnotu, například jedna z vlastností datového modelu bude vrácena jako výsledek hledání. Aby vyhledávání textu fungovalo správně, musíte poskytnout způsob mapování z datového modelu Vector Store na instanci TextSearchResult. Následující část popisuje dvě možnosti, které můžete použít k provedení tohoto mapování.

Tip

Pokud chcete spustit ukázky uvedené na této stránce, přejděte na GettingStartedWithTextSearch/Step4_Search_With_VectorStore.cs.

Mapování z datového modelu Vector Store na datový TextSearchResult model lze provést deklarativním způsobem pomocí atributů.

  1. [TextSearchResultValue] - Přidejte tento atribut do vlastnosti datového modelu, což bude hodnota TextSearchResult, například textová data, která model AI použije k zodpovězení otázek.
  2. [TextSearchResultName] - Přidejte tento atribut do vlastnosti datového modelu, který bude název objektu TextSearchResult.
  3. [TextSearchResultLink] - Přidejte tento atribut do vlastnosti datového modelu, který bude odkazem na TextSearchResult.

Následující ukázka ukazuje datový model, který má použité atributy výsledků hledání textu.

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

Mapování z datového modelu vektorového úložiště na string datový model nebo model TextSearchResult lze provést také poskytnutím implementací ITextSearchStringMapper a ITextSearchResultMapper v uvedeném pořadí.

Můžete se rozhodnout vytvořit vlastní mapovače pro následující scénáře:

  1. Pokud je potřeba zkombinovat více vlastností z datového modelu, musí se například zkombinovat více vlastností, aby bylo možné zadat hodnotu.
  2. K vygenerování jedné z vlastností datového modelu se vyžaduje další logika, například pokud je potřeba vypočítat vlastnost propojení z vlastností datového modelu.

Následující ukázka ukazuje datový model a dvě ukázkové implementace mapovačů, které lze použít s datovým modelem.

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

Implementace mapperu je možné zadat jako parametry při vytváření, VectorStoreTextSearch jak je znázorněno níže:

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

Následující ukázka ukazuje, jak vytvořit instanci VectorStoreTextSearch použití kolekce záznamů Vector Store.

Tip

Následující ukázky vyžadují instance IVectorStoreRecordCollection a ITextEmbeddingGenerationService. Pokud chcete vytvořit instanci IVectorStoreRecordCollection , přečtěte si dokumentaci ke každému konektoru. Pokud chcete vytvořit instanci ITextEmbeddingGenerationService výběru služby, kterou chcete použít, například Azure OpenAI, OpenAI, ... nebo použijte místní model ONNX, Ollama, ... a vytvořte instanci odpovídající ITextEmbeddingGenerationService implementace.

Tip

A VectorStoreTextSearch lze také vytvořit z instance IVectorizableTextSearch. V takovém případě není ITextEmbeddingGenerationService potřeba.

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

Vytvoření modulu plug-in vyhledávání z úložiště vektorů

Následující ukázka ukazuje, jak vytvořit modul plug-in pojmenovaný SearchPlugin z instance VectorStoreTextSearch. Použití CreateWithGetTextSearchResults vytvoří nový modul plug-in s jedinou GetTextSearchResults funkcí, která volá základní implementaci vyhledávání kolekce záznamů Vector Store. Přidá SearchPlugin se do Kernel něj, aby bylo možné volat během vykreslování výzvy. Šablona výzvy obsahuje volání {{SearchPlugin.Search $query}} , které vyvolá výsledky SearchPlugin související s aktuálním dotazem. Výsledky se pak před odesláním do modelu vloží do vykreslené výzvy.

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

Použití vektorového úložiště s voláním funkce

Následující ukázka také vytvoří SearchPlugin z instance VectorStoreTextSearch. Tento modul plug-in se bude inzerovat do modelu pro použití s automatickým voláním funkce pomocí FunctionChoiceBehavior nastavení spuštění výzvy. Když spustíte tuto ukázku, model vyvolá vyhledávací funkci, která načte další informace pro odpověď na otázku. Pravděpodobně bude místo celého dotazu hledat "Sémantické jádro".

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

Přizpůsobení vyhledávací funkce

Následující ukázka, jak přizpůsobit popis vyhledávací funkce, která je přidána SearchPlugindo . Tady je několik věcí, které byste mohli chtít udělat:

  1. Změňte název vyhledávací funkce tak, aby odrážel, co je v přidružené kolekci záznamů, například pokud SearchForHotels kolekce záznamů obsahuje informace o hotelu.
  2. Změňte popis funkce. Přesný popis funkce pomáhá modelu AI vybrat nejlepší funkci, která se má volat. To je zvlášť důležité, pokud přidáváte více vyhledávacích funkcí.
  3. Přidejte do vyhledávací funkce další parametr. Pokud kolekce záznamů obsahuje informace o hotelu a jedna z vlastností je název města, můžete do vyhledávací funkce přidat vlastnost, která určí město. Filtr se přidá automaticky a bude filtrovat výsledky hledání podle města.

Tip

Následující ukázka používá výchozí implementaci vyhledávání. Můžete se rozhodnout zadat vlastní implementaci, která volá podkladovou kolekci záznamů Vector Store s dalšími možnostmi pro vyladění hledání.

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

Již brzy

Další připravujeme.

Již brzy

Další připravujeme.

Další kroky