|
|
@@ -2,115 +2,57 @@ import SwiftUI
|
|
|
|
|
|
struct ContentView: View {
|
|
|
@StateObject var llamaState = LlamaState()
|
|
|
-
|
|
|
@State private var multiLineText = ""
|
|
|
-
|
|
|
- private static func cleanupModelCaches() {
|
|
|
- // Delete all models (*.gguf)
|
|
|
- let fileManager = FileManager.default
|
|
|
- let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
|
|
- do {
|
|
|
- let fileURLs = try fileManager.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil)
|
|
|
- for fileURL in fileURLs {
|
|
|
- if fileURL.pathExtension == "gguf" {
|
|
|
- try fileManager.removeItem(at: fileURL)
|
|
|
- }
|
|
|
- }
|
|
|
- } catch {
|
|
|
- print("Error while enumerating files \(documentsUrl.path): \(error.localizedDescription)")
|
|
|
- }
|
|
|
- }
|
|
|
+ @State private var showingHelp = false // To track if Help Sheet should be shown
|
|
|
|
|
|
var body: some View {
|
|
|
- VStack {
|
|
|
- ScrollView(.vertical, showsIndicators: true) {
|
|
|
- Text(llamaState.messageLog)
|
|
|
- .font(.system(size: 12))
|
|
|
- .frame(maxWidth: .infinity, alignment: .leading)
|
|
|
- .padding()
|
|
|
- .onTapGesture {
|
|
|
- UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
|
|
+ NavigationView {
|
|
|
+ VStack {
|
|
|
+ ScrollView(.vertical, showsIndicators: true) {
|
|
|
+ Text(llamaState.messageLog)
|
|
|
+ .font(.system(size: 12))
|
|
|
+ .frame(maxWidth: .infinity, alignment: .leading)
|
|
|
+ .padding()
|
|
|
+ .onTapGesture {
|
|
|
+ UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- TextEditor(text: $multiLineText)
|
|
|
- .frame(height: 80)
|
|
|
- .padding()
|
|
|
- .border(Color.gray, width: 0.5)
|
|
|
+ TextEditor(text: $multiLineText)
|
|
|
+ .frame(height: 80)
|
|
|
+ .padding()
|
|
|
+ .border(Color.gray, width: 0.5)
|
|
|
|
|
|
- HStack {
|
|
|
- Button("Send") {
|
|
|
- sendText()
|
|
|
- }
|
|
|
+ HStack {
|
|
|
+ Button("Send") {
|
|
|
+ sendText()
|
|
|
+ }
|
|
|
|
|
|
- Button("Bench") {
|
|
|
- bench()
|
|
|
- }
|
|
|
+ Button("Bench") {
|
|
|
+ bench()
|
|
|
+ }
|
|
|
|
|
|
- Button("Clear") {
|
|
|
- clear()
|
|
|
- }
|
|
|
+ Button("Clear") {
|
|
|
+ clear()
|
|
|
+ }
|
|
|
|
|
|
- Button("Copy") {
|
|
|
- UIPasteboard.general.string = llamaState.messageLog
|
|
|
+ Button("Copy") {
|
|
|
+ UIPasteboard.general.string = llamaState.messageLog
|
|
|
+ }
|
|
|
}
|
|
|
- }.buttonStyle(.bordered)
|
|
|
-
|
|
|
- VStack(alignment: .leading) {
|
|
|
- DownloadButton(
|
|
|
- llamaState: llamaState,
|
|
|
- modelName: "TinyLlama-1.1B (Q4_0, 0.6 GiB)",
|
|
|
- modelUrl: "https://huggingface.co/TheBloke/TinyLlama-1.1B-1T-OpenOrca-GGUF/resolve/main/tinyllama-1.1b-1t-openorca.Q4_0.gguf?download=true",
|
|
|
- filename: "tinyllama-1.1b-1t-openorca.Q4_0.gguf"
|
|
|
- )
|
|
|
-
|
|
|
- DownloadButton(
|
|
|
- llamaState: llamaState,
|
|
|
- modelName: "TinyLlama-1.1B (Q8_0, 1.1 GiB)",
|
|
|
- modelUrl: "https://huggingface.co/TheBloke/TinyLlama-1.1B-1T-OpenOrca-GGUF/resolve/main/tinyllama-1.1b-1t-openorca.Q8_0.gguf?download=true",
|
|
|
- filename: "tinyllama-1.1b-1t-openorca.Q8_0.gguf"
|
|
|
- )
|
|
|
-
|
|
|
- DownloadButton(
|
|
|
- llamaState: llamaState,
|
|
|
- modelName: "TinyLlama-1.1B (F16, 2.2 GiB)",
|
|
|
- modelUrl: "https://huggingface.co/ggml-org/models/resolve/main/tinyllama-1.1b/ggml-model-f16.gguf?download=true",
|
|
|
- filename: "tinyllama-1.1b-f16.gguf"
|
|
|
- )
|
|
|
-
|
|
|
- DownloadButton(
|
|
|
- llamaState: llamaState,
|
|
|
- modelName: "Phi-2.7B (Q4_0, 1.6 GiB)",
|
|
|
- modelUrl: "https://huggingface.co/ggml-org/models/resolve/main/phi-2/ggml-model-q4_0.gguf?download=true",
|
|
|
- filename: "phi-2-q4_0.gguf"
|
|
|
- )
|
|
|
-
|
|
|
- DownloadButton(
|
|
|
- llamaState: llamaState,
|
|
|
- modelName: "Phi-2.7B (Q8_0, 2.8 GiB)",
|
|
|
- modelUrl: "https://huggingface.co/ggml-org/models/resolve/main/phi-2/ggml-model-q8_0.gguf?download=true",
|
|
|
- filename: "phi-2-q8_0.gguf"
|
|
|
- )
|
|
|
-
|
|
|
- DownloadButton(
|
|
|
- llamaState: llamaState,
|
|
|
- modelName: "Mistral-7B-v0.1 (Q4_0, 3.8 GiB)",
|
|
|
- modelUrl: "https://huggingface.co/TheBloke/Mistral-7B-v0.1-GGUF/resolve/main/mistral-7b-v0.1.Q4_0.gguf?download=true",
|
|
|
- filename: "mistral-7b-v0.1.Q4_0.gguf"
|
|
|
- )
|
|
|
-
|
|
|
- Button("Clear downloaded models") {
|
|
|
- ContentView.cleanupModelCaches()
|
|
|
- llamaState.cacheCleared = true
|
|
|
+ .buttonStyle(.bordered)
|
|
|
+ .padding()
|
|
|
+
|
|
|
+ NavigationLink(destination: DrawerView(llamaState: llamaState)) {
|
|
|
+ Text("View Models")
|
|
|
}
|
|
|
+ .padding()
|
|
|
|
|
|
- LoadCustomButton(llamaState: llamaState)
|
|
|
}
|
|
|
- .padding(.top, 4)
|
|
|
- .font(.system(size: 12))
|
|
|
- .frame(maxWidth: .infinity, alignment: .leading)
|
|
|
+ .padding()
|
|
|
+ .navigationBarTitle("Model Settings", displayMode: .inline)
|
|
|
+
|
|
|
}
|
|
|
- .padding()
|
|
|
}
|
|
|
|
|
|
func sendText() {
|
|
|
@@ -131,8 +73,73 @@ struct ContentView: View {
|
|
|
await llamaState.clear()
|
|
|
}
|
|
|
}
|
|
|
+ struct DrawerView: View {
|
|
|
+
|
|
|
+ @ObservedObject var llamaState: LlamaState
|
|
|
+ @State private var showingHelp = false
|
|
|
+ func delete(at offsets: IndexSet) {
|
|
|
+ offsets.forEach { offset in
|
|
|
+ let model = llamaState.downloadedModels[offset]
|
|
|
+ let fileURL = getDocumentsDirectory().appendingPathComponent(model.filename)
|
|
|
+ do {
|
|
|
+ try FileManager.default.removeItem(at: fileURL)
|
|
|
+ } catch {
|
|
|
+ print("Error deleting file: \(error)")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Remove models from downloadedModels array
|
|
|
+ llamaState.downloadedModels.remove(atOffsets: offsets)
|
|
|
+ }
|
|
|
+
|
|
|
+ func getDocumentsDirectory() -> URL {
|
|
|
+ let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
|
|
+ return paths[0]
|
|
|
+ }
|
|
|
+ var body: some View {
|
|
|
+ List {
|
|
|
+ Section(header: Text("Download Models From Hugging Face")) {
|
|
|
+ HStack {
|
|
|
+ InputButton(llamaState: llamaState)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Section(header: Text("Downloaded Models")) {
|
|
|
+ ForEach(llamaState.downloadedModels) { model in
|
|
|
+ DownloadButton(llamaState: llamaState, modelName: model.name, modelUrl: model.url, filename: model.filename)
|
|
|
+ }
|
|
|
+ .onDelete(perform: delete)
|
|
|
+ }
|
|
|
+ Section(header: Text("Default Models")) {
|
|
|
+ ForEach(llamaState.undownloadedModels) { model in
|
|
|
+ DownloadButton(llamaState: llamaState, modelName: model.name, modelUrl: model.url, filename: model.filename)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ .listStyle(GroupedListStyle())
|
|
|
+ .navigationBarTitle("Model Settings", displayMode: .inline).toolbar {
|
|
|
+ ToolbarItem(placement: .navigationBarTrailing) {
|
|
|
+ Button("Help") {
|
|
|
+ showingHelp = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }.sheet(isPresented: $showingHelp) { // Sheet for help modal
|
|
|
+ VStack(alignment: .leading) {
|
|
|
+ VStack(alignment: .leading) {
|
|
|
+ Text("1. Make sure the model is in GGUF Format")
|
|
|
+ .padding()
|
|
|
+ Text("2. Copy the download link of the quantized model")
|
|
|
+ .padding()
|
|
|
+ }
|
|
|
+ Spacer()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-//#Preview {
|
|
|
-// ContentView()
|
|
|
-//}
|
|
|
+struct ContentView_Previews: PreviewProvider {
|
|
|
+ static var previews: some View {
|
|
|
+ ContentView()
|
|
|
+ }
|
|
|
+}
|