web-sdk-pp-detection 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -20
- package/dist/browser-global.js +335 -93
- package/dist/browser-global.js.map +1 -1
- package/dist/index.d.ts +29 -3
- package/dist/index.js +335 -93
- package/dist/index.js.map +1 -1
- package/dist/inference.worker.js +14 -5
- package/dist/inference.worker.js.map +1 -1
- package/package.json +1 -1
package/dist/browser-global.js
CHANGED
|
@@ -14258,7 +14258,11 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
14258
14258
|
original: { width: decoded.width, height: decoded.height }
|
|
14259
14259
|
},
|
|
14260
14260
|
model: this.model,
|
|
14261
|
-
runtime:
|
|
14261
|
+
runtime: {
|
|
14262
|
+
...this.runtime,
|
|
14263
|
+
fallbacks: this.runtime.fallbacks.map((fallback) => ({ ...fallback })),
|
|
14264
|
+
...this.runtime.environment ? { environment: { ...this.runtime.environment } } : {}
|
|
14265
|
+
},
|
|
14262
14266
|
timings: {
|
|
14263
14267
|
decodeMs: decoded.decodeMs,
|
|
14264
14268
|
preprocessMs,
|
|
@@ -14751,8 +14755,84 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
14751
14755
|
});
|
|
14752
14756
|
}
|
|
14753
14757
|
|
|
14758
|
+
// src/cache/coordination.ts
|
|
14759
|
+
var CacheCoordinator = class {
|
|
14760
|
+
caches = /* @__PURE__ */ new Map();
|
|
14761
|
+
generation = 0;
|
|
14762
|
+
keys = /* @__PURE__ */ new Map();
|
|
14763
|
+
pending = Promise.resolve();
|
|
14764
|
+
guard(key) {
|
|
14765
|
+
const generation = this.generation;
|
|
14766
|
+
const keyGeneration = this.keys.get(key) ?? 0;
|
|
14767
|
+
this.keys.set(key, keyGeneration);
|
|
14768
|
+
return () => generation === this.generation && keyGeneration === (this.keys.get(key) ?? 0);
|
|
14769
|
+
}
|
|
14770
|
+
run(operation) {
|
|
14771
|
+
const pending = this.pending.then(operation);
|
|
14772
|
+
this.pending = pending.catch(() => void 0);
|
|
14773
|
+
return pending;
|
|
14774
|
+
}
|
|
14775
|
+
clear(key, matches) {
|
|
14776
|
+
if (matches) {
|
|
14777
|
+
for (const [candidate, generation] of this.keys) {
|
|
14778
|
+
if (matches(candidate)) this.keys.set(candidate, generation + 1);
|
|
14779
|
+
}
|
|
14780
|
+
} else if (key === void 0) this.generation += 1;
|
|
14781
|
+
else this.keys.set(key, (this.keys.get(key) ?? 0) + 1);
|
|
14782
|
+
return this.run(async () => {
|
|
14783
|
+
const outcomes = await Promise.allSettled(
|
|
14784
|
+
[...this.caches.keys()].map(async (cache) => {
|
|
14785
|
+
if (matches && cache.list) {
|
|
14786
|
+
for (const entry of await cache.list()) {
|
|
14787
|
+
if (matches(entry.key)) await cache.clearCurrent(entry.key);
|
|
14788
|
+
}
|
|
14789
|
+
} else if (key === void 0) await cache.clearAll();
|
|
14790
|
+
else await cache.clearCurrent(key);
|
|
14791
|
+
})
|
|
14792
|
+
);
|
|
14793
|
+
const failure = outcomes.find((outcome) => outcome.status === "rejected");
|
|
14794
|
+
if (failure?.status === "rejected") throw failure.reason;
|
|
14795
|
+
});
|
|
14796
|
+
}
|
|
14797
|
+
unregister(cache) {
|
|
14798
|
+
const count = this.caches.get(cache) ?? 0;
|
|
14799
|
+
if (count > 1) {
|
|
14800
|
+
this.caches.set(cache, count - 1);
|
|
14801
|
+
return false;
|
|
14802
|
+
}
|
|
14803
|
+
this.caches.delete(cache);
|
|
14804
|
+
return true;
|
|
14805
|
+
}
|
|
14806
|
+
};
|
|
14807
|
+
var coordinators = /* @__PURE__ */ new WeakMap();
|
|
14808
|
+
function coordinateCache(cache) {
|
|
14809
|
+
const scope = cache.scope ?? cache;
|
|
14810
|
+
let coordinator = coordinators.get(scope);
|
|
14811
|
+
if (!coordinator) {
|
|
14812
|
+
coordinator = new CacheCoordinator();
|
|
14813
|
+
coordinators.set(scope, coordinator);
|
|
14814
|
+
}
|
|
14815
|
+
coordinator.caches.set(cache, (coordinator.caches.get(cache) ?? 0) + 1);
|
|
14816
|
+
return coordinator;
|
|
14817
|
+
}
|
|
14818
|
+
var databaseScopes = /* @__PURE__ */ new WeakMap();
|
|
14819
|
+
function databaseScope(factory, name) {
|
|
14820
|
+
let scopes = databaseScopes.get(factory);
|
|
14821
|
+
if (!scopes) {
|
|
14822
|
+
scopes = /* @__PURE__ */ new Map();
|
|
14823
|
+
databaseScopes.set(factory, scopes);
|
|
14824
|
+
}
|
|
14825
|
+
let scope = scopes.get(name);
|
|
14826
|
+
if (!scope) {
|
|
14827
|
+
scope = {};
|
|
14828
|
+
scopes.set(name, scope);
|
|
14829
|
+
}
|
|
14830
|
+
return scope;
|
|
14831
|
+
}
|
|
14832
|
+
|
|
14754
14833
|
// src/cache/indexeddb-cache.ts
|
|
14755
14834
|
var IndexedDBModelCache = class {
|
|
14835
|
+
scope;
|
|
14756
14836
|
factory;
|
|
14757
14837
|
databaseName;
|
|
14758
14838
|
database;
|
|
@@ -14761,6 +14841,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
14761
14841
|
if (!factory) throw new Error("\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301 IndexedDB");
|
|
14762
14842
|
this.factory = factory;
|
|
14763
14843
|
this.databaseName = options.databaseName ?? "web-sdk-pp-detection-models-v1";
|
|
14844
|
+
this.scope = databaseScope(factory, this.databaseName);
|
|
14764
14845
|
}
|
|
14765
14846
|
async get(key) {
|
|
14766
14847
|
const record3 = await this.request(
|
|
@@ -14814,6 +14895,24 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
14814
14895
|
(await this.database).close();
|
|
14815
14896
|
this.database = void 0;
|
|
14816
14897
|
}
|
|
14898
|
+
async list() {
|
|
14899
|
+
const database = await this.open();
|
|
14900
|
+
return await new Promise((resolve, reject) => {
|
|
14901
|
+
const transaction = database.transaction("models", "readonly");
|
|
14902
|
+
const request = transaction.objectStore("models").openCursor();
|
|
14903
|
+
const entries = [];
|
|
14904
|
+
request.onerror = () => reject(request.error ?? new Error("\u8BFB\u53D6\u7F13\u5B58\u5BB9\u91CF\u5931\u8D25"));
|
|
14905
|
+
request.onsuccess = () => {
|
|
14906
|
+
const cursor = request.result;
|
|
14907
|
+
if (!cursor) return;
|
|
14908
|
+
const record3 = cursor.value;
|
|
14909
|
+
entries.push({ key: record3.key, bytes: record3.size });
|
|
14910
|
+
cursor.continue();
|
|
14911
|
+
};
|
|
14912
|
+
transaction.oncomplete = () => resolve(entries);
|
|
14913
|
+
transaction.onabort = () => reject(transaction.error ?? new Error("\u7F13\u5B58\u5BB9\u91CF\u4E8B\u52A1\u4E2D\u6B62"));
|
|
14914
|
+
});
|
|
14915
|
+
}
|
|
14817
14916
|
open() {
|
|
14818
14917
|
if (this.database) return this.database;
|
|
14819
14918
|
this.database = new Promise((resolve, reject) => {
|
|
@@ -14883,6 +14982,11 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
14883
14982
|
this.entries.clear();
|
|
14884
14983
|
return Promise.resolve();
|
|
14885
14984
|
}
|
|
14985
|
+
list() {
|
|
14986
|
+
return Promise.resolve(
|
|
14987
|
+
[...this.entries].map(([key, bytes]) => ({ key, bytes: bytes.byteLength }))
|
|
14988
|
+
);
|
|
14989
|
+
}
|
|
14886
14990
|
};
|
|
14887
14991
|
|
|
14888
14992
|
// src/cache/model-cache.ts
|
|
@@ -14890,9 +14994,11 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
14890
14994
|
constructor(memory, persistent) {
|
|
14891
14995
|
this.memory = memory;
|
|
14892
14996
|
this.persistent = persistent;
|
|
14997
|
+
this.scope = persistent?.scope ?? persistent ?? memory;
|
|
14893
14998
|
}
|
|
14894
14999
|
memory;
|
|
14895
15000
|
persistent;
|
|
15001
|
+
scope;
|
|
14896
15002
|
async get(key) {
|
|
14897
15003
|
const memoryValue = await this.memory.get(key);
|
|
14898
15004
|
if (memoryValue) return memoryValue;
|
|
@@ -14915,6 +15021,13 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
14915
15021
|
estimate() {
|
|
14916
15022
|
return this.persistent?.estimate() ?? this.memory.estimate();
|
|
14917
15023
|
}
|
|
15024
|
+
async list() {
|
|
15025
|
+
const entries = /* @__PURE__ */ new Map();
|
|
15026
|
+
for (const cache of [this.memory, this.persistent]) {
|
|
15027
|
+
for (const entry of await cache?.list?.() ?? []) entries.set(entry.key, entry);
|
|
15028
|
+
}
|
|
15029
|
+
return [...entries.values()];
|
|
15030
|
+
}
|
|
14918
15031
|
async close() {
|
|
14919
15032
|
await this.memory.close?.();
|
|
14920
15033
|
await this.persistent?.close?.();
|
|
@@ -15124,6 +15237,14 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15124
15237
|
|
|
15125
15238
|
// src/model/model-manager.ts
|
|
15126
15239
|
var SDK_CACHE_NAMESPACE = "web-sdk-pp-detection:cache-v1";
|
|
15240
|
+
function matchesModel(key, model) {
|
|
15241
|
+
try {
|
|
15242
|
+
const parts = JSON.parse(key);
|
|
15243
|
+
return Array.isArray(parts) && parts[0] === SDK_CACHE_NAMESPACE && (model === void 0 || parts[1] === model.id && parts[2] === model.version);
|
|
15244
|
+
} catch {
|
|
15245
|
+
return false;
|
|
15246
|
+
}
|
|
15247
|
+
}
|
|
15127
15248
|
function now2() {
|
|
15128
15249
|
return globalThis.performance?.now() ?? Date.now();
|
|
15129
15250
|
}
|
|
@@ -15147,6 +15268,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15147
15268
|
var ModelManager = class {
|
|
15148
15269
|
fetcher;
|
|
15149
15270
|
cache;
|
|
15271
|
+
coordinator;
|
|
15150
15272
|
lifecycle = new AbortController();
|
|
15151
15273
|
activeLoads = /* @__PURE__ */ new Set();
|
|
15152
15274
|
currentKey;
|
|
@@ -15155,6 +15277,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15155
15277
|
constructor(options = {}) {
|
|
15156
15278
|
this.fetcher = options.fetcher;
|
|
15157
15279
|
this.cache = createCache(options.cache);
|
|
15280
|
+
this.coordinator = coordinateCache(this.cache);
|
|
15158
15281
|
}
|
|
15159
15282
|
cacheKey(variant3, source2, model = { id: "unknown", version: "unknown" }) {
|
|
15160
15283
|
return JSON.stringify([
|
|
@@ -15193,16 +15316,24 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15193
15316
|
const variant3 = resolveModelVariant(manifest, options.variantId);
|
|
15194
15317
|
const sourceKind2 = options.sourceKind ?? "auto";
|
|
15195
15318
|
const sources = resolveModelSources(variant3, sourceKind2);
|
|
15319
|
+
const guards = new Map(
|
|
15320
|
+
sources.map((source2) => {
|
|
15321
|
+
const key = this.cacheKey(variant3, source2, manifest.model);
|
|
15322
|
+
return [key, this.coordinator.guard(key)];
|
|
15323
|
+
})
|
|
15324
|
+
);
|
|
15196
15325
|
const failures = [];
|
|
15197
15326
|
let lastError;
|
|
15198
15327
|
for (const source2 of sources) {
|
|
15199
15328
|
throwIfAborted4(options.signal);
|
|
15200
15329
|
const asset = { model: manifest.model, variant: variant3, source: source2 };
|
|
15201
15330
|
const cacheKey = this.cacheKey(variant3, source2, manifest.model);
|
|
15331
|
+
this.currentKey = cacheKey;
|
|
15332
|
+
const canMutate = guards.get(cacheKey);
|
|
15202
15333
|
const cacheStarted = now2();
|
|
15203
15334
|
let cached;
|
|
15204
15335
|
try {
|
|
15205
|
-
cached = await this.cache.get(cacheKey);
|
|
15336
|
+
cached = await this.coordinator.run(() => this.cache.get(cacheKey));
|
|
15206
15337
|
} catch (error) {
|
|
15207
15338
|
if (error instanceof PPDetectionError && error.code === "ABORTED") throw error;
|
|
15208
15339
|
throwIfAborted4(options.signal);
|
|
@@ -15213,7 +15344,6 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15213
15344
|
const integrityStarted = now2();
|
|
15214
15345
|
try {
|
|
15215
15346
|
await verifyModelIntegrity(cached, source2, options.signal);
|
|
15216
|
-
this.currentKey = cacheKey;
|
|
15217
15347
|
return {
|
|
15218
15348
|
bytes: cached,
|
|
15219
15349
|
manifest,
|
|
@@ -15227,7 +15357,9 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15227
15357
|
} catch (error) {
|
|
15228
15358
|
if (error instanceof PPDetectionError && error.code === "ABORTED") throw error;
|
|
15229
15359
|
try {
|
|
15230
|
-
await this.
|
|
15360
|
+
await this.coordinator.run(async () => {
|
|
15361
|
+
if (canMutate()) await this.cache.clearCurrent(cacheKey);
|
|
15362
|
+
});
|
|
15231
15363
|
} catch (clearError) {
|
|
15232
15364
|
if (clearError instanceof PPDetectionError && clearError.code === "ABORTED")
|
|
15233
15365
|
throw clearError;
|
|
@@ -15263,11 +15395,12 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15263
15395
|
}
|
|
15264
15396
|
throwIfAborted4(options.signal);
|
|
15265
15397
|
try {
|
|
15266
|
-
await this.
|
|
15398
|
+
await this.coordinator.run(async () => {
|
|
15399
|
+
if (canMutate()) await this.cache.put(cacheKey, loaded.bytes);
|
|
15400
|
+
});
|
|
15267
15401
|
} catch {
|
|
15268
15402
|
}
|
|
15269
15403
|
throwIfAborted4(options.signal);
|
|
15270
|
-
this.currentKey = cacheKey;
|
|
15271
15404
|
return {
|
|
15272
15405
|
bytes: loaded.bytes,
|
|
15273
15406
|
manifest,
|
|
@@ -15292,16 +15425,44 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15292
15425
|
estimate() {
|
|
15293
15426
|
return this.getCacheEstimate();
|
|
15294
15427
|
}
|
|
15295
|
-
getCacheEstimate() {
|
|
15296
|
-
return this.
|
|
15428
|
+
getCacheEstimate(model) {
|
|
15429
|
+
return this.coordinator.run(async () => {
|
|
15430
|
+
if (!this.cache.list) {
|
|
15431
|
+
if (model)
|
|
15432
|
+
throw new PPDetectionError(
|
|
15433
|
+
"CAPABILITY_UNSUPPORTED",
|
|
15434
|
+
"\u81EA\u5B9A\u4E49\u7F13\u5B58\u9700\u5B9E\u73B0 list \u624D\u80FD\u6309\u6A21\u578B\u4F30\u7B97"
|
|
15435
|
+
);
|
|
15436
|
+
return this.cache.estimate();
|
|
15437
|
+
}
|
|
15438
|
+
const unique = /* @__PURE__ */ new Map();
|
|
15439
|
+
for (const cache of this.coordinator.caches.keys()) {
|
|
15440
|
+
for (const entry of await cache.list?.() ?? []) unique.set(entry.key, entry);
|
|
15441
|
+
}
|
|
15442
|
+
const entries = [...unique.values()].filter((entry) => matchesModel(entry.key, model));
|
|
15443
|
+
return {
|
|
15444
|
+
bytes: entries.reduce((sum, entry) => sum + entry.bytes, 0),
|
|
15445
|
+
entries: entries.length
|
|
15446
|
+
};
|
|
15447
|
+
});
|
|
15297
15448
|
}
|
|
15298
|
-
async clearCurrentModelCache() {
|
|
15449
|
+
async clearCurrentModelCache(model) {
|
|
15450
|
+
if (model) {
|
|
15451
|
+
if (!model.id || !model.version)
|
|
15452
|
+
throw new PPDetectionError("INVALID_MANIFEST", "\u7F13\u5B58\u6A21\u578B\u8EAB\u4EFD\u5FC5\u987B\u5305\u542B id \u548C version");
|
|
15453
|
+
if (!this.cache.list)
|
|
15454
|
+
throw new PPDetectionError(
|
|
15455
|
+
"CAPABILITY_UNSUPPORTED",
|
|
15456
|
+
"\u81EA\u5B9A\u4E49\u7F13\u5B58\u9700\u5B9E\u73B0 list \u624D\u80FD\u6309\u6A21\u578B\u6E05\u7406"
|
|
15457
|
+
);
|
|
15458
|
+
await this.coordinator.clear(void 0, (key) => matchesModel(key, model));
|
|
15459
|
+
return;
|
|
15460
|
+
}
|
|
15299
15461
|
if (!this.currentKey) return;
|
|
15300
|
-
await this.
|
|
15462
|
+
await this.coordinator.clear(this.currentKey);
|
|
15301
15463
|
}
|
|
15302
15464
|
async clearAllCache() {
|
|
15303
|
-
await this.
|
|
15304
|
-
this.currentKey = void 0;
|
|
15465
|
+
await this.coordinator.clear(void 0, (key) => matchesModel(key));
|
|
15305
15466
|
}
|
|
15306
15467
|
async dispose() {
|
|
15307
15468
|
if (this.disposePromise) return await this.disposePromise;
|
|
@@ -15310,7 +15471,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15310
15471
|
this.disposePromise = (async () => {
|
|
15311
15472
|
await Promise.all([...this.activeLoads]);
|
|
15312
15473
|
this.currentKey = void 0;
|
|
15313
|
-
await this.cache.close?.();
|
|
15474
|
+
if (this.coordinator.unregister(this.cache)) await this.cache.close?.();
|
|
15314
15475
|
})();
|
|
15315
15476
|
await this.disposePromise;
|
|
15316
15477
|
}
|
|
@@ -15323,14 +15484,15 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15323
15484
|
function mapError(error, phase) {
|
|
15324
15485
|
if (error instanceof PPDetectionError) return error;
|
|
15325
15486
|
const message = error instanceof Error ? error.message : String(error);
|
|
15326
|
-
|
|
15327
|
-
|
|
15487
|
+
const details = { phase, causeMessage: message };
|
|
15488
|
+
if (error instanceof Error && error.name === "AbortError")
|
|
15489
|
+
return new PPDetectionError("ABORTED", "\u63A8\u7406\u5DF2\u53D6\u6D88", details, { cause: error });
|
|
15328
15490
|
if (/memory|out.of.memory|allocation/i.test(message))
|
|
15329
|
-
return new PPDetectionError("OUT_OF_MEMORY", "\u8FD0\u884C\u65F6\u5185\u5B58\u4E0D\u8DB3",
|
|
15491
|
+
return new PPDetectionError("OUT_OF_MEMORY", "\u8FD0\u884C\u65F6\u5185\u5B58\u4E0D\u8DB3", details, { cause: error });
|
|
15330
15492
|
return new PPDetectionError(
|
|
15331
15493
|
phase === "create" ? "SESSION_CREATE_FAILED" : "INFERENCE_FAILED",
|
|
15332
15494
|
phase === "create" ? "\u521B\u5EFA ONNX Runtime \u4F1A\u8BDD\u5931\u8D25" : "ONNX Runtime \u63A8\u7406\u5931\u8D25",
|
|
15333
|
-
|
|
15495
|
+
details,
|
|
15334
15496
|
{ cause: error }
|
|
15335
15497
|
);
|
|
15336
15498
|
}
|
|
@@ -15368,6 +15530,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15368
15530
|
return {
|
|
15369
15531
|
plan,
|
|
15370
15532
|
sessionMs,
|
|
15533
|
+
runtimeVersion: ort.env.versions?.web ?? null,
|
|
15371
15534
|
async run(feeds, runOptions = {}) {
|
|
15372
15535
|
if (disposed) throw new PPDetectionError("DISPOSED", "\u4F1A\u8BDD\u5DF2\u91CA\u653E", { phase: "run" });
|
|
15373
15536
|
if (runOptions.signal?.aborted)
|
|
@@ -15488,14 +15651,13 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15488
15651
|
function fail(code, message, details) {
|
|
15489
15652
|
throw new PPDetectionError(code, message, details);
|
|
15490
15653
|
}
|
|
15491
|
-
function candidatesForBackend(requested, capabilities
|
|
15654
|
+
function candidatesForBackend(requested, capabilities) {
|
|
15492
15655
|
if (requested === "wasm") return ["wasm"];
|
|
15493
15656
|
if (requested === "webgpu")
|
|
15494
15657
|
return capabilities.webgpu ? ["webgpu"] : fail("CAPABILITY_UNSUPPORTED", "\u8BF7\u6C42\u7684 webgpu \u4E0D\u53EF\u7528", { requestedBackend: requested });
|
|
15495
15658
|
const available = [];
|
|
15496
15659
|
if (capabilities.webgpu) available.push("webgpu");
|
|
15497
15660
|
available.push("wasm");
|
|
15498
|
-
if (!allowFallback) return available.slice(0, 1);
|
|
15499
15661
|
return available;
|
|
15500
15662
|
}
|
|
15501
15663
|
function selectExecutionPlan(options, capabilities, manifest) {
|
|
@@ -15513,19 +15675,18 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15513
15675
|
requestedPrecision
|
|
15514
15676
|
});
|
|
15515
15677
|
}
|
|
15516
|
-
const candidates = candidatesForBackend(
|
|
15517
|
-
|
|
15518
|
-
|
|
15519
|
-
|
|
15520
|
-
|
|
15521
|
-
if (candidates.length === 0) {
|
|
15678
|
+
const candidates = candidatesForBackend(requestedBackend, capabilities).filter(
|
|
15679
|
+
(backend) => variant3.backends.includes(backend)
|
|
15680
|
+
);
|
|
15681
|
+
const selectedCandidates = options.allowFallback === true ? candidates : candidates.slice(0, 1);
|
|
15682
|
+
if (selectedCandidates.length === 0) {
|
|
15522
15683
|
fail("CAPABILITY_UNSUPPORTED", "\u6CA1\u6709\u4E0E\u6A21\u578B\u53D8\u4F53\u5339\u914D\u7684\u53EF\u7528\u540E\u7AEF", {
|
|
15523
15684
|
requestedBackend,
|
|
15524
15685
|
requestedPrecision,
|
|
15525
15686
|
availableBackends: variant3.backends
|
|
15526
15687
|
});
|
|
15527
15688
|
}
|
|
15528
|
-
const actualBackend =
|
|
15689
|
+
const actualBackend = selectedCandidates[0];
|
|
15529
15690
|
return {
|
|
15530
15691
|
variantId: variant3.id,
|
|
15531
15692
|
requestedBackend,
|
|
@@ -15533,7 +15694,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15533
15694
|
requestedPrecision,
|
|
15534
15695
|
actualPrecision: variant3.precision,
|
|
15535
15696
|
executionMode,
|
|
15536
|
-
candidates:
|
|
15697
|
+
candidates: selectedCandidates.map((backend) => ({
|
|
15537
15698
|
variantId: variant3.id,
|
|
15538
15699
|
backend,
|
|
15539
15700
|
precision: variant3.precision,
|
|
@@ -15688,7 +15849,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15688
15849
|
};
|
|
15689
15850
|
|
|
15690
15851
|
// src/index.ts
|
|
15691
|
-
var CURRENT_SDK_VERSION = "0.
|
|
15852
|
+
var CURRENT_SDK_VERSION = "0.2.0";
|
|
15692
15853
|
function probePPDetectionCapabilities(options = {}) {
|
|
15693
15854
|
return probeCapabilities(options);
|
|
15694
15855
|
}
|
|
@@ -15783,6 +15944,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15783
15944
|
return new URL("./inference.worker.js", (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser-global.js', document.baseURI).href));
|
|
15784
15945
|
}
|
|
15785
15946
|
async function createPPDetection(options = {}) {
|
|
15947
|
+
const loadStartedAt = now4();
|
|
15786
15948
|
if (options.model === void 0 && options.manifest === void 0)
|
|
15787
15949
|
throw new PPDetectionError("INVALID_MANIFEST", "\u521B\u5EFA PPDetection \u5B9E\u4F8B\u9700\u8981 manifest \u6216 model");
|
|
15788
15950
|
const capabilities = probeCapabilities();
|
|
@@ -15814,9 +15976,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15814
15976
|
cache: options.cache === false ? false : options.cache === "memory" ? "memory" : void 0
|
|
15815
15977
|
});
|
|
15816
15978
|
let executor;
|
|
15817
|
-
let activeBridge;
|
|
15818
15979
|
try {
|
|
15819
|
-
const loadStartedAt = now4();
|
|
15820
15980
|
options.onProgress?.({ phase: "model", status: "start" });
|
|
15821
15981
|
let modelBytes;
|
|
15822
15982
|
let actualSource;
|
|
@@ -15828,10 +15988,17 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15828
15988
|
throw new PPDetectionError("MODEL_SOURCE_UNAVAILABLE", "\u6A21\u578B\u53D8\u4F53\u6CA1\u6709\u53EF\u7528\u6765\u6E90", {
|
|
15829
15989
|
variantId: variant3.id
|
|
15830
15990
|
});
|
|
15991
|
+
const integrityStartedAt = now4();
|
|
15831
15992
|
await verifyModelIntegrity(memoryData, source2, options.signal);
|
|
15993
|
+
const integrityMs = now4() - integrityStartedAt;
|
|
15832
15994
|
modelBytes = memoryData;
|
|
15833
15995
|
actualSource = source2;
|
|
15834
|
-
loadTimings = {
|
|
15996
|
+
loadTimings = {
|
|
15997
|
+
sessionMs: 0,
|
|
15998
|
+
totalMs: now4() - loadStartedAt,
|
|
15999
|
+
integrityMs,
|
|
16000
|
+
modelSource: "memory"
|
|
16001
|
+
};
|
|
15835
16002
|
} else {
|
|
15836
16003
|
const loaded = await modelManager.load({
|
|
15837
16004
|
manifest: runtimeManifest,
|
|
@@ -15843,33 +16010,26 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15843
16010
|
modelBytes = loaded.bytes;
|
|
15844
16011
|
variant3 = loaded.variant;
|
|
15845
16012
|
actualSource = loaded.source;
|
|
15846
|
-
loadTimings = {
|
|
16013
|
+
loadTimings = {
|
|
16014
|
+
...loaded.timings,
|
|
16015
|
+
sessionMs: 0,
|
|
16016
|
+
totalMs: now4() - loadStartedAt,
|
|
16017
|
+
modelSource: loaded.fromCache ? "cache" : "network"
|
|
16018
|
+
};
|
|
15847
16019
|
}
|
|
15848
16020
|
options.onProgress?.({ phase: "model", status: "complete" });
|
|
15849
16021
|
const fallbacks = [];
|
|
15850
|
-
|
|
15851
|
-
let sessionMs = 0;
|
|
15852
|
-
for (const candidate of plan.candidates) {
|
|
15853
|
-
const candidatePlan = {
|
|
15854
|
-
...plan,
|
|
15855
|
-
variantId: candidate.variantId,
|
|
15856
|
-
actualBackend: candidate.backend,
|
|
15857
|
-
actualPrecision: candidate.precision,
|
|
15858
|
-
executionMode: candidate.executionMode,
|
|
15859
|
-
candidates: [candidate]
|
|
15860
|
-
};
|
|
16022
|
+
const createExecutorForPlan = async (candidatePlan) => {
|
|
15861
16023
|
options.onProgress?.({ phase: "session", status: "start" });
|
|
16024
|
+
let bridge;
|
|
16025
|
+
const sessionStartedAt = now4();
|
|
15862
16026
|
try {
|
|
15863
|
-
if (
|
|
16027
|
+
if (candidatePlan.executionMode === "worker") {
|
|
15864
16028
|
if (typeof Worker !== "function")
|
|
15865
16029
|
throw new PPDetectionError("CAPABILITY_UNSUPPORTED", "\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301 Worker");
|
|
15866
|
-
const worker = new Worker(workerUrl(), {
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
const bridge = new WorkerBridge(worker);
|
|
15870
|
-
activeBridge = bridge;
|
|
15871
|
-
const workerModelBytes = modelBytes.slice(0);
|
|
15872
|
-
await bridge.load(workerModelBytes, candidatePlan, {
|
|
16030
|
+
const worker = new Worker(workerUrl(), { type: "module" });
|
|
16031
|
+
bridge = new WorkerBridge(worker);
|
|
16032
|
+
const metadata = await bridge.load(modelBytes.slice(0), candidatePlan, {
|
|
15873
16033
|
onProgress: (event) => options.onProgress?.({
|
|
15874
16034
|
phase: "session",
|
|
15875
16035
|
status: event.status
|
|
@@ -15879,35 +16039,69 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15879
16039
|
numThreads: options.ort?.wasm?.numThreads
|
|
15880
16040
|
}
|
|
15881
16041
|
});
|
|
15882
|
-
|
|
15883
|
-
|
|
15884
|
-
|
|
15885
|
-
|
|
15886
|
-
{ signal }
|
|
15887
|
-
);
|
|
15888
|
-
},
|
|
15889
|
-
dispose: () => bridge.dispose()
|
|
15890
|
-
};
|
|
15891
|
-
activeBridge = void 0;
|
|
15892
|
-
} else {
|
|
15893
|
-
const session = await createOrtSession(modelBytes, candidatePlan, {
|
|
15894
|
-
ort: options.ort?.module,
|
|
15895
|
-
wasmPaths: options.ort?.wasm?.paths,
|
|
15896
|
-
numThreads: options.ort?.wasm?.numThreads
|
|
15897
|
-
});
|
|
15898
|
-
sessionMs = session.sessionMs;
|
|
15899
|
-
executor = {
|
|
16042
|
+
runtimeVersion = typeof metadata === "object" && metadata !== null && "runtimeVersion" in metadata && typeof metadata.runtimeVersion === "string" ? metadata.runtimeVersion : null;
|
|
16043
|
+
const activeBridge = bridge;
|
|
16044
|
+
options.onProgress?.({ phase: "session", status: "complete" });
|
|
16045
|
+
return {
|
|
15900
16046
|
run(input, signal) {
|
|
15901
|
-
return
|
|
16047
|
+
return activeBridge.run(
|
|
15902
16048
|
{ [input.inputName]: { data: input.data, dims: input.dims } },
|
|
15903
16049
|
{ signal }
|
|
15904
16050
|
);
|
|
15905
16051
|
},
|
|
15906
|
-
dispose: () =>
|
|
16052
|
+
dispose: () => activeBridge.dispose()
|
|
15907
16053
|
};
|
|
15908
16054
|
}
|
|
15909
|
-
|
|
16055
|
+
const session = await createOrtSession(modelBytes, candidatePlan, {
|
|
16056
|
+
ort: options.ort?.module,
|
|
16057
|
+
wasmPaths: options.ort?.wasm?.paths,
|
|
16058
|
+
numThreads: options.ort?.wasm?.numThreads
|
|
16059
|
+
});
|
|
16060
|
+
runtimeVersion = session.runtimeVersion ?? null;
|
|
15910
16061
|
options.onProgress?.({ phase: "session", status: "complete" });
|
|
16062
|
+
return {
|
|
16063
|
+
run(input, signal) {
|
|
16064
|
+
return session.run(
|
|
16065
|
+
{ [input.inputName]: { data: input.data, dims: input.dims } },
|
|
16066
|
+
{ signal }
|
|
16067
|
+
);
|
|
16068
|
+
},
|
|
16069
|
+
dispose: () => session.dispose()
|
|
16070
|
+
};
|
|
16071
|
+
} catch (error) {
|
|
16072
|
+
try {
|
|
16073
|
+
await bridge?.dispose();
|
|
16074
|
+
} catch {
|
|
16075
|
+
}
|
|
16076
|
+
if (error instanceof PPDetectionError) throw error;
|
|
16077
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
16078
|
+
throw new PPDetectionError(
|
|
16079
|
+
"SESSION_CREATE_FAILED",
|
|
16080
|
+
"\u521B\u5EFA ONNX Runtime \u4F1A\u8BDD\u5931\u8D25",
|
|
16081
|
+
{ phase: "create", causeMessage: message },
|
|
16082
|
+
{ cause: error }
|
|
16083
|
+
);
|
|
16084
|
+
} finally {
|
|
16085
|
+
sessionMs += now4() - sessionStartedAt;
|
|
16086
|
+
}
|
|
16087
|
+
};
|
|
16088
|
+
let selectedPlan = plan;
|
|
16089
|
+
let sessionMs = 0;
|
|
16090
|
+
let runtimeVersion = null;
|
|
16091
|
+
let selectedCandidateIndex = -1;
|
|
16092
|
+
for (const [candidateIndex, candidate] of plan.candidates.entries()) {
|
|
16093
|
+
const candidatePlan = {
|
|
16094
|
+
...plan,
|
|
16095
|
+
variantId: candidate.variantId,
|
|
16096
|
+
actualBackend: candidate.backend,
|
|
16097
|
+
actualPrecision: candidate.precision,
|
|
16098
|
+
executionMode: candidate.executionMode,
|
|
16099
|
+
candidates: [candidate]
|
|
16100
|
+
};
|
|
16101
|
+
try {
|
|
16102
|
+
executor = await createExecutorForPlan(candidatePlan);
|
|
16103
|
+
selectedPlan = candidatePlan;
|
|
16104
|
+
selectedCandidateIndex = candidateIndex;
|
|
15911
16105
|
break;
|
|
15912
16106
|
} catch (error) {
|
|
15913
16107
|
const mapped = error instanceof PPDetectionError ? error : new PPDetectionError("SESSION_CREATE_FAILED", String(error));
|
|
@@ -15917,11 +16111,6 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15917
16111
|
} catch {
|
|
15918
16112
|
}
|
|
15919
16113
|
executor = void 0;
|
|
15920
|
-
try {
|
|
15921
|
-
await activeBridge?.dispose();
|
|
15922
|
-
} catch {
|
|
15923
|
-
}
|
|
15924
|
-
activeBridge = void 0;
|
|
15925
16114
|
if (!hasNext) {
|
|
15926
16115
|
throw mapped;
|
|
15927
16116
|
}
|
|
@@ -15939,22 +16128,75 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15939
16128
|
}
|
|
15940
16129
|
}
|
|
15941
16130
|
if (!executor) throw new PPDetectionError("SESSION_CREATE_FAILED", "\u65E0\u6CD5\u521B\u5EFA\u68C0\u6D4B Session");
|
|
15942
|
-
const
|
|
16131
|
+
const runtime = {
|
|
16132
|
+
runtimeVersion,
|
|
16133
|
+
environment: {
|
|
16134
|
+
userAgent: globalThis.navigator?.userAgent ?? null,
|
|
16135
|
+
platform: globalThis.navigator?.platform ?? null,
|
|
16136
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
16137
|
+
},
|
|
16138
|
+
requestedBackend: options.backend ?? "auto",
|
|
16139
|
+
backend: selectedPlan.actualBackend,
|
|
16140
|
+
precision: selectedPlan.actualPrecision,
|
|
16141
|
+
mode: selectedPlan.executionMode,
|
|
16142
|
+
fallbacks,
|
|
16143
|
+
capabilities
|
|
16144
|
+
};
|
|
16145
|
+
let activeExecutor = executor;
|
|
16146
|
+
const fallbackExecutor = {
|
|
16147
|
+
async run(input, signal) {
|
|
16148
|
+
const attemptInput = runtime.mode === "worker" && options.allowFallback === true && selectedCandidateIndex < plan.candidates.length - 1 ? { ...input, data: input.data.slice() } : input;
|
|
16149
|
+
try {
|
|
16150
|
+
return await activeExecutor.run(attemptInput, signal);
|
|
16151
|
+
} catch (error) {
|
|
16152
|
+
if (options.allowFallback !== true || selectedCandidateIndex < 0 || selectedCandidateIndex >= plan.candidates.length - 1) {
|
|
16153
|
+
throw error;
|
|
16154
|
+
}
|
|
16155
|
+
const failedCandidate = plan.candidates[selectedCandidateIndex];
|
|
16156
|
+
const mapped = error instanceof PPDetectionError ? error : new PPDetectionError("INFERENCE_FAILED", String(error), {}, { cause: error });
|
|
16157
|
+
if (mapped.code === "ABORTED") throw mapped;
|
|
16158
|
+
const nextCandidate = plan.candidates[selectedCandidateIndex + 1];
|
|
16159
|
+
const nextPlan = {
|
|
16160
|
+
...plan,
|
|
16161
|
+
variantId: nextCandidate.variantId,
|
|
16162
|
+
actualBackend: nextCandidate.backend,
|
|
16163
|
+
actualPrecision: nextCandidate.precision,
|
|
16164
|
+
executionMode: nextCandidate.executionMode,
|
|
16165
|
+
candidates: [nextCandidate]
|
|
16166
|
+
};
|
|
16167
|
+
await activeExecutor.dispose();
|
|
16168
|
+
const nextExecutor = await createExecutorForPlan(nextPlan);
|
|
16169
|
+
activeExecutor = nextExecutor;
|
|
16170
|
+
selectedCandidateIndex += 1;
|
|
16171
|
+
selectedPlan = nextPlan;
|
|
16172
|
+
runtime.backend = nextPlan.actualBackend;
|
|
16173
|
+
runtime.precision = nextPlan.actualPrecision;
|
|
16174
|
+
runtime.mode = nextPlan.executionMode;
|
|
16175
|
+
runtime.runtimeVersion = runtimeVersion;
|
|
16176
|
+
const fallback = {
|
|
16177
|
+
cause: mapped.cause ?? mapped,
|
|
16178
|
+
code: mapped.code,
|
|
16179
|
+
message: mapped.message,
|
|
16180
|
+
precision: failedCandidate.precision,
|
|
16181
|
+
provider: failedCandidate.backend,
|
|
16182
|
+
stage: "inference",
|
|
16183
|
+
variantId: failedCandidate.variantId
|
|
16184
|
+
};
|
|
16185
|
+
fallbacks.push(fallback);
|
|
16186
|
+
options.onProgress?.({ phase: "fallback", status: "complete", fallback });
|
|
16187
|
+
return activeExecutor.run(input, signal);
|
|
16188
|
+
}
|
|
16189
|
+
},
|
|
16190
|
+
dispose: () => activeExecutor.dispose()
|
|
16191
|
+
};
|
|
15943
16192
|
loadTimings = { ...loadTimings, sessionMs, totalMs: now4() - loadStartedAt };
|
|
15944
16193
|
const detector = new PPDetectionDetectorImplementation({
|
|
15945
16194
|
capabilities,
|
|
15946
16195
|
manifest: runtimeManifest,
|
|
15947
16196
|
model: modelInfo(runtimeManifest, variant3.id, actualSource),
|
|
15948
|
-
runtime
|
|
15949
|
-
requestedBackend: options.backend ?? "auto",
|
|
15950
|
-
backend: selectedPlan.actualBackend,
|
|
15951
|
-
precision: selectedPlan.actualPrecision,
|
|
15952
|
-
mode: selectedPlan.executionMode,
|
|
15953
|
-
fallbacks,
|
|
15954
|
-
capabilities
|
|
15955
|
-
},
|
|
16197
|
+
runtime,
|
|
15956
16198
|
loadTimings,
|
|
15957
|
-
loadExecutor: () => Promise.resolve(
|
|
16199
|
+
loadExecutor: () => Promise.resolve(fallbackExecutor),
|
|
15958
16200
|
onProgress: options.onProgress,
|
|
15959
16201
|
clearCurrentModelCache: () => modelManager.clearCurrentModelCache(),
|
|
15960
16202
|
clearAllCache: () => modelManager.clearAllCache(),
|
|
@@ -15962,6 +16204,7 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15962
16204
|
disposeResources: () => modelManager.dispose()
|
|
15963
16205
|
});
|
|
15964
16206
|
await detector.load({ signal: options.signal });
|
|
16207
|
+
loadTimings.totalMs = now4() - loadStartedAt;
|
|
15965
16208
|
options.onProgress?.({ phase: "ready", status: "complete" });
|
|
15966
16209
|
return detector;
|
|
15967
16210
|
} catch (error) {
|
|
@@ -15969,10 +16212,6 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15969
16212
|
await executor?.dispose();
|
|
15970
16213
|
} catch {
|
|
15971
16214
|
}
|
|
15972
|
-
try {
|
|
15973
|
-
await activeBridge?.dispose();
|
|
15974
|
-
} catch {
|
|
15975
|
-
}
|
|
15976
16215
|
try {
|
|
15977
16216
|
await modelManager.dispose();
|
|
15978
16217
|
} catch {
|
|
@@ -15982,8 +16221,11 @@ ${u}`, c = n.createShaderModule({ code: d, label: e.name });
|
|
|
15982
16221
|
}
|
|
15983
16222
|
async function clearModelCache() {
|
|
15984
16223
|
const manager = new ModelManager();
|
|
15985
|
-
|
|
15986
|
-
|
|
16224
|
+
try {
|
|
16225
|
+
await manager.clearAllCache();
|
|
16226
|
+
} finally {
|
|
16227
|
+
await manager.dispose();
|
|
16228
|
+
}
|
|
15987
16229
|
}
|
|
15988
16230
|
|
|
15989
16231
|
// src/browser-global.ts
|