Microsoft.Extensions.VectorData使用模型优先方法与数据库交互。
用于更新插入或获取记录的所有方法都使用强类型模型类。 可通过两种方法定义数据模型:
- 通过使用指示每个属性用途 的属性 修饰模型类上的属性。
- 通过使用与数据模型分开提供的 记录定义 来定义存储架构。 记录定义是一个 VectorStoreCollectionDefinition 包含 属性的记录定义。
下面是一个类或数据模型的示例,该类或数据模型使用属性修饰 VectorStore*Attribute 其属性。
public class Hotel
{
[VectorStoreKey]
public ulong HotelId { get; set; }
[VectorStoreData(IsIndexed = true)]
public required string HotelName { get; set; }
[VectorStoreData(IsFullTextIndexed = true)]
public required string Description { get; set; }
[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
[VectorStoreData(IsIndexed = true)]
public required string[] Tags { get; set; }
}
数据模型属性
注释
键、数据和向量支持的.NET属性类型因数据库而异。 有关受支持的类型的信息,请查看所选矢量存储提供程序的文档。
Key 属性
每个数据模型必须具有一个键属性,该属性唯一标识集合中的每个记录。
使用 VectorStoreKeyAttribute 特性指示属性是记录的主键。
[VectorStoreKey]
public ulong HotelId { get; set; }
下表显示了用于 VectorStoreKeyAttribute. 的参数。
| 参数 | 必需 | 说明 |
|---|---|---|
| IsAutoGenerated | 否 | 指示键值是否由数据库自动生成。 默认值为 false。 |
| StorageName | 否 | 可用于提供数据库中属性的替代名称。 所有提供程序都不支持此参数,例如,支持此类 JsonPropertyNameAttribute 替代项。 |
数据属性
数据属性保存常规用途内容,例如在搜索记录时检索的文本、标记或其他元数据,还可以选择性地为筛选编制索引。
使用 VectorStoreDataAttribute 特性指示属性包含不是键或向量的常规数据。
[VectorStoreData(IsIndexed = true)]
public required string HotelName { get; set; }
下表显示了用于 VectorStoreDataAttribute. 的参数。
| 参数 | 必需 | 说明 |
|---|---|---|
| IsIndexed | 否 | 指示在数据库需要选择按属性编制索引的情况下,是否应为属性编制索引以进行筛选。 默认值为 false。 |
| IsFullTextIndexed | 否 | 指示是否应为支持全文搜索的数据库编制全文搜索的属性编制索引。 默认值为 false。 |
| StorageName | 否 | 可用于提供数据库中属性的替代名称。 所有提供程序都不支持此参数,例如,支持类似替代项 JsonPropertyNameAttribute 。 |
Vector 属性
矢量属性包含用于相似性搜索的嵌入向量;在高级方案中,数据模型可以具有多个矢量属性,以支持搜索记录的不同方面。
使用 VectorStoreVectorAttribute 特性指示属性包含向量。
[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
还可以对没有向量类型的属性使用 VectorStoreVectorAttribute ,例如类型为属性 string。 以这种方式修饰属性时,需要向向量存储提供 IEmbeddingGenerator 实例。 在插入记录时,属性中的 string 文本会自动转换并存储为数据库中的向量。 (无法使用此机制检索向量。
[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public string DescriptionEmbedding { get; set; }
小窍门
有关如何使用内置嵌入生成的详细信息,请参阅 矢量属性和嵌入生成。
下表显示了用于 VectorStoreVectorAttribute. 的参数。
| 参数 | 必需 | 说明 |
|---|---|---|
| Dimensions | 是的 | 矢量具有的维度数。 为集合创建向量索引时,这是必需的。 |
| IndexKind | 否 | 要为向量编制索引的索引的类型。 默认值因矢量存储类型而异。 |
| DistanceFunction | 否 | 在此向量搜索期间执行向量比较时要使用的函数类型。 默认值因矢量存储类型而异。 |
| StorageName | 否 | 可用于提供数据库中属性的替代名称。 所有提供程序都不支持此参数,例如,支持类似替代项 JsonPropertyNameAttribute 。 |
常见的索引类型和距离函数类型作为静态值 IndexKind 提供,并且 DistanceFunction 类。 单个矢量存储实现也可能使用自己的索引类型和距离函数,其中数据库支持异常类型。
矢量属性和嵌入生成
矢量数据库都与存储 嵌入 数据(或数据的数字表示形式)有关,这些表示形式都是由嵌入模型生成的。 存储或搜索数据时,必须先执行嵌入生成,才能将可搜索数据转换为此类嵌入。 MEVD 提供了两种嵌入生成方法:手动和自动。
手动、低级别的嵌入生成
可以将向量属性 float[] 定义为或 ReadOnlyMemory<float>直接表示嵌入,并在每次操作之前自行生成嵌入:
[VectorStoreVector(Dimensions: 1536)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
搜索时,会生成查询文本的嵌入,并将其传递给 SearchAsync:
ReadOnlyMemory<float> searchEmbedding =
(await embeddingGenerator.GenerateAsync("Find a happy hotel")).Vector;
var searchResult = collection.SearchAsync(searchEmbedding, top: 3);
虽然这有效,但它要求你管理每个呼叫站点的嵌入代系。
自动嵌入生成(建议)
建议的方法是在向量存储上配置一个 IEmbeddingGenerator<TInput,TEmbedding> 。 这允许你使用源类型(例如) string而不是 float[] 或 ReadOnlyMemory<float>。 然后,MEVD 会在更新插入和搜索操作期间自动处理嵌入生成。
首先,将向量属性定义为 string:
[VectorStoreVector(Dimensions: 1536)]
public string DescriptionEmbedding { get; set; }
然后,在创建矢量存储时配置嵌入生成器:
VectorStore vectorStore = new QdrantVectorStore(
new QdrantClient("localhost"),
ownsClient: true,
new QdrantVectorStoreOptions
{
EmbeddingGenerator = embeddingGenerator
});
现在可以直接传递文本 - MEVD 生成引擎盖下的嵌入内容:
// Search with a plain text query - embedding is generated automatically.
var searchResult = collection.SearchAsync("Find a happy hotel", top: 3);
重要
以这种方式配置的向量属性不支持从数据库检索生成的向量或原始文本。 如果需要存储原始文本,请添加单独的数据属性。
还可以在集合、记录定义或单个向量属性级别配置嵌入生成器。 不同的嵌入模型支持不同的矢量大小;确保 Dimensions 该值与已配置的模型匹配。 有关嵌入生成器和
动态映射到.NET字典
在某些情况下,不希望或可能将强类型.NET类型映射到数据库。 例如,假设在编译时不知道数据库架构的外观,并且仅通过配置提供架构。 在这种情况下,创建反映架构的.NET类型是不可能的。 相反,可以使用记录类型动态Dictionary<string, object?>映射。 将属性作为属性名称和值作为属性值添加到 Dictionary 键中。
注释
大多数应用只需使用强类型化.NET类型来为其数据建模。 动态映射适用于 Dictionary<string, object?> 高级任意数据映射方案。
使用时提供架构信息 Dictionary
使用 a Dictionary时,提供程序仍需要知道数据库架构的外观。 如果没有架构信息,提供程序将无法创建集合或知道如何映射到每个数据库使用的存储表示形式和从存储表示形式。
可以使用记录定义来提供架构信息。 与数据模型不同,在编译时不知道架构信息时,可以在 运行时 从配置创建记录定义。
示例
若要与提供程序一 Dictionary 起使用,请在创建集合时将其指定为数据模型。 还提供记录定义。
VectorStoreCollectionDefinition definition = new()
{
Properties =
[
new VectorStoreKeyProperty("Key", typeof(string)),
new VectorStoreDataProperty("Term", typeof(string)),
new VectorStoreDataProperty("Definition", typeof(string)),
new VectorStoreVectorProperty("DefinitionEmbedding", typeof(ReadOnlyMemory<float>), dimensions: 1536)
]
};
// Use GetDynamicCollection instead of the regular GetCollection method
// to get an instance of a collection using Dictionary<string, object?>.
VectorStoreCollection<object, Dictionary<string, object?>> dynamicDataModelCollection =
vectorStore.GetDynamicCollection("glossary", definition);
// Since schema information is available from the record definition,
// it's possible to create a collection with the right vectors,
// dimensions, indexes, and distance functions.
await dynamicDataModelCollection.EnsureCollectionExistsAsync();
// When retrieving a record from the collection,
// access key, data, and vector values via the dictionary entries.
Dictionary<string, object?>? record = await dynamicDataModelCollection.GetAsync("SK");
Console.WriteLine(record["Definition"]);