Fixed for decoder dl speed and mobile warnings on low memory devices.
This commit is contained in:
1 parent
2643a446d0
commit
78e99fc415
7 files changed
+208
-32
No files matched your search
+48
-18
@@ -213,6 +213,38 @@ export function App() {
|
||||
return deviceOverrides.current.get(overrideKey(forModelId, preference)) ?? preference;
|
||||
}
|
||||
|
||||
/** Mirrors ModelPicker's size-estimate fallback: until the worker reports an
|
||||
* active device, assume WASM unless the user asked for an accelerator. */
|
||||
function guessDevice(preference: DevicePreference): InferenceDevice {
|
||||
return (
|
||||
activeDevice ??
|
||||
(preference === "webgpu" ? "webgpu" : preference === "webnn" ? "webnn" : "wasm")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether loading `forModelId` on `device` risks crashing a mobile tab
|
||||
* (D-027) — independent of whether the user has already been asked. Used
|
||||
* both to decide whether to show the confirm dialog and, regardless of the
|
||||
* user's answer, to decide whether the worker should load sub-model
|
||||
* sessions sequentially (memory-safe but slower) or in parallel (fast,
|
||||
* safe everywhere this isn't true).
|
||||
*/
|
||||
function isMobileLoadRisk(forModelId: string, device: InferenceDevice): boolean {
|
||||
const targetModel = getModel(forModelId);
|
||||
if (!targetModel) return false;
|
||||
const peakBytes = estimatePeakLoadBytes(targetModel, resolveDefaultDtype(forModelId, device));
|
||||
const hint: MobileMemoryHint = {
|
||||
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : undefined,
|
||||
maxTouchPoints: typeof navigator !== "undefined" ? navigator.maxTouchPoints : undefined,
|
||||
deviceMemoryGB:
|
||||
typeof navigator !== "undefined"
|
||||
? (navigator as Navigator & { deviceMemory?: number }).deviceMemory
|
||||
: undefined,
|
||||
};
|
||||
return shouldWarnBeforeLoad(hint, peakBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm before a browser-engine load that risks crashing the tab on
|
||||
* mobile (D-027). Returns true if the load should proceed — either it
|
||||
@@ -223,25 +255,12 @@ export function App() {
|
||||
function confirmRiskyMobileLoad(forModelId: string, preference: DevicePreference): boolean {
|
||||
const targetModel = getModel(forModelId);
|
||||
if (!targetModel) return true;
|
||||
// Mirrors ModelPicker's size-estimate fallback: until the worker reports
|
||||
// an active device, assume WASM unless the user asked for an accelerator.
|
||||
const device: InferenceDevice =
|
||||
activeDevice ??
|
||||
(preference === "webgpu" ? "webgpu" : preference === "webnn" ? "webnn" : "wasm");
|
||||
const device = guessDevice(preference);
|
||||
const key = overrideKey(forModelId, device);
|
||||
if (mobileWarningAcknowledged.current.has(key)) return true;
|
||||
if (!isMobileLoadRisk(forModelId, device)) return true;
|
||||
|
||||
const peakBytes = estimatePeakLoadBytes(targetModel, resolveDefaultDtype(forModelId, device));
|
||||
const hint: MobileMemoryHint = {
|
||||
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : undefined,
|
||||
maxTouchPoints: typeof navigator !== "undefined" ? navigator.maxTouchPoints : undefined,
|
||||
deviceMemoryGB:
|
||||
typeof navigator !== "undefined"
|
||||
? (navigator as Navigator & { deviceMemory?: number }).deviceMemory
|
||||
: undefined,
|
||||
};
|
||||
if (!shouldWarnBeforeLoad(hint, peakBytes)) return true;
|
||||
|
||||
const proceed = window.confirm(
|
||||
`${targetModel.displayName} needs roughly ${formatModelSize(peakBytes)} of memory at ` +
|
||||
"once to load — more than many phones and tablets allow a browser tab to use " +
|
||||
@@ -379,6 +398,7 @@ export function App() {
|
||||
type: "load",
|
||||
modelId: message.modelId,
|
||||
device: message.device,
|
||||
sequentialSessionLoad: isMobileLoadRisk(message.modelId, message.device),
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -417,10 +437,16 @@ export function App() {
|
||||
setLoadStarted(true);
|
||||
setError(null);
|
||||
newLoadGate();
|
||||
const device = effectiveDevice(nextModelId, preference);
|
||||
postToWorker(worker, {
|
||||
type: "load",
|
||||
modelId: nextModelId,
|
||||
device: effectiveDevice(nextModelId, preference),
|
||||
device,
|
||||
// D-027/D-029: sub-model sessions load sequentially (memory-safe, but
|
||||
// slower — halves the CDN concurrency a fast connection could otherwise
|
||||
// use) only where the peak-memory crash risk is real; everywhere else
|
||||
// (desktop, low-risk models) the worker loads them in parallel.
|
||||
sequentialSessionLoad: isMobileLoadRisk(nextModelId, guessDevice(device)),
|
||||
});
|
||||
return worker;
|
||||
}
|
||||
@@ -540,10 +566,12 @@ export function App() {
|
||||
if (!loadStarted) {
|
||||
startLoad(modelId, devicePreference);
|
||||
} else {
|
||||
const device = effectiveDevice(modelId, devicePreference);
|
||||
postToWorker(workerRef.current!, {
|
||||
type: "load",
|
||||
modelId,
|
||||
device: effectiveDevice(modelId, devicePreference),
|
||||
device,
|
||||
sequentialSessionLoad: isMobileLoadRisk(modelId, guessDevice(device)),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -788,10 +816,12 @@ export function App() {
|
||||
if (!loadStarted) {
|
||||
startLoad(modelId, devicePreference);
|
||||
} else {
|
||||
const device = effectiveDevice(modelId, devicePreference);
|
||||
postToWorker(worker, {
|
||||
type: "load",
|
||||
modelId,
|
||||
device: effectiveDevice(modelId, devicePreference),
|
||||
device,
|
||||
sequentialSessionLoad: isMobileLoadRisk(modelId, guessDevice(device)),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user