|
1 | 1 | // Copyright (c) Microsoft Corporation. |
2 | 2 | // Licensed under the MIT license. |
3 | 3 | // |
| 4 | + |
4 | 5 | using Azure.AI.OpenAI; |
5 | 6 | using Azure.Core; |
6 | 7 | using Azure.Identity; |
|
16 | 17 | IConfiguration configuration = new ConfigurationBuilder() |
17 | 18 | .AddAzureAppConfiguration(options => |
18 | 19 | { |
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.")); |
| 20 | + Uri endpoint = new(Environment.GetEnvironmentVariable("AZURE_APPCONFIGURATION_ENDPOINT") ?? |
| 21 | + throw new InvalidOperationException("The environment variable 'AZURE_APPCONFIGURATION_ENDPOINT' is not set or is empty.")); |
21 | 22 | options.Connect(endpoint, credential) |
22 | 23 | // Load all keys that start with "ChatApp:" and have no label. |
23 | 24 | .Select("ChatApp:*") |
|
26 | 27 | .ConfigureRefresh(refreshOptions => |
27 | 28 | { |
28 | 29 | refreshOptions.RegisterAll(); |
| 30 | + }) |
| 31 | + .ConfigureKeyVault(keyVaultOptions => |
| 32 | + { |
| 33 | + // Use the DefaultAzureCredential to access Key Vault secrets. |
| 34 | + keyVaultOptions.SetCredential(credential); |
29 | 35 | }); |
30 | 36 |
|
31 | 37 | refresher = options.GetRefresher(); |
32 | 38 | }) |
33 | 39 | .Build(); |
34 | 40 |
|
35 | 41 | // Retrieve the OpenAI connection information from the configuration |
36 | | -Uri openaiEndpoint = new (configuration["ChatApp:AzureOpenAI:Endpoint"]); |
37 | | -string deploymentName = configuration["ChatApp:AzureOpenAI:DeploymentName"]; |
| 42 | +var azureOpenAIConfiguration = configuration.GetSection("ChatApp:AzureOpenAI").Get<AzureOpenAIConfiguration>(); |
38 | 43 |
|
39 | | -// Create a chat client |
40 | | -AzureOpenAIClient azureClient = new(openaiEndpoint, credential); |
41 | | -ChatClient chatClient = azureClient.GetChatClient(deploymentName); |
| 44 | +// Create a chat client using API key if available, otherwise use the DefaultAzureCredential |
| 45 | +AzureOpenAIClient azureClient; |
| 46 | +if (!string.IsNullOrEmpty(azureOpenAIConfiguration.ApiKey)) |
| 47 | +{ |
| 48 | + azureClient = new AzureOpenAIClient(new Uri(azureOpenAIConfiguration.Endpoint), new Azure.AzureKeyCredential(azureOpenAIConfiguration.ApiKey)); |
| 49 | +} |
| 50 | +else |
| 51 | +{ |
| 52 | + azureClient = new AzureOpenAIClient(new Uri(azureOpenAIConfiguration.Endpoint), credential); |
| 53 | +} |
| 54 | +ChatClient chatClient = azureClient.GetChatClient(azureOpenAIConfiguration.DeploymentName); |
42 | 55 |
|
| 56 | +// Initialize chat conversation |
| 57 | +var chatConversation = new List<ChatMessage>(); |
| 58 | +Console.WriteLine("Chat started! What's on your mind?"); |
43 | 59 | while (true) |
44 | 60 | { |
45 | 61 | // Refresh the configuration from Azure App Configuration |
46 | 62 | await refresher.TryRefreshAsync(); |
47 | 63 |
|
48 | 64 | // Configure chat completion with AI configuration |
49 | | - var modelConfiguration = configuration.GetSection("ChatApp:Model").Get<ModelConfiguration>(); |
| 65 | + var chatCompletionConfiguration = configuration.GetSection("ChatApp:ChatCompletion").Get<ChatCompletionConfiguration>(); |
50 | 66 | var requestOptions = new ChatCompletionOptions() |
51 | 67 | { |
52 | | - MaxOutputTokenCount = modelConfiguration.MaxTokens, |
53 | | - Temperature = modelConfiguration.Temperature, |
54 | | - TopP = modelConfiguration.TopP |
| 68 | + MaxOutputTokenCount = chatCompletionConfiguration.MaxTokens, |
| 69 | + Temperature = chatCompletionConfiguration.Temperature, |
| 70 | + TopP = chatCompletionConfiguration.TopP |
55 | 71 | }; |
56 | 72 |
|
57 | | - foreach (var message in modelConfiguration.Messages) |
| 73 | + // Get user input |
| 74 | + Console.Write("You: "); |
| 75 | + string? userInput = Console.ReadLine(); |
| 76 | + |
| 77 | + // Exit if user input is empty |
| 78 | + if (string.IsNullOrEmpty(userInput)) |
58 | 79 | { |
59 | | - Console.WriteLine($"{message.Role}: {message.Content}"); |
| 80 | + Console.WriteLine("Exiting chat. Goodbye!"); |
| 81 | + break; |
60 | 82 | } |
61 | 83 |
|
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}"); |
| 84 | + // Add user message to chat conversation |
| 85 | + chatConversation.Add(ChatMessage.CreateUserMessage(userInput)); |
| 86 | + |
| 87 | + // Get latest system message from AI configuration |
| 88 | + var chatMessages = new List<ChatMessage>(GetChatMessages(chatCompletionConfiguration)); |
| 89 | + chatMessages.AddRange(chatConversation); |
| 90 | + |
| 91 | + // Get AI response and add it to chat conversation |
| 92 | + var response = await chatClient.CompleteChatAsync(chatMessages, requestOptions); |
| 93 | + string aiResponse = response.Value.Content[0].Text; |
| 94 | + Console.WriteLine($"AI: {aiResponse}"); |
| 95 | + chatConversation.Add(ChatMessage.CreateAssistantMessage(aiResponse)); |
65 | 96 |
|
66 | | - Console.WriteLine("Press Enter to continue..."); |
67 | | - Console.ReadLine(); |
| 97 | + Console.WriteLine(); |
68 | 98 | } |
69 | 99 |
|
70 | | -static IEnumerable<ChatMessage> GetChatMessages(ModelConfiguration modelConfiguration) |
| 100 | +// Helper method to convert configuration messages to ChatMessage objects |
| 101 | +static IEnumerable<ChatMessage> GetChatMessages(ChatCompletionConfiguration chatCompletionConfiguration) |
71 | 102 | { |
72 | | - return modelConfiguration.Messages.Select<Message, ChatMessage>(message => message.Role switch |
| 103 | + return chatCompletionConfiguration.Messages.Select<Message, ChatMessage>(message => message.Role switch |
73 | 104 | { |
74 | 105 | "system" => ChatMessage.CreateSystemMessage(message.Content), |
75 | 106 | "user" => ChatMessage.CreateUserMessage(message.Content), |
|
0 commit comments