forked from bigcode-project/starcoder.cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathContentView.swift
More file actions
100 lines (86 loc) · 3.29 KB
/
Copy pathContentView.swift
File metadata and controls
100 lines (86 loc) · 3.29 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
//
// ContentView.swift
// StarCoder
//
// Created by Pedro Cuenca on 15/5/23.
//
import SwiftUI
import Dispatch
class ModelState: ObservableObject {
@Published var model: OpaquePointer? = nil
var modelPath: String {
Bundle.main.path(forResource: "bigcode_ggml_model", ofType: "bin")!
}
func load() {
DispatchQueue.global(qos: .userInitiated).async {
let begin = Date()
let model = load_model(self.modelPath)
DispatchQueue.main.async { self.model = model }
print("Loaded \(String(describing: model)) in \(Date().timeIntervalSince(begin))")
}
}
}
struct ContentView: View {
@State private var prompt: String = "def fibonacci("
@State private var generated: String = ""
@State private var generating: Bool = false
@State private var status: String = ""
@StateObject private var modelState = ModelState()
private var modelIsLoaded: Bool { modelState.model != nil }
func listenToNotifications() {
NotificationCenter.default.addObserver(forName: NSNotification.Name("decoded.token.received"), object: nil, queue: nil) { decoded in
generated = generated.appending(decoded.object as! String)
}
}
func complete(from text: String) {
guard let model = modelState.model else { return }
generating.toggle()
generated = text
status = ""
DispatchQueue.global(qos: .userInteractive).async {
func token_callback(char_ptr: UnsafePointer<CChar>?) {
guard let char_ptr = char_ptr else { return }
// We can't pass a "function that captures context" as a C function pointer, so we resort to posting a notification
DispatchQueue.main.async {
let str = String(cString: char_ptr)
NotificationCenter.default.post(name: NSNotification.Name("decoded.token.received"), object: str)
}
}
let msPerToken = generate(model, text, token_callback)
DispatchQueue.main.async {
status = String(format: "%.2f ms/token", msPerToken)
generating = false
}
}
}
var body: some View {
VStack {
Image("logo").resizable().aspectRatio(contentMode: .fit)
HStack {
TextField("Prompt", text: $prompt, axis: .vertical).lineLimit(2...5)
.textFieldStyle(.roundedBorder)
Button("Complete") {
complete(from: prompt)
}.buttonStyle(.borderedProminent).disabled(!modelIsLoaded)
}
Text(generated).frame(maxWidth: .infinity, alignment: .leading)//.multilineTextAlignment(.leading)
if generating {
ProgressView().padding()
}
Spacer()
if status != "" {
Text(status).font(.system(size: 14)).padding().frame(maxWidth: .infinity).background(Color(white: 0.9))
}
}
.padding()
.onAppear {
listenToNotifications()
modelState.load()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}