mirror of
https://github.com/ggerganov/llama.cpp.git
synced 2025-01-12 11:40:17 +00:00
e790eef21c
* Updated Models Layout - Added a models drawer - Added downloading directly from Hugging Face - Load custom models from local folder - Delete models by swiping left * trimmed trailing white space * Updated Models Layout
132 lines
4.7 KiB
Swift
132 lines
4.7 KiB
Swift
import SwiftUI
|
|
|
|
struct InputButton: View {
|
|
@ObservedObject var llamaState: LlamaState
|
|
@State private var inputLink: String = ""
|
|
@State private var status: String = "download"
|
|
@State private var filename: String = ""
|
|
|
|
@State private var downloadTask: URLSessionDownloadTask?
|
|
@State private var progress = 0.0
|
|
@State private var observation: NSKeyValueObservation?
|
|
|
|
private static func extractModelInfo(from link: String) -> (modelName: String, filename: String)? {
|
|
guard let url = URL(string: link),
|
|
let lastPathComponent = url.lastPathComponent.components(separatedBy: ".").first,
|
|
let modelName = lastPathComponent.components(separatedBy: "-").dropLast().joined(separator: "-").removingPercentEncoding,
|
|
let filename = lastPathComponent.removingPercentEncoding else {
|
|
return nil
|
|
}
|
|
|
|
return (modelName, filename)
|
|
}
|
|
|
|
private static func getFileURL(filename: String) -> URL {
|
|
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(filename)
|
|
}
|
|
|
|
private func download() {
|
|
guard let extractedInfo = InputButton.extractModelInfo(from: inputLink) else {
|
|
// Handle invalid link or extraction failure
|
|
return
|
|
}
|
|
|
|
let (modelName, filename) = extractedInfo
|
|
self.filename = filename // Set the state variable
|
|
|
|
status = "downloading"
|
|
print("Downloading model \(modelName) from \(inputLink)")
|
|
guard let url = URL(string: inputLink) else { return }
|
|
let fileURL = InputButton.getFileURL(filename: filename)
|
|
|
|
downloadTask = URLSession.shared.downloadTask(with: url) { temporaryURL, response, error in
|
|
if let error = error {
|
|
print("Error: \(error.localizedDescription)")
|
|
return
|
|
}
|
|
|
|
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
|
|
print("Server error!")
|
|
return
|
|
}
|
|
|
|
do {
|
|
if let temporaryURL = temporaryURL {
|
|
try FileManager.default.copyItem(at: temporaryURL, to: fileURL)
|
|
print("Writing to \(filename) completed")
|
|
|
|
llamaState.cacheCleared = false
|
|
|
|
let model = Model(name: modelName, url: self.inputLink, filename: filename, status: "downloaded")
|
|
llamaState.downloadedModels.append(model)
|
|
status = "downloaded"
|
|
}
|
|
} catch let err {
|
|
print("Error: \(err.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
observation = downloadTask?.progress.observe(\.fractionCompleted) { progress, _ in
|
|
self.progress = progress.fractionCompleted
|
|
}
|
|
|
|
downloadTask?.resume()
|
|
}
|
|
|
|
var body: some View {
|
|
VStack {
|
|
HStack {
|
|
TextField("Paste Quantized Download Link", text: $inputLink)
|
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
|
|
|
Button(action: {
|
|
downloadTask?.cancel()
|
|
status = "download"
|
|
}) {
|
|
Text("Cancel")
|
|
}
|
|
}
|
|
|
|
if status == "download" {
|
|
Button(action: download) {
|
|
Text("Download Custom Model")
|
|
}
|
|
} else if status == "downloading" {
|
|
Button(action: {
|
|
downloadTask?.cancel()
|
|
status = "download"
|
|
}) {
|
|
Text("Downloading \(Int(progress * 100))%")
|
|
}
|
|
} else if status == "downloaded" {
|
|
Button(action: {
|
|
let fileURL = InputButton.getFileURL(filename: self.filename)
|
|
if !FileManager.default.fileExists(atPath: fileURL.path) {
|
|
download()
|
|
return
|
|
}
|
|
do {
|
|
try llamaState.loadModel(modelUrl: fileURL)
|
|
} catch let err {
|
|
print("Error: \(err.localizedDescription)")
|
|
}
|
|
}) {
|
|
Text("Load Custom Model")
|
|
}
|
|
} else {
|
|
Text("Unknown status")
|
|
}
|
|
}
|
|
.onDisappear() {
|
|
downloadTask?.cancel()
|
|
}
|
|
.onChange(of: llamaState.cacheCleared) { newValue in
|
|
if newValue {
|
|
downloadTask?.cancel()
|
|
let fileURL = InputButton.getFileURL(filename: self.filename)
|
|
status = FileManager.default.fileExists(atPath: fileURL.path) ? "downloaded" : "download"
|
|
}
|
|
}
|
|
}
|
|
}
|