Skip to content

Commit

Permalink
Merge pull request #156 from allenai/playground-access-for-unsupporte…
Browse files Browse the repository at this point in the history
…d-devices

Playground access for unsupported devices
  • Loading branch information
jonryser authored Feb 5, 2025
2 parents 4363a27 + 26df7fa commit 79e16f3
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 51 deletions.
8 changes: 6 additions & 2 deletions OLMoE.swift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@
CODE_SIGN_ENTITLEMENTS = OLMoE.swift/OLMoE_swift.entitlements;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "-";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "${BUNDLE_VERSION}";
DEVELOPMENT_ASSET_PATHS = "\"OLMoE.swift/Preview Content\"";
Expand Down Expand Up @@ -417,7 +418,8 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand All @@ -434,6 +436,7 @@
CODE_SIGN_ENTITLEMENTS = OLMoE.swift/OLMoE_swift.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "${BUNDLE_VERSION}";
DEVELOPMENT_ASSET_PATHS = "\"OLMoE.swift/Preview Content\"";
Expand Down Expand Up @@ -463,7 +466,8 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down
20 changes: 20 additions & 0 deletions OLMoE.swift/Assets.xcassets/Warning.colorset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"red" : "0xFF",
"green" : "0xA3",
"blue" : "0x1C"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
20 changes: 16 additions & 4 deletions OLMoE.swift/Constants/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
},
"%lld%%" : {

},
"⚠️ Running on AI2's servers - not on your device" : {

},
"allenai.org" : {

Expand All @@ -28,9 +31,6 @@
},
"Delete history?" : {

},
"Device Not Supported" : {

},
"Download Model" : {

Expand Down Expand Up @@ -62,17 +62,29 @@
},
"Flush Model" : {

},
"However, you can try using OLMoE at the Ai2 Playground. This option does not download the model file to your device, but instead submits user input to a hosted version of OLMoE to remotely generate responses." : {

},
"Model is ready to use!" : {

},
"OLMoE can run locally on iPhone 15 Pro/Max, iPhone 16 models, iPad Pro 4th Gen and newer, or iPad Air 5th Gen and newer." : {

},
"On-Device OLMoE Not Available" : {

},
"Proceed Anyway" : {

},
"Proceed With Mocked Model" : {

},
"This app requires a device with at least 8GB of RAM." : {
"This device does not have the 8GB physical RAM required to run OLMoE locally." : {

},
"Try OLMoE at the Ai2 Playground" : {

},
"Welcome" : {
Expand Down
1 change: 1 addition & 0 deletions OLMoE.swift/Extensions/DeviceSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func isDeviceSupported() -> Bool {
"iPad14,5", "iPad14,6", // iPad Pro 12.9" 6th Gen
"iPad16,3", "iPad16,4", // iPad Pro 11" 5th Gen
"iPad16,5", "iPad16,6", // iPad Pro 12.9" 7th Gen
"iPad13,16", "iPad13,17", // iPad Air 5th Gen
"iPad14,8", "iPad14,9", // iPad Air 6th Gen
"iPad15,1", "iPad15,2", // Hypothetical future iPad models with 8GB RAM
]
Expand Down
121 changes: 76 additions & 45 deletions OLMoE.swift/Views/UnsupportedDeviceView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import os
import UIKit

struct UnsupportedDeviceView: View {
@State private var showWebView = false
let proceedAnyway: () -> Void
let proceedMocked: () -> Void

Expand All @@ -21,58 +22,88 @@ struct UnsupportedDeviceView: View {
let availableMemoryInGB = Double(os_proc_available_memory()) / (1024 * 1024 * 1024)
let formattedMemory = String(format: "%.2f", availableMemoryInGB)

VStack {
Image("Exclamation")
.foregroundColor(Color("AccentColor"))

Text("Device Not Supported")
.id(UUID()) // Force unique ID so onAppear gets updated width
.font(.title())
.foregroundColor(Color("AccentColor"))
.background(GeometryReader { geometry in
Color.clear.onAppear {
notSupportedWidth = geometry.size.width + 24
}
})

Text("This app requires a device with at least 8GB of RAM.")
.frame(width: notSupportedWidth)
.multilineTextAlignment(.center)
.padding([.horizontal], 32)
.padding([.vertical], 2)
.font(.body())

if FeatureFlags.allowDeviceBypass {
if availableMemoryInGB > 0 {
Text("(The model requires ~6 GB and this device has: \(formattedMemory) GB available.)")
.frame(width: notSupportedWidth)
GeometryReader { geometry in
ScrollView {
VStack(spacing: 20) {
Image("Exclamation")
.foregroundColor(Color("AccentColor"))

Text("On-Device OLMoE Not Available")
.id(UUID())
.font(.title())
.foregroundColor(Color("AccentColor"))
.background(GeometryReader { geometry in
Color.clear.onAppear {
notSupportedWidth = geometry.size.width + 24
}
})
.multilineTextAlignment(.center)

Text("This device does not have the 8GB physical RAM required to run OLMoE locally.")
.multilineTextAlignment(.center)
.padding()
.font(.body())
}

Button("Proceed Anyway") {
proceedAnyway()
}
.buttonStyle(PrimaryButton(minWidth: mockedModelButtonWidth))
.padding(.vertical, 5)
}
Text("OLMoE can run locally on iPhone 15 Pro/Max, iPhone 16 models, iPad Pro 4th Gen and newer, or iPad Air 5th Gen and newer.")
.multilineTextAlignment(.center)
.font(.body())

if FeatureFlags.allowMockedModel {
Button("Proceed With Mocked Model") {
proceedMocked()
}
.id(UUID()) // Force unique ID so onAppear gets updated width
.buttonStyle(.PrimaryButton)
.padding(.vertical, 5)
.background(GeometryReader { geometry in
Color.clear.onAppear {
mockedModelButtonWidth = geometry.size.width - 24
Text("However, you can try using OLMoE at the Ai2 Playground. This option does not download the model file to your device, but instead submits user input to a hosted version of OLMoE to remotely generate responses.")
.multilineTextAlignment(.center)
.font(.body())

Button("Try OLMoE at the Ai2 Playground") {
showWebView = true
}
.buttonStyle(PrimaryButton(minWidth: mockedModelButtonWidth))
.padding(.top, 12)
.sheet(isPresented: $showWebView, onDismiss: nil) {
SheetWrapper {
WebViewWithBanner(
url: URL(string: "https://playground.allenai.org/?model=olmoe-0125")!,
onDismiss: { showWebView = false }
)
}
.interactiveDismissDisabled(false)
}

if FeatureFlags.allowDeviceBypass {
if availableMemoryInGB > 0 {
Text("(The model requires ~6 GB and this device has: \(formattedMemory) GB available.)")
.frame(width: notSupportedWidth)
.multilineTextAlignment(.center)
.padding()
.font(.body())
}

Button("Proceed Anyway") {
proceedAnyway()
}
.buttonStyle(PrimaryButton(minWidth: mockedModelButtonWidth))
.padding(.vertical, 5)
}

if FeatureFlags.allowMockedModel {
Button("Proceed With Mocked Model") {
proceedMocked()
}
.id(UUID())
.buttonStyle(.PrimaryButton)
.padding(.vertical, 5)
.background(GeometryReader { geometry in
Color.clear.onAppear {
mockedModelButtonWidth = geometry.size.width - 24
}
})
}
})

}
.frame(minHeight: geometry.size.height)
.frame(maxWidth: 512)
.padding(.horizontal, 24)
}
.frame(maxWidth: .infinity)
.frame(height: geometry.size.height)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color("BackgroundColor"))
}
}
Expand Down
87 changes: 87 additions & 0 deletions OLMoE.swift/Views/WebView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
let url: URL

func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
let webView = WKWebView()
webView.navigationDelegate = context.coordinator
return webView
}

func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
let request = URLRequest(url: url)
uiView.load(request)
}

class Coordinator: NSObject, WKNavigationDelegate {
var parent: WebView

init(_ parent: WebView) {
self.parent = parent
}

// MARK: - WKNavigationDelegate

/// Intercepts navigation actions in the WKWebView.
func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

print("Navigation action type: \(navigationAction.navigationType)")

// Log the destination URL if available.
if let url = navigationAction.request.url {
print("Destination URL: \(url.absoluteString)")
}

// Check if the navigation action is triggered by a link click or form submission,
// and the URL contains "http"
if let url = navigationAction.request.url,
url.absoluteString.contains("http") ||
navigationAction.navigationType == .linkActivated || navigationAction.navigationType == .formSubmitted,
!url.absoluteString.contains("https://playground.allenai.org") {
// Open the URL in Safari.
UIApplication.shared.open(url, options: [:], completionHandler: nil)
// Cancel the navigation within the web view.
decisionHandler(.cancel)
return
}

// Allow all other types of navigation.
decisionHandler(.allow)
}
}

func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}

struct WebViewWithBanner: View {
let url: URL
let onDismiss: () -> Void

var body: some View {
VStack(spacing: 0) {
HStack {
Text("⚠️ Running on AI2's servers - not on your device")
.font(.footnote)

Spacer()

Button(action: onDismiss) {
Image(systemName: "xmark.circle.fill")
.foregroundColor(.black)
}
}
.padding(8)
.frame(maxWidth: .infinity)
.background(Color("Warning"))
.foregroundColor(.black)

WebView(url: url)
}
}
}

0 comments on commit 79e16f3

Please sign in to comment.