데이터 모델 정의

Microsoft.Extensions.VectorData 모델 우선 접근 방식을 사용하여 데이터베이스와 상호 작용합니다.

레코드를 upsert하거나 가져오는 모든 메서드는 강력한 형식의 모델 클래스를 사용합니다. 데이터 모델을 정의하는 방법에는 두 가지가 있습니다.

  • 모델 클래스의 속성을 각 속성의 용도를 나타내는 특성 으로 데코레이팅합니다.
  • 데이터 모델과 별도로 제공하는 레코드 정의를 사용하여 스토리지 스키마를 정의합니다. 레코드 정의는 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 속성 형식은 데이터베이스마다 다릅니다. 지원되는 형식에 대한 자세한 내용은 선택한 벡터 저장소 공급자의 설명서를 확인하세요.

주요 속성

각 데이터 모델에는 컬렉션의 각 레코드를 고유하게 식별하는 키 속성이 있어야 합니다.

VectorStoreKeyAttribute 특성을 사용하여 속성이 레코드의 기본 키임을 나타냅니다.

[VectorStoreKey]
public ulong HotelId { get; set; }

다음 표에서는 에 대한 매개 변수를 VectorStoreKeyAttribute보여줍니다.

매개 변수 필수 설명
IsAutoGenerated No 키 값이 데이터베이스에 의해 자동으로 생성되는지 여부를 나타냅니다. 기본값은 false입니다.
StorageName No 데이터베이스의 속성에 대한 대체 이름을 제공하는 데 사용할 수 있습니다. 이 매개 변수는 예를 들어 같은 대안 JsonPropertyNameAttribute 이 지원되는 모든 공급자에서 지원되지 않습니다.

데이터 속성

데이터 속성은 레코드를 검색할 때 검색되는 텍스트, 태그 또는 기타 메타데이터와 같은 범용 콘텐츠를 보유하며 필요에 따라 필터링을 위해 인덱싱할 수도 있습니다.

특성을 사용하여 속성에 VectorStoreDataAttribute 키 또는 벡터가 아닌 일반 데이터가 포함되어 있음을 나타냅니다.

[VectorStoreData(IsIndexed = true)]
public required string HotelName { get; set; }

다음 표에서는 에 대한 매개 변수를 VectorStoreDataAttribute보여줍니다.

매개 변수 필수 설명
IsIndexed No 데이터베이스에서 속성당 인덱싱을 옵트인해야 하는 경우 필터링을 위해 속성을 인덱싱해야 하는지 여부를 나타냅니다. 기본값은 false입니다.
IsFullTextIndexed No 전체 텍스트 검색을 지원하는 데이터베이스에 대한 전체 텍스트 검색을 위해 속성을 인덱싱해야 하는지 여부를 나타냅니다. 기본값은 false입니다.
StorageName No 데이터베이스의 속성에 대한 대체 이름을 제공하는 데 사용할 수 있습니다. 이 매개 변수는 예를 들어 같은 대안 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; }

팁 (조언)

기본 제공 포함 생성을 사용하는 방법에 대한 자세한 내용은 Vector 속성 및 포함 생성을 참조하세요.

다음 표에서는 에 대한 매개 변수를 VectorStoreVectorAttribute보여줍니다.

매개 변수 필수 설명
Dimensions 벡터에 있는 차원의 수입니다. 컬렉션에 대한 벡터 인덱스 만들기에 필요합니다.
IndexKind No 벡터를 인덱싱할 인덱스의 형식입니다. 기본값은 벡터 저장소 유형에 따라 다릅니다.
DistanceFunction No 이 벡터를 검색하는 동안 벡터 비교를 수행할 때 사용할 함수의 형식입니다. 기본값은 벡터 저장소 유형에 따라 다릅니다.
StorageName No 데이터베이스의 속성에 대한 대체 이름을 제공하는 데 사용할 수 있습니다. 이 매개 변수는 예를 들어 같은 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는 upsert 및 검색 작업 중에 포함 생성을 자동으로 처리합니다.

먼저 벡터 속성을 다음과 같이 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 Embeddings를 참조하세요.

.NET 사전에 동적 매핑

강력한 형식의 .NET 형식을 데이터베이스에 매핑하는 것이 바람직하지 않거나 가능하지 않은 경우가 있습니다. 예를 들어 컴파일 시간에 데이터베이스 스키마가 어떻게 표시되는지 모르고 스키마는 구성을 통해서만 제공됩니다. 이 경우 스키마를 반영하는 .NET 형식을 만드는 것은 불가능합니다. 대신 레코드 형식에 대한 값을 사용하여 Dictionary<string, object?> 매핑할 수 있습니다. 속성은 Dictionary 속성 이름으로 키와 속성 값으로 추가됩니다.

메모

대부분의 앱은 강력한 형식의 .NET 형식을 사용하여 데이터를 모델링합니다. 동적 매핑 Dictionary<string, object?> 은 고급 임의 데이터 매핑 시나리오를 위한 것입니다.

사용할 때 스키마 정보 제공 Dictionary

사용하는 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"]);