From 3e9affb18c9de0dde367e29ab61c56de6c13050f Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Wed, 18 Sep 2024 16:56:22 -0700 Subject: [PATCH 01/13] rebase --- binding/ios/PicoLLM.swift | 29 +++++++++++++++++++++++------ binding/ios/picoLLM-iOS.podspec | 4 ++-- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/binding/ios/PicoLLM.swift b/binding/ios/PicoLLM.swift index 96e5c3b6..80044bb2 100644 --- a/binding/ios/PicoLLM.swift +++ b/binding/ios/PicoLLM.swift @@ -9,7 +9,7 @@ import PvPicoLLM -// Usage information. +/// Usage information. public struct PicoLLMUsage: Codable { public let promptTokens: Int @@ -23,11 +23,12 @@ public struct PicoLLMUsage: Codable { } } -// Reasons for ending the generation process. +/// Reasons for ending the generation process. public enum PicoLLMEndpoint: Codable { case endOfSentence case completionTokenLimitReached case stopPhraseEncountered + case interrupted public static func fromC(cEndpoint: pv_picollm_endpoint_t) -> PicoLLMEndpoint? { switch cEndpoint { @@ -37,13 +38,15 @@ public enum PicoLLMEndpoint: Codable { return PicoLLMEndpoint.completionTokenLimitReached case PV_PICOLLM_ENDPOINT_STOP_PHRASE_ENCOUNTERED: return PicoLLMEndpoint.stopPhraseEncountered + case PV_PICOLLM_ENDPOINT_INTERRUPTED: + return PicoLLMEndpoint.interrupted default: return nil } } } -// Generated token and its log probability. +/// Generated token and its log probability. public struct PicoLLMToken: Codable { public let token: String @@ -57,7 +60,7 @@ public struct PicoLLMToken: Codable { } } -// Generated token within completion and top alternative tokens. +/// Generated token within completion and top alternative tokens. public struct PicoLLMCompletionToken: Codable { public let token: PicoLLMToken @@ -71,7 +74,7 @@ public struct PicoLLMCompletionToken: Codable { } } -// Result object containing stats and generated tokens. +/// Result object containing stats and generated tokens. public struct PicoLLMCompletion: Codable { public let usage: PicoLLMUsage @@ -93,7 +96,7 @@ public struct PicoLLMCompletion: Codable { } } -// Private callback for hoisting C callback into Swift callback. +/// Private callback for hoisting C callback into Swift callback. func cStreamCallback (completion: UnsafePointer?, context: UnsafeMutableRawPointer?) { let object = Unmanaged.fromOpaque(context!).takeUnretainedValue() @@ -312,6 +315,20 @@ public class PicoLLM { completion: completion) } + /// Interrupts `pv_picollm_generate()` if generation is in progress. Otherwise, it has no effect. + /// - Throws: PicoLLMError + public func interrupt() throws { + if handle == nil { + throw PicoLLMInvalidStateError("PicoLLM must be initialized before calling interrupt") + } + + let status = pv_picollm_interrupt(self.handle) + if status != PV_STATUS_SUCCESS { + let messageStack = try PicoLLM.getMessageStack() + throw PicoLLM.pvStatusToPicoLLMError(status, "PicoLLM interrupt failed", messageStack) + } + } + /// Tokenizes a given text using the model's tokenizer. /// This is a low-level function meant for benchmarking and advanced usage. /// `.generate()` should be used when possible. diff --git a/binding/ios/picoLLM-iOS.podspec b/binding/ios/picoLLM-iOS.podspec index bee6392e..96ad60b3 100644 --- a/binding/ios/picoLLM-iOS.podspec +++ b/binding/ios/picoLLM-iOS.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'picoLLM-iOS' s.module_name = 'PicoLLM' - s.version = '1.0.0' + s.version = '1.2.0' s.license = {:type => 'Apache 2.0'} s.summary = 'picoLLM Inference Engine' s.description = @@ -10,7 +10,7 @@ Pod::Spec.new do |s| DESC s.homepage = 'https://github.com/Picovoice/picollm/tree/master/binding/ios' s.author = { 'Picovoice' => 'hello@picovoice.ai' } - s.source = { :git => "https://github.com/Picovoice/picollm.git", :tag => "picoLLM-iOS-v1.0.0" } + s.source = { :git => "https://github.com/Picovoice/picollm.git", :tag => "picoLLM-iOS-v1.1.0" } s.ios.deployment_target = '16.0' s.swift_version = '5.0' s.vendored_frameworks = 'lib/ios/PvPicoLLM.xcframework' From 00e55a4aacd8b5496b3fff9992cb6319da6aba9b Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Thu, 12 Sep 2024 17:20:40 -0700 Subject: [PATCH 02/13] correct podspec --- binding/ios/picoLLM-iOS.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/ios/picoLLM-iOS.podspec b/binding/ios/picoLLM-iOS.podspec index 96ad60b3..f17d0a87 100644 --- a/binding/ios/picoLLM-iOS.podspec +++ b/binding/ios/picoLLM-iOS.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'picoLLM-iOS' s.module_name = 'PicoLLM' - s.version = '1.2.0' + s.version = '1.1.0' s.license = {:type => 'Apache 2.0'} s.summary = 'picoLLM Inference Engine' s.description = From e8ff1a88179fb5cc555f43af2d161f3965209c16 Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Fri, 13 Sep 2024 11:33:33 -0700 Subject: [PATCH 03/13] demo --- .../CompletionView.swift | 23 +++++++++---------- .../PicoLLMCompletionDemo/ViewModel.swift | 17 +++++++++++--- demo/ios/Completion/Podfile | 2 +- demo/ios/Completion/Podfile.lock | 16 ++++++------- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/demo/ios/Completion/PicoLLMCompletionDemo/CompletionView.swift b/demo/ios/Completion/PicoLLMCompletionDemo/CompletionView.swift index 904dc4c6..16485303 100644 --- a/demo/ios/Completion/PicoLLMCompletionDemo/CompletionView.swift +++ b/demo/ios/Completion/PicoLLMCompletionDemo/CompletionView.swift @@ -28,7 +28,7 @@ struct CompletionView: View { .padding(.horizontal, 12) } ) - .disabled(!viewModel.enableGenerateButton) + .disabled(viewModel.isGenerating) Spacer() Text("picoLLM Completion Demo") Spacer() @@ -41,7 +41,7 @@ struct CompletionView: View { Spacer() HStack(alignment: .center) { - if !viewModel.enableGenerateButton { + if viewModel.isGenerating { ProgressView(value: 0).progressViewStyle(CircularProgressViewStyle()) Text("Generating...") .padding(.horizontal, 12) @@ -72,20 +72,19 @@ struct CompletionView: View { .onSubmit { viewModel.generate() } - .disabled(!viewModel.enableGenerateButton) + .disabled(viewModel.isGenerating) HStack(alignment: .center) { Spacer() - Button(action: viewModel.generate) { - Image(systemName: "arrow.up") + Button(action: viewModel.isGenerating ? viewModel.interrupt : viewModel.generate) { + Image(systemName: viewModel.isGenerating ? "stop.fill" : "arrow.up") .imageScale(.medium) - .background(Constants.btnColor(viewModel.enableGenerateButton)) + .background(Constants.activeBlue) .foregroundColor(.white) .padding(6) }.background( - Capsule().fill(Constants.btnColor(viewModel.enableGenerateButton)) + Capsule().fill(Constants.activeBlue) ) .padding(.horizontal, 4) - .disabled(!viewModel.enableGenerateButton) } } .padding(.vertical, 12) @@ -102,7 +101,7 @@ struct CompletionView: View { VStack { ScrollViewReader { proxy in ScrollView { - if showStats && viewModel.enableGenerateButton { + if showStats && !viewModel.isGenerating { Text(viewModel.statsText) .padding(12) } else { @@ -128,14 +127,14 @@ struct CompletionView: View { .imageScale(.large) } .padding(.horizontal, 12) - .disabled(!viewModel.enableGenerateButton) + .disabled(viewModel.isGenerating) Spacer() Button( action: {() in showStats = !showStats}, label: { Image(systemName: "chevron.left") .imageScale(.small) - if showStats && viewModel.enableGenerateButton { + if showStats && !viewModel.isGenerating { Text("/") } else { Text(" ") @@ -147,7 +146,7 @@ struct CompletionView: View { .padding(.horizontal, 12) .disabled( viewModel.errorMessage.count > 0 || - !viewModel.enableGenerateButton || + viewModel.isGenerating || viewModel.completionText.isEmpty) } .padding(.bottom, 12) diff --git a/demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift b/demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift index dd10a701..1dfaf7f8 100644 --- a/demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift +++ b/demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift @@ -40,7 +40,7 @@ You can download directly to your device or airdrop from a Mac. @Published var generatePresencePenalty = 0.0 @Published var generateFrequencyPenalty = 0.0 @Published var generateNumTopChoices = 0.0 - @Published var enableGenerateButton = true + @Published var isGenerating = false @Published var completionPromptText = "" @Published var completionText = "" @@ -140,7 +140,7 @@ You can download directly to your device or airdrop from a Mac. return } - enableGenerateButton = false + isGenerating = true completionPromptText = promptText completionText = "" tpsText = "" @@ -171,7 +171,18 @@ You can download directly to your device or airdrop from a Mac. DispatchQueue.main.async { [self] in promptText = "" - enableGenerateButton = true + isGenerating = false + } + } + } + + public func interrupt() { + do { + try picollm?.interrupt(); + } catch { + DispatchQueue.main.async { [self] in + errorMessage = "\(error.localizedDescription)" + enableLoadModelButton = true } } } diff --git a/demo/ios/Completion/Podfile b/demo/ios/Completion/Podfile index c233ec56..5c71c4f5 100644 --- a/demo/ios/Completion/Podfile +++ b/demo/ios/Completion/Podfile @@ -2,5 +2,5 @@ source 'https://cdn.cocoapods.org/' platform :ios, '16.0' target 'PicoLLMCompletionDemo' do - pod 'picoLLM-iOS', '~> 1.0.0' + pod 'picoLLM-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec' end diff --git a/demo/ios/Completion/Podfile.lock b/demo/ios/Completion/Podfile.lock index 91961390..302dc4b7 100644 --- a/demo/ios/Completion/Podfile.lock +++ b/demo/ios/Completion/Podfile.lock @@ -1,16 +1,16 @@ PODS: - - picoLLM-iOS (1.0.0) + - picoLLM-iOS (1.2.0) DEPENDENCIES: - - picoLLM-iOS (~> 1.0.0) + - picoLLM-iOS (from `https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec`) -SPEC REPOS: - trunk: - - picoLLM-iOS +EXTERNAL SOURCES: + picoLLM-iOS: + :podspec: https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec SPEC CHECKSUMS: - picoLLM-iOS: 02cdb501b4beb74a9c1dea29d5cf461d65ea4a6c + picoLLM-iOS: 9cc5d0743d1bc856aeabe6c773889d72e884cbee -PODFILE CHECKSUM: 0f0318dbd90bfa46ae09b74d92d7e21912583c46 +PODFILE CHECKSUM: d5764505a13214074d2e9db975f4c26fd5c720be -COCOAPODS: 1.15.2 +COCOAPODS: 1.11.3 From 2072ec5a1fab1f7c12e41d36f02405bcf7554fd4 Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Wed, 18 Sep 2024 17:02:59 -0700 Subject: [PATCH 04/13] actions --- .github/workflows/ios-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ios-tests.yml b/.github/workflows/ios-tests.yml index 6fa46146..9ce32958 100644 --- a/.github/workflows/ios-tests.yml +++ b/.github/workflows/ios-tests.yml @@ -36,7 +36,7 @@ jobs: PicoLLMAppTestUITests/BaseTest.swift - name: Inject Resource URL - run: sed -i '.bak' 's?{TESTING_MODEL_URL_HERE}?http://${{secrets.PV_CICD_RES_SERVER_AUTHORITY}}/github/picollm/res/phi2-290.pllm/latest/phi2-290.pllm?' + run: sed -i '.bak' 's?{TESTING_MODEL_URL_HERE}?http://${{secrets.PV_CICD_RES_SERVER_AUTHORITY}}/github/picollm/res/phi2-290.pllm/03-280e68c/phi2-290.pllm?' PicoLLMAppTestUITests/BaseTest.swift - name: XCode Build From 467c99f5398a7b454eee679db6631dd50041ca96 Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Wed, 18 Sep 2024 17:13:10 -0700 Subject: [PATCH 05/13] add phi3 dialog --- binding/ios/PicoLLMDialog.swift | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/binding/ios/PicoLLMDialog.swift b/binding/ios/PicoLLMDialog.swift index 7e19fc94..241dc13d 100644 --- a/binding/ios/PicoLLMDialog.swift +++ b/binding/ios/PicoLLMDialog.swift @@ -160,6 +160,47 @@ public class Phi2ChatDialog: Phi2Dialog { } } +/// Dialog helper for `phi3`. +public class Phi3ChatDialog: BasePicoLLMDialog { + public override func prompt() throws -> String { + if self.humanRequests.count == self.llmResponses.count { + throw PicoLLMInvalidStateError("Only subclasses of PicoLLMDialog can return create prompts.") + } + + let humanRequests = (self.history == nil) ? + self.humanRequests[...] : + self.humanRequests[(self.humanRequests.count - Int(self.history!) - 1)...] + let llmResponses = (self.history == nil) ? + self.llmResponses[...] : + self.llmResponses[(self.llmResponses.count - Int(self.history!))...] + + var res = "" + if system != nil { + instruction = String(format: "<|system|>\n%@<|end|>\n", system!) + } + for i in 0..\n%@<|end|>\n", + humanRequests[i].trimmingCharacters(in: .whitespacesAndNewlines) + ) + res += String( + format: "<|assistant|>\n%@<|end|>\n", + llmResponses[i].trimmingCharacters(in: .whitespacesAndNewlines) + ) + } + + res += String( + format: "<|user|>\n%@<|end|>\n", + humanRequests.last!.trimmingCharacters(in: .whitespacesAndNewlines) + ) + res += String( + format: "<|assistant|>\n" + ) + + return res + } +} + /// Dialog helper for `mistral-7b-instruct-v0.1` and `mistral-7b-instruct-v0.2`. public class MistralChatDialog: BasePicoLLMDialog { public override func prompt() throws -> String { From 8ed000ae3608f79853da3f98acaf0da76e7491c7 Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Wed, 18 Sep 2024 17:23:04 -0700 Subject: [PATCH 06/13] more dialog --- binding/ios/PicoLLM.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/binding/ios/PicoLLM.swift b/binding/ios/PicoLLM.swift index 80044bb2..4c0501d9 100644 --- a/binding/ios/PicoLLM.swift +++ b/binding/ios/PicoLLM.swift @@ -514,6 +514,7 @@ public class PicoLLM { "mistral-7b-instruct-v0.1": MistralChatDialog.self, "mistral-7b-instruct-v0.2": MistralChatDialog.self, "mixtral-8x7b-instruct-v0.1": MixtralChatDialog.self + "phi3": Phi3ChatDialog.self ] private static let phi2Dialogs: [String: Phi2Dialog.Type] = [ From 0cdd81ca23b74ddacbc9284edbff257ca352d237 Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Wed, 18 Sep 2024 17:27:27 -0700 Subject: [PATCH 07/13] fix --- binding/ios/PicoLLM.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/ios/PicoLLM.swift b/binding/ios/PicoLLM.swift index 4c0501d9..32995c78 100644 --- a/binding/ios/PicoLLM.swift +++ b/binding/ios/PicoLLM.swift @@ -513,7 +513,7 @@ public class PicoLLM { "llama-3-70b-chat": Llama3ChatDialog.self, "mistral-7b-instruct-v0.1": MistralChatDialog.self, "mistral-7b-instruct-v0.2": MistralChatDialog.self, - "mixtral-8x7b-instruct-v0.1": MixtralChatDialog.self + "mixtral-8x7b-instruct-v0.1": MixtralChatDialog.self, "phi3": Phi3ChatDialog.self ] From e151cf12ee84d2e79f54a869c300a96690f5adcd Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Wed, 18 Sep 2024 17:30:28 -0700 Subject: [PATCH 08/13] fix --- binding/ios/PicoLLMDialog.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/ios/PicoLLMDialog.swift b/binding/ios/PicoLLMDialog.swift index 241dc13d..109b696b 100644 --- a/binding/ios/PicoLLMDialog.swift +++ b/binding/ios/PicoLLMDialog.swift @@ -176,7 +176,7 @@ public class Phi3ChatDialog: BasePicoLLMDialog { var res = "" if system != nil { - instruction = String(format: "<|system|>\n%@<|end|>\n", system!) + res += String(format: "<|system|>\n%@<|end|>\n", system!) } for i in 0.. Date: Wed, 18 Sep 2024 17:33:18 -0700 Subject: [PATCH 09/13] update demo and tests --- .../PicoLLMAppTestUITests.swift | 24 ++++++++++++++++++- binding/ios/PicoLLMAppTest/Podfile | 4 ++-- binding/ios/PicoLLMAppTest/Podfile.lock | 16 ++++++------- demo/ios/Completion/Podfile.lock | 4 ++-- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift index 1b584cb3..7b711336 100644 --- a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift +++ b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift @@ -345,6 +345,27 @@ class PicoLLMAppTestUITests: BaseTest { XCTAssertEqual(pieces, expected) } + func testInterrupt() throws { + let testCase = PicollmTestCase(name: "default", data: self.picollmTestData!) + + let group = DispatchGroup() + + var res: PicoLLMCompletion? + + group.enter() + DispatchQueue.global(qos: .userInitiated).async { + do { + res = try self.handle!.generate(prompt: testCase.prompt) + } catch { } + group.leave() + } + + try handle!.interrupt() + + group.wait() + XCTAssertEqual(res!.endpoint, .interrupted) + } + func testTokenize() throws { let tokenizeData = self.picollmTestData!["tokenize"] as! [String: Any] let text = tokenizeData["text"] as! String @@ -401,7 +422,8 @@ class PicoLLMAppTestUITests: BaseTest { "llama-3-chat-dialog": Llama3ChatDialog.self, "mistral-chat-dialog": MistralChatDialog.self, "phi2-chat-dialog": Phi2ChatDialog.self, - "phi2-qa-dialog": Phi2QADialog.self + "phi2-qa-dialog": Phi2QADialog.self, + "phi3-chat-dialog": Phi3ChatDialog.self ] let dialogPrompts = self.dialogTestData![testName] as! [String: String] diff --git a/binding/ios/PicoLLMAppTest/Podfile b/binding/ios/PicoLLMAppTest/Podfile index 81b177d0..e603e7ef 100644 --- a/binding/ios/PicoLLMAppTest/Podfile +++ b/binding/ios/PicoLLMAppTest/Podfile @@ -2,9 +2,9 @@ source 'https://cdn.cocoapods.org/' platform :ios, '16.0' target 'PicoLLMAppTest' do - pod 'picoLLM-iOS', '~> 1.0.0' + pod 'picoLLM-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec' end target 'PicoLLMAppTestUITests' do - pod 'picoLLM-iOS', '~> 1.0.0' + pod 'picoLLM-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec' end diff --git a/binding/ios/PicoLLMAppTest/Podfile.lock b/binding/ios/PicoLLMAppTest/Podfile.lock index 3a9d0583..188da1e9 100644 --- a/binding/ios/PicoLLMAppTest/Podfile.lock +++ b/binding/ios/PicoLLMAppTest/Podfile.lock @@ -1,16 +1,16 @@ PODS: - - picoLLM-iOS (1.0.0) + - picoLLM-iOS (1.1.0) DEPENDENCIES: - - picoLLM-iOS (~> 1.0.0) + - picoLLM-iOS (from `https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec`) -SPEC REPOS: - trunk: - - picoLLM-iOS +EXTERNAL SOURCES: + picoLLM-iOS: + :podspec: https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec SPEC CHECKSUMS: - picoLLM-iOS: 02cdb501b4beb74a9c1dea29d5cf461d65ea4a6c + picoLLM-iOS: dc03cd7e992c702ff34c667f9a35dd9a8084c061 -PODFILE CHECKSUM: 5223638a26efe0676b29af87115eb47f41185dc4 +PODFILE CHECKSUM: 8557d5c1b8e4eb632f8926bbc8eeb29802224b3d -COCOAPODS: 1.15.2 +COCOAPODS: 1.11.3 diff --git a/demo/ios/Completion/Podfile.lock b/demo/ios/Completion/Podfile.lock index 302dc4b7..62c1e7d2 100644 --- a/demo/ios/Completion/Podfile.lock +++ b/demo/ios/Completion/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - picoLLM-iOS (1.2.0) + - picoLLM-iOS (1.1.0) DEPENDENCIES: - picoLLM-iOS (from `https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec`) @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :podspec: https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec SPEC CHECKSUMS: - picoLLM-iOS: 9cc5d0743d1bc856aeabe6c773889d72e884cbee + picoLLM-iOS: dc03cd7e992c702ff34c667f9a35dd9a8084c061 PODFILE CHECKSUM: d5764505a13214074d2e9db975f4c26fd5c720be From d77a4709eeb923c56569cac8b5c6b2135c64ab7d Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Thu, 19 Sep 2024 09:51:07 -0700 Subject: [PATCH 10/13] chat demo --- demo/ios/Chat/PicoLLMChatDemo/ChatView.swift | 18 +++++++++--------- demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift | 17 ++++++++++++++--- demo/ios/Chat/Podfile | 2 +- demo/ios/Chat/Podfile.lock | 16 ++++++++-------- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/demo/ios/Chat/PicoLLMChatDemo/ChatView.swift b/demo/ios/Chat/PicoLLMChatDemo/ChatView.swift index 36c9644b..b5673914 100644 --- a/demo/ios/Chat/PicoLLMChatDemo/ChatView.swift +++ b/demo/ios/Chat/PicoLLMChatDemo/ChatView.swift @@ -26,7 +26,7 @@ struct ChatView: View { Spacer() HStack(alignment: .center) { - if !viewModel.enableGenerateButton { + if viewModel.isGenerating { ProgressView(value: 0).progressViewStyle(CircularProgressViewStyle()) Text("Generating...") .padding(.horizontal, 12) @@ -53,20 +53,20 @@ struct ChatView: View { .onSubmit { viewModel.generate() } - .disabled(isError || !viewModel.enableGenerateButton) + .disabled(isError || viewModel.isGenerating) HStack(alignment: .center) { Spacer() - Button(action: viewModel.generate) { - Image(systemName: "arrow.up") + Button(action: viewModel.isGenerating ? viewModel.interrupt : viewModel.generate) { + Image(systemName: viewModel.isGenerating ? "stop.fill" : "arrow.up") .imageScale(.medium) - .background(Constants.btnColor(viewModel.enableGenerateButton && !isError)) + .background(Constants.btnColor(!isError)) .foregroundColor(.white) .padding(6) }.background( - Capsule().fill(Constants.btnColor(viewModel.enableGenerateButton && !isError)) + Capsule().fill(Constants.btnColor(!isError)) ) .padding(.horizontal, 4) - .disabled(isError || !viewModel.enableGenerateButton) + .disabled(isError) } } .padding(.vertical, 12) @@ -111,7 +111,7 @@ struct ChatView: View { .imageScale(.large) } .padding(.horizontal, 12) - .disabled(!viewModel.enableGenerateButton) + .disabled(viewModel.isGenerating) Spacer() Button(action: viewModel.clearText) { Image(systemName: "arrow.counterclockwise") @@ -120,7 +120,7 @@ struct ChatView: View { .padding(.horizontal, 12) .disabled( viewModel.errorMessage.count > 0 || - !viewModel.enableGenerateButton || + viewModel.isGenerating || viewModel.chatText.isEmpty) } .padding(.bottom, 12) diff --git a/demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift b/demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift index 15261995..38c31a03 100644 --- a/demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift +++ b/demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift @@ -34,7 +34,7 @@ You can download directly to your device or airdrop from a Mac. @Published var picoLLMLoaded = false @Published var promptText = "" - @Published var enableGenerateButton = true + @Published var isGenerating = false @Published var chatText: [Message] = [] @@ -116,7 +116,7 @@ You can download directly to your device or airdrop from a Mac. errorMessage = "" - enableGenerateButton = false + isGenerating = true numTokens = 0 DispatchQueue.global(qos: .userInitiated).async { [self] in @@ -143,7 +143,18 @@ You can download directly to your device or airdrop from a Mac. DispatchQueue.main.async { [self] in promptText = "" - enableGenerateButton = true + isGenerating = false + } + } + } + + public func interrupt() { + do { + try picollm?.interrupt(); + } catch { + DispatchQueue.main.async { [self] in + errorMessage = "\(error.localizedDescription)" + enableLoadModelButton = true } } } diff --git a/demo/ios/Chat/Podfile b/demo/ios/Chat/Podfile index c56bc89a..07bd75e0 100644 --- a/demo/ios/Chat/Podfile +++ b/demo/ios/Chat/Podfile @@ -2,5 +2,5 @@ source 'https://cdn.cocoapods.org/' platform :ios, '16.0' target 'PicoLLMChatDemo' do - pod 'picoLLM-iOS', '~> 1.0.0' + pod 'picoLLM-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec' end diff --git a/demo/ios/Chat/Podfile.lock b/demo/ios/Chat/Podfile.lock index 0b22387e..83aec644 100644 --- a/demo/ios/Chat/Podfile.lock +++ b/demo/ios/Chat/Podfile.lock @@ -1,16 +1,16 @@ PODS: - - picoLLM-iOS (1.0.0) + - picoLLM-iOS (1.1.0) DEPENDENCIES: - - picoLLM-iOS (~> 1.0.0) + - picoLLM-iOS (from `https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec`) -SPEC REPOS: - trunk: - - picoLLM-iOS +EXTERNAL SOURCES: + picoLLM-iOS: + :podspec: https://raw.githubusercontent.com/Picovoice/picollm/v1.1-ios/binding/ios/picoLLM-iOS.podspec SPEC CHECKSUMS: - picoLLM-iOS: 02cdb501b4beb74a9c1dea29d5cf461d65ea4a6c + picoLLM-iOS: dc03cd7e992c702ff34c667f9a35dd9a8084c061 -PODFILE CHECKSUM: 5ceffe351e8a95d803e0000324674ffa525cbb43 +PODFILE CHECKSUM: 51304d5689a6025865f0d87106b6efef0b049eb8 -COCOAPODS: 1.15.2 +COCOAPODS: 1.11.3 From 27ac63c7cfcec3aee2ffaa3acc911abe49495f74 Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Thu, 19 Sep 2024 11:01:56 -0700 Subject: [PATCH 11/13] fix --- .../ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift | 2 +- .../PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift | 2 +- demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift | 4 ++-- demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift | 4 ++-- resources/.lint/spell-check/dict.txt | 1 + 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift index 9d75dbbc..e5b1923b 100644 --- a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift +++ b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift @@ -17,7 +17,7 @@ class BaseTest: XCTestCase { let accessKey: String = "{TESTING_ACCESS_KEY_HERE}" let modelURL = URL(string: "{TESTING_MODEL_URL_HERE}") - let cleanModel = false + let cleanModel = true var modelPath: String = "" var picollmTestData: [String: Any]? diff --git a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift index 7b711336..f3b5b890 100644 --- a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift +++ b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift @@ -351,7 +351,7 @@ class PicoLLMAppTestUITests: BaseTest { let group = DispatchGroup() var res: PicoLLMCompletion? - + group.enter() DispatchQueue.global(qos: .userInitiated).async { do { diff --git a/demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift b/demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift index 38c31a03..91463943 100644 --- a/demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift +++ b/demo/ios/Chat/PicoLLMChatDemo/ViewModel.swift @@ -147,10 +147,10 @@ You can download directly to your device or airdrop from a Mac. } } } - + public func interrupt() { do { - try picollm?.interrupt(); + try picollm?.interrupt() } catch { DispatchQueue.main.async { [self] in errorMessage = "\(error.localizedDescription)" diff --git a/demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift b/demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift index 1dfaf7f8..2261bada 100644 --- a/demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift +++ b/demo/ios/Completion/PicoLLMCompletionDemo/ViewModel.swift @@ -175,10 +175,10 @@ You can download directly to your device or airdrop from a Mac. } } } - + public func interrupt() { do { - try picollm?.interrupt(); + try picollm?.interrupt() } catch { DispatchQueue.main.async { [self] in errorMessage = "\(error.localizedDescription)" diff --git a/resources/.lint/spell-check/dict.txt b/resources/.lint/spell-check/dict.txt index be899255..c0d435ad 100644 --- a/resources/.lint/spell-check/dict.txt +++ b/resources/.lint/spell-check/dict.txt @@ -35,6 +35,7 @@ picollmoutofmemoryerror picovoice pllm pluginutils +podspec readables rtld salut From 52cf79bf9e6fefeec1e7f67f2ab5d854c00063bd Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Thu, 19 Sep 2024 12:00:40 -0700 Subject: [PATCH 12/13] fix --- .../PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift index f3b5b890..4efa8d0c 100644 --- a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift +++ b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/PicoLLMAppTestUITests.swift @@ -353,13 +353,13 @@ class PicoLLMAppTestUITests: BaseTest { var res: PicoLLMCompletion? group.enter() - DispatchQueue.global(qos: .userInitiated).async { + DispatchQueue.global(qos: .background).async { do { res = try self.handle!.generate(prompt: testCase.prompt) } catch { } group.leave() } - + sleep(1) try handle!.interrupt() group.wait() @@ -426,7 +426,6 @@ class PicoLLMAppTestUITests: BaseTest { "phi3-chat-dialog": Phi3ChatDialog.self ] let dialogPrompts = self.dialogTestData![testName] as! [String: String] - let conversation = self.dialogTestData!["conversation"] as! [[String]] for (dialogClassName, dialogClassType) in dialogClasses { @@ -437,6 +436,7 @@ class PicoLLMAppTestUITests: BaseTest { try dialog.addHumanRequest(content: conversation[i][0]) try dialog.addLLMResponse(content: conversation[i][1]) } + try dialog.addHumanRequest(content: conversation.last![0]) XCTAssertEqual(try dialog.prompt(), prompt) } From 5051766e373319936ca989e261844da5b145def3 Mon Sep 17 00:00:00 2001 From: Ian Lavery Date: Thu, 19 Sep 2024 15:21:56 -0700 Subject: [PATCH 13/13] fix --- binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift index e5b1923b..9d75dbbc 100644 --- a/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift +++ b/binding/ios/PicoLLMAppTest/PicoLLMAppTestUITests/BaseTest.swift @@ -17,7 +17,7 @@ class BaseTest: XCTestCase { let accessKey: String = "{TESTING_ACCESS_KEY_HERE}" let modelURL = URL(string: "{TESTING_MODEL_URL_HERE}") - let cleanModel = true + let cleanModel = false var modelPath: String = "" var picollmTestData: [String: Any]?