Az adatmodell meghatározása

Microsoft.Extensions.VectorData modellelső megközelítést használ az adatbázisokkal való interakcióhoz.

A rekordok frissítésére vagy lekérésére használt összes metódus szigorúan beírt modellosztályokat használ. Az adatmodell kétféleképpen definiálható:

  • A modellosztályok tulajdonságainak dekorálásával olyan attribútumokkal , amelyek az egyes tulajdonságok célját jelölik.
  • A tárolási sémát az adatmodelltől elkülönítve megadott rekorddefinícióval definiálhatja. A rekorddefiníció VectorStoreCollectionDefinition tartalmaz.

Íme egy példa egy osztályra vagy adatmodellre, amelynek tulajdonságait attribútumok díszítik 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; }
}

Adatmodell tulajdonságai

Megjegyzés:

A kulcsokhoz, adatokhoz és vektorokhoz támogatott .NET tulajdonságtípusok adatbázisonként eltérőek. A támogatott típusokkal kapcsolatos információkért tekintse meg a kiválasztott vektortároló-szolgáltató dokumentációját.

Kulcstulajdonság

Minden adatmodellnek rendelkeznie kell egy olyan kulcstulajdonságsal, amely egyedileg azonosítja a gyűjtemény összes rekordját.

VectorStoreKeyAttribute Az attribútum használatával jelezheti, hogy a tulajdonság a rekord elsődleges kulcsa.

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

Az alábbi táblázat a következő paramétereket VectorStoreKeyAttributemutatja be: .

Paraméter Szükséges Leírás
IsAutoGenerated No Azt jelzi, hogy a kulcs értékét az adatbázis automatikusan létrehozza-e. Az alapértelmezett érték false.
StorageName No Az adatbázis tulajdonságának alternatív nevének megadására használható. Ezt a paramétert nem minden szolgáltató támogatja, például ahol az olyan alternatívák támogatottak, mint JsonPropertyNameAttribute például.

Adattulajdonság

Az adattulajdonságok olyan általános célú tartalmakat tartalmaznak, mint például a rekordok keresésekor lekért szöveg, címkék vagy egyéb metaadatok, és a szűréshez is indexelhetők.

VectorStoreDataAttribute Az attribútum használatával jelezheti, hogy a tulajdonság olyan általános adatokat tartalmaz, amelyek nem kulcsok vagy vektorok.

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

Az alábbi táblázat a következő paramétereket VectorStoreDataAttributemutatja be: .

Paraméter Szükséges Leírás
IsIndexed No Azt jelzi, hogy a tulajdonságot indexelni kell-e szűrés céljából olyan esetekben, amikor egy adatbázis megköveteli a tulajdonságonkénti indexelést. Az alapértelmezett érték a false.
IsFullTextIndexed No Azt jelzi, hogy a tulajdonságot indexelni kell-e a teljes szöveges keresést támogató adatbázisok teljes szöveges kereséséhez. Az alapértelmezett érték a false.
StorageName No Az adatbázis tulajdonságának alternatív nevének megadására használható. Ezt a paramétert nem támogatja minden szolgáltató, például ahol az alternatív JsonPropertyNameAttribute megoldások támogatottak.

Vektor tulajdonság

A vektortulajdonságok tartalmazzák a hasonlóság kereséséhez használt beágyazási vektorokat; speciális helyzetekben az adatmodellek több vektortulajdonságtal is rendelkezhetnek, amelyek támogatják a rekord különböző aspektusai közötti keresést.

VectorStoreVectorAttribute Az attribútum használatával jelezheti, hogy a tulajdonság vektort tartalmaz.

[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }

Olyan tulajdonságokon is használható VectorStoreVectorAttribute , amelyek nem rendelkeznek vektortípussal, például egy típustulajdonság string. Ha egy tulajdonság ilyen módon van dekorálva, meg kell adnia egy példányt IEmbeddingGenerator a vektortárolónak. A rekord hozzáadásakor a tulajdonságban lévő string szöveg automatikusan konvertálódik és vektorként lesz tárolva az adatbázisban. (Ezzel a mechanizmussal nem kérhető le vektor.)

[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public string DescriptionEmbedding { get; set; }

Jótanács

A beépített beágyazási generáció használatáról további információt a Vektor tulajdonságai és a beágyazási generáció című témakörben talál.

Az alábbi táblázat a következő paramétereket VectorStoreVectorAttributemutatja be: .

Paraméter Szükséges Leírás
Dimensions Igen A vektor dimenzióinak száma. Erre akkor van szükség, ha vektorindexet hoz létre egy gyűjteményhez.
IndexKind No Az index típusa, amellyel indexelni szeretné a vektort. Az alapértelmezett érték a vektortároló típusa szerint változik.
DistanceFunction No A vektorok összehasonlításához használandó függvény típusa a vektoron végzett vektorkeresés során. Az alapértelmezett érték a vektortároló típusa szerint változik.
StorageName No Az adatbázis tulajdonságának alternatív nevének megadására használható. Ezt a paramétert nem minden szolgáltató támogatja, például olyan alternatív megoldásokat, mint JsonPropertyNameAttribute amilyenek támogatottak.

A gyakori indextípusok és távolságfüggvény-típusok statikus értékekként vannak megadva az osztályokon és IndexKind az DistanceFunction osztályokon. Az egyes vektortároló-implementációk saját indextípusokat és távolságfüggvényeket is használhatnak, ahol az adatbázis támogatja a szokatlan típusokat.

Vektortulajdonságok és beágyazási generáció

A vektoradatbázisok a beágyazási modell által létrehozott beágyazások – vagy az adatok numerikus reprezentációi – tárolásáról szólnak. Adatok tárolásakor vagy keresésekor először beágyazási generálást kell végrehajtani a kereshető adatok ilyen beágyazásokká alakításához. A MEVD két módszert kínál a beágyazás generálására: manuális és automatikus.

Manuális, alacsony szintű beágyazási generáció

A vektortulajdonságokat float[] definiálhatja közvetlenül a beágyazást jelképező vagy ReadOnlyMemory<float>azokat jelképező módon, és minden művelet előtt létrehozhat beágyazásokat:

[VectorStoreVector(Dimensions: 1536)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }

Kereséskor létrehozná a lekérdezés szövegének beágyazását, és átadná a következőnek SearchAsync:

ReadOnlyMemory<float> searchEmbedding =
    (await embeddingGenerator.GenerateAsync("Find a happy hotel")).Vector;

var searchResult = collection.SearchAsync(searchEmbedding, top: 3);

Bár ez működik, minden hívási helyen kezelnie kell a beágyazási generációt.

A javasolt módszer egy vektortároló konfigurálása IEmbeddingGenerator<TInput,TEmbedding> . Ez lehetővé teszi a vektortulajdonság definiálását a forrástípus (például string) helyett vagy ReadOnlyMemory<float>helyettfloat[]. A MEVD ezután automatikusan kezeli a beágyazási generálást mind az upsert, mind a keresési műveletek során.

Először definiálja a vektortulajdonságot a következőként string:

[VectorStoreVector(Dimensions: 1536)]
public string DescriptionEmbedding { get; set; }

Ezután konfiguráljon egy beágyazási generátort a vektortároló létrehozásakor:

VectorStore vectorStore = new QdrantVectorStore(
    new QdrantClient("localhost"),
    ownsClient: true,
    new QdrantVectorStoreOptions
    {
        EmbeddingGenerator = embeddingGenerator
    });

Mostantól közvetlenül is átadhat szöveget – a MEVD beágyazásokat hoz létre a motorháztető alatt:

// Search with a plain text query - embedding is generated automatically.
var searchResult = collection.SearchAsync("Find a happy hotel", top: 3);

Fontos

Az így konfigurált vektortulajdonságok nem támogatják a létrehozott vektor vagy az eredeti szöveg beolvasását az adatbázisból. Ha az eredeti szöveget kell tárolnia, adjon hozzá egy külön adattulajdonságot.

A beágyazási generátorok a gyűjtemény, a rekorddefiníció vagy az egyes vektortulajdonságok szintjén is konfigurálhatók. A különböző beágyazási modellek különböző vektorméreteket támogatnak; győződjön meg arról, hogy az Dimensions érték megegyezik a konfigurált modellel. A generátorok beágyazásával és a Microsoft.Extensions.AI absztrakciókkal kapcsolatos további információkért lásd: Embeddings in .NET.

Dinamikus leképezés egy .NET szótárra

Vannak olyan esetek, amikor nem kívánatos vagy lehetséges egy erősen beírt .NET típus hozzárendelése az adatbázishoz. Tegyük fel például, hogy fordításkor nem tudja, hogyan néz ki az adatbázisséma, és a séma csak konfiguráción keresztül érhető el. Ebben az esetben lehetetlen létrehozni a sémát tükröző .NET típust. Ehelyett dinamikusan képezheti le a rekordtípust Dictionary<string, object?> . A tulajdonságokat a rendszer hozzáadja a Dictionary kulcshoz a tulajdonság neveként, az értéket pedig tulajdonságértékként.

Megjegyzés:

A legtöbb alkalmazás egyszerűen erősen gépelt .NET típusokat használ az adataik modellezéséhez. A dinamikus leképezés Dictionary<string, object?> speciális, tetszőleges adatleképezési forgatókönyvekhez készült.

Sémainformációk megadása a használat során Dictionary

Ha használ egy adatbázist Dictionary, a szolgáltatóknak továbbra is tudniuk kell, hogyan néz ki az adatbázisséma. A sémainformációk nélkül a szolgáltató nem hozhat létre gyűjteményt, és nem tudja, hogyan képezheti le és használhatja az egyes adatbázisok által használt tárterület-reprezentációt.

A sémainformációkat rekorddefinícióval is megadhatja. Az adatmodellekkel ellentétben a konfigurációból futásidőben is létrehozhat rekorddefiníciót, ha a sémainformációk fordításkor nem ismertek.

Example

Ha szolgáltatóval szeretné használni Dictionary , adja meg adatmodellként a gyűjtemény létrehozásakor. Adjon meg rekorddefiníciót is.

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"]);