in Elastic.SemanticKernel.Playground/Program.cs [23:109]
public static async Task Main(string[] args)
{
#pragma warning disable SKEXP0010 // Some SK methods are still experimental
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"));
// Crate collection and ingest a few demo records.
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]
});
}
}
// 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());
Console.WriteLine(response.ToString());
// > Urban Chic Hotel has a rooftop bar with stunning views (Source: https://example.com/stu654).
}