Partilhar via


Definindo seu esquema de armazenamento usando uma definição de registro (Visualização)

Aviso

A funcionalidade Semantic Kernel Vetor Store está em pré-visualização, e melhorias que exigem alterações de quebra ainda podem ocorrer em circunstâncias limitadas antes do lançamento.

Aviso

A funcionalidade Semantic Kernel Vetor Store está em pré-visualização, e melhorias que exigem alterações de quebra ainda podem ocorrer em circunstâncias limitadas antes do lançamento.

Descrição geral

Os conectores do Semantic Kernel Vetor Store usam uma abordagem de modelo inicial para interagir com bancos de dados e permitem anotar modelos de dados com informações necessárias para criar índices ou mapear dados para o esquema de banco de dados.

Outra forma de fornecer essas informações é por meio de definições de registro, que podem ser definidas e fornecidas separadamente ao modelo de dados. Isso pode ser útil em vários cenários:

  • Pode haver um caso em que um desenvolvedor queira usar o mesmo modelo de dados com mais de uma configuração.
  • Pode haver um caso em que um desenvolvedor queira usar um tipo interno, como um dict, ou um formato otimizado, como um dataframe e ainda queira aproveitar a funcionalidade de armazenamento vetorial.

Aqui está um exemplo de como criar uma definição de registro.

using Microsoft.Extensions.VectorData;

var hotelDefinition = new VectorStoreCollectionDefinition
{
    Properties = new List<VectorStoreProperty>
    {
        new VectorStoreKeyProperty("HotelId", typeof(ulong)),
        new VectorStoreDataProperty("HotelName", typeof(string)) { IsIndexed = true },
        new VectorStoreDataProperty("Description", typeof(string)) { IsFullTextIndexed = true },
        new VectorStoreVectorProperty("DescriptionEmbedding", typeof(float), dimensions: 4) { DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw },
    }
};

Ao criar uma definição, você sempre precisa fornecer um nome e um tipo para cada propriedade em seu esquema, pois isso é necessário para a criação de índice e mapeamento de dados.

Para usar a definição, passe-a para o método GetCollection.

var collection = vectorStore.GetCollection<ulong, Hotel>("skhotels", hotelDefinition);

Classes de configuração da propriedade de registro

VectorStoreKeyProperty

Use essa classe para indicar que sua propriedade é a chave do registro.

new VectorStoreKeyProperty("HotelId", typeof(ulong)),

Definições de configuração de VectorStoreKeyProperty

Parâmetro Necessário Descrição
Nome Sim O nome da propriedade no modelo de dados. Usado pelo mapeador para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
Tipo Não O tipo da propriedade no modelo de dados. Usado pelo mapeador para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
Nome do Armazenamento Não Pode ser usado para fornecer um nome alternativo para a propriedade no banco de dados. Note que este parâmetro não é suportado por todos os conectores, por exemplo, onde alternativas como JsonPropertyNameAttribute é suportado.

Gorjeta

Para obter mais informações sobre quais conectores suportam StorageName e quais alternativas estão disponíveis, consulte a documentação de cada conector.

VectorStoreDataProperty

Use essa classe para indicar que sua propriedade contém dados gerais que não são uma chave ou um vetor.

new VectorStoreDataProperty("HotelName", typeof(string)) { IsIndexed = true },

Definições de configuração de VectorStoreDataProperty

Parâmetro Necessário Descrição
Nome Sim O nome da propriedade no modelo de dados. Usado pelo mapeador para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
Tipo Não O tipo da propriedade no modelo de dados. Usado pelo mapeador para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
IsIndexado Não Indica se a propriedade deve ser indexada para filtragem nos casos em que um banco de dados requer a aceitação da indexação por propriedade. A predefinição é falsa.
IsFullTextIndexed Não Indica se a propriedade deve ser indexada para pesquisa de texto completo para bancos de dados que oferecem suporte à pesquisa de texto completo. A predefinição é falsa.
Nome do Armazenamento Não Pode ser usado para fornecer um nome alternativo para a propriedade no banco de dados. Note que este parâmetro não é suportado por todos os conectores, por exemplo, onde alternativas como JsonPropertyNameAttribute é suportado.

Gorjeta

Para obter mais informações sobre quais conectores suportam StorageName e quais alternativas estão disponíveis, consulte a documentação de cada conector.

VectorStoreVectorProperty

Use essa classe para indicar que sua propriedade contém um vetor.

new VectorStoreVectorProperty("DescriptionEmbedding", typeof(float), dimensions: 4) { DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw },

Definições de configuração de VectorStoreVectorProperty

Parâmetro Necessário Descrição
Nome Sim O nome da propriedade no modelo de dados. Usado pelo mapeador para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
Tipo Não O tipo da propriedade no modelo de dados. Usado pelo mapeador para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
Dimensões Sim O número de dimensões que o vetor tem. Isso é necessário para criar um índice vetorial para uma coleção.
IndexKind Não O tipo de índice com o qual indexar o vetor. O padrão varia de acordo com o tipo de armazenamento vetorial.
Função DistânciaDistância Não O tipo de função a ser usada ao fazer a comparação de vetores durante a pesquisa vetorial sobre esse vetor. O padrão varia de acordo com o tipo de armazenamento vetorial.
Nome do Armazenamento Não Pode ser usado para fornecer um nome alternativo para a propriedade no banco de dados. Note que este parâmetro não é suportado por todos os conectores, por exemplo, onde alternativas como JsonPropertyNameAttribute é suportado.
EmbeddingGenerator Não Permite especificar uma Microsoft.Extensions.AI.IEmbeddingGenerator instância a ser usada para gerar incorporações automaticamente para a propriedade decorada.

Gorjeta

Para obter mais informações sobre quais conectores suportam StorageName e quais alternativas estão disponíveis, consulte a documentação de cada conector.

Aqui está um exemplo de como criar uma definição de registro, para uso com um DataFrame pandas.

Nota

Os mesmos campos que na definição do modelo de dados são usados aqui, para um modelo de dados eles são adicionados como anotações, aqui como um ditado com o nome.

Há algumas coisas importantes a observar, além das próprias definições de campos. O primeiro é o container_mode parâmetro. Quando definido como True, isso indica que o modelo de dados é um tipo de contêiner, como um DataFrame, e que o modelo de dados é, portanto, um contêiner de registros, em vez de um único, um registro de contêiner pode ser usado exatamente da mesma maneira, a principal diferença é que get e get_batch retornará o mesmo tipo de dados, com um único registo para um get e um ou mais para um get_batch. Quando você quer fazer um upsert, upsert e upsert_batch pode ser usado de forma intercambiável, em outras palavras, passar um contêiner para upsert resultará em vários upserts, em vez de um único.

O segundo é a adição dos métodos andto_dict, que são usados para converter entre o modelo de dados e o esquema de from_dict armazenamento. Nesse caso, o to_dict método é usado para converter o DataFrame em uma lista de registros, e o from_dict método é usado para converter uma lista de registros em um DataFrame. Também pode haver um serialize método e deserialize (não mostrado no exemplo abaixo), para obter detalhes sobre a diferença entre eles, consulte a documentação de serialização.

from semantic_kernel.data import (
    VectorStoreRecordDataField,
    VectorStoreRecordDefinition,
    VectorStoreRecordKeyField,
    VectorStoreRecordVectorField,
)

hotel_definition = VectorStoreRecordDefinition(
    fields={
        "hotel_id": VectorStoreRecordKeyField(property_type="str"),
        "hotel_name": VectorStoreRecordDataField(property_type="str", is_filterable=True),
        "description": VectorStoreRecordDataField(
            property_type="str", has_embedding=True, embedding_property_name="description_embedding"
        ),
        "description_embedding": VectorStoreRecordVectorField(property_type="list[float]"),
    },
    container_mode=True,
    to_dict=lambda record, **_: record.to_dict(orient="records"),
    from_dict=lambda records, **_: DataFrame(records),
)

Ao criar uma definição, você sempre precisa fornecer um nome (como a chave no fields ditado) e digitar para cada propriedade em seu esquema, já que isso é necessário para a criação de índice e mapeamento de dados.

Para usar a definição, passe-a para o método GetCollection ou um construtor de coleção, juntamente com o tipo de modelo de dados.

collection = vector_store.get_collection(
    collection_name="skhotels", 
    record_type=pd.DataFrame, 
    definition=hotel_definition,
)

Aqui está um exemplo de como criar uma definição de registro.

var hotelDefinition = VectorStoreRecordDefinition.fromFields(
    Arrays.asList(
        VectorStoreRecordKeyField.builder().withName("hotelId").withFieldType(String.class).build(),
        VectorStoreRecordDataField.builder()
            .withName("name")
            .withFieldType(String.class)
            .isFilterable(true).build(),
        VectorStoreRecordDataField.builder()
            .withName("description")
            .withFieldType(String.class)
            .isFullTextSearchable(true).build(),
        VectorStoreRecordVectorField.builder().withName("descriptionEmbedding")
            .withDimensions(4)
            .withIndexKind(IndexKind.HNSW)
            .withDistanceFunction(DistanceFunction.COSINE_DISTANCE)
            .withFieldType(List.class).build()
    )
);

Ao criar uma definição, você sempre precisa fornecer um nome e um tipo para cada campo em seu esquema, pois isso é necessário para a criação de índice e mapeamento de dados.

Para usar a definição, passe-a para o método GetCollection.

var collection = vectorStore.getCollection("skhotels",
        JDBCVectorStoreRecordCollectionOptions.builder()
            .withRecordDefinition(hotelDefinition)
            .build()
    );

Classes de configuração do campo de registro

VectorStoreRecordKeyField

Use essa classe para indicar que seu campo é a chave do registro.

VectorStoreRecordKeyField.builder().withName("hotelId").withFieldType(String.class).build(),

Definições de configuração de VectorStoreRecordKeyField

Parâmetro Necessário Descrição
nome Sim O nome do campo no modelo de dados. Usado pelos mapeadores integrados para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
Tipo de campo Sim O tipo do campo no modelo de dados. Usado pelos mapeadores integrados para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
nome_do_armazenamento Não Pode ser usado para fornecer um nome alternativo para o campo no banco de dados. Observe que este parâmetro não é suportado por todos os conectores, por exemplo, onde Jackson é usado, nesse caso, o nome do armazenamento pode ser especificado usando anotações Jackson.

Gorjeta

Para obter mais informações sobre quais conectores suportam storageName e quais alternativas estão disponíveis, consulte a documentação de cada conector.

VectorStoreRecordDataField

Use essa classe para indicar que sua propriedade contém dados gerais que não são uma chave ou um vetor.

VectorStoreRecordDataField.builder()
    .withName("name")
    .withFieldType(String.class)
    .isFilterable(true).build(),

Definições de configuração de VectorStoreRecordDataField

Parâmetro Necessário Descrição
nome Sim O nome do campo no modelo de dados. Usado pelos mapeadores integrados para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
Tipo de campo Sim O tipo do campo no modelo de dados. Usado pelos mapeadores integrados para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
isFiltrável Não Indica se o campo deve ser indexado para filtragem nos casos em que um banco de dados requer a aceitação da indexação por campo. A predefinição é falsa.
isFullTextSearchable Não Indica se o campo deve ser indexado para pesquisa de texto completo para bancos de dados que suportam pesquisa de texto completo. A predefinição é falsa.
nome_do_armazenamento Não Pode ser usado para fornecer um nome alternativo para o campo no banco de dados. Observe que este parâmetro não é suportado por todos os conectores, por exemplo, onde Jackson é usado, nesse caso, o nome do armazenamento pode ser especificado usando anotações Jackson.

Gorjeta

Para obter mais informações sobre quais conectores suportam storageName e quais alternativas estão disponíveis, consulte a documentação de cada conector.

VectorStoreRecordVectorField

Use essa classe para indicar que seu campo contém um vetor.

VectorStoreRecordVectorField.builder().withName("descriptionEmbedding")
    .withDimensions(4)
    .withIndexKind(IndexKind.HNSW)
    .withDistanceFunction(DistanceFunction.COSINE_DISTANCE)
    .withFieldType(List.class).build(),

Definições de configuração de VectorStoreRecordVectorField

Parâmetro Necessário Descrição
nome Sim O nome do campo no modelo de dados. Usado pelos mapeadores integrados para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
Tipo de campo Sim O tipo do campo no modelo de dados. Usado pelos mapeadores integrados para mapear automaticamente entre o esquema de armazenamento e o modelo de dados e para criar índices.
dimensões Sim para criar coleção, opcional caso contrário O número de dimensões que o vetor tem. Isso geralmente é necessário ao criar um índice de vetor para uma coleção.
indexKind Não O tipo de índice com o qual indexar o vetor. O padrão varia de acordo com o tipo de armazenamento vetorial.
distanceFunction Não O tipo de função a ser usada ao fazer a comparação de vetores durante a pesquisa vetorial sobre esse vetor. O padrão varia de acordo com o tipo de armazenamento vetorial.
nome_do_armazenamento Não Pode ser usado para fornecer um nome alternativo para o campo no banco de dados. Observe que este parâmetro não é suportado por todos os conectores, por exemplo, onde Jackson é usado, nesse caso, o nome do armazenamento pode ser especificado usando anotações Jackson.

Gorjeta

Para obter mais informações sobre quais conectores suportam storageName e quais alternativas estão disponíveis, consulte a documentação de cada conector.