From ada9bf779da801c5c7411fa2479dbee382e8ed0e Mon Sep 17 00:00:00 2001 From: Augustinas Malinauskas Date: Sat, 27 Apr 2024 09:15:28 +0100 Subject: [PATCH] feat: temperature for completions --- Enchanted.xcodeproj/project.pbxproj | 10 ++++--- .../xcshareddata/swiftpm/Package.resolved | 30 ++++++++++++------- Enchanted/Stores/ConversationStore.swift | 4 ++- .../Models/CompletionInstructionSD.swift | 6 ++-- .../CompletionsEditorView.swift | 3 +- .../UpsertCompletionView.swift | 20 ++++++++----- .../Components/CompletionPanelView.swift | 2 +- .../PromptPanel/PanelCompletionsVM.swift | 8 ++++- .../UI/macOS/PromptPanel/PanelManager.swift | 6 +++- 9 files changed, 60 insertions(+), 29 deletions(-) diff --git a/Enchanted.xcodeproj/project.pbxproj b/Enchanted.xcodeproj/project.pbxproj index cbb46c7..c53ba53 100644 --- a/Enchanted.xcodeproj/project.pbxproj +++ b/Enchanted.xcodeproj/project.pbxproj @@ -133,6 +133,7 @@ FF38F8572B7AB1AD00546B56 /* PanelManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelManager.swift; sourceTree = ""; }; FF38F8592B7AB28300546B56 /* PromptPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromptPanelView.swift; sourceTree = ""; }; FF38F85B2B7ABC2C00546B56 /* PromptPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromptPanel.swift; sourceTree = ""; }; + FF4A605E2BC4443800D7BD4F /* OllamaKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = OllamaKit; path = ../OllamaKit; sourceTree = ""; }; FF5FA0D52B35169400BC471D /* Binding+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Binding+Extension.swift"; sourceTree = ""; }; FF66A51C2B76949A00FAAC1E /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; FF6B7B122B3EE7AC00E8FEA3 /* Throttler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Throttler.swift; sourceTree = ""; }; @@ -381,6 +382,7 @@ FFEC32842B24779A003E5C04 = { isa = PBXGroup; children = ( + FF4A605E2BC4443800D7BD4F /* OllamaKit */, FFEC328F2B24779A003E5C04 /* Enchanted */, FFEC328E2B24779A003E5C04 /* Products */, ); @@ -798,7 +800,7 @@ CODE_SIGN_ENTITLEMENTS = Enchanted/Enchanted.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 22; + CURRENT_PROJECT_VERSION = 25; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"Enchanted/Preview Content\""; DEVELOPMENT_TEAM = JDDZ55DT74; @@ -824,7 +826,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.5.9; + MARKETING_VERSION = 1.6.1; PRODUCT_BUNDLE_IDENTIFIER = subj.Enchanted; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -847,7 +849,7 @@ CODE_SIGN_ENTITLEMENTS = Enchanted/Enchanted.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 22; + CURRENT_PROJECT_VERSION = 25; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"Enchanted/Preview Content\""; DEVELOPMENT_TEAM = JDDZ55DT74; @@ -873,7 +875,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.5.9; + MARKETING_VERSION = 1.6.1; PRODUCT_BUNDLE_IDENTIFIER = subj.Enchanted; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Enchanted.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Enchanted.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3cc2e4d..8db6db2 100644 --- a/Enchanted.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Enchanted.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,4 @@ { - "originHash" : "6b50cfa02d4bf895641059b1849b6511c22d9d977d28d59a759075bbc4840fa2", "pins" : [ { "identity" : "activityindicatorview", @@ -46,15 +45,6 @@ "version" : "6.0.0" } }, - { - "identity" : "ollamakit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/AugustDev/OllamaKit", - "state" : { - "branch" : "main", - "revision" : "487bbb54e2f7dc8ea09d8542e21899376c89602d" - } - }, { "identity" : "sauce", "kind" : "remoteSourceControl", @@ -91,6 +81,24 @@ "version" : "1.1.0" } }, + { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-plugin.git", + "state" : { + "revision" : "26ac5758409154cc448d7ab82389c520fa8a8247", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-docc-symbolkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-symbolkit", + "state" : { + "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", + "version" : "1.0.0" + } + }, { "identity" : "swift-markdown-ui", "kind" : "remoteSourceControl", @@ -119,5 +127,5 @@ } } ], - "version" : 3 + "version" : 2 } diff --git a/Enchanted/Stores/ConversationStore.swift b/Enchanted/Stores/ConversationStore.swift index 7b16e12..b0224a9 100644 --- a/Enchanted/Stores/ConversationStore.swift +++ b/Enchanted/Stores/ConversationStore.swift @@ -166,7 +166,9 @@ final class ConversationStore: Sendable { if await OllamaService.shared.ollamaKit.reachable() { DispatchQueue.global(qos: .background).async { - let request = OKChatRequestData(model: model.name, messages: messageHistory) + var request = OKChatRequestData(model: model.name, messages: messageHistory) + request.options = OKCompletionOptions(temperature: 0) + self.generation = OllamaService.shared.ollamaKit.chat(data: request) .sink(receiveCompletion: { [weak self] completion in switch completion { diff --git a/Enchanted/SwiftData/Models/CompletionInstructionSD.swift b/Enchanted/SwiftData/Models/CompletionInstructionSD.swift index 29dd593..82f9943 100644 --- a/Enchanted/SwiftData/Models/CompletionInstructionSD.swift +++ b/Enchanted/SwiftData/Models/CompletionInstructionSD.swift @@ -15,16 +15,18 @@ final class CompletionInstructionSD: Identifiable { var keyboardCharacterStr: String var instruction: String var order: Int + var modelTemperature: Float? = 0.8 var keyboardCharacter: Character { keyboardCharacterStr.first ?? "x" } - init(name: String, keyboardCharacterStr: String, instruction: String, order: Int) { + init(name: String, keyboardCharacterStr: String, instruction: String, order: Int, modelTemperature: Float = 0.8) { self.name = name self.keyboardCharacterStr = keyboardCharacterStr self.instruction = instruction self.order = order + self.modelTemperature = modelTemperature } } @@ -32,7 +34,7 @@ final class CompletionInstructionSD: Identifiable { extension CompletionInstructionSD { static let samples: [CompletionInstructionSD] = [ .init(name: "Fix Grammar", keyboardCharacterStr: "f", instruction: "Fix grammar for the text below", order: 1), - .init(name: "Summarize", keyboardCharacterStr: "s", instruction: "Summarize the following text, focusing strictly on the key facts and core arguments. Exclude any model-generated politeness or introductory phrases. Provide a direct, concise summary.", order: 2), + .init(name: "Summarize", keyboardCharacterStr: "s", instruction: "Summarize the following text, focusing strictly on the key facts and core arguments. Exclude any model-generated politeness or introductory phrases. Provide a direct, concise summary in bulletpoints.", order: 2), .init(name: "Write More", keyboardCharacterStr: "w", instruction: "Elaborate on the following content, providing additional insights, examples, detailed explanations, and related concepts. Dive deeper into the topic to offer a comprehensive understanding and explore various dimensions not covered in the original text.", order: 3), .init(name: "Politely Decline", keyboardCharacterStr: "d", instruction: "Write a response politely declining the offer below", order: 4) ] diff --git a/Enchanted/UI/macOS/CompletionsEditor/CompletionsEditorView.swift b/Enchanted/UI/macOS/CompletionsEditor/CompletionsEditorView.swift index 158551c..1233899 100644 --- a/Enchanted/UI/macOS/CompletionsEditor/CompletionsEditorView.swift +++ b/Enchanted/UI/macOS/CompletionsEditor/CompletionsEditorView.swift @@ -27,7 +27,8 @@ struct CompletionsEditorView: View { name: "New Completion", keyboardCharacterStr: "x", instruction: "", - order: completions.count + order: completions.count, + modelTemperature: 0.8 ) withAnimation { completions.append(newCompletion) diff --git a/Enchanted/UI/macOS/CompletionsEditor/UpsertCompletionView.swift b/Enchanted/UI/macOS/CompletionsEditor/UpsertCompletionView.swift index 6482f28..9b59c1e 100644 --- a/Enchanted/UI/macOS/CompletionsEditor/UpsertCompletionView.swift +++ b/Enchanted/UI/macOS/CompletionsEditor/UpsertCompletionView.swift @@ -13,6 +13,7 @@ struct UpsertCompletionView: View { @State var name: String = "New Instruction" @State var prompt: String = "" @State var keyboardShortcutKey: String = "x" + @State var temperature: String = "0.8" var existingCompletion: CompletionInstructionSD? var onSave: () -> () @@ -25,6 +26,7 @@ struct UpsertCompletionView: View { _name = State(initialValue: completion.name) _prompt = State(initialValue: completion.instruction) _keyboardShortcutKey = State(initialValue: completion.keyboardCharacter.lowercased()) + _temperature = State(initialValue: String(format: "%.2f", completion.modelTemperature ?? 0.8)) } } @@ -32,6 +34,7 @@ struct UpsertCompletionView: View { existingCompletion?.name = name existingCompletion?.instruction = prompt existingCompletion?.keyboardCharacterStr = keyboardShortcutKey + existingCompletion?.modelTemperature = Float(temperature) ?? 0.8 onSave() presentationMode.wrappedValue.dismiss() } @@ -63,13 +66,13 @@ struct UpsertCompletionView: View { VStack(alignment: .trailing) { - LabeledContent("Instruction Prompt") { - TextEditor(text: $prompt) - .scrollContentBackground(.hidden) - .lineLimit(6) - .frame(height: 80) - - } + LabeledContent("Instruction Prompt") { + TextEditor(text: $prompt) + .scrollContentBackground(.hidden) + .lineLimit(6) + .frame(height: 80) + + } Text("Instruction Prompt gets appended before the selected text and together sent to the LLM.") .font(.caption) @@ -89,6 +92,9 @@ struct UpsertCompletionView: View { .font(.caption) .foregroundColor(.gray) } + + TextField("Temperature", text: $temperature) + .textFieldStyle(RoundedBorderTextFieldStyle()) } .padding(.bottom, 20) diff --git a/Enchanted/UI/macOS/Components/CompletionPanelView.swift b/Enchanted/UI/macOS/Components/CompletionPanelView.swift index ec875f8..47b82f3 100644 --- a/Enchanted/UI/macOS/Components/CompletionPanelView.swift +++ b/Enchanted/UI/macOS/Components/CompletionPanelView.swift @@ -108,7 +108,7 @@ struct PanelCompletionsView: View { case .completionsInApp: Text("Respond in **App**.") case .completionsInCurrentWindow: - Text("Respond in **Window**.") + Text("Respond in current **Window**.") } Text("SPACE") diff --git a/Enchanted/UI/macOS/PromptPanel/PanelCompletionsVM.swift b/Enchanted/UI/macOS/PromptPanel/PanelCompletionsVM.swift index c521a44..5373c83 100644 --- a/Enchanted/UI/macOS/PromptPanel/PanelCompletionsVM.swift +++ b/Enchanted/UI/macOS/PromptPanel/PanelCompletionsVM.swift @@ -44,7 +44,8 @@ final class CompletionsPanelVM { let messages: [OKChatRequestData.Message] = [ .init(role: .user, content: prompt) ] - let request = OKChatRequestData(model: model.name, messages: messages) + var request = OKChatRequestData(model: model.name, messages: messages) + request.options = OKCompletionOptions(temperature: completion.modelTemperature ?? 0.8) currentMessageBuffer = "" messageResponse = "" @@ -87,4 +88,9 @@ final class CompletionsPanelVM { private func handleComplete() { print("model response ", self.messageResponse) } + + @MainActor + func cancel() { + generation?.cancel() + } } diff --git a/Enchanted/UI/macOS/PromptPanel/PanelManager.swift b/Enchanted/UI/macOS/PromptPanel/PanelManager.swift index 09afe25..ef8f2d4 100644 --- a/Enchanted/UI/macOS/PromptPanel/PanelManager.swift +++ b/Enchanted/UI/macOS/PromptPanel/PanelManager.swift @@ -42,6 +42,10 @@ class PanelManager: NSObject, NSApplicationDelegate { for await _ in timer { // If user focused different application stop writing if lastPrintApplication != nil && lastPrintApplication?.localizedName != NSWorkspace.shared.runningApplications.first(where: {$0.isActive})?.localizedName { + // dequeue all and stop execution + await completionsPanelVM.cancel() + _ = await completionsPanelVM.sentenceQueue.dequeueAll() + lastPrintApplication = nil continue } @@ -57,8 +61,8 @@ class PanelManager: NSObject, NSApplicationDelegate { } print("printing: \((sentencesToConsume)) \(Date())") - await printer.write(sentencesToConsume) lastPrintApplication = NSWorkspace.shared.runningApplications.first{$0.isActive} + await printer.write(sentencesToConsume) } }