forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOpenAIView.swift
More file actions
119 lines (110 loc) · 4.22 KB
/
Copy pathOpenAIView.swift
File metadata and controls
119 lines (110 loc) · 4.22 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
import AppKit
import Client
import OpenAIService
import Preferences
import SuggestionModel
import SwiftUI
struct OpenAIView: View {
final class Settings: ObservableObject {
@AppStorage(\.openAIAPIKey) var openAIAPIKey: String
@AppStorage(\.chatGPTModel) var chatGPTModel: String
@AppStorage(\.embeddingModel) var embeddingModel: String
@AppStorage(\.openAIBaseURL) var openAIBaseURL: String
init() {}
}
let apiKeyURL = URL(string: "https://platform.openai.com/account/api-keys")!
let modelURL = URL(
string: "https://platform.openai.com/docs/models/model-endpoint-compatibility"
)!
@Environment(\.openURL) var openURL
@Environment(\.toast) var toast
@State var isTesting = false
@StateObject var settings = Settings()
var body: some View {
Form {
HStack {
SecureField(text: $settings.openAIAPIKey, prompt: Text("sk-*")) {
Text("OpenAI API Key")
}
.textFieldStyle(.roundedBorder)
Button(action: {
openURL(apiKeyURL)
}) {
Image(systemName: "questionmark.circle.fill")
}.buttonStyle(.plain)
}
HStack {
TextField(
text: $settings.openAIBaseURL,
prompt: Text("https://api.openai.com")
) {
Text("OpenAI Base URL")
}.textFieldStyle(.roundedBorder)
Button("Test") {
Task { @MainActor in
isTesting = true
defer { isTesting = false }
do {
let reply =
try await ChatGPTService(
configuration: UserPreferenceChatGPTConfiguration()
.overriding(.init(featureProvider: .openAI))
)
.sendAndWait(content: "Hello", summary: nil)
toast("ChatGPT replied: \(reply ?? "N/A")", .info)
} catch {
toast(error.localizedDescription, .error)
}
}
}.disabled(isTesting)
}
HStack {
Picker(selection: $settings.chatGPTModel) {
if !settings.chatGPTModel.isEmpty,
ChatGPTModel(rawValue: settings.chatGPTModel) == nil
{
Text(settings.chatGPTModel).tag(settings.chatGPTModel)
}
ForEach(ChatGPTModel.allCases, id: \.self) { model in
Text(model.rawValue).tag(model.rawValue)
}
} label: {
Text("ChatGPT Model")
}.pickerStyle(.menu)
Button(action: {
openURL(modelURL)
}) {
Image(systemName: "questionmark.circle.fill")
}.buttonStyle(.plain)
}
HStack {
Picker(selection: $settings.embeddingModel) {
if !settings.embeddingModel.isEmpty,
OpenAIEmbeddingModel(rawValue: settings.embeddingModel) == nil
{
Text(settings.embeddingModel).tag(settings.embeddingModel)
}
ForEach(OpenAIEmbeddingModel.allCases, id: \.self) { model in
Text(model.rawValue).tag(model.rawValue)
}
} label: {
Text("Embedding Model")
}.pickerStyle(.menu)
Button(action: {
openURL(modelURL)
}) {
Image(systemName: "questionmark.circle.fill")
}.buttonStyle(.plain)
}
}
}
}
struct OpenAIView_Previews: PreviewProvider {
static var previews: some View {
VStack(alignment: .leading, spacing: 8) {
OpenAIView()
}
.frame(height: 800)
.padding(.all, 8)
}
}