public static async Task Main()

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).
    }