Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
In this guide, you build an AI chat application and iterate on the prompt using chat completion configuration dynamically loaded from Azure App Configuration.
The full sample source code is available in the Azure App Configuration GitHub repository.
Prerequisites
- Complete the tutorial to Create a chat completion configuration.
- The latest .NET SDK
Create a console app
Create a new folder for your project. In the new folder, run the following command to create a new .NET console app project:
dotnet new console
Install the following NuGet packages in your project:
dotnet add package Microsoft.Extensions.Configuration.AzureAppConfiguration dotnet add package Microsoft.Extensions.Configuration.Binder dotnet add package Azure.Identity dotnet add package Azure.AI.OpenAI
Open the Program.cs file, and add the following namespaces at the top of the file:
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.AzureAppConfiguration; using Azure.Identity; using Azure.AI.OpenAI; using OpenAI.Chat;
Connect to your App Configuration store by calling the
AddAzureAppConfiguration
method in the Program.cs file.You can connect to App Configuration using either Microsoft Entra ID (recommended) or a connection string. In this example, you use Microsoft Entra ID with
DefaultAzureCredential
to authenticate to your App Configuration store. Follow these instructions to assign the App Configuration Data Reader role to the identity represented byDefaultAzureCredential
. Be sure to allow sufficient time for the permission to propagate before running your application.TokenCredential credential = new DefaultAzureCredential(); IConfigurationRefresher refresher = null; // Load configuration from Azure App Configuration IConfiguration configuration = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { Uri endpoint = new(Environment.GetEnvironmentVariable("AZURE_APPCONFIGURATION_ENDPOINT") ?? throw new InvalidOperationException("The environment variable 'AZURE_APPCONFIGURATION_ENDPOINT' is not set or is empty.")); options.Connect(endpoint, credential) // Load all keys that start with "ChatApp:" and have no label. .Select("ChatApp:*") // Reload configuration if any selected key-values have changed. // Use the default refresh interval of 30 seconds. It can be overridden via refreshOptions.SetRefreshInterval. .ConfigureRefresh(refreshOptions => { refreshOptions.RegisterAll(); }); refresher = options.GetRefresher(); }) .Build();
Create an instance of the
AzureOpenAIClient
to connect to your Azure OpenAI resource. You can use either Microsoft Entra ID or API key for authentication.To access your Azure OpenAI resource with Microsoft Entra ID, you use
DefaultAzureCredential
. Assign the Cognitive Services OpenAI User role to the identity represented byDefaultAzureCredential
. For detailed steps, refer to the Role-based access control for Azure OpenAI service guide. Be sure to allow sufficient time for the permission to propagate before running your application.// Retrieve the OpenAI connection information from the configuration Uri openaiEndpoint = new(configuration["ChatApp:AzureOpenAI:Endpoint"]); string deploymentName = configuration["ChatApp:AzureOpenAI:DeploymentName"]; // Initialize the AzureOpenAIClient AzureOpenAIClient azureClient = new(openaiEndpoint, credential); // Create a chat client ChatClient chatClient = azureClient.GetChatClient(deploymentName);
To access your Azure OpenAI resource with an API key, add the following code:
// Initialize the AzureOpenAIClient var apiKey = configuration["ChatApp:AzureOpenAI:ApiKey"]; AzureOpenAIClient client = new(openAIEndpoint, new AzureKeyCredential(apiKey));
If the key ChatApp:AzureOpenAI:ApiKey is a Key Vault reference in App Configuration, make sure to add the following code snippet to the
AddAzureAppConfiguration
call and grant your app access to Key Vault.options.ConfigureKeyVault(keyVaultOptions => { keyVaultOptions.SetCredential(credential); });
Define the
ChatCompletionConfiguration
class in Program.cs file:internal class ChatCompletionConfiguration { [ConfigurationKeyName("model")] public string? Model { get; set; } [ConfigurationKeyName("messages")] public List<Message>? Messages { get; set; } [ConfigurationKeyName("max_tokens")] public int MaxTokens { get; set; } [ConfigurationKeyName("temperature")] public float Temperature { get; set; } [ConfigurationKeyName("top_p")] public float TopP { get; set; } } internal class Message { [ConfigurationKeyName("role")] public required string Role { get; set; } [ConfigurationKeyName("content")] public string? Content { get; set; } }
Update the Program.cs file to add a helper method
GetChatMessages
to process chat messages:// Helper method to convert configuration messages to ChatMessage objects static IEnumerable<ChatMessage> GetChatMessages(ChatCompletionConfiguration chatCompletionConfiguration) { return chatCompletionConfiguration.Messages.Select<Message, ChatMessage>(message => message.Role switch { "system" => ChatMessage.CreateSystemMessage(message.Content), "user" => ChatMessage.CreateUserMessage(message.Content), "assistant" => ChatMessage.CreateAssistantMessage(message.Content), _ => throw new ArgumentException($"Unknown role: {message.Role}", nameof(message.Role)) }); }
Next, update the existing code in the Program.cs file to refresh the configuration from Azure App Configuration, apply the latest AI configuration values to the chat completion settings, and retrieve a response from the AI model.
// Initialize chat conversation var chatConversation = new List<ChatMessage>(); Console.WriteLine("Chat started! What's on your mind?"); while (true) { // Get user input Console.Write("You: "); string? userInput = Console.ReadLine(); // Exit if user input is empty if (string.IsNullOrEmpty(userInput)) { Console.WriteLine("Exiting chat. Goodbye!"); break; } chatConversation.Add(ChatMessage.CreateUserMessage(userInput)); // Refresh the configuration from Azure App Configuration await refresher.RefreshAsync(); // Configure chat completion with AI configuration var chatCompletionConfiguration = configuration.GetSection("ChatApp:ChatCompletion").Get<ChatCompletionConfiguration>(); var requestOptions = new ChatCompletionOptions() { MaxOutputTokenCount = chatCompletionConfiguration.MaxTokens, Temperature = chatCompletionConfiguration.Temperature, TopP = chatCompletionConfiguration.TopP }; // Get latest system message from AI configuration var chatMessages = new List<ChatMessage>(GetChatMessages(chatCompletionConfiguration)); chatMessages.AddRange(chatConversation); // Get AI response and add it to chat conversation var response = await chatClient.CompleteChatAsync(chatMessages, requestOptions); string aiResponse = response.Value.Content[0].Text; Console.WriteLine($"AI: {aiResponse}"); chatConversation.Add(ChatMessage.CreateAssistantMessage(aiResponse)); Console.WriteLine(); }
After completing the previous steps, your Program.cs file should now contain the complete implementation as shown below:
using Azure.AI.OpenAI; using Azure.Identity; using Azure.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.AzureAppConfiguration; using OpenAI.Chat; TokenCredential credential = new DefaultAzureCredential(); IConfigurationRefresher refresher = null; // Load configuration from Azure App Configuration IConfiguration configuration = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { Uri endpoint = new(Environment.GetEnvironmentVariable("AZURE_APPCONFIGURATION_ENDPOINT") ?? throw new InvalidOperationException("The environment variable 'AZURE_APPCONFIGURATION_ENDPOINT' is not set or is empty.")); options.Connect(endpoint, credential) // Load all keys that start with "ChatApp:" and have no label. .Select("ChatApp:*") // Reload configuration if any selected key-values have changed. // Use the default refresh interval of 30 seconds. It can be overridden via refreshOptions.SetRefreshInterval. .ConfigureRefresh(refreshOptions => { refreshOptions.RegisterAll(); }); refresher = options.GetRefresher(); }) .Build(); // Retrieve the OpenAI connection information from the configuration Uri openaiEndpoint = new(configuration["ChatApp:AzureOpenAI:Endpoint"]); string deploymentName = configuration["ChatApp:AzureOpenAI:DeploymentName"]; // Create a chat client AzureOpenAIClient azureClient = new(openaiEndpoint, credential); ChatClient chatClient = azureClient.GetChatClient(deploymentName); // Initialize chat conversation var chatConversation = new List<ChatMessage>(); Console.WriteLine("Chat started! What's on your mind?"); while (true) { // Get user input Console.Write("You: "); string? userInput = Console.ReadLine(); // Exit if user input is empty if (string.IsNullOrEmpty(userInput)) { Console.WriteLine("Exiting chat. Goodbye!"); break; } chatConversation.Add(ChatMessage.CreateUserMessage(userInput)); // Refresh the configuration from Azure App Configuration await refresher.RefreshAsync(); // Configure chat completion with AI configuration var chatCompletionConfiguration = configuration.GetSection("ChatApp:ChatCompletion").Get<ChatCompletionConfiguration>(); var requestOptions = new ChatCompletionOptions() { MaxOutputTokenCount = chatCompletionConfiguration.MaxTokens, Temperature = chatCompletionConfiguration.Temperature, TopP = chatCompletionConfiguration.TopP }; // Get latest system message from AI configuration var chatMessages = new List<ChatMessage>(GetChatMessages(chatCompletionConfiguration)); chatMessages.AddRange(chatConversation); // Get AI response and add it to chat conversation var response = await chatClient.CompleteChatAsync(chatMessages, requestOptions); string aiResponse = response.Value.Content[0].Text; Console.WriteLine($"AI: {aiResponse}"); chatConversation.Add(ChatMessage.CreateAssistantMessage(aiResponse)); Console.WriteLine(); } // Helper method to convert configuration messages to ChatMessage objects static IEnumerable<ChatMessage> GetChatMessages(ChatCompletionConfiguration chatCompletionConfiguration) { return chatCompletionConfiguration.Messages.Select<Message, ChatMessage>(message => message.Role switch { "system" => ChatMessage.CreateSystemMessage(message.Content), "user" => ChatMessage.CreateUserMessage(message.Content), "assistant" => ChatMessage.CreateAssistantMessage(message.Content), _ => throw new ArgumentException($"Unknown role: {message.Role}", nameof(message.Role)) }); } internal class ChatCompletionConfiguration { [ConfigurationKeyName("model")] public string? Model { get; set; } [ConfigurationKeyName("messages")] public List<Message>? Messages { get; set; } [ConfigurationKeyName("max_tokens")] public int MaxTokens { get; set; } [ConfigurationKeyName("temperature")] public float Temperature { get; set; } [ConfigurationKeyName("top_p")] public float TopP { get; set; } } internal class Message { [ConfigurationKeyName("role")] public required string Role { get; set; } [ConfigurationKeyName("content")] public string? Content { get; set; } }
Build and run the app
Set the environment variable named AZURE_APPCONFIGURATION_ENDPOINT to the endpoint of your App Configuration store found under the Overview of your store in the Azure portal.
If you use the Windows command prompt, run the following command and restart the command prompt to allow the change to take effect:
setx AZURE_APPCONFIGURATION_ENDPOINT "<endpoint-of-your-app-configuration-store>"
If you use PowerShell, run the following command:
$Env:AZURE_APPCONFIGURATION_ENDPOINT = "<endpoint-of-your-app-configuration-store>"
If you use macOS or Linux run the following command:
export AZURE_APPCONFIGURATION_ENDPOINT ='<endpoint-of-your-app-configuration-store>'
After the environment variable is properly set, run the following command to build and run your app.
dotnet run
Type the message "What is your name?" when prompted with "You:" and then press the Enter key.
Chat started! What's on your mind? You: What is your name ? AI: I'm your helpful assistant! I don't have a personal name, but you can call me whatever you'd like. 😊 Do you have a name in mind?
In Azure portal, select the App Configuration store instance that you created. From the Operations menu, select Configuration explorer and select the ChatApp:ChatCompletion key. Update the value of the Messages property:
- Role: system
- Content: "You are a pirate and your name is Eddy."
Type the same message when prompted with "You:". Be sure to wait a few moments for the refresh interval to elapse, and then press the Enter key to see the updated AI response in the output.
Chat started! What's on your mind? You: What is your name ? AI: I'm your helpful assistant! I don't have a personal name, but you can call me whatever you'd like. 😊 Do you have a name in mind? You: What is your name ? AI: Arrr, matey! Me name be Eddy, the most fearsome pirate to ever sail the seven seas! What be yer name, landlubber?