// Copyright (c) Microsoft. All rights reserved. using System.Text.Json; using Azure.AI.OpenAI; using DevTeam.Options; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Connectors.OpenAI; using Microsoft.SemanticKernel.Connectors.Qdrant; using Microsoft.SemanticKernel.Memory; namespace DevTeam; public static class SemanticKernelHostingExtensions { public static IHostApplicationBuilder ConfigureSemanticKernel(this IHostApplicationBuilder builder) { builder.Services.Configure(o => { o.EmbeddingsEndpoint = o.ImageEndpoint = o.ChatEndpoint = builder.Configuration["OpenAI:Endpoint"] ?? throw new InvalidOperationException("Ensure that OpenAI:Endpoint is set in configuration"); o.EmbeddingsApiKey = o.ImageApiKey = o.ChatApiKey = builder.Configuration["OpenAI:Key"]!; o.EmbeddingsDeploymentOrModelId = "text-embedding-3-large"; o.ImageDeploymentOrModelId = "dall-e-3"; o.ChatDeploymentOrModelId = "gpt-4o"; }); builder.Services.Configure(o => { o.Retry.NetworkTimeout = TimeSpan.FromMinutes(5); }); builder.Services.AddOptions().Bind(builder.Configuration.GetSection("Qdrant")) .ValidateDataAnnotations() .ValidateOnStart(); builder.Services.Configure(options => { options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; }); builder.Services.AddTransient(CreateKernel); builder.Services.AddTransient(CreateMemory); return builder; } static ISemanticTextMemory CreateMemory(IServiceProvider provider) { var qdrantConfig = provider.GetRequiredService>().Value; var openAiConfig = provider.GetRequiredService>().Value; var qdrantHttpClient = new HttpClient(); if (!string.IsNullOrEmpty(qdrantConfig.ApiKey)) { qdrantHttpClient.DefaultRequestHeaders.Add("api-key", qdrantConfig.ApiKey); } var loggerFactory = provider.GetRequiredService(); var memoryBuilder = new MemoryBuilder(); return memoryBuilder.WithLoggerFactory(loggerFactory) .WithQdrantMemoryStore(qdrantHttpClient, qdrantConfig.VectorSize, qdrantConfig.Endpoint) .WithAzureOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAiConfig.EmbeddingsEndpoint, openAiConfig.EmbeddingsApiKey) .Build(); } static Kernel CreateKernel(IServiceProvider provider) { OpenAIOptions openAiConfig = provider.GetRequiredService>().Value; var builder = Kernel.CreateBuilder(); // Chat if (openAiConfig.ChatEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase)) { var openAIClient = new OpenAIClient(new Uri(openAiConfig.ChatEndpoint), new Azure.AzureKeyCredential(openAiConfig.ChatApiKey)); builder.Services.AddAzureOpenAIChatCompletion(openAiConfig.ChatDeploymentOrModelId, openAIClient); } else { var openAIClient = new OpenAIClient(openAiConfig.ChatApiKey); builder.Services.AddOpenAIChatCompletion(openAiConfig.ChatDeploymentOrModelId, openAIClient); } // Text to Image if (openAiConfig.ImageEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase)) { ArgumentException.ThrowIfNullOrEmpty(openAiConfig.ImageDeploymentOrModelId); var openAIClient = new OpenAIClient(new Uri(openAiConfig.ImageEndpoint), new Azure.AzureKeyCredential(openAiConfig.ImageApiKey)); builder.Services.AddAzureOpenAITextToImage(openAiConfig.ImageDeploymentOrModelId, openAIClient); } else { builder.Services.AddOpenAITextToImage(openAiConfig.ImageApiKey, modelId: openAiConfig.ImageDeploymentOrModelId); } // Embeddings if (openAiConfig.EmbeddingsEndpoint.Contains(".azure", StringComparison.OrdinalIgnoreCase)) { var openAIClient = new OpenAIClient(new Uri(openAiConfig.EmbeddingsEndpoint), new Azure.AzureKeyCredential(openAiConfig.EmbeddingsApiKey)); builder.Services.AddAzureOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAIClient); } else { var openAIClient = new OpenAIClient(openAiConfig.EmbeddingsApiKey); builder.Services.AddOpenAITextEmbeddingGeneration(openAiConfig.EmbeddingsDeploymentOrModelId, openAIClient); } return builder.Build(); } }