セマンティック カーネル テキスト検索でベクター ストアを使用する方法
ベクター ストアのすべての コネクタ をテキスト検索に使用できます。
- Vector Store コネクタを使用して、検索するレコード コレクションを取得します。
- レコード コレクションを
VectorStoreTextSearch
でラップします。 - RAG や関数呼び出しのシナリオで使用するためにプラグインに変換します。
プラグイン検索機能をカスタマイズして、レコード コレクションで使用可能なデータの種類を説明に反映させる必要がある可能性が非常に高くなります。 たとえば、レコード コレクションにホテルに関する情報が含まれている場合は、プラグイン検索機能の説明でこれに言及する必要があります。 これにより、複数のプラグインを登録できます。たとえば、1 つはホテルを検索し、もう 1 つはレストラン用に、もう 1 つは実行できます。
テキスト検索の抽象化には正規化された検索結果 、つまりTextSearchResult
のインスタンスを返す関数が含まれます。
この正規化された検索結果には、値と、必要に応じて名前とリンクが含まれます。
テキスト検索の抽象化には文字列値を返す関数が含まれています。たとえば、データ モデルのプロパティの 1 つが検索結果として返されます。
テキスト検索を正しく機能させるには、Vector Store データ モデルから TextSearchResult
のインスタンスにマップする方法を提供する必要があります。
次のセクションでは、このマッピングを実行するために使用できる 2 つのオプションについて説明します。
ヒント
このページに示されているサンプルを実行するには、 GettingStartedWithTextSearch/Step4_Search_With_VectorStore.cs に移動します。
テキスト検索でのベクター ストア モデルの使用
Vector Store データ モデルから TextSearchResult
へのマッピングは、属性を使用して宣言によって行うことができます。
[TextSearchResultValue]
- AI モデルが質問に回答するために使用するテキスト データなど、TextSearchResult
の値となるデータ モデルのプロパティにこの属性を追加します。[TextSearchResultName]
- この属性を、TextSearchResult
の名前となるデータ モデルのプロパティに追加します。[TextSearchResultLink]
- この属性を、TextSearchResult
へのリンクとなるデータ モデルのプロパティに追加します。
次の例は、テキスト検索結果属性が適用されたデータ モデルを示しています。
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; }
}
Vector Store データ モデルから string
または TextSearchResult
へのマッピングは、それぞれ ITextSearchStringMapper
と ITextSearchResultMapper
の実装を提供することで行うこともできます。
次のシナリオに合わせてカスタム マッパーを作成できます。
- 複数のプロパティを組み合わせて値を指定する必要がある場合など、データ モデルの複数のプロパティを組み合わせる必要があります。
- リンク プロパティをデータ モデルのプロパティから計算する必要がある場合など、プロパティの 1 つを生成するには、追加のロジックが必要です。
次の例は、データ モデルと、データ モデルで使用できる 2 つのマッパー実装例を示しています。
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.");
}
}
マッパーの実装は、次に示すように、 VectorStoreTextSearch
を作成するときにパラメーターとして提供できます。
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);
テキスト検索でのベクター ストアの使用
次のサンプルは、Vector Store レコード コレクションを使用して VectorStoreTextSearch
のインスタンスを作成する方法を示しています。
ヒント
次のサンプルでは、 IVectorStoreRecordCollection
と ITextEmbeddingGenerationService
のインスタンスが必要です。
IVectorStoreRecordCollection
のインスタンスを作成するには、各コネクタのドキュメントを参照してください。
ITextEmbeddingGenerationService
のインスタンスを作成するには、使用するサービス (Azure OpenAI、OpenAI、...または、ローカル モデル ONNX、Ollama、... を使用します。対応するITextEmbeddingGenerationService
実装のインスタンスを作成します。
ヒント
VectorStoreTextSearch
は、IVectorizableTextSearch
のインスタンスから構築することもできます。 この場合、 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}");
}
ベクター ストアからの検索プラグインの作成
次のサンプルは、VectorStoreTextSearch
のインスタンスから SearchPlugin
という名前のプラグインを作成する方法を示しています。
CreateWithGetTextSearchResults
を使用すると、基になる Vector Store レコード コレクション検索の実装を呼び出す単一のGetTextSearchResults
関数を持つ新しいプラグインが作成されます。
SearchPlugin
がKernel
に追加され、プロンプトレンダリング中に呼び出せます。
プロンプト テンプレートには、現在のクエリに関連する結果を取得するSearchPlugin
を呼び出す{{SearchPlugin.Search $query}}
の呼び出しが含まれています。
結果は、モデルに送信される前に、レンダリングされたプロンプトに挿入されます。
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
));
関数呼び出しでのベクター ストアの使用
次のサンプルでは、VectorStoreTextSearch
のインスタンスからSearchPlugin
も作成されます。
このプラグインは、プロンプト実行設定の FunctionChoiceBehavior
を使用した自動関数呼び出しで使用するためにモデルにアドバタイズされます。
このサンプルを実行すると、モデルは検索機能を呼び出して、質問に応答するための追加情報を取得します。
クエリ全体ではなく、"セマンティック カーネル" を検索するだけです。
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));
検索機能のカスタマイズ
次のサンプルでは、 SearchPlugin
に追加される検索機能の説明をカスタマイズする方法を示します。
次の操作を実行できます。
- 検索関数の名前を変更して、関連付けられているレコード コレクション内の内容を反映させます。たとえば、レコード コレクションにホテル情報が含まれている場合に
SearchForHotels
関数に名前を付けたい場合などです。 - 関数の説明を変更します。 正確な関数の説明は、AI モデルが呼び出す最適な関数を選択するのに役立ちます。 これは、複数の検索機能を追加する場合に特に重要です。
- 検索機能にパラメーターを追加します。 レコード コレクションにホテル情報が含まれており、プロパティの 1 つが市区町村名である場合は、検索関数にプロパティを追加して都市を指定できます。 フィルターが自動的に追加され、検索結果が市区町村別にフィルター処理されます。
ヒント
次のサンプルでは、検索の既定の実装を使用します。 検索を微調整するための追加オプションを使用して、基になる Vector Store レコード コレクションを呼び出す独自の実装を提供することもできます。
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));
間もなく利用できます
詳細は近日公開予定です。
間もなく利用できます
詳細は近日公開予定です。