警告
语义内核向量存储功能目前处于预览状态,并且在发布前的某些有限情况下,可能仍需要实施会引发重大更改的改进。
警告
语义内核向量存储功能目前处于预览状态,并且在发布前的某些有限情况下,可能仍需要实施会引发重大更改的改进。
语义内核向量存储连接器支持多种生成嵌入方法。
嵌入内容可由开发人员生成,并在使用 VectorStoreCollection
记录时作为记录的一部分传递,也可以在内部 VectorStoreCollection
生成。
让向量存储生成嵌入内容
可以在矢量存储上配置嵌入生成器,从而允许在更新插入和搜索作期间自动生成嵌入,而无需手动预处理。
若要在进行 upsert 操作时自动生成向量,数据模型中的向量属性被定义为源类型,例如字符串,但仍使用 VectorStoreVectorPropertyAttribute
进行修饰。
[VectorStoreVector(1536)]
public string Embedding { get; set; }
在插入或更新之前,该 Embedding
属性应包含一个字符串,从中将生成一个矢量。 存储在数据库中的矢量的类型(例如 float32、float16 等)将从配置的嵌入生成器派生。
重要
这些向量属性不支持检索生成的向量或从中生成矢量的原始文本。 它们也不会存储原始文本。 如果需要存储原始文本,应添加单独的 Data 属性来存储它。
支持实现抽象的 Microsoft.Extensions.AI
嵌入生成器,并且可以在各种级别进行配置:
在向量存储上:可以为整个向量存储设置默认嵌入生成器。 除非重写,否则此生成器将用于所有集合和属性。
using Microsoft.Extensions.AI; using Microsoft.SemanticKernel.Connectors.Qdrant; using OpenAI; using Qdrant.Client; var embeddingGenerator = new OpenAIClient("your key") .GetEmbeddingClient("your chosen model") .AsIEmbeddingGenerator(); var vectorStore = new QdrantVectorStore( new QdrantClient("localhost"), ownsClient: true, new QdrantVectorStoreOptions { EmbeddingGenerator = embeddingGenerator });
在集合中:可以为特定集合配置嵌入生成器,替换存储级生成器。
using Microsoft.Extensions.AI; using Microsoft.SemanticKernel.Connectors.Qdrant; using OpenAI; using Qdrant.Client; var embeddingGenerator = new OpenAIClient("your key") .GetEmbeddingClient("your chosen model") .AsIEmbeddingGenerator(); var collectionOptions = new QdrantCollectionOptions { EmbeddingGenerator = embeddingGenerator }; var collection = new QdrantCollection<ulong, MyRecord>( new QdrantClient("localhost"), "myCollection", ownsClient: true, collectionOptions);
在记录定义:使用
VectorStoreCollectionDefinition
编程方式定义属性时,可以为所有属性指定嵌入生成器。using Microsoft.Extensions.AI; using Microsoft.Extensions.VectorData; using Microsoft.SemanticKernel.Connectors.Qdrant; using OpenAI; using Qdrant.Client; var embeddingGenerator = new OpenAIClient("your key") .GetEmbeddingClient("your chosen model") .AsIEmbeddingGenerator(); var definition = new VectorStoreCollectionDefinition { EmbeddingGenerator = embeddingGenerator, Properties = new List<VectorStoreProperty> { new VectorStoreKeyProperty("Key", typeof(ulong)), new VectorStoreVectorProperty("DescriptionEmbedding", typeof(string), dimensions: 1536) } }; var collectionOptions = new QdrantCollectionOptions { Definition = definition }; var collection = new QdrantCollection<ulong, MyRecord>( new QdrantClient("localhost"), "myCollection", ownsClient: true, collectionOptions);
在向量属性定义:以编程方式定义属性时,可以直接在属性上设置嵌入生成器。
using Microsoft.Extensions.AI; using Microsoft.Extensions.VectorData; using OpenAI; var embeddingGenerator = new OpenAIClient("your key") .GetEmbeddingClient("your chosen model") .AsIEmbeddingGenerator(); var vectorProperty = new VectorStoreVectorProperty("DescriptionEmbedding", typeof(string), dimensions: 1536) { EmbeddingGenerator = embeddingGenerator };
示例用法
以下示例演示如何在创建或更新和搜索操作期间使用嵌入生成器自动生成矢量。 此方法无需手动预计算嵌入,从而简化了工作流。
// The data model
internal class FinanceInfo
{
[VectorStoreKey]
public string Key { get; set; } = string.Empty;
[VectorStoreData]
public string Text { get; set; } = string.Empty;
// Note that the vector property is typed as a string, and
// its value is derived from the Text property. The string
// value will however be converted to a vector on upsert and
// stored in the database as a vector.
[VectorStoreVector(1536)]
public string Embedding => this.Text;
}
// Create an OpenAI embedding generator.
var embeddingGenerator = new OpenAIClient("your key")
.GetEmbeddingClient("your chosen model")
.AsIEmbeddingGenerator();
// Use the embedding generator with the vector store.
var vectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
var collection = vectorStore.GetCollection<string, FinanceInfo>("finances");
await collection.EnsureCollectionExistsAsync();
// Create some test data.
string[] budgetInfo =
{
"The budget for 2020 is EUR 100 000",
"The budget for 2021 is EUR 120 000",
"The budget for 2022 is EUR 150 000",
"The budget for 2023 is EUR 200 000",
"The budget for 2024 is EUR 364 000"
};
// Embeddings are generated automatically on upsert.
var records = budgetInfo.Select((input, index) => new FinanceInfo { Key = index.ToString(), Text = input });
await collection.UpsertAsync(records);
// Embeddings for the search is automatically generated on search.
var searchResult = collection.SearchAsync(
"What is my budget for 2024?",
top: 1);
// Output the matching result.
await foreach (var result in searchResult)
{
Console.WriteLine($"Key: {result.Record.Key}, Text: {result.Record.Text}");
}
自行生成嵌入内容
构造嵌入生成器
有关如何构造语义内核实例的示例,请参阅ITextEmbeddingGenerationService
。
有关如何构造嵌入生成服务的信息,请参阅 Microsoft.Extensions.AI.Abstractions。Microsoft.Extensions.AI
使用语义内核在 upsert 上生成嵌入内容 ITextEmbeddingGenerationService
public async Task GenerateEmbeddingsAndUpsertAsync(
ITextEmbeddingGenerationService textEmbeddingGenerationService,
VectorStoreCollection<ulong, Hotel> collection)
{
// Upsert a record.
string descriptionText = "A place where everyone can be happy.";
ulong hotelId = 1;
// Generate the embedding.
ReadOnlyMemory<float> embedding =
await textEmbeddingGenerationService.GenerateEmbeddingAsync(descriptionText);
// Create a record and upsert with the already generated embedding.
await collection.UpsertAsync(new Hotel
{
HotelId = hotelId,
HotelName = "Hotel Happy",
Description = descriptionText,
DescriptionEmbedding = embedding,
Tags = new[] { "luxury", "pool" }
});
}
使用语义内核在搜索上生成嵌入内容 ITextEmbeddingGenerationService
public async Task GenerateEmbeddingsAndSearchAsync(
ITextEmbeddingGenerationService textEmbeddingGenerationService,
VectorStoreCollection<ulong, Hotel> collection)
{
// Upsert a record.
string descriptionText = "Find me a hotel with happiness in mind.";
// Generate the embedding.
ReadOnlyMemory<float> searchEmbedding =
await textEmbeddingGenerationService.GenerateEmbeddingAsync(descriptionText);
// Search using the already generated embedding.
IAsyncEnumerable<VectorSearchResult<Hotel>> searchResult = collection.SearchAsync(searchEmbedding, top: 1);
List<VectorSearchResult<Hotel>> resultItems = await searchResult.ToListAsync();
// Print the first search result.
Console.WriteLine("Score for first result: " + resultItems.FirstOrDefault()?.Score);
Console.WriteLine("Hotel description for first result: " + resultItems.FirstOrDefault()?.Record.Description);
}
提示
有关生成嵌入内容的详细信息,请参阅 在语义内核中嵌入代系。
嵌入维度
矢量数据库通常需要指定每个向量在创建集合时具有的维度数。
不同的嵌入模型通常支持生成具有各种维度大小的矢量。 例如,OpenAI text-embedding-ada-002
生成具有 1536 个维度的向量。 某些模型还允许开发人员在输出向量中选择所需的维度数。 例如,默认情况下,Google text-embedding-004
会生成具有 768 个维度的矢量,但允许开发人员选择介于 1 到 768 之间的任意数量的维度。
请务必确保嵌入模型生成的向量具有与数据库中匹配向量相同的维度数。
如果使用语义内核向量存储抽象创建集合,则需要通过批注或通过记录定义指定每个向量属性所需的维度数。 下面是将维度数设置为 1536 的两个示例。
[VectorStoreVector(Dimensions: 1536)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
new VectorStoreVectorProperty("DescriptionEmbedding", typeof(float), dimensions: 1536);
提示
有关如何批注数据模型的详细信息,请参阅 定义数据模型。
提示
有关创建记录定义的详细信息,请参阅 使用记录定义定义架构。
即将推出
更多信息即将推出。
即将推出
更多信息即将推出。