Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Microsoft.Extensions.VectorData usa uma abordagem de primeiro modelo para interagir com bancos de dados.
Todos os métodos para upsert ou obter registros usam classes de modelo fortemente tipada. Há duas maneiras de definir o modelo de dados:
- Decorando propriedades nas classes de modelo com atributos que indicam a finalidade de cada propriedade.
- Definindo seu esquema de armazenamento usando uma definição de registro que você fornece separadamente do modelo de dados. A definição de registro é uma VectorStoreCollectionDefinition que contém propriedades.
Aqui está um exemplo de uma classe, ou modelo de dados, cujas propriedades são decoradas com VectorStore*Attribute atributos.
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; }
}
Propriedades do modelo de dados
Observação
Os tipos de propriedade .NET compatíveis com chaves, dados e vetores variam entre bancos de dados. Para obter informações sobre tipos com suporte, verifique a documentação do provedor de repositório de vetores escolhido.
Propriedade-chave
Cada modelo de dados deve ter uma propriedade de chave que identifique exclusivamente cada registro na coleção.
Use o VectorStoreKeyAttribute atributo para indicar que sua propriedade é a chave primária do registro.
[VectorStoreKey]
public ulong HotelId { get; set; }
A tabela a seguir mostra os parâmetros para VectorStoreKeyAttribute.
| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| IsAutoGenerated | No | Indica se o valor da chave é gerado automaticamente pelo banco de dados. O padrão é false. |
| StorageName | No | Pode ser usado para fornecer um nome alternativo para a propriedade no banco de dados. Esse parâmetro não é compatível com todos os provedores, por exemplo, em que há suporte para alternativas como JsonPropertyNameAttribute . |
Propriedade de dados
As propriedades de dados contêm conteúdo de uso geral, como texto, marcas ou outros metadados recuperados ao pesquisar registros e, opcionalmente, também podem ser indexados para filtragem.
Use o VectorStoreDataAttribute atributo para indicar que sua propriedade contém dados gerais que não são uma chave ou um vetor.
[VectorStoreData(IsIndexed = true)]
public required string HotelName { get; set; }
A tabela a seguir mostra os parâmetros para VectorStoreDataAttribute.
| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| IsIndexed | No | Indica se a propriedade deve ser indexada para filtragem em casos em que um banco de dados requer a aceitação da indexação por propriedade. O padrão é false. |
| IsFullTextIndexed | No | Indica se a propriedade deve ser indexada para pesquisa de texto completo para bancos de dados que dão suporte à pesquisa de texto completo. O padrão é false. |
| StorageName | No | Pode ser usado para fornecer um nome alternativo para a propriedade no banco de dados. Esse parâmetro não tem suporte para todos os provedores, por exemplo, em que há suporte para alternativas como JsonPropertyNameAttribute . |
Propriedade Vector
As propriedades de vetor contêm os vetores de inserção usados para pesquisa de similaridade; em cenários avançados, um modelo de dados pode ter várias propriedades de vetor para dar suporte à pesquisa em diferentes aspectos do registro.
Use o VectorStoreVectorAttribute atributo para indicar que sua propriedade contém um vetor.
[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
Também é possível usar VectorStoreVectorAttribute em propriedades que não têm um tipo de vetor, por exemplo, uma propriedade do tipo string. Quando uma propriedade é decorada dessa forma, você precisa fornecer uma IEmbeddingGenerator instância para o repositório de vetores. Ao aumentar o registro, o texto que está na string propriedade é automaticamente convertido e armazenado como um vetor no banco de dados. (Não é possível recuperar um vetor usando esse mecanismo.)
[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public string DescriptionEmbedding { get; set; }
Dica
Para obter mais informações sobre como usar a geração de inserção interna, consulte as propriedades do Vector e a geração de inserção.
A tabela a seguir mostra os parâmetros para VectorStoreVectorAttribute.
| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| Dimensions | Sim | O número de dimensões que o vetor tem. Isso é necessário ao criar um índice de vetor para uma coleção. |
| IndexKind | No | O tipo de índice com o qual indexar o vetor. O padrão varia de acordo com o tipo de repositório de vetores. |
| DistanceFunction | No | O tipo de função a ser usada ao fazer comparação de vetor durante a pesquisa de vetor sobre esse vetor. O padrão varia de acordo com o tipo de repositório de vetores. |
| StorageName | No | Pode ser usado para fornecer um nome alternativo para a propriedade no banco de dados. Esse parâmetro não tem suporte para todos os provedores, por exemplo, em que há suporte para alternativas como JsonPropertyNameAttribute essa. |
Tipos de índice comuns e tipos de função de distância são fornecidos como valores estáticos nas classes e IndexKind nas DistanceFunction classes. Implementações individuais do repositório de vetores também podem usar seus próprios tipos de índice e funções de distância, em que o banco de dados dá suporte a tipos incomuns.
Propriedades de vetor e geração de inserção
Os bancos de dados vetoriais são todos sobre armazenar inserções - ou representações numéricas de seus dados - que são geradas por um modelo de inserção. Ao armazenar ou pesquisar dados, a geração de inserção deve ser executada primeiro para converter os dados pesquisáveis em tais inserções. O MEVD fornece duas abordagens para a geração de inserção: manual e automática.
Geração de inserção manual de baixo nível
Você pode definir sua propriedade de vetor como float[] ou ReadOnlyMemory<float>, representando a inserção diretamente, e gerar inserções por conta própria antes de cada operação:
[VectorStoreVector(Dimensions: 1536)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
Ao pesquisar, você geraria a inserção para o texto da consulta e a passaria para SearchAsync:
ReadOnlyMemory<float> searchEmbedding =
(await embeddingGenerator.GenerateAsync("Find a happy hotel")).Vector;
var searchResult = collection.SearchAsync(searchEmbedding, top: 3);
Embora isso funcione, isso exige que você gerencie a geração de inserção em cada site de chamada.
Geração automática de inserção (recomendado)
A abordagem recomendada é configurar um IEmbeddingGenerator<TInput,TEmbedding> repositório de vetores. Isso permite que você defina sua propriedade de vetor usando o tipo de origem (por exemplo, string) em vez de float[] ou ReadOnlyMemory<float>. O MEVD manipula automaticamente a geração de inserção durante operações upsert e search.
Primeiro, defina a propriedade de vetor como string:
[VectorStoreVector(Dimensions: 1536)]
public string DescriptionEmbedding { get; set; }
Em seguida, configure um gerador de inserção ao criar seu repositório de vetores:
VectorStore vectorStore = new QdrantVectorStore(
new QdrantClient("localhost"),
ownsClient: true,
new QdrantVectorStoreOptions
{
EmbeddingGenerator = embeddingGenerator
});
Agora você pode passar o texto diretamente – o MEVD gera inserções sob o capô:
// Search with a plain text query - embedding is generated automatically.
var searchResult = collection.SearchAsync("Find a happy hotel", top: 3);
Importante
As propriedades de vetor configuradas dessa forma não dão suporte à recuperação do vetor gerado ou ao texto original do banco de dados. Se você precisar armazenar o texto original, adicione uma propriedade de dados separada.
Os geradores de inserção também podem ser configurados no nível de propriedade de coleção, de registro ou de vetor individual. Diferentes modelos de inserção dão suporte a diferentes tamanhos de vetor; Verifique se o Dimensions valor corresponde ao modelo que você configurou. Para obter mais informações sobre geradores de inserção e abstrações Microsoft.Extensions.AI, consulte Embeddings no .NET.
Mapeamento dinâmico para um dicionário de .NET
Há casos em que não é desejável ou possível mapear um tipo de .NET fortemente tipado para o banco de dados. Por exemplo, imagine que você não sabe no momento da compilação a aparência do esquema de banco de dados e o esquema só é fornecido por meio da configuração. Criar um tipo de .NET que reflita o esquema seria impossível nesse caso. Em vez disso, você pode mapear dinamicamente usando um Dictionary<string, object?> tipo de registro. As propriedades são adicionadas à Dictionary chave com como o nome da propriedade e o valor como o valor da propriedade.
Observação
A maioria dos aplicativos simplesmente usará tipos de .NET fortemente tipados para modelar seus dados. O mapeamento dinâmico por meio Dictionary<string, object?> é para cenários avançados e arbitrários de mapeamento de dados.
Fornecer informações de esquema ao usar Dictionary
Quando você usa um Dictionaryprovedor, os provedores ainda precisam saber como é o esquema de banco de dados. Sem as informações de esquema, o provedor não seria capaz de criar uma coleção ou saber como mapear de e para a representação de armazenamento que cada banco de dados usa.
Você pode usar uma definição de registro para fornecer as informações de esquema. Ao contrário de um modelo de dados, uma definição de registro pode ser criada a partir da configuração em runtime quando as informações do esquema não são conhecidas no momento da compilação.
Exemplo
Para usar Dictionary com um provedor, especifique-o como seu modelo de dados ao criar a coleção. Forneça também uma definição de registro.
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"]);