Compartilhar via


Usando o conector Elasticsearch (versão prévia)

Aviso

A funcionalidade semântica do Repositório de Vetores kernel está em versão prévia e melhorias que exigem alterações significativas ainda podem ocorrer em circunstâncias limitadas antes do lançamento.

Visão geral

O conector do Elasticsearch Vector Store pode ser usado para acessar e gerenciar dados no Elasticsearch. O conector tem as seguintes características.

Área de Funcionalidade Apoio
A coleção é mapeada para Índice Elasticsearch
Tipos de propriedade de chave com suporte corda
Tipos de propriedade de dados com suporte Todos os tipos que são compatíveis com System.Text.Json (seja nativamente ou usando um conversor personalizado)
Tipos de propriedades de vetor suportados
  • ReadOnlyMemory<float>
  • IEnumerable<ponto flutuante>
Tipos de índice com suporte
  • HNSW (32, 8 ou 4 bits)
  • FLAT (32, 8 ou 4 bits)
Funções de distância suportadas
  • CosineSimilaridade
  • DotProductSimilarity
  • EuclideanDistance
  • MaxInnerProduct
Cláusulas de filtro com suporte
  • AnyTagEqualTo
  • EqualTo
Dá suporte a vários vetores em um registro Sim
Há suporte para o IsFilterable? Sim
Há suporte para o IsFullTextSearchable? Sim
StoragePropertyName é suportado? Não, use JsonSerializerOptions e JsonPropertyNameAttribute em vez disso. Veja aqui para obter mais informações.

Começando

Para executar o Elasticsearch localmente para desenvolvimento local ou teste, execute o script start-local com um comando:

curl -fsSL https://elastic.co/start-local | sh

Adicione o pacote NuGet do conector do Elasticsearch Vector Store ao seu projeto.

dotnet add package Elastic.SemanticKernel.Connectors.Elasticsearch --prerelease

Você pode adicionar o repositório de vetores ao contêiner de injeção de dependência disponível no KernelBuilder ou ao contêiner de injeção de dependência IServiceCollection usando métodos de extensão fornecidos pelo Kernel Semântico.

using Microsoft.SemanticKernel;
using Elastic.Clients.Elasticsearch;

// Using Kernel Builder.
var kernelBuilder = Kernel
    .CreateBuilder()
    .AddElasticsearchVectorStore(new ElasticsearchClientSettings(new Uri("http://localhost:9200")));
using Microsoft.SemanticKernel;
using Elastic.Clients.Elasticsearch;

// Using IServiceCollection with ASP.NET Core.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddElasticsearchVectorStore(new ElasticsearchClientSettings(new Uri("http://localhost:9200")));

Métodos de extensão que não têm parâmetros também são fornecidos. Isso requer que uma instância da classe Elastic.Clients.Elasticsearch.ElasticsearchClient seja registrada de forma distinta no container de injeção de dependência.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Elastic.Clients.Elasticsearch;

// Using Kernel Builder.
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.Services.AddSingleton<ElasticsearchClient>(sp =>
    new ElasticsearchClient(new ElasticsearchClientSettings(new Uri("http://localhost:9200"))));
kernelBuilder.AddElasticsearchVectorStore();
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Elastic.Clients.Elasticsearch;

// Using IServiceCollection with ASP.NET Core.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ElasticsearchClient>(sp =>
    new ElasticsearchClient(new ElasticsearchClientSettings(new Uri("http://localhost:9200"))));
builder.Services.AddElasticsearchVectorStore();

Você pode construir uma instância do Elasticsearch Vector Store diretamente.

using Elastic.SemanticKernel.Connectors.Elasticsearch;
using Elastic.Clients.Elasticsearch;

var vectorStore = new ElasticsearchVectorStore(
    new ElasticsearchClient(new ElasticsearchClientSettings(new Uri("http://localhost:9200"))));

É possível construir uma referência direta a uma coleção nomeada.

using Elastic.SemanticKernel.Connectors.Elasticsearch;
using Elastic.Clients.Elasticsearch;

var collection = new ElasticsearchVectorStoreRecordCollection<Hotel>(
    new ElasticsearchClient(new ElasticsearchClientSettings(new Uri("http://localhost:9200"))),
    "skhotels");

Mapeamento de dados

O conector do Elasticsearch usará System.Text.Json.JsonSerializer para fazer mapeamento. Como o Elasticsearch armazena documentos com uma chave/id e um valor separados, o mapeador serializará todas as propriedades, exceto a chave para um objeto JSON e a usará como o valor.

O uso do JsonPropertyNameAttribute é suportado se for necessário um nome de armazenamento diferente do nome da propriedade do modelo de dados. Também é possível usar uma instância personalizada de JsonSerializerOptions com uma política de nomenclatura de propriedade personalizada. Para habilitar isso, um serializador de origem personalizado deve ser configurado.

using Elastic.SemanticKernel.Connectors.Elasticsearch;
using Elastic.Clients.Elasticsearch;
using Elastic.Clients.Elasticsearch.Serialization;
using Elastic.Transport;

var nodePool = new SingleNodePool(new Uri("http://localhost:9200"));
var settings = new ElasticsearchClientSettings(
    nodePool,
    sourceSerializer: (defaultSerializer, settings) =>
        new DefaultSourceSerializer(settings, options => 
            options.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseUpper));
var client = new ElasticsearchClient(settings);

var collection = new ElasticsearchVectorStoreRecordCollection<Hotel>(
    client,
    "skhotelsjson");

Como alternativa, a função lambda DefaultFieldNameInferrer pode ser configurada para obter o mesmo resultado ou personalizar ainda mais a nomenclatura de propriedade com base em condições dinâmicas.

using Elastic.SemanticKernel.Connectors.Elasticsearch;
using Elastic.Clients.Elasticsearch;

var settings = new ElasticsearchClientSettings(new Uri("http://localhost:9200"));
settings.DefaultFieldNameInferrer(name => JsonNamingPolicy.SnakeCaseUpper.ConvertName(name));
var client = new ElasticsearchClient(settings);

var collection = new ElasticsearchVectorStoreRecordCollection<Hotel>(
    client,
    "skhotelsjson");

Como foi escolhida uma política de nomenclatura no formato "SNAKE_CASE" maiúsculo, aqui está um exemplo de como esse tipo de dado será definido no Elasticsearch. Observe também o uso de JsonPropertyNameAttribute na propriedade Description para personalizar ainda mais a nomenclatura de armazenamento.

using System.Text.Json.Serialization;
using Microsoft.Extensions.VectorData;

public class Hotel
{
    [VectorStoreRecordKey]
    public string HotelId { get; set; }

    [VectorStoreRecordData(IsFilterable = true)]
    public string HotelName { get; set; }

    [JsonPropertyName("HOTEL_DESCRIPTION")]
    [VectorStoreRecordData(IsFullTextSearchable = true)]
    public string Description { get; set; }

    [VectorStoreRecordVector(Dimensions: 4, DistanceFunction.CosineSimilarity, IndexKind.Hnsw)]
    public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
}
{
  "_index" : "skhotelsjson",
  "_id" : "h1",
  "_source" : {
    "HOTEL_NAME" : "Hotel Happy",
    "HOTEL_DESCRIPTION" : "A place where everyone can be happy.",
    "DESCRIPTION_EMBEDDING" : [
      0.9,
      0.1,
      0.1,
      0.1
    ]
  }
}

Sem suporte

Não há suporte.

Sem suporte

Não há suporte.