From 0907d7ff1ece5de218fd1385dc98cf0f1839e05a Mon Sep 17 00:00:00 2001 From: David Koski <46639364+davidkoski@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:15:22 -0700 Subject: [PATCH] fix #113 -- fall back to local files if offline (#133) --- .../StableDiffusionExample/ContentView.swift | 25 ++++-- Libraries/LLM/Load.swift | 9 +++ Libraries/LLM/Tokenizer.swift | 21 ++++- .../xcschemes/StableDiffusionExample.xcscheme | 78 +++++++++++++++++++ 4 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 mlx-swift-examples.xcodeproj/xcshareddata/xcschemes/StableDiffusionExample.xcscheme diff --git a/Applications/StableDiffusionExample/ContentView.swift b/Applications/StableDiffusionExample/ContentView.swift index 8eae4f5c..6f62448f 100644 --- a/Applications/StableDiffusionExample/ContentView.swift +++ b/Applications/StableDiffusionExample/ContentView.swift @@ -146,12 +146,25 @@ actor ModelFactory { switch loadState { case .idle: let task = Task { - try await configuration.download { progress in - if progress.fractionCompleted < 0.99 { - reportProgress( - .init( - title: "Download", current: progress.fractionCompleted * 100, - limit: 100)) + do { + try await configuration.download { progress in + if progress.fractionCompleted < 0.99 { + reportProgress( + .init( + title: "Download", current: progress.fractionCompleted * 100, + limit: 100)) + } + } + } catch { + let nserror = error as NSError + if nserror.domain == NSURLErrorDomain + && nserror.code == NSURLErrorNotConnectedToInternet + { + // Internet connection appears to be offline -- fall back to loading from + // the local directory + reportProgress(.init(title: "Offline", current: 100, limit: 100)) + } else { + throw error } } diff --git a/Libraries/LLM/Load.swift b/Libraries/LLM/Load.swift index b704c868..33f99a96 100644 --- a/Libraries/LLM/Load.swift +++ b/Libraries/LLM/Load.swift @@ -31,6 +31,15 @@ func prepareModelDirectory( // an authorizationRequired means (typically) that the named repo doesn't exist on // on the server so retry with local only configuration return configuration.modelDirectory(hub: hub) + } catch { + let nserror = error as NSError + if nserror.domain == NSURLErrorDomain && nserror.code == NSURLErrorNotConnectedToInternet { + // Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." + // fall back to the local directory + return configuration.modelDirectory(hub: hub) + } else { + throw error + } } } diff --git a/Libraries/LLM/Tokenizer.swift b/Libraries/LLM/Tokenizer.swift index d28dbda7..a21da89f 100644 --- a/Libraries/LLM/Tokenizer.swift +++ b/Libraries/LLM/Tokenizer.swift @@ -21,8 +21,25 @@ func loadTokenizerConfig(configuration: ModelConfiguration, hub: HubApi) async t switch configuration.id { case .id(let id): - config = LanguageModelConfigurationFromHub( - modelName: configuration.tokenizerId ?? id, hubApi: hub) + do { + // the load can fail (async when we try to use it) + let loaded = LanguageModelConfigurationFromHub( + modelName: configuration.tokenizerId ?? id, hubApi: hub) + _ = try await loaded.tokenizerConfig + config = loaded + } catch { + let nserror = error as NSError + if nserror.domain == NSURLErrorDomain + && nserror.code == NSURLErrorNotConnectedToInternet + { + // Internet connection appears to be offline -- fall back to loading from + // the local directory + config = LanguageModelConfigurationFromHub( + modelFolder: configuration.modelDirectory(hub: hub), hubApi: hub) + } else { + throw error + } + } case .directory(let directory): config = LanguageModelConfigurationFromHub(modelFolder: directory, hubApi: hub) } diff --git a/mlx-swift-examples.xcodeproj/xcshareddata/xcschemes/StableDiffusionExample.xcscheme b/mlx-swift-examples.xcodeproj/xcshareddata/xcschemes/StableDiffusionExample.xcscheme new file mode 100644 index 00000000..a241f89d --- /dev/null +++ b/mlx-swift-examples.xcodeproj/xcshareddata/xcschemes/StableDiffusionExample.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +