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.
- Pomocí konektoru Vector Store načtěte kolekci záznamů, kterou chcete prohledat.
- Zabalte kolekci záznamů pomocí
VectorStoreTextSearch
. - 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.
Použití modelu vektorového úložiště s vyhledáváním textu
Mapování z datového modelu Vector Store na datový TextSearchResult
model lze provést deklarativním způsobem pomocí atributů.
[TextSearchResultValue]
- Přidejte tento atribut do vlastnosti datového modelu, což bude hodnotaTextSearchResult
, například textová data, která model AI použije k zodpovězení otázek.[TextSearchResultName]
- Přidejte tento atribut do vlastnosti datového modelu, který bude název objektuTextSearchResult
.[TextSearchResultLink]
- Přidejte tento atribut do vlastnosti datového modelu, který bude odkazem naTextSearchResult
.
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:
- 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.
- 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);
Použití vektorového úložiště s vyhledáváním textu
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 SearchPlugin
do .
Tady je několik věcí, které byste mohli chtít udělat:
- 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. - 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í.
- 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.