-
Notifications
You must be signed in to change notification settings - Fork 79
Expand file tree
/
Copy pathmain.go
More file actions
160 lines (133 loc) · 4.98 KB
/
main.go
File metadata and controls
160 lines (133 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package main
import (
"bufio"
"context"
"fmt"
"log"
"os"
"github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
openai "github.com/openai/openai-go"
"github.com/openai/openai-go/azure"
)
type AIConfig struct {
ChatCompletion ChatCompletion
AzureOpenAI AzureOpenAI
}
type ChatCompletion struct {
Model string `json:"model"`
Messages []Message `json:"messages"`
MaxTokens int64 `json:"max_tokens"`
Temperature float64 `json:"temperature"`
TopP float64 `json:"top_p"`
}
type AzureOpenAI struct {
Endpoint string
APIVersion string
APIKey string
}
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
}
var aiConfig AIConfig
var tokenCredential, _ = azidentity.NewDefaultAzureCredential(nil)
func main() {
configProvider, err := loadAzureAppConfiguration(context.Background())
if err != nil {
log.Fatal("Error loading Azure App Configuration:", err)
}
// Configure chat completion with AI configuration
configProvider.Unmarshal(&aiConfig, &azureappconfiguration.ConstructionOptions{Separator: ":"})
// Register a callback to refresh AI configuration on changes
configProvider.OnRefreshSuccess(func() {
configProvider.Unmarshal(&aiConfig, &azureappconfiguration.ConstructionOptions{Separator: ":"})
})
// Create a chat client using API key if available, otherwise use the DefaultAzureCredential
var openAIClient openai.Client
if aiConfig.AzureOpenAI.APIKey != "" {
openAIClient = openai.NewClient(azure.WithAPIKey(aiConfig.AzureOpenAI.APIKey), azure.WithEndpoint(aiConfig.AzureOpenAI.Endpoint, aiConfig.AzureOpenAI.APIVersion))
} else {
openAIClient = openai.NewClient(azure.WithEndpoint(aiConfig.AzureOpenAI.Endpoint, aiConfig.AzureOpenAI.APIVersion), azure.WithTokenCredential(tokenCredential))
}
// Initialize chat conversation
var chatConversation []openai.ChatCompletionMessageParamUnion
fmt.Println("Chat started! What's on your mind?")
reader := bufio.NewReader(os.Stdin)
for {
// Refresh the configuration from Azure App Configuration
configProvider.Refresh(context.Background())
// Get user input
fmt.Print("You: ")
userInput, _ := reader.ReadString('\n')
// Exit if user input is empty
if userInput == "" {
fmt.Println("Exiting Chat. Goodbye!")
break
}
// Add user message to chat conversation
chatConversation = append(chatConversation, openai.UserMessage(userInput))
// Get AI response and add it to chat conversation
response, _ := getAIResponse(openAIClient, chatConversation)
fmt.Printf("AI: %s\n", response)
chatConversation = append(chatConversation, openai.AssistantMessage(response))
fmt.Println()
}
}
// Load configuration from Azure App Configuration
func loadAzureAppConfiguration(ctx context.Context) (*azureappconfiguration.AzureAppConfiguration, error) {
endpoint := os.Getenv("AZURE_APPCONFIGURATION_ENDPOINT")
if endpoint == "" {
return nil, fmt.Errorf("AZURE_APPCONFIGURATION_ENDPOINT environment variable is not set")
}
authOptions := azureappconfiguration.AuthenticationOptions{
Endpoint: endpoint,
Credential: tokenCredential,
}
options := &azureappconfiguration.Options{
Selectors: []azureappconfiguration.Selector{
// Load all keys that start with "ChatApp:" and have no label
{
KeyFilter: "ChatApp:*",
},
},
TrimKeyPrefixes: []string{"ChatApp:"},
// Reload configuration if any selected key-values have changed.
// Use the default refresh interval of 30 seconds. It can be overridden via RefreshOptions.Interval
RefreshOptions: azureappconfiguration.KeyValueRefreshOptions{
Enabled: true,
},
KeyVaultOptions: azureappconfiguration.KeyVaultOptions{
Credential: tokenCredential,
},
}
return azureappconfiguration.Load(ctx, authOptions, options)
}
func getAIResponse(openAIClient openai.Client, chatConversation []openai.ChatCompletionMessageParamUnion) (string, error) {
var completionMessages []openai.ChatCompletionMessageParamUnion
for _, msg := range aiConfig.ChatCompletion.Messages {
switch msg.Role {
case "system":
completionMessages = append(completionMessages, openai.SystemMessage(msg.Content))
case "user":
completionMessages = append(completionMessages, openai.UserMessage(msg.Content))
case "assistant":
completionMessages = append(completionMessages, openai.AssistantMessage(msg.Content))
}
}
// Add the chat conversation history
completionMessages = append(completionMessages, chatConversation...)
// Create chat completion parameters
params := openai.ChatCompletionNewParams{
Messages: completionMessages,
Model: aiConfig.ChatCompletion.Model,
MaxTokens: openai.Int(aiConfig.ChatCompletion.MaxTokens),
Temperature: openai.Float(aiConfig.ChatCompletion.Temperature),
TopP: openai.Float(aiConfig.ChatCompletion.TopP),
}
if completion, err := openAIClient.Chat.Completions.New(context.Background(), params); err != nil {
return "", err
} else {
return completion.Choices[0].Message.Content, nil
}
}