Comment utiliser le connecteur Elasticsearch Vector Store pour Microsoft Semantic Kernel pour le développement d'agents d'intelligence artificielle ?
Microsoft Semantic Kernel est un kit de développement léger et open-source qui vous permet de créer facilement des agents d'intelligence artificielle et d'intégrer les derniers modèles d'intelligence artificielle dans votre base de code C#, Python ou Java. Avec la sortie du connecteur Semantic Kernel Elasticsearch Vector Store, les développeurs qui utilisent Semantic Kernel pour créer des agents d'intelligence artificielle peuvent désormais utiliser Elasticsearch comme un magasin vectoriel d'entreprise évolutif tout en continuant à utiliser les abstractions de Semantic Kernel.
En collaboration avec l'équipe de Microsoft Semantic Kernel, nous annonçons la disponibilité du connecteur Semantic Kernel Elasticsearch Vector Store, pour les utilisateurs de Microsoft Semantic Kernel (.NET). Semantic Kernel simplifie la création d'agents d'intelligence artificielle de niveau professionnel, notamment en permettant d'améliorer les grands modèles de langage (LLM) grâce à des réponses plus pertinentes et fondées sur des données provenant d'un magasin de vecteurs. Semantic Kernel fournit une couche d'abstraction transparente pour interagir avec les magasins vectoriels tels qu'Elasticsearch, offrant des fonctionnalités essentielles telles que la création, l'énumération et la suppression de collections d'enregistrements et le téléchargement, l'extraction et la suppression d'enregistrements individuels.
Le connecteur Semantic Kernel Elasticsearch Vector Store, prêt à l'emploi, prend en charge les abstractions du Semantic Kernel vector store, ce qui permet aux développeurs de brancher très facilement Elasticsearch en tant que magasin vectoriel lors de la création d'agents d'intelligence artificielle.
Elasticsearch est solidement ancré dans la communauté des logiciels libres et a récemment adopté la licence AGPL. Associés au noyau sémantique Microsoft open-source, ces outils offrent une solution puissante, prête pour l'entreprise. Vous pouvez commencer localement en démarrant Elasticsearch en quelques minutes en exécutant cette commande curl -fsSL https://elastic.co/start-local | sh (voir start-local pour plus de détails) et évoluer vers des versions hébergées dans le nuage ou auto-hébergées tout en mettant en production vos agents d'IA.
Dans ce blog, nous verrons comment utiliser le connecteur Semantic Kernel Elasticsearch Vector Store lors de l'utilisation de Semantic Kernel. Une version Python du connecteur sera disponible à l'avenir.
Scénario de haut niveau : Construire une application RAG avec Semantic Kernel & Elasticsearch
Dans la section suivante, nous présentons un exemple. À un niveau élevé, nous construisons une application RAG (Retrieval Augmented Generation) qui prend la question d'un utilisateur en entrée et renvoie une réponse. Nous utiliserons Azure OpenAI(un LLM local peut également être utilisé) comme LLM, Elasticsearch comme magasin de vecteurs et Semantic Kernel (.net) comme cadre pour relier tous les composants ensemble.
Si vous n'êtes pas familier avec les architectures RAG, vous pouvez vous familiariser rapidement avec cet article : https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag.
La réponse est générée par le LLM qui est alimenté par le contexte, pertinent pour la question, récupéré à partir du vectorstore Elasticsearch. La réponse inclut également la source qui a été utilisée comme contexte par le LLM.
Exemple de GCR
Dans cet exemple spécifique, nous créons une application qui permet aux utilisateurs de poser des questions sur les hôtels stockés dans une base de données interne. L'utilisateur peut par exemple rechercher un hôtel spécifique, en fonction de différents critères, ou demander une liste d'hôtels.
Pour la base de données d'exemple, nous avons généré une liste d'hôtels contenant 100 entrées. La taille de l'échantillon est volontairement réduite pour vous permettre d'essayer la démo du connecteur aussi facilement que possible. Dans une application réelle, le connecteur Elasticsearch montrerait ses avantages par rapport à d'autres options, telles que l'implémentation du magasin vectoriel `InMemory`, en particulier lorsque l'on travaille avec de très grandes quantités de données.
L'application de démonstration complète se trouve dans le référentiel du connecteur Elasticsearch vector store.
Commençons par ajouter les paquets NuGet et les directives nécessaires à notre projet :
dotnet add package "Elastic.Clients.Elasticsearch" -v 8.16.2
dotnet add package "Elastic.SemanticKernel.Connectors.Elasticsearch" -v 0.1.2
dotnet add package "Microsoft.Extensions.Hosting" -v 9.0.0
dotnet add package "Microsoft.SemanticKernel.Connectors.AzureOpenAI" -v 1.30.0
dotnet add package "Microsoft.SemanticKernel.PromptTemplates.Handlebars" -v 1.30.0using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Elastic.Clients.Elasticsearch;
using Elastic.Transport;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.Embeddings;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;Nous pouvons maintenant créer notre modèle de données et le doter d'attributs spécifiques au Semantic Kernel pour définir le schéma du modèle de stockage et quelques indications pour la recherche textuelle :
/// <summary>
/// Data model for storing a "hotel" with a name, a description, a description embedding and an optional reference link.
/// </summary>
public sealed record Hotel
{
[VectorStoreRecordKey]
public required string HotelId { get; set; }
[TextSearchResultName]
[VectorStoreRecordData(IsFilterable = true)]
public required string HotelName { get; set; }
[TextSearchResultValue]
[VectorStoreRecordData(IsFullTextSearchable = true)]
public required string Description { get; set; }
[VectorStoreRecordVector(Dimensions: 1536, DistanceFunction.CosineSimilarity, IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
[TextSearchResultLink]
[VectorStoreRecordData]
public string? ReferenceLink { get; set; }
}Les attributs du schéma du modèle de stockage (`VectorStore*`) sont les plus pertinents pour l'utilisation réelle du connecteur Elasticsearch Vector Store, à savoir :
VectorStoreRecordKeypour marquer une propriété d'une classe d'enregistrement comme étant la clé sous laquelle l'enregistrement est stocké dans un magasin vectoriel.VectorStoreRecordDatapour marquer une propriété d'une classe d'enregistrement comme "data".VectorStoreRecordVectorpour marquer une propriété d'une classe d'enregistrement en tant que vecteur.
Tous ces attributs acceptent divers paramètres facultatifs qui peuvent être utilisés pour personnaliser davantage le modèle de stockage. Dans le cas de VectorStoreRecordKey , par exemple, il est possible de spécifier une fonction de distance différente ou un type d'indice différent.
Les attributs de recherche de texte (TextSearch*) seront importants dans la dernière étape de cet exemple. Nous y reviendrons plus tard.
Dans l'étape suivante, nous initialisons le moteur du noyau sémantique et obtenons des références aux services de base. Dans une application réelle, l' injection de dépendances devrait être utilisée au lieu d'accéder directement à la collection de services. La même chose s'applique à la configuration et aux secrets codés en dur, qui doivent être lus à l'aide d'un fournisseur de configuration:
var builder = Host.CreateApplicationBuilder(args);
// Register AI services.
var kernelBuilder = builder.Services.AddKernel();
kernelBuilder.AddAzureOpenAIChatCompletion("gpt-4o", "https://my-service.openai.azure.com", "my_token");
kernelBuilder.AddAzureOpenAITextEmbeddingGeneration("ada-002", "https://my-service.openai.azure.com", "my_token");
// Register text search service.
kernelBuilder.AddVectorStoreTextSearch<Hotel>();
// Register Elasticsearch vector store.
var elasticsearchClientSettings = new ElasticsearchClientSettings(new Uri("https://my-elasticsearch-instance.cloud"))
.Authentication(new BasicAuthentication("elastic", "my_password"));
kernelBuilder.AddElasticsearchVectorStoreRecordCollection<string, Hotel>("skhotels", elasticsearchClientSettings);
// Build the host.
using var host = builder.Build();
// For demo purposes, we access the services directly without using a DI context.
var kernel = host.Services.GetService<Kernel>()!;
var embeddings = host.Services.GetService<ITextEmbeddingGenerationService>()!;
var vectorStoreCollection = host.Services.GetService<IVectorStoreRecordCollection<string, Hotel>>()!;
// Register search plugin.
var textSearch = host.Services.GetService<VectorStoreTextSearch<Hotel>>()!;
kernel.Plugins.Add(textSearch.CreateWithGetTextSearchResults("SearchPlugin"));Le service vectorStoreCollection peut maintenant être utilisé pour créer la collection et ingérer quelques enregistrements de démonstration :
await vectorStoreCollection.CreateCollectionIfNotExistsAsync();
// CSV format: ID;Hotel Name;Description;Reference Link
var hotels = (await File.ReadAllLinesAsync("hotels.csv"))
.Select(x => x.Split(';'));
foreach (var chunk in hotels.Chunk(25))
{
var descriptionEmbeddings = await embeddings.GenerateEmbeddingsAsync(chunk.Select(x => x[2]).ToArray());
for (var i = 0; i < chunk.Length; ++i)
{
var hotel = chunk[i];
await vectorStoreCollection.UpsertAsync(new Hotel
{
HotelId = hotel[0],
HotelName = hotel[1],
Description = hotel[2],
DescriptionEmbedding = descriptionEmbeddings[i],
ReferenceLink = hotel[3]
});
}
}Cela montre comment Semantic Kernel réduit l'utilisation d'un magasin de vecteurs, avec toute sa complexité, à quelques simples appels de méthodes.
Sous le capot, un nouvel index est créé dans Elasticsearch et tous les mappages de propriétés nécessaires sont créés. Notre ensemble de données est ensuite intégré de manière totalement transparente dans le modèle de stockage et finalement stocké dans l'index. Voici à quoi ressemblent les mappings dans Elasticsearch.
{
"mappings": {
"properties": {
"descriptionEmbedding": {
"dims": 1536,
"index": true,
"index_options": {
"type": "hnsw"
},
"similarity": "cosine",
"type": "dense_vector"
},
"hotelName": {
"type": "keyword"
},
"description": {
"type": "text"
}
}
}
}Le site embeddings.GenerateEmbeddingsAsync() appelle de manière transparente le service Azure AI Embeddings Generation configuré.
La dernière étape de cette démonstration est encore plus magique.
Avec un seul appel à InvokePromptAsync, toutes les opérations suivantes sont effectuées lorsque l'utilisateur pose une question sur les données :
1. L'intégration de la question de l'utilisateur est générée.
2. Le magasin de vecteurs est parcouru à la recherche d'entrées pertinentes
3. Les résultats de la requête sont insérés dans un modèle d'invite
4. La requête proprement dite, sous la forme de l'invite finale, est envoyée au service d'achèvement de chat de l'IA.
// Invoke the LLM with a template that uses the search plugin to
// 1. get related information to the user query from the vector store
// 2. add the information to the LLM prompt.
var response = await kernel.InvokePromptAsync(
promptTemplate: """
Please use this information to answer the question:
{{#with (SearchPlugin-GetTextSearchResults question)}}
{{#each this}}
Name: {{Name}}
Value: {{Value}}
Source: {{Link}}
-----------------
{{/each}}
{{/with}}
Include the source of relevant information in the response.
Question: {{question}}
""",
arguments: new KernelArguments
{
{ "question", "Please show me all hotels that have a rooftop bar." },
},
templateFormat: "handlebars",
promptTemplateFactory: new HandlebarsPromptTemplateFactory());Vous vous souvenez des attributs TextSearch* que nous avons définis précédemment dans notre modèle de données ? Ces attributs nous permettent d'utiliser les espaces réservés correspondants dans notre modèle d'invite, qui sont automatiquement remplis avec les informations provenant de nos entrées dans le magasin de vecteurs.
La réponse finale à notre question "Veuillez m'indiquer tous les hôtels qui disposent d'un bar sur le toit." est la suivante :
Console.WriteLine(response.ToString());
// > The hotel that has a rooftop bar is Skyline Suites. You can find more information about this hotel [here](https://example.com/yz567).La réponse se réfère correctement à l'entrée suivante dans notre fichier hotels.csv
9;
Skyline Suites;
Offering panoramic city views from every suite, this hotel is perfect for those who love the urban landscape. Enjoy luxurious amenities, a rooftop bar, and close proximity to attractions. Luxurious and contemporary.;
https://example.com/yz567Cet exemple montre très bien comment l'utilisation de Microsoft Semantic Kernel permet une réduction significative de la complexité grâce à ses abstractions bien pensées, tout en permettant un très haut niveau de flexibilité. En changeant une seule ligne de code, par exemple, le magasin de vecteurs ou les services d'intelligence artificielle utilisés peuvent être remplacés sans qu'il soit nécessaire de remanier une autre partie du code.
Dans le même temps, le cadre fournit un ensemble considérable de fonctionnalités de haut niveau, telles que la fonction `InvokePrompt`, ou le système de plugin de modèle ou de recherche.
L'application de démonstration complète se trouve dans le référentiel du connecteur Elasticsearch vector store.
Quelles sont les autres possibilités offertes par Elasticsearch ?
Nouveau mappage semantic_text d'Elasticsearch : Simplifier la recherche sémantique
Classement sémantique dans Elasticsearch à l'aide d'extracteurs
Techniques avancées de RAG partie 1 : Traitement des données
Elasticsearch & Semantic Kernel : Quelle est la prochaine étape ?
Nous avons montré comment le magasin vectoriel Elasticsearch peut être facilement intégré au Semantic Kernel lors de la construction d'applications GenAI en .NET. Restez à l'écoute pour une prochaine intégration de Python.
Comme Semantic Kernel construit des abstractions pour des fonctions de recherche avancées telles que la recherche hybride, la connexion Elasticsearch permettra aux développeurs .NET de les mettre en œuvre facilement tout en utilisant Semantic Kernel.
Questions fréquentes
Qu'est-ce que le noyau sémantique de Microsoft ?
Microsoft Semantic Kernel est un kit de développement léger et open-source qui vous permet de créer facilement des agents d'intelligence artificielle et d'intégrer les derniers modèles d'intelligence artificielle dans votre base de code C#, Python ou Java.




