Partager via


Utilisation du connecteur Elasticsearch (préversion)

Avertissement

La fonctionnalité de magasin de vecteurs du noyau sémantique est en version préliminaire, et des améliorations nécessitant des changements incompatibles peuvent encore survenir dans des circonstances limitées avant la version finale.

Aperçu

Le connecteur Elasticsearch Vector Store peut être utilisé pour accéder aux données et les gérer dans Elasticsearch. Le connecteur présente les caractéristiques suivantes.

Zone de fonctionnalité Soutien
Les cartes de collection correspondent à Index d'Elasticsearch
Types de propriétés de clé pris en charge corde
Types de propriétés de données pris en charge Tous les types pris en charge par System.Text.Json (etiher intégré ou à l’aide d’un convertisseur personnalisé)
Types de propriétés vectorielles pris en charge
  • ReadOnlyMemory<float>
  • IEnumerable<float>
Types d’index pris en charge
  • HNSW (32, 8 ou 4 bits)
  • FLAT (32, 8 ou 4 bits)
Fonctions de distance prises en charge
  • CosineSimilarity
  • DotProductSimilarity
  • EuclideanDistance
  • MaxInnerProduct
Clauses de filtre prises en charge
  • AnyTagEqualTo
  • EqualTo
Prend en charge plusieurs vecteurs dans un enregistrement Oui
La fonction IsFilterable est-elle prise en charge ? Oui
La fonctionnalité de recherche en texte intégral est-elle prise en charge ? Oui
NomDePropriétéDeStockage pris en charge ? Non, utilisez JsonSerializerOptions et JsonPropertyNameAttribute à la place. Voir ici pour plus d’informations.

Commencer

Pour exécuter Elasticsearch localement pour le développement local ou les tests, exécutez le script start-local avec une commande :

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

Ajoutez le package NuGet du connecteur Elasticsearch Vector Store à votre projet.

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

Vous pouvez ajouter le magasin de vecteurs au conteneur d’injection de dépendances disponible sur le KernelBuilder ou au conteneur d’injection de dépendances IServiceCollection à l’aide de méthodes d’extension fournies par le noyau sémantique.

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

Les méthodes d’extension qui ne prennent aucun paramètre sont également fournies. Celles-ci nécessitent qu’une instance de la classe Elastic.Clients.Elasticsearch.ElasticsearchClient soit inscrite séparément auprès du conteneur d’injection de dépendances.

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();

Vous pouvez construire directement une instance Elasticsearch Vector Store.

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

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

Il est possible de construire une référence directe à une collection nommée.

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

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

Mappage des données

Le connecteur Elasticsearch utilise System.Text.Json.JsonSerializer pour effectuer le mappage. Dans la mesure où Elasticsearch stocke des documents avec une clé/id et une valeur distinctes, le mappeur sérialise toutes les propriétés à l’exception de la clé vers un objet JSON et l’utilise comme valeur.

L’utilisation du JsonPropertyNameAttribute est prise en charge si un nom de stockage différent du nom de propriété du modèle de données est requis. Il est également possible d’utiliser une instance de JsonSerializerOptions personnalisée avec une politique de nommage des propriétés personnalisée. Pour l’activer, un sérialiseur source personnalisé doit être configuré.

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

En guise d’alternative, la fonction lambda DefaultFieldNameInferrer peut être configurée pour obtenir le même résultat ou encore personnaliser davantage le nommage de propriété en fonction de conditions dynamiques.

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

Étant donné qu'une politique de nommage en majuscules snake_case a été choisie, voici un exemple de la façon dont ce type de données sera défini dans Elasticsearch. Notez également l’utilisation de JsonPropertyNameAttribute sur la propriété Description pour personnaliser davantage la nomenclature du stockage.

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
    ]
  }
}

Non pris en charge

Non pris en charge.

Non pris en charge

Non pris en charge.