|
| 1 | +// Copyright (c) Microsoft Corporation. |
| 2 | +// Licensed under the MIT license. |
| 3 | +// |
| 4 | +using Azure.AI.OpenAI; |
| 5 | +using Azure.Core; |
| 6 | +using Azure.Identity; |
| 7 | +using ChatApp; |
| 8 | +using Microsoft.Extensions.Configuration; |
| 9 | +using Microsoft.Extensions.Configuration.AzureAppConfiguration; |
| 10 | +using OpenAI.Chat; |
| 11 | + |
| 12 | +TokenCredential credential = new DefaultAzureCredential(); |
| 13 | +IConfigurationRefresher refresher = null; |
| 14 | + |
| 15 | +// Load configuration from Azure App Configuration |
| 16 | +IConfiguration configuration = new ConfigurationBuilder() |
| 17 | + .AddAzureAppConfiguration(options => |
| 18 | + { |
| 19 | + Uri endpoint = new(Environment.GetEnvironmentVariable("AZURE_APPCONFIG_ENDPOINT") ?? |
| 20 | + throw new InvalidOperationException("The environment variable 'AZURE_APPCONFIG_ENDPOINT' is not set or is empty.")); |
| 21 | + options.Connect(endpoint, credential) |
| 22 | + // Load all keys that start with "ChatApp:" and have no label. |
| 23 | + .Select("ChatApp:*") |
| 24 | + // Reload configuration if any selected key-values have changed. |
| 25 | + // Use the default refresh interval of 30 seconds. It can be overridden via refreshOptions.SetRefreshInterval. |
| 26 | + .ConfigureRefresh(refreshOptions => |
| 27 | + { |
| 28 | + refreshOptions.RegisterAll(); |
| 29 | + }); |
| 30 | + |
| 31 | + refresher = options.GetRefresher(); |
| 32 | + }) |
| 33 | + .Build(); |
| 34 | + |
| 35 | +// Retrieve the OpenAI connection information from the configuration |
| 36 | +Uri openaiEndpoint = new (configuration["ChatApp:AzureOpenAI:Endpoint"]); |
| 37 | +string deploymentName = configuration["ChatApp:AzureOpenAI:DeploymentName"]; |
| 38 | + |
| 39 | +// Create a chat client |
| 40 | +AzureOpenAIClient azureClient = new(openaiEndpoint, credential); |
| 41 | +ChatClient chatClient = azureClient.GetChatClient(deploymentName); |
| 42 | + |
| 43 | +while (true) |
| 44 | +{ |
| 45 | + // Refresh the configuration from Azure App Configuration |
| 46 | + await refresher.TryRefreshAsync(); |
| 47 | + |
| 48 | + // Configure chat completion with AI configuration |
| 49 | + var modelConfiguration = configuration.GetSection("ChatApp:Model").Get<ModelConfiguration>(); |
| 50 | + var requestOptions = new ChatCompletionOptions() |
| 51 | + { |
| 52 | + MaxOutputTokenCount = modelConfiguration.MaxTokens, |
| 53 | + Temperature = modelConfiguration.Temperature, |
| 54 | + TopP = modelConfiguration.TopP |
| 55 | + }; |
| 56 | + |
| 57 | + foreach (var message in modelConfiguration.Messages) |
| 58 | + { |
| 59 | + Console.WriteLine($"{message.Role}: {message.Content}"); |
| 60 | + } |
| 61 | + |
| 62 | + // Get chat response from AI |
| 63 | + var response = await chatClient.CompleteChatAsync(GetChatMessages(modelConfiguration), requestOptions); |
| 64 | + System.Console.WriteLine($"AI response: {response.Value.Content[0].Text}"); |
| 65 | + |
| 66 | + Console.WriteLine("Press Enter to continue..."); |
| 67 | + Console.ReadLine(); |
| 68 | +} |
| 69 | + |
| 70 | +static IEnumerable<ChatMessage> GetChatMessages(ModelConfiguration modelConfiguration) |
| 71 | +{ |
| 72 | + return modelConfiguration.Messages.Select<Message, ChatMessage>(message => message.Role switch |
| 73 | + { |
| 74 | + "system" => ChatMessage.CreateSystemMessage(message.Content), |
| 75 | + "user" => ChatMessage.CreateUserMessage(message.Content), |
| 76 | + "assistant" => ChatMessage.CreateAssistantMessage(message.Content), |
| 77 | + _ => throw new ArgumentException($"Unknown role: {message.Role}", nameof(message.Role)) |
| 78 | + }); |
| 79 | +} |
0 commit comments