From 62ca9dc7b6d107233286343b5eb756d1741943d0 Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Sat, 30 Sep 2023 08:21:24 -0700 Subject: [PATCH 01/14] copy to llama.cpp as subdir --- examples/llama.swiftui/.gitignore | 1 + .../llama.cpp.swift/LibLlama.swift | 138 ++++++ .../llama.cpp.swift/bridging-header.h | 5 + .../llama.swiftui.xcodeproj/project.pbxproj | 461 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcschemes/xcschememanagement.plist | 14 + .../xcschemes/xcschememanagement.plist | 14 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../Assets.xcassets/Contents.json | 6 + .../llama.swiftui/Models/LlamaState.swift | 49 ++ .../Preview Assets.xcassets/Contents.json | 6 + .../llama.swiftui/Resources/models/.gitignore | 0 .../llama.swiftui/UI/ContentView.swift | 42 ++ .../llama.swiftui/llama_swiftuiApp.swift | 10 + 16 files changed, 785 insertions(+) create mode 100644 examples/llama.swiftui/.gitignore create mode 100644 examples/llama.swiftui/llama.cpp.swift/LibLlama.swift create mode 100644 examples/llama.swiftui/llama.cpp.swift/bridging-header.h create mode 100644 examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj create mode 100644 examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/bach.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/baileyc.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 examples/llama.swiftui/llama.swiftui/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 examples/llama.swiftui/llama.swiftui/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/llama.swiftui/llama.swiftui/Assets.xcassets/Contents.json create mode 100644 examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift create mode 100644 examples/llama.swiftui/llama.swiftui/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 examples/llama.swiftui/llama.swiftui/Resources/models/.gitignore create mode 100644 examples/llama.swiftui/llama.swiftui/UI/ContentView.swift create mode 100644 examples/llama.swiftui/llama.swiftui/llama_swiftuiApp.swift diff --git a/examples/llama.swiftui/.gitignore b/examples/llama.swiftui/.gitignore new file mode 100644 index 0000000000000..4f405ccc66e1a --- /dev/null +++ b/examples/llama.swiftui/.gitignore @@ -0,0 +1 @@ +xcuserdata \ No newline at end of file diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift new file mode 100644 index 0000000000000..03d7c68971a79 --- /dev/null +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -0,0 +1,138 @@ +import Foundation + +// import llama + +enum LlamaError: Error { + case couldNotInitializeContext +} + +actor LlamaContext { + private var model: OpaquePointer + private var context: OpaquePointer + + private var tokens_list: [llama_token] + + init(model: OpaquePointer, context: OpaquePointer) { + self.model = model + self.context = context + self.tokens_list = [] + } + + deinit { + llama_free(context) + llama_free_model(model) + llama_backend_free() + } + + static func createContext(path: String) throws -> LlamaContext { + llama_backend_init(false) + let params = llama_context_default_params() + let model = llama_load_model_from_file(path, params) + guard let model else { + print("Could not load model at \(path)") + throw LlamaError.couldNotInitializeContext + } + + let context = llama_new_context_with_model(model, params) + guard let context else { + print("Could not load context!") + throw LlamaError.couldNotInitializeContext + } + + return LlamaContext(model: model, context: context) + } + + func get_kv_cache() -> Int32 { + return llama_get_kv_cache_token_count(context) + } + + func completion_init(text: String) -> Int32 { + print("attempting to complete \(text)...") + + tokens_list = tokenize(text: text, add_bos: true) + + let max_context_size = llama_n_ctx(context) + let max_tokens_list_size = max_context_size - 4 + + if tokens_list.count > max_tokens_list_size { + print("error: prompt too long (\(tokens_list.count) tokens, max \(max_tokens_list_size)") + } + + for id in tokens_list { + print(token_to_piece(token: id)) + } + + let n_gen = min(32, max_context_size) + return n_gen + } + + func completion_loop() -> String { + var done = false + tokens_list.withUnsafeBufferPointer() { cArray in + let res = llama_eval(context, cArray.baseAddress, Int32(tokens_list.count), llama_get_kv_cache_token_count(context), 8) + if res != 0 { + print("error evaluating llama!") + done = true + return + } + } + if done { + return "" + } + + tokens_list.removeAll() + + var new_token_id: llama_token = 0 + + let logits = llama_get_logits(context) + let n_vocab = llama_n_vocab(context) + + var candidates = Array() + candidates.reserveCapacity(Int(n_vocab)) + + for token_id in 0...n_vocab { + candidates.append(llama_token_data(id: token_id, logit: logits![Int(token_id)], p: 0.0)) + } + candidates.withUnsafeMutableBufferPointer() { buffer in + var candidates_p = llama_token_data_array(data: buffer.baseAddress, size: buffer.count, sorted: false) + + new_token_id = llama_sample_token_greedy(context, &candidates_p) + } + let new_token_str = token_to_piece(token: new_token_id) + print(new_token_str) + tokens_list.append(new_token_id) + return new_token_str + } + + func clear() { + tokens_list.removeAll() + } + + private func tokenize(text: String, add_bos: Bool) -> [llama_token] { + let n_tokens = text.count + (add_bos ? 1 : 0) + let tokens = UnsafeMutablePointer.allocate(capacity: n_tokens) + let tokenCount = llama_tokenize(context, text, Int32(text.count), tokens, Int32(n_tokens), add_bos) + + var swiftTokens: [llama_token] = [] + for i in 0.. String { + let result = UnsafeMutablePointer.allocate(capacity: 8) + result.initialize(repeating: Int8(0), count: 8) + + let _ = llama_token_to_piece(context, token, result, 8) + + let resultStr = String(cString: result) + + result.deallocate() + + return resultStr + } +} diff --git a/examples/llama.swiftui/llama.cpp.swift/bridging-header.h b/examples/llama.swiftui/llama.cpp.swift/bridging-header.h new file mode 100644 index 0000000000000..6cd72c97919ea --- /dev/null +++ b/examples/llama.swiftui/llama.cpp.swift/bridging-header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "llama.h" diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000..f29c647db8e72 --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj @@ -0,0 +1,461 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09B2AC8723900A8AEE9 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_K_QUANTS"; }; }; + 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */; }; + 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A12AC8729100A8AEE9 /* llama.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_K_QUANTS"; }; }; + 542EA0A62AC872A100A8AEE9 /* k_quants.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A52AC872A100A8AEE9 /* k_quants.c */; }; + 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */; }; + 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83782AC328BD0096AF73 /* ContentView.swift */; }; + 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */; }; + 8A1C837E2AC328BE0096AF73 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */; }; + 8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A39BE092AC7601000BFEB40 /* Accelerate.framework */; }; + 8A3F84242AC4C891005E2EE8 /* models in Resources */ = {isa = PBXBuildFile; fileRef = 8A3F84232AC4C891005E2EE8 /* models */; }; + 8A907F332AC7138A006146EA /* LibLlama.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A907F322AC7134E006146EA /* LibLlama.swift */; }; + 8A9F7C4D2AC332EE008AE1EA /* LlamaState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 542EA09B2AC8723900A8AEE9 /* ggml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ggml.c; path = ../../ggml.c; sourceTree = ""; }; + 542EA09C2AC8723900A8AEE9 /* ggml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ggml.h; path = ../../ggml.h; sourceTree = ""; }; + 542EA09E2AC8725700A8AEE9 /* ggml-alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-alloc.h"; path = "../../ggml-alloc.h"; sourceTree = ""; }; + 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ggml-alloc.c"; path = "../../ggml-alloc.c"; sourceTree = ""; }; + 542EA0A12AC8729100A8AEE9 /* llama.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = llama.cpp; path = ../../llama.cpp; sourceTree = ""; }; + 542EA0A22AC8729100A8AEE9 /* llama.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = llama.h; path = ../../llama.h; sourceTree = ""; }; + 542EA0A42AC872A100A8AEE9 /* k_quants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = k_quants.h; path = ../../k_quants.h; sourceTree = ""; }; + 542EA0A52AC872A100A8AEE9 /* k_quants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = k_quants.c; path = ../../k_quants.c; sourceTree = ""; }; + 8A08D20A2AC73B1500FE6CD4 /* bridging-header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "bridging-header.h"; sourceTree = ""; }; + 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = llama.swiftui.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = llama_swiftuiApp.swift; sourceTree = ""; }; + 8A1C83782AC328BD0096AF73 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 8A39BE092AC7601000BFEB40 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; + 8A3F841F2AC4C824005E2EE8 /* llama-2-7b-chat.Q2_K.gguf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "llama-2-7b-chat.Q2_K.gguf"; sourceTree = ""; }; + 8A3F84232AC4C891005E2EE8 /* models */ = {isa = PBXFileReference; lastKnownFileType = folder; name = models; path = llama.swiftui/Resources/models; sourceTree = ""; }; + 8A907F322AC7134E006146EA /* LibLlama.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibLlama.swift; sourceTree = ""; }; + 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LlamaState.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8A1C83702AC328BD0096AF73 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8A08D1F62AC7383900FE6CD4 /* llama.cpp */ = { + isa = PBXGroup; + children = ( + 542EA09B2AC8723900A8AEE9 /* ggml.c */, + 542EA09C2AC8723900A8AEE9 /* ggml.h */, + 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */, + 542EA09E2AC8725700A8AEE9 /* ggml-alloc.h */, + 542EA0A12AC8729100A8AEE9 /* llama.cpp */, + 542EA0A22AC8729100A8AEE9 /* llama.h */, + 542EA0A52AC872A100A8AEE9 /* k_quants.c */, + 542EA0A42AC872A100A8AEE9 /* k_quants.h */, + ); + name = llama.cpp; + sourceTree = ""; + }; + 8A1C836A2AC328BD0096AF73 = { + isa = PBXGroup; + children = ( + 8A08D1F62AC7383900FE6CD4 /* llama.cpp */, + 8A907F312AC7134E006146EA /* llama.cpp.swift */, + 8A3F84232AC4C891005E2EE8 /* models */, + 8A1C83752AC328BD0096AF73 /* llama.swiftui */, + 8A1C83742AC328BD0096AF73 /* Products */, + 8A39BE082AC7601000BFEB40 /* Frameworks */, + ); + sourceTree = ""; + }; + 8A1C83742AC328BD0096AF73 /* Products */ = { + isa = PBXGroup; + children = ( + 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */, + ); + name = Products; + sourceTree = ""; + }; + 8A1C83752AC328BD0096AF73 /* llama.swiftui */ = { + isa = PBXGroup; + children = ( + 8A3F84102AC4BD85005E2EE8 /* Resources */, + 8A9F7C4B2AC332DC008AE1EA /* Models */, + 8A9F7C4A2AC332BF008AE1EA /* UI */, + 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */, + 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */, + 8A1C837C2AC328BE0096AF73 /* Preview Content */, + ); + path = llama.swiftui; + sourceTree = ""; + }; + 8A1C837C2AC328BE0096AF73 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 8A39BE082AC7601000BFEB40 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8A39BE092AC7601000BFEB40 /* Accelerate.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 8A3F84102AC4BD85005E2EE8 /* Resources */ = { + isa = PBXGroup; + children = ( + 8A3F84112AC4BD8C005E2EE8 /* models */, + ); + path = Resources; + sourceTree = ""; + }; + 8A3F84112AC4BD8C005E2EE8 /* models */ = { + isa = PBXGroup; + children = ( + 8A3F841F2AC4C824005E2EE8 /* llama-2-7b-chat.Q2_K.gguf */, + ); + path = models; + sourceTree = ""; + }; + 8A907F312AC7134E006146EA /* llama.cpp.swift */ = { + isa = PBXGroup; + children = ( + 8A08D20A2AC73B1500FE6CD4 /* bridging-header.h */, + 8A907F322AC7134E006146EA /* LibLlama.swift */, + ); + path = llama.cpp.swift; + sourceTree = ""; + }; + 8A9F7C4A2AC332BF008AE1EA /* UI */ = { + isa = PBXGroup; + children = ( + 8A1C83782AC328BD0096AF73 /* ContentView.swift */, + ); + path = UI; + sourceTree = ""; + }; + 8A9F7C4B2AC332DC008AE1EA /* Models */ = { + isa = PBXGroup; + children = ( + 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */, + ); + path = Models; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8A1C83722AC328BD0096AF73 /* llama.swiftui */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8A1C83812AC328BE0096AF73 /* Build configuration list for PBXNativeTarget "llama.swiftui" */; + buildPhases = ( + 8A1C836F2AC328BD0096AF73 /* Sources */, + 8A1C83702AC328BD0096AF73 /* Frameworks */, + 8A1C83712AC328BD0096AF73 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = llama.swiftui; + packageProductDependencies = ( + ); + productName = llama.swiftui; + productReference = 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8A1C836B2AC328BD0096AF73 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + 8A1C83722AC328BD0096AF73 = { + CreatedOnToolsVersion = 15.0; + LastSwiftMigration = 1500; + }; + }; + }; + buildConfigurationList = 8A1C836E2AC328BD0096AF73 /* Build configuration list for PBXProject "llama.swiftui" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 8A1C836A2AC328BD0096AF73; + packageReferences = ( + ); + productRefGroup = 8A1C83742AC328BD0096AF73 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8A1C83722AC328BD0096AF73 /* llama.swiftui */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8A1C83712AC328BD0096AF73 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A3F84242AC4C891005E2EE8 /* models in Resources */, + 8A1C837E2AC328BE0096AF73 /* Preview Assets.xcassets in Resources */, + 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8A1C836F2AC328BD0096AF73 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */, + 8A907F332AC7138A006146EA /* LibLlama.swift in Sources */, + 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */, + 8A9F7C4D2AC332EE008AE1EA /* LlamaState.swift in Sources */, + 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */, + 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */, + 542EA0A62AC872A100A8AEE9 /* k_quants.c in Sources */, + 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 8A1C837F2AC328BE0096AF73 /* Debug */ = { + 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"; + 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; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + 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; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 8A1C83802AC328BE0096AF73 /* Release */ = { + 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"; + 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-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + 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; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8A1C83822AC328BE0096AF73 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"llama.swiftui/Preview Content\""; + DEVELOPMENT_TEAM = STLSG3FG8Q; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + 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"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swiftui"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "llama.cpp.swift/bridging-header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 8A1C83832AC328BE0096AF73 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"llama.swiftui/Preview Content\""; + DEVELOPMENT_TEAM = STLSG3FG8Q; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + 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"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swiftui"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "llama.cpp.swift/bridging-header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8A1C836E2AC328BD0096AF73 /* Build configuration list for PBXProject "llama.swiftui" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A1C837F2AC328BE0096AF73 /* Debug */, + 8A1C83802AC328BE0096AF73 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8A1C83812AC328BE0096AF73 /* Build configuration list for PBXNativeTarget "llama.swiftui" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A1C83822AC328BE0096AF73 /* Debug */, + 8A1C83832AC328BE0096AF73 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8A1C836B2AC328BD0096AF73 /* Project object */; +} diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000000..919434a6254f0 --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000..18d981003d68d --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/bach.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/bach.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000000000..11b4c77ae139e --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/bach.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + llama.swiftui.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/baileyc.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/baileyc.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000000000..11b4c77ae139e --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/baileyc.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + llama.swiftui.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/examples/llama.swiftui/llama.swiftui/Assets.xcassets/AccentColor.colorset/Contents.json b/examples/llama.swiftui/llama.swiftui/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000000..eb87897008164 --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/llama.swiftui/llama.swiftui/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/llama.swiftui/llama.swiftui/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000000..13613e3ee1a93 --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/llama.swiftui/llama.swiftui/Assets.xcassets/Contents.json b/examples/llama.swiftui/llama.swiftui/Assets.xcassets/Contents.json new file mode 100644 index 0000000000000..73c00596a7fca --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift b/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift new file mode 100644 index 0000000000000..1c02bdd26f5d0 --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift @@ -0,0 +1,49 @@ +import Foundation + +@MainActor +class LlamaState: ObservableObject { + @Published var messageLog = "" + + private var llamaContext: LlamaContext? + private var modelUrl: URL? { + Bundle.main.url(forResource: "q8_0", withExtension: "gguf", subdirectory: "models") + // Bundle.main.url(forResource: "llama-2-7b-chat", withExtension: "Q2_K.gguf", subdirectory: "models") + } + init() { + do { + try loadModel() + } catch { + messageLog += "Error!\n" + } + } + + + private func loadModel() throws { + messageLog += "Loading model...\n" + if let modelUrl { + llamaContext = try LlamaContext.createContext(path: modelUrl.path()) + messageLog += "Loaded model \(modelUrl.lastPathComponent)\n" + } else { + messageLog += "Could not locate model\n" + } + } + + func complete(text: String) async { + guard let llamaContext else { + return + } + messageLog += "Attempting to complete text...\n" + let n_ctx = await llamaContext.completion_init(text: text) + messageLog += "context size: \(n_ctx)\n" + messageLog += "\(text)" + + if n_ctx > 0 { + while await llamaContext.get_kv_cache() < n_ctx { + let result = await llamaContext.completion_loop() + messageLog += "\(result)" + } + await llamaContext.clear() + messageLog += "\n\ndone\n" + } + } +} diff --git a/examples/llama.swiftui/llama.swiftui/Preview Content/Preview Assets.xcassets/Contents.json b/examples/llama.swiftui/llama.swiftui/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000000000..73c00596a7fca --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/llama.swiftui/llama.swiftui/Resources/models/.gitignore b/examples/llama.swiftui/llama.swiftui/Resources/models/.gitignore new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/examples/llama.swiftui/llama.swiftui/UI/ContentView.swift b/examples/llama.swiftui/llama.swiftui/UI/ContentView.swift new file mode 100644 index 0000000000000..070ecde78c3e0 --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui/UI/ContentView.swift @@ -0,0 +1,42 @@ +import SwiftUI + +struct ContentView: View { + @StateObject var llamaState = LlamaState() + + @State private var multiLineText = "" + + var body: some View { + VStack { + ScrollView(.vertical) { + Text(llamaState.messageLog) + } + + TextEditor(text: $multiLineText) + .frame(height: 200) + .padding() + .border(Color.gray, width: 0.5) + Button(action: { + sendText() + }) { + Text("Send") + .padding() + .background(Color.blue) + .foregroundColor(.white) + .cornerRadius(8) + } + } + .padding() + } + + func sendText() { + Task { + await llamaState.complete(text: multiLineText) + multiLineText = "" + } + } +} +/* +#Preview { + ContentView() +} +*/ diff --git a/examples/llama.swiftui/llama.swiftui/llama_swiftuiApp.swift b/examples/llama.swiftui/llama.swiftui/llama_swiftuiApp.swift new file mode 100644 index 0000000000000..cccda8a979f5e --- /dev/null +++ b/examples/llama.swiftui/llama.swiftui/llama_swiftuiApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct llama_swiftuiApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} From f632a3c15edf61daef97a84fda1c85956842a54b Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Sun, 1 Oct 2023 10:52:55 -0700 Subject: [PATCH 02/14] attempt enabling metal, fails --- .../llama.swiftui.xcodeproj/project.pbxproj | 30 ++++++++++++++++-- .../Resources/llama_llama/default.metallib | Bin 0 -> 267276 bytes 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 examples/llama.swiftui/llama.swiftui/Resources/llama_llama/default.metallib diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj index f29c647db8e72..ba5ca8d38236d 100644 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj @@ -7,10 +7,13 @@ objects = { /* Begin PBXBuildFile section */ - 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09B2AC8723900A8AEE9 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_K_QUANTS"; }; }; + 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09B2AC8723900A8AEE9 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_METAL -DGGML_USE_K_QUANTS"; }; }; 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */; }; - 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A12AC8729100A8AEE9 /* llama.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_K_QUANTS"; }; }; + 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A12AC8729100A8AEE9 /* llama.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_K_QUANTS -DGGML_USE_METAL"; }; }; 542EA0A62AC872A100A8AEE9 /* k_quants.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A52AC872A100A8AEE9 /* k_quants.c */; }; + 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549479CA2AC9E16000E0F78B /* Metal.framework */; }; + 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */ = {isa = PBXBuildFile; fileRef = 549479C52AC9E0F200E0F78B /* ggml-metal.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -DGGML_SWIFT -DGGML_USE_METAL"; }; }; + 549479D42AC9E86200E0F78B /* llama_llama in Resources */ = {isa = PBXBuildFile; fileRef = 549479D32AC9E86200E0F78B /* llama_llama */; }; 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */; }; 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83782AC328BD0096AF73 /* ContentView.swift */; }; 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */; }; @@ -30,6 +33,12 @@ 542EA0A22AC8729100A8AEE9 /* llama.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = llama.h; path = ../../llama.h; sourceTree = ""; }; 542EA0A42AC872A100A8AEE9 /* k_quants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = k_quants.h; path = ../../k_quants.h; sourceTree = ""; }; 542EA0A52AC872A100A8AEE9 /* k_quants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = k_quants.c; path = ../../k_quants.c; sourceTree = ""; }; + 549479C52AC9E0F200E0F78B /* ggml-metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ggml-metal.m"; path = "../../ggml-metal.m"; sourceTree = ""; }; + 549479C62AC9E0F200E0F78B /* ggml-metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-metal.h"; path = "../../ggml-metal.h"; sourceTree = ""; }; + 549479C82AC9E10B00E0F78B /* ggml-metal.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; name = "ggml-metal.metal"; path = "../../ggml-metal.metal"; sourceTree = ""; }; + 549479CA2AC9E16000E0F78B /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + 549479D02AC9E63A00E0F78B /* default.metallib */ = {isa = PBXFileReference; lastKnownFileType = "archive.metal-library"; path = default.metallib; sourceTree = ""; }; + 549479D32AC9E86200E0F78B /* llama_llama */ = {isa = PBXFileReference; lastKnownFileType = folder; name = llama_llama; path = llama.swiftui/Resources/llama_llama; sourceTree = ""; }; 8A08D20A2AC73B1500FE6CD4 /* bridging-header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "bridging-header.h"; sourceTree = ""; }; 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = llama.swiftui.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = llama_swiftuiApp.swift; sourceTree = ""; }; @@ -48,6 +57,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */, 8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -55,9 +65,20 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 549479D22AC9E79600E0F78B /* llama_llama */ = { + isa = PBXGroup; + children = ( + 549479D02AC9E63A00E0F78B /* default.metallib */, + ); + path = llama_llama; + sourceTree = ""; + }; 8A08D1F62AC7383900FE6CD4 /* llama.cpp */ = { isa = PBXGroup; children = ( + 549479C82AC9E10B00E0F78B /* ggml-metal.metal */, + 549479C62AC9E0F200E0F78B /* ggml-metal.h */, + 549479C52AC9E0F200E0F78B /* ggml-metal.m */, 542EA09B2AC8723900A8AEE9 /* ggml.c */, 542EA09C2AC8723900A8AEE9 /* ggml.h */, 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */, @@ -73,6 +94,7 @@ 8A1C836A2AC328BD0096AF73 = { isa = PBXGroup; children = ( + 549479D32AC9E86200E0F78B /* llama_llama */, 8A08D1F62AC7383900FE6CD4 /* llama.cpp */, 8A907F312AC7134E006146EA /* llama.cpp.swift */, 8A3F84232AC4C891005E2EE8 /* models */, @@ -114,6 +136,7 @@ 8A39BE082AC7601000BFEB40 /* Frameworks */ = { isa = PBXGroup; children = ( + 549479CA2AC9E16000E0F78B /* Metal.framework */, 8A39BE092AC7601000BFEB40 /* Accelerate.framework */, ); name = Frameworks; @@ -122,6 +145,7 @@ 8A3F84102AC4BD85005E2EE8 /* Resources */ = { isa = PBXGroup; children = ( + 549479D22AC9E79600E0F78B /* llama_llama */, 8A3F84112AC4BD8C005E2EE8 /* models */, ); path = Resources; @@ -223,6 +247,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 549479D42AC9E86200E0F78B /* llama_llama in Resources */, 8A3F84242AC4C891005E2EE8 /* models in Resources */, 8A1C837E2AC328BE0096AF73 /* Preview Assets.xcassets in Resources */, 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */, @@ -236,6 +261,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */, 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */, 8A907F332AC7138A006146EA /* LibLlama.swift in Sources */, 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */, diff --git a/examples/llama.swiftui/llama.swiftui/Resources/llama_llama/default.metallib b/examples/llama.swiftui/llama.swiftui/Resources/llama_llama/default.metallib new file mode 100644 index 0000000000000000000000000000000000000000..119ce681bb058d4ca68ecbe2ac904663fd588560 GIT binary patch literal 267276 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�fAe{~v4I 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 Date: Wed, 4 Oct 2023 18:10:16 -0700 Subject: [PATCH 03/14] ggml metal compiles! --- examples/llama.swiftui/README.md | 5 +++++ .../llama.swiftui.xcodeproj/project.pbxproj | 16 ++-------------- .../Resources/llama_llama/default.metallib | Bin 267276 -> 0 bytes ggml-metal.m | 14 ++++++++++---- 4 files changed, 17 insertions(+), 18 deletions(-) create mode 100644 examples/llama.swiftui/README.md delete mode 100644 examples/llama.swiftui/llama.swiftui/Resources/llama_llama/default.metallib diff --git a/examples/llama.swiftui/README.md b/examples/llama.swiftui/README.md new file mode 100644 index 0000000000000..d1356085bf6d5 --- /dev/null +++ b/examples/llama.swiftui/README.md @@ -0,0 +1,5 @@ +# llama.swiftui + +Local inference of llama.cpp on an iPhone. +So far I only tested with starcoder 1B model, but it can most likely handle 7B models as well. + diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj index ba5ca8d38236d..3af90cf2a1bbb 100644 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj @@ -7,13 +7,13 @@ objects = { /* Begin PBXBuildFile section */ + 542378792ACE3F3500834A7B /* ggml-metal.metal in Resources */ = {isa = PBXBuildFile; fileRef = 549479C82AC9E10B00E0F78B /* ggml-metal.metal */; }; 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09B2AC8723900A8AEE9 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_METAL -DGGML_USE_K_QUANTS"; }; }; 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */; }; 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A12AC8729100A8AEE9 /* llama.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_K_QUANTS -DGGML_USE_METAL"; }; }; 542EA0A62AC872A100A8AEE9 /* k_quants.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A52AC872A100A8AEE9 /* k_quants.c */; }; 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549479CA2AC9E16000E0F78B /* Metal.framework */; }; 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */ = {isa = PBXBuildFile; fileRef = 549479C52AC9E0F200E0F78B /* ggml-metal.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -DGGML_SWIFT -DGGML_USE_METAL"; }; }; - 549479D42AC9E86200E0F78B /* llama_llama in Resources */ = {isa = PBXBuildFile; fileRef = 549479D32AC9E86200E0F78B /* llama_llama */; }; 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */; }; 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83782AC328BD0096AF73 /* ContentView.swift */; }; 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */; }; @@ -37,8 +37,6 @@ 549479C62AC9E0F200E0F78B /* ggml-metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-metal.h"; path = "../../ggml-metal.h"; sourceTree = ""; }; 549479C82AC9E10B00E0F78B /* ggml-metal.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; name = "ggml-metal.metal"; path = "../../ggml-metal.metal"; sourceTree = ""; }; 549479CA2AC9E16000E0F78B /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; - 549479D02AC9E63A00E0F78B /* default.metallib */ = {isa = PBXFileReference; lastKnownFileType = "archive.metal-library"; path = default.metallib; sourceTree = ""; }; - 549479D32AC9E86200E0F78B /* llama_llama */ = {isa = PBXFileReference; lastKnownFileType = folder; name = llama_llama; path = llama.swiftui/Resources/llama_llama; sourceTree = ""; }; 8A08D20A2AC73B1500FE6CD4 /* bridging-header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "bridging-header.h"; sourceTree = ""; }; 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = llama.swiftui.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = llama_swiftuiApp.swift; sourceTree = ""; }; @@ -65,14 +63,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 549479D22AC9E79600E0F78B /* llama_llama */ = { - isa = PBXGroup; - children = ( - 549479D02AC9E63A00E0F78B /* default.metallib */, - ); - path = llama_llama; - sourceTree = ""; - }; 8A08D1F62AC7383900FE6CD4 /* llama.cpp */ = { isa = PBXGroup; children = ( @@ -94,7 +84,6 @@ 8A1C836A2AC328BD0096AF73 = { isa = PBXGroup; children = ( - 549479D32AC9E86200E0F78B /* llama_llama */, 8A08D1F62AC7383900FE6CD4 /* llama.cpp */, 8A907F312AC7134E006146EA /* llama.cpp.swift */, 8A3F84232AC4C891005E2EE8 /* models */, @@ -145,7 +134,6 @@ 8A3F84102AC4BD85005E2EE8 /* Resources */ = { isa = PBXGroup; children = ( - 549479D22AC9E79600E0F78B /* llama_llama */, 8A3F84112AC4BD8C005E2EE8 /* models */, ); path = Resources; @@ -247,7 +235,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 549479D42AC9E86200E0F78B /* llama_llama in Resources */, + 542378792ACE3F3500834A7B /* ggml-metal.metal in Resources */, 8A3F84242AC4C891005E2EE8 /* models in Resources */, 8A1C837E2AC328BE0096AF73 /* Preview Assets.xcassets in Resources */, 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */, diff --git a/examples/llama.swiftui/llama.swiftui/Resources/llama_llama/default.metallib b/examples/llama.swiftui/llama.swiftui/Resources/llama_llama/default.metallib deleted file mode 100644 index 119ce681bb058d4ca68ecbe2ac904663fd588560..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 267276 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�fAe{~v4I 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 Date: Wed, 4 Oct 2023 18:34:58 -0700 Subject: [PATCH 04/14] Update README.md --- examples/llama.swiftui/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/llama.swiftui/README.md b/examples/llama.swiftui/README.md index d1356085bf6d5..44049dc81c5b3 100644 --- a/examples/llama.swiftui/README.md +++ b/examples/llama.swiftui/README.md @@ -3,3 +3,5 @@ Local inference of llama.cpp on an iPhone. So far I only tested with starcoder 1B model, but it can most likely handle 7B models as well. +https://github.com/bachittle/llama.cpp/assets/39804642/e290827a-4edb-4093-9642-2a5e399ec545 + From ae6beb4696c5948fc7cc31841cef861a88aa2a94 Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Thu, 5 Oct 2023 17:03:49 -0700 Subject: [PATCH 05/14] initial conversion to new format, utf8 errors? --- .../llama.cpp.swift/LibLlama.swift | 89 ++++++++++++------- .../llama.swiftui/Models/LlamaState.swift | 15 ++-- 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift index 03d7c68971a79..4a2da49823a8d 100644 --- a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -9,13 +9,18 @@ enum LlamaError: Error { actor LlamaContext { private var model: OpaquePointer private var context: OpaquePointer - + private var batch: llama_batch private var tokens_list: [llama_token] + var n_len: Int32 = 32 + var n_cur: Int32 = 0 + var n_decode: Int32 = 0 + init(model: OpaquePointer, context: OpaquePointer) { self.model = model self.context = context self.tokens_list = [] + self.batch = llama_batch_init(512, 0) } deinit { @@ -26,14 +31,15 @@ actor LlamaContext { static func createContext(path: String) throws -> LlamaContext { llama_backend_init(false) - let params = llama_context_default_params() - let model = llama_load_model_from_file(path, params) + let model_params = llama_model_default_params() + + let model = llama_load_model_from_file(path, model_params) guard let model else { print("Could not load model at \(path)") throw LlamaError.couldNotInitializeContext } - - let context = llama_new_context_with_model(model, params) + let ctx_params = llama_context_default_params() + let context = llama_new_context_with_model(model, ctx_params) guard let context else { print("Could not load context!") throw LlamaError.couldNotInitializeContext @@ -42,50 +48,52 @@ actor LlamaContext { return LlamaContext(model: model, context: context) } - func get_kv_cache() -> Int32 { - return llama_get_kv_cache_token_count(context) + func get_n_tokens() -> Int32 { + return batch.n_tokens; } - func completion_init(text: String) -> Int32 { + func completion_init(text: String) { print("attempting to complete \(text)...") tokens_list = tokenize(text: text, add_bos: true) - let max_context_size = llama_n_ctx(context) - let max_tokens_list_size = max_context_size - 4 + let n_ctx = llama_n_ctx(context) + let n_kv_req = tokens_list.count + (Int(n_len) - tokens_list.count) - if tokens_list.count > max_tokens_list_size { - print("error: prompt too long (\(tokens_list.count) tokens, max \(max_tokens_list_size)") + print("\n n_len = \(n_len), n_ctx = \(n_ctx), n_kv_req = \(n_kv_req)") + + if n_kv_req > n_ctx { + print("error: n_kv_req > n_ctx, the required KV cache size is not big enough") } for id in tokens_list { print(token_to_piece(token: id)) } - let n_gen = min(32, max_context_size) - return n_gen - } - - func completion_loop() -> String { - var done = false - tokens_list.withUnsafeBufferPointer() { cArray in - let res = llama_eval(context, cArray.baseAddress, Int32(tokens_list.count), llama_get_kv_cache_token_count(context), 8) - if res != 0 { - print("error evaluating llama!") - done = true - return - } - } - if done { - return "" + // batch = llama_batch_init(512, 0) // done in init() + batch.n_tokens = Int32(tokens_list.count) + + for i1 in 0...batch.n_tokens { + let i = Int(i1) + batch.token[i] = tokens_list[i] + batch.pos[i] = i1 + batch.seq_id[i] = 0 + batch.logits[i] = 0 // false } + batch.logits[Int(batch.n_tokens) - 1] = 1 // true - tokens_list.removeAll() + if llama_decode(context, batch) != 0 { + print("llama_decode() failed") + } + n_cur = batch.n_tokens + } + + func completion_loop() -> String { var new_token_id: llama_token = 0 - let logits = llama_get_logits(context) let n_vocab = llama_n_vocab(context) + let logits = llama_get_logits(context) var candidates = Array() candidates.reserveCapacity(Int(n_vocab)) @@ -98,9 +106,30 @@ actor LlamaContext { new_token_id = llama_sample_token_greedy(context, &candidates_p) } + + if new_token_id == llama_token_eos(context) || n_cur == n_len { + print("\n") + return "" + } + let new_token_str = token_to_piece(token: new_token_id) print(new_token_str) tokens_list.append(new_token_id) + + batch.token[Int(batch.n_tokens)] = new_token_id + batch.pos[Int(batch.n_tokens)] = n_cur + batch.seq_id[Int(batch.n_tokens)] = 0 + batch.logits[Int(batch.n_tokens)] = 1 // true + + batch.n_tokens += 1 + n_decode += 1 + + n_cur += 1 + + if llama_decode(context, batch) != 0 { + print("failed to evaluate llama!") + } + return new_token_str } diff --git a/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift b/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift index 1c02bdd26f5d0..ed1573f4e2d49 100644 --- a/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift +++ b/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift @@ -33,17 +33,14 @@ class LlamaState: ObservableObject { return } messageLog += "Attempting to complete text...\n" - let n_ctx = await llamaContext.completion_init(text: text) - messageLog += "context size: \(n_ctx)\n" + await llamaContext.completion_init(text: text) messageLog += "\(text)" - if n_ctx > 0 { - while await llamaContext.get_kv_cache() < n_ctx { - let result = await llamaContext.completion_loop() - messageLog += "\(result)" - } - await llamaContext.clear() - messageLog += "\n\ndone\n" + while await llamaContext.n_cur <= llamaContext.n_len { + let result = await llamaContext.completion_loop() + messageLog += "\(result)" } + await llamaContext.clear() + messageLog += "\n\ndone\n" } } From 090383b21b466ca7be9afa98cf5c28cd82e53c69 Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Thu, 5 Oct 2023 17:53:42 -0700 Subject: [PATCH 06/14] bug fixes, but now has an invalid memory access :( --- .../llama.swiftui/llama.cpp.swift/LibLlama.swift | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift index 4a2da49823a8d..86bdb85870b5e 100644 --- a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -38,7 +38,12 @@ actor LlamaContext { print("Could not load model at \(path)") throw LlamaError.couldNotInitializeContext } - let ctx_params = llama_context_default_params() + var ctx_params = llama_context_default_params() + ctx_params.seed = 1234 + ctx_params.n_ctx = 2048 + ctx_params.n_threads = 8 + ctx_params.n_threads_batch = 8 + let context = llama_new_context_with_model(model, ctx_params) guard let context else { print("Could not load context!") @@ -53,7 +58,7 @@ actor LlamaContext { } func completion_init(text: String) { - print("attempting to complete \(text)...") + print("attempting to complete \"\(text)\"") tokens_list = tokenize(text: text, add_bos: true) @@ -73,7 +78,7 @@ actor LlamaContext { // batch = llama_batch_init(512, 0) // done in init() batch.n_tokens = Int32(tokens_list.count) - for i1 in 0...batch.n_tokens { + for i1 in 0...batch.n_tokens-1 { let i = Int(i1) batch.token[i] = tokens_list[i] batch.pos[i] = i1 @@ -140,7 +145,7 @@ actor LlamaContext { private func tokenize(text: String, add_bos: Bool) -> [llama_token] { let n_tokens = text.count + (add_bos ? 1 : 0) let tokens = UnsafeMutablePointer.allocate(capacity: n_tokens) - let tokenCount = llama_tokenize(context, text, Int32(text.count), tokens, Int32(n_tokens), add_bos) + let tokenCount = llama_tokenize(model, text, Int32(text.count), tokens, Int32(n_tokens), add_bos) var swiftTokens: [llama_token] = [] for i in 0...allocate(capacity: 8) result.initialize(repeating: Int8(0), count: 8) - let _ = llama_token_to_piece(context, token, result, 8) + let _ = llama_token_to_piece(model, token, result, 8) let resultStr = String(cString: result) From cd618549dd15564b03f20a56481949ba7549cb63 Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Fri, 17 Nov 2023 19:43:30 -0800 Subject: [PATCH 07/14] added O3, now has insufficient memory access --- .../llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj index 3af90cf2a1bbb..cdf59caea9b3b 100644 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj @@ -8,12 +8,12 @@ /* Begin PBXBuildFile section */ 542378792ACE3F3500834A7B /* ggml-metal.metal in Resources */ = {isa = PBXBuildFile; fileRef = 549479C82AC9E10B00E0F78B /* ggml-metal.metal */; }; - 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09B2AC8723900A8AEE9 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_METAL -DGGML_USE_K_QUANTS"; }; }; + 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09B2AC8723900A8AEE9 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_METAL -DGGML_USE_K_QUANTS -O3"; }; }; 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */; }; - 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A12AC8729100A8AEE9 /* llama.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_K_QUANTS -DGGML_USE_METAL"; }; }; + 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A12AC8729100A8AEE9 /* llama.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_K_QUANTS -DGGML_USE_METAL -O3"; }; }; 542EA0A62AC872A100A8AEE9 /* k_quants.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A52AC872A100A8AEE9 /* k_quants.c */; }; 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549479CA2AC9E16000E0F78B /* Metal.framework */; }; - 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */ = {isa = PBXBuildFile; fileRef = 549479C52AC9E0F200E0F78B /* ggml-metal.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -DGGML_SWIFT -DGGML_USE_METAL"; }; }; + 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */ = {isa = PBXBuildFile; fileRef = 549479C52AC9E0F200E0F78B /* ggml-metal.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -DGGML_SWIFT -DGGML_USE_METAL -O3"; }; }; 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */; }; 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83782AC328BD0096AF73 /* ContentView.swift */; }; 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */; }; From ce31d955f3fc31cf680cf3d69c56663cf2e447cc Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Fri, 17 Nov 2023 20:01:41 -0800 Subject: [PATCH 08/14] begin sync with master --- examples/llama.swiftui/llama.cpp.swift/LibLlama.swift | 2 +- .../llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift index 86bdb85870b5e..e6c4f04f71f05 100644 --- a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -20,7 +20,7 @@ actor LlamaContext { self.model = model self.context = context self.tokens_list = [] - self.batch = llama_batch_init(512, 0) + self.batch = llama_batch_init(512, 0, 1) } deinit { diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj index cdf59caea9b3b..74fc682ed0875 100644 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj @@ -406,7 +406,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swiftui"; + PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swift"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "llama.cpp.swift/bridging-header.h"; @@ -439,7 +439,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swiftui"; + PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swift"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "llama.cpp.swift/bridging-header.h"; From a22264ac0be7403406b13f711dd88857c6370249 Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Tue, 21 Nov 2023 18:28:19 -0800 Subject: [PATCH 09/14] update to match latest code, new errors --- .../llama.cpp.swift/LibLlama.swift | 8 +++++--- .../llama.swiftui.xcodeproj/project.pbxproj | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift index e6c4f04f71f05..1fae81006237f 100644 --- a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -82,7 +82,7 @@ actor LlamaContext { let i = Int(i1) batch.token[i] = tokens_list[i] batch.pos[i] = i1 - batch.seq_id[i] = 0 + batch.seq_id[Int(i)]![0] = 0 batch.logits[i] = 0 // false } batch.logits[Int(batch.n_tokens) - 1] = 1 // true @@ -100,6 +100,8 @@ actor LlamaContext { let n_vocab = llama_n_vocab(context) let logits = llama_get_logits(context) + print("n_vocab: \(n_vocab)") + var candidates = Array() candidates.reserveCapacity(Int(n_vocab)) @@ -123,7 +125,7 @@ actor LlamaContext { batch.token[Int(batch.n_tokens)] = new_token_id batch.pos[Int(batch.n_tokens)] = n_cur - batch.seq_id[Int(batch.n_tokens)] = 0 + batch.seq_id[Int(batch.n_tokens)]![0] = 0 batch.logits[Int(batch.n_tokens)] = 1 // true batch.n_tokens += 1 @@ -145,7 +147,7 @@ actor LlamaContext { private func tokenize(text: String, add_bos: Bool) -> [llama_token] { let n_tokens = text.count + (add_bos ? 1 : 0) let tokens = UnsafeMutablePointer.allocate(capacity: n_tokens) - let tokenCount = llama_tokenize(model, text, Int32(text.count), tokens, Int32(n_tokens), add_bos) + let tokenCount = llama_tokenize(model, text, Int32(text.count), tokens, Int32(n_tokens), add_bos, false) var swiftTokens: [llama_token] = [] for i in 0.. Date: Tue, 21 Nov 2023 18:47:05 -0800 Subject: [PATCH 10/14] fixed it! --- .../llama.cpp.swift/LibLlama.swift | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift index 1fae81006237f..8050e03996a72 100644 --- a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -82,8 +82,9 @@ actor LlamaContext { let i = Int(i1) batch.token[i] = tokens_list[i] batch.pos[i] = i1 + batch.n_seq_id[Int(i)] = 1 batch.seq_id[Int(i)]![0] = 0 - batch.logits[i] = 0 // false + batch.logits[i] = 0 } batch.logits[Int(batch.n_tokens) - 1] = 1 // true @@ -97,11 +98,9 @@ actor LlamaContext { func completion_loop() -> String { var new_token_id: llama_token = 0 - let n_vocab = llama_n_vocab(context) - let logits = llama_get_logits(context) - - print("n_vocab: \(n_vocab)") - + let n_vocab = llama_n_vocab(model) + let logits = llama_get_logits_ith(context, batch.n_tokens - 1) + var candidates = Array() candidates.reserveCapacity(Int(n_vocab)) @@ -121,14 +120,17 @@ actor LlamaContext { let new_token_str = token_to_piece(token: new_token_id) print(new_token_str) - tokens_list.append(new_token_id) + // tokens_list.append(new_token_id) + + batch.n_tokens = 0 batch.token[Int(batch.n_tokens)] = new_token_id batch.pos[Int(batch.n_tokens)] = n_cur + batch.n_seq_id[Int(batch.n_tokens)] = 1 batch.seq_id[Int(batch.n_tokens)]![0] = 0 batch.logits[Int(batch.n_tokens)] = 1 // true - batch.n_tokens += 1 + n_decode += 1 n_cur += 1 From 1e65f66c30669f19bad9bec7807053b2c2d43763 Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Wed, 22 Nov 2023 16:35:17 -0800 Subject: [PATCH 11/14] fix for loop conditionals, increase result size --- examples/llama.swiftui/llama.cpp.swift/LibLlama.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift index 8050e03996a72..7f8b0f0b6d04a 100644 --- a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -12,7 +12,7 @@ actor LlamaContext { private var batch: llama_batch private var tokens_list: [llama_token] - var n_len: Int32 = 32 + var n_len: Int32 = 512 var n_cur: Int32 = 0 var n_decode: Int32 = 0 @@ -78,7 +78,7 @@ actor LlamaContext { // batch = llama_batch_init(512, 0) // done in init() batch.n_tokens = Int32(tokens_list.count) - for i1 in 0...batch.n_tokens-1 { + for i1 in 0..() candidates.reserveCapacity(Int(n_vocab)) - for token_id in 0...n_vocab { + for token_id in 0.. Date: Sat, 25 Nov 2023 13:16:14 -0500 Subject: [PATCH 12/14] fix current workflow errors --- examples/llama.swiftui/.gitignore | 2 +- examples/llama.swiftui/README.md | 4 +- .../llama.cpp.swift/LibLlama.swift | 80 +- .../llama.swiftui.xcodeproj/project.pbxproj | 896 +++++++++--------- .../xcshareddata/IDEWorkspaceChecks.plist | 4 +- .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 14 - .../llama.swiftui/Models/LlamaState.swift | 7 +- .../llama.swiftui/UI/ContentView.swift | 8 +- 9 files changed, 500 insertions(+), 529 deletions(-) delete mode 100644 examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/bach.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/baileyc.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/examples/llama.swiftui/.gitignore b/examples/llama.swiftui/.gitignore index 4f405ccc66e1a..9bce6af399ba9 100644 --- a/examples/llama.swiftui/.gitignore +++ b/examples/llama.swiftui/.gitignore @@ -1 +1 @@ -xcuserdata \ No newline at end of file +xcuserdata diff --git a/examples/llama.swiftui/README.md b/examples/llama.swiftui/README.md index 44049dc81c5b3..fa68e6ed8e34d 100644 --- a/examples/llama.swiftui/README.md +++ b/examples/llama.swiftui/README.md @@ -1,7 +1,7 @@ # llama.swiftui -Local inference of llama.cpp on an iPhone. -So far I only tested with starcoder 1B model, but it can most likely handle 7B models as well. +Local inference of llama.cpp on an iPhone. +So far I only tested with starcoder 1B model, but it can most likely handle 7B models as well. https://github.com/bachittle/llama.cpp/assets/39804642/e290827a-4edb-4093-9642-2a5e399ec545 diff --git a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift index 7f8b0f0b6d04a..aaef09611bc90 100644 --- a/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift +++ b/examples/llama.swiftui/llama.cpp.swift/LibLlama.swift @@ -11,28 +11,28 @@ actor LlamaContext { private var context: OpaquePointer private var batch: llama_batch private var tokens_list: [llama_token] - + var n_len: Int32 = 512 var n_cur: Int32 = 0 var n_decode: Int32 = 0 - + init(model: OpaquePointer, context: OpaquePointer) { self.model = model self.context = context self.tokens_list = [] self.batch = llama_batch_init(512, 0, 1) } - + deinit { llama_free(context) llama_free_model(model) llama_backend_free() } - + static func createContext(path: String) throws -> LlamaContext { llama_backend_init(false) let model_params = llama_model_default_params() - + let model = llama_load_model_from_file(path, model_params) guard let model else { print("Could not load model at \(path)") @@ -43,41 +43,41 @@ actor LlamaContext { ctx_params.n_ctx = 2048 ctx_params.n_threads = 8 ctx_params.n_threads_batch = 8 - + let context = llama_new_context_with_model(model, ctx_params) guard let context else { print("Could not load context!") throw LlamaError.couldNotInitializeContext } - + return LlamaContext(model: model, context: context) } - + func get_n_tokens() -> Int32 { return batch.n_tokens; } - + func completion_init(text: String) { print("attempting to complete \"\(text)\"") - + tokens_list = tokenize(text: text, add_bos: true) - + let n_ctx = llama_n_ctx(context) let n_kv_req = tokens_list.count + (Int(n_len) - tokens_list.count) - + print("\n n_len = \(n_len), n_ctx = \(n_ctx), n_kv_req = \(n_kv_req)") if n_kv_req > n_ctx { print("error: n_kv_req > n_ctx, the required KV cache size is not big enough") } - + for id in tokens_list { print(token_to_piece(token: id)) } - + // batch = llama_batch_init(512, 0) // done in init() batch.n_tokens = Int32(tokens_list.count) - + for i1 in 0.. String { var new_token_id: llama_token = 0 - + let n_vocab = llama_n_vocab(model) let logits = llama_get_logits_ith(context, batch.n_tokens - 1) - + var candidates = Array() candidates.reserveCapacity(Int(n_vocab)) - + for token_id in 0.. [llama_token] { let n_tokens = text.count + (add_bos ? 1 : 0) let tokens = UnsafeMutablePointer.allocate(capacity: n_tokens) let tokenCount = llama_tokenize(model, text, Int32(text.count), tokens, Int32(n_tokens), add_bos, false) - + var swiftTokens: [llama_token] = [] for i in 0.. String { let result = UnsafeMutablePointer.allocate(capacity: 8) result.initialize(repeating: Int8(0), count: 8) - + let _ = llama_token_to_piece(model, token, result, 8) - + let resultStr = String(cString: result) - + result.deallocate() - + return resultStr } } diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj index 0093e0f00fd48..bc1fd15cebb31 100644 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.pbxproj @@ -1,481 +1,481 @@ // !$*UTF8*$! { - archiveVersion = 1; - classes = { - }; - objectVersion = 56; - objects = { + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { /* Begin PBXBuildFile section */ - 542376082B0D9BFB008E6A1C /* ggml-quants.c in Sources */ = {isa = PBXBuildFile; fileRef = 542376072B0D9BFB008E6A1C /* ggml-quants.c */; }; - 5423760B2B0D9C4B008E6A1C /* ggml-backend.c in Sources */ = {isa = PBXBuildFile; fileRef = 5423760A2B0D9C4B008E6A1C /* ggml-backend.c */; }; - 542378792ACE3F3500834A7B /* ggml-metal.metal in Resources */ = {isa = PBXBuildFile; fileRef = 549479C82AC9E10B00E0F78B /* ggml-metal.metal */; }; - 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09B2AC8723900A8AEE9 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_METAL -DGGML_USE_K_QUANTS -O3"; }; }; - 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */; }; - 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A12AC8729100A8AEE9 /* llama.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_K_QUANTS -DGGML_USE_METAL -O3"; }; }; - 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549479CA2AC9E16000E0F78B /* Metal.framework */; }; - 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */ = {isa = PBXBuildFile; fileRef = 549479C52AC9E0F200E0F78B /* ggml-metal.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -DGGML_SWIFT -DGGML_USE_METAL -O3"; }; }; - 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */; }; - 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83782AC328BD0096AF73 /* ContentView.swift */; }; - 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */; }; - 8A1C837E2AC328BE0096AF73 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */; }; - 8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A39BE092AC7601000BFEB40 /* Accelerate.framework */; }; - 8A3F84242AC4C891005E2EE8 /* models in Resources */ = {isa = PBXBuildFile; fileRef = 8A3F84232AC4C891005E2EE8 /* models */; }; - 8A907F332AC7138A006146EA /* LibLlama.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A907F322AC7134E006146EA /* LibLlama.swift */; }; - 8A9F7C4D2AC332EE008AE1EA /* LlamaState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */; }; + 542376082B0D9BFB008E6A1C /* ggml-quants.c in Sources */ = {isa = PBXBuildFile; fileRef = 542376072B0D9BFB008E6A1C /* ggml-quants.c */; }; + 5423760B2B0D9C4B008E6A1C /* ggml-backend.c in Sources */ = {isa = PBXBuildFile; fileRef = 5423760A2B0D9C4B008E6A1C /* ggml-backend.c */; }; + 542378792ACE3F3500834A7B /* ggml-metal.metal in Resources */ = {isa = PBXBuildFile; fileRef = 549479C82AC9E10B00E0F78B /* ggml-metal.metal */; }; + 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09B2AC8723900A8AEE9 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -DGGML_USE_METAL -DGGML_USE_K_QUANTS -O3"; }; }; + 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */; }; + 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 542EA0A12AC8729100A8AEE9 /* llama.cpp */; settings = {COMPILER_FLAGS = "-DGGML_USE_K_QUANTS -DGGML_USE_METAL -O3"; }; }; + 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549479CA2AC9E16000E0F78B /* Metal.framework */; }; + 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */ = {isa = PBXBuildFile; fileRef = 549479C52AC9E0F200E0F78B /* ggml-metal.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -DGGML_SWIFT -DGGML_USE_METAL -O3"; }; }; + 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */; }; + 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1C83782AC328BD0096AF73 /* ContentView.swift */; }; + 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */; }; + 8A1C837E2AC328BE0096AF73 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */; }; + 8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A39BE092AC7601000BFEB40 /* Accelerate.framework */; }; + 8A3F84242AC4C891005E2EE8 /* models in Resources */ = {isa = PBXBuildFile; fileRef = 8A3F84232AC4C891005E2EE8 /* models */; }; + 8A907F332AC7138A006146EA /* LibLlama.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A907F322AC7134E006146EA /* LibLlama.swift */; }; + 8A9F7C4D2AC332EE008AE1EA /* LlamaState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 542376062B0D9BEA008E6A1C /* ggml-quants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-quants.h"; path = "../../ggml-quants.h"; sourceTree = ""; }; - 542376072B0D9BFB008E6A1C /* ggml-quants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ggml-quants.c"; path = "../../ggml-quants.c"; sourceTree = ""; }; - 542376092B0D9C40008E6A1C /* ggml-backend.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "ggml-backend.h"; path = "../../ggml-backend.h"; sourceTree = ""; }; - 5423760A2B0D9C4B008E6A1C /* ggml-backend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ggml-backend.c"; path = "../../ggml-backend.c"; sourceTree = ""; }; - 542EA09B2AC8723900A8AEE9 /* ggml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ggml.c; path = ../../ggml.c; sourceTree = ""; }; - 542EA09C2AC8723900A8AEE9 /* ggml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ggml.h; path = ../../ggml.h; sourceTree = ""; }; - 542EA09E2AC8725700A8AEE9 /* ggml-alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-alloc.h"; path = "../../ggml-alloc.h"; sourceTree = ""; }; - 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ggml-alloc.c"; path = "../../ggml-alloc.c"; sourceTree = ""; }; - 542EA0A12AC8729100A8AEE9 /* llama.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = llama.cpp; path = ../../llama.cpp; sourceTree = ""; }; - 542EA0A22AC8729100A8AEE9 /* llama.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = llama.h; path = ../../llama.h; sourceTree = ""; }; - 549479C52AC9E0F200E0F78B /* ggml-metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ggml-metal.m"; path = "../../ggml-metal.m"; sourceTree = ""; }; - 549479C62AC9E0F200E0F78B /* ggml-metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-metal.h"; path = "../../ggml-metal.h"; sourceTree = ""; }; - 549479C82AC9E10B00E0F78B /* ggml-metal.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; name = "ggml-metal.metal"; path = "../../ggml-metal.metal"; sourceTree = ""; }; - 549479CA2AC9E16000E0F78B /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; - 8A08D20A2AC73B1500FE6CD4 /* bridging-header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "bridging-header.h"; sourceTree = ""; }; - 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = llama.swiftui.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = llama_swiftuiApp.swift; sourceTree = ""; }; - 8A1C83782AC328BD0096AF73 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; - 8A39BE092AC7601000BFEB40 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; - 8A3F841F2AC4C824005E2EE8 /* llama-2-7b-chat.Q2_K.gguf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "llama-2-7b-chat.Q2_K.gguf"; sourceTree = ""; }; - 8A3F84232AC4C891005E2EE8 /* models */ = {isa = PBXFileReference; lastKnownFileType = folder; name = models; path = llama.swiftui/Resources/models; sourceTree = ""; }; - 8A907F322AC7134E006146EA /* LibLlama.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibLlama.swift; sourceTree = ""; }; - 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LlamaState.swift; sourceTree = ""; }; + 542376062B0D9BEA008E6A1C /* ggml-quants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-quants.h"; path = "../../ggml-quants.h"; sourceTree = ""; }; + 542376072B0D9BFB008E6A1C /* ggml-quants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ggml-quants.c"; path = "../../ggml-quants.c"; sourceTree = ""; }; + 542376092B0D9C40008E6A1C /* ggml-backend.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "ggml-backend.h"; path = "../../ggml-backend.h"; sourceTree = ""; }; + 5423760A2B0D9C4B008E6A1C /* ggml-backend.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ggml-backend.c"; path = "../../ggml-backend.c"; sourceTree = ""; }; + 542EA09B2AC8723900A8AEE9 /* ggml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ggml.c; path = ../../ggml.c; sourceTree = ""; }; + 542EA09C2AC8723900A8AEE9 /* ggml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ggml.h; path = ../../ggml.h; sourceTree = ""; }; + 542EA09E2AC8725700A8AEE9 /* ggml-alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-alloc.h"; path = "../../ggml-alloc.h"; sourceTree = ""; }; + 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ggml-alloc.c"; path = "../../ggml-alloc.c"; sourceTree = ""; }; + 542EA0A12AC8729100A8AEE9 /* llama.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = llama.cpp; path = ../../llama.cpp; sourceTree = ""; }; + 542EA0A22AC8729100A8AEE9 /* llama.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = llama.h; path = ../../llama.h; sourceTree = ""; }; + 549479C52AC9E0F200E0F78B /* ggml-metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ggml-metal.m"; path = "../../ggml-metal.m"; sourceTree = ""; }; + 549479C62AC9E0F200E0F78B /* ggml-metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ggml-metal.h"; path = "../../ggml-metal.h"; sourceTree = ""; }; + 549479C82AC9E10B00E0F78B /* ggml-metal.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; name = "ggml-metal.metal"; path = "../../ggml-metal.metal"; sourceTree = ""; }; + 549479CA2AC9E16000E0F78B /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + 8A08D20A2AC73B1500FE6CD4 /* bridging-header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "bridging-header.h"; sourceTree = ""; }; + 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = llama.swiftui.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = llama_swiftuiApp.swift; sourceTree = ""; }; + 8A1C83782AC328BD0096AF73 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 8A39BE092AC7601000BFEB40 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; + 8A3F841F2AC4C824005E2EE8 /* llama-2-7b-chat.Q2_K.gguf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "llama-2-7b-chat.Q2_K.gguf"; sourceTree = ""; }; + 8A3F84232AC4C891005E2EE8 /* models */ = {isa = PBXFileReference; lastKnownFileType = folder; name = models; path = llama.swiftui/Resources/models; sourceTree = ""; }; + 8A907F322AC7134E006146EA /* LibLlama.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibLlama.swift; sourceTree = ""; }; + 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LlamaState.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 8A1C83702AC328BD0096AF73 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */, - 8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 8A1C83702AC328BD0096AF73 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */, + 8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 8A08D1F62AC7383900FE6CD4 /* llama.cpp */ = { - isa = PBXGroup; - children = ( - 5423760A2B0D9C4B008E6A1C /* ggml-backend.c */, - 542376092B0D9C40008E6A1C /* ggml-backend.h */, - 542376062B0D9BEA008E6A1C /* ggml-quants.h */, - 542376072B0D9BFB008E6A1C /* ggml-quants.c */, - 549479C82AC9E10B00E0F78B /* ggml-metal.metal */, - 549479C62AC9E0F200E0F78B /* ggml-metal.h */, - 549479C52AC9E0F200E0F78B /* ggml-metal.m */, - 542EA09B2AC8723900A8AEE9 /* ggml.c */, - 542EA09C2AC8723900A8AEE9 /* ggml.h */, - 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */, - 542EA09E2AC8725700A8AEE9 /* ggml-alloc.h */, - 542EA0A12AC8729100A8AEE9 /* llama.cpp */, - 542EA0A22AC8729100A8AEE9 /* llama.h */, - ); - name = llama.cpp; - sourceTree = ""; - }; - 8A1C836A2AC328BD0096AF73 = { - isa = PBXGroup; - children = ( - 8A08D1F62AC7383900FE6CD4 /* llama.cpp */, - 8A907F312AC7134E006146EA /* llama.cpp.swift */, - 8A3F84232AC4C891005E2EE8 /* models */, - 8A1C83752AC328BD0096AF73 /* llama.swiftui */, - 8A1C83742AC328BD0096AF73 /* Products */, - 8A39BE082AC7601000BFEB40 /* Frameworks */, - ); - sourceTree = ""; - }; - 8A1C83742AC328BD0096AF73 /* Products */ = { - isa = PBXGroup; - children = ( - 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */, - ); - name = Products; - sourceTree = ""; - }; - 8A1C83752AC328BD0096AF73 /* llama.swiftui */ = { - isa = PBXGroup; - children = ( - 8A3F84102AC4BD85005E2EE8 /* Resources */, - 8A9F7C4B2AC332DC008AE1EA /* Models */, - 8A9F7C4A2AC332BF008AE1EA /* UI */, - 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */, - 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */, - 8A1C837C2AC328BE0096AF73 /* Preview Content */, - ); - path = llama.swiftui; - sourceTree = ""; - }; - 8A1C837C2AC328BE0096AF73 /* Preview Content */ = { - isa = PBXGroup; - children = ( - 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */, - ); - path = "Preview Content"; - sourceTree = ""; - }; - 8A39BE082AC7601000BFEB40 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 549479CA2AC9E16000E0F78B /* Metal.framework */, - 8A39BE092AC7601000BFEB40 /* Accelerate.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 8A3F84102AC4BD85005E2EE8 /* Resources */ = { - isa = PBXGroup; - children = ( - 8A3F84112AC4BD8C005E2EE8 /* models */, - ); - path = Resources; - sourceTree = ""; - }; - 8A3F84112AC4BD8C005E2EE8 /* models */ = { - isa = PBXGroup; - children = ( - 8A3F841F2AC4C824005E2EE8 /* llama-2-7b-chat.Q2_K.gguf */, - ); - path = models; - sourceTree = ""; - }; - 8A907F312AC7134E006146EA /* llama.cpp.swift */ = { - isa = PBXGroup; - children = ( - 8A08D20A2AC73B1500FE6CD4 /* bridging-header.h */, - 8A907F322AC7134E006146EA /* LibLlama.swift */, - ); - path = llama.cpp.swift; - sourceTree = ""; - }; - 8A9F7C4A2AC332BF008AE1EA /* UI */ = { - isa = PBXGroup; - children = ( - 8A1C83782AC328BD0096AF73 /* ContentView.swift */, - ); - path = UI; - sourceTree = ""; - }; - 8A9F7C4B2AC332DC008AE1EA /* Models */ = { - isa = PBXGroup; - children = ( - 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */, - ); - path = Models; - sourceTree = ""; - }; + 8A08D1F62AC7383900FE6CD4 /* llama.cpp */ = { + isa = PBXGroup; + children = ( + 5423760A2B0D9C4B008E6A1C /* ggml-backend.c */, + 542376092B0D9C40008E6A1C /* ggml-backend.h */, + 542376062B0D9BEA008E6A1C /* ggml-quants.h */, + 542376072B0D9BFB008E6A1C /* ggml-quants.c */, + 549479C82AC9E10B00E0F78B /* ggml-metal.metal */, + 549479C62AC9E0F200E0F78B /* ggml-metal.h */, + 549479C52AC9E0F200E0F78B /* ggml-metal.m */, + 542EA09B2AC8723900A8AEE9 /* ggml.c */, + 542EA09C2AC8723900A8AEE9 /* ggml.h */, + 542EA09F2AC8725700A8AEE9 /* ggml-alloc.c */, + 542EA09E2AC8725700A8AEE9 /* ggml-alloc.h */, + 542EA0A12AC8729100A8AEE9 /* llama.cpp */, + 542EA0A22AC8729100A8AEE9 /* llama.h */, + ); + name = llama.cpp; + sourceTree = ""; + }; + 8A1C836A2AC328BD0096AF73 = { + isa = PBXGroup; + children = ( + 8A08D1F62AC7383900FE6CD4 /* llama.cpp */, + 8A907F312AC7134E006146EA /* llama.cpp.swift */, + 8A3F84232AC4C891005E2EE8 /* models */, + 8A1C83752AC328BD0096AF73 /* llama.swiftui */, + 8A1C83742AC328BD0096AF73 /* Products */, + 8A39BE082AC7601000BFEB40 /* Frameworks */, + ); + sourceTree = ""; + }; + 8A1C83742AC328BD0096AF73 /* Products */ = { + isa = PBXGroup; + children = ( + 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */, + ); + name = Products; + sourceTree = ""; + }; + 8A1C83752AC328BD0096AF73 /* llama.swiftui */ = { + isa = PBXGroup; + children = ( + 8A3F84102AC4BD85005E2EE8 /* Resources */, + 8A9F7C4B2AC332DC008AE1EA /* Models */, + 8A9F7C4A2AC332BF008AE1EA /* UI */, + 8A1C83762AC328BD0096AF73 /* llama_swiftuiApp.swift */, + 8A1C837A2AC328BE0096AF73 /* Assets.xcassets */, + 8A1C837C2AC328BE0096AF73 /* Preview Content */, + ); + path = llama.swiftui; + sourceTree = ""; + }; + 8A1C837C2AC328BE0096AF73 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 8A1C837D2AC328BE0096AF73 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 8A39BE082AC7601000BFEB40 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 549479CA2AC9E16000E0F78B /* Metal.framework */, + 8A39BE092AC7601000BFEB40 /* Accelerate.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 8A3F84102AC4BD85005E2EE8 /* Resources */ = { + isa = PBXGroup; + children = ( + 8A3F84112AC4BD8C005E2EE8 /* models */, + ); + path = Resources; + sourceTree = ""; + }; + 8A3F84112AC4BD8C005E2EE8 /* models */ = { + isa = PBXGroup; + children = ( + 8A3F841F2AC4C824005E2EE8 /* llama-2-7b-chat.Q2_K.gguf */, + ); + path = models; + sourceTree = ""; + }; + 8A907F312AC7134E006146EA /* llama.cpp.swift */ = { + isa = PBXGroup; + children = ( + 8A08D20A2AC73B1500FE6CD4 /* bridging-header.h */, + 8A907F322AC7134E006146EA /* LibLlama.swift */, + ); + path = llama.cpp.swift; + sourceTree = ""; + }; + 8A9F7C4A2AC332BF008AE1EA /* UI */ = { + isa = PBXGroup; + children = ( + 8A1C83782AC328BD0096AF73 /* ContentView.swift */, + ); + path = UI; + sourceTree = ""; + }; + 8A9F7C4B2AC332DC008AE1EA /* Models */ = { + isa = PBXGroup; + children = ( + 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */, + ); + path = Models; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 8A1C83722AC328BD0096AF73 /* llama.swiftui */ = { - isa = PBXNativeTarget; - buildConfigurationList = 8A1C83812AC328BE0096AF73 /* Build configuration list for PBXNativeTarget "llama.swiftui" */; - buildPhases = ( - 8A1C836F2AC328BD0096AF73 /* Sources */, - 8A1C83702AC328BD0096AF73 /* Frameworks */, - 8A1C83712AC328BD0096AF73 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = llama.swiftui; - packageProductDependencies = ( - ); - productName = llama.swiftui; - productReference = 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */; - productType = "com.apple.product-type.application"; - }; + 8A1C83722AC328BD0096AF73 /* llama.swiftui */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8A1C83812AC328BE0096AF73 /* Build configuration list for PBXNativeTarget "llama.swiftui" */; + buildPhases = ( + 8A1C836F2AC328BD0096AF73 /* Sources */, + 8A1C83702AC328BD0096AF73 /* Frameworks */, + 8A1C83712AC328BD0096AF73 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = llama.swiftui; + packageProductDependencies = ( + ); + productName = llama.swiftui; + productReference = 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 8A1C836B2AC328BD0096AF73 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1500; - LastUpgradeCheck = 1500; - TargetAttributes = { - 8A1C83722AC328BD0096AF73 = { - CreatedOnToolsVersion = 15.0; - LastSwiftMigration = 1500; - }; - }; - }; - buildConfigurationList = 8A1C836E2AC328BD0096AF73 /* Build configuration list for PBXProject "llama.swiftui" */; - compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 8A1C836A2AC328BD0096AF73; - packageReferences = ( - ); - productRefGroup = 8A1C83742AC328BD0096AF73 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 8A1C83722AC328BD0096AF73 /* llama.swiftui */, - ); - }; + 8A1C836B2AC328BD0096AF73 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + 8A1C83722AC328BD0096AF73 = { + CreatedOnToolsVersion = 15.0; + LastSwiftMigration = 1500; + }; + }; + }; + buildConfigurationList = 8A1C836E2AC328BD0096AF73 /* Build configuration list for PBXProject "llama.swiftui" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 8A1C836A2AC328BD0096AF73; + packageReferences = ( + ); + productRefGroup = 8A1C83742AC328BD0096AF73 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8A1C83722AC328BD0096AF73 /* llama.swiftui */, + ); + }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 8A1C83712AC328BD0096AF73 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 542378792ACE3F3500834A7B /* ggml-metal.metal in Resources */, - 8A3F84242AC4C891005E2EE8 /* models in Resources */, - 8A1C837E2AC328BE0096AF73 /* Preview Assets.xcassets in Resources */, - 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 8A1C83712AC328BD0096AF73 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 542378792ACE3F3500834A7B /* ggml-metal.metal in Resources */, + 8A3F84242AC4C891005E2EE8 /* models in Resources */, + 8A1C837E2AC328BE0096AF73 /* Preview Assets.xcassets in Resources */, + 8A1C837B2AC328BE0096AF73 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 8A1C836F2AC328BD0096AF73 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 542376082B0D9BFB008E6A1C /* ggml-quants.c in Sources */, - 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */, - 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */, - 8A907F332AC7138A006146EA /* LibLlama.swift in Sources */, - 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */, - 8A9F7C4D2AC332EE008AE1EA /* LlamaState.swift in Sources */, - 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */, - 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */, - 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */, - 5423760B2B0D9C4B008E6A1C /* ggml-backend.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 8A1C836F2AC328BD0096AF73 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 542376082B0D9BFB008E6A1C /* ggml-quants.c in Sources */, + 549479CD2AC9E42A00E0F78B /* ggml-metal.m in Sources */, + 542EA09D2AC8723900A8AEE9 /* ggml.c in Sources */, + 8A907F332AC7138A006146EA /* LibLlama.swift in Sources */, + 542EA0A32AC8729100A8AEE9 /* llama.cpp in Sources */, + 8A9F7C4D2AC332EE008AE1EA /* LlamaState.swift in Sources */, + 8A1C83792AC328BD0096AF73 /* ContentView.swift in Sources */, + 8A1C83772AC328BD0096AF73 /* llama_swiftuiApp.swift in Sources */, + 542EA0A02AC8725700A8AEE9 /* ggml-alloc.c in Sources */, + 5423760B2B0D9C4B008E6A1C /* ggml-backend.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - 8A1C837F2AC328BE0096AF73 /* Debug */ = { - 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"; - 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; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - 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; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 8A1C83802AC328BE0096AF73 /* Release */ = { - 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"; - 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-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_NO_COMMON_BLOCKS = YES; - 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; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 8A1C83822AC328BE0096AF73 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"llama.swiftui/Preview Content\""; - DEVELOPMENT_TEAM = STLSG3FG8Q; - ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - 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"; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swift"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "llama.cpp.swift/bridging-header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 8A1C83832AC328BE0096AF73 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"llama.swiftui/Preview Content\""; - DEVELOPMENT_TEAM = STLSG3FG8Q; - ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - 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"; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swift"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "llama.cpp.swift/bridging-header.h"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; + 8A1C837F2AC328BE0096AF73 /* Debug */ = { + 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"; + 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; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + 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; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 8A1C83802AC328BE0096AF73 /* Release */ = { + 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"; + 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-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + 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; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8A1C83822AC328BE0096AF73 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"llama.swiftui/Preview Content\""; + DEVELOPMENT_TEAM = STLSG3FG8Q; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + 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"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swift"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "llama.cpp.swift/bridging-header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 8A1C83832AC328BE0096AF73 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"llama.swiftui/Preview Content\""; + DEVELOPMENT_TEAM = STLSG3FG8Q; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + 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"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.bachittle.llama-swift"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "llama.cpp.swift/bridging-header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 8A1C836E2AC328BD0096AF73 /* Build configuration list for PBXProject "llama.swiftui" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 8A1C837F2AC328BE0096AF73 /* Debug */, - 8A1C83802AC328BE0096AF73 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 8A1C83812AC328BE0096AF73 /* Build configuration list for PBXNativeTarget "llama.swiftui" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 8A1C83822AC328BE0096AF73 /* Debug */, - 8A1C83832AC328BE0096AF73 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; + 8A1C836E2AC328BD0096AF73 /* Build configuration list for PBXProject "llama.swiftui" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A1C837F2AC328BE0096AF73 /* Debug */, + 8A1C83802AC328BE0096AF73 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8A1C83812AC328BE0096AF73 /* Build configuration list for PBXNativeTarget "llama.swiftui" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8A1C83822AC328BE0096AF73 /* Debug */, + 8A1C83832AC328BE0096AF73 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ - }; - rootObject = 8A1C836B2AC328BD0096AF73 /* Project object */; + }; + rootObject = 8A1C836B2AC328BD0096AF73 /* Project object */; } diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist index 18d981003d68d..3d4c1e55259fe 100644 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ b/examples/llama.swiftui/llama.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -2,7 +2,7 @@ - IDEDidComputeMac32BitWarning - + IDEDidComputeMac32BitWarning + diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/bach.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/bach.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 11b4c77ae139e..0000000000000 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/bach.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - llama.swiftui.xcscheme_^#shared#^_ - - orderHint - 0 - - - - diff --git a/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/baileyc.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/baileyc.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 11b4c77ae139e..0000000000000 --- a/examples/llama.swiftui/llama.swiftui.xcodeproj/xcuserdata/baileyc.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - llama.swiftui.xcscheme_^#shared#^_ - - orderHint - 0 - - - - diff --git a/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift b/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift index ed1573f4e2d49..babc60cdcc9dc 100644 --- a/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift +++ b/examples/llama.swiftui/llama.swiftui/Models/LlamaState.swift @@ -3,7 +3,7 @@ import Foundation @MainActor class LlamaState: ObservableObject { @Published var messageLog = "" - + private var llamaContext: LlamaContext? private var modelUrl: URL? { Bundle.main.url(forResource: "q8_0", withExtension: "gguf", subdirectory: "models") @@ -17,7 +17,6 @@ class LlamaState: ObservableObject { } } - private func loadModel() throws { messageLog += "Loading model...\n" if let modelUrl { @@ -27,7 +26,7 @@ class LlamaState: ObservableObject { messageLog += "Could not locate model\n" } } - + func complete(text: String) async { guard let llamaContext else { return @@ -35,7 +34,7 @@ class LlamaState: ObservableObject { messageLog += "Attempting to complete text...\n" await llamaContext.completion_init(text: text) messageLog += "\(text)" - + while await llamaContext.n_cur <= llamaContext.n_len { let result = await llamaContext.completion_loop() messageLog += "\(result)" diff --git a/examples/llama.swiftui/llama.swiftui/UI/ContentView.swift b/examples/llama.swiftui/llama.swiftui/UI/ContentView.swift index 070ecde78c3e0..0bd16a806d10f 100644 --- a/examples/llama.swiftui/llama.swiftui/UI/ContentView.swift +++ b/examples/llama.swiftui/llama.swiftui/UI/ContentView.swift @@ -2,15 +2,15 @@ import SwiftUI struct ContentView: View { @StateObject var llamaState = LlamaState() - + @State private var multiLineText = "" - + var body: some View { VStack { ScrollView(.vertical) { Text(llamaState.messageLog) } - + TextEditor(text: $multiLineText) .frame(height: 200) .padding() @@ -27,7 +27,7 @@ struct ContentView: View { } .padding() } - + func sendText() { Task { await llamaState.complete(text: multiLineText) From 256478a97e51d3106a4535630dd165502d6db25d Mon Sep 17 00:00:00 2001 From: Bailey Chittle Date: Sun, 26 Nov 2023 11:17:08 +0000 Subject: [PATCH 13/14] attempt a llama.swiftui workflow --- .github/workflows/build.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc295d52d2d5d..bf31652677940 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -497,6 +497,16 @@ jobs: with: path: | cudart-llama-bin-win-cu${{ matrix.cuda }}-x64.zip + ios-xcode-build: + runs-on: macos-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Build Xcode project + run: xcodebuild -project examples/llama.swiftui/llama.swiftui.xcodeproj -scheme llama.swiftui -sdk iphoneos CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= -destination 'generic/platform=iOS' build + # freeBSD-latest: # runs-on: macos-12 From af05571d23434fe310b9b2649e6ebea5a8fef0c8 Mon Sep 17 00:00:00 2001 From: Bailey Chittle <39804642+bachittle@users.noreply.github.com> Date: Mon, 27 Nov 2023 09:32:54 -0500 Subject: [PATCH 14/14] Update .github/workflows/build.yml Co-authored-by: Georgi Gerganov --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf31652677940..22be233e6d11e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -497,6 +497,7 @@ jobs: with: path: | cudart-llama-bin-win-cu${{ matrix.cuda }}-x64.zip + ios-xcode-build: runs-on: macos-latest