From 3dd6610c39b19aba2fe791352ba511792f440e23 Mon Sep 17 00:00:00 2001 From: Philipp Zagar Date: Mon, 4 Dec 2023 13:24:15 -0800 Subject: [PATCH] Local LLM Execution Capabilities (#35) # *Local LLM Execution Capabilities* ## :recycle: Current situation & Problem As of now, the Spezi ecosystem (via `SpeziML`) provides an OpenAI integration for easy LLM execution. However, using a remote, opaque service like OpenAI comes with a multitude of challenges, especially in the health domain. The challenges include privacy, trust, security but also financial considerations. ## :gear: Release Notes - Renaming the SPM package (and the entire repo) from `SpeziML` to `SpeziLLM` to better reflect the current functionality of the package. - Complete restructuring of the package to support local and remote LLM execution. Introduced four separate targets `SpeziLLM` (providing base LLM infrastructure), `SpeziLLMLocal` (providing local execution capabilities), `SpeziLLMLocalDownload` (providing download and local storage functionality), as well as `SpeziLLMOpenAI` (providing a OpenAI GPT integration). All of these targets are subject to change in the upcoming releases. ## :books: Documentation Documentation has been provided via inline DocC comments and code examples. ## :white_check_mark: Testing Wrote appropriate UI Tests which utilize an LLM mock. ## :pencil: Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md). --------- Co-authored-by: Paul Schmiedmayer --- .github/workflows/build-and-test.yml | 6 +- .spi.yml | 7 +- CITATION.cff | 4 +- CONTRIBUTORS.md | 4 +- Package.swift | 56 +++- README.md | 196 +++++------ .../LLMRunnerConfiguration.swift | 31 ++ .../Helpers/BundleDescription+Bundle.swift | 18 + Sources/SpeziLLM/LLM.swift | 56 ++++ Sources/SpeziLLM/LLMError.swift | 54 +++ Sources/SpeziLLM/LLMHostingType.swift | 17 + Sources/SpeziLLM/LLMRunner.swift | 160 +++++++++ .../SpeziLLM/LLMState+OperationState.swift | 26 ++ Sources/SpeziLLM/LLMState.swift | 36 ++ Sources/SpeziLLM/Mock/LLMMock.swift | 39 +++ .../SpeziLLM/Resources/Localizable.xcstrings | 157 +++++++++ .../Resources/Localizable.xcstrings.license | 5 + Sources/SpeziLLM/SpeziLLM.docc/SpeziLLM.md | 162 +++++++++ .../SpeziLLM/Tasks/LLMGenerationTask.swift | 85 +++++ .../SpeziLLM/Tasks/LLMRunnerSetupTask.swift | 33 ++ .../Tasks/LLMRunnerSetupTaskBuilder.swift | 58 ++++ .../Tasks/LLMRunnerSetupTaskCollection.swift | 33 ++ .../SpeziLLM/Tasks/LLMTaskIdentifier.swift | 25 ++ Sources/SpeziLLM/Views/LLMChatView.swift | 101 ++++++ .../Configuration/LLMContextParameters.swift | 177 ++++++++++ .../Configuration/LLMParameters.swift | 175 ++++++++++ .../Configuration/LLMSamplingParameters.swift | 298 +++++++++++++++++ .../SpeziLLMLocal/LLMLlama+Generation.swift | 149 +++++++++ Sources/SpeziLLMLocal/LLMLlama+Helpers.swift | 159 +++++++++ Sources/SpeziLLMLocal/LLMLlama.swift | 100 ++++++ .../LLMLocalRunnerSetupTask.swift | 45 +++ .../Resources/Localizable.xcstrings | 16 + .../Resources/Localizable.xcstrings.license | 5 + .../SpeziLLMLocal.docc/Resources/ChatView.png | Bin 0 -> 102090 bytes .../Resources/ChatView.png.license | 5 + .../Resources/ChatView~dark.png | Bin 0 -> 68402 bytes .../Resources/ChatView~dark.png.license | 5 + .../SpeziLLMLocal.docc/SpeziLLMLocal.md | 106 ++++++ ...MLocalDownloadManager+OperationState.swift | 26 ++ .../LLMLocalDownloadManager.swift | 121 +++++++ .../LLMLocalDownloadManagerDelegate.swift | 86 +++++ .../LLMLocalDownloadView.swift | 194 +++++++++++ .../Resources/Localizable.xcstrings | 106 ++++++ .../Resources/Localizable.xcstrings.license | 5 + .../Resources/LLMLocalDownload.png | Bin 0 -> 56242 bytes .../Resources/LLMLocalDownload.png.license | 5 + .../Resources/LLMLocalDownload~dark.png | Bin 0 -> 52155 bytes .../LLMLocalDownload~dark.png.license | 5 + .../SpeziLLMLocalDownload.md | 92 +++++ .../OpenAIAPIKeyOnboardingStep.swift | 2 +- .../OpenAIChatStreamResult+Sendable.swift | 9 + .../OpenAIConstants.swift | 0 .../OpenAIError.swift | 0 .../OpenAIModel.swift | 40 ++- .../OpenAIModelSelectionOnboardingStep.swift | 0 .../OpenAIModule.swift | 2 +- .../Resources/Localizable.xcstrings | 204 ++++++++++++ .../Resources/Localizable.xcstrings.license | 5 + .../Resources/ChatView.png | Bin 0 -> 47173 bytes .../Resources/ChatView.png.license | 4 +- .../Resources/ChatView~dark.png | Bin 0 -> 46046 bytes .../Resources/ChatView~dark.png.license | 4 +- .../Resources/OpenAIAPIKeyOnboardingStep.png | Bin .../OpenAIAPIKeyOnboardingStep.png.license | 4 +- .../OpenAIAPIKeyOnboardingStep~dark.png | Bin ...penAIAPIKeyOnboardingStep~dark.png.license | 4 +- .../OpenAIModelSelectionOnboardingStep.png | Bin ...AIModelSelectionOnboardingStep.png.license | 4 +- ...penAIModelSelectionOnboardingStep~dark.png | Bin ...elSelectionOnboardingStep~dark.png.license | 4 +- .../SpeziLLMOpenAI.docc/SpeziLLMOpenAI.md} | 72 ++-- Sources/SpeziOpenAI/ChatView.swift | 79 ----- Sources/SpeziOpenAI/MessageInputView.swift | 172 ---------- .../MessageInputViewHeightKey.swift | 24 -- Sources/SpeziOpenAI/MessageView.swift | 98 ------ Sources/SpeziOpenAI/MessagesView.swift | 115 ------- Sources/SpeziOpenAI/OpenAI+Extensions.swift | 27 -- .../Resources/en.lproj/Localizable.strings | 27 -- .../SpeziOpenAI.docc/Resources/ChatView.png | Bin 90974 -> 0 bytes .../Resources/ChatView~dark.png | Bin 91225 -> 0 bytes .../SpeechRecognizer.swift | 144 -------- .../SpeechSynthesizer.swift | 82 ----- .../SpeziLLMTests.swift} | 6 +- Tests/UITests/TestApp.xctestplan | 19 +- Tests/UITests/TestApp.xctestplan.license | 4 +- .../Contents.json.license | 2 +- .../AppIcon.appiconset/Contents.json.license | 2 +- .../Assets.xcassets/Contents.json.license | 2 +- Tests/UITests/TestApp/ContentView.swift | 40 --- Tests/UITests/TestApp/FeatureFlags.swift | 15 + .../LLMLocal/Helpers/Binding+Negate.swift | 20 ++ .../LLMLocal/Helpers/StorageKeys.swift | 13 + .../LLMLocal/LLMLocalChatTestView.swift | 47 +++ .../TestApp/LLMLocal/LLMLocalTestView.swift | 28 ++ .../LLMLocalOnboardingDownloadView.swift | 35 ++ .../Onboarding/LLMLocalOnboardingFlow.swift | 33 ++ .../LLMLocalOnboardingWelcomeView.swift | 63 ++++ .../LLMOpenAI/LLMOpenAIChatTestView.swift | 39 +++ .../LLMOpenAIOnboardingView.swift} | 6 +- .../TestApp/Resources/Localizable.xcstrings | 136 ++++++++ .../Resources/Localizable.xcstrings.license | 5 + Tests/UITests/TestApp/TestApp.swift | 37 ++- Tests/UITests/TestApp/TestAppDelegate.swift | 10 +- .../TestAppLLMLocalUITests.swift | 53 +++ ...ts.swift => TestAppLLMOpenAIUITests.swift} | 26 +- .../UITests/UITests.xcodeproj/project.pbxproj | 313 +++++++++--------- .../UITests.xcodeproj/project.pbxproj.license | 2 +- .../contents.xcworkspacedata.license | 2 +- .../IDEWorkspaceChecks.plist.license | 2 +- .../xcshareddata/xcschemes/TestApp.xcscheme | 64 +++- .../xcschemes/TestApp.xcscheme.license | 2 +- 111 files changed, 4212 insertions(+), 1189 deletions(-) create mode 100644 Sources/SpeziLLM/Configuration/LLMRunnerConfiguration.swift create mode 100644 Sources/SpeziLLM/Helpers/BundleDescription+Bundle.swift create mode 100644 Sources/SpeziLLM/LLM.swift create mode 100644 Sources/SpeziLLM/LLMError.swift create mode 100644 Sources/SpeziLLM/LLMHostingType.swift create mode 100644 Sources/SpeziLLM/LLMRunner.swift create mode 100644 Sources/SpeziLLM/LLMState+OperationState.swift create mode 100644 Sources/SpeziLLM/LLMState.swift create mode 100644 Sources/SpeziLLM/Mock/LLMMock.swift create mode 100644 Sources/SpeziLLM/Resources/Localizable.xcstrings create mode 100644 Sources/SpeziLLM/Resources/Localizable.xcstrings.license create mode 100644 Sources/SpeziLLM/SpeziLLM.docc/SpeziLLM.md create mode 100644 Sources/SpeziLLM/Tasks/LLMGenerationTask.swift create mode 100644 Sources/SpeziLLM/Tasks/LLMRunnerSetupTask.swift create mode 100644 Sources/SpeziLLM/Tasks/LLMRunnerSetupTaskBuilder.swift create mode 100644 Sources/SpeziLLM/Tasks/LLMRunnerSetupTaskCollection.swift create mode 100644 Sources/SpeziLLM/Tasks/LLMTaskIdentifier.swift create mode 100644 Sources/SpeziLLM/Views/LLMChatView.swift create mode 100644 Sources/SpeziLLMLocal/Configuration/LLMContextParameters.swift create mode 100644 Sources/SpeziLLMLocal/Configuration/LLMParameters.swift create mode 100644 Sources/SpeziLLMLocal/Configuration/LLMSamplingParameters.swift create mode 100644 Sources/SpeziLLMLocal/LLMLlama+Generation.swift create mode 100644 Sources/SpeziLLMLocal/LLMLlama+Helpers.swift create mode 100644 Sources/SpeziLLMLocal/LLMLlama.swift create mode 100644 Sources/SpeziLLMLocal/LLMLocalRunnerSetupTask.swift create mode 100644 Sources/SpeziLLMLocal/Resources/Localizable.xcstrings create mode 100644 Sources/SpeziLLMLocal/Resources/Localizable.xcstrings.license create mode 100644 Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView.png create mode 100644 Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView.png.license create mode 100644 Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView~dark.png create mode 100644 Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView~dark.png.license create mode 100644 Sources/SpeziLLMLocal/SpeziLLMLocal.docc/SpeziLLMLocal.md create mode 100644 Sources/SpeziLLMLocalDownload/LLMLocalDownloadManager+OperationState.swift create mode 100644 Sources/SpeziLLMLocalDownload/LLMLocalDownloadManager.swift create mode 100644 Sources/SpeziLLMLocalDownload/LLMLocalDownloadManagerDelegate.swift create mode 100644 Sources/SpeziLLMLocalDownload/LLMLocalDownloadView.swift create mode 100644 Sources/SpeziLLMLocalDownload/Resources/Localizable.xcstrings create mode 100644 Sources/SpeziLLMLocalDownload/Resources/Localizable.xcstrings.license create mode 100644 Sources/SpeziLLMLocalDownload/SpeziLLMLocalDownload.docc/Resources/LLMLocalDownload.png create mode 100644 Sources/SpeziLLMLocalDownload/SpeziLLMLocalDownload.docc/Resources/LLMLocalDownload.png.license create mode 100644 Sources/SpeziLLMLocalDownload/SpeziLLMLocalDownload.docc/Resources/LLMLocalDownload~dark.png create mode 100644 Sources/SpeziLLMLocalDownload/SpeziLLMLocalDownload.docc/Resources/LLMLocalDownload~dark.png.license create mode 100644 Sources/SpeziLLMLocalDownload/SpeziLLMLocalDownload.docc/SpeziLLMLocalDownload.md rename Sources/{SpeziOpenAI => SpeziLLMOpenAI}/OpenAIAPIKeyOnboardingStep.swift (98%) create mode 100644 Sources/SpeziLLMOpenAI/OpenAIChatStreamResult+Sendable.swift rename Sources/{SpeziOpenAI => SpeziLLMOpenAI}/OpenAIConstants.swift (100%) rename Sources/{SpeziOpenAI => SpeziLLMOpenAI}/OpenAIError.swift (100%) rename Sources/{SpeziOpenAI => SpeziLLMOpenAI}/OpenAIModel.swift (69%) rename Sources/{SpeziOpenAI => SpeziLLMOpenAI}/OpenAIModelSelectionOnboardingStep.swift (100%) rename Sources/{SpeziOpenAI => SpeziLLMOpenAI}/OpenAIModule.swift (93%) create mode 100644 Sources/SpeziLLMOpenAI/Resources/Localizable.xcstrings create mode 100644 Sources/SpeziLLMOpenAI/Resources/Localizable.xcstrings.license create mode 100644 Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView.png rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/ChatView.png.license (50%) create mode 100644 Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView~dark.png rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/ChatView~dark.png.license (50%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/OpenAIAPIKeyOnboardingStep.png (100%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/OpenAIAPIKeyOnboardingStep.png.license (50%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/OpenAIAPIKeyOnboardingStep~dark.png (100%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/OpenAIAPIKeyOnboardingStep~dark.png.license (50%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/OpenAIModelSelectionOnboardingStep.png (100%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/OpenAIModelSelectionOnboardingStep.png.license (50%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/OpenAIModelSelectionOnboardingStep~dark.png (100%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc => SpeziLLMOpenAI/SpeziLLMOpenAI.docc}/Resources/OpenAIModelSelectionOnboardingStep~dark.png.license (50%) rename Sources/{SpeziOpenAI/SpeziOpenAI.docc/SpeziOpenAI.md => SpeziLLMOpenAI/SpeziLLMOpenAI.docc/SpeziLLMOpenAI.md} (64%) delete mode 100644 Sources/SpeziOpenAI/ChatView.swift delete mode 100644 Sources/SpeziOpenAI/MessageInputView.swift delete mode 100644 Sources/SpeziOpenAI/MessageInputViewHeightKey.swift delete mode 100644 Sources/SpeziOpenAI/MessageView.swift delete mode 100644 Sources/SpeziOpenAI/MessagesView.swift delete mode 100644 Sources/SpeziOpenAI/OpenAI+Extensions.swift delete mode 100644 Sources/SpeziOpenAI/Resources/en.lproj/Localizable.strings delete mode 100644 Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView.png delete mode 100644 Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView~dark.png delete mode 100644 Sources/SpeziSpeechRecognizer/SpeechRecognizer.swift delete mode 100644 Sources/SpeziSpeechSynthesizer/SpeechSynthesizer.swift rename Tests/{SpeziOpenAITests/SpeziOpenAITests.swift => SpeziLLMTests/SpeziLLMTests.swift} (69%) delete mode 100644 Tests/UITests/TestApp/ContentView.swift create mode 100644 Tests/UITests/TestApp/FeatureFlags.swift create mode 100644 Tests/UITests/TestApp/LLMLocal/Helpers/Binding+Negate.swift create mode 100644 Tests/UITests/TestApp/LLMLocal/Helpers/StorageKeys.swift create mode 100644 Tests/UITests/TestApp/LLMLocal/LLMLocalChatTestView.swift create mode 100644 Tests/UITests/TestApp/LLMLocal/LLMLocalTestView.swift create mode 100644 Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingDownloadView.swift create mode 100644 Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingFlow.swift create mode 100644 Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingWelcomeView.swift create mode 100644 Tests/UITests/TestApp/LLMOpenAI/LLMOpenAIChatTestView.swift rename Tests/UITests/TestApp/{OnboardingView.swift => LLMOpenAI/LLMOpenAIOnboardingView.swift} (85%) create mode 100644 Tests/UITests/TestApp/Resources/Localizable.xcstrings create mode 100644 Tests/UITests/TestApp/Resources/Localizable.xcstrings.license create mode 100644 Tests/UITests/TestAppUITests/TestAppLLMLocalUITests.swift rename Tests/UITests/TestAppUITests/{TestAppUITests.swift => TestAppLLMOpenAIUITests.swift} (77%) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 0aa3b30..15bdc3c 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -20,9 +20,9 @@ jobs: name: Build and Test Swift Package uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2 with: - artifactname: SpeziML-Package.xcresult + artifactname: SpeziLLM-Package.xcresult runsonlabels: '["macOS", "self-hosted"]' - scheme: SpeziML-Package + scheme: SpeziLLM-Package buildandtestuitests: name: Build and Test UI Tests uses: StanfordSpezi/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2 @@ -36,4 +36,4 @@ jobs: needs: [buildandtest, buildandtestuitests] uses: StanfordSpezi/.github/.github/workflows/create-and-upload-coverage-report.yml@v2 with: - coveragereports: SpeziML-Package.xcresult TestApp.xcresult + coveragereports: SpeziLLM-Package.xcresult TestApp.xcresult diff --git a/.spi.yml b/.spi.yml index b32a84a..af6ea0d 100644 --- a/.spi.yml +++ b/.spi.yml @@ -11,6 +11,7 @@ builder: configs: - platform: ios documentation_targets: - - SpeziOpenAI - - SpeziSpeechRecognizer - - SpeziSpeechSynthesizer + - SpeziLLM + - SpeziLLMLocal + - SpeziLLMLocalDownload + - SpeziLLMOpenAI diff --git a/CITATION.cff b/CITATION.cff index a46ef83..8e684ab 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -15,6 +15,6 @@ authors: - family-names: "Ravi" given-names: "Vishnu" orcid: "https://orcid.org/0000-0003-0359-1275" -title: "SpeziML" +title: "SpeziLLM" doi: 10.5281/zenodo.7538165 -url: "https://github.com/StanfordSpezi/SpeziML" +url: "https://github.com/StanfordSpezi/SpeziLLM" diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 41ace4f..7431090 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -10,8 +10,10 @@ --> -SpeziML contributors +SpeziLLM contributors ==================== * [Paul Schmiedmayer](https://github.com/PSchmiedmayer) * [Vishnu Ravi](https://github.com/vishnuravi) +* [Philipp Zagar](https://github.com/philippzagar) +* [Adrit Rao](https://github.com/AdritRao) diff --git a/Package.swift b/Package.swift index 3ecb867..0f08fbf 100644 --- a/Package.swift +++ b/Package.swift @@ -12,44 +12,70 @@ import PackageDescription let package = Package( - name: "SpeziML", + name: "SpeziLLM", defaultLocalization: "en", platforms: [ .iOS(.v17) ], products: [ - .library(name: "SpeziOpenAI", targets: ["SpeziOpenAI"]), - .library(name: "SpeziSpeechRecognizer", targets: ["SpeziSpeechRecognizer"]), - .library(name: "SpeziSpeechSynthesizer", targets: ["SpeziSpeechSynthesizer"]) + .library(name: "SpeziLLM", targets: ["SpeziLLM"]), + .library(name: "SpeziLLMLocal", targets: ["SpeziLLMLocal"]), + .library(name: "SpeziLLMLocalDownload", targets: ["SpeziLLMLocalDownload"]), + .library(name: "SpeziLLMOpenAI", targets: ["SpeziLLMOpenAI"]) ], dependencies: [ .package(url: "https://github.com/MacPaw/OpenAI", .upToNextMinor(from: "0.2.4")), + .package(url: "https://github.com/StanfordBDHG/llama.cpp", .upToNextMinor(from: "0.1.6")), .package(url: "https://github.com/StanfordSpezi/Spezi", .upToNextMinor(from: "0.8.0")), .package(url: "https://github.com/StanfordSpezi/SpeziStorage", .upToNextMinor(from: "0.5.0")), - .package(url: "https://github.com/StanfordSpezi/SpeziOnboarding", .upToNextMinor(from: "0.7.0")) + .package(url: "https://github.com/StanfordSpezi/SpeziOnboarding", .upToNextMinor(from: "0.7.0")), + .package(url: "https://github.com/StanfordSpezi/SpeziSpeech", .upToNextMinor(from: "0.1.1")), + .package(url: "https://github.com/StanfordSpezi/SpeziChat", .upToNextMinor(from: "0.1.1")), + .package(url: "https://github.com/StanfordSpezi/SpeziViews", .upToNextMinor(from: "0.6.3")) ], targets: [ .target( - name: "SpeziOpenAI", + name: "SpeziLLM", dependencies: [ - .target(name: "SpeziSpeechRecognizer"), - .product(name: "OpenAI", package: "OpenAI"), .product(name: "Spezi", package: "Spezi"), - .product(name: "SpeziLocalStorage", package: "SpeziStorage"), - .product(name: "SpeziSecureStorage", package: "SpeziStorage"), - .product(name: "SpeziOnboarding", package: "SpeziOnboarding") + .product(name: "SpeziChat", package: "SpeziChat"), + .product(name: "SpeziViews", package: "SpeziViews") ] ), .target( - name: "SpeziSpeechRecognizer" + name: "SpeziLLMLocal", + dependencies: [ + .target(name: "SpeziLLM"), + .product(name: "llama", package: "llama.cpp"), + .product(name: "Spezi", package: "Spezi") + ], + swiftSettings: [ + .interoperabilityMode(.Cxx) + ] ), .target( - name: "SpeziSpeechSynthesizer" + name: "SpeziLLMLocalDownload", + dependencies: [ + .product(name: "SpeziOnboarding", package: "SpeziOnboarding"), + .product(name: "SpeziViews", package: "SpeziViews") + ] + ), + .target( + name: "SpeziLLMOpenAI", + dependencies: [ + .product(name: "OpenAI", package: "OpenAI"), + .product(name: "Spezi", package: "Spezi"), + .product(name: "SpeziChat", package: "SpeziChat"), + .product(name: "SpeziLocalStorage", package: "SpeziStorage"), + .product(name: "SpeziSecureStorage", package: "SpeziStorage"), + .product(name: "SpeziSpeechRecognizer", package: "SpeziSpeech"), + .product(name: "SpeziOnboarding", package: "SpeziOnboarding") + ] ), .testTarget( - name: "SpeziOpenAITests", + name: "SpeziLLMTests", dependencies: [ - .target(name: "SpeziOpenAI") + .target(name: "SpeziLLMOpenAI") ] ) ] diff --git a/README.md b/README.md index 1e833d4..2f40a45 100644 --- a/README.md +++ b/README.md @@ -8,168 +8,148 @@ SPDX-License-Identifier: MIT --> -# Spezi ML +# Spezi LLM -[![Build and Test](https://github.com/StanfordSpezi/SpeziML/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/StanfordSpezi/SpeziML/actions/workflows/build-and-test.yml) -[![codecov](https://codecov.io/gh/StanfordSpezi/SpeziML/branch/main/graph/badge.svg?token=pptLyqtoNR)](https://codecov.io/gh/StanfordSpezi/SpeziML) +[![Build and Test](https://github.com/StanfordSpezi/SpeziLLM/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/StanfordSpezi/SpeziLLM/actions/workflows/build-and-test.yml) +[![codecov](https://codecov.io/gh/StanfordSpezi/SpeziLLM/branch/main/graph/badge.svg?token=pptLyqtoNR)](https://codecov.io/gh/StanfordSpezi/SpeziLLM) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7954213.svg)](https://doi.org/10.5281/zenodo.7954213) -[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStanfordSpezi%2FSpeziML%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/StanfordSpezi/SpeziML) -[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStanfordSpezi%2FSpeziML%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/StanfordSpezi/SpeziML) +[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStanfordSpezi%2FSpeziLLM%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/StanfordSpezi/SpeziLLM) +[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FStanfordSpezi%2FSpeziLLM%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/StanfordSpezi/SpeziLLM) -# Overview +## Overview -The Spezi ML Swift Package includes modules that are helpful to integrate ML-related functionality in your application. +The Spezi LLM Swift Package includes modules that are helpful to integrate LLM-related functionality in your application. +The package provides all necessary tools for local LLM execution as well as the usage of remote OpenAI-based LLMs. -# Spezi Open AI - -A module that allows you to interact with GPT-based large language models (LLMs) from OpenAI within your Spezi application. - -|Screenshot displaying the OpenAI API Key Onboarding view from Spezi OpenAI.|Screenshot displaying the Open AI Model Selection Onboarding Step from Spezi OpenAI.|Screenshot displaying the Chat View from Spezi OpenAI.| +|Screenshot displaying the Chat View utilizing the OpenAI API from SpeziLLMOpenAI.|Screenshot displaying the Local LLM Download View from SpeziLLMLocalDownload.|Screenshot displaying the Chat View utilizing a locally executed LLM via SpeziLLMLocal.| |:--:|:--:|:--:| -|`API Key Onboarding`|`Model Selection`|`Chat View`| - +|`OpenAI LLM Chat View`|`Language Model Download`|`Local LLM Chat View`| ## Setup -### 1. Add Spezi ML as a Dependency +### 1. Add Spezi LLM as a Dependency -First, you will need to add the SpeziML Swift package to +You need to add the SpeziLLM Swift package to [your app in Xcode](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app#) or -[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package). When adding the package, select the `SpeziOpenAI` target to add. +[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package). -### 2. Register the Open AI Module - -> [!IMPORTANT] +> [!IMPORTANT] > If your application is not yet configured to use Spezi, follow the [Spezi setup article](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/initial-setup) to set up the core Spezi infrastructure. -You can configure the `OpenAIModule` in the `SpeziAppDelegate` as follows. -In the example, we configure the `OpenAIModule` to use the GPT-4 model with a default API key. - -```swift -import Spezi -import SpeziOpenAI +### 2. Follow the setup steps of the individual targets +As Spezi LLM contains a variety of different targets for specific LLM functionalities, please follow the additional setup guide in the respective target section of this README. -class ExampleDelegate: SpeziAppDelegate { - override var configuration: Configuration { - Configuration { - OpenAIModule(apiToken: "API_KEY", openAIModel: .gpt4) - } - } -} -``` +## Targets -The OpenAIModule injects an ``OpenAIModel`` in the SwiftUI environment to make it accessible thoughout your application. +Spezi LLM provides a number of targets to help developers integrate LLMs in their Spezi-based applications: +- [SpeziLLM](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm): Base infrastructure of LLM execution in the Spezi ecosystem. +- [SpeziLLMLocal](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmlocal): Local LLM execution capabilities directly on-device. Integration with [Meta's Llama2 models](https://ai.meta.com/llama/). +- [SpeziLLMLocalDownload](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmlocaldownload): Download and storage manager of local Language Models, including onboarding views. +- [SpeziLLMOpenAI](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmopenai): Integration with [OpenAIs GPT models](https://openai.com/gpt-4) via using OpenAIs API service. -```swift -class ExampleView: View { - @Environment(OpenAIModel.self) var model +The section below highlights the setup and basic use of the [SpeziLLMLocal](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmlocal) and [SpeziLLMOpenAI](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmopenai) targets in order to integrate Language Models in a Spezi-based application. +> [!NOTE] +> To learn more about the usage of the individual targets, please refer to the [DocC documentation of the package] (https://swiftpackageindex.com/stanfordspezi/spezillm/documentation). - var body: some View { - // ... - } -} -``` +### Spezi LLM Local -> [!NOTE] -> The choice of model and API key are persisted across application launches. The `apiToken` and `openAIModel` can also be accessed and changed at runtime. +The target enables developers to easily execute medium-size Language Models (LLMs) locally on-device via the [llama.cpp framework](https://github.com/ggerganov/llama.cpp). The module allows you to interact with the locally run LLM via purely Swift-based APIs, no interaction with low-level C or C++ code is necessary. -The `SpeziOpenAI` package also provides an `OpenAIAPIKeyOnboardingStep` that can be used to allow the user to provide their API key during the onboarding process instead (see `Examples` below). If using the `OpenAIAPIKeyOnboardingStep`, the `apiToken` property can be omitted here. +#### Setup -> [!NOTE] -> You can learn more about a [`Module` in the Spezi documentation](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/module). +You can configure the Spezi Local LLM execution within the typical `SpeziAppDelegate`. +In the example below, the `LLMRunner` from the [SpeziLLM](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm) target which is responsible for providing LLM functionality within the Spezi ecosystem is configured with the `LLMLocalRunnerSetupTask` from the [SpeziLLMLocal](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmlocal) target. This prepares the `LLMRunner` to locally execute Language Models. -## Examples +``` +import Spezi +import SpeziLLM +import SpeziLLMLocal +import SpeziLLMOpenAI -### Creating a Chat Interface +class TestAppDelegate: SpeziAppDelegate { + override var configuration: Configuration { + Configuration { + LLMRunner { + LLMLocalRunnerSetupTask() + } + } + } +} +``` -In this example, we will create a chat interface that allows the user to converse with the model. Responses from the model will be streamed. +Spezi will then automatically inject the `LLMRunner` in the SwiftUI environment to make it accessible throughout your application. +The example below also showcases how to use the `LLMRunner` to execute a SpeziLLM-based [`LLM`](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm/llm). ```swift -import OpenAI -import SpeziOpenAI -import SwiftUI +class ExampleView: View { + @Environment(LLMRunner.self) var runner + @State var model: LLM = LLMLlama( + modelPath: URL(string: "...") // The locally stored Language Model File in the ".gguf" format + ) -struct OpenAIChatView: View { - @Environment(OpenAIModel.self) var model - @State private var chat: [Chat] - var body: some View { - ChatView($chat) - .onChange(of: chat) { _ in - let chatStreamResults = try await model.queryAPI(withChat: chat) + EmptyView() + .task { + // Returns an `AsyncThrowingStream` which yields the produced output of the LLM. + let stream = try await runner(with: model).generate(prompt: "Some example prompt") - for try await chatStreamResult in chatStreamResults { - for choice in chatStreamResult.choices { - guard let newContent = choice.delta.content else { - continue - } - - if chat.last?.role == .assistent, let previousContent = chat.last?.content { - chat[chat.count - 1] = Chat( - role: .assistant, - content: previousContent + newContent - ) - } else { - chat.append(Chat(role: .assistent, content: newContent)) - } - } - } + // ... } } } ``` -### Setting the API Key During Onboarding +> [!NOTE] +> To learn more about the usage of SpeziLLMLocal, please refer to the [DocC documentation]: (https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmlocal). -The `OpenAIAPIKeyOnboardingStep` provides a view that can be used for the user to enter an OpenAI API key during onboarding in your Spezi application. We will show an example of how you can add an OpenAI onboarding step within an application created from the Spezi Template Application below. +### Spezi LLM Open AI -First, create a new view to show the onboarding step: +A module that allows you to interact with GPT-based large language models (LLMs) from OpenAI within your Spezi application. -```swift -import SpeziOnboarding -import SpeziOpenAI -import SwiftUI +#### Setup +You can configure the `OpenAIModule` in the `SpeziAppDelegate` as follows. +In the example, we configure the `OpenAIModule` to use the GPT-4 model with a default API key. -struct OpenAIAPIKey: View { - @EnvironmentObject private var onboardingNavigationPath: OnboardingNavigationPath - - var body: some View { - OpenAIAPIKeyOnboardingStep { - onboardingNavigationPath.nextStep() +```swift +import Spezi +import SpeziLLMOpenAI + +class ExampleDelegate: SpeziAppDelegate { + override var configuration: Configuration { + Configuration { + OpenAIModule(apiToken: "API_KEY", openAIModel: .gpt4) } } } ``` -This view can then be added to the `OnboardingFlow` within the Spezi Template Application: +The OpenAIModule injects an `OpenAIModel` in the SwiftUI environment to make it accessible throughout your application. The model is queried via an instance of [`Chat` from the SpeziChat package](https://swiftpackageindex.com/stanfordspezi/spezichat/documentation/spezichat/chat). ```swift -import SpeziOnboarding -import SpeziOpenAI -import SwiftUI - +class ExampleView: View { + @Environment(OpenAIModel.self) var model + let chat: Chat = [ + .init(role: .user, content: "Example prompt!"), + ] -struct OnboardingFlow: View { - @AppStorage(StorageKeys.onboardingFlowComplete) var completedOnboardingFlow = false - - var body: some View { - OnboardingStack(onboardingFlowComplete: $completedOnboardingFlow) { - // ... other steps - OpenAIAPIKey() - // ... other steps - } + EmptyView() + .task { + // Returns an `AsyncThrowingStream` which yields the produced output of the LLM. + let stream = try model.queryAPI(withChat: chat) + + // ... + } } } ``` -Now the OpenAI API Key entry view will appear within your application's onboarding process. The API Key entered will be persisted across application launches. - -For more information, please refer to the [API documentation](https://swiftpackageindex.com/StanfordSpezi/SpeziML/documentation). +> [!NOTE] +> To learn more about the usage of SpeziLLMOpenAI, please refer to the [DocC documentation] (https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmopenai). ## Contributing @@ -178,7 +158,7 @@ Contributions to this project are welcome. Please make sure to read the [contrib ## License -This project is licensed under the MIT License. See [Licenses](https://github.com/StanfordSpezi/SpeziML/tree/main/LICENSES) for more information. +This project is licensed under the MIT License. See [Licenses](https://github.com/StanfordSpezi/SpeziLLM/tree/main/LICENSES) for more information. ![Spezi Footer](https://raw.githubusercontent.com/StanfordSpezi/.github/main/assets/FooterLight.png#gh-light-mode-only) ![Spezi Footer](https://raw.githubusercontent.com/StanfordSpezi/.github/main/assets/FooterDark.png#gh-dark-mode-only) diff --git a/Sources/SpeziLLM/Configuration/LLMRunnerConfiguration.swift b/Sources/SpeziLLM/Configuration/LLMRunnerConfiguration.swift new file mode 100644 index 0000000..8729301 --- /dev/null +++ b/Sources/SpeziLLM/Configuration/LLMRunnerConfiguration.swift @@ -0,0 +1,31 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + +/// The ``LLMRunnerConfiguration`` represents the configuration of the Spezi ``LLMRunner``. +public struct LLMRunnerConfiguration: Sendable { + /// The task priority of the initiated LLM inference tasks. + public let taskPriority: TaskPriority + /// Indicates if this is a device with non-unified memory access. + public let nonUniformMemoryAccess: Bool + + + /// Creates the ``LLMRunnerConfiguration`` which configures the Spezi ``LLMRunner``. + /// + /// - Parameters: + /// - taskPriority: The task priority of the initiated LLM inference tasks, defaults to `.userInitiated`. + /// - nonUniformMemoryAccess: Indicates if this is a device with non-unified memory access. + public init( + taskPriority: TaskPriority = .userInitiated, + nonUniformMemoryAccess: Bool = false + ) { + self.taskPriority = taskPriority + self.nonUniformMemoryAccess = nonUniformMemoryAccess + } +} diff --git a/Sources/SpeziLLM/Helpers/BundleDescription+Bundle.swift b/Sources/SpeziLLM/Helpers/BundleDescription+Bundle.swift new file mode 100644 index 0000000..41c1cfd --- /dev/null +++ b/Sources/SpeziLLM/Helpers/BundleDescription+Bundle.swift @@ -0,0 +1,18 @@ +// +// This source file is part of the Stanford Spezi open-source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + + +extension LocalizedStringResource.BundleDescription { + /// Convenience method to create a `BundleDescription.atURL()` from a given Bundle instance. + /// - Parameter bundle: The Bundle instance to retrieve the Bundle URL from. + public static func atURL(from bundle: Bundle) -> LocalizedStringResource.BundleDescription { + .atURL(bundle.bundleURL) + } +} diff --git a/Sources/SpeziLLM/LLM.swift b/Sources/SpeziLLM/LLM.swift new file mode 100644 index 0000000..f8f9103 --- /dev/null +++ b/Sources/SpeziLLM/LLM.swift @@ -0,0 +1,56 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + + +/// The ``LLM`` protocol provides an abstraction layer for the usage of Large Language Models within the Spezi ecosystem, +/// regardless of the execution locality (local or remote) or the specific model type. +/// Developers can use the ``LLM`` protocol to conform their LLM interface implementations to a standard which is consistent throughout the Spezi ecosystem. +/// +/// It is recommended that ``LLM`` should be used in conjunction with the [Swift Actor concept](https://developer.apple.com/documentation/swift/actor), meaning one should use the `actor` keyword (not `class`) for the implementation of the model component. The Actor concept provides guarantees regarding concurrent access to shared instances from multiple threads. +/// +/// - Important: An ``LLM`` shouldn't be executed on it's own but always used together with the ``LLMRunner``. +/// Please refer to the ``LLMRunner`` documentation for a complete code example. +/// +/// ### Usage +/// +/// An example conformance of the ``LLM`` looks like the code sample below (lots of details were omitted for simplicity). +/// The key point is the need to implement the ``LLM/setup(runnerConfig:)`` as well as the ``LLM/generate(prompt:continuation:)`` functions, whereas the ``LLM/setup(runnerConfig:)`` has an empty default implementation as not every ``LLMHostingType`` requires the need for a setup closure. +/// +/// ```swift +/// actor LLMTest: LLM { +/// var type: LLMHostingType = .local +/// var state: LLMState = .uninitialized +/// +/// func setup(/* */) async {} +/// func generate(/* */) async {} +/// } +/// ``` +public protocol LLM { + /// The type of the ``LLM`` as represented by the ``LLMHostingType``. + var type: LLMHostingType { get async } + /// The state of the ``LLM`` indicated by the ``LLMState``. + @MainActor var state: LLMState { get } + + + /// Performs any setup-related actions for the ``LLM``. + /// After this function completes, the state of the ``LLM`` should be ``LLMState/ready``. + /// + /// - Parameters: + /// - runnerConfig: The runner configuration as a ``LLMRunnerConfiguration``. + func setup(runnerConfig: LLMRunnerConfiguration) async throws + + /// Performs the actual text generation functionality of the ``LLM`` based on an input prompt `String`. + /// The result of the text generation is streamed via a Swift `AsyncThrowingStream` that is passed as a parameter. + /// + /// - Parameters: + /// - prompt: The input prompt `String` used for the text generation. + /// - continuation: A Swift `AsyncThrowingStream` enabling the streaming of the text generation. + func generate(prompt: String, continuation: AsyncThrowingStream.Continuation) async +} diff --git a/Sources/SpeziLLM/LLMError.swift b/Sources/SpeziLLM/LLMError.swift new file mode 100644 index 0000000..edc41b9 --- /dev/null +++ b/Sources/SpeziLLM/LLMError.swift @@ -0,0 +1,54 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + + +/// The ``LLMError`` describes possible errors that occur during the execution of the ``LLM`` via the ``LLMRunner``. +public enum LLMError: LocalizedError { + /// Indicates that the local model file is not found. + case modelNotFound + /// Indicates that the ``LLM`` is not yet ready, e.g., not initialized. + case modelNotReadyYet + /// Indicates that during generation an error occurred. + case generationError + + + public var errorDescription: String? { + switch self { + case .modelNotFound: + String(localized: LocalizedStringResource("LLM_MODEL_NOT_FOUND_ERROR_DESCRIPTION", bundle: .atURL(from: .module))) + case .modelNotReadyYet: + String(localized: LocalizedStringResource("LLM_MODEL_NOT_READY_ERROR_DESCRIPTION", bundle: .atURL(from: .module))) + case .generationError: + String(localized: LocalizedStringResource("LLM_GENERATION_ERROR_DESCRIPTION", bundle: .atURL(from: .module))) + } + } + + public var recoverySuggestion: String? { + switch self { + case .modelNotFound: + String(localized: LocalizedStringResource("LLM_MODEL_NOT_FOUND_RECOVERY_SUGGESTION", bundle: .atURL(from: .module))) + case .modelNotReadyYet: + String(localized: LocalizedStringResource("LLM_MODEL_NOT_READY_RECOVERY_SUGGESTION", bundle: .atURL(from: .module))) + case .generationError: + String(localized: LocalizedStringResource("LLM_GENERATION_ERROR_RECOVERY_SUGGESTION", bundle: .atURL(from: .module))) + } + } + + public var failureReason: String? { + switch self { + case .modelNotFound: + String(localized: LocalizedStringResource("LLM_MODEL_NOT_FOUND_FAILURE_REASON", bundle: .atURL(from: .module))) + case .modelNotReadyYet: + String(localized: LocalizedStringResource("LLM_MODEL_NOT_READY_FAILURE_REASON", bundle: .atURL(from: .module))) + case .generationError: + String(localized: LocalizedStringResource("LLM_GENERATION_ERROR_FAILURE_REASON", bundle: .atURL(from: .module))) + } + } +} diff --git a/Sources/SpeziLLM/LLMHostingType.swift b/Sources/SpeziLLM/LLMHostingType.swift new file mode 100644 index 0000000..ff22127 --- /dev/null +++ b/Sources/SpeziLLM/LLMHostingType.swift @@ -0,0 +1,17 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +/// The ``LLMHostingType`` indicates the hosting platform that a Spezi ``LLM`` should run on. +public enum LLMHostingType: String, CaseIterable { + /// Local, on-device execution of the ``LLM``. + case local + /// Execution of the ``LLM`` in the fog layer. + case fog + /// Remote, cloud-based execution of the ``LLM``. + case cloud +} diff --git a/Sources/SpeziLLM/LLMRunner.swift b/Sources/SpeziLLM/LLMRunner.swift new file mode 100644 index 0000000..f624a80 --- /dev/null +++ b/Sources/SpeziLLM/LLMRunner.swift @@ -0,0 +1,160 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import Spezi + +/// The ``LLMRunner`` is a Spezi `Module` that handles the execution of Large Language Models (LLMs) in the Spezi ecosystem. +/// A ``LLMRunner`` wraps a Spezi ``LLM`` during it's execution, handling all management overhead tasks of the models execution. +/// +/// The ``LLMRunner`` needs to be initialized in the Spezi `Configuration` with the ``LLMRunnerConfiguration`` as well as a set of ``LLMRunnerSetupTask``s as arguments. +/// +/// The runner manages a set of ``LLMGenerationTask``'s as well as the respective LLM execution backends in order to enable +/// a smooth and efficient model execution. +/// +/// ### Usage +/// +/// The code section below showcases a complete code example on how to use the ``LLMRunner`` in combination with a `LLMLlama` (locally executed Language Model) from the [SpeziLLMLocal](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm/spezillmlocal) target. +/// +/// ```swift +/// class LocalLLMAppDelegate: SpeziAppDelegate { +/// override var configuration: Configuration { +/// Configuration { +/// // Configure the runner responsible for executing LLMs +/// LLMRunner( +/// runnerConfig: .init( +/// taskPriority: .medium +/// ) +/// ) { +/// // Runner setup tasks conforming to `LLMRunnerSetupTask` protocol +/// LLMLocalRunnerSetupTask() +/// } +/// } +/// } +/// } +/// +/// struct LocalLLMChatView: View { +/// // The runner responsible for executing the local LLM. +/// @Environment(LLMRunner.self) private var runner: LLMRunner +/// +/// // The locally executed LLM +/// private let model: LLMLlama = .init( +/// modelPath: ... +/// ) +/// +/// @State var responseText: String +/// +/// func executePrompt(prompt: String) { +/// // Execute the query on the runner, returning a stream of outputs +/// let stream = try await runner(with: model).generate(prompt: "Hello LLM!") +/// +/// for try await token in stream { +/// responseText.append(token) +/// } +/// } +/// } +/// ``` +public actor LLMRunner: Module, DefaultInitializable, EnvironmentAccessible { + /// The ``State`` describes the current state of the ``LLMRunner``. + /// As of now, the ``State`` is quite minimal with only ``LLMRunner/State-swift.enum/idle`` and ``LLMRunner/State-swift.enum/processing`` states. + public enum State { + case idle + case processing + } + + + /// The configuration of the runner represented by ``LLMRunnerConfiguration``. + private let runnerConfiguration: LLMRunnerConfiguration + /// All to be performed ``LLMRunner``-related setup tasks. + private let runnerSetupTasks: [LLMHostingType: any LLMRunnerSetupTask] + /// Stores all currently available ``LLMGenerationTask``'s, one for each Spezi ``LLM``, identified by the ``LLMTaskIdentifier``. + private var runnerTasks: [LLMTaskIdentifier: LLMGenerationTask] = [:] + /// Indicates for which ``LLMHostingType`` the runner backend is already initialized. + private var runnerBackendInitialized: [LLMHostingType: Bool] = [:] + + /// The ``State`` of the runner, derived from the individual ``LLMGenerationTask``'s. + @MainActor public var state: State { + get async { + var state: State = .idle + + for runnerTask in await self.runnerTasks.values where await runnerTask.state == .generating { + state = .processing + } + + return state + } + } + + /// Creates the ``LLMRunner`` which is responsible for executing the Spezi ``LLM``'s. + /// + /// - Parameters: + /// - runnerConfig: The configuration of the ``LLMRunner`` represented by the ``LLMRunnerConfiguration``. + /// - content: A result builder that aggregates all stated ``LLMRunnerSetupTask``'s. + public init( + runnerConfig: LLMRunnerConfiguration = .init(), + @LLMRunnerSetupTaskBuilder _ content: @Sendable @escaping () -> _LLMRunnerSetupTaskCollection + ) { + self.runnerConfiguration = runnerConfig + self.runnerSetupTasks = content().runnerSetupTasks + + for modelType in LLMHostingType.allCases { + self.runnerBackendInitialized[modelType] = false + } + } + + /// Convenience initializer for the creation of a ``LLMRunner``. + public init() { + self.init(runnerConfig: .init()) {} + } + + + /// This call-as-a-function ``LLMRunner`` usage wraps a Spezi ``LLM`` and makes it ready for execution. + /// It manages a set of all ``LLMGenerationTask``'s, guaranteeing efficient model execution. + /// + /// - Parameters: + /// - with: The ``LLM`` that should be executed. + /// + /// - Returns: The ready to use ``LLMGenerationTask``. + public func callAsFunction(with model: any LLM) async -> LLMGenerationTask { + let modelType = await model.type + /// If necessary, setup of the runner backend + if runnerBackendInitialized[modelType] == false { + /// Initializes the required runner backends for the respective ``LLMHostingType``. + guard let task = self.runnerSetupTasks[modelType] else { + preconditionFailure(""" + A LLMRunnerSetupTask setting up the runner for a specific LLM environment was not found. + Please ensure that a LLMRunnerSetupTask is passed to the Spezi LLMRunner within the Spezi Configuration. + """) + } + + try? await task.setupRunner(runnerConfig: self.runnerConfiguration) + + runnerBackendInitialized[modelType] = true + } + + /// Check if a fitting ``LLMRunnerInferenceTask`` for that model already exists + let taskIdentifier = LLMTaskIdentifier(fromModel: model) + guard let runnerTask = runnerTasks[taskIdentifier] else { + let runnerTask = LLMGenerationTask(model: model, runnerConfig: runnerConfiguration) + runnerTasks[taskIdentifier] = runnerTask + return runnerTask + } + + return runnerTask + } + + + /// Upon deinit, cancel all ``LLMRunnerInferenceTask``'s. + deinit { + Task { + for runnerTask in await runnerTasks.values { + await runnerTask.task?.cancel() + } + } + } +} diff --git a/Sources/SpeziLLM/LLMState+OperationState.swift b/Sources/SpeziLLM/LLMState+OperationState.swift new file mode 100644 index 0000000..5e128d9 --- /dev/null +++ b/Sources/SpeziLLM/LLMState+OperationState.swift @@ -0,0 +1,26 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SpeziViews + +// Needs to be in a separate file as an extension in the file of the ``LLMState`` will lead to +// the "Circular reference resolving attached macro 'Observable'" error during compiling (see https://github.com/apple/swift/issues/66450) +/// Maps the ``LLMState`` to the SpeziViews `ViewState` via the conformance to the SpeziViews `OperationState` protocol. +extension LLMState: OperationState { + public var representation: ViewState { + switch self { + case .uninitialized, .ready: + .idle + case .generating, .loading: + .processing + case .error(let error): + .error(error) + } + } +} diff --git a/Sources/SpeziLLM/LLMState.swift b/Sources/SpeziLLM/LLMState.swift new file mode 100644 index 0000000..1729db8 --- /dev/null +++ b/Sources/SpeziLLM/LLMState.swift @@ -0,0 +1,36 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + +/// The ``LLMState`` describes possible states that the LLM can be in. +/// Based on the ``LLMState``, `SpeziLLM` performs proper actions on the model as well as state management. +public enum LLMState: CustomStringConvertible, Equatable { + /// The Spezi ``LLM`` is allocated, but the underlying llama.cpp model has not yet been initialized. + case uninitialized + /// The Spezi ``LLM`` is in the process of being initialized, so the model file is loaded from memory. + case loading + /// The Spezi ``LLM`` as well as the underlying llama.cpp model is initialized and ready for use. + case ready + /// The Spezi ``LLM`` is currently in the process of generating an output. + case generating + /// The Spezi ``LLM`` is in an error state as described by the associated value ``LLMError``. + case error(error: LLMError) + + + /// A textual description of the current ``LLMState``. + public var description: String { + switch self { + case .uninitialized: String(localized: LocalizedStringResource("LLM_STATE_UNINITIALIZED", bundle: .atURL(from: .module))) + case .loading: String(localized: LocalizedStringResource("LLM_STATE_LOADING", bundle: .atURL(from: .module))) + case .ready: String(localized: LocalizedStringResource("LLM_STATE_READY", bundle: .atURL(from: .module))) + case .generating: String(localized: LocalizedStringResource("LLM_STATE_GENERATING", bundle: .atURL(from: .module))) + case .error: String(localized: LocalizedStringResource("LLM_STATE_ERROR", bundle: .atURL(from: .module))) + } + } +} diff --git a/Sources/SpeziLLM/Mock/LLMMock.swift b/Sources/SpeziLLM/Mock/LLMMock.swift new file mode 100644 index 0000000..e2dcb45 --- /dev/null +++ b/Sources/SpeziLLM/Mock/LLMMock.swift @@ -0,0 +1,39 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + + +/// A mock SpeziLLM ``LLM`` that is used for testing and preview purposes. +public actor LLMMock: LLM { + public let type: LLMHostingType = .local + @MainActor public var state: LLMState = .uninitialized + + + public init() {} + + + public func setup(runnerConfig: LLMRunnerConfiguration) async throws { + await MainActor.run { + self.state = .ready + } + } + + public func generate(prompt: String, continuation: AsyncThrowingStream.Continuation) async { + /// Generate mock message + try? await Task.sleep(for: .seconds(1)) + continuation.yield("Mock ") + try? await Task.sleep(for: .milliseconds(500)) + continuation.yield("Message ") + try? await Task.sleep(for: .milliseconds(500)) + continuation.yield("from ") + try? await Task.sleep(for: .milliseconds(500)) + continuation.yield("SpeziLLM!") + continuation.finish() + } +} diff --git a/Sources/SpeziLLM/Resources/Localizable.xcstrings b/Sources/SpeziLLM/Resources/Localizable.xcstrings new file mode 100644 index 0000000..288773c --- /dev/null +++ b/Sources/SpeziLLM/Resources/Localizable.xcstrings @@ -0,0 +1,157 @@ +{ + "sourceLanguage" : "en", + "strings" : { + "CHAT_VIEW_TITLE" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spezi LLM Chat" + } + } + } + }, + "LLM_GENERATION_ERROR_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generation of LLM output failed." + } + } + } + }, + "LLM_GENERATION_ERROR_FAILURE_REASON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An unknown error has occurred during the generation of the output." + } + } + } + }, + "LLM_GENERATION_ERROR_RECOVERY_SUGGESTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ensure that the device has enough free computing and memory resources. Try restarting the application." + } + } + } + }, + "LLM_MODEL_NOT_FOUND_ERROR_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM file not found." + } + } + } + }, + "LLM_MODEL_NOT_FOUND_FAILURE_REASON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The specified LLM file could not be found on the device." + } + } + } + }, + "LLM_MODEL_NOT_FOUND_RECOVERY_SUGGESTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ensure that the LLM file is downloaded successfully and properly stored on the device. Try restarting the application." + } + } + } + }, + "LLM_MODEL_NOT_READY_ERROR_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM not ready yet." + } + } + } + }, + "LLM_MODEL_NOT_READY_FAILURE_REASON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The LLM needs to be initialized before usage." + } + } + } + }, + "LLM_MODEL_NOT_READY_RECOVERY_SUGGESTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Make sure that the application initialized the LLM properly. Try restarting the application." + } + } + } + }, + "LLM_STATE_ERROR" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM state error." + } + } + } + }, + "LLM_STATE_GENERATING" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM state generating." + } + } + } + }, + "LLM_STATE_LOADING" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM state loading." + } + } + } + }, + "LLM_STATE_READY" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM state ready." + } + } + } + }, + "LLM_STATE_UNINITIALIZED" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM state uninitialized." + } + } + } + } + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/Sources/SpeziLLM/Resources/Localizable.xcstrings.license b/Sources/SpeziLLM/Resources/Localizable.xcstrings.license new file mode 100644 index 0000000..6917c4b --- /dev/null +++ b/Sources/SpeziLLM/Resources/Localizable.xcstrings.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziLLM/SpeziLLM.docc/SpeziLLM.md b/Sources/SpeziLLM/SpeziLLM.docc/SpeziLLM.md new file mode 100644 index 0000000..2048047 --- /dev/null +++ b/Sources/SpeziLLM/SpeziLLM.docc/SpeziLLM.md @@ -0,0 +1,162 @@ +# ``SpeziLLM`` + + + +Provides base Large Language Model (LLM) execution infrastructure within the Spezi ecosystem. + +## Overview + +The ``SpeziLLM`` target provides the base infrastructure for Large Language Model (LLM) execution within the Swift-based Spezi ecosystem. It contains necessary abstractions of LLMs that can be reused in an arbitrary context as well as a runner component handling the actual inference of the Language Model. + +## Setup + +### Add Spezi LLM as a Dependency + +You need to add the SpeziLLM Swift package to +[your app in Xcode](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app#) or +[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package). + +> Important: If your application is not yet configured to use Spezi, follow the [Spezi setup article](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/initial-setup) to set up the core Spezi infrastructure. + +## Spezi LLM Components + +The two main components of ``SpeziLLM`` are the ``LLM`` abstraction as well as the ``LLMRunner`` execution capability. The following section highlights the usage of these parts. + +### LLM abstraction + +``SpeziLLM`` provides the ``LLM`` protocol which provides an abstraction of an arbitrary Language Model, regardless of the execution locality (local or remote) or the specific model type. +Developers can use the ``LLM`` protocol to conform their LLM interface implementations to a standard which is consistent throughout the Spezi ecosystem. +It is recommended that ``LLM`` should be used in conjunction with the [Swift Actor concept](https://developer.apple.com/documentation/swift/actor), meaning one should use the `actor` keyword (not `class`) for the implementation of the model component. The Actor concept provides guarantees regarding concurrent access to shared instances from multiple threads. + +> Important: An ``LLM`` shouldn't be executed on it's own but always used together with the ``LLMRunner``. +> Please refer to the ``LLMRunner`` documentation for a complete code example. + +#### Usage + +An example conformance of the ``LLM`` looks like the code sample below (lots of details were omitted for simplicity). +The key point is the need to implement the ``LLM/setup(runnerConfig:)`` as well as the ``LLM/generate(prompt:continuation:)`` functions, whereas the ``LLM/setup(runnerConfig:)`` has an empty default implementation as not every ``LLMHostingType`` requires the need for a setup closure. + +```swift +actor LLMTest: LLM { + var type: LLMHostingType = .local + var state: LLMState = .uninitialized + + func setup(/* */) async {} + func generate(/* */) async {} +} +``` + +### LLM runner + +The ``LLMRunner`` is a Spezi `Module` that handles the execution of Language Models in the Spezi ecosystem, regardless of their execution locality (local or remote) or the specific model type. A ``LLMRunner`` wraps a Spezi ``LLM`` during it's execution, handling all management overhead tasks of the models execution. + +The runner manages a set of ``LLMGenerationTask``'s as well as the respective LLM execution backends in order to enable a smooth and efficient model execution. + +#### Setup + +The ``LLMRunner`` needs to be initialized in the Spezi `Configuration` with the ``LLMRunnerConfiguration`` as well as a set of ``LLMRunnerSetupTask``s as arguments. + +```swift +class LocalLLMAppDelegate: SpeziAppDelegate { + override var configuration: Configuration { + Configuration { + // Configure the runner responsible for executing LLMs + LLMRunner( + runnerConfig: .init( + taskPriority: .medium + ) + ) { + // Runner setup tasks conforming to `LLMRunnerSetupTask` protocol + LLMLocalRunnerSetupTask() + } + } + } +} +``` + +#### Usage + +The code section below showcases a complete code example on how to use the ``LLMRunner`` in combination with a `LLMLlama` (locally executed Language Model) from the [SpeziLLMLocal](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmlocal) target. + +```swift +import SpeziLLMLocal +// ... + +struct LocalLLMChatView: View { + // The runner responsible for executing the local LLM. + @Environment(LLMRunner.self) private var runner: LLMRunner + + // The locally executed LLM + private let model: LLMLlama = .init( + modelPath: ... + ) + + @State var responseText: String + + func executePrompt(prompt: String) { + // Execute the query on the runner, returning a stream of outputs + let stream = try await runner(with: model).generate(prompt: "Hello LLM!") + + for try await token in stream { + responseText.append(token) + } + } +} +``` + +### LLM Chat View + +The ``LLMChatView`` presents a basic chat view that enables users to chat with a Spezi ``LLM`` in a typical chat-like fashion. The input can be either typed out via the iOS keyboard or provided as voice input and transcribed into written text. +The ``LLMChatView`` takes an ``LLM`` instance as well as initial assistant prompt as arguments to configure the chat properly. + +> Tip: The ``LLMChatView`` builds on top of the [SpeziChat package](https://swiftpackageindex.com/stanfordspezi/spezichat/documentation). +> For more details, please refer to the DocC documentation of the [`ChatView`](https://swiftpackageindex.com/stanfordspezi/spezichat/documentation/spezichat/chatview). + +#### Usage + +An example usage of the ``LLMChatView`` can be seen in the following example. +The example uses the ``LLMMock`` as the passed ``LLM`` instance in order to provide a default output generation stream. + +```swift +struct LLMLocalChatTestView: View { + var body: some View { + LLMChatView( + model: LLMMock(), + initialAssistantPrompt: [ + .init( + role: .assistant, + content: "Hello!" + ) + ] + ) + } +} +``` + +## Topics + +### Model + +- ``LLM`` +- ``LLMState`` +- ``LLMError`` +- ``LLMHostingType`` + +### Execution + +- ``LLMRunner`` +- ``LLMRunnerConfiguration`` +- ``LLMGenerationTask`` +- ``LLMRunnerSetupTask`` + +### Views + +- ``LLMChatView`` diff --git a/Sources/SpeziLLM/Tasks/LLMGenerationTask.swift b/Sources/SpeziLLM/Tasks/LLMGenerationTask.swift new file mode 100644 index 0000000..9bb417a --- /dev/null +++ b/Sources/SpeziLLM/Tasks/LLMGenerationTask.swift @@ -0,0 +1,85 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + + +/// The ``LLMGenerationTask`` with the specific responsibility to handle LLM generation tasks. +/// It wraps a Spezi ``LLM`` and performs management overhead tasks. +/// +/// A code example on how to use ``LLMGenerationTask`` in combination with the ``LLMRunner`` can be +/// found in the documentation of the ``LLMRunner``. +public actor LLMGenerationTask { + /// The ``LLM`` which is executed by the ``LLMGenerationTask``. + let model: any LLM + /// The configuration of the ``LLMRunner``. + let runnerConfig: LLMRunnerConfiguration + /// A task managing the ``LLM` output generation. + var task: Task<(), Never>? + + + /// The `LLMTaskIdentifier` of the ``LLMGenerationTask``. + var id: LLMTaskIdentifier { + get async { + .init(fromModel: model) + } + } + + /// Describes the state of the ``LLM`` as a ``LLMState``. + public var state: LLMState { + get async { + await self.model.state + } + } + + + /// Creates the ``LLMGenerationTask`` based on the respective ``LLM``. + /// + /// - Parameters: + /// - model: The ``LLM`` that should be executed. + /// - runnerConfig: The configuration of the ``LLMRunner``. + init(model: any LLM, runnerConfig: LLMRunnerConfiguration) { + self.model = model + self.runnerConfig = runnerConfig + } + + + /// Starts the LLM output generation based on an input prompt. + /// Handles management takes like the initial setup of the ``LLM``. + /// + /// - Parameters: + /// - prompt: The `String` that should be used as an input to the ``LLM`` + /// + /// - Returns: An asynchronous stream of the ``LLM`` generation results. + public func generate(prompt: String) async throws -> AsyncThrowingStream { + let (stream, continuation) = AsyncThrowingStream.makeStream(of: String.self) + + /// Setup the model if necessary. + if await self.model.state == .uninitialized { + try await model.setup(runnerConfig: self.runnerConfig) + } + + /// Execute the LLM generation. + switch await model.state { + case .ready, .error: + self.task = Task(priority: self.runnerConfig.taskPriority) { + await model.generate(prompt: prompt, continuation: continuation) + } + + return stream + default: + throw LLMError.modelNotReadyYet + } + } + + + /// Upon deinit, cancel the LLM `Task`. + deinit { + task?.cancel() + } +} diff --git a/Sources/SpeziLLM/Tasks/LLMRunnerSetupTask.swift b/Sources/SpeziLLM/Tasks/LLMRunnerSetupTask.swift new file mode 100644 index 0000000..69b713e --- /dev/null +++ b/Sources/SpeziLLM/Tasks/LLMRunnerSetupTask.swift @@ -0,0 +1,33 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + + +/// The ``LLMRunnerSetupTask`` provides an abstraction of different runner-related setup `Task`'s. +/// These setup tasks must be stated within the Spezi ``LLMRunner`` initializer in order to properly configure the local environment for executing Spezi `LLM`s. +/// +/// ```swift +/// class LLMAppDelegate: SpeziAppDelegate { +/// override var configuration: Configuration { +/// Configuration { +/// LLMRunner { +/// // Concrete `LLMRunnerSetupTask`s +/// ... +/// } +/// } +/// } +/// } +public protocol LLMRunnerSetupTask { + /// The ``LLMHostingType`` that the ``LLMRunnerSetupTask`` sets up. + var type: LLMHostingType { get } + + + /// Performs runner setup-related actions for the ``LLMRunner``. + func setupRunner(runnerConfig: LLMRunnerConfiguration) async throws +} diff --git a/Sources/SpeziLLM/Tasks/LLMRunnerSetupTaskBuilder.swift b/Sources/SpeziLLM/Tasks/LLMRunnerSetupTaskBuilder.swift new file mode 100644 index 0000000..bc0a133 --- /dev/null +++ b/Sources/SpeziLLM/Tasks/LLMRunnerSetupTaskBuilder.swift @@ -0,0 +1,58 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SwiftUI + + +/// A result builder used to aggregate multiple Spezi ``LLMRunnerSetupTask``s within the ``LLMRunner``. +@resultBuilder +@_documentation(visibility: internal) +public enum LLMRunnerSetupTaskBuilder { + /// If declared, provides contextual type information for statement expressions to translate them into partial results. + public static func buildExpression(_ expression: any LLMRunnerSetupTask) -> [any LLMRunnerSetupTask] { + [expression] + } + + /// Required by every result builder to build combined results from statement blocks. + public static func buildBlock(_ children: [any LLMRunnerSetupTask]...) -> [any LLMRunnerSetupTask] { + children.flatMap { $0 } + } + + /// Enables support for `if` statements that do not have an `else`. + public static func buildOptional(_ component: [any LLMRunnerSetupTask]?) -> [any LLMRunnerSetupTask] { + // swiftlint:disable:previous discouraged_optional_collection + // The optional collection is a requirement defined by @resultBuilder, we can not use a non-optional collection here. + component ?? [] + } + + /// With buildEither(second:), enables support for 'if-else' and 'switch' statements by folding conditional results into a single result. + public static func buildEither(first: [any LLMRunnerSetupTask]) -> [any LLMRunnerSetupTask] { + first + } + + /// With buildEither(first:), enables support for 'if-else' and 'switch' statements by folding conditional results into a single result. + public static func buildEither(second: [any LLMRunnerSetupTask]) -> [any LLMRunnerSetupTask] { + second + } + + /// Enables support for 'for..in' loops by combining the results of all iterations into a single result. + public static func buildArray(_ components: [[any LLMRunnerSetupTask]]) -> [any LLMRunnerSetupTask] { + components.flatMap { $0 } + } + + /// If declared, this will be called on the partial result of an 'if #available' block to allow the result builder to erase type information. + public static func buildLimitedAvailability(_ component: [any LLMRunnerSetupTask]) -> [any LLMRunnerSetupTask] { + component + } + + /// If declared, this will be called on the partial result from the outermost block statement to produce the final returned result. + public static func buildFinalResult(_ component: [any LLMRunnerSetupTask]) -> _LLMRunnerSetupTaskCollection { + _LLMRunnerSetupTaskCollection(runnerSetupTasks: component) + } +} diff --git a/Sources/SpeziLLM/Tasks/LLMRunnerSetupTaskCollection.swift b/Sources/SpeziLLM/Tasks/LLMRunnerSetupTaskCollection.swift new file mode 100644 index 0000000..d84f88f --- /dev/null +++ b/Sources/SpeziLLM/Tasks/LLMRunnerSetupTaskCollection.swift @@ -0,0 +1,33 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SwiftUI + + +/// A `_LLMRunnerSetupTaskCollection` defines a collection of Spezi ``LLMRunnerSetupTask``s that are defined with a ``LLMRunner``. +/// +/// You can not create a `_LLMRunnerSetupTaskCollection` yourself. Please use the ``LLMRunner`` that internally creates a `_LLMRunnerSetupTaskCollection` with the passed views. +public struct _LLMRunnerSetupTaskCollection { // swiftlint:disable:this type_name + let runnerSetupTasks: [LLMHostingType: any LLMRunnerSetupTask] + + + init(runnerSetupTasks: [any LLMRunnerSetupTask]) { + self.runnerSetupTasks = runnerSetupTasks.reduce(into: [LLMHostingType: any LLMRunnerSetupTask]()) { partialResult, runnerSetupTask in + /// Check if there are no duplicate ``LLMRunnerSetupTask``'s for the same ``LLMHostingType``. + guard partialResult[runnerSetupTask.type] == nil else { + fatalError(""" + LLMRunner was initialized with LLMRunnerSetupTasks's of the same LLMHostingType type. + Ensure that only one LLMRunnerSetupTask is responsible for setting up the runner of one LLMHostingType. + """) + } + + partialResult[runnerSetupTask.type] = runnerSetupTask + } + } +} diff --git a/Sources/SpeziLLM/Tasks/LLMTaskIdentifier.swift b/Sources/SpeziLLM/Tasks/LLMTaskIdentifier.swift new file mode 100644 index 0000000..db644ec --- /dev/null +++ b/Sources/SpeziLLM/Tasks/LLMTaskIdentifier.swift @@ -0,0 +1,25 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + + +/// An identifier for a ``LLMGenerationTask` based on the respective ``LLM``. +struct LLMTaskIdentifier: Hashable { + /// The wrapped identifier of the `LLM``. + let taskIdentifier: String + + + /// Creates the `LLMTaskIdentifier` identifying ``LLM``'s. + /// + /// - Parameters: + /// - fromModel: The ``LLM`` that should be identified. + init(fromModel model: any LLM) { + self.taskIdentifier = String(describing: type(of: model)) + } +} diff --git a/Sources/SpeziLLM/Views/LLMChatView.swift b/Sources/SpeziLLM/Views/LLMChatView.swift new file mode 100644 index 0000000..6bf9817 --- /dev/null +++ b/Sources/SpeziLLM/Views/LLMChatView.swift @@ -0,0 +1,101 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SpeziChat +import SpeziViews +import SwiftUI + + +/// Presents a basic chat view that enables users to chat with a Spezi ``LLM`` in a typical chat-like fashion. +/// The input can be either typed out via the iOS keyboard or provided as voice input and transcribed into written text. +/// The ``LLMChatView`` takes an ``LLM`` instance as well as initial assistant prompt as arguments to configure the chat properly. +/// +/// > Tip: The ``LLMChatView`` builds on top of the [SpeziChat package](https://swiftpackageindex.com/stanfordspezi/spezichat/documentation). +/// > For more details, please refer to the DocC documentation of the [`ChatView`](https://swiftpackageindex.com/stanfordspezi/spezichat/documentation/spezichat/chatview). +/// +/// ### Usage +/// +/// An example usage of the ``LLMChatView`` can be seen in the following example. +/// The example uses the ``LLMMock`` as the passed ``LLM`` instance in order to provide a default output generation stream. +/// +/// ```swift +/// struct LLMLocalChatTestView: View { +/// var body: some View { +/// LLMChatView( +/// model: LLMMock(), +/// initialAssistantPrompt: [ +/// .init( +/// role: .assistant, +/// content: "Hello!" +/// ) +/// ] +/// ) +/// } +/// } +/// ``` +public struct LLMChatView: View { + /// A ``LLMRunner`` is responsible for executing the ``LLM``. Must be configured via the Spezi `Configuration`. + @Environment(LLMRunner.self) private var runner + /// Represents the chat content that is displayed. + @State private var chat: Chat = [] + /// Indicates if the input field is disabled. + @State private var inputDisabled = false + /// Indicates the state of the view, get's derived from the ``LLM/state``. + @State private var viewState: ViewState = .idle + + /// A SpeziLLM ``LLM`` that is used for the text generation within the chat view + @State private var model: any LLM + + + public var body: some View { + ChatView($chat, disableInput: $inputDisabled) + .onChange(of: chat) { oldValue, newValue in + /// Once the user enters a message in the chat, send a request to the local LLM. + if oldValue.count != newValue.count, + let lastChat = newValue.last, lastChat.role == .user { + Task { + inputDisabled = true + + /// Stream the LLMs response via an `AsyncThrowingStream` + let stream = try await runner(with: model).generate(prompt: lastChat.content) + chat.append(.init(role: .assistant, content: "")) + + for try await token in stream { + let lastMessageContent = chat.last?.content ?? "" + chat[chat.count - 1] = .init(role: .assistant, content: lastMessageContent + token) + } + + inputDisabled = false + } + } + } + .viewStateAlert(state: model.state) + } + + + /// Creates a ``LLMChatView`` that provides developers with a basic chat view towards a SpeziLLM ``LLM``. + /// + /// - Parameters: + /// - model: The SpeziLLM ``LLM`` that should be used for the text generation. + /// - initialAssistantPrompt: The initial message of the LLM assistant. + public init( + model: any LLM, + initialAssistantPrompt chat: Chat + ) { + self._model = State(wrappedValue: model) + self._chat = State(wrappedValue: chat) + } +} + + +#Preview { + LLMChatView( + model: LLMMock(), + initialAssistantPrompt: [.init(role: .assistant, content: "Hello world!")] + ) +} diff --git a/Sources/SpeziLLMLocal/Configuration/LLMContextParameters.swift b/Sources/SpeziLLMLocal/Configuration/LLMContextParameters.swift new file mode 100644 index 0000000..ea8c438 --- /dev/null +++ b/Sources/SpeziLLMLocal/Configuration/LLMContextParameters.swift @@ -0,0 +1,177 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import llama + + +/// The ``LLMContextParameters`` represents the context parameters of the LLM. +/// Internally, these data points are passed as a llama.cpp `llama_context_params` C struct to the LLM. +public struct LLMContextParameters: Sendable { + /// Wrapped C struct from the llama.cpp library, later-on passed to the LLM + private var wrapped: llama_context_params + + + /// Context parameters in llama.cpp's low-level C representation + var llamaCppRepresentation: llama_context_params { + wrapped + } + + /// RNG seed of the LLM + var seed: UInt32 { + get { + wrapped.seed + } + set { + wrapped.seed = newValue + } + } + + /// Context window size in tokens (0 = take default window size from model) + var contextWindowSize: UInt32 { + get { + wrapped.n_ctx + } + set { + wrapped.n_ctx = newValue + } + } + + /// Maximum batch size during prompt processing + var batchSize: UInt32 { + get { + wrapped.n_batch + } + set { + wrapped.n_batch = newValue + } + } + + /// Number of threads used by LLM for generation of output + var threadCount: UInt32 { + get { + wrapped.n_threads + } + set { + wrapped.n_threads = newValue + } + } + + /// Number of threads used by LLM for batch processing + var threadCountBatch: UInt32 { + get { + wrapped.n_threads_batch + } + set { + wrapped.n_threads_batch = newValue + } + } + + /// RoPE base frequency (0 = take default from model) + var ropeFreqBase: Float { + get { + wrapped.rope_freq_base + } + set { + wrapped.rope_freq_base = newValue + } + } + + /// RoPE frequency scaling factor (0 = take default from model) + var ropeFreqScale: Float { + get { + wrapped.rope_freq_scale + } + set { + wrapped.rope_freq_scale = newValue + } + } + + /// Set the usage of experimental `mul_mat_q` kernels + var useMulMatQKernels: Bool { + get { + wrapped.mul_mat_q + } + set { + wrapped.mul_mat_q = newValue + } + } + + /// If `true`, use fp16 for KV cache, fp32 otherwise + var useFp16Cache: Bool { + get { + wrapped.f16_kv + } + set { + wrapped.f16_kv = newValue + } + } + + /// If `true`, the (deprecated) `llama_eval()` call computes all logits, not just the last one + var computeAllLogits: Bool { + get { + wrapped.logits_all + } + set { + wrapped.logits_all = newValue + } + } + + /// If `true`, the mode is set to embeddings only + var embeddingsOnly: Bool { + get { + wrapped.embedding + } + set { + wrapped.embedding = newValue + } + } + + /// Creates the ``LLMContextParameters`` which wrap the underlying llama.cpp `llama_context_params` C struct. + /// Is passed to the underlying llama.cpp model in order to configure the context of the LLM. + /// + /// - Parameters: + /// - seed: RNG seed of the LLM, defaults to `4294967295` (which represents a random seed). + /// - contextWindowSize: Context window size in tokens, defaults to `1024`. + /// - batchSize: Maximum batch size during prompt processing, defaults to `1024` tokens. + /// - threadCount: Number of threads used by LLM for generation of output, defaults to the processor count of the device. + /// - threadCountBatch: Number of threads used by LLM for batch processing, defaults to the processor count of the device. + /// - ropeFreqBase: RoPE base frequency, defaults to `0` indicating the default from model. + /// - ropeFreqScale: RoPE frequency scaling factor, defaults to `0` indicating the default from model. + /// - useMulMatQKernels: Usage of experimental `mul_mat_q` kernels, defaults to `true`. + /// - useFp16Cache: Usage of fp16 for KV cache, fp32 otherwise, defaults to `true`. + /// - computeAllLogits: `llama_eval()` call computes all logits, not just the last one. Defaults to `false`. + /// - embeddingsOnly: Embedding-only mode, defaults to `false`. + public init( + seed: UInt32 = 4294967295, + contextWindowSize: UInt32 = 1024, + batchSize: UInt32 = 1024, + threadCount: UInt32 = .init(ProcessInfo.processInfo.processorCount), + threadCountBatch: UInt32 = .init(ProcessInfo.processInfo.processorCount), + ropeFreqBase: Float = 0.0, + ropeFreqScale: Float = 0.0, + useMulMatQKernels: Bool = true, + useFp16Cache: Bool = true, + computeAllLogits: Bool = false, + embeddingsOnly: Bool = false + ) { + self.wrapped = llama_context_default_params() + + self.seed = seed + self.contextWindowSize = contextWindowSize + self.batchSize = batchSize + self.threadCount = threadCount + self.threadCountBatch = threadCountBatch + self.ropeFreqBase = ropeFreqBase + self.ropeFreqScale = ropeFreqScale + self.useMulMatQKernels = useMulMatQKernels + self.useFp16Cache = useFp16Cache + self.computeAllLogits = computeAllLogits + self.embeddingsOnly = embeddingsOnly + } +} diff --git a/Sources/SpeziLLMLocal/Configuration/LLMParameters.swift b/Sources/SpeziLLMLocal/Configuration/LLMParameters.swift new file mode 100644 index 0000000..cbb52d2 --- /dev/null +++ b/Sources/SpeziLLMLocal/Configuration/LLMParameters.swift @@ -0,0 +1,175 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import llama + + +/// The ``LLMParameters`` represents the parameters of the LLM. +/// Internally, these data points are passed as a llama.cpp `llama_model_params` C struct to the LLM. +public struct LLMParameters: Sendable { + /// Typealias for an internal llama.cpp progress callback function + public typealias LlamaProgressCallback = (@convention(c) (Float, UnsafeMutableRawPointer?) -> Void) + + + /// Defaults of possible LLMs parameter settings. + public enum Defaults { + public static let defaultLlama2SystemPrompt: String = { + String(localized: LocalizedStringResource("SPEZI_LLM_LOCAL_LLAMA_SYSTEM_PROMPT", bundle: .atURL(from: .module))) + }() + } + + + /// The to-be-used system prompt of the LLM + let systemPrompt: String + /// Indicates the maximum output length generated by the ``LLM``. + let maxOutputLength: Int + /// Indicates whether the BOS token is added by the ``LLM``. If `nil`, the default from the model itself is taken. + let addBosToken: Bool + + + /// Wrapped C struct from the llama.cpp library, later-on passed to the LLM + private var wrapped: llama_model_params + + + /// Model parameters in llama.cpp's low-level C representation + var llamaCppRepresentation: llama_model_params { + wrapped + } + + /// Number of layers to store in VRAM + /// - Note: On iOS simulators, this property has to be set to 0 (which is automatically done by the library). + var gpuLayerCount: Int32 { + get { + wrapped.n_gpu_layers + } + set { + wrapped.n_gpu_layers = newValue + } + } + + /// Indicates the GPU that is used for scratch and small tensors. + var mainGpu: Int32 { + get { + wrapped.main_gpu + } + set { + wrapped.main_gpu = newValue + } + } + + /// Indicates how to split layers across multiple GPUs. + var tensorSplit: UnsafePointer? { + get { + wrapped.tensor_split + } + set { + wrapped.tensor_split = newValue + } + } + + /// Progress callback called with a progress value between 0 and 1 + var progressCallback: LlamaProgressCallback? { + get { + wrapped.progress_callback + } + set { + wrapped.progress_callback = newValue + } + } + + /// Context pointer that is passed to the progress callback + var progressCallbackUserData: UnsafeMutableRawPointer? { + get { + wrapped.progress_callback_user_data + } + set { + wrapped.progress_callback_user_data = newValue + } + } + + /// Indicates wether booleans should be kept together to avoid misalignment during copy-by-value. + var vocabOnly: Bool { + get { + wrapped.vocab_only + } + set { + wrapped.vocab_only = newValue + } + } + + /// Indicates if mmap should be used. + var useMmap: Bool { + get { + wrapped.use_mmap + } + set { + wrapped.use_mmap = newValue + } + } + + /// Forces the system to keep model in RAM. + var useMlock: Bool { + get { + wrapped.use_mlock + } + set { + wrapped.use_mlock = newValue + } + } + + + /// Creates the ``LLMParameters`` which wrap the underlying llama.cpp `llama_model_params` C struct. + /// Is passed to the underlying llama.cpp model in order to configure the LLM. + /// + /// - Parameters: + /// - systemPromot: The to-be-used system prompt of the LLM enabling fine-tuning of the LLMs behaviour. Defaults to the regular Llama2 system prompt. + /// - maxOutputLength: The maximum output length generated by the Spezi `LLM`, defaults to `1024`. + /// - addBosToken: Indicates wether the BOS token is added by the Spezi `LLM`, defaults to `false`. + /// - gpuLayerCount: Number of layers to store in VRAM, defaults to `1`, meaning Apple's `Metal` framework is enabled. + /// - mainGpu: GPU that is used for scratch and small tensors, defaults to `0` representing the main GPU. + /// - tensorSplit: Split layers across multiple GPUs, defaults to `nil`, meaning no split. + /// - progressCallback: Progress callback called with a progress value between 0 and 1, defaults to `nil`. + /// - progressCallbackUserData: Context pointer that is passed to the progress callback, defaults to `nil`. + /// - vocabOnly: Indicates wether booleans should be kept together to avoid misalignment during copy-by-value., defaults to `false`. + /// - useMmap: Indicates if mmap should be used., defaults to `true`. + /// - useMlock: Forces the system to keep model in RAM, defaults to `false`. + public init( + systemPrompt: String = Defaults.defaultLlama2SystemPrompt, + maxOutputLength: Int = 1024, + addBosToken: Bool = false, + gpuLayerCount: Int32 = 1, + mainGpu: Int32 = 0, + tensorSplit: UnsafePointer? = nil, + progressCallback: LlamaProgressCallback? = nil, + progressCallbackUserData: UnsafeMutableRawPointer? = nil, + vocabOnly: Bool = false, + useMmap: Bool = true, + useMlock: Bool = false + ) { + self.wrapped = llama_model_default_params() + + self.systemPrompt = systemPrompt + self.maxOutputLength = maxOutputLength + self.addBosToken = addBosToken + + /// Overwrite `gpuLayerCount` in case of a simulator target environment + #if targetEnvironment(simulator) + self.gpuLayerCount = 0 // Disable Metal on simulator as crash otherwise + #else + self.gpuLayerCount = gpuLayerCount + #endif + self.mainGpu = mainGpu + self.tensorSplit = tensorSplit + self.progressCallback = progressCallback + self.progressCallbackUserData = progressCallbackUserData + self.vocabOnly = vocabOnly + self.useMmap = useMmap + self.useMlock = useMlock + } +} diff --git a/Sources/SpeziLLMLocal/Configuration/LLMSamplingParameters.swift b/Sources/SpeziLLMLocal/Configuration/LLMSamplingParameters.swift new file mode 100644 index 0000000..18a7524 --- /dev/null +++ b/Sources/SpeziLLMLocal/Configuration/LLMSamplingParameters.swift @@ -0,0 +1,298 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import llama + + +/// The ``LLMSamplingParameters`` represents the sampling parameters of the LLM. +/// Internally, these data points are passed as a llama.cpp `llama_sampling_params` C struct to the LLM. +public struct LLMSamplingParameters: Sendable { + /// Helper enum for the Mirostat sampling method + public enum Mirostat { + init(rawValue: Int, targetEntropy: Float = 5.0, learningRate: Float = 0.1) { + switch rawValue { + case 0: + self = .disabled + case 1: + self = .v1(targetEntropy: targetEntropy, learningRate: learningRate) + case 2: + self = .v2(targetEntropy: targetEntropy, learningRate: learningRate) + default: + self = .disabled + } + } + + + case disabled + case v1(targetEntropy: Float, learningRate: Float) // swiftlint:disable:this identifier_name + case v2(targetEntropy: Float, learningRate: Float) // swiftlint:disable:this identifier_name + + + var rawValue: Int { + switch self { + case .disabled: + return 0 + case .v1: + return 1 + case .v2: + return 2 + } + } + } + + public struct ClassifierFreeGuidance { + let negativePrompt: String? + let scale: Float + + + public init(negativePrompt: String? = nil, scale: Float = 1.0) { + self.negativePrompt = negativePrompt + self.scale = scale + } + } + + + /// Wrapped C struct from the llama.cpp library, later-on passed to the LLM. + private var wrapped: llama_sampling_params + + + /// Sampling parameters in llama.cpp's low-level C representation. + var llamaCppRepresentation: llama_sampling_params { + wrapped + } + + var llamaCppSamplingContext: UnsafeMutablePointer? { + llama_sampling_init(wrapped) + } + + /// Number of previous tokens to remember. + var rememberTokens: Int32 { + get { + wrapped.n_prev + } + set { + wrapped.n_prev = newValue + } + } + + /// If greater than 0, output the probabilities of top n\_probs tokens. + var outputProbabilities: Int32 { + get { + wrapped.n_probs + } + set { + wrapped.n_probs = newValue + } + } + + /// Top-K Sampling: K most likely next words (<= 0 to use vocab size). + var topK: Int32 { + get { + wrapped.top_k + } + set { + wrapped.top_k = newValue + } + } + + /// Top-p Sampling: Smallest possible set of words whose cumulative probability exceeds the probability p (1.0 = disabled). + var topP: Float { + get { + wrapped.top_p + } + set { + wrapped.top_p = newValue + } + } + + /// Min-p Sampling (0.0 = disabled). + var minP: Float { + get { + wrapped.min_p + } + set { + wrapped.min_p = newValue + } + } + + /// Tail Free Sampling (1.0 = disabled). + var tfs: Float { + get { + wrapped.tfs_z + } + set { + wrapped.tfs_z = newValue + } + } + + /// Locally Typical Sampling. + var typicalP: Float { + get { + wrapped.typical_p + } + set { + wrapped.typical_p = newValue + } + } + + /// Temperature Sampling: A higher value indicates more creativity of the model but also more hallucinations. + var temperature: Float { + get { + wrapped.temp + } + set { + wrapped.temp = newValue + } + } + + /// Last n tokens to penalize (0 = disable penalty, -1 = context size). + var penaltyLastTokens: Int32 { + get { + wrapped.penalty_last_n + } + set { + wrapped.penalty_last_n = newValue + } + } + + /// Penalize repeated tokens (1.0 = disabled). + var penaltyRepeat: Float { + get { + wrapped.penalty_repeat + } + set { + wrapped.penalty_repeat = newValue + } + } + + /// Penalize frequency (0.0 = disabled). + var penaltyFrequency: Float { + get { + wrapped.penalty_repeat + } + set { + wrapped.penalty_repeat = newValue + } + } + + /// Presence penalty (0.0 = disabled). + var penaltyPresence: Float { + get { + wrapped.penalty_present + } + set { + wrapped.penalty_present = newValue + } + } + + /// Penalize new lines. + var penalizeNewLines: Bool { + get { + wrapped.penalize_nl + } + set { + wrapped.penalize_nl = newValue + } + } + + /// Mirostat sampling. + var mirostat: Mirostat { + get { + .init( + rawValue: Int(wrapped.mirostat), + targetEntropy: wrapped.mirostat_tau, + learningRate: wrapped.mirostat_eta + ) + } + set { + wrapped.mirostat = Int32(newValue.rawValue) + + if case .v1(let targetEntropy, let learningRate) = mirostat { + wrapped.mirostat_tau = targetEntropy + wrapped.mirostat_eta = learningRate + } else if case .v2(let targetEntropy, let learningRate) = mirostat { + wrapped.mirostat_tau = targetEntropy + wrapped.mirostat_eta = learningRate + } else { + wrapped.mirostat_tau = 5.0 + wrapped.mirostat_eta = 0.1 + } + } + } + + /// Classifier-Free Guidance. + var cfg: ClassifierFreeGuidance { + get { + .init( + negativePrompt: String(wrapped.cfg_negative_prompt), + scale: wrapped.cfg_scale + ) + } + set { + wrapped.cfg_negative_prompt = std.string(newValue.negativePrompt) + wrapped.cfg_scale = newValue.scale + } + } + + + /// Creates the ``LLMContextParameters`` which wrap the underlying llama.cpp `llama_context_params` C struct. + /// Is passed to the underlying llama.cpp model in order to configure the context of the LLM. + /// + /// - Parameters: + /// - rememberTokens: Number of previous tokens to remember. + /// - outputProbabilities: If greater than 0, output the probabilities of top n\_probs tokens. + /// - topK: Top-K Sampling: K most likely next words (<= 0 to use vocab size). + /// - topP: Top-p Sampling: Smallest possible set of words whose cumulative probability exceeds the probability p (1.0 = disabled). + /// - minP: Min-p Sampling (0.0 = disabled). + /// - tfs: Tail Free Sampling (1.0 = disabled). + /// - typicalP: Locally Typical Sampling. + /// - temperature: Temperature Sampling: A higher value indicates more creativity of the model but also more hallucinations. + /// - penaltyLastTokens: Last n tokens to penalize (0 = disable penalty, -1 = context size). + /// - penaltyRepeat: Penalize repeated tokens (1.0 = disabled). + /// - penaltyFrequency: Penalize frequency (0.0 = disabled). + /// - penaltyPresence: Presence penalty (0.0 = disabled). + /// - penalizeNewLines: Penalize new lines. + /// - mirostat: Mirostat sampling. + /// - cfg: Classifier-Free Guidance. + public init( + rememberTokens: Int32 = 256, + outputProbabilities: Int32 = 0, + topK: Int32 = 40, + topP: Float = 0.95, + minP: Float = 0.05, + tfs: Float = 1.0, + typicalP: Float = 1.0, + temperature: Float = 0.8, + penaltyLastTokens: Int32 = 64, + penaltyRepeat: Float = 1.1, + penaltyFrequency: Float = 0.0, + penaltyPresence: Float = 0.0, + penalizeNewLines: Bool = true, + mirostat: Mirostat = .disabled, + cfg: ClassifierFreeGuidance = .init() + ) { + self.wrapped = llama_sampling_params() + + self.rememberTokens = rememberTokens + self.outputProbabilities = outputProbabilities + self.topK = topK + self.topP = topP + self.minP = minP + self.tfs = tfs + self.typicalP = typicalP + self.temperature = temperature + self.penaltyLastTokens = penaltyLastTokens + self.penaltyRepeat = penaltyRepeat + self.penaltyFrequency = penaltyFrequency + self.penaltyPresence = penaltyPresence + self.penalizeNewLines = penalizeNewLines + self.mirostat = mirostat + self.cfg = cfg + } +} diff --git a/Sources/SpeziLLMLocal/LLMLlama+Generation.swift b/Sources/SpeziLLMLocal/LLMLlama+Generation.swift new file mode 100644 index 0000000..0474ea2 --- /dev/null +++ b/Sources/SpeziLLMLocal/LLMLlama+Generation.swift @@ -0,0 +1,149 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import llama +import SpeziLLM + + +/// Extension of ``LLMLlama`` handling the text generation. +extension LLMLlama { + /// Typealias for the llama.cpp `llama_token`. + typealias LLMLlamaToken = llama_token + + + /// Based on the input prompt, generate the output with llama.cpp + /// + /// - Parameters: + /// - prompt: The input `String` prompt. + /// - continuation: A Swift `AsyncThrowingStream` that streams the generated output. + func _generate( // swiftlint:disable:this identifier_name function_body_length + prompt: String, + continuation: AsyncThrowingStream.Continuation + ) async { + await MainActor.run { + self.state = .generating + } + + // Log the most important parameters of the LLM + Self.logger.debug("n_length = \(self.parameters.maxOutputLength, privacy: .public), n_ctx = \(self.contextParameters.contextWindowSize, privacy: .public), n_batch = \(self.contextParameters.batchSize, privacy: .public), n_kv_req = \(self.parameters.maxOutputLength, privacy: .public)") + + // Allocate new model context, if not already present + if self.context == nil { + guard let context = llama_new_context_with_model(model, self.contextParameters.llamaCppRepresentation) else { + Self.logger.error("Failed to initialize context") + continuation.finish(throwing: LLMError.generationError) + return + } + self.context = context + } + + // Check if the maximal output generation length is smaller or equals to the context window size. + guard self.parameters.maxOutputLength <= self.contextParameters.contextWindowSize else { + Self.logger.error("Error: n_kv_req \(self.parameters.maxOutputLength, privacy: .public) > n_ctx, the required KV cache size is not big enough") + continuation.finish(throwing: LLMError.generationError) + return + } + + let tokens = tokenize(prompt) + + // Check if the input token count is smaller than the context window size decremented by 4 (space for end tokens). + guard tokens.count <= self.contextParameters.contextWindowSize - 4 else { + Self.logger.error(""" + Input prompt is too long with \(tokens.count, privacy: .public) tokens for the configured + context window size of \(self.contextParameters.contextWindowSize, privacy: .public) tokens. + """) + continuation.finish(throwing: LLMError.generationError) + return + } + + // Clear the KV cache in order to free up space for the incoming prompt (as we inject the entire history of the chat again) + llama_kv_cache_clear(self.context) + + var batch = llama_batch_init(Int32(tokens.count), 0, 1) + defer { + llama_batch_free(batch) + } + + // Evaluate the initial prompt + for (tokenIndex, token) in tokens.enumerated() { + llama_batch_add(&batch, token, Int32(tokenIndex), getLlamaSeqIdVector(), false) + } + // llama_decode will output logits only for the last token of the prompt + batch.logits[Int(batch.n_tokens) - 1] = 1 + + if llama_decode(self.context, batch) != 0 { + Self.logger.error("Initial decoding of the input prompt failed.") + continuation.finish(throwing: LLMError.generationError) + return + } + + // Batch already includes tokens from the input prompt + var batchTokenIndex = batch.n_tokens + var decodedTokens = 0 + + // Calculate the token generation rate + let startTime = Date() + + while decodedTokens <= self.parameters.maxOutputLength { + let nextTokenId = sample(batchSize: batch.n_tokens) + + // Either finish the generation once EOS token appears, the maximum output length of the answer is reached or the context window is reached + if nextTokenId == llama_token_eos(self.model) + || decodedTokens == self.parameters.maxOutputLength + || batchTokenIndex == self.contextParameters.contextWindowSize { + self.generatedText.append(Self.EOS) + continuation.finish() + await MainActor.run { + self.state = .ready + } + return + } + + var nextStringPiece = String(llama_token_to_piece(context, nextTokenId)) + // As first character is sometimes randomly prefixed by a single space (even though prompt has an additional character) + if decodedTokens == 0 && nextStringPiece.starts(with: " ") { + nextStringPiece = String(nextStringPiece.dropFirst()) + } + + continuation.yield(nextStringPiece) + self.generatedText.append(nextStringPiece) + + // Prepare the next batch + llama_batch_clear(&batch) + + // Push generated output token for the next evaluation round + llama_batch_add(&batch, nextTokenId, batchTokenIndex, getLlamaSeqIdVector(), true) + + decodedTokens += 1 + batchTokenIndex += 1 + + // Evaluate the current batch with the transformer model + let decodeOutput = llama_decode(self.context, batch) + if decodeOutput != 0 { // = 0 Success, > 0 Warning, < 0 Error + Self.logger.error("Decoding of generated output failed. Output: \(decodeOutput, privacy: .public)") + await MainActor.run { + self.state = .error(error: .generationError) + } + continuation.finish(throwing: LLMError.generationError) + return + } + } + + let elapsedTime = Date().timeIntervalSince(startTime) + + Self.logger.debug("Decoded \(decodedTokens, privacy: .public) tokens in \(String(format: "%.2f", elapsedTime), privacy: .public) s, speed: \(String(format: "%.2f", Double(decodedTokens) / elapsedTime), privacy: .public)) t/s") + + llama_print_timings(self.context) + + continuation.finish() + await MainActor.run { + self.state = .ready + } + } +} diff --git a/Sources/SpeziLLMLocal/LLMLlama+Helpers.swift b/Sources/SpeziLLMLocal/LLMLlama+Helpers.swift new file mode 100644 index 0000000..f3a0308 --- /dev/null +++ b/Sources/SpeziLLMLocal/LLMLlama+Helpers.swift @@ -0,0 +1,159 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import CxxStdlib +import Foundation +import llama + + +/// Extension of ``LLMLlama`` handling the text tokenization. +extension LLMLlama { + /// BOS token of the LLM, used at the start of each prompt passage. + static let BOS: String = { + "" + }() + + /// EOS token of the LLM, used at the end of each prompt passage. + static let EOS: String = { + "" + }() + + /// BOSYS token of the LLM, used at the start of the system prompt. + static let BOSYS: String = { + "<>" + }() + + /// EOSYS token of the LLM, used at the end of the system prompt. + static let EOSYS: String = { + "<>" + }() + + /// BOINST token of the LLM, used at the start of the instruction part of the prompt. + static let BOINST: String = { + "[INST]" + }() + + /// EOINST token of the LLM, used at the end of the instruction part of the prompt. + static let EOINST: String = { + "[/INST]" + }() + + + /// Converts a textual `String` to the individual `LLMLlamaToken`'s based on the model's dictionary. + /// This is a required tasks as LLMs internally processes tokens. + /// + /// - Parameters: + /// - toBeTokenizedText: The input `String` that should be tokenized. + /// + /// - Returns: The tokenized `String` as `LLMLlamaToken`'s. + func tokenize(_ toBeTokenizedText: String) -> [LLMLlamaToken] { + let formattedPrompt = buildPrompt(with: toBeTokenizedText) + if self.generatedText.isEmpty { + self.generatedText = formattedPrompt + } else { + self.generatedText.append(formattedPrompt) + } + + var tokens: [LLMLlamaToken] = .init( + llama_tokenize_with_context(self.context, std.string(self.generatedText), self.parameters.addBosToken, true) + ) + + // Truncate tokens if there wouldn't be enough context size for the generated output + if tokens.count > Int(self.contextParameters.contextWindowSize) - self.parameters.maxOutputLength { + tokens = Array(tokens.suffix(Int(self.contextParameters.contextWindowSize) - self.parameters.maxOutputLength)) + } + + // Output generation shouldn't run without any tokens + if tokens.isEmpty { + tokens.append(llama_token_bos(self.model)) + Self.logger.warning(""" + The input prompt didn't map to any tokens, so the prompt was considered empty. + To mediate this issue, a BOS token was added to the prompt so that the output generation + doesn't run without any tokens. + """) + } + + return tokens + } + + /// Converts an array of `LLMLlamaToken`s to an array of tupels of `LLMLlamaToken`s as well as their `String` representation. + /// + /// - Parameters: + /// - tokens: An array of `LLMLlamaToken`s that should be detokenized. + /// - Returns: An array of tupels of `LLMLlamaToken`s as well as their `String` representation. + /// + /// - Note: Used only for debug purposes + func detokenize(tokens: [LLMLlamaToken]) -> [(LLMLlamaToken, String)] { + tokens.reduce(into: [(LLMLlamaToken, String)]()) { partialResult, token in + partialResult.append((token, String(llama_token_to_piece(self.context, token)))) + } + } + + /// Based on the current state of the context, sample the to be inferred output via the temperature method + /// + /// - Parameters: + /// - batchSize: The current size of the `llama_batch` + /// - Returns: A sampled `LLMLLamaToken` + func sample(batchSize: Int32) -> LLMLlamaToken { + let nVocab = llama_n_vocab(model) + let logits = llama_get_logits_ith(self.context, batchSize - 1) + + var candidates: [llama_token_data] = .init(repeating: llama_token_data(), count: Int(nVocab)) + + for tokenId in 0 ..< nVocab { + candidates.append(llama_token_data(id: tokenId, logit: logits?[Int(tokenId)] ?? 0, p: 0.0)) + } + + var candidatesP: llama_token_data_array = .init( + data: candidates.withUnsafeMutableBytes { $0.baseAddress?.assumingMemoryBound(to: llama_token_data.self) }, // &candidates + size: candidates.count, + sorted: false + ) + + // Sample via the temperature method + let minKeep = Int(max(1, self.samplingParameters.outputProbabilities)) + llama_sample_top_k(self.context, &candidatesP, self.samplingParameters.topK, minKeep) + llama_sample_tail_free(self.context, &candidatesP, self.samplingParameters.tfs, minKeep) + llama_sample_typical(self.context, &candidatesP, self.samplingParameters.typicalP, minKeep) + llama_sample_top_p(self.context, &candidatesP, self.samplingParameters.topP, minKeep) + llama_sample_min_p(self.context, &candidatesP, self.samplingParameters.minP, minKeep) + llama_sample_temp(self.context, &candidatesP, self.samplingParameters.temperature) + + return llama_sample_token(self.context, &candidatesP) + } + + /// Build a typical Llama2 prompt format out of the user's input including the system prompt and all necessary instruction tokens. + /// + /// The typical format of an Llama2 prompt looks like: + /// """ + /// [INST] <> + /// {your_system_message} + /// <> + /// + /// {user_message_1} [/INST] {model_reply_1}[INST] {user_message_2} [/INST] + /// """ + /// + /// - Parameters: + /// - userInputString: String-based input prompt of the user. + /// - Returns: Properly formatted Llama2 prompt including system prompt. + private func buildPrompt(with userInputString: String) -> String { + if self.generatedText.isEmpty { + """ + \(Self.BOS)\(Self.BOINST) \(Self.BOSYS) + \(self.parameters.systemPrompt) + \(Self.EOSYS) + + \(userInputString) \(Self.EOINST) + """ + " " // Add a spacer to the generated output from the model + } else { + """ + \(Self.BOS)\(Self.BOINST) \(userInputString) \(Self.EOINST) + """ + " " // Add a spacer to the generated output from the model + } + } +} diff --git a/Sources/SpeziLLMLocal/LLMLlama.swift b/Sources/SpeziLLMLocal/LLMLlama.swift new file mode 100644 index 0000000..912a80f --- /dev/null +++ b/Sources/SpeziLLMLocal/LLMLlama.swift @@ -0,0 +1,100 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import llama +import os +import SpeziLLM + + +/// The ``LLMLlama`` is a Spezi `LLM` and utilizes the llama.cpp library to locally execute an LLM on-device. +/// +/// - Important: ``LLMLlama`` shouldn't be used on it's own but always wrapped by the Spezi `LLMRunner` as the runner handles +/// all management overhead tasks. A code example on how to use ``LLMLlama`` in combination with the `LLMRunner` can be +/// found in the documentation of the `LLMRunner`. +public actor LLMLlama: LLM { + /// A Swift Logger that logs important information from the ``LLMLlama``. + static let logger = Logger(subsystem: "edu.stanford.spezi", category: "SpeziLLM") + public let type: LLMHostingType = .local + @MainActor public var state: LLMState = .uninitialized + + /// Parameters of the llama.cpp ``LLM``. + let parameters: LLMParameters + /// Context parameters of the llama.cpp ``LLM``. + let contextParameters: LLMContextParameters + /// Sampling parameters of the llama.cpp ``LLM``. + let samplingParameters: LLMSamplingParameters + /// The on-device `URL` where the model is located. + private let modelPath: URL + /// A pointer to the allocated model via llama.cpp. + var model: OpaquePointer? + /// A pointer to the allocated model context from llama.cpp. + var context: OpaquePointer? + /// Keeps track of all already text being processed by the LLM, including the system prompt, instructions, and model responses. + var generatedText: String = "" + + + /// Creates a ``LLMLlama`` instance that can then be passed to the `LLMRunner` for execution. + /// + /// - Parameters: + /// - modelPath: A local `URL` where the LLM file is stored. The format of the LLM must be in the llama.cpp `.gguf` format. + /// - parameters: Parameterize the ``LLMLlama`` via ``LLMParameters``. + /// - contextParameters: Configure the context of the ``LLMLlama`` via ``LLMContextParameters``. + /// - samplingParameters: Parameterize the sampling methods of the ``LLMLlama`` via ``LLMSamplingParameters``. + public init( + modelPath: URL, + parameters: LLMParameters = .init(), + contextParameters: LLMContextParameters = .init(), + samplingParameters: LLMSamplingParameters = .init() + ) { + self.modelPath = modelPath + self.parameters = parameters + self.contextParameters = contextParameters + self.samplingParameters = samplingParameters + } + + + public func setup(runnerConfig: LLMRunnerConfiguration) async throws { + await MainActor.run { + self.state = .loading + } + + guard let model = llama_load_model_from_file(modelPath.path().cString(using: .utf8), parameters.llamaCppRepresentation) else { + await MainActor.run { + self.state = .error(error: LLMError.modelNotFound) + } + throw LLMError.modelNotFound + } + + /// Check if model was trained for the configured context window size + guard self.contextParameters.contextWindowSize <= llama_n_ctx_train(model) else { + Self.logger.warning("Model was trained on only \(llama_n_ctx_train(model), privacy: .public) context tokens, not the configured \(self.contextParameters.contextWindowSize, privacy: .public) context tokens") + await MainActor.run { + self.state = .error(error: LLMError.generationError) + } + throw LLMError.modelNotFound + } + + self.model = model + + await MainActor.run { + self.state = .ready + } + } + + public func generate(prompt: String, continuation: AsyncThrowingStream.Continuation) async { + await _generate(prompt: prompt, continuation: continuation) + } + + + /// Upon deinit, free the context and the model via llama.cpp + deinit { + llama_free(context) + llama_free_model(self.model) + } +} diff --git a/Sources/SpeziLLMLocal/LLMLocalRunnerSetupTask.swift b/Sources/SpeziLLMLocal/LLMLocalRunnerSetupTask.swift new file mode 100644 index 0000000..fe556e3 --- /dev/null +++ b/Sources/SpeziLLMLocal/LLMLocalRunnerSetupTask.swift @@ -0,0 +1,45 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import llama +import Spezi +import SpeziLLM + + +/// The ``LLMLocalRunnerSetupTask`` sets up the local environment in order to execute Spezi `LLM`s. +/// It needs to be stated within the `LLMRunner` initializer. +/// +/// ```swift +/// class LocalLLMAppDelegate: SpeziAppDelegate { +/// override var configuration: Configuration { +/// Configuration { +/// // Configure the runner responsible for executing local LLMs +/// LLMRunner { +/// LLMLocalRunnerSetupTask() +/// } +/// } +/// } +/// } +public class LLMLocalRunnerSetupTask: LLMRunnerSetupTask, DefaultInitializable { + public let type: LLMHostingType = .local + + + public required init() { } + + + public func setupRunner(runnerConfig: LLMRunnerConfiguration) async throws { + /// Initialize the llama.cpp backend. + llama_backend_init(runnerConfig.nonUniformMemoryAccess) + } + + + deinit { + /// Frees the llama.cpp backend. + llama_backend_free() + } +} diff --git a/Sources/SpeziLLMLocal/Resources/Localizable.xcstrings b/Sources/SpeziLLMLocal/Resources/Localizable.xcstrings new file mode 100644 index 0000000..d2597c7 --- /dev/null +++ b/Sources/SpeziLLMLocal/Resources/Localizable.xcstrings @@ -0,0 +1,16 @@ +{ + "sourceLanguage" : "en", + "strings" : { + "SPEZI_LLM_LOCAL_LLAMA_SYSTEM_PROMPT" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe and still concise. Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that your responses are socially unbiased and positive in nature.\nIf a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. If you don't know the answer to a question, please don't share false information." + } + } + } + } + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/Sources/SpeziLLMLocal/Resources/Localizable.xcstrings.license b/Sources/SpeziLLMLocal/Resources/Localizable.xcstrings.license new file mode 100644 index 0000000..6917c4b --- /dev/null +++ b/Sources/SpeziLLMLocal/Resources/Localizable.xcstrings.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView.png b/Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView.png new file mode 100644 index 0000000000000000000000000000000000000000..a665db4fbe483423e8013caa9a3aff0255a909f4 GIT binary patch literal 102090 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 literal 0 HcmV?d00001 diff --git a/Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView.png.license b/Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView.png.license new file mode 100644 index 0000000..7f16969 --- /dev/null +++ b/Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView.png.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT \ No newline at end of file diff --git a/Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView~dark.png b/Sources/SpeziLLMLocal/SpeziLLMLocal.docc/Resources/ChatView~dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9000830a33f0e7ddde572be193139ea034f33a70 GIT binary patch literal 68402 zcmb5VRajgx+cpXC@+C1C>T(zm(Lo) zUT=$MnEb4wB`fc&!p6q-EImI!AkfdxkA#Hezv2hR55B&>pFe+gb#=A0wEV9dB_%Zt z4Gm7{lZwiJ0-v6q-o2yr_V#9GX5r-IL_qoX144-CnO9N_luGXAUP-syUWhAw{S5C8DdF6?|{n@2y=g{aT zhu8F*HiLE(o8#dr5HhM7Y^iOHQF;i3G*B}*FzsG+DAznagiGaqCM^q>$|Cskg~67p zsyNYDqeMpCIpJ7=F7m10u$KY^PFYMz+*pF_;fB5F_@#b?eo0@N_=!G@)SM~j<@S49 zm5`oI(piy`r;QZfGx2E*eC6eKPnkPIn{8Z^;OwQo#0L=B4FT41=* zB5tq*cl5k1v8={x?66;-6{If0z{t)&V+Z%&Qpx{C6Hz|RUYtXR5=69j(y!QkdL>=3 z*n%ptnmArdo7#m|zHKrV%nz1F`D30c!Au}?{&z?59D}eeRPbj;ZRB<+M-eyjx9~;_ z)B0Xu*@vV2>F+$IPfMz!<4J!(6~A}q1!KQrgb*kslD!D+eMN-!M-(-?rmbqkkV9AY zl`Eq%&jXpy+ZTV7voul^+PqiZ|C&}ZjV-}uI_<)t@c;ILZUyb~y|>YX(Ki%Nu7o6N z`3ZJaSF4Lhn0MP2y>-BRAXPQx2NuMK70@JSoE8Ja=4;P5EC79w&n1~Rc5_>oUU~sq z_pB(t=wq>6MrLu#@Q)NNQK>3EwUOSDT8{jQc6bs9`^&|N8-rE>ZV{G0849|ulhZ4o z;_f!*tu-e@Imat`!}S+YnCI=BG(PdXPmEtKxa7I$elrH+y`aq*Qst!MoCprT!&Q@P z$&C2s^d%eqaQBIbkO>VN2Mq<9Cbs4K($Tk!MkaJqU)sp{sv;Z^uZEHTLq7Kbj_TFj z#wX$Ew|3nPd(B)e`oYgjGuS4(bGV>v{|=9u?A_Rl!j~JRsFA-CFf+^Au-RT*Ufcyx zXZWb@m^20}(X`iIT!=@D*TJ@$M~bNSA*Z9{ESz5woEcGf2@bQ!a~e9}AAJixAF|4- z%~HzK;EFq}Hc8Cokv}|+14gukoRyJVx+RVQ+rua$(UO6jYvx4Kbs2C z3Us$^RWJStORgFj{b3DZWA3rbJ?wlZm=UI)L=Y!dsj z<%KAA$Su#U+W(#WPzvIb>YS(hID zw5$2!7IHpt|IYZRicSX4gY7&E<#&G-D}JEOtt)Emoyn>`RDg6~k$`TpWu!X~H!L1v%7+a{;h~L*irR-mOp{58~Ef(Z13{ z4E0W~Hh1M;B%x)cJJR`;P#jFM4x{+o`XFzZqN~d>3M%Tu4@l-;=;h}WmSroCtnBV+OYv+QKNVGCoxf*s=ab8}xi2t2GOpwna-${T{qH;6U zh1-$_hTUpf1d1ZsWp8PZwbpBN?RpX-Y|S5w4Tg^m-Z8@s` z9fqieBR9h0d@oPU#(xPc-IykBz!nE^dL^EAxtFi@T37>uC*EiV^U)lp=^pyhNejme z|MaZ&>INmZU2^`|g<72_TqmzJsX2t6=AO|Z3R;etxGf-ia+?$|92S~)G{*sDoceTk zCwPu|uw{btftF~zW$E=l4@Y4!ob525ml>mI{zvfQ!7oh56Xyv7lkdBuoKU-r<9c+M zJ%vfKIp;cvO)?FS>XG-ew;m&#eI-O5agW7dl7LPBseJ}-zL&?S=cC4V5@Z2g0r*{C zZtX=?OGJ{4y5m~FlUe}TiDIj*zC^rh!C_E2056~fiV5s&zoPRmLB;~I@{kW`0eQpO zA$XdAIitRmlY8!agm@4rlv5MZ-(gvTJa9@Z_kTnSP_K4+r~(B!1)t|q|LFP{5YP;U zCENYYhKez>*A*Qq0WYRXVH63qD zT8uE@Xb>D};<##8F%5_HZt~9P%$QAt`z~$He!J!S>a!KodAh32;9oMt-tjx9rHMw% z&@~2N&zD2}PMj1QlvTvav26U(czj*Z#~}`@UVj1=jr*<3wf^!T6J?$EJK^ zMFBdoVsvL??ueST2;beAsO&prfKH5vsyRu6AN>60f)RPMNiYZ&V;~_mhpYv}QoGh(<}|QoZBV&O(Z9gZVIeSQ&G> z#AwIYt5H3gWW&$RZ~7QplkdVB(@lC1?=qxLG(k%w<6_?f>xRDXN!~aoiu@EC!K<69 zHyBH>#Pg7MgKb6BbE-F~Z8JxHoj1$RHD7F{l+)qqqNxLvwct3lz&eAW3Mu-3x>EhF zVknZINZe2BL)v39Vq+^^YSR2Rq_k@c=f2!j)aFg3v^|)18BDZEdT)o#VH3mY(J!oH zMz@sGOga|@Y^-`6yo7ki`3O70Xi+eLngbMSlLTE1^ZFR(qNM_Cr;3 zR)B@&glLyLqduF?^het);=+U^iaGB}l#ZXzFVUE1VR5W2RRi9QwZchyMU`=T#1lI7 z3v;&fYG0Ywt!WD&2f5IdIZtf$6Z~i3ZE(}yNXNC&EwD5$K!F!4d`srvq?F7JPM1F% z+gXoGBYn#&@UD$5V}&h{7gYaxAOUpMeD~s#JW8ykQS^!>;3Z-JipuS@Hf$BRT4H`8#`WqF=x z35CZPMxyHmKXWAARc=0v`!?!=s}JUoiqYw{fRL8O*kV7eE0v#djK4C0uljgXN2v_Y zyiU^$ek2TJMb83hr9KN9Z^4&_S1bEr-EMGfj-wlyEHq=kw4&AZHJ!ZQp?|ie37M(0 zhJ?I73FO^aAzgxsj1?j%7Rj(PObhZPaY>MhfTQ6iXV@(km->xMT-N5cF z6H;kI{TDtUqHwY+@Og_?-rM9S;CbEmRpAPyZh2;}168S%ab79=Uw3i zD^GGDO}06D&~+OCuI%7lT6osGiVM!V8Ek5im{yvIY&89IU^o%LGgc?$h6_-*uDtvezwPAQ?S!R>6?opTF-K9n~uKr?@UVJ-nKGk6pa)x~;PuUzdDN!>g#} zO@-m$wpzsZPeb+d8zpD)O7?q#z2+FUB{>5g=VCcz0Kn-1XLjDg|z)fZ9R6aUk~nD45E9{ zS<{vz`ha(yo+pQ*hyp_sa;P@T_4V!>qV%JatH1 zzUG^-^6}+4xfiG>GwoXIK-Bvt^99b#NmqAD%XmO_rYs+CB2G^A?qP>l(unrn&bOYn zGjw22Ue=p1Ajg7{T$JE5+0Td&I3hLaD>dp0B}O@G9mV0Hvot6Z`=FZ3N4;Fmyv+L zwYz5CtOE7yFl`@M6Eb*h#OflCCo%mYJjMBkKE18;N#;AjRgT7N_6dx0 zUs!1cju(#mukH3IzTp$!5sZ_bbx#(>TVa;lJiE2bUg3GALCX2FV%KZ}U`Qz|)(S>7nW`KEn+MM&z<>T-$tKwqRQ+yBlfu(DnK4G>(~NwsmsveCsp!X51S{ zD{{QtU!El(M%3IRuXmKOP`WaKomFRfou^-^PBm%JC%||c8%tk4zY`z+F|RrUHhKwO zQ1a{;TXbQsf7c1f=SgZ+_thi zIqP~B-z8I4f2m1h99@wEP>zIFPNr$iiS*sTbm#;5X zYl(qG?d!5>jFzbn+jP$5Oh%jT-38I*`EjaCwxb4S;!H;TBc0Xn4bOkhEt+j2#%Qd0 z1K3g;qbRwBJ;dCs#CD<&AXJn8E^B4pDp-2$<=6A5LNv zMc)N^@0%)!+J-%{y4%fH1bvp~kC=8M;T|f7m9Kr)69xpJenco}mtBqo2RAM5j%9fQ z)Z5(`X!w>BjT$1vhkf@CFYXUoe6B2&avkzNUd@y*B=yVwxpVzeedIh?Uhg5;JyhXX zy_hr@qe0{$Z%9rKieq_Ftg7Q9;TWug{x;AooKE*BQ6L5V@zSpfIm*tlfK%{hg*)t+{C zu*0UnF)UdXwtI*;HUD%*pqb6{JzFOxxC32#4z!LZrGpW2tZT>Z4`0KxjdD`u-f>PT zQJb!gb4oK|JKMDa4>rMYUe;Na~>l>X`roQq~D2a;d`se=LfNk>3{EbkFNcd z;NBZE7l~KcTdb%oLPA>E*K<{*mnR100dHT{%^l1h!~R|9c9n;Z)`$6jQKyD{tkpRJ zu+ki1JJ9%KtMRo#G{rb8w>(TVWCG3#R3E1swX?MZKHg=EJOy(~_g)u}uNG5Y|MdQQ zm`tut(0nb-GMuKn5MW#ev8bFd^M8{+XwRO))F?b^&bM$BmoN4*i|?Hnl<`%%Ha)_g z4f{q=PgI${n7XTTXYw6KD@d1(z{I=ifR71OqDN2+ME4(-45u`gbIlzUwY_L}D9yUd zpXR#b)wEGQ3v@3Y-E$RftJJsazLsDkeMUdB6wpHx$} z8Ge!WXt!GBqZTtpRKTpR#mD2h_HR`uk^ULhmXEStGR}nNa)W%B%ZFy`cEJ0>M(|iE z;xPy4LK}Z^?7t1Nsv6*1fR{7oz|UV>3rC3*)~&7jY!z!X*)ZIkEc(+Bc4Y5EIMg*d zdJq7(4Q9a9BAbz$H&2DYeZe%~q==$|?(l+0C1OwMXOIc~X&*b1_Fw-sO!cMsvK0yR zB6Jc%l3bJI?qyf8Rt7nVg!JdH_k=+py#e*FNY>^~7XmckODeds?sKs4X&=Ovj@fTB zrFol_-$x(5a`-|LObanvI#yIn>GT-V4#tPoC^h-MD=;#iQB1+u_>47DA-B!ngkh7C zP=F)1P0QSt>3{9nGJ~#2iZw!dJFc4CR={LOa3lHqr*7vfgZDR8`5+;`5E+J z*CM0nR-+j=2w!^^enGB2fOBSDY6;gNI;-gEJvB+UpAKT)1>XP!eG4S3;C@GKUvF=;zKnToCtU3``L z{07nR;ohRQBf?Asjhro;dnWVw%ha=>RpQw~IL@KJcVkhG^BiSCYqfGppW=h~>p_D? z-bXrna8e2Dw-7-iwnBa~7*~5Yey%3ediluDM>2y6jabga zWC|Y2ua4E4ra~b$3ro6?d-fg~$_wHE4#!x1ulq?0Od4xS&$9p2r%FkyU~=)5w}USH z6Ohd12Q5(OC(N`PD>yP=-Kn3M?^~!tHhyA4Cnz1J&9#jpDdbM+TEi*~3(KfTx~P|+ zK}(zRdY)(8G45yj8p#~Oa}1lROI5)Iwm|?a*6y3Msqnve!LF+SJ3I$3X#o?DykY*wE|7athS`vWHk09=JMMQ3Gr) zh^yrcj&rkcp`A(@z2sIKz`6)8xNZ%{jb?$#PZ#5vI1>W`mLg~hW7Jg5y8NUGi4jDH z^(qeFN21%*ABPat>?;y9gP3&M!w~9t02?N7pqJ?g$Mego!#N4%P0n+2=u<=Vw;Y(? zRiygEZjdp*@S7jp2r>`n{9BZuPTu6Wj^nA~ zU)vc*=Ok#`P!8Y6$C{+@y#DVhAVII@AjoqSuR#^`{y$~o0jB-Io889RIycE>KZ1K| zL=umGx_@UPTXQf&kZp!YfLXL8Np5>Hi*4QMLW;-Iyl=h=rbgque5W8te!-0A&`-zu zO$LVg+?<64A5Abm{_2FtDWx`6vce-m+FmNl1s^w@Ptno(l^nkG$3GM?Wqrqjc#E@q zLMRidZ?w(#_LSC0{U|~14J)Ib6ym*qYFfC2iByJtfVBdcU#n)_VVjUTAt^M(B9(@4 zHb_NHKmmb5gN6vW5as;|{BzJkD!%K7@jQPI`1=VLiK+#B(Z@RyIo;UwlmcgUmgy}p z{!8|VFjQKGmBwfHmT4Rud~H{vHQrG%$H{5~z64G+7grl`tXh6y+3Au+)g!t8at)BX zpw}1_Fkn4(XbzUJK~Bsvo#WJ$zw*UO!lDT-$yEnYZKou4R`7+pH$Ei&$uAwj!Q6_& zrmC7^S_1ShlVKs&j~E(N?M?JXZ!8C(p@1Z#t$y0BRF6NVpfXuz6XILRI5VU@5u(8X z6uk{_f{Es;?|&mq=E#eq3Wm`6l6Qiy{%#cWCZS1sH36G~4wkV%wke+;J3cOOs)8bs zO92#AQDvtZ5+$cQ{8dfm@;_)`D6r+GTnJ93m0oz~$E<~6HQpw0NoKKBtf;y#>YY8o zlLmYCw7z|qkqpRQPI@050XeF7Tj{JzhKvTAEmY{cCMM0|;KN0Yd>l!AO(<7^t~y6U#ym7h5&ybufr;`463(hWD9pg9wxpudrz}gYP)_QLD8y83*{vnbOVYOHN%T$%} z1<*tidHi7;pH=*g{{I<}1NDn~o0pjUv}yLEGaFUvTF%`f zbZuV2f9`wR*LrcmHPUXFLKpT~bb_Dr!bzi>?t5D>=ocPZmbxNX^qgYAovf43?yYyd zi2mK9CBVO__WM38R`~d`kG*piEXj=ZS#5{NlXm78g1R}vz(HQu} zhPj>t2Pz}>;nT%5^qNOW$wp0=t9GXy>&D9^l&_N~z(^a2FNIH~ocI(nT2NcAVE9&574-M-0->&0Eu5ugl_Ev3 z>GEYe=eq*v^-Neb5o&rT+-4)?2f!PwupxV$L<0fN*{F)Bij3Ev+Gh|3d)9=)gE}X# z0qiR`l#U>_5xiLBKR|p)`WOq~wRIz8N*xX;4XZOtc{G7-CqQwPMwQL^xZ>&|TwaF$vJ zVq|wi{_8MZP2R`JdS=+7d}Clg!MfW{o?fzb?w-hSBrFy(?g9xP2qy+vqO0*R#qEkl zuvKu1|1NjuRR6bhUC_P*lu<7WA*G6jw{<>h?CheMYJFmvoEIwHelZ)iBgict;OU}d zdN4Zc3nK9-65mZ_Bl4q}CY9u1W#zlF7Xo@v!`@mqv83-k_WZS#>+ncbIvTEex+OR%xy;RyAw?gloBh3+V0qWxtZ$#`riVtg1bZqxUQ6 zm4|i4zmZ1!y<@}Wdr$J4kC2QU=v}*deOhCqczg_gOv@C=mqtuqj5tYuw;@hBo)*H^ z>aM@zH)~LkXG!nlI*RP?uMeCI&f#74>Tu!+3&XulS^PTXBV^aXlp6x@2FaL=IL=hI z<7^3~%qcNl0DONTMq4IoS!tS6rt6mVQ?}|cS@Z9#N+~v&^!)a3j0cqisuJa*s^E~y zlQW?PbZ~deLZt*vd-dJ>;@sZYJ*U9MUBfZwEVV6Q!5Xyy*L#zKpbXt~9${BIp3_{s zD3VpYR4LnpilV`nGyj&kO`{hJx4xj(h8ViaOT+`^Sv~_v2BN zNEnPN23#B ze7W{UHNSP0nbjKC#RfPN3^Hmq;G+gfb&_BrU$6^!t#lGIqO@`NYug%2yAy{hF=PzS zOk72FV$!T}%yq9Y%|Mb;R~)=L^ndRHv?!=zs2(=seCos$i(Z^i#*b97ZTLHiRGZdK zQwJ4v#18a~eTur&+8~_7lWyT9UB_9N5Kf+G9I-ERA^S;Dah5q&a*XiwV!~h=iq5oU3AUHb833Hf ztug5yuYBMbBNFPAIs8Vqp04&Ypk4>}7yZJE{UIljjJ zn>~pn9N{OlygySWb8S&BItLuRA{N2{|1-9LWMqmPxy^j(+?(5MT0ZT^k3yv%s@sYA z6zCNPZ#hs?x}t+dy}7MmtL+|EH3<|I`%%J*1r$g?`rJsyM!!QNe#o2 zeAo}z+Vy~+O1yV#p^0RE>ydrl84q|@->%FX@GoM|aKQo_x}#y?g7xRydttClu6D-B z@b+3WHf?)Vlfp4ZBM0GEiZ0&vp$>Ip6?N)s087soLy@)w5yq&$XU6_-NmUMzEVsRH z+VM7YX5?FaNadowM(?t;tJ}}AJD(|5@Eg8TP&KJ~xU5)F8M~kQTXe7PHo29SIyfrl zmK{ntg<_j^Ix?Dzh2-!}~eYx;pzc8!ip*M1%t9@=9=m2Y7m zMQ*}Fw6ii$in7AzsLH?A(2N}8GaQb+KOmYEWrWu6Le(qQEr)svh^Enj9M4HH%?@31 z=zH4k8BUzp6GBC@?;MOB9@serOJ9iBVk{1a{=W1%*TJi2+QVQlZ@G@2-7u0L`3=9G z5S3kEY~?(mZ?9G|xViNW@2vB4TM!GkwiX2bLT& zGfA3wOG4f>s*VWI&Rwf$h#gf09LzNp5<`&f&@E!j(gnt3&d#^fR0aaCCp{3Yn9vZo z$03mqX=8<3YymA~vZETS&RcY`%!;8msH{;g`GlpW>pE2VSSSE~0gdwptAu8{{^>E= zSmcN$5J`Fu%^#J7N zZ5UVP6m=P9$0RcJDm4Yu&S+)QBljW+{%5}D-RTDT1}4;Qmg$mX;PupRR}Nkt$u)U& zAZGzMsEqHDKZ;?I?$zm*{N_f&RU#1}z4`{O@6eD>1#Me9@3a)X{9)e@Jn!TH=4~+2 zMQL>^2bRIv_1hJB)jeQ5x9c%o=~^*B5PVvfV%5;#?AN7UQKNBl+bS};+)sL19NmSc z-RT#g_lkql_T!%6hYJA9*@=ab%$km)>hHmwCE^wI8BL}U%uP9s?|KJA+kowY9m@s! zl;yRsvugmW811UchtaC0uei&gqkZJ{^?aHP8f=@$0`$kE#5jOuTAEA{b>+ zdYtIkS`KNxX`*4UbcaR3DV*9Dk^MC3K6gJh9F{wX7m%H(z*VPXpeQu2Fn9dK@WUm5 zC5x~rK5bhdzU;^6B~?G-9~H@~N)*Bg<@)v}_x~aQh9@)XAg$XhVHkon61Sa?67CCH zGOufCJ z+Qg)VT9;nI&kts;#(V61D|^CKe{HheR|w*|haw!15R!n*)fHX=?$y`M$p7B|wK|sB08E;$sSc&(+>keF?B$ zzBtSX9L;-p<*U)nHp0kwK!!CxUQDa5#$QV$-jJxQ=!qF^sA1Q?HrLN#_BJM69DCD5A076nEt0 z>Ce_!6i1!)Xa3i7wMBzE%lo7e2Gu;xb~{Zqo(y!De86l=(rDpf*Hat%I;8 zqn&uigxjGXhZy|0319-!OGqIQaiHPLoLfB{g%6a}>amT#ww;!U8AZ+SdO`*68zDj+ z5W8Fk<1M1*$g^pAys?Fe-QiRGy@2o9?bEiJ23HuxpqJ?z^={dMWuI!HIwV0(aQ&1| z<`!|coQ%~x2eR`$8E4f+>fq<_DS5HM(xd*xrA|NGj$9K@0|T5AMVfQM+ld zu`X~SVRO3j+!k$HuvDpvF01U2Fy3ca7#)`PqwLj|ydKl*aww+aK?Qz8T0I&X+arJW zMJ(X1D<{kUVllyGNTrz4)7SkdvXywx)PzT|%6Y@D+Yu9`7X*hw*+`1Rj~YW3*v6An zUjUzzD7xmD^Ms}>1N`^1|JolK6ID-hQ8uSf7y5aqamxMKqtBCCa!4H6cP%83q>e-W z-2H;6m|&T(@Tptw>ws8zIgks?EvMeD0ete}#;iR$TvB|gQGr86P=m7arj>m&!934^YZr z?NQ>G9!!#JIP{Sz@%o*fz=5 zNAXL`_A=u7^pE#!6B~=a{g&TJ7Y^7bvY73;~GdHzH2AK(9y{|Ek;9Pz)bKRUgpm_j5bu@8~b zo3H(8iLqdq!d#I<1=ZrC6I`k?N1=tm5_t0hNwv%F4u_#CJ6otx5@6hpH|?nW_=nn3 z`yC-NL7fzSA70!@1Y&lZUwCmLgl~R`PMIY53cn2;%2WTz!F0%Z75>IO@BYtWg5@_n zm^uO^LDP3GIg9e}k_w}1X9|-6FeT0#h}i?>f}#57#Pva$|AUi#P}=_>UjH-pgyI~6 z)H_gs`A08rC7vk7$qz#Um=49hfWdH4G$0DiA-lAA4jv*aM_?L$(|JH}_;MB#p|a!k z;|gi7>9B zUIO&&>*1udoxI-DM6+bOU55(D5t+)HonT!S1CFSeb5T0JYGB|$9`Wp-RK%tnM+o_c z?Yuoc*DJ#e$Gf(ag&&iK8T}qDAG#_V2&Z!@jdt=nnz6rO6F#jtKs_{{=bc1<=YYnc zpJTM7O6SOnsR|l%Vt-BIRZd7+AQ(`N_4gdTQU2>PMu8)~0 z3doucH&z3s%Vlr!d91HUCC%Q_6*sZGk_tVtL+fc0dEsC{3R^h{>U?lQ`XYK$rVrL~ z)t%zLA!8*>j<74A-XV+~k*(<$un&0H<6dI9m!;f{N>`~RO<{sEshzCHoHB}qIF0p| zbJOy(L)n+2&;3NK0B`)zE==Eimeh%-O-$DsH;x3BOEvxHdw>KDLh)CdK<*SIy)p9f zC&VvSTJ9mc4U6K>5QFA;yr_yDUYj!h?<#PY819xoR!ygwz_S zOT3`4oLvl0efLG(WTZen{qW>qX%9>{&GjIeV1 z6|JX-Fh)%7S_}6_{3#zWx_v4poGn&aoVScE_6?l58Mjr*I@Zf&$g1rxF=1wB)0?rKil zvryf>J7Lk(U26Kl(jr9g8p2V^(+Y@ZOww~AK&v>r96GWob*%W<&yksZ$r6uxjRa{QURc?YbKD)123Y{>tI zGbUzYdwYdJz~fKT;^_EUQ)Bg|kLGglW~25`&8A?$eWH2hDRD}QI&0-H{FOuqx%O68`&5i{@C8rQzI}A7nSf!$`M{ihd~Kv zA?py?foQ;FW!ca7o)2t{JheKt9_?LivxD9zW03+R;|_>*nFVD8Ezl5|N`Y8vYzj{~ zDlpM^y@eJ)3vbZx1ec_6m7MhqL#PnJP16h*!#)Rpf9|EgTJjHvSAunal^vP-_maG_ zkYLpfVlTVW+>SZpXenu$n3SQ3+E!YMC;6U%zHPPmg}s`-epp9YC7)?Bp)suTO+w}L zP;A%74bUR3xA^{F)5u@U*J*cHhg{+XFxpC!xT(m5h0F~3cj+WBszf6-nCVWU8yfJI zey~K?YW8+MQYWrz#~gEp%=gx=fq? z%RO`f9Lj%J9uD9AW*pXrn$Yw07LA>tU38XIC|eoZu~C^M5xlX{6hYy z#Hna9G>ss+iV_~xscvHeT2E%8%QlIce6_Tt_0AdT%A^_c|(oy9Zfr`WPc0 zvg8I`jWfYbVs)As@p{@iK84^0vpkQp74!6S5m?!h|3f!#giEt_47Cpbg0UR@s|y1# zy_4fZUrY9^6t3lCofb?MTy-hKTCPUNvNzXSyPwCIDI;r_wwKndL`P(AkQ?S>ROm5g%ArfFQ_9Vs$-4`hHp{Q*GoCLq}h%raZ=B9Hw+og!k+wT>7SGbCY(d{dBxj(n|O zJYI2>oi0jD5H~!+Q}qkE@5Wgk39%Y;@8WE#4ot1+>t^oL0Ny%=lYJA7MwPRTD;48T zb013FD{Nwv-n!7ec4v{b9Q~Eo;hk6on(M{Oy13^D>W2Ns;=A4>hFzeWt&NKWsRIQM zTJE=<@P;rZ7^lL$RO86!cO`j9^~;TRE&ooOp7QU$*8F|@6P9L7I#J4v`}8&Z+_Ib; zndhW~l+ocN4Mxj@zAipK-9xmJtmrnuvUmodl0jAN=li)?) zx#z6G-gp~}hK1rQekF^ugd1clUld)!}w`1^Lj7N5m=@las3(D`hvBz{ZDYD%u5)1~8593hVPdl_kn>q7^21Bi@xlRcmYT{ns`ZP!TlXb5~B>UQC^(iB2kJ zWQ{V-I9f*}C8K=T`uY{3!7fP3`XJ<-n{!auZiy47M zh}U>Qt|#N>TTV6g0CkvUWCnaXJ#w&++UM*%!!%4#m-coqrDV>Tf&YfgClcfgtu+}%Bv<^foE#Hh&}NiT7}w2Zvm zA`{fZ{WLv0i?RYll#EQ^Kn<@{H>j2rT=2U0L9SAakFAG-X^q3Jx+eth%Kh3@c74vc zozGk{?~XMW7~d>t8g>t4`VPFJ6)ywcRs(2Muk(F%kcQsB3L^w`?-MTEHc{LT0tD22jw*K?lan39n?@l(J+@m`{ivWkZ!dHAmVFy)y2j`3@s zfJIKivJ|tMyBwR(jMOM+F-}UA`6mERQ}ZPK&qrOhm@YnIk74|8ir=$=l%8b}%)rw5 z^~T9WNZN7?+%22>HqY_XN@}{eKM{?YqaqakK%L?6>O_04dAN1+u#jXP@$UWx_Hes{ z?1D{}y_yU+$pPNdQ2YPcOI{p&b#W9yHze6 z-MD4X?OVdbGpv0~OYO7%h+58x`xNns2tHBK$YWKT%f#IUF16KBDSEsw^I^8xXE*qP zDw&6qI-few{q(dV6B-n1XnR!Ex~}I?UO3_E`$|M8lMWbJspp>{>_e+PJPT2VQ2~h_V58GaSoLa4_7fX#{@zI2%pVQ-W zao_N8`@!gZEd!2rzDq}Fv_Z$XS7s}Q=JdQN02vN9n8uDzw1`J!S8wkeA7_^|JZsxf zHll1LJ+21C>6p*@2mOU|gTHGI+Pd#%Y<+#`W5ZdWGFn81^>_VOOGfL*owE^Rd3la@ z5sR-55%`Bi%zv1#LSrA%NPjzLm%F^}lZM?nY*V(6Eu8iY*YK4@R&Htd{gnT98$>BK zT)=9_$~|Y{5zMan>7sRDR^(D^Ac<=D{fE+q@hkTis!0kP{It0Wc?6^7@4t92qb&SO zkS5~97;viOnDD-cF3E6iY`x{9o@#Pq$IRVm^67o#TTvZ*1N6?`e4PSVxsv$X!hC0ezkGAyOYQa?7%E* zDVHHK7Vbrg+ydjH-8xr9iDCev7EiVOLc-HjfpMMM%9!T3IQm*XnXl=+_tgM7KoJhW z*BvwZ*OSBw=!7z9V@F9p%w|4^8Zf?Oe@*M8K<^K($=M7!LtB?gHYY3$`|23rwvi&# z_MUwT7%5||%J;c2x>%GRHjINP`YvrE$3N+PcN8D-p=eborO%jm<=REGGitT3D$X;_ zz{dNH)~eWR)?33vq!wmL`(O)l?M4s+fC0y$P(Th316?aYzl1=Vh}i5wMU^|Zyu*EECp3KbB-cN2Iir- zI^XPc7)iz)zp!Wj?ij6Aa7a2^u}1OvGSjh96B4JSIPK`-25IQcWWD}K=zH+v<-$E5TzgH9rqP`H4(buF^0WUGCa_mAsabq(L4n-_)4cqO}QMuEU=+eFE z1pPoX7HrN(5sSb1cx7>zKU4cqcqkHX z6pd%zJR#_Lc*!Mb-y@POSrz~J7xub?y}6cwXWER%sUWSW)|%?;D+2Q2|9cm}A8^yN zZB9B=Bb4iPEut~;^=AIOfASaL|IqZ+QEfcm+fYg=P@rgWic_?>r?^un6t`l<-6cqI z_u{U_-3bMXyF0-N8YCr<0Dbv<-}C!p&)H4xedg}Y?40Decb-uzp8m%Q>mi1n)KrY? zFao$90`I6QNKMQMlT6nNo?Y|R$G%5}Uh6}2a`t{8ZOcy|THT|dNkrq*s z`DK&k0M39U{bd)rN0cbBc@R7hAu%=Jv}=MFtBF$a)>vc21w% zu%MTwwP|U!`0PDK(+kF!l%0AP%RN6-?RRg8bGMcS6@Fc2Le}Xrdy>55Ni6<0#_!A6 zvG;lXwTG9+vk`Vm!vxmw>_YS{iLTiR9sgk~qs9ir&>qEI@Ul&Vg8{c)GZ9}Z*&a8V z5(@G5te8LZ#O|faPN@ri!lNeXvfX}eX&iEs{|>kcp8?7wBc<@?02Rm#+-hWUnGc)x zT0_2eK!;!aBnY~G0`P?I(YpzDg@BA=Yuh})Rooy>(OQE|uhA|!a4w>*IHBjX13c4q z3>eztC3m8xJV5-ZnW^r(pqaipwZb|RHI(LqbS<))wv*3$1k+qyQKC*0w{m%vd3nmv zkQgZUlp>{Ay8*$pQ3a>aJf&EHRw|roh4~1|GhD>&Bb1lAAc5oYoIz+4x%X9D!3jst zein#~#_L=n(fIuJ0|KvPd4RNEc@Js2VM8xgLQ(iUYB;si3%IIzSYkF*IcTJ-JTJN1 z#+-RY_&!*a#PvKPzA}XAi^85e;LykSHl)pi#^qO+&#aB;` zAkxgT+I{%kFxZD{FHz{Tz#ATU7^BvnlK9Nci{AG4iY|~Xmv!bSbcg$S>44t(ProQn zwkm&`R?i+SAE)r=n)JuJkd_^Q`F@AvpQ!dWI`MTvr)Bcty9`>neF-_gML{mZ_F0WD zuYGZz%jU~%MiNUSzo~;_KZl0#9ABdYJvr&eVhDn(H|vf;1x^^ueNRQf8S=XHREt;> zV>t?CG7V{1wuzy1(Rd8zF0xX&Lh~vU=oAPg9n+MRPs#1&7ze-g{77_j~K=N8!+n5aBYOg4HFTU)30 z{+X9|LX!a}qaf?o27RY#Tw(X0*B|ff=#^0rbo|l6`BiVUEIFOJQK8t(>3jsr`pB6mLfkc&V=xCd(hs@FP0$ zB{^&}%(Yd$YZrBBEzHJcGw05<*ybyLJXIDmYsSa4)0rm7TjJDJjuBxm2yN@%coq%U z-P4be;XEVH9h8{|;_*oTIxu1g^(&Z$fczi>a3S;Rx}7+{q(BzLTZY|#D`%D>H<;%~ zdG+nvgv*cmsIE0j-mz)P=e#dk$aqL}b!P));gZty--hLUR}JxPsEejEoi$%ZTQICy z1QD{!C5`l9kkY;rovSUb4XsAO)Zm}qFG7B^!Z4wwm5#QMp}x93&e=8$PF;q$5u~jz z^0vO7Ef{_Fi&Nhho5*kUzIvF?%$doxtvZF>jP#n7ATa|Rz3Oa}(SWa)uTdau_7 z$yC@s@6d0Uv-b+~b%o>zhF{`s&t^>m34kslGIQzUm}A`J97h1Ssr!+k9P6<935piR zZ23}6?9v-Z6O)dSGxkXT>x)Q`On9anseDDSrMsjYEu@W3{P)*y>yr^>Z-xEWUVTxsu}XQV z0I6CWQIgCjCx&INDFl0udtkrYcJ&k@z3@}96CDNSErg@EsJIST;v_+~KLtv>t)wz1 z!QsSG^(jvE3lfo`IZz$TqzS8Jj>U41KTM$tk4#Xy9W`K=a=U}|hprXN5ws4gg z;AiZ>(+0JcFyjCAl%pZ}U~xK`D`6 z$xPPuiR*5{@`QB4*$5sE@2^;A6BwA&Lmo*{l<)QOlv0{GS9un z?aw(hDMMt2lZryj55Dq9dW%w#~_Pb^uQ-=?J(*|d`N&(4fhV#Pc`{Q~9%|JbYxWf@$|cao_U;e~8*YO2Mz z#amB&D%TX~Cn0L-D7ne`5{gB=(yD*D%$zLTFA`fiieZWTxB;(s1slQo`p08d>3LWr zJ1ZpwC`D^PGJZ6Xru6=69?{p;o#Vhe6!VPJejUU9W>l>Omf52;3xZ-gUN}bpM>K~P z_1tdRzoB7mRwM7>-AlgWgdOcRsgCO(BmHqlOCIjyz)@@%s;jmU^c9`7Ja1R^m#x#% z3yp*cIwLjVi&j+8geu2rXYjxnu&zigKNLF=$$;R4E5am=rT&rR#&YF#c|na9V2%uZ>l zpH~bQWCy(euB` zUG_Jc5t((u20NRexKcQ0?_tb3RkyW(` zUhQ0*-}IEuX`4b10bf6}N+gINa7xA<$Q&Q)c=`QA zQ6v2z-H!|RaR96zQe}x4P?ndQa=c1rOxOoWQu(9o&v#%@d@qLOeBK@xpzNi(Ze6<@ zd7jG@Vg`(0g>hU?{_e1Ei=nT)nOSDP$&%EPYIB~8apMUp>Q+1X{H#3#PUkrdXAf@3 zDQ6(Eb@Y0lBW+2kMVZKB;6vhVDf-+^RJwqSf! zpwTovY9UwBEX3h0Q8P!P_QI+(jU%<`Ns0b3a|VKr7qDkM-(pj?fbS@bFDow|hns{$c%O9Wcq=ze&O3wKWN3bvS`UoXO%dvMg`g?ODKbQF!I6C9ZU;86Oq}9< z(iTzP_75%(UTv0bzSan4EGqoKW*?L?;V}-hW@vBCbwZlDsq(=Y(bO9Dq-6fE>f=Sn zyO4>q+DQ>&H<|Oin{ui-{}SNftZk~?l$C2%bXvd>%!V6+urV2&qDEA{0$zy-|D`v9 zhm25{*GJgEEa^8b-pY<9I+O(;-bQLt=)N&>`a#q>we|{v9*zV!9UTW`v^?Iu07g_& z6&Wr#44_)8%0hN3TI|;lJQjvUT!~&Re5&G1_*?JF4gd=gwx`{V!bIsTWT$1LwGeLB z1CUGA4a@)%-=;}lD`lNqUQw4Gd%{R3&aVCXy#*f97ct^B<2yUX(F9oNN>ftt;N5}DA}uN=`aoBD=`pY)&02~ zK@mf3+s~%)Da>g~NbKYuR1N{aslE+FwYf509?gx-d%KL?yms(h?)+-}4Q2EV-tNqS zQ5duMP$V*OT&C@O#Vf2Ef~_xM^|^fAnFi5W?wvWM4|TXj^%eTJ?^Qu3a5Kkw0h|LZ&sf&_bgOu$FE-b#I1a?GwUUxuSN*{8{fdi z-y<~gh)-nxzT`_r$FVvioNz|I(y%WjGwfG%eF>yPOa5hOkypRl#_rf zO&*M{g7IV@bm74`JQ0#yAAf2wH?2ObUR2kc7`0990zzZ0B5GF^A_&0qM{c%sU^Ma_u;Hvcj53vG}6F+~%MhoOyTbA?C7hkwu zcL!^5Ex=;>%@z9GoXYe~olZ?fqx*)(b@ejeBu2X)> zszWu<4uBpGl!->3D8B?+XsxW$6n^!8xmh~v6Mzo`W(Ey|CHAb_q3eay3@LBmWUx$& zcBtR6m@3bxbN(~y5snPN1qLFX*$%P`2lz|D=Umo!2ei~9Z-TS7~1;~F&Fsn zZn9vSVE{-I0|Ey=q9^~)6+j6@`SgH&{r`agq(FV7*?(?;5YV)8EO(PH&U1s0GwSshvM zaf%5*wih@rPRNrL^5176MNZK8MyihU2x0i?Tg1s^Zn|g-l@(McA9Q{m~XFUIfg5klBcELx}>fj*x?JqW{{M|dm zJA}=3*U;<;8CaH^huX8`X|E@s05j1tAh8YB-c1iwo0h;R>v?Ay8ce9i;PRtjJK`Ic z$YD;x%fDi8rEXshm*fwqukM6iSby*D5-vyt-4so~2DZ_LdOO?QY;t()yDJ>~WJ}R| za80TJ+@BRB1Z!!?o9I~QpDrwY)%j;;$>GBKFA`b;sEsag;iSf-an7B((6k{5F9f8yOrKLqN&-n817`DwRnjGoeUY8ohxtSvJsN4{<< zn>qs(aIt)px-^2aV|J>s^P#va04(7bKR+!X-I%$r40U*D0cf9 zcpaG|xAGW^29AEi2w7Z@m>W%I{#?uCjm;J8{N|^1Q4D-6eyBo zq@?#{{iZ8@VaXJ4#-E;!3YDpn?=!M_>G!GxZHjEJ0GX+&(HHo-ZrDJ=hG!KXMRyt% z9aDRLtm1_JF%*+BV6VaY6=G`!4=yE@JL3*+?s2+$3uL0ILpKV!v}EuBaikIztA6*j zaV|dXT5KR@6QMeqm6;tKa1==3xA;CWqmyBB{CSk_@H7$!=%Y03wkhd$k)-a?(Qe^# z-_rJMTiKfk?8p5vNnraH0Nt&S8QwN2K=blu9< zhAV%IVai*e$gGkR>&L_LNC#yq;-$J{#A!s8RmTEA$!;+KvSU$tjzka;;h*tpWn^3? z|4h&iw~uf+_H>zJYbt#WAZI+-u(@Oi8qEi#D zcT!5)>`2p~mY;4<^%XyG4``a5C&SA?GzYII!OQKL7{&6V7b&_axL(CeD>SD2o}6C8 zJH16=2`Rd;;H26bq#H=az5Ck0c*<{TBqK%7>S8DK%zx8ZBhbt zKlX!AaQ~bv8|sfv4A+}yuM5<}k@hQN&9?YTVm={&Z9y~gpgI~Jm_kAA~HJBafRyU1V_N=Os{WRrj zo5(+L<pMQ(iO8-1ZlmFRkhZ*OFCN#b@z7mj>5 zrvjir0pnfgldTBYId-CgO2*F=2il@yw$8z(Ih3+%i$&D470Uc~5wC>IGiLuZXArv( zpw~-2D{Vwa(k}d&R5-FVz<1~RScofJg>7g3UNMa|g6c)3pyT_0LrAG|E!RKL=2F!R z(BQzY>?G!&?}TMZ595`;C1D#Z9E%M48{d6kXA4!v-GqiM(->%+#JW^~)j$oD1ID8b#c_+EwN1o2yli+G#z-aLF zLu7NpZ4M@WUApqwQm=(#*wG=0;bVb+G6ASGDRP`=>LVKmSKKbkRS6I7eU}2UNwbTR z!U<{iam=-p2{gUr^!3l;vgE~f{J5pC(3wxiw5(>OpetB=!uQH#h8msq=lPqk7IHBt*+8!n{Fvv{aVz!f)UHGKDp2jn-Y<-V}IJLPPuo!8-M;P zfRD@88i{48dd-8CP1XMK-Rp<~CukKXUbTm5N9CHY#?h||&BaCc<9X`d;!OVz`^{!0 zLY)ttg=wJf0)xth%{Q%o-YdUn@$7s#Bfv{NpXF-;3ianZ;c_Y88v&TD%0_<9DZy+K z>bazUGOKM$j>~V)4GY&J@JjLfo@zlPG7!u94$2-(h+BRFjA4$I7WiYR8(zr?wa0gL zv5T>fP$q8%Esm)y9gX*pYD;XcK?6d?nifBP?UJqtvmrUP5kqq%ANbek_4E=Fd*4_; zi*WAW`Ff0;^lJK4xMXyDnV_05T)+GM(<&Tdyq}x>^IR-j{EB%BZaR7s$~#@v_T=he zU?f*!@1lrh>puXJJf7dm0f_79FVkbz4#~thuLxGdIkrf#+7EMe89ZhX>U-Hvq$@}g zr-uV_-^3C{%J=>i+)Q}`bMV6ffV5HL_{x`xD=jgMGU&OyInPhVFU2j-pa$tQ>XLF5Dghkh8&W+z^l&ymIPd?H{W@e(J`>sjti=u8?1Ghe_G;rSi8U&UsD&;LvE z*~!SEp-tD?I;%X(!TxhJs@IyWWRQ+Ffs4cauM`DFs|1#0SV9_;iD z0daOh#{51boEZu-zrEswqx_gEwr(L*50%S;KOcE+R}X0at8bKB?r~z&F1)%kO><^HL+NW{(r{CDbw&~4_R1F|f_h-^PXHD%GC%|G7A z{O?eAQUT{!=2^+pbY(cZ^p@Ir7nCvIj@Py5cCVuU$nbH!Ci%U}RVg~7Q|nZLd2-rz zab#8gB8L!V|IxsZGSGSPz#n41|5)?~h@@FO{KWE=d2El$^73iL>xFnM=>Fb2-xF`2 z*0BPN^;(QGFk(jVQ~m_uiZo1py7{-0Ny0d|`FXv7C7v4Vg7TZh>j++4d2W!2m$yiv zv2~EwGJMS$mOCDc7KZ2cc>(p|QG_HQCD&!9`BXF%&!gbcMge>p?w{dN^lAwDd*WvQ zSo%(VU{CN1bp9=1p~~GWwgJpwmzU+4a9LgFTj%m&5wyD{h%1TurB2np2|X1k%M;!~}?)w}nVf873B zdO#>lE~i2gUO)|d?wp}?h^TmYk~aN)ub<_KurSm>Oz+CDMq5-(+fPkf@DnId7~ zf4_Iz(Px4yK6ZGs`EcjM%k-e#1|xhFT9WtO$JX!b6|Q>sP$6I8Yb$gix>WDvaRa=m z>Q7mpT)lZj;ykVf>i_E%-?!>~{Gj(qdm6VjV2j#Q|7miog;BniZdTk~M%EA>!Bj@# z;sd)p5k;EJTQD&&y#6)jsk&}Cpys6*nJ$#GZ$UR4(|8Y7p38p?oMBYBl2pwCy+UbE z;Pw@K(-bafwXfWQN0|Y?rvzmm+~4GzlsoaOZHbxwK#9FguPT4zRWNOR1gn}|rgrsO za_Z{F|D6KLkpFFo4Ltx*zIPLnSYz@CZVn43*%5zb)K|_q_9^ip;NK1E2E5rN z?4LBBX2>9quW8rgB(T_B>M@7BuVWN4X zj=E$K^lgGG8;jQd-J)i-M1HU*%RhzeZQu?kc;foOhqH5gZsb+=)p{v6ElA4i6JnbR zDjQ*tQnmCLaN(D8Vpbx2dH8b1yLZvXjy45V%24(+C+4@~W2XMTHv ztMHfcieoBu{f_xHuFBKX@im98#yVMd+&ozrRg1WZVAGa+7^zHtUPWA2p^zgxj;Fnd z&;Qi|sJmmJF}Rab_*!ej3a{z=+WcbnP?j%pSMUR=foj#AIii%2Ep$z}(H>E<3wlq> zLNuC0bD2Zff1_^zMy>l{W?B52!~cpWdVUtxs4Xi;mQ2s?uPvInFTt3SsRV)+K+%9N zxpC^aq?X}qjp_t3AwxJKrZs<3TYohC)McLNu+#hcyh;UZo{Y$7e@mXoffu>jLEE|Z zE9RF`-;iw_2rB}uc^0Klyocibc@T>Ay86dCRBH~30Lhie<;g@okq zEIp;k8ua+`l^u2U$1GxJs!i#})PPYcdOR55NJ=Q^e>M zx?sVAWmzAEF6TO3Y+8<%GmfO(4abw(ZjCr2podW8G6#%%vk&_-`7qdmpXndQc|GY@ zr4KCOG_}8Wqg_4}KKv9(YU+4FwDCefvRnDar?Pm&3#a2fozt8r!9h413YDy^v3IANNdZCo3qk_lu*Kc|;?{_b*$oy5 z(St^zfuaJi+CvJU%s&(4E>||~U`Ib{w2y%)ggLHOi<3CHA&9F^acl?GnScxoDPJze zyDlG~SXBs1P%1cQzaKwx-OczBTfTXwoKj*L)Dh$(XrgX9fatk(XE_7_c< zZe;BdZ0>Ca+peb97#pZIbK8ued@5`E5L$QKN<*fl-Lb|3I^)KHi?Hva_0;?lzo>z@ zX%fu&KR%$p_qbPjz3}eNX^A(IrXsmw#N>4tlOdD!-r~szBaDlXS&7mw2`9ybVZVnk zmm(nH=Y&VaE;kG|4)>Be)PD|5`Yt@ycH+N!18|_ofZsOy!O2%*j|;<~*cj zTQmvrEQ;|Yz&CldJy8I^(#&roke3UVDas$|dJR_0EXfukq+BBhRMPw=n+g*A@w*pr zaV3a|D|_pbzWns7IAdyC5AeLY#v|-3N~rDl)BLBz@stNwCt4uE_Z663lc;^?M77+f zQ@v{nH?;kn*x$Xn$$;}ZkU5LltcIVWDr{(o>GPT);|4eHq-JBwYfG1rX`og!o(zB_ z!=9>Cfc!%i9Xeb3tWMNy6&e`=o-YUH4b%@d59Em{vPT5s&JV*Yic0uMbVq=t2udLXBzhPGG-H<@+6x%f7E7} z&PwBa%@aV6qm9YYPtZ76gX`1h8D^uZ`al^`on`zeGL80nz6tjykUn*y4#(Pi5~~Kz zW-oh=nGUJdFTWO3m-^KgtyC~vcUSidnIZmQw$5Z5ed;h>}pdF-@!y6G@ z0&WBAwdh^Ma)08=sVi+h6L9&cyMh;B2NA$DNu{vQC=th?TU{x_F4G&3lU0HbZ7rnV zlovMY@992t^8no+k4L6vi^XiO<8aBn`4QHQ8S?cfc6)#0ezNu}QVz9c)_i%aCm&dk zzv;y|(@}zyZ@mH?`gLpFKo|<@D`_b+5)nC?+Gd06B~>wn8{KrCj@K=We{nfhOTyCx z+Dr#z@Jh#k4MhnJnu%c?^@fV0CLMSb2OXGU&bx25`>ARS_v<>y{9vXXE$vF+jTPOt z8nfKY;Z6nE-|Vj2JasZvx@%$_lnZNaquI-9v}y%L4_BY_>}wZ@-~HT1x(mi#;c|9E zg;zlD1u!w2GigrOrh#vMefyZA_X*AB{ore}?bW&PROoz(^&zox1hmsbB`(mh5c)3;FlX@A=~Lx;T}GiBtk7DH zn{{c+)JG!`z4}t9_Z9u|E4agGbP0495PdxC{Z`?a^FleGLZ*moBzsC_*6QL2K#bf~ zGH*zx_<4j1KPF`|7LNBAO-{Y<3!u^S`6(8G`jol>pRigF+>)aq%MKD8=Vm3nrjx3} zfF?5=NMq4+~47=rJ$BPFDDRC=MB7)a0{Fkv4+YDH`g?D`pS^;>O*`7@!O z2Qy+!X`^?F_u`aqx?z7e(;TmL8$fGz;+>5wIqVp?IlKFFCKD#6;$G%6#C@sqI_c11 z!^_{Xv=e{)yQ!1hXTHhLH?Wkn4>XqsSx0Ccc;GJ;6yo(lohG6%%svxjE0n^75s5U6 zQOAvdWV4^o4aSGPu_7Qdds=hJckrm^+Kold;0#4>|J0sI>Q!65v?hrA4oQi&|NA)k z0G#Uy{+So_l9fRdR_ZqC=1X2!h==3i`j2AvONuBfs@^MI1QHh9>*N9snT^19+T+~( zm*s3Ct{a}jL`y)Dk<3*iLm>0H02VYl?n z!)&$nUef>}h4HSIjCgI%QD$KsSz@@PJJG3YTo&5b-};kQnXdSni>2sTl;=qQ=qbwL zI)_IYd53l;BQqmPow}8E>buv2U#iDwgC z#r?f&j@7RSwO^m7uj$4Qf0mKI1&A7*-tqa4Ml_ml4^6eJ?P=dT2R%>B*}V5g>D_;M zy}kG5M3hudF;-l1tfq+ZK4ILPqP0Wo%4NY+CO7Uob6tAtb-xZXr4b=YAYT;4BfJz| z-1fgC7<8@NQUq3T^sUxoCLLL91TNA2P%9uhgXFuIe~_l-rO=8$=lhvMk7?j~5CE2! z$gJYf;v-9n^C>}8ZOHjWO`y~`lu z2A>4aE37{Yn+6j&kEC7?kh@$W?yW9KsR-+B`J=X5_+wM>rX9WWt28%S_{Z%0tJ;me>k|u0(l#~b z4vo}ZdjI_}O-jGSg)~PJ>;*42l@Kilo4A}ego56j9S0#_ig%?K7z3$hPQIwK+I2jl zEKavhfGAPPlJ8V3M(B&}1(X5KpXbd#cMj zUgJ6)$f0*@kJyM+CG%{aH_FyL>Sis8Rrvf$6UI%PzN&+}_>l3l#Et&2OdFF`hY|7> zQ?5UJ*B<#W(MH`{jVaq+?7utW_Y@a5c|RC*{aW3TzBUGTr!91|n&8XxKa?gJ)ceBX z4N4BZMVIUVf07HoB|^DRP$@9Q+$rEE{1*Cw=9ATwqjVOkOJ?5(n#RIIHBo5AY0E1pd?W4!cT9bZEjgj zO4Vqi?b&QPeF^mZUMYbwfLt+1ZT;hc=MnU5UDM3|pA(QCCVm5k8bAzeT>giK_}S}J znwB?l?XSIP`Rq4-ZTO5Q1@^iTV!tprzMq9R{)d_xn-my8mE0|eoY>xk#{mNUfqG^x zU@x_)n_V&dCDKF5lH4fBb4z^K1nUc2>hOHIM`zPuT+3T|eXled-u; zTki#Te>L;{Y!${AdwwF>e1Y76J&mLJGcC$22vS|I#EHZ(hA|ox z8KgZ<0wkD=(C;NGxChO)R|b)6Tu@7x@U@W^+~d90tv{aUQ_2rS{hSTp@Rp1F$>eW! zRAZZk-`vW6W*Q2!T>jv~<~zVMr>RZ!v0AuIqWR){{|t@Gy)E;Q@?%@~-(DM0->DbH zPPU{sSrQbOcFM2@v~J5vQ$_m~na^ciF*eAWliC)jw%7fi9Ok)nt!0eKm@;Er^Uuqp zZA>plY~oQwC%XYY&6Y2lH~CZ=37aRwe=GfTT!1^mAt`N7Fd|x5WB4t3>*wYc=eJyw<QESJu2u;Aa& zC-FBq_y(kzORwz)Wqz&$N6l*xIy#a^zd8;fXrFhBJw3LYH8yXi=ssk_ymQUdfA4Zk zUO%mH%v%OxTTmTl?U5PI!cV$+s5ak^f?0lo@trOC84s&c6cdA{uSKRrIk@$tlB-zN zmn&tpD7!&TGqvQmg6;Pl0zgC4e%!$2La50JOi_Wx_PjfW(3e0Rh0X*uyQLZDFR=Es zxEoPcr^{bQT)s&p_ybT^SkvcUy!>3QqjsbB%n&vmBNR26@Ch8R2XqT5UJup~y@Z14z0D^k1@OXtP3wwmtt9vby;=#^fKPgd_(GOCcsCBM zqwrfh)D2#QjxqlWjvvz8E3z0GmS{Ka(IDFArl*|%n5z6;{T_%p-zGt=!F7+S;JN)v zSdvPRCH5MqzJ)gNa>+c`StHxIad)uNJtL@hj(nlLOb*`>dyZv%$_bb8)gkI?yAwGn9MdqG5rWLf{4kM3YY?pR zsFqmoF$~nMfX=IM3hw2&;vfJ+JlgBaoNe?#KbCvd?+lj~VHg3|G2ca{rfAj<&^Z)n z++rm{1`C_0fn{DpBnKZLNPl6qiy0QgQ>hBr6ba&p~4{sZv{OV3_=G0bfK|)A2Hwg>~D7QB_fXr*FdaqVKOS8M=iw%`B-l|{o9uc}7 zYHyrHrD%?4{xTCG6!P${{5A@ooQNvDS@iL4II=pu85LRdTo)?|SRo4mIgM5x*R|U5 zj_Y5Q3<#k0Zph}D=X~#pNH&?wHsA@f$yV13F{LbiL8s*QD*IdX&2@Xi%VG{Yf!sMX z>jfq2(iFbYr`x?ZUy_dgxKE8xIz>X~4XeV<7mE`NL+Xnnkk63alQ(}NC~xt7r_j0X zLOl9I$vGAmRjfLhN_b7@|CoIs-h$hNV@?ZA99^K+qu=H?+tzekgmC5nVkmz{hur2g zy#)_bf6SUWbfRNW4IH6Gyn?Y=K%6 z6BGO^XB5}*`bAOhHp6Im)bTg7&y>vkm=+czWxs$gtP0fz_RG?QP1cVxg{G-oznAal zYTc)Eyb2IL1xGMOh+B#SsTJpO1{z~mQ`dQTA=3N%94q#{mj{4c^u#mb`|(kuN!^)c>SRd?a7*gGp(e? zBdGQ2g^IzOhwGmnea}XXoQ84GJD3w~IfW0k^Ab8nzz1Z{@z)4LkY_gy_tV$u=T7N8 zKo8IRfc0GgsUs{RGDvfGP`i7H6b#S%rA;xBm7OWJG{bxQo6AXU*=&i|18i0E`5kqX zMyZ+zWQ6dB(0^&e*YFJxr@`Af(LWZcSFnr^4}Mx#;Po30V2y$50o zFOJ;Q18Jhf@jrcajW)O%X9o860`NaAY+(fW__c0+_8Sv|NuLL99~DD)Ls>CEYPIwM z6&%jU2bioH=8Tt*3odI;4wcVTiuh^JU7^{4;1fBQ(36?=gEyj9B3QH-o<{Qnt3Vs^iTj- zpRjs{2`>gzbcrBcDcy|P`_Vc-Eeypc^bI$9F`%G75frH5J4I#<@Iyqgz!OMCe`c4FF3CK{=pQ7 z6=>jlX+Cw4V}(C2Ui(;i8M1?!shEK~GP{%B3k9?P+QHYjdIlkY54|9~FeM$K3+Y1K zXaMGOW`UqwO@AJ)l?WihqE{n2(S@WeRSGFQrz^sqEyvygGdv^AXu{_0Y`j2f zLm7lEr*}8bKyX5e+wOy>tVvHW9D`Nu!buu2g;k!u-1Vz<{51`0+-$yoJ1m!YimNW7 zE5j!IvQXno_~m*c;4{UZ?azw7Kpq~Q}M=f89o zAWwh9SU!Ax13tTObSzs0d)~g!oi`st4|;Rh&7eqwi%{=~72mrDSsbU#{w;KkGGT&L z?QI4r3EzrYAd)HJqdY^o6{)4)`|k$}p=bLHqdCm+2z6nP0PYi@RapQ1ftDF;rvk49 z!?Nh4{@yS>rT_R~@h?kOO%oc?*m8|g12u?%%+GiEi4ZtM z+mI7u%hgcg*t0OFO|rsYp@-c(!dU9ATIoyLr}9c_8Ykc3lk(F&2#TiGS+Xh!_N)Bb z^~eM#x2?giZ)MP(_@$xmu;ZtN*t8AX2<-7Jud|5mac$XjOi0zD0S@q2%WYm*Kkw%m zk?W}@i}2*0ZgTczELF^3V@s3UfNF5)C`&Uwv<1K)KDrtYIItEc|AQ#?Hdp6W+(Pqc z{9K*_Vv2{CyFe`3B2HX*12SSkJ*m5`7uI)Auv_@w*4;G?U#)+`+JfyQEjO@@U!lh7 zD}Mg>NKUFBa68JJ=OOUBsYS8&=>D<3Zq+9s;K=(+=k#=l5(GyZNSKGD^TX-A8NB9l zbzhY~J5A0LDO!7E6B{%y|HshnDcb;l|Jv!C;XI*E6`U1Kqi+j9GiOYWNt~0MX0UyntEqB+i zaYjVj&Fb9DdhwEPd=X!^4P4d1b8xXkyr1#27fdNgFuWS?YAj{^;=}xDkoMDIDXeF+ z!#7gSkaBbJ$+HMTKRfy@@fSCgb~YVh+X*fgllC`Z13}sFY-=KT0;^^cOp+X<77HIu z2@2|1D#s>W$@!Ro{XjmTS?aPck#WHN6S+Eq+RsvFa)j_LB9tFO4`szjavzmivxFLb zJux!`V+f-xDl3J~U^s0N^%%W?t=c_-)vIoI|H&$WBmGNRWjPN}p&tfk7$V&mse#7d zf3CT3%^!a(sI*6ems*_+ZFYTmg@|@kn%mlJ!EsVY2A}SD5>iN*$nO(or-CHs?RgtEZ*ai(pu>uVi{>hE0W-`S zpnbyJ$Wzm_zlp+BIL~>!7Aa6EK|g)tDsiq#!<;tn^{sH&<)$ zsG>q^UEvFvR@a}g0tAhp)%qq=LgjyUhzW>q@ z9si~UtNq(M{=E1<9q{FH8Pa7#bIQZ7GOv3o=3fo`^ew?Rt4z|e)%uDJrqvN{KHR9s z?3sGvn^UG=>UHeC5sJ)P^Vm#JKZs2ti<)jCt;WlkXHKj1NDJB9Zd11LBM>T^(!s^r zD;T!1RlQ+c*`3WDR?T+nun|UG&)<1CJj1eq%GkBhVv)min&jz){iv4?3JTI=f z5Kia0N)Z`|3MdCQYt+lrF~a>U-8^<4cz}|b+uI-_PF^qAd}IjYN7SPW6qApxH1G?p z)|vEC8CfATH(H?R%t}yjjOg88LnU`sd|~fMX@sIp3U#%eHk-71;w2wryB3pq_>Zi` zD5oi_IgTdmh6en4w<0H4k`Q|K;n<~VIEu*Jqll8ks2YTR$Lx1Tgq;$LOtpTWHE6_? z$We|=LptA4&d*G9{=Bg{YaB&tO^Aar{gJ^(qm1^x3_1=$_WOd_U=8cfrwgH ziO$rg#96;{^IW9~>bQ*dKO$mt7{!BiGlGjL!p(3Fxhx~S;+Oku@;#0mt&;# z*R%Blbkc`|0w5TL?w)(E-P4&v8beeHe!Fa03u*jjxsXIc95;ur*GN%{=jwI>P+%^Y zJRGT5BBYjl#X0)Y;E&|=zfYSR;)fZ+LA>o>1SFS!2dW=~EUCl0X@G%uaCnbIJ|z0I z3Y#71vUEes#u7IjWV*U#LxUMYjULLghK}}@a4$7v7RCmXEGQEl+tpTP&llyxu+1U? z+b|g)S(un&kYRtgk#JAu0HUbiHNMK;#p))al0-;|^*POGyd{X74VZD{e$kZxV5wT| zIby{9YVDq@akA}x;en2P=M2z%wT}Y)Els|2sM^DU+HiID{wa~CU$^i95M(EdCp^6# zhLh=|%qsYu-BZ@AkyV0bL-)rE%5SkP86Lq-f!~$}Ln%|kd@}FWmx|H=BJhCBfp0K& z3z}}rv-@Sayg+s2T}5g*7g8sRSoE!csVn58B~=E|wM+u6q4kfCordR@VwUPp00Im6 z{^y}O<$;U>DqR8g&F7a*cJCnQ1TK7*uihqz1Ai@jkn{U98plcpEF+0~{78B5w%5Zh zWemglftp#o8~u$UEZ~>W`>ZAv8M}Z4Cm}fHV@S+z+V7i|#5N-2`;?*zMRBeJzcZVZ zYv_P2bEnupyml=+T_%&*v+GUJixpn8n^nar52E(UBFf(L<@Hk)dqR(I-d|^!@4c!x z^b5~}mIG(kXO9LN2TcC;mtxGw&ySLzzs7o_GJdIGl5^YENb`};Qo-bs6{ws~8b!`Y zahPK_FZtaTz20Mf_{YeIC2CmGIpF#Me^}Wa1OA$n@VH4jg>-5{n;6FfRmJXob2aA@ z*3`fFjT7MaAp85U5oKwL?e|9mYm;{DF0F&;uiSMI8E)0^or7i*ZIC)u4SIWAs#P)Y zVXdvP4qmfqk#V>wuvh~N6WLL_itkO& zh%CZ>=|H7g)kep!weaB2Yn<&|&xRK_Gz}F|*@g&YTLvtNP zWybw4JQ#PKQq%l~HGd6^qdy91?WAn-MlcrPt3fK^=xd~ag;veU*Mi?O^%nTK&fMhx zY5~9wO`OV6uI6>XGigR#MNStLL?pRnAlKYCJEzz3FBV|6Badi??j{|opQ zlW=feTB!pGA^Vb!dhcr2_w{X~$l~9pZ{PYEXLZ8+5sZlPx3$k9tj!eMdbpnqbN9XOd(V2`uhF;E`*2d~ zs=dCt*m)3no(_?x!y@-wkWWRPi8!yu!0smJxr;pAUA3LGiYMiqx>eiV)_oi8yNf)f zs%}=gaI@}X5P6pQ#s!Gy9?)k#VYseJNu+)nc^<0m;Jg&4^bD5M`nRRgt&T2?Z ze)J9L`|;iD@)_-0k|Aq2Y95U6H0wg04?ijXj6Rl1uzIV0uGoedYa{(bFRmI@KJ-n{3> zZOM1!`6=zAY0t0m9xaN3{;cA_mWl(;jfbD4c}AZD(5$%(!n`8dRk!`Vp=3?>Z|REz zn9mk4$E}}gp9x~mixnE7mHUdr>Ov7erZ2>b!vY4bNo)7=B7Gj#2o}-G#*ehm`0@gM zaa4G=&-{X3oZphZ|GXQ0(OCkD0Vm1av9EVji@@Lv-JI#hu3s$;RaETzsGjNcb=cxeNy>`)#t9#Rm@`ye}j+bc> z#@@M^uj5-KrF%82r?K95|NP*q_`4%s&{-S1RMm{?28um|Nphgln@2wa@%8j zuHD^IKe&rUD1}0)g^a+sp3F;@7C)hX!D;q%yduW-f!|7>n#wI#=+zJC+d0kj4q>We ze=?OBG{F2cc%`8~Wh$gcMHtPsLSM4&IOt%XlKFbor9SvR<3si2PQ@|x-K>iY{e})Y z8oIfsOu%ukZ%qw*W*bhwqv*`OZ`YOTBjDl=q6r_V+O!G2} zExZ$a-NxtHicU2;a|H%~>bn~`O^CKp)ys~MAGP|fKk1E3hmcIOiV@B zUh|G&5twuX9gsA&?h9*36iZz*CJ-3rjOGD{%{?X#iRBpNpzN5L?0GkJFtm*>aN-sd z2pKbhW;|7lZG4^pV^P#c-?s`KU8_xj>`eHxMc>c+&hyvkqhZXCTeVMD`2DoK=RtEe zY#%ZOJ@3=Q-~Ec(T;W7bp7#$nektad}@$A^FF`J0Ix?C4{pub{(`jRK=Zpe$evg#sJ;-TS=h0GZL< z6v!@ce(INIzo+jD|8MAfu|s$Kjk|o#kr0Ud`U>@%y#17O4#x*Lk6D$}=gH@i%=!30dV0!{^+=N(J-qL(IQMqHBtN=Kr_w&E%VSwysiC{ynA@os*7yBhzRxC` ztnd4-d7n)-S>N|-+4;()s zpWSh=$)>;7_l1AgjsyKMA_L@;awG4)A7k!*CLHJ&S^3_Iv^x&p+7OUpu>WF~^Ju8+ z;a%rTI_Zg&pT{q_=Zk6K^EN1kxz}MFp2><+= z&Bn^qxsT^P*9=XAl)eLime2Eh(bvdv={`dF^Lh_V0$&LK?Pg7zxQ;_}Q#9nhl(KTK zC%<%!>r?8ZBdU%p7XhzUDcAgt_=1FTVkb%$!iy3WF=@qw|3z#^Un3GmhEA-ZGq`7) zo15GavRrj!2_7}EfNm9;59-f}lydV>-W-oyr zhpxK@-=|X$qV)7!{~baH4YP<`f5M840(2j6!ovoAtll*=yvv@$z!1Dc66M{&W~dM2`;;E%()wT}E4`@-wtkR-&-XHozDP40 zuNCqUd!mkhFW(pbtW}qfzftneOrG8?DNfGlTk^+e-+{igZpUO{vq2x^R<=As0R`yC zr-KT5l`moK-7ntV&j#+Y|ZGV71;zU@wuSK8tHu}h~UkEA> zDx%?NH~AXW!kad-P!e>=&D}gf`CY&vLxSX}mvd6GDbwg9Jxj8p4kAjgl}J3~ceTFn zL+C?ly~w$7-93|?Ztt*a`0yCYkVO01^C6SlGU2x3XjaSAFJ!>m83CQ>%$ny!^p=hC zeS2o7hZywTEomOtC!rJ1grD#JGuMhico_#E9;JnDjDJx+C&i{F-*jau{dq$l3A=3b znCKLty*?g!nnGxskLXjT(7D-spiw|H(7Gm<*C_gaN~x;kr-)VqXGU#*Ep|g zj;~SE@bbMsSJ}V;wIT@@SI`nx$V|`cPYk#QeF1lG_g}etTa1J@QWkZ}H}s)yUui_Y zQkk4IS`G_>0HaNnGOYlJalWHZ^#x{l#?G<|H}nxG5g19*-sM+%8hN5#dj+O%3$7&O zV2r9n7d>U27`(ljkk@UNw6*Ihf?c9tNZoHFx)iGR8ijC!o2tcKR}%u?c|Z~t z$#N(6fPkCK=#ly(_(pREI+>zJ@x)S8VQSEaLNKkF8iOA!YijrVK7ziqmTX?eWoj#I zBD80sYxoMs7SZLwwqhw{6Q7PzJl0pmJWe@6%x@>mr0{W952o#6TV|xZMFRAo60C~U zE&;20$(Cg<{Dy=%+_ubYW1y!))e6XFW->-iy^EM&`ag?F37t5NKD!aOZ|Ea^Cw7|m zryNVVx80mct~A~?`qI2;H)#kGt&h=1aCB*0A1{)*if-s@)L?IaJ~@3&|rTK95x#Z!(2={j%VzX;5{rn8w6gCZX0HiF$ER zSH(qh;YY|~?@Fkl4rZHMT}^oQWFRVB+^PKGOmKI7jvC&YAJ4Jy5Uads>y(_(*X;{a zEE(%R)A#+?=z|FiDte5Wm(1%G0N|DhLxnD-4kFZw7p+gnlvIa0w$4cc9jOz=?dT=t zSSH?xIw}+e?R4MRNci6XNb%Gt5&n){H)2NKybjf*^7IxZ?m!2*Bsv@LSrHC*vcyZW zG83qnGT`IjdMK$JZs!MV(krjG5wlM~K zXfUnj3{S!}D4r5j>cy!lcTsRYMRifsb;0>4-kObzTHB3J@KfIGy!S(3)+cuSAjH;S zSMn5I=?A1y9}Mj1b86HdrCI?L;mrTYZ(aWD2&2el&=k7$f-+dp&nxuJ#VEQJHN0?L z&oRds9-A^PRfp(XrjfOsj8OzKnOk|01x(Fx29ENUFnmLIGbaEYa$OUHzD!I^t{t?U z8G811RjX#W0z$%d^p+NNy`bqp6AEhC&HzNI)(*pU@s>iavVf~lu5&|QT9rl@i5$h$ z(K;mnyQA;Oz0Qrw?jzUN>j_Oh;WW{?q3`x(6+Cs@pT7K;wWzVHA4Ym<=_MS(f)Gb4>O_sWda(_PpG3Zf!2 zGLuZxlJ;ua?wuQQ2JM0LkJNV$(cE(jrdVBLf(h3=L06$KFKA(^Lvl4kat4$3eK6@0 z@4H5yb4!xg2t6*P|by2QGKXyR%0# zS;*~h>^UI&#_M7*$z4aE$p;Lxn3nEop>H`+v+__~tpn~e9ofP1+!~svOUGa=5L>!l z*tKx^75eVXLJ~T&)}U<9Il1WjOhB(LLLgRGn48x}YYNBfH1z2|N*Cn3pbyMP)&c8+ zXYPy8m9wU~=1GKL3iQF2@Z7!~FvWgIms})l`dak)x$S6#NS~KM&tc?1Rw2VzB!%H% zu9{%Dq5o%r&|8|*9l7T?JFpd5{G!p#LhC{I**=iI1@hWs2JV9P@7q2ELKS>>?z46*TKH1~hL;KVv zWWnu0K;))=Ipo2|V@X&f)X^6ZR4gzHJ$dYTaj)i>*4J(+(Zu- zz4Y6T(mZJocg$V8W7=mAydnk5Z>T&ODgqC7>;-X{yM|&V6^HyjcumGYw)Y>p$e0 zef+*3{65chy;XW98)K>&X~~v7`Dhg%4%^sMjuHCCl{~_92$T`lNsA69?UY6%p_cEk zW_gw?wbX$2>P|&uJ95ukS2j2g?I1xfO)cJMpwHwt@5S>$2i(v{I1XZlF)ahlOP{@0 z^wAPR+)(CM)E94FpQoImSMKBXwqqK;ppU^PGe6Gg^D!Zw?8R4dqj#WhWnk_WErS_! z6;tE^LF8ES_MLHvZbKi|nSvYF^3FaE5IraKsZN`0SFb>%8~kpOrpNny`P48V?;85p!IiUtSlkVQr0PCR=4C*jsGs3W zoe)p^(G)#WAC{Yj9Pu_Xvb0FZ-@oKOznsL-RB<&9$=Lp()a3I%&!5oeKK;mE+P0)= zUeQNLPzhM0Id-QpA7enDh;u14?rh2Z*9%7~hNeiQ)~=y%u)ns)K#GRmhQ2$xQQnre zEE@BOK4L>ONpIJ!96_)OePp>p^@QO$r?0pEgg&yAi$qkJcS(KbN_|jYBo1G=4|Z!X zv`6X$`jQG>?=BY}xlap`ttz9z=qs+#ceieXxnJ;PGQBDE5ns)P+}TzvlR)#_=-5rs zx;rlImv|pcj>gbOnEJj>#UsK@#-+>%}U>i3aFnuun}y1tIu5tHG4xbGjJ&&kSa zP7)ym*%2%HB&yhsBtA5(%Q1yM?~vW^M(o2eOdE5f%-^ApJ5Uce7dn~bh(01%(-hkl z5J>JS)67G53VBFG2(nlETkh*h1W?>7>a!K~aj4H@=3w;gDKwmAHk94j6C}E!^AdZ* z>?8WzWiVBZ70gQV@)&*jHTpOSTDxHI+KxVmA=*wDtvdSdPrDjuco^fwKU5%Cw0P?1 zW1sR!eduf*PqGrEr$s|4nu`0Jg`5rcF|BVzSmyL??)S& zq5nT1(u61OvykSgINr)8bM(Cr_x)Y;AyVD=uF^bL)n&>QGis`f8rxKt&F^zqA~~rp z5HLg)OXcEM=%c4@Xdic}d7f35G!ez~TV@6G%N}<0Sw<7Y&$_x?f{*BXEB=e)H0N%MqgRH>=9upYlpv;Ls(5`Dxmg-lha6-=U!;_%ob z4nLu9i#VtY4kh{?TEs!7$>%+YaYrAg)N#(K6_$yq*EjJu75eZmjr!K3b#1vw5tENt z?1{6A`z8%7)BdGLCR zXgkOLdI9@r~e}yktvLTW z{?<(}*p95WLXx%mwBkOL_m%xR4PFRP`Frs;>0A%#8yA18bDaw9q+*Y>usEP<=osP9nwW@(ydUy@;& zZr|^p?rWYW9#~dht~1Sip2SKpLf@j#;|pFt9}5n}!*^_={26-4G!uN6o<_Unx+wHn zDUt#5&<&qB=z;6Kc7M$b0_z&}8TJwpW*x#fU8LiNe4<)bg3>%gT9M|~$eqy1GZf?g zUuvHJzUmSO!C2nxwwjxHQ(d+!>rn)ImUX3#ty$KJ`@Ft@Fo7)VnE=$ID7xW~ahCOn zh5Q%jLzY((FZNQ5Q?>ei1c}5P;?nNd9BfWHE=D0L<51gfJzG>t*xvmu`p6JA6Ue*k zR@TTcmem+suxDSyA-p{#j_gpH9kpq1cF}4aZmaV0l4b4OCOUe%W?5HAtbB*QEh~Gw zU>NYoc@a(7W^0zU;5$;$%}E{WfIcLMO{JaMrOd(BrX$^J9FR1$dws~i#?7M%6P%;X z->$T`M(nvR9o_Myq6dd_@oBaBU(0p*PrOYx%!p=!BoRqWyf7Oaaj2qr;Mx_@*bWy$ z9LD%XA6_N`6@_p+FsDca60cEV)D^*6#|l^kaeY@6M$kvUcJYl*>ML8Fc*v1lfio^! zt_zVT-u*Ljg;6^RJ_vy@a*yvcPGfFr>P`@W<9|Fx+q z2^(yjv6DDSCusU~dxX}KE<)SA-Fdg&ouN;yi=?t&h6ihoxb2D4TPvoP!=2H}L~wiI zd6W}L*r~f(E_|~rUMaL-V@x1*&qE)bzosG(tI~ASYrZ!F=$lxT${ZTQrMpr7Z$0bs z1^4?ByztoHtjByvgn7Q$`dj*?e|^!l|@mX*ycoQX4L>sGrA|sjj+;-^4!U) zFi^K^1%3O4YR-?Ok~)lVLb?-6yX}}r44*uO>8X9Ix~O_O_{{7$tMIwHPl`9(ifNyb zC|lMELvaN~UB4AUwQ%4|*VSW!MqP#R%Fu^BS>M>jFmqSP+1PiG(}iNZ?_0=}Zr8#P zEwC;MSBD@+8{!r?_32l2@tuSe6jzd4)y#&?sePR%NHH0<{{-)xvI#M=+wXs-5{KrMD{zjYhh@JJ3z& zJUINubDm$qEFo-1aXav~Y&?a&6nRtQz_Hc30;k>frJu0Ma>mfChzurD1YyI&X(h2O z%M^VY>}DMPowyw+Kb2Oa(n9K5BvKH2NI)H4f|q>bB&zcqi3O z*kZ~>r^Hm_V1?P)oQ7emnJF|#fXouQMIhQ4224|Zv{x?_0rOium!q1o*`PQvN-$#6 zm9b$hPKjb6rz})sm=g=guN?cnK)+A13{8J2^i3Yq20P917JgT>%9& zVT`%@0lVYpQZ3=a8cT|%#Ud=4a!qJ~Zh|=1F>urTw88=@zu;mpyJ-rYz1ZKwuKiD< z?;G^{H2N+sz|T*b{XD1c26wy1#S&<%!W8>I<+$vkwKd9kjLgNMv`=Gz-8juYfIjiF z(Z`#>45Nt!@Ud=T$!K+x@Haac{QT_tP!N~VkUZ%{^yAQH|4c6HRrDp-em|%)S>_PA zeigq%CkT%@-uz(wwN9Ah7++~G@XRlsWQu?FtjpJreN9-@_Jv;=&ek`79QwStAF3>P z55qdMWwo>Z8v0mT7rU#2310naQcK%em-nJ?xt4j;?+3lfc^d@IMEv`p^BSZ5W79r# zY13XQL-Eo`pJa+nzwcfZm9?e6&ykIL-n;w*D+E8gW>2%&TCJaGifz?p({10}cY*z1 zJZbie^!qmVr`>kSdPCplwz2O=>i2DKbKBUrjeVQj#=dRUWpkVR^J|{l*tfZD?Ayk^ z&24TQ`@Rx=--cNBQwz4a-!b<63;TUaG;uHP5C1v1_`h_-i(ntZHeO77k`o)+wz2OM z(B~Oukm8NzBx&wD=IJ@f8$yam`+DKnp0`2LEPJd-gV=c^L&nQE{>bsngA>GY`J9uh zZ4xveNttKo+z0`xM@B3l?CoD<0Hs=@p?>K2@uJ>@GTJVWI z+Pz7oxxW{Eo}C` z?n*!ybspcJmoPj3!{{5n z1$|DP#r8Ju`%Ye$-RVG7Hv$_vZ9c%JRM7 z<0i6D;FR;u;G>(_e*k^rB;~oy`@VYK$5wxGQNuV<(<-R*>?#?$CS#g17j zr;!QsYVo(06GgBqKx{ zzs%B`$Q0Qs`mSqF5(_VzeAr-~$I& zA$XchKangfaSjXg39AfZdVV6(OpS#PKWVVPv8YE%D-&D^eJb5j&#w-Sp;zs#CW+%X zX_s>}-X@MF+l8O8ih0rF#Q~Fyk-2se(+E(kB}o*Gg4d|%Cq`Ig@5Q2M8rnmNA|XX! z!2j=U=d|+z=@{n{V1$WCcm;i)Dx+gl2l=p$P9p~L5nra(RfIYdxCs-;miA=y8OzSayW-5u@X38Sb`UV!mt z7xrB@_E|iqRAUFTDinno@|k1)p)8kb1-htXAI^6MnPpaehkE8cBmn7~VNb=EdiRgP zlrltubj%Vuo&nF@BLuIcCxW8VLX;~dsPcq_C$7->ZVO2soec!95#~S+{xRzN zUXta}4D%efvF{1!v*gjw>nkN!}>ubMt~Ehuhl}7o&m&D0wVqqvVd$0O7&o$xluw|- zc_T>oY?{TP_IiC_uQGD843cttgYlq*y{d$){(vweLlQ# zbI2D3(s4im^r3D9iUGMj>R@H4$;B_wN180~ATu$4H(K<02X)s`87)MCLOvT3WnDm* zs%x1DN0P~p?~aaDHFbeKHMBZ?KBgOhJ3#45`9p=jzW<5 z8Z!PO`bM-l=IavwJ(40~dC~S`F)YyspCC{NDki+@@Gt|jYZ6o2DJ?QozeLq9stbv@ z;rr$SeG<{v9s6z!^IW1(uzNBPs_$V%qa!p!9l%Gt5&F6~{;^8W^uDE<(r(E~z<)zdGq!bLSszpS|Ot7JCxnH>xho)EkNgw534A#oHQlU(qZ zeNy>-Y`+Me?oh|>6^jPFIXDR6HT8Jx1Hhw4Yo53~!B^1Ngvw^ZLYYdFU!xCTF-i<^ zKJsagM;UgUo zii(#Ih_@2a%h@{m{C?MZ9AfT9l_4640t${wX${x~Wpg7m1IH$b=JJ`_S(i^oAGVd! zZHMuT(VG}m#4gdtgVC)>NE~%!-QGdXVCYZe<0W~Wyyz1$Zt)=cMpJz~1tUqzY4mw< zcPvQQlBH&DUZD?WWhiY=huky0YAR4)*%0q7*k!@xVh1iG zCP+GitAS9ML*b@V^tH6GmQTP&P1xWWeVY~p?K)ueF`1-!xoo=0BTK#BYk5GQ(Oil& z;}K9{?-Fpa^<0hVr82=-52-44(!$MROlZt=^o}xQ^~f$^ ziax&5E*dojSFmLgxD-+j z?7;gj`gjOTlrfM_(6_dr+fTpZqP@}9!u?*YPq;et0exx&x;Yu~m$muMETV4l7TC5c zf_$z!tsVv53-qmA8tZ_3{B{gD=|mY4j!aj6PqxHhWe7j6S0w zEW~wP;7*-IAfKANteF=(~Onec29uhS$_R>VkJNx3)2J z3+HJ#Y1#QO-^J6;E(O7_91|?mzr8}Aa4Q(KbSrSx_wsghllva}V2YcEI7c7KVb3k# zF$#Fi8lpEwALOiZ_FH|nwtLNXgxVx9`TO`P(E_o1=k{--kLymW0}5|P^wAsKzUf=p ze93*k0s2B2>z^`?C-}n$m6ewR3|C75oa*zm?|?p_yN)IBJ?2;U1bxE3UNAp>0Lo1u z0-O5?ld_ES*R;>8^2ARDY82=4bLbOUJ^JA&OPc7M_6eB#!eMSv?9pd@0DXvNT$UNW zMBlha-*;%AyBtuQk0?PXO2yAu=v+!=CT z`ziE!Pv|45zrCh)+1~m&hxRDDE6GE2uSkki-<>H zxlcUFZ^DGk{=|94FVVL-pqA%5a-L(_tgkxzD|MdE??n65zutxZ(Qe1;$Ia66rgbN* z^K^a*?bD9fUQpFL0=A$}PfxO!#l&k-5<*)Fg*vUXd5J!{cB2*WAb3V{AN+Kt`4U6x zvWs!>(nSG*mOx*Y`$>@*i_Y^IeP~gu7KYWG)4q4u-&1cUTKyh9p(dKo#(UGC3Sai`b+Nnm(gd|h+fd1{C3-# z^qMmj_6?tpL|geb_P+B}1s|q;u9;hrq#3s6Qf<6E%QZ39Pc|rS} z6+9w1SRCH(un1_1n}hRwze{DKRSuuE#j`HFtGHj_uflfDnJ@JZw9j2NnP|A6Pi+sZ z?Mz&Sowc_2CHMW?oTsw3t50HP<;BBrt0JE=en99`9xj_a6rS^l8t?P8&rI_oa%ZF6 z_=G;;KJwghlmW6veu@=+-7U^Qr;V1b{0q4cHsyz2{mAHp(RzT<8i77}$aD}CFK!U6 z!*=ONS;1%mjXo>{Pa=6cMIZ3Fwm6sjaPg(uDtz7cv=1aY;x8GicnPI2+vk-sM5F^- z?g^0HWabI=!0M-E!v`aufePVE1jw+y&@guWUx1-jDH`Ve14WUAxptspsEjG%Y zW@&5MPIZCbTJY!5KIcD1``~2_Pu_Ye%ETWpfdMz=+n8Tci~X)ErC`tJj7acjJc-i& zFztgiF_g8HPVlncX!#boub~?@zzw_T{heBd2p2mh*X1btSLlQPa~HF-vy>{{-Mhy$ zB5e_ho{=lMgZ9v_3!(+kesFl zyQe~q@nONPHIG2EDkl{CGN^^*wC}iL8k;9@=APg+-62TG1I3eQL*0&YA0H5Vlb2(u zb)HB|aKlDzVqRmMAH8XeRy%*G+~@p1B8)WpGUB3U^pQ+nZ6b^yQ*ne5y^I^IPNAG2 z7q|^b3&*~6F>^1}R}ykrNkOFI9DTW_lR6mQ4>#8KPN5GGM#O31tKD^pANF;7h%mam zAydp8BIJ+xb>oVL2pPl$g-LA1FRksgdIZ&kiL{ijiwe|1s1N<^r&bAcR*%>lWN~VW zjyuryb4H)xTsSf)35RJ?T9-pkGl3u|-J(_=qt$9{7pc-rBCldd3l76Bj}AG_1cI1& zgx-SWNb;e`E~@#B&RxYE8TWidD-{~0y3qp+IZOqE_I+!mUk`{F;*sASF}5_|O-C5b zZ<Z;ev)4izz~-z<0fJ*ltF@^o8%bw14%o1kRICHXusPG1v26=X zLdUu+*PdGw8NK6V1Hq@h_w&RiISYlOM&RbvL$w#%tQkv&i)DA55`(*~z15qV4`_Ms z!pj=YL80cnQs>I~6{P{b;`?4@Ra&hAVw3l0Nwp)M+8D+$tJ3yKQ)xXSmN4Q~n?OKF^@f z6vKUn`%E###5@i9OflT|Mc(r?#gzYN%+qk6DTe#r7kwt`Vv6BD!+oZhV)lIoeQ!3a z8y9?K?sE(hQ2PgTREbHQUDVHznMnO`XUSaI1 zNSf&H3<9(7dn@#bPyIgV1u0FMP0nwOXz!3DNr8Vwb6V5mR%2bffTl!JPtU%8^78I5 zE6;Zt?vZ!$#!%B>JUXdj5Dwv-vl;4=Fb+DJs&yF^i}M@JKsL{*tf-XfnAus`?Eeb-uA0$?`~C*^JybjS_2|0z z!7c9{SA8%3;8{O+={8eX(W)HtIPFF({@-q%zj{(Of%@#DS{ zKhsqo(I;-vm;MC$e%+y;^&3Y2!M+bd8}b@TfMS$NS9iQgPUlOVVD73ZwUL*)e4=AQ z?vK~RbV_uLuHM`W=}GrrfmhT^k?0Iy_9$DR5|$8^EMR- zvAvCu{%zJoy4NKepwf9}d&G?^Zmwd3@7#FLed$>XbwTc>4sOx+p{*bKVbgoJ2OfFz z7JazLzqUxJ$KTqiy|`vAM8)4e)a(Cj#zDhU3vvekuY*ZZG! zHYj;IkTuunyubkm-k>Uxp>{Xg)2@I$^h=<#+tNv}YfZw-bwuzQjy+)wKcB8be4tcl zuV2xp9kb1k>st-?L*riM*Qs77DX#g3$qn#kFU2$Tsf+k7P~HrRZm?_Wj&ro#np4+u zUn))1w$ggjJ;N0kq_0^cJ zGS0FftDvXpCd%5jN*I}bk&Zg*2rY!xk-|^fcGoO)TD{32k80|PYAN$mQI8!BymK{{ zI{P8rrd8p1}niAKPZ4kg*Hyt3qikfoK-vh$LNC-+1PraNk|0g z2r&+7(KZkkRc%`E&8IZ?kd=PI75O^ZXiMM}!+pPuJ~wG&Rw}XW31T(=Aq#6~j58d` zQYI|_Tn%A7Oml1x)tRNCmC9lo_$J`f{Hk5`g=#xQ7UeDA$Jv9fVT2*HCF6+~0^F$}MN}>TW z@gdhbcl|^3K}Q2l2Rp9dY^%%csdAFM8VPOgsu70aZigukjJ~$p zfY7m5@uz;d66U^LLCdxTIMVt zsjRKZBExAk{#NNY#0>5)!*dpCl*3*d64@K;Su{%%+-_ z!rh`T%*H8QxJhj}kCn4jV@Mu@ZABfkCG~z>Iw)H-R44 z8SH6+WhbYlN&Ex)R_>$W40@0JZ>+~j__nH;hN#3_WobMSuza6mo<0?gK31pZt9-X8 zvk-s+`od{<`bKW7vQ@+RyWAJlEHeRGw$@u*tmva=)4bAMMKCl+6NMSrc%#Auy?HH`Qb9(xn zMZ#zan$-goi-?qH;QPElq~!}@W!93#r6qvA7}CZ!;WD3No+gKTwqM#xa?3BHJ(0DWtPhZ|kpXE9HU5QW>W=!0B4M*3bHiSuwzSu7ok zI16aGL-g7rdR+L32;`WUfiK1I?JJZ<(uKXJHGEd%<}25}}_0O?z- z3|Kc_K+cyn#P@JUIQ@|Pgjsn$iMoIxlr}o;&>BYHq@QM4wDVd7Kb@Nj71j1}I&_M9 zUK&nL9aj<*9TC1$Vy+wsb5FDmwXxG(}H=in^Tlm*HFq-qgiue)b}TE3C!{pkSmrp#RjR zJ@81BMu-SJRRT3Yfa&5n`n=9wLo1BotlO-9XdsSIaV2JoA^HkHC&%j>CxrAT`@Zsa zpT&`wQpXf%O&34e_Z=~M3ybZy&LvncqP^|798T_4|LYEY1noLl?ZPh&qfbu(s4rd~ zMLqdl7uqd4&eG97Elg=owW5zkb=LLD6mMOj!UFEAMlq})h)!M6yS_5+NVJ|d+Wr8Z zzgu}KC+a>r(QboQ*N@R>4+%eX5r+{<#(WQlrvW#m73)dggP8G$OV3Xj^X#KaSkG*F{q=Gd?(w|*uQcXVPD1G0jYerM1F+E{u&ZqwbFavwcLLmhAm( zl!S(cG;a9moX{vs8mkkV$cV=M{jo^Oa3_yQ^hbPoeJH2li_n+oqfVSPku+Cx4SmDY zKwl=&rxW^U5sRs3#3Y+f&;I@PeNk0YiR<_FIHbkt===Ca_k_Oq0)6l!6!@BX(~1o| zfVAQB6OXokr*NAWG~)qBQoU&RhmU;^#bq_|KKiyi*CvJvee4xyX8>BLr3@3&p?-l@ zrdbZlYiK`+K8-1MycV8TxDV!sc>|86shfc~QL~O6KBBycKFi?mv2Q2!xed0jXGE@} z58US;8!lZ|I@bA&1H6BP%(Ey(1m|9v$+4mfKp%Bv(m^=*1Y;X-x*UM;yq1mozTmQn zE@`_DqwiIskH&N++aB8U-;Db{fBzW;RCdujTU`pDP?ZTW=e{fS!6n}(MMp#1&;kw2 z5I+)A5rRm05gL&bK@8|~PvTq>sd?T-A3EwO$^ZZ$07*naR4}xLJ|K+v4T@*V-i5b8 zpM8rydqiKeZ?ahfVD_-8FwI)5KJ5l?dH{XVW9S3-wWYDyY&d*nJJva%&u?daSys9Q z>m!X-CX%F+=+o^wOa+8<+p^vQecfFC=!W~y(s>g__~+aQOIk6jqK}`D`~LCs`{z~k zz5MgXzyC$$=g;>N(C)v;5oqmPhPJ0UhFKCF^7&%20lM|0RSj%`k8gn7gY zd|%}CP>8xs{SnR67&T9G;qoKU(Ebu8oh{oG@(a!LV&A8&qt7GFbG$|(Pnu^t zY)MC}AJvvcll)b!!OB7kUlkZhJGk;5&^&kg!`vsWF7_01I@3IxzB-E%d$iv8ezxJU zqQ*1&_yhG-WTeG$59a}Co{2Lb0Q&}g)b&{~y9J)4Kjgj`mbB_z$Kknbo?jK=2@q1PGqsP6#fI1_&NJxI?hu4vi(ayEhJvHPUDUd3@hKd*A)eJ@<}t z|J^sn`%$CjnzL5Plr`pBt7etIC~dmh{Jv(aN5|*y$4=vznpCL8eQd9%fB)E~>}nY- z(0j-37VKu$x*1{R%Ni{>v{xIIYNP!)#`8bW5Ca`O`|;bA6!_00+_1jHmNc5X*^KF= zRMdSF9|q6OE;P>+UXA9BOCr)3*Q&iG6cN$g3sj~c+22mlJXh zjlYL!fWRkyn6Bl6Kta1kY?PhdnJ!z(|Fi zhd0HJD>QlE+Kh=ch~!9L9K}$l%)? znSY<1t$0>@_Ac=vV#j7Gpn;gfpepmKsJu;_bb9Mdj8^MSPR1d+wrpxu6V_Xp&Hc!F z#jY})Sd;F!Zrqv@C)lDOtGbakT1oX4Mz`+s$LOMrTO=>N*ai(fCJRy=h3w(NbfNca z!tVTeW1L`J;k!h#aU5RHrOF8_ZRtFHiyPmTtX9IqVblx#=xmHn)Qi73u~!n0hVP*_mLqdzDG0Rq8)WVWiF)>i5KWM z7}^2$F895^h3wS^g}zj__YO1i{;WH0MKbbC`cTiNr z(#YP{?ORot10}dqMQgU&lBvKPN|j`3>jjNYPt~hS{RGP73DrxCZ08A@=ij7XucC0b zKq}74u522~=<}ji}7;_N3X_8Dihjnl3Q5N%uwts;XI7=&v#`PD-6% zx!9-m6$!-hCxB+8L#rsj1N(WpHgk?UdLIxzd*|Nzw&SnE22rNG<}b5u7ZJm41rn_J zJi#xDENoi8+#kDtRhQfiKqZ1m67onWq+#nbT98hK9wn*Mr>TNp9rZQEVr6+tmMaN{ zJ*@!$eE;~>q+t|etj8yB>?g)YZWxkZ%%WIeBmpf~t7k7EVd>Lyefzs<$pUK5qZ7 zT@vd>Bn0?Fh^^12!LdIzc7(dPreBWRU(ad z{mDb)^Lo&G|5yGJ0Z^X8uY18Jq;)w=OR0cWgUm+0eadc$WfMXe1gW5~Pyq5wy};sF zbuL(-1ali0wSE286&A3}om3k#`=`qa1>=}zlw=bTfy<)K^vctIs96p`LyK%rpIB63 zXRrS0FKg}UwJBU<)0KVqL^w6MT49L!MM%8-Mm$~ERS8%1_LE!1{d8Hg%WJ9*4xdZm zSJnl=XNi}=E7Egsx_8D=fVDDFav6)?e51d00R&ZOP$ump4rwleo&6%5(yWNiu`1q^ zS;M_B8kX*7#VaEdq)Y)n34kD3inRNz-hI|5UBnCC%Zv^APf>BsfBMDv7qD^F>0DvKP4}`by&_@{kzJ3qTiIE$gMn zISEwaVyYe7e$VrAB$xaXV{&+8p-FpxId?jHv~R-0K5o^>x$>0SR7ldz)!_bS5K$`T zlz8*yB|Rtl_60D@>et8ufHBL$H2> zaljqaLia}OGi2v%$69+@a?aUrve`>n|666`x4kLdKly`yQX`&SfuA83;M1E80<_69 zajz~_5B!Rn9hU%VIUVBD3b{@o^HwySY%vhOvCq zT5$=Ye^4aR&RxGFe7zG}ICf9yGuN=f9wVE5CvJ|~O=sS_?6gDhcz{)_^#!VX#+Gnq zR+6!qtfO5j!s&wd-v3-8YF~y_~lCN*jWf9Y;c{G+2jF#57+D~BtHi?1s1*2ixfe) zT^NlVK(9_gMT4#yemRCn$@?#IaBF{c8Qwn)GBvDy6Fz4q;Pxgs+VRlj9$YHhX%4n^ z(}HqgXmLvTQ@quj3-^yfYNf$o;T#4q@ z5i$Fd-u`-RQuF4ZK-S{)&UigL8q(%$ryYXO&2cgjXdOzvLn47WJo?7VS4?}zFUViW z_8u1m%gnM#bMRGu$q7DqgPJY^bSdx8CgQKf!0F_QzZQ-BmHqq=F3{J~zcPWb;7`&8 zXai^EYApl;*aa49S+Lc!OOGiUUKSp5cc<*6a~;(W1+46JBM3J>=Yc`KOqR@a57G@+ zM#nrYLp5xOE?tvVoq>b{3IKwEJGtZS_DV7H-N-W47onpG)gn+EpECuWGwSWAy=*Rg zRd33)Y|$!@8;)-<_|yHvZdj8SUb2(Xu`MAL62Vax46MpA^&@p{YUz+>t+CH~`^Lo8 zlLVYXaSPc1b_|`{S<{|&e59~4ws%VX{G-(eF@k-bC%)ah+8Z*r?2a(YeVoZj{zT?{ zWh=QO=e}H@B4>47a-j!0XXbrbDcddaUtH~l&2Co>1eg1EpF8iSQ?7{gNDbE)IAwH2 zmwc}BHK4pdg-l*3)$43KVq6`c&pbnamf7*S-MGCJxVd^cGI#Q61hy#<*3=((eEwtn z%Dv_k`SUyXif6-R-{lxV^RAcBu4E8TB(V~i^+LMOI#K!$D!T`LcnV$`l6X|a3A1s4 z^(8}GO7x%2^rA?2wfFJ2!b(joU=~g?T~hu}CJ5Kr?Rq#e1NkMJ#VnrIB8&>A$BW-H z{mzm#qoyV`?4u+554oG&mWjS+V3AT^QCoTe<0dZk(%03$Z77SU@pqh;YmOmCvD>BQ zu;~6!oaESIf?nR81aTV{vw9s$+7M)gtrf*!m!E;O&5CDN#l@~lfd z_Ivi*&9{Ix$g`uqwo)s>-HY#K6G(xbvh+a$jHQ0OaW>6uNOvV`!%2>ypKi3vmi&~k z_I=2NhvO+S@w@(w_3P1IgW0aEL2>!%6!qojmVm{wh+@z4G!5N+mTW2=`)c*ie($=* zXS%lC)~!#3HVnJ76Yp}rW8vV>HBk@|eyrz2ISyvMR=7}E+z|~ zfQ{p(JiGPen?IYl@)SSpIoLsIbaL#tfb3Tj22!$03g=)?2VXCI(ZL+ou=k@^7D z6ba3g63d>=<;N?3RF-+BG8CSDE;Rm_w-3}zI7~5-Pg+hd7^~%Vl1!rD{v9>bLhy~Y z#;abZU!GBv1(h%n=8VB(TPDU<8I$h-ed{Hz$i|n=zf16=^y>g)tk1?;j08j#pOR0# z+nZYUKumh`nM>^{hBCnur%Fn4aBG7EX3DLQ|? zQs!knQht+--K`>>GdrF*OVxaTgq<}Xf*BN$`)LDBAicEbjjY-plhwy|#;-!<;2?6o z8-LbfdW_{j$j3B>`+97`YN_uy$`W%4(k4|h0FHa z#fZjxFRO?IWP)RVM_9K+Qx)Q3hVUX%zLoK{ipG~UII&fDzR!!?5uV-~%973Y&4u$F zqn%H14loffS3Pr@gj;9PIt=?WIjo4944SDCGQm3K*?I+sh%h%(2W(^F6Wqdp%5Uk) z9v@b=jt{3()PV^CsXrHLw`l=UjgXGsA z{}~b8Qnz;(D_b85wR%{59sY5VYM?7?Cy@`r%w-AdrRjO~yCg9mtN^BuJxrj?x>uOaPsp>r+4miD9G@GAoK9>hp=GKtE4dz(6yNjBAk?=E{3)R_R#s9Oe))tKmm)Hv5`dU z2Z|_G{RHP11sz~4gyQP{fb>{vSQjfAQYXQ1gDpzUyXbBwVSUI#uXb<)l*T{Mwu!aj zC8Qftlegi3=7Ks7oD+I1CzRYwr6i(6IzDMFEu&7bf7S2}fnZS$l0Re4&%w(Luit75 zd?F~H9#*S%<8rGJQ2kW#U70-0FEDIYu(4OMC^8VJU+DaVs9bjK;!45P<2p``krSELT@Q+>RnP9N41zcc zftEkxkJGLXqlBp~3O7(r%J2UQtRLaO+RoSXFR~=K+y9RIAw%xhgOfsz_mGEy{2^4i zP2uslKN4s5b%y!_w}5?WjP;MP8mIKX^S=#pC9Wx(5uMtQvqoQba~nt8(G6|Qc;-jZ z`BwQO?c}lx$30p{&KT?UUXZ`&Hb=eC!PSx;N}J6y$#r^PFxrpDt(UW~a+Or2-Zx%E zOoop+Fw_`WXkYExwqNJxTTFRS*7KBsTQ`d!00_<^4EJW;&~E^Cp+yz1;ImPBG!IPI zG#!k1nN07yaW^FBN?~XIAV|{7aT;~hs(vq-=Hei~VTLf`A77w?7Ieal9nKj7zYQ0) zo&%$SokKq?Os&Kx(53eb#D1OnR@UuT`Y6v5@A;fnbWvPM$OD>q!YO^bb7I|1cR~!) z^26bwIj_wGhHcm;&Fo1Va&j{=mcAy(d1B-p19CtR1pvCujcF*>>0tfB>XL5{;3j1+ zomXx{*@UilL69MtTn^ev7oBFw4hd+_!{57vC=*3l6au&Fq7N>Fr|M?+ zrh=3BGNb?#m^E3~V(lVi^UoF=@AmUOjHWB!fAr~(xBrPU{hk$?@1%^_^8}8zaF(>L z%nv`?AGZ`piys_{{t6RAkd<+ZIc7Js%6c_A^e5Ty`si-l?M#{(UWC0ZEVw~d2VO~G=`gn{$ zhJnA=vvWY~h>6(>+a3PyKJ7iG4LXAUzJmEphKWIvqkYn*DWF~WRBuu zVb!jxaYoXP2{mun?^)WbiajyDtB-v39u~r1QWW+g`?y+}BDT;FANjn@@DFDi@gcu& z3Pl6`!+?Ikm*_#|4KecB?%Du$x1%4Nl+3nop#BSDjofn1+;}E47vs3Hti%{W8L|71 zn{((YHtM_bpJ|mo)7!|O&EL6|0{VMKfiG^W!2X;&&1bRN&&daN#1ND!00|w$2n82d z4NBC^(w!I9Ds%*21ezIC*B6Gf{9#8hf+cIg8OP_Xr9_O>M^vg#d@!xEY8s=9SW`{M zQIn@hj$CRUFqb`Bo3xB~ezSf`CZ@}^U{Y}LLZP`vl{qr8_!a|PQV>hqbQ5inQB$?D zm7(3I{!|kNUF|3uQ)JqQ$x3AM>iJab;U-~(9wAYEhd83x)U}uxs^ECK%Zj6XZ1eKS!e(#Immbc6kX$Av)&W%UG@L_# z6E50PqY&hWn=^so%XQAFKAVnyymlHYq~54qAmzeUK3Gy`v|JYsV^^eSjR*mW*xcU4I^Y=|9*U zVXnTkgrg_SZgOa66C2cX3Iq>c4wM5r{tPgT$f%m6h0Qcm@oq+Z)LoH_4=40s-@DCe zPUkQ<=YD?m7|gP}{P^eW;2?>5b<)d^J>(G{wQ-bnibVtDdoIF~(0=l))X0{43ahLP z{z_p6HQIzmHkg^RZi!)TQeQk!&40I|f?(*k2(yC7&^s|Yc|F{>LN5}6YVCdG&<^{9 zCslN=ImdT1_%50Bm}$piOuzY-4*|{^eLQX-JqI_bFe|sanW$DUZpAMnA2+e(m+JjB zDX2>cL5yEpzIkIuJw{DR&E0E#pJX~I0}qp%)>osls5uOoIK5}ja}f+S=S@4aO7a!(DFxx|+mpOOl{X@Iu`)e9 z?-xq<1xAOa7dgkRP73NV@-)FU;q3OHsg>;7$5BpWom9+#>^<+sqh^XVPgW3C!7pgc=HkSP5Au)aUZf7doB4ggR=N zW7?J16iuuvmzNZKvW`OP!5vMjE{EZ|68*3DR0$FHe@H=Qi&If7NzPf0!=3_@SL=M> zEd`oV&utgpa?+l;&3ed;jb-IGN!X<30<^6vi^5VA1`cf{|%FG#do(mb5(Y3#0J-)ke>HScBGTUOFo` zr9hwwEXWx+;XGvB)C)7EqH_~{62Se{ZfWb@hk{rm$fW`k@xn8KENkvU2;tn9OGDoB z%81&)(zc-6lxw(#{iJtRap1*Q<^AdsdPr|N{U6nz#%n8(fYmK}B|;7>oQ>cjo{ z=da<2bE2hr*}QQ?RXEwvQK-=9$VtB>8CkO{`HFv@3AL9-8AWo^wA}BMn&im-qh!Yt zz5VZ%O?kL>{9t1yh0^|nOU~*3LF$Bd+O&__NdpwF1^Ia&mCZN?Vcz{q_4)RmU8i}5 zB6Q9AN_Oao%+&N#O&9K`iH+`CStM@i3A!_j;OcL?!LX&3C52TRDvw)eFK>`#6sC9b z!?<9^%kamJ<*f?a$Gb6?R;*53I=D8K}an z7A2szLtGl868p{jp)Itgt*%-3T?Q~!9#RODo%kI!uuY-tVrltUvWUDx|dTfy4*jr?JO z=mjDfKam9x3RDK>!`sMX%~)G)e5mm@A>;$hU)Zu%m`4R_H*sYSYH^sqJZSGb3Nx;| zkC3_KEQ04Ej!tS}q}VR1U#+tXa#+Lv)9h~C_CNnx#!i*0CK;Z@XKo7t`8?z%x82} zvXjtT=$cLy`YWrOu$IBD!1ABI0HD3f7GDqsROTK?6-nu{MtF-1g_o@PSVNpXass;m zh?k-8>ITq*MCITG27DK#z09YO8^d>@t z$ge(~V3H*y$-jy^kzfOhv)$jlvm^?7C={+axk;3V55TBZ)_j3D($HDXmJ`CgV0tWs zG|?k^H1{7xG%ykRU&TNm)|0=AQULV-DE^n|U+p=BL4T8uV@m&B{F~=r#YfivGm--Q zv;BV|Uiu$e{0r^RL1)%*yj*I+%kNsaF{(}FI_@B6-{l)N~@ShDBqm+KU?XO$^f`8Zhe{ey4 zEdCP$Z~upS|J`n|LjT_x`8OBL#}54${9FJ2TW9`L$Ny5#4B~$p_+P2_Hy6O8dH;eR z|Hk<5QTp53|9>$4KRg)I`%B0YLVLjfG_?O*9slJD`RBa;3;)~PR+zhb$A8fUSQ1*o zd=QuZ&kOTk%jv&2+t3fvZ#yrgt04d9`u+X9`IorAS8wxe8x*sFFyg|i3>2jbuWBkr@0JdaV4r?H^ZWgPG7ls~lAJq>)Y@kfr=cywg&N=|6(lo)w}b@!I+F7h#aeT#$^! z+xG3pm~0XvVC$bew#kmTT46Pny>^W6SGWIYj*vIsJPlwUa5Du4{K?!_dk9 zzQsv>c01ZbuPkyUd7cT3Ts#vH&uA=uxrcYn=l|Y+2|z!KCrqqO6YCa5UcCKJl%zDv!8#y zI!`$sZ@eMg(_&juq5}9%wFb?Y#NBQE5$w&{H=jmmEGyk6o~Xv&Y`~2V^(K1e_wwHY zU|QXnJB_*%m*WfZ%tQUh82Hr8 zAOECi@l~)6w0M_qC^Tex2m3i|(&+67k7RUl>=WtJ9_JKO*SlE?rf-C2o^vnB`AnV@ zfG1-KFMw`dWhNl5!UG0AXIL#>o!{x^lz}8>`J#iVa2-T0Xo?jA4z8=y znS?BFpDehCLy#_oY>?&1-$wb!Bc6r~?Kfk0=P$Wob^(O2p8GUqI^(jZI%Jk zSaDz=i$l`~pjPV+ z_ep*_B?OSlZfO&ty%xJkB^}au39$f3Lx=0OeppfHy&whqyL7vlDA@@%LH+bqeHy~D zKtgS?@M=0)=;x-Zl60R}^k6G9_Pw%HtptN=A4GL%t;(MWNRd26-}7R)?aG`@02i&R zjqB#;5eXtNZ3X<(?g*Z0msNe2yaUoc{OPUVy@*ftS<&j%HDXW`i2>%5257x`jOVN~ zu;X=ngQE2!3~>JDclktLq6!U}ZXEZVN6fR0GsVFrLxIV)Qk-k&_iT!t40Fi|>Vq^` zD#GAeTc~L>3T9hxRDL)`aM)RYZ{jl=AJ4~c=xfo}7`Y*O;$t%%^0cd@31Ol5_AQIOGB>!lMRMf_b@p4 zz`^NOyzec3PnDSv=C5iJYQh)E-&fVB^wggBycQ!1V@ISqQr*M|nvrxw5MwZu$^LLO zr>=2a(ujA~J=aPXIvW=Eu0_M(p>1Za40JfC`KS;#h7QhiVmeFO5b<<&PAVIS&9C~M zKx{^sKka7d3v}NQ{e9p4c5K(jCQa-;`4XyAP*03=o8@!aq%xZ#3rs!o&H?V=ITRSv z3a+@5g&1+w6#iWdj}W;Z=|x0`JACOfO57h30|}W;2hN2J#74<-@5*E2(Z1}cIFRpT z$uy-7Oh1#UA!emObcqX?hTCwe;H{`l^|NwospvNGR+*dWO&~P=Y-GaZUl#KulL`f9 zaqscDqR(>gaUf%uC%S{GPf_KQU6M>xBdVA3RQ4!Cofg_a3!?_gr(Qo^o|K#yQMp8m z%lGE+J|$Qm_*jizxg&OS`YU4n`$u9hEliAG6j1*3bVRmThR<*2$Z|1no7OME2XTM6 z4VGlCh!Tfp0u8Sy**v9^y#g7E8BB^{@`sk1doN#^P!AiBzpLDil|dAyjKJ5w+#bF9ymjd=8u7eV=Uaz#_9FAa*#YQg z*4;rE9KCwAJNj}=&jg;Z4vArCBEhPu!Sd`z!&2V(bZair*pbd=e9 zJ@Rw(NXw_Z{x~Yjf!-`GC9AI_u&xQFG9WN%P8332+>XI7-^;k*uWqO0p=}gk=r@R7 z>N$-Rv_=T*&1oMN(m*F8y!YiJ1kzpi=H*_kL~>XNuV%_r*p#kp-tY`Q2b{ibK6QY_ z=HB3kS45YzsIMKvbFJ{QA z;ZfU2S6sL1`8}v*T^xw-o8LNU6B=jzTF_N`jieoPl{rYtbbCAL!Tx>|v7Wzt|5N#F zCIV_PAblidLg_W?J=K?7c>+;&x;@iu>V5W!q&7aXPpN;1SjuGMS(qz5eQ|8y`F1MN zjYv7Sam!!P21W#)kz=7K;)*4S}+@XHV8#yLIGZjbMcfB)pj2~&oKwl6y{}_zI@Wm7Bx~l#m z@$AnZRS!!x@I)oMXB?=pOH= z`MvCk(A-s+i#>H$xV3X+eMD#Hie9QzzffU>Hxzl7rJX?B!?HZ^n}U=ZBMjs%^So8^ zN9dK|rRsDeQQ2C{mqXloC&j5M(wlJ;PVuBmiP3gGr_}dl(VG*jPO$PQ#>287;7eC; zck->Xy$+f_Ivi)Ht2e^%Gc3}j0PG$Q=Eu}SPZ2H1JB;(5GM8iFlC;rQsQ^s^=@ zE9;uR9y0k;{NzJNzKv};3B$Ck1s%5(kc4GLfkAP*Hpw%Pu=X57yfuM}GmmTe9?rI2;y0a*%;Sa1vAE2GQT;(e%BghEbY;kAB zkru`JN(wuujL7A^_j|d+gQ2=g-K+A*AK(HpF_ZF~6fGOT4Y>e3cH)B`J;$XXg2C*v zxw=CMv2!ZUUs~nVXr7yaCzee5QhdyHn=-Bsc#FMZ=?6KC@q1G(?&dz^vNqbZQSTsk ziHh;fEhk~#%_t$kTE@8Y!tz^h2NBJ57B45!2v%zXDa5EdEsha+a zOEV_IxJeIIGr$mf1uI2y`JknV;u=5FI({x3%Uu7>Jl#t#{^g-b;Lw&S_D+xCsPdBK z6ld_LjSWvxqT8D+t7;bJIwuquhq|}U6vX~=8*nf=!*s;a2Z299TCPkgC`UES*+NC| zu6_u8{{W@$f}o}^>Q6|M@MHwi(aF7$0|RJ3V$%-h4%M{cUAm2G5X6~gcLm+jqjxkF zUr$qHgCG1SyU4wuR^^8YF5wv8RhOGw#>`~wwkViPc$>{7xm}Y&M^nEg?0_>4K359~ z&oQTf{Y$M)b`srqKYg=>Mp;2)Ne)RJP2UBAo3B6v2gsnu2_UkdP`C>_P~83H&5|Z1 z%t=E%S*b#av{n|ma4*o~6&qciqhLes?RHLHrkC;~zlz6k6jWLqi#v}e^dC=H8bM7( z3I{S|k$9r?o4cN0@*cF+wXOq~dt!I=U+{9Is7;?9=8J<1^6l1inU~}$ zzza+D7zD{bJkN*U^uZv;LVKy{S2uP7vM9@uv^7q2S74VoFj|7^r`=48qc#!czM?HJ zY<4*w#V>KkTpDFiv(Xr0?&mM4CCU3SsO8m$f&N=l%Qs%MxuH!TWpO@A<{NNx=kAJt zYGU6-Iesc};i-yJ#1_36q4ZDWQ|G@_{Nt@>#8u_=7!5VP0gs+T0{Yetnto@FEzvyx z^PuvA*1~8{v1{%@J38B@b=e@3$Y-%7t9Iq?y`7Tx+> z9^_)5kd}E2^F7NLd5d5izRq1Aivh@H*(*l~o%PV9*g$QGft?>JY5kTY;*<>w)DQwf z1UI3ze6X?_eCD%^9Kq-_kz|#u(Npc`2oEf8>BkeolwC}q)oy?a-*tz$S-o(xSO%xY z>r*Y;>`$eWins2#AORZNqFn*Ma0j~Mj_yh>mwNr`5vo6+>vvpt`qxZT5m^nq zT-&(%6ND*7(I>)u2lZ2uA+f}XbEA?G{=lnOuVwK3vY79U3UpDPof~!I=eKnyI3Xh{ zu2f5D4@jzbxAEfUm!C$*==S0p4*9XB zz~?8;zd+t;7f`1^ZDdW6gPhFZ`!`5o>LY9;NE_IgtKIe*G z$8wMc_T`N-L7MHb=oNuqbD$W?vfR;)SmUvZ+)=o}R|(Lx%xs|!O$46zP7UD(<}!5z zROGhNbJw~aF(bBfvyGey&LWartF7~!+ z)QE=h5}#jtO=!T%#J}O`eE>2jH@TxxQt6ELte=IDCa(!p`?eMowd7NiV3c)>v4;sI zZBn=yT7xc0!Uw|Ll%{m|-ldeXq!oe$rdqXCK(n`jew`9$pgeykl`E3NrC3B%qq~WX z*Jo#wX3~-8NWYUnllp#C1ln=q9X~W21>#(KwVMgciUR>9a{WaDWfqz$``vv|r$`@3 z^iV3UuC643tI(0e!;-|YIf!2aOw+4YV$l(5Qg4QSi+Tl;8gT9p>F>ih7D;AVso)v{ zdY@Zggqj=|Sjl#vWq{U5lZ)BU%sk#@ckXt(i)(3TX2A7Yw^Ns2$ERiS+;1SLX5a_~%K^6p-%4cOX?H+#9h=Cdi%JErL;Te|j zTA~1yyn9U6A_%)#fkA!L7_HGrHOv`=wVy3}|W zkzWjaMf42)IL7mf7p4RM)KGgN(srt_JJIU(QsKMJzTy{r4sFJO%fyhUU$O35GxE!q z0J8_LON53>=z3~fj>^ni(63%c*i$%YK0Iv@5!sIV@GQt^@B23r6i2)>pji+}5QO-C zt&OB$xM|c?X_5QPCS}e~bsTjqU*jS zUF6}rF574T3P0v#L#&u;)nI{g(*{L0JFDGYONfF5YEG)BW+Qm9Dgs6#=odz4dxx^7 z#aMhKhR0D4?uyq~zP`}#ej@cm!e;%3W;T<`2I;3`gS?}rOx^!QSjaN&__(REF{v+? z7+z}L-1>_&uKPShQuaYt?(%oBa#XFn#ABsH=<=y=yW_7k(>QBJP~K1 z&NsoXq~Ru`KUki4Ql@+P(sWV2M=S<-S6A8RVJu!R{vr87tJvr$j zD7}Y*!VXKH(e|vF)^ zoI~pum(pxm|nD58SrS;YBrLr$+RCC&T-kq zF|Fp|fTzX*f=bXA3b*s#Ju@N2fSXfDB*MNHJBlJl?i`*?S07%&u1f~t=dPa zgB))aIEj_Z-9mh0?W(P09#PbZ#Nbv&&h&& z1=Y!vx66FL2q7%vzTy_&ViO>4nUj44m(PBI#;nC&e|pNF>8m%G4}E(Z;qGUBAJ8iV zzM0guo1+K^Sow^;w7y5-2iI&rwe_532eX|fz;6Qmq{IgLjxJ`n!MR5R;n~R(H*O|t zZ73CXw@o>jG0k^(`eg`=4GNHtB_+@M3pA?8s6t@Z=Ujt&x9H}RsVvDqLzSZDb6KB^ z1KdTpeOE+`C8l}6u8Ug2CTvrlsP_TMaj|7$_w5iTw*;Q~^GL=k=h zsADolK48t$O~xw?9o%v?RumNMd?ne(%t+Xqq}Ewy7V)vIHpKXgPK@BgPtp^fl&U#? zQU^(~m0~5^pGjf3nqf_s@2<1dC3Bd!BJb5S$$skAV;(Kk7bhF}1o=sE^j}H4Sy{K8 zkn-rA|AWfxJahBM@f|dJf7E(8p;AJDG~|}S6NSpLN#*)x^pxvB&E_a|<(A)?{V3*Po|h4Lng@XgW9qV^9HEm-lv zE#6wr0sg(@eE}n2w`qA6{>&ESw;;XV_ARR}bu|*G55F>??|yidB@pjl$$sWcUGG}I z-s@(i?(^XNoIvAU;3}{3>M6Zx>s*?GWC--lK%WTr;+nfiYs*DC8+Ud1NcK+$ z7}6oYKhK|)AYZ56w_6mczz^0qV(TSf-%JqnS6yn%qeUlF!<@bRaJTvH8ka`Ife;pR#jo5J-f1=W zBJ-thspW2Foe3jHfpi=n0j1)Jqc3{F^$)j)&wvxx zb>zEG{G?Y1N2kWH>rIMU>QBKl0TQH;^X^5?)=$!9hg}g-=}g znFkc)E@pK&Jf7*00CZx`3HVlc=fTY`Fw%|j?(92={eYD8Hbe~+a(;Y$Rmvy#oMN;H z?N*cA^M#xXFFvU!-=>{OX0qxr=q(cz+>Wsf;qI-Qe+%O2>L}A(gfAM513YhdKW}~os01#@C$tj z+R0)(=BeJWXy&tZlmkY6f(0VbkH z=h>n^MwNXQ@(hORz)BxuKr0nC&EWB%6=$vEiA4U2brJ~BGE zQJDc2UFA7dprZAWFFsFp^CO6D7e{8aR@?Z;c;uAF@t00ttR+S9xKjiVi$*T&Zp5cv z>iX=Eg!AW=PH-ZFR}JR*8=NP5J>b-s&1 z{5UbzAQTv6hlPXJPw}%I{goCT+9-zqC>H$bTRnZ(MOS&f(|!Gv5X#=zQN?)gDxQw_ zjbD9jHpZvTPE>D>bR^Fjiv9)7}{X#_QGn@j!nsZl!%Eq9%nBA3D7y z{?wS+XMr+dbmF;*qyKlmmQ&h?wzWOdzyj$eV*&4s_IWa;UC$_ZSm$p(TOPv z>n_pJ)R}Ocv_VMXvJTx9jgl4fTXD`dH>(}8l#HM%fNA^04~u3J_g8QIXqG4c@e@vL zW^b*!cGD*jl&qp_%ud}^x?dt#)_Tw+!y#5dUW1^F6daNPv_1=-jOyU-Hp7;>&^R!sQ^!Pk)HZlZ0Jje%>*( zG?Q0Vpw)@A*?#QSr4@6f!2!~ut6KTF^orF034Ez4DWx?zhW;#UydobH3~+u_+`6x2 z)$5=CPXO5gCjQ@fdl-Nho-e}lzJ=+%6MFd+9=f160s+A|L4c+6%c|IHjZtTc~Z}lq&XcE*j?kZ;!c1k z$a_1}D_Nk(LIr|~L7}YH-8;R;m6cXSCXaIFy>~5 z)Jg8p@ucTLljV)kGZ0h^N(d!}3)kf&a!2Ga#=9`QUax7IW}qZXgz(iqX(|$H@LST* z*GUzxnG^;>#v_8qMY!AX7~zq^AA8VU$X204W5jlj?nAaWGp zrppy*BA%vTRo%q;qWY$-i?0E$FS=Zpe_63EZhu`b|Nm~j?$)hq&%hP;g}W$fE_nmw zECC&-4!GmkL8^)15qZ@v$Qk4iDhdUNoJ5WyzzDLG<_b*G`^uWDa1hb)4S}*j;$#2` z>Ns}9U1JC(g@Qx)!q;)R6tC$Tp@a;6t-dF{m6mJmy@x+6*CMf8itG}Y1L&055qD2= zh$PMwjgm;XlSm>G^2qp + +Provides local Language Model execution capabilities on-device. + +## Overview + +The ``SpeziLLMLocal`` target enables the usage of locally executed Language Models (LLMs) directly on-device, without the need for any kind of internet connection and no data every leaving the local device. The underlying technology used for the LLM inference is [llama.cpp](https://github.com/ggerganov/llama.cpp), a C/C++ library for executing [LLaMa models](https://ai.meta.com/llama/). ``SpeziLLMLocal`` provides a pure Swift-based API for interacting with the locally executed model, building on top of the infrastructure of the [SpeziLLM target](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm). + +## Setup + +### Add Spezi LLM as a Dependency + +You need to add the SpeziLLM Swift package to +[your app in Xcode](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app#) or +[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package). + +> Important: If your application is not yet configured to use Spezi, follow the [Spezi setup article](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/initial-setup) to set up the core Spezi infrastructure. + +## Spezi LLM Local Components + +The core component of the ``SpeziLLMLocal`` target is the ``LLMLlama`` [Actor](https://developer.apple.com/documentation/swift/actor) which conforms to the [`LLM` protocol of SpeziLLM](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm/llm). ``LLMLlama`` heavily utilizes the [llama.cpp library](https://github.com/ggerganov/llama.cpp) to perform the inference of the Language Model. + +> Important: To execute a LLM locally, ``LLMLlama`` requires the model file being present on the local device. +> The model must be in the popular `.gguf` format introduced by the [llama.cpp library](https://github.com/ggerganov/llama.cpp) + +> Tip: In order to download the model file of the Language model to the local device, SpeziLLM provides the [SpeziLLMLocalDownload](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillmlocaldownload) target which provides model download and storage functionalities. + +``LLMLlama`` offers a variety of configuration possibilities, such as the used model file, the context window, the maximum output size or the batch size. These options can be set via the ``LLMLlama/init(modelPath:parameters:contextParameters:samplingParameters:)`` initializer and the ``LLMParameters``, ``LLMContextParameters``, and ``LLMSamplingParameters`` types. Keep in mind that the model file must be in the popular `.gguf` format! + +- Important: ``LLMLlama`` shouldn't be used on it's own but always wrapped by the Spezi `LLMRunner` as the runner handles all management overhead tasks. + +### Setup + +In order to use the ``LLMLlama``, the [SpeziLLM](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm) [`LLMRunner`](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm/llmrunner) needs to be initialized in the Spezi `Configuration`. Only after, the `LLMRunner` can be used to execute the ``LLMLlama`` locally. +See the [SpeziLLM documentation](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm) for more details. + +```swift +class LocalLLMAppDelegate: SpeziAppDelegate { + override var configuration: Configuration { + Configuration { + LLMRunner( + runnerConfig: .init( + taskPriority: .medium + ) + ) { + LLMLocalRunnerSetupTask() + } + } + } +} +``` + +### Usage + +The code example below showcases the interaction with the ``LLMLlama`` through the the [SpeziLLM](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm) [`LLMRunner`](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm/llmrunner). +Based on a `String` prompt, the `LLMGenerationTask/generate(prompt:)` method returns an `AsyncThrowingStream` which yields the inferred characters until the generation has completed. + +> Important: The ``LLMLlama`` should only be used together with the [SpeziLLM](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm) [`LLMRunner`](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm/llmrunner)! + +```swift +struct LocalLLMChatView: View { + @Environment(LLMRunner.self) private var runner: LLMRunner + + // The locally executed LLM + private let model: LLMLlama = .init( + modelPath: ... + ) + + @State var responseText: String + + func executePrompt(prompt: String) { + // Execute the query on the runner, returning a stream of outputs + let stream = try await runner(with: model).generate(prompt: "Hello LLM!") + + for try await token in stream { + responseText.append(token) + } + } +} +``` + +## Topics + +### Model + +- ``LLMLlama`` + +### Configuration + +- ``LLMParameters`` +- ``LLMContextParameters`` +- ``LLMSamplingParameters`` + +### Setup + +- ``LLMLocalRunnerSetupTask`` diff --git a/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManager+OperationState.swift b/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManager+OperationState.swift new file mode 100644 index 0000000..d08c2ca --- /dev/null +++ b/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManager+OperationState.swift @@ -0,0 +1,26 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SpeziViews + +// Needs to be in a separate file as an extension in the file of the ``LLMLocalDownloadManager`` will lead to +// the "Circular reference resolving attached macro 'Observable'" error during compiling (see https://github.com/apple/swift/issues/66450) +/// Maps the ``LLMLocalDownloadManager/DownloadState`` to the SpeziViews `ViewState` via the conformance to the SpeziViews `OperationState` protocol. +extension LLMLocalDownloadManager.DownloadState: OperationState { + public var representation: ViewState { + switch self { + case .idle, .downloaded: + .idle + case .downloading: + .processing + case .error(let error): + .error(error) + } + } +} diff --git a/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManager.swift b/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManager.swift new file mode 100644 index 0000000..a70a551 --- /dev/null +++ b/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManager.swift @@ -0,0 +1,121 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import Observation +import SpeziViews + + +/// The ``LLMLocalDownloadManager`` manages the download and storage of Large Language Models (LLM) to the local device. +/// +/// One configures the ``LLMLocalDownloadManager`` via the ``LLMLocalDownloadManager/init(llmDownloadUrl:llmStorageUrl:)`` initializer, +/// passing a download `URL` as well as a storage `URL` to the ``LLMLocalDownloadManager``. +/// The download of a model is started via ``LLMLocalDownloadManager/startDownload()`` and can be cancelled (early) via ``LLMLocalDownloadManager/cancelDownload()``. +/// +/// The current state of the ``LLMLocalDownloadManager`` is exposed via the ``LLMLocalDownloadManager/state`` property which +/// is of type ``LLMLocalDownloadManager/DownloadState``, containing states such as ``LLMLocalDownloadManager/DownloadState/downloading(progress:)`` +/// which includes the progress of the download or ``LLMLocalDownloadManager/DownloadState/downloaded(storageUrl:)`` which indicates that the download has finished. +@Observable +public final class LLMLocalDownloadManager: NSObject { + /// Defaults of possible LLMs to download via the ``LLMLocalDownloadManager``. + public enum LLMUrlDefaults { + /// LLama 2 7B model in its chat variation (~3.5GB) + public static var llama2ChatModelUrl: URL { + guard let url = URL(string: "https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_0.gguf") else { + preconditionFailure(""" + SpeziLLM: Invalid LLMUrlDefaults LLM download URL. + """) + } + + return url + } + + /// LLama 2 13B model in its chat variation (~7GB) + public static var llama2Chat13BModelUrl: URL { + guard let url = URL(string: "https://huggingface.co/TheBloke/Llama-2-13B-chat-GGML/resolve/main/llama-2-13b-chat.ggmlv3.q4_0.bin") else { + preconditionFailure(""" + SpeziLLM: Invalid LLMUrlDefaults LLM download URL. + """) + } + + return url + } + + /// Tiny LLama2 1B model (~700MB) + public static var tinyLLama2ModelUrl: URL { + guard let url = URL(string: "https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v0.3-GGUF/resolve/main/tinyllama-1.1b-chat-v0.3.Q4_0.gguf") else { + preconditionFailure(""" + SpeziLLM: Invalid LLMUrlDefaults LLM download URL. + """) + } + + return url + } + } + + /// An enum containing all possible states of the ``LLMLocalDownloadManager``. + public enum DownloadState: Equatable { + case idle + case downloading(progress: Double) + case downloaded(storageUrl: URL) + case error(LocalizedError) + + + public static func == (lhs: LLMLocalDownloadManager.DownloadState, rhs: LLMLocalDownloadManager.DownloadState) -> Bool { + switch (lhs, rhs) { + case (.idle, .idle): true + case (.downloading, .downloading): true + case (.downloaded, .downloaded): true + case (.error, .error): true + default: false + } + } + } + + /// The delegate handling the download manager tasks. + @ObservationIgnored private var downloadDelegate: LLMLocalDownloadManagerDelegate? // swiftlint:disable:this weak_delegate + /// The `URLSessionDownloadTask` that handles the download of the model. + @ObservationIgnored private var downloadTask: URLSessionDownloadTask? + /// Remote `URL` from where the LLM file should be downloaded. + private let llmDownloadUrl: URL + /// Local `URL` where the downloaded model is stored. + let llmStorageUrl: URL + /// Indicates the current state of the ``LLMLocalDownloadManager``. + @MainActor public var state: DownloadState = .idle + + + /// Creates a ``LLMLocalDownloadManager`` that helps with downloading LLM files from remote servers. + /// + /// - Parameters: + /// - llmDownloadUrl: The remote `URL` from where the LLM file should be downloaded. + /// - llmStorageUrl: The local `URL` where the LLM file should be stored. + public init( + llmDownloadUrl: URL = LLMUrlDefaults.llama2ChatModelUrl, + llmStorageUrl: URL = .cachesDirectory.appending(path: "llm.gguf") + ) { + self.llmDownloadUrl = llmDownloadUrl + self.llmStorageUrl = llmStorageUrl + } + + + /// Starts a `URLSessionDownloadTask` to download the specified model. + public func startDownload() { + downloadTask?.cancel() + + downloadDelegate = LLMLocalDownloadManagerDelegate(manager: self, storageUrl: llmStorageUrl) + let session = URLSession(configuration: .default, delegate: downloadDelegate, delegateQueue: nil) + downloadTask = session.downloadTask(with: llmDownloadUrl) + + downloadTask?.resume() + } + + /// Cancels the download of a specified model via a `URLSessionDownloadTask`. + public func cancelDownload() { + downloadTask?.cancel() + } +} diff --git a/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManagerDelegate.swift b/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManagerDelegate.swift new file mode 100644 index 0000000..780dc05 --- /dev/null +++ b/Sources/SpeziLLMLocalDownload/LLMLocalDownloadManagerDelegate.swift @@ -0,0 +1,86 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import os +import SpeziViews + + +/// Delegate of the ``LLMLocalDownloadManager`` implementing the methods of the`URLSessionDownloadDelegate` conformance. +class LLMLocalDownloadManagerDelegate: NSObject, URLSessionDownloadDelegate { + /// A Swift `Logger` that logs important information from the `LocalLLMDownloadManager`. + private static let logger = Logger(subsystem: "edu.stanford.spezi", category: "SpeziLLM") + /// A `weak` reference to the ``LLMLocalDownloadManager``. + private weak var manager: LLMLocalDownloadManager? + /// The storage location `URL` of the downloaded LLM. + private let storageUrl: URL + + + /// Creates a new `LLMLocalDownloadManagerDelegate` + /// - Parameters: + /// - manager: The ``LLMLocalDownloadManager`` from which the `LLMLocalDownloadManagerDelegate` is initialized. + /// - storageUrl: The `URL` where the downloaded LLM should be stored. + init(manager: LLMLocalDownloadManager, storageUrl: URL) { + self.manager = manager + self.storageUrl = storageUrl + } + + + /// Indicates the progress of the current model download. + func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didWriteData bytesWritten: Int64, + totalBytesWritten: Int64, + totalBytesExpectedToWrite: Int64 + ) { + let progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite) * 100 + Task { @MainActor in + self.manager?.state = .downloading(progress: progress) + } + } + + /// Indicates the completion of the model download including the downloaded file `URL`. + func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { + do { + _ = try FileManager.default.replaceItemAt(self.storageUrl, withItemAt: location) + Task { @MainActor in + self.manager?.state = .downloaded(storageUrl: self.storageUrl) + } + } catch { + Task { @MainActor in + self.manager?.state = .error( + AnyLocalizedError( + error: error, + defaultErrorDescription: + LocalizedStringResource("LLM_DOWNLOAD_FAILED_ERROR", bundle: .atURL(from: .module)) + ) + ) + } + Self.logger.error("\(String(describing: error))") + } + } + + /// Indicates an error during the model download + func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + // The `error` property is set for client-side errors (e.g. couldn't resolve host name), + // the `task.error` property is set in the case of server-side errors. + // If none of these properties are set, no error has occurred. + if let error = error ?? task.error { + Task { @MainActor in + self.manager?.state = .error( + AnyLocalizedError( + error: error, + defaultErrorDescription: LocalizedStringResource("LLM_DOWNLOAD_FAILED_ERROR", bundle: .atURL(from: .module)) + ) + ) + } + Self.logger.error("\(String(describing: error))") + } + } +} diff --git a/Sources/SpeziLLMLocalDownload/LLMLocalDownloadView.swift b/Sources/SpeziLLMLocalDownload/LLMLocalDownloadView.swift new file mode 100644 index 0000000..3ce2704 --- /dev/null +++ b/Sources/SpeziLLMLocalDownload/LLMLocalDownloadView.swift @@ -0,0 +1,194 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SpeziOnboarding +import SpeziViews +import SwiftUI + + +/// The ``LLMLocalDownloadView`` provides an out-of-the-box onboarding view for downloading locally executed Spezi `LLM`s to the device. +/// It can be combined with the SpeziOnboarding `OnboardingStack` to create an easy onboarding flow within the application. +/// +/// The ``LLMLocalDownloadView/init(llmDownloadUrl:llmStorageUrl:action:)`` initializer accepts the remote download `URL` of the LLM, the local storage `URL` of the downloaded model, as well as an action closure to move onto the next (onboarding) step. +/// +/// The heavy lifting of downloading and storing the model is done by the ``LLMLocalDownloadManager`` which exposes the current downloading state view the ``LLMLocalDownloadManager/state`` property of type ``LLMLocalDownloadManager/DownloadState``. +/// +/// ### Usage +/// +/// ```swift +/// struct LLMLocalDownloadApp: View { +/// @State private var path = NavigationPath() +/// +/// var body: some View { +/// NavigationStack(path: $path) { +/// LLMLocalOnboardingDownloadView() +/// } +/// } +/// } +/// +/// struct LLMLocalOnboardingDownloadView: View { +/// @Environment(OnboardingNavigationPath.self) private var onboardingNavigationPath +/// +/// var body: some View { +/// LLMLocalDownloadView( +/// llmDownloadUrl: LLMLocalDownloadManager.LLMUrlDefaults.llama2ChatModelUrl, // Download the Llama2 7B model +/// llmStorageUrl: .cachesDirectory.appending(path: "llm.gguf") // Store the downloaded LLM in the caches directory +/// ) { +/// onboardingNavigationPath.nextStep() +/// } +/// } +/// } +/// ``` +public struct LLMLocalDownloadView: View { + /// The ``LLMLocalDownloadManager`` manages the download and storage of the models. + @State private var downloadManager: LLMLocalDownloadManager + /// The action that should be performed when pressing the primary button of the view. + private let action: () async throws -> Void + + /// Indicates the state of the view, get's derived from the ``LLMLocalDownloadManager/state``. + @State private var viewState: ViewState = .idle + + + public var body: some View { + OnboardingView( + contentView: { + VStack { + informationView + + if !modelExists { + downloadButton + + if isDownloading { + downloadProgressView + } + } else { + Group { + switch downloadManager.state { + case .downloaded: + Text("LLM_DOWNLOADED_DESCRIPTION", bundle: .module) + default: + Text("LLM_ALREADY_DOWNLOADED_DESCRIPTION", bundle: .module) + } + } + .multilineTextAlignment(.center) + .padding(.vertical, 16) + .bold() + .italic() + } + + Spacer() + } + .transition(.opacity) + .animation(.easeInOut, value: isDownloading || modelExists) + }, actionView: { + OnboardingActionsView(.init("LLM_DOWNLOAD_NEXT_BUTTON", bundle: .atURL(from: .module))) { + try await self.action() + } + .disabled(!modelExists) + } + ) + .map(state: downloadManager.state, to: $viewState) + .viewStateAlert(state: $viewState) + .navigationBarBackButtonHidden(isDownloading) + } + + /// Presents information about the model download. + @MainActor @ViewBuilder private var informationView: some View { + OnboardingTitleView( + title: .init("LLM_DOWNLOAD_TITLE", bundle: .atURL(from: .module)), + subtitle: .init("LLM_DOWNLOAD_SUBTITLE", bundle: .atURL(from: .module)) + ) + Spacer() + Image(systemName: "shippingbox") + .font(.system(size: 100)) + .foregroundColor(.accentColor) + .accessibilityHidden(true) + Text("LLM_DOWNLOAD_DESCRIPTION", bundle: .module) + .multilineTextAlignment(.center) + .padding(.vertical, 16) + } + + /// Button which starts the download of the model. + @MainActor private var downloadButton: some View { + Button(action: downloadManager.startDownload) { + Text("LLM_DOWNLOAD_BUTTON", bundle: .module) + .padding(.horizontal) + .padding(.vertical, 6) + } + .buttonStyle(.borderedProminent) + .disabled(isDownloading) + .padding() + } + + /// A progress view indicating the state of the download + @MainActor private var downloadProgressView: some View { + VStack { + ProgressView(value: downloadProgress, total: 100.0) { + Text("LLM_DOWNLOADING_PROGRESS_TEXT", bundle: .module) + } + .progressViewStyle(LinearProgressViewStyle()) + .padding() + + Text("Downloaded \(String(format: "%.2f", downloadProgress))% of 100%.", bundle: .module) + .padding(.top, 5) + } + } + + /// A `Bool` flag indicating if the model is currently being downloaded + @MainActor private var isDownloading: Bool { + if case .downloading = self.downloadManager.state { + return true + } + + return false + } + + /// Represents the download progress of the model in percent (from 0 to 100) + @MainActor private var downloadProgress: Double { + if case .downloading(let progress) = self.downloadManager.state { + return progress + } else if case .downloaded = self.downloadManager.state { + return 100.0 + } + + return 0.0 + } + + /// A `Bool` flag indicating if the model already exists on the device + private var modelExists: Bool { + FileManager.default.fileExists( + atPath: self.downloadManager.llmStorageUrl.path() + ) + } + + + /// Creates a ``LLMLocalDownloadView`` that presents an onboarding view that helps with downloading the necessary LLM files from remote servers. + /// + /// - Parameters: + /// - llmDownloadUrl: The remote `URL` from where the LLM file should be downloaded. + /// - llmDownloadLocation: The local `URL` where the LLM file should be stored. + /// - action: The action that should be performed when pressing the primary button of the view. + public init( + llmDownloadUrl: URL = LLMLocalDownloadManager.LLMUrlDefaults.llama2ChatModelUrl, + llmStorageUrl: URL = .cachesDirectory.appending(path: "llm.gguf"), + action: @escaping () async throws -> Void + ) { + self._downloadManager = State( + wrappedValue: LLMLocalDownloadManager( + llmDownloadUrl: llmDownloadUrl, + llmStorageUrl: llmStorageUrl + ) + ) + self.action = action + } +} + + +#Preview { + LLMLocalDownloadView(action: {}) +} diff --git a/Sources/SpeziLLMLocalDownload/Resources/Localizable.xcstrings b/Sources/SpeziLLMLocalDownload/Resources/Localizable.xcstrings new file mode 100644 index 0000000..ed6989a --- /dev/null +++ b/Sources/SpeziLLMLocalDownload/Resources/Localizable.xcstrings @@ -0,0 +1,106 @@ +{ + "sourceLanguage" : "en", + "strings" : { + "Downloaded %@%% of 100%%." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Downloaded %@%% of 100%%." + } + } + } + }, + "LLM_ALREADY_DOWNLOADED_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The Large Language Model is already present on the device." + } + } + } + }, + "LLM_DOWNLOAD_BUTTON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download LLM" + } + } + } + }, + "LLM_DOWNLOAD_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "By default, the application downloads the Llama 2 7B model in its chat variation. The size of the model is around 3.5GB." + } + } + } + }, + "LLM_DOWNLOAD_FAILED_ERROR" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An error occurred during the download of the LLM." + } + } + } + }, + "LLM_DOWNLOAD_NEXT_BUTTON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Finish setup" + } + } + } + }, + "LLM_DOWNLOAD_SUBTITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "In order to locally execute a LLM, first download a model." + } + } + } + }, + "LLM_DOWNLOAD_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM Download" + } + } + } + }, + "LLM_DOWNLOADED_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The Large Language Model is downloaded to the device." + } + } + } + }, + "LLM_DOWNLOADING_PROGRESS_TEXT" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Downloading..." + } + } + } + } + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/Sources/SpeziLLMLocalDownload/Resources/Localizable.xcstrings.license b/Sources/SpeziLLMLocalDownload/Resources/Localizable.xcstrings.license new file mode 100644 index 0000000..6917c4b --- /dev/null +++ b/Sources/SpeziLLMLocalDownload/Resources/Localizable.xcstrings.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziLLMLocalDownload/SpeziLLMLocalDownload.docc/Resources/LLMLocalDownload.png b/Sources/SpeziLLMLocalDownload/SpeziLLMLocalDownload.docc/Resources/LLMLocalDownload.png new file mode 100644 index 0000000000000000000000000000000000000000..2c0b9150a5255c5d88d43f6eeb8c2226f8445dc5 GIT binary patch literal 56242 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%0AwkB4#NTdI_EC^L_r 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 z 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 + +Provides download and storage functionality for Large Language Models (LLMs). + +## Overview + +The ``SpeziLLMLocalDownload`` target provides download and storage functionality for Large Language Models (LLMs) to the local device in the Spezi ecosystem. As Language Models typically have big file sizes and therefore long transmission times, the download process has to be properly managed with care. ``SpeziLLMLocalDownload`` offers reusable view- and manager components for developers to easily achieve their desired local LLM setup process in an application. + +## Setup + +### Add Spezi LLM as a Dependency + +You need to add the SpeziLLM Swift package to +[your app in Xcode](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app#) or +[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package). + +> Important: If your application is not yet configured to use Spezi, follow the [Spezi setup article](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/initial-setup) to set up the core Spezi infrastructure. + +## Spezi LLM Local Download Components + +The two main components of ``SpeziLLMLocalDownload`` are the ``LLMLocalDownloadView`` providing an out-of-the-box onboarding view to download large models and the ``LLMLocalDownloadManager`` that contains all the logic for the model download and local storage. + +### Download View + +The ``LLMLocalDownloadView`` provides an out-of-the-box onboarding view for downloading locally executed [SpeziLLM](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm) [`LLM`s](https://swiftpackageindex.com/stanfordspezi/spezillm/documentation/spezillm/llmrunner) to the device. +It can be combined with the [SpeziOnboarding](https://swiftpackageindex.com/stanfordspezi/spezionboarding/documentation) [`OnboardingStack`](https://swiftpackageindex.com/stanfordspezi/spezionboarding/documentation/spezionboarding/onboardingstack) to create an easy onboarding flow within the application. +The ``LLMLocalDownloadView`` automatically checks if the model already exists on disk, and if not, offers the start of the download via a button click. The download process itself includes the presentation of a percentage progress view in order to give the user a better feeling for the download progress. + +The ``LLMLocalDownloadView/init(llmDownloadUrl:llmStorageUrl:action:)`` initializer accepts the remote download `URL` of the LLM, the local storage `URL` of the downloaded model, as well as an action closure to move onto the next (onboarding) step. + +The heavy lifting of downloading and storing the model is done by the ``LLMLocalDownloadManager`` which exposes the current downloading state view the ``LLMLocalDownloadManager/state`` property of type ``LLMLocalDownloadManager/DownloadState``. + +#### Usage + +The code example below creates an onboarding flow via the [SpeziOnboarding](https://swiftpackageindex.com/stanfordspezi/spezionboarding/documentation) [`OnboardingStack`](https://swiftpackageindex.com/stanfordspezi/spezionboarding/documentation/spezionboarding/onboardingstack) that downloads and stores an Language Model on the local device via the use of the ``LLMLocalDownloadView``. +Is downloads the LLama2 7B model via the ``LLMLocalDownloadManager/LLMUrlDefaults/llama2ChatModelUrl`` property and stores it within the cache application directory. + +```swift +struct LLMLocalDownloadApp: View { + @State private var path = NavigationPath() + + var body: some View { + NavigationStack(path: $path) { + LLMLocalOnboardingDownloadView() + } + } +} + +struct LLMLocalOnboardingDownloadView: View { + @Environment(OnboardingNavigationPath.self) private var onboardingNavigationPath + + var body: some View { + LLMLocalDownloadView( + llmDownloadUrl: LLMLocalDownloadManager.LLMUrlDefaults.llama2ChatModelUrl, // Download the Llama2 7B model + llmStorageUrl: .cachesDirectory.appending(path: "llm.gguf") // Store the downloaded LLM in the caches directory + ) { + onboardingNavigationPath.nextStep() + } + } +} +``` + +### Download Manager + +The ``LLMLocalDownloadManager`` manages the download and storage of Large Language Models to the local device. + +One configures the ``LLMLocalDownloadManager`` via the ``LLMLocalDownloadManager/init(llmDownloadUrl:llmStorageUrl:)`` initializer, +passing a download `URL` as well as a local storage `URL` to the ``LLMLocalDownloadManager``. +The download of a model is started via ``LLMLocalDownloadManager/startDownload()`` and can be cancelled (early) via ``LLMLocalDownloadManager/cancelDownload()``. + +The current state of the ``LLMLocalDownloadManager`` is exposed via the ``LLMLocalDownloadManager/state`` property which +is of type ``LLMLocalDownloadManager/DownloadState``, containing states such as ``LLMLocalDownloadManager/DownloadState/downloading(progress:)`` which includes the progress of the download or ``LLMLocalDownloadManager/DownloadState/downloaded(storageUrl:)`` which indicates that the download has finished. + +## Topics + +### Views + +- ``LLMLocalDownloadView`` + +### Operations + +- ``LLMLocalDownloadManager`` diff --git a/Sources/SpeziOpenAI/OpenAIAPIKeyOnboardingStep.swift b/Sources/SpeziLLMOpenAI/OpenAIAPIKeyOnboardingStep.swift similarity index 98% rename from Sources/SpeziOpenAI/OpenAIAPIKeyOnboardingStep.swift rename to Sources/SpeziLLMOpenAI/OpenAIAPIKeyOnboardingStep.swift index bb23e77..8f7e194 100644 --- a/Sources/SpeziOpenAI/OpenAIAPIKeyOnboardingStep.swift +++ b/Sources/SpeziLLMOpenAI/OpenAIAPIKeyOnboardingStep.swift @@ -47,7 +47,7 @@ public struct OpenAIAPIKeyOnboardingStep: View { VStack(spacing: 0) { Text(String(localized: "OPENAI_API_KEY_SUBTITLE", bundle: .module)) .multilineTextAlignment(.center) - TextField(String(localized: "OPENAI_API_KEY_PROMT", bundle: .module), text: apiToken) + TextField(String(localized: "OPENAI_API_KEY_PROMPT", bundle: .module), text: apiToken) .frame(height: 50) .textFieldStyle(.roundedBorder) .padding(.vertical, 16) diff --git a/Sources/SpeziLLMOpenAI/OpenAIChatStreamResult+Sendable.swift b/Sources/SpeziLLMOpenAI/OpenAIChatStreamResult+Sendable.swift new file mode 100644 index 0000000..1223af8 --- /dev/null +++ b/Sources/SpeziLLMOpenAI/OpenAIChatStreamResult+Sendable.swift @@ -0,0 +1,9 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +extension OpenAI.ChatStreamResult: @unchecked Sendable {} diff --git a/Sources/SpeziOpenAI/OpenAIConstants.swift b/Sources/SpeziLLMOpenAI/OpenAIConstants.swift similarity index 100% rename from Sources/SpeziOpenAI/OpenAIConstants.swift rename to Sources/SpeziLLMOpenAI/OpenAIConstants.swift diff --git a/Sources/SpeziOpenAI/OpenAIError.swift b/Sources/SpeziLLMOpenAI/OpenAIError.swift similarity index 100% rename from Sources/SpeziOpenAI/OpenAIError.swift rename to Sources/SpeziLLMOpenAI/OpenAIError.swift diff --git a/Sources/SpeziOpenAI/OpenAIModel.swift b/Sources/SpeziLLMOpenAI/OpenAIModel.swift similarity index 69% rename from Sources/SpeziOpenAI/OpenAIModel.swift rename to Sources/SpeziLLMOpenAI/OpenAIModel.swift index 80c1fee..894fd95 100644 --- a/Sources/SpeziOpenAI/OpenAIModel.swift +++ b/Sources/SpeziLLMOpenAI/OpenAIModel.swift @@ -6,11 +6,15 @@ // SPDX-License-Identifier: MIT // -import OpenAI +import struct OpenAI.Chat +import struct OpenAI.ChatFunctionDeclaration +import struct OpenAI.ChatQuery +import class OpenAI.OpenAI @_exported import struct OpenAI.Model @_exported import struct OpenAI.ChatStreamResult import Foundation import Observation +import SpeziChat import SpeziSecureStorage @@ -76,18 +80,42 @@ public class OpenAIModel { } } - - /// Queries the OpenAI API using the provided messages. + /// Queries the OpenAI API using the provided chat messages. + /// Builds on top of the [SpeziChat](https://github.com/StanfordSpezi/SpeziChat) module to handle the `SpeziChat.Chat` data structure. + /// + /// - Parameters: + /// - chat: A collection of chat messages (from the `SpeziChat` dependency) used in the conversation. + /// + /// - Returns: The content of the response from the API. + public func queryAPI( + withChat chat: SpeziChat.Chat + ) throws -> AsyncThrowingStream { + guard let apiToken, !apiToken.isEmpty else { + throw OpenAIError.noAPIToken + } + + let openAIChat: [Chat] = chat.map { speziChat in + .init( + role: Chat.Role(rawValue: speziChat.role.rawValue) ?? .assistant, + content: speziChat.content + ) + } + + return try self.queryAPI(withOpenAIChat: openAIChat) + } + + /// Queries the OpenAI API using the provided chat messages. + /// Supports advanced OpenAI functionality like Function Calling using the native OpenAI `[OpenAI.Chat]` data structure. /// /// - Parameters: - /// - chat: A collection of chat messages used in the conversation. + /// - chat: A collection of chat messages (from the `OpenAI` dependency) used in the conversation. /// - chatFunctionDeclaration: OpenAI functions that should be injected in the OpenAI query. /// /// - Returns: The content of the response from the API. public func queryAPI( - withChat chat: [Chat], + withOpenAIChat chat: [Chat], withFunction chatFunctionDeclaration: [ChatFunctionDeclaration] = [] - ) async throws -> AsyncThrowingStream { + ) throws -> AsyncThrowingStream { guard let apiToken, !apiToken.isEmpty else { throw OpenAIError.noAPIToken } diff --git a/Sources/SpeziOpenAI/OpenAIModelSelectionOnboardingStep.swift b/Sources/SpeziLLMOpenAI/OpenAIModelSelectionOnboardingStep.swift similarity index 100% rename from Sources/SpeziOpenAI/OpenAIModelSelectionOnboardingStep.swift rename to Sources/SpeziLLMOpenAI/OpenAIModelSelectionOnboardingStep.swift diff --git a/Sources/SpeziOpenAI/OpenAIModule.swift b/Sources/SpeziLLMOpenAI/OpenAIModule.swift similarity index 93% rename from Sources/SpeziOpenAI/OpenAIModule.swift rename to Sources/SpeziLLMOpenAI/OpenAIModule.swift index 07af819..888b762 100644 --- a/Sources/SpeziOpenAI/OpenAIModule.swift +++ b/Sources/SpeziLLMOpenAI/OpenAIModule.swift @@ -23,7 +23,7 @@ public class OpenAIModule: Module, DefaultInitializable { private var defaultOpenAIModel: Model? - /// Initializes a new instance of `OpenAIGPT` with the specified API token and OpenAI model. + /// Initializes a new instance of `OpenAIModule` with the specified API token and OpenAI model. /// /// - Parameters: /// - apiToken: The API token for the OpenAI API. diff --git a/Sources/SpeziLLMOpenAI/Resources/Localizable.xcstrings b/Sources/SpeziLLMOpenAI/Resources/Localizable.xcstrings new file mode 100644 index 0000000..acee49a --- /dev/null +++ b/Sources/SpeziLLMOpenAI/Resources/Localizable.xcstrings @@ -0,0 +1,204 @@ +{ + "sourceLanguage" : "en", + "strings" : { + "OPENAI_API_KEY_PROMPT" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI-API-Schlüssel" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI API Key" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clave API de OpenAI" + } + } + } + }, + "OPENAI_API_KEY_SAVE_BUTTON" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Weiter" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Next" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Siguiente" + } + } + } + }, + "OPENAI_API_KEY_SUBTITLE" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bitte geben Sie Ihren OpenAI-API-Schlüssel ein." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Please enter your OpenAI API key." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Por favor, introduzca su clave API de OpenAI." + } + } + } + }, + "OPENAI_API_KEY_SUBTITLE_HINT" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sie können Ihre OpenAI-API-Schlüssel [im API-Schlüsselbereich Ihres OpenAI-Kontos erstellen und überprüfen.](https://platform.openai.com/account/api-keys)" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You can create and inspect your OpenAI API keys [in the API keys section of your OpenAI Account](https://platform.openai.com/account/api-keys)." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puede crear e inspeccionar sus claves API de OpenAI [en la sección de claves API de su cuenta de OpenAI.](https://platform.openai.com/account/api-keys)" + } + } + } + }, + "OPENAI_API_KEY_TITLE" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI-API-Schlüssel" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI API Key" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clave API de OpenAI" + } + } + } + }, + "OPENAI_MODEL_SELECTION_DESCRIPTION" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI GPT-Modell" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI GPT Model" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelo GPT de OpenAI" + } + } + } + }, + "OPENAI_MODEL_SELECTION_SAVE_BUTTON" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Weiter" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Next" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Siguiente" + } + } + } + }, + "OPENAI_MODEL_SELECTION_SUBTITLE" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wählen Sie das OpenAI-Modell, das Sie verwenden möchten. Stellen Sie sicher, dass Ihr API-Schlüssel angemessenen Zugriff auf das ausgewählte Modell hat." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Select the OpenAI model that you want to use. Ensure that your API key has proper access to the model you select." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seleccione el modelo de OpenAI que desea utilizar. Asegúrese de que su clave API tenga acceso adecuado al modelo que seleccione." + } + } + } + }, + "OPENAI_MODEL_SELECTION_TITLE" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wählen Sie ein OpenAI-Modell" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Select an OpenAI Model" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seleccione un Modelo de OpenAI" + } + } + } + } + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/Sources/SpeziLLMOpenAI/Resources/Localizable.xcstrings.license b/Sources/SpeziLLMOpenAI/Resources/Localizable.xcstrings.license new file mode 100644 index 0000000..6917c4b --- /dev/null +++ b/Sources/SpeziLLMOpenAI/Resources/Localizable.xcstrings.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView.png b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView.png new file mode 100644 index 0000000000000000000000000000000000000000..186341e66c14b9221a3f2c4243eec2e9c0b4c8c2 GIT binary patch literal 47173 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 SE02l*0000CJDv> diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView~dark.png b/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView~dark.png deleted file mode 100644 index 930190e2585d978f2ecb0be62b8087c003116603..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91225 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 AsyncThrowingStream { // swiftlint:disable:this function_body_length - // We allow a larger function and closure length as the function provides a clear encapsulated functionality and the closue is mainly the function - // wrapped in a continuation. - AsyncThrowingStream { continuation in // swiftlint:disable:this closure_body_length - guard !isRecording else { - print("You already having a recording session in progress, please cancel the first one using `stop` before starting a new session.") - stop() - continuation.finish() - return - } - - guard isAvailable, let audioEngine, let speechRecognizer else { - print("The speechrecognizer is not available.") - stop() - continuation.finish() - return - } - - do { - let audioSession = AVAudioSession.sharedInstance() - try audioSession.setCategory(.record, mode: .measurement, options: .duckOthers) - try audioSession.setActive(true, options: .notifyOthersOnDeactivation) - } catch { - print("Error setting up the audio session: \(error.localizedDescription)") - stop() - continuation.finish(throwing: error) - } - - let inputNode = audioEngine.inputNode - - let recognitionRequest = SFSpeechAudioBufferRecognitionRequest() - recognitionRequest.shouldReportPartialResults = true - self.recognitionRequest = recognitionRequest - - recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in - if let error { - continuation.finish(throwing: error) - } - - guard self.isRecording, let result else { - self.stop() - return - } - - continuation.yield(result) - } - - let recordingFormat = inputNode.outputFormat(forBus: 0) - inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in - self.recognitionRequest?.append(buffer) - } - - audioEngine.prepare() - do { - isRecording = true - try audioEngine.start() - } catch { - print("Error setting up the audio session: \(error.localizedDescription)") - stop() - continuation.finish(throwing: error) - } - - continuation.onTermination = { @Sendable _ in - self.stop() - } - } - } - - /// Stops the current speech recognition session. - public func stop() { - guard isAvailable && isRecording else { - return - } - - audioEngine?.stop() - audioEngine?.inputNode.removeTap(onBus: 0) - - recognitionRequest?.endAudio() - recognitionRequest = nil - - recognitionTask?.cancel() - recognitionTask = nil - - isRecording = false - } - - @_documentation(visibility: internal) - public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { - guard self.speechRecognizer == speechRecognizer else { - return - } - - self.isAvailable = available - } -} diff --git a/Sources/SpeziSpeechSynthesizer/SpeechSynthesizer.swift b/Sources/SpeziSpeechSynthesizer/SpeechSynthesizer.swift deleted file mode 100644 index 43708d7..0000000 --- a/Sources/SpeziSpeechSynthesizer/SpeechSynthesizer.swift +++ /dev/null @@ -1,82 +0,0 @@ -// -// This source file is part of the Stanford Spezi open source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -import AVFoundation - - -/// An object that produces synthesized speech from text utterances. -/// -/// Encapsulates the functionality of the `AVSpeechSynthesizer`. -public class SpeechSynthesizer: NSObject, ObservableObject, AVSpeechSynthesizerDelegate { - private let avSpeechSynthesizer = AVSpeechSynthesizer() - - - /// A Boolean value that indicates whether the speech synthesizer is speaking or is in a paused state and has utterances to speak. - @Published public private(set) var isSpeaking = false - /// A Boolean value that indicates whether a speech synthesizer is in a paused state. - @Published public private(set) var isPaused = false - - - override public init() { - super.init() - avSpeechSynthesizer.delegate = self - } - - - /// Adds the text to the speech synthesizer’s queue. - /// - Parameters: - /// - text: A string that contains the text to speak. - /// - language: Optional BCP 47 code that identifies the language and locale for a voice. - public func speak(_ text: String, language: String? = nil) { - let utterance = AVSpeechUtterance(string: text) - - if let language { - utterance.voice = AVSpeechSynthesisVoice(language: language) - } - - speak(utterance) - } - - /// Adds the utterance to the speech synthesizer’s queue. - /// - Parameter utterance: An `AVSpeechUtterance` instance that contains text to speak. - public func speak(_ utterance: AVSpeechUtterance) { - avSpeechSynthesizer.speak(utterance) - } - - - // MARK: - AVSpeechSynthesizerDelegate - @_documentation(visibility: internal) - public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) { - isSpeaking = true - isPaused = false - } - - @_documentation(visibility: internal) - public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance) { - isSpeaking = false - isPaused = true - } - - @_documentation(visibility: internal) - public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didContinue utterance: AVSpeechUtterance) { - isSpeaking = true - isPaused = false - } - - @_documentation(visibility: internal) - public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) { - isSpeaking = false - isPaused = false - } - - @_documentation(visibility: internal) - public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) { - isSpeaking = false - isPaused = false - } -} diff --git a/Tests/SpeziOpenAITests/SpeziOpenAITests.swift b/Tests/SpeziLLMTests/SpeziLLMTests.swift similarity index 69% rename from Tests/SpeziOpenAITests/SpeziOpenAITests.swift rename to Tests/SpeziLLMTests/SpeziLLMTests.swift index 90dcc04..0f97ec9 100644 --- a/Tests/SpeziOpenAITests/SpeziOpenAITests.swift +++ b/Tests/SpeziLLMTests/SpeziLLMTests.swift @@ -6,12 +6,12 @@ // SPDX-License-Identifier: MIT // -@testable import SpeziOpenAI +@testable import SpeziLLM import XCTest -final class SpeziOpenAITests: XCTestCase { - func testSpeziOpenAITests() throws { +final class SpeziLLMTests: XCTestCase { + func testSpeziLLMTests() throws { XCTAssert(true) } } diff --git a/Tests/UITests/TestApp.xctestplan b/Tests/UITests/TestApp.xctestplan index 4a27fa3..980674b 100644 --- a/Tests/UITests/TestApp.xctestplan +++ b/Tests/UITests/TestApp.xctestplan @@ -13,8 +13,23 @@ "targets" : [ { "containerPath" : "container:..\/..", - "identifier" : "SpeziOpenAI", - "name" : "SpeziOpenAI" + "identifier" : "SpeziLLMOpenAI", + "name" : "SpeziLLMOpenAI" + }, + { + "containerPath" : "container:..\/..", + "identifier" : "SpeziLLM", + "name" : "SpeziLLM" + }, + { + "containerPath" : "container:..\/..", + "identifier" : "SpeziLLMLocal", + "name" : "SpeziLLMLocal" + }, + { + "containerPath" : "container:..\/..", + "identifier" : "SpeziLLMLocalDownload", + "name" : "SpeziLLMLocalDownload" } ] }, diff --git a/Tests/UITests/TestApp.xctestplan.license b/Tests/UITests/TestApp.xctestplan.license index 8d01219..6917c4b 100644 --- a/Tests/UITests/TestApp.xctestplan.license +++ b/Tests/UITests/TestApp.xctestplan.license @@ -1,5 +1,5 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/Tests/UITests/TestApp/Assets.xcassets/AccentColor.colorset/Contents.json.license b/Tests/UITests/TestApp/Assets.xcassets/AccentColor.colorset/Contents.json.license index 8d01219..7f16969 100644 --- a/Tests/UITests/TestApp/Assets.xcassets/AccentColor.colorset/Contents.json.license +++ b/Tests/UITests/TestApp/Assets.xcassets/AccentColor.colorset/Contents.json.license @@ -1,4 +1,4 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) diff --git a/Tests/UITests/TestApp/Assets.xcassets/AppIcon.appiconset/Contents.json.license b/Tests/UITests/TestApp/Assets.xcassets/AppIcon.appiconset/Contents.json.license index 8d01219..7f16969 100644 --- a/Tests/UITests/TestApp/Assets.xcassets/AppIcon.appiconset/Contents.json.license +++ b/Tests/UITests/TestApp/Assets.xcassets/AppIcon.appiconset/Contents.json.license @@ -1,4 +1,4 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) diff --git a/Tests/UITests/TestApp/Assets.xcassets/Contents.json.license b/Tests/UITests/TestApp/Assets.xcassets/Contents.json.license index 8d01219..7f16969 100644 --- a/Tests/UITests/TestApp/Assets.xcassets/Contents.json.license +++ b/Tests/UITests/TestApp/Assets.xcassets/Contents.json.license @@ -1,4 +1,4 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) diff --git a/Tests/UITests/TestApp/ContentView.swift b/Tests/UITests/TestApp/ContentView.swift deleted file mode 100644 index d135a38..0000000 --- a/Tests/UITests/TestApp/ContentView.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// This source file is part of the SpeziML open-source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -import SpeziOpenAI -import SwiftUI - - -struct ContentView: View { - @State var chat: [Chat] = [ - Chat(role: .system, content: "System Message!"), - Chat(role: .system, content: "System Message (hidden)!"), - Chat(role: .function, content: "Function Message!"), - Chat(role: .user, content: "User Message!"), - Chat(role: .assistant, content: "Assistant Message!") - ] - @State var showOnboarding = false - - - var body: some View { - NavigationStack { - ChatView($chat) - .navigationTitle("Spezi ML") - .toolbar { - ToolbarItem { - Button("Onboarding") { - showOnboarding.toggle() - } - } - } - } - .sheet(isPresented: $showOnboarding) { - OnboardingView() - } - } -} diff --git a/Tests/UITests/TestApp/FeatureFlags.swift b/Tests/UITests/TestApp/FeatureFlags.swift new file mode 100644 index 0000000..dba1217 --- /dev/null +++ b/Tests/UITests/TestApp/FeatureFlags.swift @@ -0,0 +1,15 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation + + +enum FeatureFlags { + /// Configures the local LLM to mock all generated responses in order to simplify development and write UI Tests. + static let mockLocalLLM = ProcessInfo.processInfo.arguments.contains("--mockLocalLLM") +} diff --git a/Tests/UITests/TestApp/LLMLocal/Helpers/Binding+Negate.swift b/Tests/UITests/TestApp/LLMLocal/Helpers/Binding+Negate.swift new file mode 100644 index 0000000..97b726e --- /dev/null +++ b/Tests/UITests/TestApp/LLMLocal/Helpers/Binding+Negate.swift @@ -0,0 +1,20 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +extension Binding where Value == Bool { + /// Negates a `Binding`. + prefix static func ! (value: Binding) -> Binding { + Binding( + get: { !value.wrappedValue }, + set: { value.wrappedValue = !$0 } + ) + } +} diff --git a/Tests/UITests/TestApp/LLMLocal/Helpers/StorageKeys.swift b/Tests/UITests/TestApp/LLMLocal/Helpers/StorageKeys.swift new file mode 100644 index 0000000..f683c5e --- /dev/null +++ b/Tests/UITests/TestApp/LLMLocal/Helpers/StorageKeys.swift @@ -0,0 +1,13 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +/// Constants shared across the local LLM execution demo application to access storage information including the `AppStorage`. +enum StorageKeys { + /// A `Bool` flag indicating of the onboarding was completed. + static let onboardingFlowComplete = "onboardingFlow.complete" +} diff --git a/Tests/UITests/TestApp/LLMLocal/LLMLocalChatTestView.swift b/Tests/UITests/TestApp/LLMLocal/LLMLocalChatTestView.swift new file mode 100644 index 0000000..37c757e --- /dev/null +++ b/Tests/UITests/TestApp/LLMLocal/LLMLocalChatTestView.swift @@ -0,0 +1,47 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SpeziLLM +import SpeziLLMLocal +import SwiftUI + + +/// Presents a chat view that enables user's to interact with the local LLM. +struct LLMLocalChatTestView: View { + /// The Spezi `LLM` that is configured and executed on the `LLMRunner` + @State private var model: LLM = { + if FeatureFlags.mockLocalLLM { + LLMMock() + } else { + LLMLlama( + modelPath: .cachesDirectory.appending(path: "llm.gguf"), /// Loads the LLM from the passed cache directory + parameters: .init(maxOutputLength: 512), /// Limits the size of the generated response to 512 tokens + contextParameters: .init(contextWindowSize: 1024) /// Sets the context size of the model at 1024 tokens + ) + } + }() + + + var body: some View { + LLMChatView( + model: model, + initialAssistantPrompt: [ + .init( + role: .assistant, + content: "Hello! I'm a locally executed Llama 2 7B model, enabled by the Spezi ecosystem!" + ) + ] + ) + .navigationTitle("LLM_LOCAL_CHAT_VIEW_TITLE") + } +} + + +#Preview { + LLMLocalChatTestView() +} diff --git a/Tests/UITests/TestApp/LLMLocal/LLMLocalTestView.swift b/Tests/UITests/TestApp/LLMLocal/LLMLocalTestView.swift new file mode 100644 index 0000000..accc363 --- /dev/null +++ b/Tests/UITests/TestApp/LLMLocal/LLMLocalTestView.swift @@ -0,0 +1,28 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SpeziOnboarding +import SwiftUI + + +struct LLMLocalTestView: View { + @AppStorage(StorageKeys.onboardingFlowComplete) private var completedOnboardingFlow = false + + + var body: some View { + LLMLocalChatTestView() + .sheet(isPresented: !$completedOnboardingFlow) { + LLMLocalOnboardingFlow() + } + } +} + + +#Preview { + LLMLocalTestView() +} diff --git a/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingDownloadView.swift b/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingDownloadView.swift new file mode 100644 index 0000000..1c09fe3 --- /dev/null +++ b/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingDownloadView.swift @@ -0,0 +1,35 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SpeziLLMLocalDownload +import SpeziOnboarding +import SpeziViews +import SwiftUI + + +/// Onboarding LLM Download view for the Local LLM example application. +struct LLMLocalOnboardingDownloadView: View { + @Environment(OnboardingNavigationPath.self) private var onboardingNavigationPath + + + var body: some View { + LLMLocalDownloadView( + llmDownloadUrl: LLMLocalDownloadManager.LLMUrlDefaults.llama2ChatModelUrl, /// By default, download the Llama2 model + llmStorageUrl: .cachesDirectory.appending(path: "llm.gguf") /// Store the downloaded LLM in the caches directory + ) { + onboardingNavigationPath.nextStep() + } + } +} + + +#Preview { + OnboardingStack { + LLMLocalOnboardingDownloadView() + } +} diff --git a/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingFlow.swift b/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingFlow.swift new file mode 100644 index 0000000..3d083bf --- /dev/null +++ b/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingFlow.swift @@ -0,0 +1,33 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SpeziOnboarding +import SwiftUI + + +/// Displays a multi-step onboarding flow for the Local LLM example application. +struct LLMLocalOnboardingFlow: View { + @AppStorage(StorageKeys.onboardingFlowComplete) private var completedOnboardingFlow = false + + + var body: some View { + OnboardingStack(onboardingFlowComplete: $completedOnboardingFlow) { + LLMLocalOnboardingWelcomeView() + + if !FeatureFlags.mockLocalLLM { + LLMLocalOnboardingDownloadView() + } + } + .interactiveDismissDisabled(!completedOnboardingFlow) + } +} + + +#Preview { + LLMLocalOnboardingFlow() +} diff --git a/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingWelcomeView.swift b/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingWelcomeView.swift new file mode 100644 index 0000000..20278a2 --- /dev/null +++ b/Tests/UITests/TestApp/LLMLocal/Onboarding/LLMLocalOnboardingWelcomeView.swift @@ -0,0 +1,63 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SpeziOnboarding +import SwiftUI + + +/// Onboarding Welcome view for the Local LLM example application. +struct LLMLocalOnboardingWelcomeView: View { + @Environment(OnboardingNavigationPath.self) private var onboardingNavigationPath + + + var body: some View { + OnboardingView( + title: "WELCOME_TITLE", + subtitle: "WELCOME_SUBTITLE", + areas: [ + OnboardingInformationView.Content( + icon: { + Image(systemName: "apps.iphone") + .accessibilityHidden(true) + }, + title: "WELCOME_AREA1_TITLE", + description: "WELCOME_AREA1_DESCRIPTION" + ), + OnboardingInformationView.Content( + icon: { + Image(systemName: "shippingbox.fill") + .accessibilityHidden(true) + }, + title: "WELCOME_AREA2_TITLE", + description: "WELCOME_AREA2_DESCRIPTION" + ), + OnboardingInformationView.Content( + icon: { + Image(systemName: "globe") + .accessibilityHidden(true) + }, + title: "WELCOME_AREA3_TITLE", + description: "WELCOME_AREA3_DESCRIPTION" + ) + ], + actionText: "WELCOME_BUTTON", + action: { + onboardingNavigationPath.nextStep() + } + ) + .padding(.top, 24) + } +} + + +#Preview { + OnboardingStack { + LLMLocalOnboardingWelcomeView() + LLMLocalOnboardingDownloadView() + } +} diff --git a/Tests/UITests/TestApp/LLMOpenAI/LLMOpenAIChatTestView.swift b/Tests/UITests/TestApp/LLMOpenAI/LLMOpenAIChatTestView.swift new file mode 100644 index 0000000..4d62db0 --- /dev/null +++ b/Tests/UITests/TestApp/LLMOpenAI/LLMOpenAIChatTestView.swift @@ -0,0 +1,39 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SpeziChat +import SwiftUI + + +struct LLMOpenAIChatTestView: View { + @State var chat: Chat = [ + .init(role: .system, content: "System Message!"), + .init(role: .system, content: "System Message (hidden)!"), + .init(role: .function, content: "Function Message!"), + .init(role: .user, content: "User Message!"), + .init(role: .assistant, content: "Assistant Message!") + ] + @State var showOnboarding = false + + + var body: some View { + ChatView($chat) + .navigationTitle("LLM_OPENAI_CHAT_VIEW_TITLE") + .toolbar { + ToolbarItem { + Button("LLM_OPENAI_CHAT_ONBOARDING_BUTTON") { + showOnboarding.toggle() + } + } + } + .sheet(isPresented: $showOnboarding) { + LLMOpenAIOnboardingView() + } + .accentColor(Color(red: 0, green: 166 / 255, blue: 126 / 255)) // OpenAI Green Color + } +} diff --git a/Tests/UITests/TestApp/OnboardingView.swift b/Tests/UITests/TestApp/LLMOpenAI/LLMOpenAIOnboardingView.swift similarity index 85% rename from Tests/UITests/TestApp/OnboardingView.swift rename to Tests/UITests/TestApp/LLMOpenAI/LLMOpenAIOnboardingView.swift index 913921a..018d6fe 100644 --- a/Tests/UITests/TestApp/OnboardingView.swift +++ b/Tests/UITests/TestApp/LLMOpenAI/LLMOpenAIOnboardingView.swift @@ -1,17 +1,17 @@ // -// This source file is part of the SpeziML open-source project +// This source file is part of the Stanford Spezi open source project // // SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) // // SPDX-License-Identifier: MIT // -import SpeziOpenAI +import SpeziLLMOpenAI import SwiftUI import XCTSpezi -struct OnboardingView: View { +struct LLMOpenAIOnboardingView: View { enum Step: String, Codable { case modelSelection } diff --git a/Tests/UITests/TestApp/Resources/Localizable.xcstrings b/Tests/UITests/TestApp/Resources/Localizable.xcstrings new file mode 100644 index 0000000..1c949eb --- /dev/null +++ b/Tests/UITests/TestApp/Resources/Localizable.xcstrings @@ -0,0 +1,136 @@ +{ + "sourceLanguage" : "en", + "strings" : { + "LLM_LOCAL_CHAT_VIEW_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM Local Chat" + } + } + } + }, + "LLM_OPENAI_CHAT_ONBOARDING_BUTTON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onboarding" + } + } + } + }, + "LLM_OPENAI_CHAT_VIEW_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLM OpenAI Chat" + } + } + } + }, + "SPEZI_LLM_TEST_NAVIGATION_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "SpeziLLM UI Test" + } + } + } + }, + "WELCOME_AREA1_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Locally execute LLMs directly on your phone." + } + } + } + }, + "WELCOME_AREA1_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "LLMs on an iPhone" + } + } + } + }, + "WELCOME_AREA2_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The LLM execution is provided by a module available through the Swift Package Manager." + } + } + } + }, + "WELCOME_AREA2_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Swift Package Manager" + } + } + } + }, + "WELCOME_AREA3_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This application is built on top of the Stanford Spezi ecosystem." + } + } + } + }, + "WELCOME_AREA3_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The Stanford Spezi ecosystem" + } + } + } + }, + "WELCOME_BUTTON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Next" + } + } + } + }, + "WELCOME_SUBTITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This application demonstrates the local execution of a Large Language Model on an iPhone." + } + } + } + }, + "WELCOME_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Local LLM Execution" + } + } + } + } + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/Tests/UITests/TestApp/Resources/Localizable.xcstrings.license b/Tests/UITests/TestApp/Resources/Localizable.xcstrings.license new file mode 100644 index 0000000..6917c4b --- /dev/null +++ b/Tests/UITests/TestApp/Resources/Localizable.xcstrings.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Tests/UITests/TestApp/TestApp.swift b/Tests/UITests/TestApp/TestApp.swift index 75daa67..1aac52f 100644 --- a/Tests/UITests/TestApp/TestApp.swift +++ b/Tests/UITests/TestApp/TestApp.swift @@ -1,23 +1,54 @@ // -// This source file is part of the SpeziML open-source project +// This source file is part of the Stanford Spezi open source project // // SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) // // SPDX-License-Identifier: MIT // -import SpeziOpenAI import SwiftUI @main struct UITestsApp: App { + enum Tests: String, CaseIterable, Identifiable { + case llmOpenAI = "LLMOpenAI" + case llmLocal = "LLMLocal" + + + var id: RawValue { + self.rawValue + } + + + @MainActor + @ViewBuilder + func view(withNavigationPath path: Binding) -> some View { + switch self { + case .llmOpenAI: + LLMOpenAIChatTestView() + case .llmLocal: + LLMLocalTestView() + } + } + } + + @UIApplicationDelegateAdaptor(TestAppDelegate.self) var appDelegate + @State private var path = NavigationPath() var body: some Scene { WindowGroup { - ContentView() + NavigationStack(path: $path) { + List(Tests.allCases) { test in + NavigationLink(test.rawValue, value: test) + } + .navigationDestination(for: Tests.self) { test in + test.view(withNavigationPath: $path) + } + .navigationTitle("SPEZI_LLM_TEST_NAVIGATION_TITLE") + } .spezi(appDelegate) } } diff --git a/Tests/UITests/TestApp/TestAppDelegate.swift b/Tests/UITests/TestApp/TestAppDelegate.swift index 2a42bde..311a3b8 100644 --- a/Tests/UITests/TestApp/TestAppDelegate.swift +++ b/Tests/UITests/TestApp/TestAppDelegate.swift @@ -1,5 +1,5 @@ // -// This source file is part of the SpeziML open-source project +// This source file is part of the Stanford Spezi open source project // // SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) // @@ -7,13 +7,17 @@ // import Spezi -import SpeziOpenAI -import XCTSpezi +import SpeziLLM +import SpeziLLMLocal +import SpeziLLMOpenAI class TestAppDelegate: SpeziAppDelegate { override var configuration: Configuration { Configuration { + LLMRunner { + LLMLocalRunnerSetupTask() + } OpenAIModule() } } diff --git a/Tests/UITests/TestAppUITests/TestAppLLMLocalUITests.swift b/Tests/UITests/TestAppUITests/TestAppLLMLocalUITests.swift new file mode 100644 index 0000000..48618ad --- /dev/null +++ b/Tests/UITests/TestAppUITests/TestAppLLMLocalUITests.swift @@ -0,0 +1,53 @@ +// +// This source file is part of the Stanford Spezi open source project +// +// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import XCTest +import XCTestExtensions + + +class TestAppLLMLocalUITests: XCTestCase { + override func setUpWithError() throws { + try super.setUpWithError() + + continueAfterFailure = false + + let app = XCUIApplication() + app.launchArguments = ["--mockLocalLLM"] + app.deleteAndLaunch(withSpringboardAppName: "TestApp") + } + + func testSpeziLLMLocal() throws { + let app = XCUIApplication() + + XCTAssert(app.buttons["LLMLocal"].waitForExistence(timeout: 2)) + app.buttons["LLMLocal"].tap() + + // Onboarding + XCTAssert(app.staticTexts["Local LLM Execution"].waitForExistence(timeout: 2)) + XCTAssert(app.staticTexts["LLMs on an iPhone"].waitForExistence(timeout: 2)) + XCTAssert(app.staticTexts["Swift Package Manager"].waitForExistence(timeout: 2)) + XCTAssert(app.staticTexts["The Stanford Spezi ecosystem"].waitForExistence(timeout: 2)) + + XCTAssert(app.buttons["Next"].waitForExistence(timeout: 2)) + app.buttons["Next"].tap() + + // Chat + XCTAssert(app.staticTexts["Hello! I'm a locally executed Llama 2 7B model, enabled by the Spezi ecosystem!"].waitForExistence(timeout: 2)) + + try app.textViews["Message Input Textfield"].enter(value: "New Message!", dismissKeyboard: false) + + XCTAssert(app.buttons["Send Message"].waitForExistence(timeout: 2)) + app.buttons["Send Message"].tap() + + XCTAssert(app.staticTexts["New Message!"].waitForExistence(timeout: 5)) + + sleep(3) + + XCTAssert(app.staticTexts["Mock Message from SpeziLLM!"].waitForExistence(timeout: 5)) + } +} diff --git a/Tests/UITests/TestAppUITests/TestAppUITests.swift b/Tests/UITests/TestAppUITests/TestAppLLMOpenAIUITests.swift similarity index 77% rename from Tests/UITests/TestAppUITests/TestAppUITests.swift rename to Tests/UITests/TestAppUITests/TestAppLLMOpenAIUITests.swift index 446e2c1..c2c33c9 100644 --- a/Tests/UITests/TestAppUITests/TestAppUITests.swift +++ b/Tests/UITests/TestAppUITests/TestAppLLMOpenAIUITests.swift @@ -1,5 +1,5 @@ // -// This source file is part of the SpeziML open-source project +// This source file is part of the Stanford Spezi open source project // // SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) // @@ -10,7 +10,7 @@ import XCTest import XCTestExtensions -class TestAppUITests: XCTestCase { +class TestAppLLMOpenAIUITests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() @@ -21,14 +21,14 @@ class TestAppUITests: XCTestCase { } - func testSpeziMLOnboarding() throws { + func testSpeziLLMOpenAIOnboarding() throws { let app = XCUIApplication() + XCTAssert(app.buttons["LLMOpenAI"].waitForExistence(timeout: 2)) + app.buttons["LLMOpenAI"].tap() - let elementsQuery = XCUIApplication().scrollViews.otherElements - elementsQuery.staticTexts["User Message!"].tap() - elementsQuery.staticTexts["Assistant Message!"].tap() - + app.staticTexts["User Message!"].tap() + app.staticTexts["Assistant Message!"].tap() app.buttons["Onboarding"].tap() @@ -49,6 +49,10 @@ class TestAppUITests: XCTestCase { app.terminate() app.launch() + XCTAssert(app.buttons["LLMOpenAI"].waitForExistence(timeout: 2)) + app.buttons["LLMOpenAI"].tap() + + XCTAssert(app.buttons["Onboarding"].waitForExistence(timeout: 2)) app.buttons["Onboarding"].tap() XCTAssert(app.textFields["New Token"].waitForExistence(timeout: 2)) @@ -60,6 +64,9 @@ class TestAppUITests: XCTestCase { app.deleteAndLaunch(withSpringboardAppName: "TestApp") + XCTAssert(app.buttons["LLMOpenAI"].waitForExistence(timeout: 2)) + app.buttons["LLMOpenAI"].tap() + app.buttons["Onboarding"].tap() XCTAssert(app.textFields["OpenAI API Key"].waitForExistence(timeout: 2)) @@ -70,9 +77,12 @@ class TestAppUITests: XCTestCase { XCTAssert(app.pickerWheels["GPT 3.5 Turbo"].waitForExistence(timeout: 2)) } - func testSpeziMLChat() throws { + func testSpeziLLMOpenAIChat() throws { let app = XCUIApplication() + XCTAssert(app.buttons["LLMOpenAI"].waitForExistence(timeout: 2)) + app.buttons["LLMOpenAI"].tap() + XCTAssert(app.staticTexts["User Message!"].waitForExistence(timeout: 2)) XCTAssert(app.staticTexts["Assistant Message!"].waitForExistence(timeout: 2)) XCTAssert(app.buttons["Record Message"].waitForExistence(timeout: 2)) diff --git a/Tests/UITests/UITests.xcodeproj/project.pbxproj b/Tests/UITests/UITests.xcodeproj/project.pbxproj index bc10467..8972590 100644 --- a/Tests/UITests/UITests.xcodeproj/project.pbxproj +++ b/Tests/UITests/UITests.xcodeproj/project.pbxproj @@ -7,18 +7,30 @@ objects = { /* Begin PBXBuildFile section */ - 2F55FC552A1B42D20051DF48 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F55FC542A1B42D20051DF48 /* ContentView.swift */; }; 2F6D139A28F5F386007C25D6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2F6D139928F5F386007C25D6 /* Assets.xcassets */; }; - 2F8A431329130A8C005D2B8F /* TestAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F8A431229130A8C005D2B8F /* TestAppUITests.swift */; }; + 2F8A431329130A8C005D2B8F /* TestAppLLMOpenAIUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F8A431229130A8C005D2B8F /* TestAppLLMOpenAIUITests.swift */; }; 2FA7382C290ADFAA007ACEB9 /* TestApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA7382B290ADFAA007ACEB9 /* TestApp.swift */; }; - 2FC186012AD528830065EBB2 /* SpeziOpenAI in Frameworks */ = {isa = PBXBuildFile; productRef = 2FC186002AD528830065EBB2 /* SpeziOpenAI */; }; - 2FC186032AD528830065EBB2 /* SpeziSpeechRecognizer in Frameworks */ = {isa = PBXBuildFile; productRef = 2FC186022AD528830065EBB2 /* SpeziSpeechRecognizer */; }; - 2FC186052AD52C5B0065EBB2 /* SpeziSpeechSynthesizer in Frameworks */ = {isa = PBXBuildFile; productRef = 2FC186042AD52C5B0065EBB2 /* SpeziSpeechSynthesizer */; }; - 2FD590472A19E42000153BE4 /* TestAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD590452A19E41D00153BE4 /* TestAppDelegate.swift */; }; 2FD590492A19E4AE00153BE4 /* Spezi in Frameworks */ = {isa = PBXBuildFile; productRef = 2FD590482A19E4AE00153BE4 /* Spezi */; }; 2FD5904B2A19E4AE00153BE4 /* XCTSpezi in Frameworks */ = {isa = PBXBuildFile; productRef = 2FD5904A2A19E4AE00153BE4 /* XCTSpezi */; }; - 2FD5904F2A19E70000153BE4 /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD5904E2A19E70000153BE4 /* OnboardingView.swift */; }; 2FD590522A19E9F000153BE4 /* XCTestExtensions in Frameworks */ = {isa = PBXBuildFile; productRef = 2FD590512A19E9F000153BE4 /* XCTestExtensions */; }; + 9756D2512B0316240006B6BD /* Binding+Negate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9756D24B2B0316240006B6BD /* Binding+Negate.swift */; }; + 9756D2522B0316240006B6BD /* StorageKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9756D24C2B0316240006B6BD /* StorageKeys.swift */; }; + 9756D2532B0316240006B6BD /* LLMLocalOnboardingDownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9756D24E2B0316240006B6BD /* LLMLocalOnboardingDownloadView.swift */; }; + 9756D2542B0316240006B6BD /* LLMLocalOnboardingWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9756D24F2B0316240006B6BD /* LLMLocalOnboardingWelcomeView.swift */; }; + 9756D2552B0316240006B6BD /* LLMLocalOnboardingFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9756D2502B0316240006B6BD /* LLMLocalOnboardingFlow.swift */; }; + 9756D2582B0316740006B6BD /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9756D2562B0316740006B6BD /* Localizable.xcstrings */; }; + 9756D2592B0316740006B6BD /* Localizable.xcstrings.license in Resources */ = {isa = PBXBuildFile; fileRef = 9756D2572B0316740006B6BD /* Localizable.xcstrings.license */; }; + 9756D25E2B0316A30006B6BD /* LLMLocalChatTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9756D25C2B0316A30006B6BD /* LLMLocalChatTestView.swift */; }; + 9756D2602B0316D80006B6BD /* SpeziLLMLocal in Frameworks */ = {isa = PBXBuildFile; productRef = 9756D25F2B0316D80006B6BD /* SpeziLLMLocal */; }; + 9756D2622B0316D80006B6BD /* SpeziLLMLocalDownload in Frameworks */ = {isa = PBXBuildFile; productRef = 9756D2612B0316D80006B6BD /* SpeziLLMLocalDownload */; }; + 976179502B034E0400E1046E /* TestAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9761794F2B034E0400E1046E /* TestAppDelegate.swift */; }; + 976179522B034F0900E1046E /* TestAppLLMLocalUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 976179512B034F0900E1046E /* TestAppLLMLocalUITests.swift */; }; + 976179542B03501100E1046E /* FeatureFlags.swift in Sources */ = {isa = PBXBuildFile; fileRef = 976179532B03501100E1046E /* FeatureFlags.swift */; }; + 9772D6802B03381400E62B9D /* LLMOpenAIOnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9772D67F2B03381400E62B9D /* LLMOpenAIOnboardingView.swift */; }; + 9772D6822B033D5500E62B9D /* LLMOpenAIChatTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9772D6812B033D5500E62B9D /* LLMOpenAIChatTestView.swift */; }; + 977E49A02B035563001485D4 /* LLMLocalTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 977E499F2B035563001485D4 /* LLMLocalTestView.swift */; }; + 97DD56BB2B02F7E400389331 /* SpeziChat in Frameworks */ = {isa = PBXBuildFile; productRef = 97DD56BA2B02F7E400389331 /* SpeziChat */; }; + 97DD56BD2B02F80100389331 /* SpeziLLMOpenAI in Frameworks */ = {isa = PBXBuildFile; productRef = 97DD56BC2B02F80100389331 /* SpeziLLMOpenAI */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -32,16 +44,28 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 2F55FC542A1B42D20051DF48 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - 2F68C3C6292E9F8F00B3E12C /* SpeziML */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = SpeziML; path = ../..; sourceTree = ""; }; + 2F68C3C6292E9F8F00B3E12C /* SpeziLLM */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = SpeziLLM; path = ../..; sourceTree = ""; }; 2F6D139228F5F384007C25D6 /* TestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2F6D139928F5F386007C25D6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 2F6D13AC28F5F386007C25D6 /* TestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 2F8A431229130A8C005D2B8F /* TestAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAppUITests.swift; sourceTree = ""; }; + 2F8A431229130A8C005D2B8F /* TestAppLLMOpenAIUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAppLLMOpenAIUITests.swift; sourceTree = ""; }; 2FA7382B290ADFAA007ACEB9 /* TestApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestApp.swift; sourceTree = ""; }; 2FB0758A299DDB9000C0B37F /* TestApp.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TestApp.xctestplan; sourceTree = ""; }; - 2FD590452A19E41D00153BE4 /* TestAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAppDelegate.swift; sourceTree = ""; }; - 2FD5904E2A19E70000153BE4 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = ""; }; + 9756D24B2B0316240006B6BD /* Binding+Negate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Binding+Negate.swift"; sourceTree = ""; }; + 9756D24C2B0316240006B6BD /* StorageKeys.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageKeys.swift; sourceTree = ""; }; + 9756D24E2B0316240006B6BD /* LLMLocalOnboardingDownloadView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LLMLocalOnboardingDownloadView.swift; sourceTree = ""; }; + 9756D24F2B0316240006B6BD /* LLMLocalOnboardingWelcomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LLMLocalOnboardingWelcomeView.swift; sourceTree = ""; }; + 9756D2502B0316240006B6BD /* LLMLocalOnboardingFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LLMLocalOnboardingFlow.swift; sourceTree = ""; }; + 9756D2562B0316740006B6BD /* Localizable.xcstrings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; }; + 9756D2572B0316740006B6BD /* Localizable.xcstrings.license */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Localizable.xcstrings.license; sourceTree = ""; }; + 9756D25C2B0316A30006B6BD /* LLMLocalChatTestView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LLMLocalChatTestView.swift; sourceTree = ""; }; + 9761794F2B034E0400E1046E /* TestAppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestAppDelegate.swift; sourceTree = ""; }; + 976179512B034F0900E1046E /* TestAppLLMLocalUITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestAppLLMLocalUITests.swift; sourceTree = ""; }; + 976179532B03501100E1046E /* FeatureFlags.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFlags.swift; sourceTree = ""; }; + 9772D67F2B03381400E62B9D /* LLMOpenAIOnboardingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LLMOpenAIOnboardingView.swift; sourceTree = ""; }; + 9772D6812B033D5500E62B9D /* LLMOpenAIChatTestView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LLMOpenAIChatTestView.swift; sourceTree = ""; }; + 977438092B05709700EC6527 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; + 977E499F2B035563001485D4 /* LLMLocalTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LLMLocalTestView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -49,11 +73,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2FC186032AD528830065EBB2 /* SpeziSpeechRecognizer in Frameworks */, 2FD5904B2A19E4AE00153BE4 /* XCTSpezi in Frameworks */, - 2FC186012AD528830065EBB2 /* SpeziOpenAI in Frameworks */, + 97DD56BB2B02F7E400389331 /* SpeziChat in Frameworks */, + 97DD56BD2B02F80100389331 /* SpeziLLMOpenAI in Frameworks */, + 9756D2602B0316D80006B6BD /* SpeziLLMLocal in Frameworks */, + 9756D2622B0316D80006B6BD /* SpeziLLMLocalDownload in Frameworks */, 2FD590492A19E4AE00153BE4 /* Spezi in Frameworks */, - 2FC186052AD52C5B0065EBB2 /* SpeziSpeechSynthesizer in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -72,7 +97,7 @@ isa = PBXGroup; children = ( 2FB0758A299DDB9000C0B37F /* TestApp.xctestplan */, - 2F68C3C6292E9F8F00B3E12C /* SpeziML */, + 2F68C3C6292E9F8F00B3E12C /* SpeziLLM */, 2F6D139428F5F384007C25D6 /* TestApp */, 2F6D13AF28F5F386007C25D6 /* TestAppUITests */, 2F6D139328F5F384007C25D6 /* Products */, @@ -92,10 +117,12 @@ 2F6D139428F5F384007C25D6 /* TestApp */ = { isa = PBXGroup; children = ( + 9756D25A2B0316790006B6BD /* Resources */, + 97DD56B32B02F72D00389331 /* LLMLocal */, + 97DD56B42B02F72D00389331 /* LLMOpenAI */, 2FA7382B290ADFAA007ACEB9 /* TestApp.swift */, - 2F55FC542A1B42D20051DF48 /* ContentView.swift */, - 2FD590452A19E41D00153BE4 /* TestAppDelegate.swift */, - 2FD5904E2A19E70000153BE4 /* OnboardingView.swift */, + 9761794F2B034E0400E1046E /* TestAppDelegate.swift */, + 976179532B03501100E1046E /* FeatureFlags.swift */, 2F6D139928F5F386007C25D6 /* Assets.xcassets */, ); path = TestApp; @@ -104,7 +131,8 @@ 2F6D13AF28F5F386007C25D6 /* TestAppUITests */ = { isa = PBXGroup; children = ( - 2F8A431229130A8C005D2B8F /* TestAppUITests.swift */, + 976179512B034F0900E1046E /* TestAppLLMLocalUITests.swift */, + 2F8A431229130A8C005D2B8F /* TestAppLLMOpenAIUITests.swift */, ); path = TestAppUITests; sourceTree = ""; @@ -112,10 +140,59 @@ 2F6D13C228F5F3BE007C25D6 /* Frameworks */ = { isa = PBXGroup; children = ( + 977438092B05709700EC6527 /* libc++.tbd */, ); name = Frameworks; sourceTree = ""; }; + 9756D24A2B0316240006B6BD /* Helpers */ = { + isa = PBXGroup; + children = ( + 9756D24B2B0316240006B6BD /* Binding+Negate.swift */, + 9756D24C2B0316240006B6BD /* StorageKeys.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 9756D24D2B0316240006B6BD /* Onboarding */ = { + isa = PBXGroup; + children = ( + 9756D24E2B0316240006B6BD /* LLMLocalOnboardingDownloadView.swift */, + 9756D24F2B0316240006B6BD /* LLMLocalOnboardingWelcomeView.swift */, + 9756D2502B0316240006B6BD /* LLMLocalOnboardingFlow.swift */, + ); + path = Onboarding; + sourceTree = ""; + }; + 9756D25A2B0316790006B6BD /* Resources */ = { + isa = PBXGroup; + children = ( + 9756D2562B0316740006B6BD /* Localizable.xcstrings */, + 9756D2572B0316740006B6BD /* Localizable.xcstrings.license */, + ); + path = Resources; + sourceTree = ""; + }; + 97DD56B32B02F72D00389331 /* LLMLocal */ = { + isa = PBXGroup; + children = ( + 9756D24A2B0316240006B6BD /* Helpers */, + 9756D24D2B0316240006B6BD /* Onboarding */, + 9756D25C2B0316A30006B6BD /* LLMLocalChatTestView.swift */, + 977E499F2B035563001485D4 /* LLMLocalTestView.swift */, + ); + path = LLMLocal; + sourceTree = ""; + }; + 97DD56B42B02F72D00389331 /* LLMOpenAI */ = { + isa = PBXGroup; + children = ( + 9772D6812B033D5500E62B9D /* LLMOpenAIChatTestView.swift */, + 9772D67F2B03381400E62B9D /* LLMOpenAIOnboardingView.swift */, + ); + path = LLMOpenAI; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -136,9 +213,10 @@ packageProductDependencies = ( 2FD590482A19E4AE00153BE4 /* Spezi */, 2FD5904A2A19E4AE00153BE4 /* XCTSpezi */, - 2FC186042AD52C5B0065EBB2 /* SpeziSpeechSynthesizer */, - 2FC186002AD528830065EBB2 /* SpeziOpenAI */, - 2FC186022AD528830065EBB2 /* SpeziSpeechRecognizer */, + 97DD56BA2B02F7E400389331 /* SpeziChat */, + 97DD56BC2B02F80100389331 /* SpeziLLMOpenAI */, + 9756D25F2B0316D80006B6BD /* SpeziLLMLocal */, + 9756D2612B0316D80006B6BD /* SpeziLLMLocalDownload */, ); productName = Example; productReference = 2F6D139228F5F384007C25D6 /* TestApp.app */; @@ -173,7 +251,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1410; - LastUpgradeCheck = 1410; + LastUpgradeCheck = 1500; TargetAttributes = { 2F6D139128F5F384007C25D6 = { CreatedOnToolsVersion = 14.1; @@ -196,6 +274,7 @@ packageReferences = ( 2FD590442A19E40F00153BE4 /* XCRemoteSwiftPackageReference "Spezi" */, 2FD590502A19E9F000153BE4 /* XCRemoteSwiftPackageReference "XCTestExtensions" */, + 97DD56B92B02F7E400389331 /* XCRemoteSwiftPackageReference "SpeziChat" */, ); productRefGroup = 2F6D139328F5F384007C25D6 /* Products */; projectDirPath = ""; @@ -212,7 +291,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9756D2582B0316740006B6BD /* Localizable.xcstrings in Resources */, 2F6D139A28F5F386007C25D6 /* Assets.xcassets in Resources */, + 9756D2592B0316740006B6BD /* Localizable.xcstrings.license in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -251,10 +332,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2FD590472A19E42000153BE4 /* TestAppDelegate.swift in Sources */, + 9772D6802B03381400E62B9D /* LLMOpenAIOnboardingView.swift in Sources */, + 9756D25E2B0316A30006B6BD /* LLMLocalChatTestView.swift in Sources */, + 9756D2532B0316240006B6BD /* LLMLocalOnboardingDownloadView.swift in Sources */, + 9756D2542B0316240006B6BD /* LLMLocalOnboardingWelcomeView.swift in Sources */, + 977E49A02B035563001485D4 /* LLMLocalTestView.swift in Sources */, + 9756D2522B0316240006B6BD /* StorageKeys.swift in Sources */, + 9772D6822B033D5500E62B9D /* LLMOpenAIChatTestView.swift in Sources */, + 976179542B03501100E1046E /* FeatureFlags.swift in Sources */, + 976179502B034E0400E1046E /* TestAppDelegate.swift in Sources */, + 9756D2552B0316240006B6BD /* LLMLocalOnboardingFlow.swift in Sources */, 2FA7382C290ADFAA007ACEB9 /* TestApp.swift in Sources */, - 2F55FC552A1B42D20051DF48 /* ContentView.swift in Sources */, - 2FD5904F2A19E70000153BE4 /* OnboardingView.swift in Sources */, + 9756D2512B0316240006B6BD /* Binding+Negate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -262,7 +351,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2F8A431329130A8C005D2B8F /* TestAppUITests.swift in Sources */, + 2F8A431329130A8C005D2B8F /* TestAppLLMOpenAIUITests.swift in Sources */, + 976179522B034F0900E1046E /* TestAppLLMLocalUITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -281,6 +371,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -341,6 +432,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -396,6 +488,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -415,10 +508,11 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.speziml.testapp; + PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.spezillm.testapp; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_INTEROP_MODE = objcxx; SWIFT_STRICT_CONCURRENCY = complete; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -430,6 +524,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -449,10 +544,11 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.speziml.testapp; + PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.spezillm.testapp; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_INTEROP_MODE = objcxx; SWIFT_STRICT_CONCURRENCY = complete; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -468,7 +564,7 @@ DEVELOPMENT_TEAM = 637867499T; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.SpeziML.testappuitests; + PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.spezillm.testappuitests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; SWIFT_EMIT_LOC_STRINGS = NO; @@ -487,7 +583,7 @@ DEVELOPMENT_TEAM = 637867499T; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.SpeziML.testappuitests; + PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.spezillm.testappuitests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; SWIFT_EMIT_LOC_STRINGS = NO; @@ -497,119 +593,6 @@ }; name = Release; }; - 2FB07587299DDB6000C0B37F /* Test */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = TEST; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Test; - }; - 2FB07588299DDB6000C0B37F /* Test */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 637867499T; - ENABLE_PREVIEWS = YES; - ENABLE_TESTING_SEARCH_PATHS = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_NSMicrophoneUsageDescription = "The Test Application uses the micophone to test the dication functionality."; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.speziml.testapp; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_STRICT_CONCURRENCY = complete; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Test; - }; - 2FB07589299DDB6000C0B37F /* Test */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 637867499T; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.SpeziML.testappuitests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestApp; - }; - name = Test; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -617,7 +600,6 @@ isa = XCConfigurationList; buildConfigurations = ( 2F6D13B428F5F386007C25D6 /* Debug */, - 2FB07587299DDB6000C0B37F /* Test */, 2F6D13B528F5F386007C25D6 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -627,7 +609,6 @@ isa = XCConfigurationList; buildConfigurations = ( 2F6D13B728F5F386007C25D6 /* Debug */, - 2FB07588299DDB6000C0B37F /* Test */, 2F6D13B828F5F386007C25D6 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -637,7 +618,6 @@ isa = XCConfigurationList; buildConfigurations = ( 2F6D13BD28F5F386007C25D6 /* Debug */, - 2FB07589299DDB6000C0B37F /* Test */, 2F6D13BE28F5F386007C25D6 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -662,21 +642,17 @@ minimumVersion = 0.4.4; }; }; + 97DD56B92B02F7E400389331 /* XCRemoteSwiftPackageReference "SpeziChat" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/StanfordSpezi/SpeziChat"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 0.1.1; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 2FC186002AD528830065EBB2 /* SpeziOpenAI */ = { - isa = XCSwiftPackageProductDependency; - productName = SpeziOpenAI; - }; - 2FC186022AD528830065EBB2 /* SpeziSpeechRecognizer */ = { - isa = XCSwiftPackageProductDependency; - productName = SpeziSpeechRecognizer; - }; - 2FC186042AD52C5B0065EBB2 /* SpeziSpeechSynthesizer */ = { - isa = XCSwiftPackageProductDependency; - productName = SpeziSpeechSynthesizer; - }; 2FD590482A19E4AE00153BE4 /* Spezi */ = { isa = XCSwiftPackageProductDependency; package = 2FD590442A19E40F00153BE4 /* XCRemoteSwiftPackageReference "Spezi" */; @@ -692,6 +668,23 @@ package = 2FD590502A19E9F000153BE4 /* XCRemoteSwiftPackageReference "XCTestExtensions" */; productName = XCTestExtensions; }; + 9756D25F2B0316D80006B6BD /* SpeziLLMLocal */ = { + isa = XCSwiftPackageProductDependency; + productName = SpeziLLMLocal; + }; + 9756D2612B0316D80006B6BD /* SpeziLLMLocalDownload */ = { + isa = XCSwiftPackageProductDependency; + productName = SpeziLLMLocalDownload; + }; + 97DD56BA2B02F7E400389331 /* SpeziChat */ = { + isa = XCSwiftPackageProductDependency; + package = 97DD56B92B02F7E400389331 /* XCRemoteSwiftPackageReference "SpeziChat" */; + productName = SpeziChat; + }; + 97DD56BC2B02F80100389331 /* SpeziLLMOpenAI */ = { + isa = XCSwiftPackageProductDependency; + productName = SpeziLLMOpenAI; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 2F6D138A28F5F384007C25D6 /* Project object */; diff --git a/Tests/UITests/UITests.xcodeproj/project.pbxproj.license b/Tests/UITests/UITests.xcodeproj/project.pbxproj.license index 8d01219..7f16969 100644 --- a/Tests/UITests/UITests.xcodeproj/project.pbxproj.license +++ b/Tests/UITests/UITests.xcodeproj/project.pbxproj.license @@ -1,4 +1,4 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) diff --git a/Tests/UITests/UITests.xcodeproj/project.xcworkspace/contents.xcworkspacedata.license b/Tests/UITests/UITests.xcodeproj/project.xcworkspace/contents.xcworkspacedata.license index 8d01219..7f16969 100644 --- a/Tests/UITests/UITests.xcodeproj/project.xcworkspace/contents.xcworkspacedata.license +++ b/Tests/UITests/UITests.xcodeproj/project.xcworkspace/contents.xcworkspacedata.license @@ -1,4 +1,4 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) diff --git a/Tests/UITests/UITests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist.license b/Tests/UITests/UITests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist.license index 8d01219..7f16969 100644 --- a/Tests/UITests/UITests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist.license +++ b/Tests/UITests/UITests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist.license @@ -1,4 +1,4 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) diff --git a/Tests/UITests/UITests.xcodeproj/xcshareddata/xcschemes/TestApp.xcscheme b/Tests/UITests/UITests.xcodeproj/xcshareddata/xcschemes/TestApp.xcscheme index 06496c0..3c2223e 100644 --- a/Tests/UITests/UITests.xcodeproj/xcshareddata/xcschemes/TestApp.xcscheme +++ b/Tests/UITests/UITests.xcodeproj/xcshareddata/xcschemes/TestApp.xcscheme @@ -1,6 +1,6 @@ + + + + + + + + + + + + @@ -37,7 +79,7 @@ @@ -90,6 +132,12 @@ ReferencedContainer = "container:UITests.xcodeproj"> + + + +

-;gS@7c{m=e6mXv}EyVtb9G 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 Bqxt{< literal 0 HcmV?d00001 diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView.png.license b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView.png.license similarity index 50% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView.png.license rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView.png.license index 9a52dec..9bfad3b 100644 --- a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView.png.license +++ b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView.png.license @@ -1,5 +1,5 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView~dark.png b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView~dark.png new file mode 100644 index 0000000000000000000000000000000000000000..fe02353356f2861a27efb913118c46c317d75b81 GIT binary patch literal 46046 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 literal 0 HcmV?d00001 diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView~dark.png.license b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView~dark.png.license similarity index 50% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView~dark.png.license rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView~dark.png.license index 9a52dec..9bfad3b 100644 --- a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView~dark.png.license +++ b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/ChatView~dark.png.license @@ -1,5 +1,5 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png similarity index 100% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png.license b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png.license similarity index 50% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png.license rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png.license index 9a52dec..9bfad3b 100644 --- a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png.license +++ b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep.png.license @@ -1,5 +1,5 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png similarity index 100% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png.license b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png.license similarity index 50% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png.license rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png.license index 9a52dec..9bfad3b 100644 --- a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png.license +++ b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIAPIKeyOnboardingStep~dark.png.license @@ -1,5 +1,5 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png similarity index 100% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png.license b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png.license similarity index 50% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png.license rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png.license index 9a52dec..9bfad3b 100644 --- a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png.license +++ b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep.png.license @@ -1,5 +1,5 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png similarity index 100% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png.license b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png.license similarity index 50% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png.license rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png.license index 9a52dec..9bfad3b 100644 --- a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png.license +++ b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/Resources/OpenAIModelSelectionOnboardingStep~dark.png.license @@ -1,5 +1,5 @@ -This source file is part of the SpeziML open-source project +This source file is part of the Stanford Spezi open-source project SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/SpeziOpenAI.md b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/SpeziLLMOpenAI.md similarity index 64% rename from Sources/SpeziOpenAI/SpeziOpenAI.docc/SpeziOpenAI.md rename to Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/SpeziLLMOpenAI.md index bbb0244..90d8c18 100644 --- a/Sources/SpeziOpenAI/SpeziOpenAI.docc/SpeziOpenAI.md +++ b/Sources/SpeziLLMOpenAI/SpeziLLMOpenAI.docc/SpeziLLMOpenAI.md @@ -1,4 +1,4 @@ -# ``SpeziOpenAI`` +# ``SpeziLLMOpenAI`` +Interact with Large Language Models (LLMs) from OpenAI. + ## Overview A module that allows you to interact with GPT-based large language models (LLMs) from OpenAI within your Spezi application. @@ -26,19 +28,19 @@ A module that allows you to interact with GPT-based large language models (LLMs) } } @Column { - @Image(source: "ChatView", alt: "Screenshot displaying the Chat View."){ - ``ChatView`` + @Image(source: "ChatView", alt: "Screenshot displaying the usage of the OpenAIModule with the SpeziChat Chat View."){ + ``OpenAIModule`` } } } ## Setup -### 1. Add Spezi ML as a Dependency +### 1. Add Spezi LLM as a Dependency -First, you will need to add the SpeziML Swift package to +First, you will need to add the SpeziLLM Swift package to [your app in Xcode](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app#) or -[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package). When adding the package, select the `SpeziOpenAI` target to add. +[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package). When adding the package, select the `SpeziLLMOpenAI` target to add. ### 2. Register the Open AI Module @@ -49,7 +51,7 @@ In the example, we configure the `OpenAIModule` to use the GPT-4 model with a de ```swift import Spezi -import SpeziOpenAI +import SpeziLLMOpenAI class ExampleDelegate: SpeziAppDelegate { @@ -61,7 +63,7 @@ class ExampleDelegate: SpeziAppDelegate { } ``` -The OpenAIModule injects an ``OpenAIModel`` in the SwiftUI environment to make it accessible thoughout your application. +The OpenAIModule injects an ``OpenAIModel`` in the SwiftUI environment to make it accessible throughout your application. ```swift class ExampleView: View { @@ -76,7 +78,7 @@ class ExampleView: View { > Tip: The choice of model and API key are persisted across application launches. The `apiToken` and `openAIModel` can also be accessed and changed at runtime. -The `SpeziOpenAI` package also provides an `OpenAIAPIKeyOnboardingStep` that can be used to allow the user to provide their API key during the onboarding process instead (see `Examples` below). If using the `OpenAIAPIKeyOnboardingStep`, the `apiToken` property can be omitted here. +The `SpeziLLMOpenAI` package also provides an `OpenAIAPIKeyOnboardingStep` that can be used to allow the user to provide their API key during the onboarding process instead (see `Examples` below). If using the `OpenAIAPIKeyOnboardingStep`, the `apiToken` property can be omitted here. > Tip: You can learn more about a [`Module` in the Spezi documentation](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/module). @@ -85,34 +87,44 @@ The `SpeziOpenAI` package also provides an `OpenAIAPIKeyOnboardingStep` that can ### Creating a Chat Interface In this example, we will create a chat interface that allows the user to converse with the model. Responses from the model will be streamed. +To properly visualize the chat interface with the LLM, the example utilizes the [SpeziChat](https://github.com/StanfordSpezi/SpeziChat) module of the Spezi ecosystem, providing developers with easy to use chat interfaces like the `ChatView`. ```swift -import OpenAI -import SpeziOpenAI +import SpeziChat +import SpeziLLMOpenAI import SwiftUI + struct OpenAIChatView: View { @Environment(OpenAIModel.self) var model - @State private var chat: [Chat] + @State private var chat: Chat = [ + .init(role: .assistant, content: "Assistant Message!") + ] var body: some View { ChatView($chat) - .onChange(of: chat) { _ in - let chatStreamResults = try await model.queryAPI(withChat: chat) - - for try await chatStreamResult in chatStreamResults { - for choice in chatStreamResult.choices { - guard let newContent = choice.delta.content else { - continue - } - - if chat.last?.role == .assistent, let previousContent = chat.last?.content { - chat[chat.count - 1] = Chat( - role: .assistant, - content: previousContent + newContent - ) - } else { - chat.append(Chat(role: .assistent, content: newContent)) + .onChange(of: chat) { _, _ in + Task { + let chatStreamResults = try model.queryAPI(withChat: chat) + + for try await chatStreamResult in chatStreamResults { + for choice in chatStreamResult.choices { + guard let newContent = choice.delta.content else { + continue + } + + if chat.last?.role == .assistant, let previousContent = chat.last?.content { + await MainActor.run { + chat[chat.count - 1] = ChatEntity( + role: .assistant, + content: previousContent + newContent + ) + } + } else { + await MainActor.run { + chat.append(ChatEntity(role: .assistant, content: newContent)) + } + } } } } @@ -129,7 +141,7 @@ First, create a new view to show the onboarding step: ```swift import SpeziOnboarding -import SpeziOpenAI +import SpeziLLMOpenAI import SwiftUI @@ -148,7 +160,7 @@ This view can then be added to the `OnboardingFlow` within the Spezi Template Ap ```swift import SpeziOnboarding -import SpeziOpenAI +import SpeziLLMOpenAI import SwiftUI diff --git a/Sources/SpeziOpenAI/ChatView.swift b/Sources/SpeziOpenAI/ChatView.swift deleted file mode 100644 index 43c9484..0000000 --- a/Sources/SpeziOpenAI/ChatView.swift +++ /dev/null @@ -1,79 +0,0 @@ -// -// This source file is part of the Stanford Spezi open source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -import OpenAI -@_exported import struct OpenAI.Chat -import SwiftUI - - -/// A view to display an OpenAI-based chat view. -public struct ChatView: View { - let messagePlaceholder: String? - - @Binding var chat: [Chat] - @Binding var disableInput: Bool - @State var messageInputHeight: CGFloat = 0 - - - public var body: some View { - ZStack { - VStack { - MessagesView($chat, bottomPadding: $messageInputHeight) - .gesture( - TapGesture().onEnded { - UIApplication.shared.sendAction( - #selector(UIResponder.resignFirstResponder), - to: nil, - from: nil, - for: nil - ) - } - ) - } - VStack { - Spacer() - MessageInputView($chat, messagePlaceholder: messagePlaceholder) - .disabled(disableInput) - .onPreferenceChange(MessageInputViewHeightKey.self) { newValue in - messageInputHeight = newValue - } - } - } - } - - - /// - Parameters: - /// - chat: The chat that should be displayed. - /// - disableInput: Flag if the input view should be disabled. - /// - messagePlaceholder: Placeholder text that should be added in the input field. - public init( - _ chat: Binding<[Chat]>, - disableInput: Binding = .constant(false), - messagePlaceholder: String? = nil - ) { - self._chat = chat - self._disableInput = disableInput - self.messagePlaceholder = messagePlaceholder - } -} - - -struct ChatView_Previews: PreviewProvider { - @State static var chat = [ - Chat(role: .system, content: "System Message!"), - Chat(role: .system, content: "System Message (hidden)!"), - Chat(role: .user, content: "User Message!"), - Chat(role: .assistant, content: "Assistant Message!"), - Chat(role: .function, content: "Function Message!") - ] - - - static var previews: some View { - ChatView($chat) - } -} diff --git a/Sources/SpeziOpenAI/MessageInputView.swift b/Sources/SpeziOpenAI/MessageInputView.swift deleted file mode 100644 index 4464aff..0000000 --- a/Sources/SpeziOpenAI/MessageInputView.swift +++ /dev/null @@ -1,172 +0,0 @@ -// -// This source file is part of the Stanford Spezi open source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -import AVFoundation -import OpenAI -import Speech -import SpeziSpeechRecognizer -import SwiftUI - - -/// Displays a textfield to append a message to a chat. -public struct MessageInputView: View { - private let messagePlaceholder: String - @StateObject private var speechRecognizer = SpeechRecognizer() - - @Binding private var chat: [Chat] - @State private var message: String = "" - @State private var messageViewHeight: CGFloat = 0 - - - public var body: some View { - HStack(alignment: .bottom) { - TextField(messagePlaceholder, text: $message, axis: .vertical) - .accessibilityLabel(String(localized: "MESSAGE_INPUT_TEXTFIELD", bundle: .module)) - .frame(maxWidth: .infinity) - .padding(.horizontal, 12) - .padding(.vertical, 8) - .background { - RoundedRectangle(cornerRadius: 20) - .stroke(Color(UIColor.systemGray2), lineWidth: 0.2) - .background { - RoundedRectangle(cornerRadius: 20) - .fill(.white.opacity(0.2)) - } - .padding(.trailing, -42) - } - .lineLimit(1...5) - Group { - if speechRecognizer.isAvailable && (message.isEmpty || speechRecognizer.isRecording) { - microphoneButton - } else { - sendButton - .disabled(message.isEmpty) - } - } - .frame(minWidth: 33) - } - .padding(.horizontal, 16) - .padding(.vertical, 6) - .background(.thinMaterial) - .background { - GeometryReader { proxy in - Color.clear - .onAppear { - messageViewHeight = proxy.size.height - } - .onChange(of: message) { - messageViewHeight = proxy.size.height - } - } - } - .messageInputViewHeight(messageViewHeight) - } - - private var sendButton: some View { - Button( - action: { - sendMessageButtonPressed() - }, - label: { - Image(systemName: "arrow.up.circle.fill") - .accessibilityLabel(String(localized: "SEND_MESSAGE", bundle: .module)) - .font(.title) - .foregroundColor( - message.isEmpty ? Color(.systemGray5) : .accentColor - ) - } - ) - .offset(x: -2, y: -3) - } - - private var microphoneButton: some View { - Button( - action: { - microphoneButtonPressed() - }, - label: { - Image(systemName: "mic.fill") - .accessibilityLabel(String(localized: "MICROPHONE_BUTTON", bundle: .module)) - .font(.title2) - .foregroundColor( - speechRecognizer.isRecording ? .red : Color(.systemGray2) - ) - .scaleEffect(speechRecognizer.isRecording ? 1.2 : 1.0) - .opacity(speechRecognizer.isRecording ? 0.7 : 1.0) - .animation( - speechRecognizer.isRecording ? .easeInOut(duration: 0.5).repeatForever(autoreverses: true) : .default, - value: speechRecognizer.isRecording - ) - } - ) - .offset(x: -4, y: -6) - } - - - /// - Parameters: - /// - chat: The chat that should be appended to. - /// - messagePlaceholder: Placeholder text that should be added in the input field - public init( - _ chat: Binding<[Chat]>, - messagePlaceholder: String? = nil - ) { - self._chat = chat - self.messagePlaceholder = messagePlaceholder ?? "Message" - } - - - private func sendMessageButtonPressed() { - speechRecognizer.stop() - chat.append(Chat(role: .user, content: message)) - message = "" - } - - private func microphoneButtonPressed() { - if speechRecognizer.isRecording { - speechRecognizer.stop() - } else { - Task { - do { - for try await result in speechRecognizer.start() { - if result.bestTranscription.formattedString.contains("send") { - sendMessageButtonPressed() - } else { - message = result.bestTranscription.formattedString - } - } - } - } - } - } -} - - -struct MessageInputView_Previews: PreviewProvider { - @State static var chat = [ - Chat(role: .system, content: "System Message!"), - Chat(role: .system, content: "System Message (hidden)!"), - Chat(role: .function, content: "Function Message!"), - Chat(role: .user, content: "User Message!"), - Chat(role: .assistant, content: "Assistant Message!") - ] - - - static var previews: some View { - ZStack { - Color(.secondarySystemBackground) - .ignoresSafeArea() - VStack { - MessagesView($chat) - MessageInputView($chat) - } - .onPreferenceChange(MessageInputViewHeightKey.self) { newValue in - print("New MessageView height: \(newValue)") - } - } - } -} diff --git a/Sources/SpeziOpenAI/MessageInputViewHeightKey.swift b/Sources/SpeziOpenAI/MessageInputViewHeightKey.swift deleted file mode 100644 index c4dfadb..0000000 --- a/Sources/SpeziOpenAI/MessageInputViewHeightKey.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// This source file is part of the Stanford Spezi open source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -import SwiftUI - - -struct MessageInputViewHeightKey: PreferenceKey { - static var defaultValue: CGFloat = 0 - - static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { - value = nextValue() - } -} - -extension View { - func messageInputViewHeight(_ value: CGFloat) -> some View { - self.preference(key: MessageInputViewHeightKey.self, value: value) - } -} diff --git a/Sources/SpeziOpenAI/MessageView.swift b/Sources/SpeziOpenAI/MessageView.swift deleted file mode 100644 index fbb1c19..0000000 --- a/Sources/SpeziOpenAI/MessageView.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// This source file is part of the Stanford Spezi open source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -import OpenAI -import SwiftUI - - -/// Displays the content of a `Chat` message in a message bubble -public struct MessageView: View { - public enum Defaults { - public static let hideMessagesWithRoles: Set = [.system, .function] - } - - - private let chat: Chat - private let hideMessagesWithRoles: Set - - - private var foregroundColor: Color { - chat.allignment == .leading ? .primary : .white - } - - private var backgroundColor: Color { - chat.allignment == .leading ? Color(.secondarySystemBackground) : .accentColor - } - - private var multilineTextAllignment: TextAlignment { - chat.allignment == .leading ? .leading : .trailing - } - - private var arrowRotation: Angle { - .degrees(chat.allignment == .leading ? -50 : -130) - } - - private var arrowAllignment: CGFloat { - chat.allignment == .leading ? -7 : 7 - } - - public var body: some View { - if !hideMessagesWithRoles.contains(chat.role), let content = chat.content { - HStack { - if chat.allignment == .trailing { - Spacer(minLength: 32) - } - Text(content) - .multilineTextAlignment(multilineTextAllignment) - .frame(idealWidth: .infinity) - .padding(.horizontal, 10) - .padding(.vertical, 8) - .foregroundColor(foregroundColor) - .background(backgroundColor) - .clipShape(RoundedRectangle(cornerRadius: 16)) - .overlay( - Image(systemName: "arrowtriangle.left.fill") - .accessibilityHidden(true) - .foregroundColor(backgroundColor) - .rotationEffect(arrowRotation) - .offset(x: arrowAllignment), - alignment: chat.allignment == .leading ? .bottomLeading : .bottomTrailing - ) - .padding(.horizontal, 4) - if chat.allignment == .leading { - Spacer(minLength: 32) - } - } - } - } - - - /// - Parameters: - /// - chat: The chat message that should be displayed. - /// - hideMessagesWithRoles: If .system and/or .function messages should be hidden from the chat overview. - public init(_ chat: Chat, hideMessagesWithRoles: Set = MessageView.Defaults.hideMessagesWithRoles) { - self.chat = chat - self.hideMessagesWithRoles = hideMessagesWithRoles - } -} - - -struct MessageView_Previews: PreviewProvider { - static var previews: some View { - ScrollView { - VStack { - MessageView(Chat(role: .system, content: "System Message!"), hideMessagesWithRoles: []) - MessageView(Chat(role: .system, content: "System Message (hidden)!")) - MessageView(Chat(role: .function, content: "Function Message!"), hideMessagesWithRoles: [.system]) - MessageView(Chat(role: .user, content: "User Message!")) - MessageView(Chat(role: .assistant, content: "Assistant Message!")) - } - .padding() - } - } -} diff --git a/Sources/SpeziOpenAI/MessagesView.swift b/Sources/SpeziOpenAI/MessagesView.swift deleted file mode 100644 index 9a78d1b..0000000 --- a/Sources/SpeziOpenAI/MessagesView.swift +++ /dev/null @@ -1,115 +0,0 @@ -// -// This source file is part of the Stanford Spezi open source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -import Combine -import OpenAI -import SwiftUI - - -/// Displays the content of a `Chat` message in a message bubble -public struct MessagesView: View { - private static let bottomSpacerIdentifier = "Bottom Spacer" - - @Binding private var chat: [Chat] - @Binding private var bottomPadding: CGFloat - private let hideMessagesWithRoles: Set - - - private var keyboardPublisher: AnyPublisher { - Publishers - .Merge( - NotificationCenter - .default - .publisher(for: UIResponder.keyboardWillShowNotification) - .map { _ in true }, - NotificationCenter - .default - .publisher(for: UIResponder.keyboardWillHideNotification) - .map { _ in false } - ) - .debounce(for: .seconds(0.1), scheduler: RunLoop.main) - .eraseToAnyPublisher() - } - - - public var body: some View { - ScrollViewReader { scrollViewProxy in - ScrollView { - VStack { - ForEach(Array(chat.enumerated()), id: \.offset) { _, message in - MessageView(message, hideMessagesWithRoles: hideMessagesWithRoles) - } - Spacer() - .frame(height: bottomPadding) - .id(MessagesView.bottomSpacerIdentifier) - } - .padding(.horizontal) - .onAppear { - scrollToBottom(scrollViewProxy) - } - .onChange(of: chat) { - scrollToBottom(scrollViewProxy) - } - .onReceive(keyboardPublisher) { _ in - scrollToBottom(scrollViewProxy) - } - } - } - } - - - /// - Parameters: - /// - chat: The chat messages that should be displayed. - /// - bottomPadding: A fixed bottom padding for the messages view. - /// - hideMessagesWithRoles: The .system and .function roles are hidden from message view - public init( - _ chat: [Chat], - hideMessagesWithRoles: Set = MessageView.Defaults.hideMessagesWithRoles, - bottomPadding: CGFloat = 0 - ) { - self._chat = .constant(chat) - self.hideMessagesWithRoles = hideMessagesWithRoles - self._bottomPadding = .constant(bottomPadding) - } - - /// - Parameters: - /// - chat: The chat messages that should be displayed. - /// - bottomPadding: A bottom padding for the messages view. - /// - hideMessagesWithRoles: Defines which messages should be hidden based on the passed in message roles. - public init( - _ chat: Binding<[Chat]>, - hideMessagesWithRoles: Set = MessageView.Defaults.hideMessagesWithRoles, - bottomPadding: Binding = .constant(0) - ) { - self._chat = chat - self.hideMessagesWithRoles = hideMessagesWithRoles - self._bottomPadding = bottomPadding - } - - - private func scrollToBottom(_ scrollViewProxy: ScrollViewProxy) { - withAnimation(.easeOut) { - scrollViewProxy.scrollTo(MessagesView.bottomSpacerIdentifier) - } - } -} - - -struct MessagesView_Previews: PreviewProvider { - static var previews: some View { - MessagesView( - [ - Chat(role: .system, content: "System Message!"), - Chat(role: .system, content: "System Message (hidden)!"), - Chat(role: .function, content: "Function Message!"), - Chat(role: .user, content: "User Message!"), - Chat(role: .assistant, content: "Assistant Message!") - ] - ) - } -} diff --git a/Sources/SpeziOpenAI/OpenAI+Extensions.swift b/Sources/SpeziOpenAI/OpenAI+Extensions.swift deleted file mode 100644 index a3b7575..0000000 --- a/Sources/SpeziOpenAI/OpenAI+Extensions.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// This source file is part of the Stanford Spezi open source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -import OpenAI - - -extension Chat { - enum Allignment { - case leading - case trailing - } - - - var allignment: Allignment { - switch self.role { - case .user: - return .trailing - default: - return .leading - } - } -} diff --git a/Sources/SpeziOpenAI/Resources/en.lproj/Localizable.strings b/Sources/SpeziOpenAI/Resources/en.lproj/Localizable.strings deleted file mode 100644 index 84e54c0..0000000 --- a/Sources/SpeziOpenAI/Resources/en.lproj/Localizable.strings +++ /dev/null @@ -1,27 +0,0 @@ -// -// This source file is part of the Stanford Spezi open-source project -// -// SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) -// -// SPDX-License-Identifier: MIT -// - -// MARK: OpenAIAPIKeyOnboardingStep -"OPENAI_API_KEY_TITLE" = "OpenAI API Key"; -"OPENAI_API_KEY_SUBTITLE" = "Please enter your OpenAI API key."; -"OPENAI_API_KEY_SUBTITLE_HINT" = "You can create and inspect your OpenAI API keys [in the API keys section of your OpenAI Account](https://platform.openai.com/account/api-keys)."; -"OPENAI_API_KEY_PROMT" = "OpenAI API Key"; -"OPENAI_API_KEY_SAVE_BUTTON" = "Next"; - - -// MARK: OpenAIModelSelectionOnboardingStep -"OPENAI_MODEL_SELECTION_TITLE" = "Select an OpenAI Model"; -"OPENAI_MODEL_SELECTION_SUBTITLE" = "Select the OpenAI model that you want to use. Ensure that your API key has proper access to the model you select."; -"OPENAI_MODEL_SELECTION_DESCRIPTION" = "OpenAI GPT Model"; -"OPENAI_MODEL_SELECTION_SAVE_BUTTON" = "Next"; - - -// MARK: Message Views -"MESSAGE_INPUT_TEXTFIELD" = "Message Input Textfield"; -"MICROPHONE_BUTTON" = "Record Message"; -"SEND_MESSAGE" = "Send Message"; diff --git a/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView.png b/Sources/SpeziOpenAI/SpeziOpenAI.docc/Resources/ChatView.png deleted file mode 100644 index 491658f3e07efa1d9fd6b7f8d48aa0621266ec15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90974 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⊥TkJtZq#dU68UrRf1^#0Zz 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 DL7a~yNo}|# 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