chore: deploy chat app 838143e
Browse files- flutter_bootstrap.js +1 -1
- index.html +1 -1
- llamadart-build.json +1 -1
- main.dart.js +0 -0
- webgpu_bridge/llama_webgpu_bridge.d.ts +49 -0
- webgpu_bridge/llama_webgpu_bridge.js +596 -108
- webgpu_bridge/llama_webgpu_core.js +0 -0
- webgpu_bridge/llama_webgpu_core.wasm +2 -2
- webgpu_bridge/llama_webgpu_core_mem64.js +0 -0
- webgpu_bridge/llama_webgpu_core_mem64.wasm +2 -2
- webgpu_bridge/manifest.json +31 -31
- webgpu_bridge/sha256sums.txt +6 -6
flutter_bootstrap.js
CHANGED
|
@@ -42,6 +42,6 @@ _flutter.buildConfig = {"engineRevision":"5d531788691ec3404cac0cee66ead4007b1773
|
|
| 42 |
|
| 43 |
_flutter.loader.load({
|
| 44 |
serviceWorkerSettings: {
|
| 45 |
-
serviceWorkerVersion: "
|
| 46 |
}
|
| 47 |
});
|
|
|
|
| 42 |
|
| 43 |
_flutter.loader.load({
|
| 44 |
serviceWorkerSettings: {
|
| 45 |
+
serviceWorkerVersion: "1025218781" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
| 46 |
}
|
| 47 |
});
|
index.html
CHANGED
|
@@ -211,7 +211,7 @@
|
|
| 211 |
typeof configuredRepo === 'string' && configuredRepo.length > 0
|
| 212 |
? configuredRepo
|
| 213 |
: 'leehack/llama-web-bridge-assets';
|
| 214 |
-
const defaultBridgeAssetsTag = 'v0.1.
|
| 215 |
const defaultBridgeLlamaCppTag = 'v0.4.1';
|
| 216 |
const bridgeAssetsTag =
|
| 217 |
typeof configuredTag === 'string' && configuredTag.length > 0
|
|
|
|
| 211 |
typeof configuredRepo === 'string' && configuredRepo.length > 0
|
| 212 |
? configuredRepo
|
| 213 |
: 'leehack/llama-web-bridge-assets';
|
| 214 |
+
const defaultBridgeAssetsTag = 'v0.1.47';
|
| 215 |
const defaultBridgeLlamaCppTag = 'v0.4.1';
|
| 216 |
const bridgeAssetsTag =
|
| 217 |
typeof configuredTag === 'string' && configuredTag.length > 0
|
llamadart-build.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
{"commit":"
|
|
|
|
| 1 |
+
{"commit":"838143e3eb8160cd03ce8cf2758a99e03c249ffc","tree":"b07164124f1115bcae6de9ba399f5fef1577ece4","base_href":"/","target":"lib/main.dart","flutter_version":"3.47.1"}
|
main.dart.js
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
webgpu_bridge/llama_webgpu_bridge.d.ts
CHANGED
|
@@ -143,6 +143,48 @@ export interface TextToSpeechResult {
|
|
| 143 |
truncated: boolean;
|
| 144 |
}
|
| 145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
export type ModelMetadata = Record<string, unknown>;
|
| 147 |
|
| 148 |
export interface StateLoadResult {
|
|
@@ -189,6 +231,13 @@ export class LlamaWebGpuBridge {
|
|
| 189 |
supportsAudio(): boolean;
|
| 190 |
getTextToSpeechCapabilities(): Promise<TextToSpeechCapabilities>;
|
| 191 |
synthesizeSpeech(options: TextToSpeechOptions): Promise<TextToSpeechResult>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
getModelMetadata(): ModelMetadata | null;
|
| 194 |
getContextSize(): number;
|
|
|
|
| 143 |
truncated: boolean;
|
| 144 |
}
|
| 145 |
|
| 146 |
+
export interface DecisionCapabilities {
|
| 147 |
+
apiVersion: number;
|
| 148 |
+
supported: boolean;
|
| 149 |
+
/** Why the loaded model cannot run decision heads; absent when supported. */
|
| 150 |
+
reason?: string;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
export interface DecisionHeadOptions {
|
| 154 |
+
/** Laya `rl_agent_config.json` text; omit to read the head's `laya.config` metadata. */
|
| 155 |
+
configJson?: string | null;
|
| 156 |
+
/** Download progress of a URL head, in bytes. */
|
| 157 |
+
onProgress?: (progress: { loaded: number; total: number }) => void;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
export interface DecisionHeadInfo {
|
| 161 |
+
apiVersion: number;
|
| 162 |
+
handle: number;
|
| 163 |
+
hiddenSize: number;
|
| 164 |
+
clsToken: number;
|
| 165 |
+
sepToken: number;
|
| 166 |
+
maskToken: number;
|
| 167 |
+
maskText: string;
|
| 168 |
+
configJson: string;
|
| 169 |
+
deviceName: string;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
/** 0 = choice, 1 = score, 2 = noul. */
|
| 173 |
+
export type DecisionQuestionType = 0 | 1 | 2;
|
| 174 |
+
|
| 175 |
+
export interface DecisionSequence {
|
| 176 |
+
tokens: Int32Array | readonly number[];
|
| 177 |
+
/** Token indexes of the option markers, in option order. */
|
| 178 |
+
markers: Int32Array | readonly number[];
|
| 179 |
+
questionType: DecisionQuestionType;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
export interface DecisionOutput {
|
| 183 |
+
/** One raw logit per marker. */
|
| 184 |
+
logits: Float32Array;
|
| 185 |
+
actLogits: Float32Array;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
export type ModelMetadata = Record<string, unknown>;
|
| 189 |
|
| 190 |
export interface StateLoadResult {
|
|
|
|
| 231 |
supportsAudio(): boolean;
|
| 232 |
getTextToSpeechCapabilities(): Promise<TextToSpeechCapabilities>;
|
| 233 |
synthesizeSpeech(options: TextToSpeechOptions): Promise<TextToSpeechResult>;
|
| 234 |
+
getDecisionCapabilities(): Promise<DecisionCapabilities>;
|
| 235 |
+
loadDecisionHead(
|
| 236 |
+
source: string | ArrayBuffer | ArrayBufferView,
|
| 237 |
+
options?: DecisionHeadOptions,
|
| 238 |
+
): Promise<DecisionHeadInfo>;
|
| 239 |
+
runDecision(handle: number, sequences: readonly DecisionSequence[]): Promise<DecisionOutput[]>;
|
| 240 |
+
freeDecisionHead(handle: number): Promise<void>;
|
| 241 |
|
| 242 |
getModelMetadata(): ModelMetadata | null;
|
| 243 |
getContextSize(): number;
|
webgpu_bridge/llama_webgpu_bridge.js
CHANGED
|
@@ -8,6 +8,8 @@ var defaultModelCacheName = "llamadart-webgpu-model-cache-v1";
|
|
| 8 |
var BRIDGE_DISPOSED_MESSAGE = "Bridge has been disposed.";
|
| 9 |
var GENERATION_ALREADY_ACTIVE_RC = -7;
|
| 10 |
var GENERATION_ALREADY_ACTIVE_MESSAGE = "Generation is already active on this bridge runtime.";
|
|
|
|
|
|
|
| 11 |
function createAbortError(message) {
|
| 12 |
if (typeof DOMException === "function") {
|
| 13 |
return new DOMException(message, "AbortError");
|
|
@@ -332,8 +334,7 @@ async function writeResponseToFsFileWithProgress(response, fs, filePath, progres
|
|
| 332 |
const useBigIntPosition = writeOptions.useBigIntPosition === true;
|
| 333 |
const startOffset = parsePositiveInteger(writeOptions.startOffset);
|
| 334 |
const preservePartialOnError = writeOptions.preservePartialOnError === true;
|
| 335 |
-
const
|
| 336 |
-
const appendMode = allowAppend && startOffset > 0;
|
| 337 |
const chunkTimeoutMs = parsePositiveInteger(writeOptions.chunkTimeoutMs);
|
| 338 |
const signal = writeOptions.signal || null;
|
| 339 |
const abortMessage = writeOptions.abortMessage || "Model transfer was cancelled.";
|
|
@@ -503,6 +504,120 @@ function toFloat32Array(value) {
|
|
| 503 |
}
|
| 504 |
return null;
|
| 505 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
async function decodeImageBytesToRgb(bytes, options = {}) {
|
| 507 |
const sourceBytes = toUint8Array(bytes);
|
| 508 |
if (!sourceBytes || sourceBytes.length === 0) {
|
|
@@ -602,6 +717,37 @@ async function decodeImageBytesToRgb(bytes, options = {}) {
|
|
| 602 |
}
|
| 603 |
}
|
| 604 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 605 |
function serializeWorkerError(error) {
|
| 606 |
if (!error) {
|
| 607 |
return "Unknown worker error";
|
|
@@ -861,6 +1007,29 @@ function installBridgeWorkerHost() {
|
|
| 861 |
);
|
| 862 |
return;
|
| 863 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 864 |
if (method === "unloadMultimodalProjector") {
|
| 865 |
const value2 = await bridge.unloadMultimodalProjector();
|
| 866 |
self.postMessage({ type: "result", id, value: value2, state: snapshotBridgeState(bridge) });
|
|
@@ -1059,7 +1228,7 @@ var BridgeWorkerProxy = class {
|
|
| 1059 |
async call(method, args, onEvent, transferList = [], operationMeta = null) {
|
| 1060 |
await this._ready;
|
| 1061 |
const id = this._nextId++;
|
| 1062 |
-
const timeoutMs = this._resolveRequestTimeoutMs(method);
|
| 1063 |
const transfers = Array.isArray(transferList) ? transferList.filter((item) => item != null) : [];
|
| 1064 |
return new Promise((resolve, reject) => {
|
| 1065 |
let timeoutHandle = null;
|
|
@@ -1127,7 +1296,7 @@ var BridgeWorkerProxy = class {
|
|
| 1127 |
}
|
| 1128 |
}, timeoutMs);
|
| 1129 |
}
|
| 1130 |
-
_resolveRequestTimeoutMs(method) {
|
| 1131 |
const explicitGlobal = Number(this._config.workerRequestTimeoutMs);
|
| 1132 |
const clamp = (value, fallback) => {
|
| 1133 |
if (!Number.isFinite(value) || value <= 0) {
|
|
@@ -1147,6 +1316,13 @@ var BridgeWorkerProxy = class {
|
|
| 1147 |
if (method === "synthesizeSpeech") {
|
| 1148 |
return clamp(Number(this._config.workerTextToSpeechTimeoutMs), clamp(explicitGlobal, 20 * 60 * 1e3));
|
| 1149 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1150 |
return clamp(explicitGlobal, 12e4);
|
| 1151 |
}
|
| 1152 |
async dispose() {
|
|
@@ -1191,6 +1367,7 @@ var LlamaWebGpuBridgeRuntime = class {
|
|
| 1191 |
this._mmSupportsAudio = false;
|
| 1192 |
this._mediaFileCounter = 0;
|
| 1193 |
this._stateFileCounter = 0;
|
|
|
|
| 1194 |
this._stagedMediaPaths = [];
|
| 1195 |
this._nCtx = 4096;
|
| 1196 |
this._abortRequested = false;
|
|
@@ -1485,49 +1662,18 @@ var LlamaWebGpuBridgeRuntime = class {
|
|
| 1485 |
return () => {
|
| 1486 |
};
|
| 1487 |
}
|
| 1488 |
-
_logLevelForName(level) {
|
| 1489 |
-
switch (level) {
|
| 1490 |
-
case "debug":
|
| 1491 |
-
return 0;
|
| 1492 |
-
case "log":
|
| 1493 |
-
case "info":
|
| 1494 |
-
return 1;
|
| 1495 |
-
case "warn":
|
| 1496 |
-
return 2;
|
| 1497 |
-
case "error":
|
| 1498 |
-
return 3;
|
| 1499 |
-
default:
|
| 1500 |
-
return 1;
|
| 1501 |
-
}
|
| 1502 |
-
}
|
| 1503 |
-
_logThresholdForConfiguredLevel(level) {
|
| 1504 |
-
switch (level) {
|
| 1505 |
-
case 0:
|
| 1506 |
-
return 99;
|
| 1507 |
-
case 1:
|
| 1508 |
-
return 0;
|
| 1509 |
-
case 2:
|
| 1510 |
-
return 1;
|
| 1511 |
-
case 3:
|
| 1512 |
-
return 2;
|
| 1513 |
-
case 4:
|
| 1514 |
-
return 3;
|
| 1515 |
-
default:
|
| 1516 |
-
return 1;
|
| 1517 |
-
}
|
| 1518 |
-
}
|
| 1519 |
_shouldEmitLoggerLevel(level) {
|
| 1520 |
const current = Number(this._logLevel);
|
| 1521 |
if (!Number.isFinite(current) || current < 0) {
|
| 1522 |
return true;
|
| 1523 |
}
|
| 1524 |
-
const threshold =
|
| 1525 |
Math.max(0, Math.min(4, Math.trunc(current)))
|
| 1526 |
);
|
| 1527 |
if (threshold > 3) {
|
| 1528 |
return false;
|
| 1529 |
}
|
| 1530 |
-
return
|
| 1531 |
}
|
| 1532 |
_emitLogger(level, message) {
|
| 1533 |
if (!this._shouldEmitLoggerLevel(level)) {
|
|
@@ -1762,19 +1908,7 @@ var LlamaWebGpuBridgeRuntime = class {
|
|
| 1762 |
];
|
| 1763 |
}
|
| 1764 |
_nativeLoadOptionTypes() {
|
| 1765 |
-
return
|
| 1766 |
-
"number",
|
| 1767 |
-
"number",
|
| 1768 |
-
"number",
|
| 1769 |
-
"number",
|
| 1770 |
-
"number",
|
| 1771 |
-
"number",
|
| 1772 |
-
"number",
|
| 1773 |
-
"number",
|
| 1774 |
-
"number",
|
| 1775 |
-
"number",
|
| 1776 |
-
"number"
|
| 1777 |
-
];
|
| 1778 |
}
|
| 1779 |
async _tryLoadModelFromRemoteFetchBackend(core, url, options = {}) {
|
| 1780 |
if (!this._canUseRemoteFetchBackend(options)) {
|
|
@@ -2060,6 +2194,15 @@ var LlamaWebGpuBridgeRuntime = class {
|
|
| 2060 |
}
|
| 2061 |
}
|
| 2062 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2063 |
_deleteFsFile(path) {
|
| 2064 |
if (!this._core || typeof path !== "string" || path.length === 0) {
|
| 2065 |
return false;
|
|
@@ -2704,7 +2847,6 @@ var LlamaWebGpuBridgeRuntime = class {
|
|
| 2704 |
{
|
| 2705 |
useBigIntPosition: this._coreVariant === "wasm64",
|
| 2706 |
startOffset: resumeOffset,
|
| 2707 |
-
allowAppend: resumeOffset > 0,
|
| 2708 |
preservePartialOnError: true,
|
| 2709 |
totalBytes: knownTotalBytes,
|
| 2710 |
chunkTimeoutMs: streamChunkTimeoutMs,
|
|
@@ -3288,6 +3430,201 @@ var LlamaWebGpuBridgeRuntime = class {
|
|
| 3288 |
this._textToSpeechDone = null;
|
| 3289 |
}
|
| 3290 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3291 |
_clearStagedMediaFiles() {
|
| 3292 |
if (!this._core || this._stagedMediaPaths.length === 0) {
|
| 3293 |
this._stagedMediaPaths = [];
|
|
@@ -3993,6 +4330,8 @@ var LlamaWebGpuBridge = class {
|
|
| 3993 |
this._disposed = false;
|
| 3994 |
this._disposePromise = null;
|
| 3995 |
this._disposalWaiters = /* @__PURE__ */ new Set();
|
|
|
|
|
|
|
| 3996 |
if (this._shouldUseWorker()) {
|
| 3997 |
try {
|
| 3998 |
this._workerProxy = new BridgeWorkerProxy({
|
|
@@ -4526,7 +4865,7 @@ var LlamaWebGpuBridge = class {
|
|
| 4526 |
}
|
| 4527 |
_isRecoverableWorkerFsError(error) {
|
| 4528 |
const text = serializeWorkerError(error).toLowerCase();
|
| 4529 |
-
return text.includes("fs error") || text.includes("no such file") || text.includes("not found") || text.includes("invalid argument") || text.includes("
|
| 4530 |
}
|
| 4531 |
_isWorkerRequestTimeoutError(error) {
|
| 4532 |
const text = serializeWorkerError(error).toLowerCase();
|
|
@@ -4610,9 +4949,6 @@ var LlamaWebGpuBridge = class {
|
|
| 4610 |
const text = serializeWorkerError(error).toLowerCase();
|
| 4611 |
return text.includes("worker completion stalled") || text.includes("worker createcompletion stalled") || text.includes("worker timed out") || text.includes("worker timeout");
|
| 4612 |
}
|
| 4613 |
-
_isForcedCpuMultimodalFallbackError(error) {
|
| 4614 |
-
return error && typeof error === "object" && error.llamadartForceCpuMultimodal === true;
|
| 4615 |
-
}
|
| 4616 |
_isCpuModelMode() {
|
| 4617 |
const requestedLayers = Number(this._loadedModelOptions?.nGpuLayers);
|
| 4618 |
if (Number.isFinite(requestedLayers)) {
|
|
@@ -4655,12 +4991,11 @@ var LlamaWebGpuBridge = class {
|
|
| 4655 |
const multimodalRuntimeRequired = mediaPartsRequested || textToSpeechRequested;
|
| 4656 |
const shouldEnsureMultimodalInRuntime = multimodalRuntimeRequired && typeof this._loadedMmProjUrl === "string" && this._loadedMmProjUrl.length > 0;
|
| 4657 |
const workerTimedOut = this._isWorkerTimeoutError(fallbackError);
|
| 4658 |
-
const forcedCpuFallback = this._isForcedCpuMultimodalFallbackError(fallbackError);
|
| 4659 |
const dispatchWorkgroupFallback = this._isDispatchWorkgroupLimitError(fallbackError);
|
| 4660 |
const loadedGpuLayers = Number(this._loadedModelOptions?.nGpuLayers);
|
| 4661 |
const metadataGpuLayers = Number(this._metadata?.["llamadart.webgpu.n_gpu_layers"]);
|
| 4662 |
const modelLoadedWithGpu = Number.isFinite(loadedGpuLayers) ? loadedGpuLayers !== 0 : Number.isFinite(metadataGpuLayers) ? metadataGpuLayers !== 0 : true;
|
| 4663 |
-
const shouldUseCpuMultimodalFallback = multimodalRuntimeRequired && modelLoadedWithGpu && (dispatchWorkgroupFallback ||
|
| 4664 |
try {
|
| 4665 |
if (Number(this._runtime?._modelBytes) > 0 && !forceReloadRequested && !shouldUseCpuMultimodalFallback) {
|
| 4666 |
if (shouldEnsureMultimodalInRuntime) {
|
|
@@ -4689,10 +5024,6 @@ var LlamaWebGpuBridge = class {
|
|
| 4689 |
this._emitBridgeWarn(
|
| 4690 |
"llamadart: retrying text-to-speech once with CPU fallback after WebGPU failure."
|
| 4691 |
);
|
| 4692 |
-
} else if (forcedCpuFallback) {
|
| 4693 |
-
this._emitBridgeWarn(
|
| 4694 |
-
"llamadart: using CPU fallback for multimodal generation stability."
|
| 4695 |
-
);
|
| 4696 |
} else if (workerTimedOut) {
|
| 4697 |
this._emitBridgeWarn(
|
| 4698 |
"llamadart: retrying multimodal generation with CPU fallback after worker timeout."
|
|
@@ -4884,44 +5215,13 @@ var LlamaWebGpuBridge = class {
|
|
| 4884 |
}
|
| 4885 |
return 2;
|
| 4886 |
}
|
| 4887 |
-
_bridgeLogLevelForName(level) {
|
| 4888 |
-
switch (level) {
|
| 4889 |
-
case "debug":
|
| 4890 |
-
return 0;
|
| 4891 |
-
case "log":
|
| 4892 |
-
case "info":
|
| 4893 |
-
return 1;
|
| 4894 |
-
case "warn":
|
| 4895 |
-
return 2;
|
| 4896 |
-
case "error":
|
| 4897 |
-
return 3;
|
| 4898 |
-
default:
|
| 4899 |
-
return 1;
|
| 4900 |
-
}
|
| 4901 |
-
}
|
| 4902 |
-
_bridgeLogThresholdForConfiguredLevel(level) {
|
| 4903 |
-
switch (level) {
|
| 4904 |
-
case 0:
|
| 4905 |
-
return 99;
|
| 4906 |
-
case 1:
|
| 4907 |
-
return 0;
|
| 4908 |
-
case 2:
|
| 4909 |
-
return 1;
|
| 4910 |
-
case 3:
|
| 4911 |
-
return 2;
|
| 4912 |
-
case 4:
|
| 4913 |
-
return 3;
|
| 4914 |
-
default:
|
| 4915 |
-
return 1;
|
| 4916 |
-
}
|
| 4917 |
-
}
|
| 4918 |
_shouldEmitBridgeLevel(level) {
|
| 4919 |
const configured = this._resolvedBridgeLogLevel();
|
| 4920 |
-
const threshold =
|
| 4921 |
if (threshold > 3) {
|
| 4922 |
return false;
|
| 4923 |
}
|
| 4924 |
-
return
|
| 4925 |
}
|
| 4926 |
_shouldSuppressBridgeWarn(message) {
|
| 4927 |
const text = String(message || "").trim();
|
|
@@ -4959,21 +5259,14 @@ var LlamaWebGpuBridge = class {
|
|
| 4959 |
}
|
| 4960 |
}
|
| 4961 |
_disableWorkerFallback(error) {
|
| 4962 |
-
const
|
| 4963 |
-
const reason = forcedCpuMultimodal ? "multimodal_stability_mode" : serializeWorkerError(error);
|
| 4964 |
this._workerFallbackReason = reason;
|
| 4965 |
if (typeof globalThis !== "undefined") {
|
| 4966 |
globalThis.__llamadartBridgeWorkerFallbackReason = reason;
|
| 4967 |
}
|
| 4968 |
-
|
| 4969 |
-
|
| 4970 |
-
|
| 4971 |
-
);
|
| 4972 |
-
} else {
|
| 4973 |
-
this._emitBridgeWarn(
|
| 4974 |
-
`llamadart: bridge worker unavailable, falling back to main thread (${reason})`
|
| 4975 |
-
);
|
| 4976 |
-
}
|
| 4977 |
if (this._workerProxy) {
|
| 4978 |
const workerProxy = this._workerProxy;
|
| 4979 |
this._advanceWorkerGeneration();
|
|
@@ -4991,9 +5284,6 @@ var LlamaWebGpuBridge = class {
|
|
| 4991 |
}
|
| 4992 |
if (this._runtime && Array.isArray(this._runtime._runtimeNotes) && typeof reason === "string" && reason.length > 0) {
|
| 4993 |
this._runtime._runtimeNotes.push(`worker_fallback:${reason}`);
|
| 4994 |
-
if (forcedCpuMultimodal) {
|
| 4995 |
-
this._runtime._runtimeNotes.push("worker_fallback_forced_multimodal");
|
| 4996 |
-
}
|
| 4997 |
}
|
| 4998 |
}
|
| 4999 |
async _callWorker(method, args, onEvent, transferList = []) {
|
|
@@ -5517,6 +5807,203 @@ var LlamaWebGpuBridge = class {
|
|
| 5517 |
throw error;
|
| 5518 |
}
|
| 5519 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5520 |
async tokenize(text, addSpecial = true) {
|
| 5521 |
return this._runExclusive(
|
| 5522 |
() => this._tokenizeUnlocked(text, addSpecial),
|
|
@@ -5793,6 +6280,7 @@ var LlamaWebGpuBridge = class {
|
|
| 5793 |
this._loadedMmProjUrl = null;
|
| 5794 |
this._workerFallbackReason = null;
|
| 5795 |
this._multimodalWorkerCpuMode = false;
|
|
|
|
| 5796 |
this._lifecycleState = "disposed";
|
| 5797 |
}
|
| 5798 |
}
|
|
|
|
| 8 |
var BRIDGE_DISPOSED_MESSAGE = "Bridge has been disposed.";
|
| 9 |
var GENERATION_ALREADY_ACTIVE_RC = -7;
|
| 10 |
var GENERATION_ALREADY_ACTIVE_MESSAGE = "Generation is already active on this bridge runtime.";
|
| 11 |
+
var DECISION_API_VERSION = 1;
|
| 12 |
+
var DECISION_WORKER_TIMEOUT_PER_SEQUENCE_MS = 60 * 1e3;
|
| 13 |
function createAbortError(message) {
|
| 14 |
if (typeof DOMException === "function") {
|
| 15 |
return new DOMException(message, "AbortError");
|
|
|
|
| 334 |
const useBigIntPosition = writeOptions.useBigIntPosition === true;
|
| 335 |
const startOffset = parsePositiveInteger(writeOptions.startOffset);
|
| 336 |
const preservePartialOnError = writeOptions.preservePartialOnError === true;
|
| 337 |
+
const appendMode = startOffset > 0;
|
|
|
|
| 338 |
const chunkTimeoutMs = parsePositiveInteger(writeOptions.chunkTimeoutMs);
|
| 339 |
const signal = writeOptions.signal || null;
|
| 340 |
const abortMessage = writeOptions.abortMessage || "Model transfer was cancelled.";
|
|
|
|
| 504 |
}
|
| 505 |
return null;
|
| 506 |
}
|
| 507 |
+
function isInt32(value) {
|
| 508 |
+
return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
|
| 509 |
+
}
|
| 510 |
+
function decisionHandleFrom(handle) {
|
| 511 |
+
if (!isInt32(handle) || handle <= 0) {
|
| 512 |
+
throw new TypeError(`Decision head handle must be a positive integer, got ${String(handle)}.`);
|
| 513 |
+
}
|
| 514 |
+
return handle;
|
| 515 |
+
}
|
| 516 |
+
function decisionHeadBytes(source) {
|
| 517 |
+
if (source instanceof ArrayBuffer) {
|
| 518 |
+
return new Uint8Array(source);
|
| 519 |
+
}
|
| 520 |
+
if (ArrayBuffer.isView(source)) {
|
| 521 |
+
return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
|
| 522 |
+
}
|
| 523 |
+
return null;
|
| 524 |
+
}
|
| 525 |
+
function decisionIntegerList(value, label) {
|
| 526 |
+
const isList = Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
|
| 527 |
+
if (!isList) {
|
| 528 |
+
throw new TypeError(`${label} must be an array or typed array of integers.`);
|
| 529 |
+
}
|
| 530 |
+
const list = (
|
| 531 |
+
/** @type {ArrayLike<unknown>} */
|
| 532 |
+
value
|
| 533 |
+
);
|
| 534 |
+
const out = new Int32Array(list.length);
|
| 535 |
+
for (let index = 0; index < list.length; index += 1) {
|
| 536 |
+
const item = list[index];
|
| 537 |
+
if (!isInt32(item)) {
|
| 538 |
+
throw new TypeError(`${label}[${index}] is ${String(item)}; expected a 32-bit integer.`);
|
| 539 |
+
}
|
| 540 |
+
out[index] = /** @type {number} */
|
| 541 |
+
item;
|
| 542 |
+
}
|
| 543 |
+
return out;
|
| 544 |
+
}
|
| 545 |
+
function normalizeDecisionSequences(sequences) {
|
| 546 |
+
if (!Array.isArray(sequences)) {
|
| 547 |
+
throw new TypeError("Decision sequences must be an array.");
|
| 548 |
+
}
|
| 549 |
+
return sequences.map((sequence, index) => {
|
| 550 |
+
const label = `Decision sequence ${index}`;
|
| 551 |
+
if (!sequence || typeof sequence !== "object") {
|
| 552 |
+
throw new TypeError(`${label} must be an object with tokens, markers and questionType.`);
|
| 553 |
+
}
|
| 554 |
+
const tokens = decisionIntegerList(sequence.tokens, `${label} tokens`);
|
| 555 |
+
const markers = decisionIntegerList(sequence.markers, `${label} markers`);
|
| 556 |
+
const questionType = sequence.questionType;
|
| 557 |
+
if (!isInt32(questionType)) {
|
| 558 |
+
throw new TypeError(
|
| 559 |
+
`${label} questionType is ${String(questionType)}; expected 0 (choice), 1 (score) or 2 (noul).`
|
| 560 |
+
);
|
| 561 |
+
}
|
| 562 |
+
return { tokens, markers, questionType: (
|
| 563 |
+
/** @type {number} */
|
| 564 |
+
questionType
|
| 565 |
+
) };
|
| 566 |
+
});
|
| 567 |
+
}
|
| 568 |
+
function encodeDecisionSequences(sequences) {
|
| 569 |
+
const encoded = normalizeDecisionSequences(sequences);
|
| 570 |
+
let words = 1;
|
| 571 |
+
for (const sequence of encoded) {
|
| 572 |
+
words += 3 + sequence.tokens.length + sequence.markers.length;
|
| 573 |
+
}
|
| 574 |
+
const bytes = new Uint8Array(words * 4);
|
| 575 |
+
const view = new DataView(bytes.buffer);
|
| 576 |
+
let offset = 0;
|
| 577 |
+
const put = (value) => {
|
| 578 |
+
view.setInt32(offset, value, true);
|
| 579 |
+
offset += 4;
|
| 580 |
+
};
|
| 581 |
+
put(encoded.length);
|
| 582 |
+
for (const sequence of encoded) {
|
| 583 |
+
put(sequence.questionType);
|
| 584 |
+
put(sequence.tokens.length);
|
| 585 |
+
put(sequence.markers.length);
|
| 586 |
+
sequence.tokens.forEach(put);
|
| 587 |
+
sequence.markers.forEach(put);
|
| 588 |
+
}
|
| 589 |
+
return bytes;
|
| 590 |
+
}
|
| 591 |
+
function decodeDecisionOutputs(bytes, count) {
|
| 592 |
+
const malformed = () => new Error("Decision output from the WebGPU core is malformed.");
|
| 593 |
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
| 594 |
+
let offset = 0;
|
| 595 |
+
const floats = (length) => {
|
| 596 |
+
const values = new Float32Array(length);
|
| 597 |
+
for (let index = 0; index < length; index += 1) {
|
| 598 |
+
values[index] = view.getFloat32(offset, true);
|
| 599 |
+
offset += 4;
|
| 600 |
+
}
|
| 601 |
+
return values;
|
| 602 |
+
};
|
| 603 |
+
const outputs = [];
|
| 604 |
+
for (let index = 0; index < count; index += 1) {
|
| 605 |
+
if (bytes.byteLength - offset < 8) {
|
| 606 |
+
throw malformed();
|
| 607 |
+
}
|
| 608 |
+
const logitCount = view.getInt32(offset, true);
|
| 609 |
+
const actCount = view.getInt32(offset + 4, true);
|
| 610 |
+
offset += 8;
|
| 611 |
+
if (logitCount < 0 || actCount < 0 || (logitCount + actCount) * 4 > bytes.byteLength - offset) {
|
| 612 |
+
throw malformed();
|
| 613 |
+
}
|
| 614 |
+
outputs.push({ logits: floats(logitCount), actLogits: floats(actCount) });
|
| 615 |
+
}
|
| 616 |
+
if (offset !== bytes.byteLength) {
|
| 617 |
+
throw malformed();
|
| 618 |
+
}
|
| 619 |
+
return outputs;
|
| 620 |
+
}
|
| 621 |
async function decodeImageBytesToRgb(bytes, options = {}) {
|
| 622 |
const sourceBytes = toUint8Array(bytes);
|
| 623 |
if (!sourceBytes || sourceBytes.length === 0) {
|
|
|
|
| 717 |
}
|
| 718 |
}
|
| 719 |
}
|
| 720 |
+
function logLevelForName(level) {
|
| 721 |
+
switch (level) {
|
| 722 |
+
case "debug":
|
| 723 |
+
return 0;
|
| 724 |
+
case "log":
|
| 725 |
+
case "info":
|
| 726 |
+
return 1;
|
| 727 |
+
case "warn":
|
| 728 |
+
return 2;
|
| 729 |
+
case "error":
|
| 730 |
+
return 3;
|
| 731 |
+
default:
|
| 732 |
+
return 1;
|
| 733 |
+
}
|
| 734 |
+
}
|
| 735 |
+
function logThresholdForConfiguredLevel(level) {
|
| 736 |
+
switch (level) {
|
| 737 |
+
case 0:
|
| 738 |
+
return 99;
|
| 739 |
+
case 1:
|
| 740 |
+
return 0;
|
| 741 |
+
case 2:
|
| 742 |
+
return 1;
|
| 743 |
+
case 3:
|
| 744 |
+
return 2;
|
| 745 |
+
case 4:
|
| 746 |
+
return 3;
|
| 747 |
+
default:
|
| 748 |
+
return 1;
|
| 749 |
+
}
|
| 750 |
+
}
|
| 751 |
function serializeWorkerError(error) {
|
| 752 |
if (!error) {
|
| 753 |
return "Unknown worker error";
|
|
|
|
| 1007 |
);
|
| 1008 |
return;
|
| 1009 |
}
|
| 1010 |
+
if (method === "loadDecisionHead") {
|
| 1011 |
+
const options = args[1] && typeof args[1] === "object" ? { ...args[1] } : {};
|
| 1012 |
+
options.onProgress = (progress) => {
|
| 1013 |
+
self.postMessage({ type: "event", id, event: "progress", payload: progress || {} });
|
| 1014 |
+
};
|
| 1015 |
+
const value2 = await bridge.loadDecisionHead(args[0], options);
|
| 1016 |
+
self.postMessage({ type: "result", id, value: value2 });
|
| 1017 |
+
return;
|
| 1018 |
+
}
|
| 1019 |
+
if (method === "runDecision") {
|
| 1020 |
+
const value2 = await bridge.runDecision(args[0], args[1]);
|
| 1021 |
+
const transfers = [];
|
| 1022 |
+
for (const output of Array.isArray(value2) ? value2 : []) {
|
| 1023 |
+
for (const values of [output?.logits, output?.actLogits]) {
|
| 1024 |
+
const buffer = values?.buffer;
|
| 1025 |
+
if (buffer instanceof ArrayBuffer && !transfers.includes(buffer)) {
|
| 1026 |
+
transfers.push(buffer);
|
| 1027 |
+
}
|
| 1028 |
+
}
|
| 1029 |
+
}
|
| 1030 |
+
self.postMessage({ type: "result", id, value: value2 }, transfers);
|
| 1031 |
+
return;
|
| 1032 |
+
}
|
| 1033 |
if (method === "unloadMultimodalProjector") {
|
| 1034 |
const value2 = await bridge.unloadMultimodalProjector();
|
| 1035 |
self.postMessage({ type: "result", id, value: value2, state: snapshotBridgeState(bridge) });
|
|
|
|
| 1228 |
async call(method, args, onEvent, transferList = [], operationMeta = null) {
|
| 1229 |
await this._ready;
|
| 1230 |
const id = this._nextId++;
|
| 1231 |
+
const timeoutMs = this._resolveRequestTimeoutMs(method, args);
|
| 1232 |
const transfers = Array.isArray(transferList) ? transferList.filter((item) => item != null) : [];
|
| 1233 |
return new Promise((resolve, reject) => {
|
| 1234 |
let timeoutHandle = null;
|
|
|
|
| 1296 |
}
|
| 1297 |
}, timeoutMs);
|
| 1298 |
}
|
| 1299 |
+
_resolveRequestTimeoutMs(method, args = []) {
|
| 1300 |
const explicitGlobal = Number(this._config.workerRequestTimeoutMs);
|
| 1301 |
const clamp = (value, fallback) => {
|
| 1302 |
if (!Number.isFinite(value) || value <= 0) {
|
|
|
|
| 1316 |
if (method === "synthesizeSpeech") {
|
| 1317 |
return clamp(Number(this._config.workerTextToSpeechTimeoutMs), clamp(explicitGlobal, 20 * 60 * 1e3));
|
| 1318 |
}
|
| 1319 |
+
if (method === "loadDecisionHead") {
|
| 1320 |
+
return clamp(explicitGlobal, 10 * 60 * 1e3);
|
| 1321 |
+
}
|
| 1322 |
+
if (method === "runDecision") {
|
| 1323 |
+
const sequences = Array.isArray(args?.[1]) ? args[1].length : 0;
|
| 1324 |
+
return clamp(explicitGlobal, 10 * 60 * 1e3 + sequences * DECISION_WORKER_TIMEOUT_PER_SEQUENCE_MS);
|
| 1325 |
+
}
|
| 1326 |
return clamp(explicitGlobal, 12e4);
|
| 1327 |
}
|
| 1328 |
async dispose() {
|
|
|
|
| 1367 |
this._mmSupportsAudio = false;
|
| 1368 |
this._mediaFileCounter = 0;
|
| 1369 |
this._stateFileCounter = 0;
|
| 1370 |
+
this._decisionFileCounter = 0;
|
| 1371 |
this._stagedMediaPaths = [];
|
| 1372 |
this._nCtx = 4096;
|
| 1373 |
this._abortRequested = false;
|
|
|
|
| 1662 |
return () => {
|
| 1663 |
};
|
| 1664 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1665 |
_shouldEmitLoggerLevel(level) {
|
| 1666 |
const current = Number(this._logLevel);
|
| 1667 |
if (!Number.isFinite(current) || current < 0) {
|
| 1668 |
return true;
|
| 1669 |
}
|
| 1670 |
+
const threshold = logThresholdForConfiguredLevel(
|
| 1671 |
Math.max(0, Math.min(4, Math.trunc(current)))
|
| 1672 |
);
|
| 1673 |
if (threshold > 3) {
|
| 1674 |
return false;
|
| 1675 |
}
|
| 1676 |
+
return logLevelForName(level) >= threshold;
|
| 1677 |
}
|
| 1678 |
_emitLogger(level, message) {
|
| 1679 |
if (!this._shouldEmitLoggerLevel(level)) {
|
|
|
|
| 1908 |
];
|
| 1909 |
}
|
| 1910 |
_nativeLoadOptionTypes() {
|
| 1911 |
+
return this._nativeLoadOptionValues().map(() => "number");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1912 |
}
|
| 1913 |
async _tryLoadModelFromRemoteFetchBackend(core, url, options = {}) {
|
| 1914 |
if (!this._canUseRemoteFetchBackend(options)) {
|
|
|
|
| 2194 |
}
|
| 2195 |
}
|
| 2196 |
}
|
| 2197 |
+
_unlinkDecisionFile(path) {
|
| 2198 |
+
if (!this._core || typeof path !== "string" || path.length === 0) {
|
| 2199 |
+
return;
|
| 2200 |
+
}
|
| 2201 |
+
try {
|
| 2202 |
+
this._core.FS.unlink(path);
|
| 2203 |
+
} catch (_) {
|
| 2204 |
+
}
|
| 2205 |
+
}
|
| 2206 |
_deleteFsFile(path) {
|
| 2207 |
if (!this._core || typeof path !== "string" || path.length === 0) {
|
| 2208 |
return false;
|
|
|
|
| 2847 |
{
|
| 2848 |
useBigIntPosition: this._coreVariant === "wasm64",
|
| 2849 |
startOffset: resumeOffset,
|
|
|
|
| 2850 |
preservePartialOnError: true,
|
| 2851 |
totalBytes: knownTotalBytes,
|
| 2852 |
chunkTimeoutMs: streamChunkTimeoutMs,
|
|
|
|
| 3430 |
this._textToSpeechDone = null;
|
| 3431 |
}
|
| 3432 |
}
|
| 3433 |
+
getDecisionCapabilities() {
|
| 3434 |
+
const unsupported = (reason) => ({
|
| 3435 |
+
apiVersion: DECISION_API_VERSION,
|
| 3436 |
+
supported: false,
|
| 3437 |
+
reason
|
| 3438 |
+
});
|
| 3439 |
+
const core = this._core;
|
| 3440 |
+
if (!core) {
|
| 3441 |
+
return unsupported("WebGPU core is not initialized");
|
| 3442 |
+
}
|
| 3443 |
+
if (typeof core._llamadart_webgpu_decision_capabilities_json !== "function") {
|
| 3444 |
+
return unsupported("This WebGPU core build does not include decision heads.");
|
| 3445 |
+
}
|
| 3446 |
+
const coreVersion = Number(
|
| 3447 |
+
core.ccall("llamadart_webgpu_decision_api_version", "number", [], [])
|
| 3448 |
+
);
|
| 3449 |
+
if (coreVersion !== DECISION_API_VERSION) {
|
| 3450 |
+
return unsupported(
|
| 3451 |
+
`The WebGPU core implements decision API version ${coreVersion}; this bridge needs version ${DECISION_API_VERSION}.`
|
| 3452 |
+
);
|
| 3453 |
+
}
|
| 3454 |
+
const raw = core.ccall(
|
| 3455 |
+
"llamadart_webgpu_decision_capabilities_json",
|
| 3456 |
+
"string",
|
| 3457 |
+
[],
|
| 3458 |
+
[]
|
| 3459 |
+
) || "{}";
|
| 3460 |
+
try {
|
| 3461 |
+
return JSON.parse(raw);
|
| 3462 |
+
} catch (_) {
|
| 3463 |
+
return unsupported("WebGPU decision capability response is invalid");
|
| 3464 |
+
}
|
| 3465 |
+
}
|
| 3466 |
+
_ensureDecisionDir() {
|
| 3467 |
+
try {
|
| 3468 |
+
this._core.FS.mkdir("/decision");
|
| 3469 |
+
} catch (_) {
|
| 3470 |
+
}
|
| 3471 |
+
}
|
| 3472 |
+
async _stageDecisionHeadFromUrl(url, headPath, onProgress) {
|
| 3473 |
+
const fetchTimeoutMs = this._resolveFetchTimeoutMs({}, 18e4);
|
| 3474 |
+
const chunkTimeoutMs = this._resolveStreamChunkTimeoutMs({}, 9e4);
|
| 3475 |
+
for (let attempt = 0; ; attempt += 1) {
|
| 3476 |
+
try {
|
| 3477 |
+
const response = await this._fetchWithTimeout(
|
| 3478 |
+
url,
|
| 3479 |
+
{ cache: "no-store" },
|
| 3480 |
+
fetchTimeoutMs
|
| 3481 |
+
);
|
| 3482 |
+
if (!response.ok) {
|
| 3483 |
+
throw new Error(
|
| 3484 |
+
`Failed to fetch decision head: ${response.status} ${response.statusText}`
|
| 3485 |
+
);
|
| 3486 |
+
}
|
| 3487 |
+
await writeResponseToFsFileWithProgress(
|
| 3488 |
+
response,
|
| 3489 |
+
this._core.FS,
|
| 3490 |
+
headPath,
|
| 3491 |
+
typeof onProgress === "function" ? onProgress : null,
|
| 3492 |
+
{
|
| 3493 |
+
useBigIntPosition: this._coreVariant === "wasm64",
|
| 3494 |
+
chunkTimeoutMs
|
| 3495 |
+
}
|
| 3496 |
+
);
|
| 3497 |
+
return;
|
| 3498 |
+
} catch (error) {
|
| 3499 |
+
this._unlinkDecisionFile(headPath);
|
| 3500 |
+
if (!isRetryableStreamNetworkError(error) || attempt >= 1) {
|
| 3501 |
+
throw error;
|
| 3502 |
+
}
|
| 3503 |
+
this._runtimeNotes.push(`decision_head_fetch_retry:${attempt + 1}`);
|
| 3504 |
+
}
|
| 3505 |
+
}
|
| 3506 |
+
}
|
| 3507 |
+
/**
|
| 3508 |
+
* @param {string | ArrayBuffer | ArrayBufferView} source
|
| 3509 |
+
* @param {{ configJson?: string | null, onProgress?: (progress: { loaded: number, total: number }) => void }} [options]
|
| 3510 |
+
*/
|
| 3511 |
+
async loadDecisionHead(source, options = {}) {
|
| 3512 |
+
if (!this._core || this._modelBytes <= 0) {
|
| 3513 |
+
throw new Error("No model loaded. Call loadModelFromUrl first.");
|
| 3514 |
+
}
|
| 3515 |
+
const configJson = options?.configJson ?? null;
|
| 3516 |
+
if (configJson !== null && typeof configJson !== "string") {
|
| 3517 |
+
throw new TypeError("Decision head configJson must be a string.");
|
| 3518 |
+
}
|
| 3519 |
+
let bytes = null;
|
| 3520 |
+
if (typeof source === "string") {
|
| 3521 |
+
if (source.length === 0) {
|
| 3522 |
+
throw new Error("Decision head URL is empty.");
|
| 3523 |
+
}
|
| 3524 |
+
} else {
|
| 3525 |
+
bytes = decisionHeadBytes(source);
|
| 3526 |
+
if (!bytes) {
|
| 3527 |
+
throw new TypeError("Decision head source must be a URL string, an ArrayBuffer or a typed array.");
|
| 3528 |
+
}
|
| 3529 |
+
if (bytes.byteLength === 0) {
|
| 3530 |
+
throw new Error("Decision head bytes are empty.");
|
| 3531 |
+
}
|
| 3532 |
+
}
|
| 3533 |
+
const capabilities = this.getDecisionCapabilities();
|
| 3534 |
+
if (capabilities.supported !== true) {
|
| 3535 |
+
throw new Error(
|
| 3536 |
+
capabilities.reason || "The loaded model does not support decision heads."
|
| 3537 |
+
);
|
| 3538 |
+
}
|
| 3539 |
+
const core = this._core;
|
| 3540 |
+
this._ensureDecisionDir();
|
| 3541 |
+
const taskId = `${Date.now()}_${++this._decisionFileCounter}`;
|
| 3542 |
+
const headPath = `/decision/head_${taskId}.safetensors`;
|
| 3543 |
+
const configPath = configJson === null ? null : `/decision/config_${taskId}.json`;
|
| 3544 |
+
try {
|
| 3545 |
+
let label = "decision head bytes";
|
| 3546 |
+
if (bytes) {
|
| 3547 |
+
core.FS.writeFile(headPath, bytes);
|
| 3548 |
+
} else {
|
| 3549 |
+
label = basenameFromUrl(source).slice(0, 256);
|
| 3550 |
+
await this._stageDecisionHeadFromUrl(source, headPath, options?.onProgress);
|
| 3551 |
+
}
|
| 3552 |
+
if (configPath !== null) {
|
| 3553 |
+
core.FS.writeFile(configPath, textEncoder.encode(configJson));
|
| 3554 |
+
}
|
| 3555 |
+
const handle = Number(
|
| 3556 |
+
await core.ccall(
|
| 3557 |
+
"llamadart_webgpu_decision_load",
|
| 3558 |
+
"number",
|
| 3559 |
+
["string", "string", "string"],
|
| 3560 |
+
[headPath, label, configPath],
|
| 3561 |
+
{ async: true }
|
| 3562 |
+
)
|
| 3563 |
+
);
|
| 3564 |
+
if (handle <= 0) {
|
| 3565 |
+
throw new Error(this._coreErrorMessage("Failed to load decision head", handle));
|
| 3566 |
+
}
|
| 3567 |
+
const raw = core.ccall(
|
| 3568 |
+
"llamadart_webgpu_decision_head_info_json",
|
| 3569 |
+
"string",
|
| 3570 |
+
["number"],
|
| 3571 |
+
[handle]
|
| 3572 |
+
) || "{}";
|
| 3573 |
+
return JSON.parse(raw);
|
| 3574 |
+
} finally {
|
| 3575 |
+
this._unlinkDecisionFile(headPath);
|
| 3576 |
+
this._unlinkDecisionFile(configPath);
|
| 3577 |
+
}
|
| 3578 |
+
}
|
| 3579 |
+
/**
|
| 3580 |
+
* @param {number} handle
|
| 3581 |
+
* @param {unknown} sequences
|
| 3582 |
+
*/
|
| 3583 |
+
async runDecision(handle, sequences) {
|
| 3584 |
+
const nativeHandle = decisionHandleFrom(handle);
|
| 3585 |
+
const input = encodeDecisionSequences(sequences);
|
| 3586 |
+
if (!this._core || this._modelBytes <= 0) {
|
| 3587 |
+
throw new Error("No model loaded. Call loadModelFromUrl first.");
|
| 3588 |
+
}
|
| 3589 |
+
const core = this._core;
|
| 3590 |
+
this._ensureDecisionDir();
|
| 3591 |
+
const taskId = `${Date.now()}_${++this._decisionFileCounter}`;
|
| 3592 |
+
const inputPath = `/decision/input_${taskId}.bin`;
|
| 3593 |
+
const outputPath = `/decision/output_${taskId}.bin`;
|
| 3594 |
+
try {
|
| 3595 |
+
core.FS.writeFile(inputPath, input);
|
| 3596 |
+
const count = Number(
|
| 3597 |
+
await core.ccall(
|
| 3598 |
+
"llamadart_webgpu_decision_run",
|
| 3599 |
+
"number",
|
| 3600 |
+
["number", "string", "string"],
|
| 3601 |
+
[nativeHandle, inputPath, outputPath],
|
| 3602 |
+
{ async: true }
|
| 3603 |
+
)
|
| 3604 |
+
);
|
| 3605 |
+
if (count < 0) {
|
| 3606 |
+
throw new Error(this._coreErrorMessage("Decision run failed", count));
|
| 3607 |
+
}
|
| 3608 |
+
return decodeDecisionOutputs(core.FS.readFile(outputPath), count);
|
| 3609 |
+
} finally {
|
| 3610 |
+
this._unlinkDecisionFile(inputPath);
|
| 3611 |
+
this._unlinkDecisionFile(outputPath);
|
| 3612 |
+
}
|
| 3613 |
+
}
|
| 3614 |
+
/** @param {number} handle */
|
| 3615 |
+
async freeDecisionHead(handle) {
|
| 3616 |
+
const nativeHandle = decisionHandleFrom(handle);
|
| 3617 |
+
if (!this._core) {
|
| 3618 |
+
return;
|
| 3619 |
+
}
|
| 3620 |
+
await this._core.ccall(
|
| 3621 |
+
"llamadart_webgpu_decision_free",
|
| 3622 |
+
"number",
|
| 3623 |
+
["number"],
|
| 3624 |
+
[nativeHandle],
|
| 3625 |
+
{ async: true }
|
| 3626 |
+
);
|
| 3627 |
+
}
|
| 3628 |
_clearStagedMediaFiles() {
|
| 3629 |
if (!this._core || this._stagedMediaPaths.length === 0) {
|
| 3630 |
this._stagedMediaPaths = [];
|
|
|
|
| 4330 |
this._disposed = false;
|
| 4331 |
this._disposePromise = null;
|
| 4332 |
this._disposalWaiters = /* @__PURE__ */ new Set();
|
| 4333 |
+
this._decisionHeads = /* @__PURE__ */ new Map();
|
| 4334 |
+
this._nextDecisionHandle = 1;
|
| 4335 |
if (this._shouldUseWorker()) {
|
| 4336 |
try {
|
| 4337 |
this._workerProxy = new BridgeWorkerProxy({
|
|
|
|
| 4865 |
}
|
| 4866 |
_isRecoverableWorkerFsError(error) {
|
| 4867 |
const text = serializeWorkerError(error).toLowerCase();
|
| 4868 |
+
return text.includes("fs error") || text.includes("no such file") || text.includes("not found") || text.includes("invalid argument") || text.includes("timed out");
|
| 4869 |
}
|
| 4870 |
_isWorkerRequestTimeoutError(error) {
|
| 4871 |
const text = serializeWorkerError(error).toLowerCase();
|
|
|
|
| 4949 |
const text = serializeWorkerError(error).toLowerCase();
|
| 4950 |
return text.includes("worker completion stalled") || text.includes("worker createcompletion stalled") || text.includes("worker timed out") || text.includes("worker timeout");
|
| 4951 |
}
|
|
|
|
|
|
|
|
|
|
| 4952 |
_isCpuModelMode() {
|
| 4953 |
const requestedLayers = Number(this._loadedModelOptions?.nGpuLayers);
|
| 4954 |
if (Number.isFinite(requestedLayers)) {
|
|
|
|
| 4991 |
const multimodalRuntimeRequired = mediaPartsRequested || textToSpeechRequested;
|
| 4992 |
const shouldEnsureMultimodalInRuntime = multimodalRuntimeRequired && typeof this._loadedMmProjUrl === "string" && this._loadedMmProjUrl.length > 0;
|
| 4993 |
const workerTimedOut = this._isWorkerTimeoutError(fallbackError);
|
|
|
|
| 4994 |
const dispatchWorkgroupFallback = this._isDispatchWorkgroupLimitError(fallbackError);
|
| 4995 |
const loadedGpuLayers = Number(this._loadedModelOptions?.nGpuLayers);
|
| 4996 |
const metadataGpuLayers = Number(this._metadata?.["llamadart.webgpu.n_gpu_layers"]);
|
| 4997 |
const modelLoadedWithGpu = Number.isFinite(loadedGpuLayers) ? loadedGpuLayers !== 0 : Number.isFinite(metadataGpuLayers) ? metadataGpuLayers !== 0 : true;
|
| 4998 |
+
const shouldUseCpuMultimodalFallback = multimodalRuntimeRequired && modelLoadedWithGpu && (dispatchWorkgroupFallback || workerTimedOut);
|
| 4999 |
try {
|
| 5000 |
if (Number(this._runtime?._modelBytes) > 0 && !forceReloadRequested && !shouldUseCpuMultimodalFallback) {
|
| 5001 |
if (shouldEnsureMultimodalInRuntime) {
|
|
|
|
| 5024 |
this._emitBridgeWarn(
|
| 5025 |
"llamadart: retrying text-to-speech once with CPU fallback after WebGPU failure."
|
| 5026 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5027 |
} else if (workerTimedOut) {
|
| 5028 |
this._emitBridgeWarn(
|
| 5029 |
"llamadart: retrying multimodal generation with CPU fallback after worker timeout."
|
|
|
|
| 5215 |
}
|
| 5216 |
return 2;
|
| 5217 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5218 |
_shouldEmitBridgeLevel(level) {
|
| 5219 |
const configured = this._resolvedBridgeLogLevel();
|
| 5220 |
+
const threshold = logThresholdForConfiguredLevel(configured);
|
| 5221 |
if (threshold > 3) {
|
| 5222 |
return false;
|
| 5223 |
}
|
| 5224 |
+
return logLevelForName(level) >= threshold;
|
| 5225 |
}
|
| 5226 |
_shouldSuppressBridgeWarn(message) {
|
| 5227 |
const text = String(message || "").trim();
|
|
|
|
| 5259 |
}
|
| 5260 |
}
|
| 5261 |
_disableWorkerFallback(error) {
|
| 5262 |
+
const reason = serializeWorkerError(error);
|
|
|
|
| 5263 |
this._workerFallbackReason = reason;
|
| 5264 |
if (typeof globalThis !== "undefined") {
|
| 5265 |
globalThis.__llamadartBridgeWorkerFallbackReason = reason;
|
| 5266 |
}
|
| 5267 |
+
this._emitBridgeWarn(
|
| 5268 |
+
`llamadart: bridge worker unavailable, falling back to main thread (${reason})`
|
| 5269 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5270 |
if (this._workerProxy) {
|
| 5271 |
const workerProxy = this._workerProxy;
|
| 5272 |
this._advanceWorkerGeneration();
|
|
|
|
| 5284 |
}
|
| 5285 |
if (this._runtime && Array.isArray(this._runtime._runtimeNotes) && typeof reason === "string" && reason.length > 0) {
|
| 5286 |
this._runtime._runtimeNotes.push(`worker_fallback:${reason}`);
|
|
|
|
|
|
|
|
|
|
| 5287 |
}
|
| 5288 |
}
|
| 5289 |
async _callWorker(method, args, onEvent, transferList = []) {
|
|
|
|
| 5807 |
throw error;
|
| 5808 |
}
|
| 5809 |
}
|
| 5810 |
+
/** @returns {Map<number, { owner: object, handle: number }>} */
|
| 5811 |
+
_decisionHeadMap() {
|
| 5812 |
+
if (!(this._decisionHeads instanceof Map)) {
|
| 5813 |
+
this._decisionHeads = /* @__PURE__ */ new Map();
|
| 5814 |
+
this._nextDecisionHandle = 1;
|
| 5815 |
+
}
|
| 5816 |
+
return this._decisionHeads;
|
| 5817 |
+
}
|
| 5818 |
+
_registerDecisionHead(owner, info) {
|
| 5819 |
+
const heads = this._decisionHeadMap();
|
| 5820 |
+
const handle = this._nextDecisionHandle++;
|
| 5821 |
+
heads.set(handle, { owner, handle: Number(info?.handle) });
|
| 5822 |
+
return { ...info, handle };
|
| 5823 |
+
}
|
| 5824 |
+
_decisionOwner() {
|
| 5825 |
+
return this._workerProxy || this._runtime || null;
|
| 5826 |
+
}
|
| 5827 |
+
_staleDecisionHeadError(handle) {
|
| 5828 |
+
return new Error(
|
| 5829 |
+
`Decision head ${handle} is not loaded; it was freed, its model was unloaded, or the bridge runtime restarted. Load the decision head again.`
|
| 5830 |
+
);
|
| 5831 |
+
}
|
| 5832 |
+
/** @param {number} handle */
|
| 5833 |
+
_resolveDecisionHead(handle) {
|
| 5834 |
+
decisionHandleFrom(handle);
|
| 5835 |
+
const heads = this._decisionHeadMap();
|
| 5836 |
+
const entry = heads.get(handle);
|
| 5837 |
+
if (!entry) {
|
| 5838 |
+
return null;
|
| 5839 |
+
}
|
| 5840 |
+
if (entry.owner !== this._decisionOwner()) {
|
| 5841 |
+
heads.delete(handle);
|
| 5842 |
+
return null;
|
| 5843 |
+
}
|
| 5844 |
+
return entry;
|
| 5845 |
+
}
|
| 5846 |
+
_requireDecisionRuntime() {
|
| 5847 |
+
if (!this._runtime) {
|
| 5848 |
+
throw new Error("No model loaded. Call loadModelFromUrl first.");
|
| 5849 |
+
}
|
| 5850 |
+
return this._runtime;
|
| 5851 |
+
}
|
| 5852 |
+
/**
|
| 5853 |
+
* Moves a failed worker's work to the main-thread runtime. Heads the worker
|
| 5854 |
+
* held are gone with it; the model is reloaded so later calls keep working.
|
| 5855 |
+
*/
|
| 5856 |
+
async _recoverDecisionWorker(error) {
|
| 5857 |
+
this._disableWorkerFallback(error);
|
| 5858 |
+
await this._waitForWorkerDisposal();
|
| 5859 |
+
await this._ensureRuntimeReadyAfterWorkerFallback({}, error);
|
| 5860 |
+
}
|
| 5861 |
+
async getDecisionCapabilities() {
|
| 5862 |
+
return this._runExclusive(
|
| 5863 |
+
() => this._getDecisionCapabilitiesUnlocked(),
|
| 5864 |
+
{ kind: "decision-capabilities" }
|
| 5865 |
+
);
|
| 5866 |
+
}
|
| 5867 |
+
async _getDecisionCapabilitiesUnlocked() {
|
| 5868 |
+
if (!this._workerProxy) {
|
| 5869 |
+
return this._runtime ? this._runtime.getDecisionCapabilities() : { apiVersion: DECISION_API_VERSION, supported: false, reason: "WebGPU core is not initialized" };
|
| 5870 |
+
}
|
| 5871 |
+
try {
|
| 5872 |
+
return await this._callWorker("getDecisionCapabilities", []);
|
| 5873 |
+
} catch (error) {
|
| 5874 |
+
this._throwIfOperationCancelled(error, "Decision capability probe was cancelled.");
|
| 5875 |
+
if (!this._shouldFallbackToMainThread(error)) {
|
| 5876 |
+
throw error;
|
| 5877 |
+
}
|
| 5878 |
+
await this._recoverDecisionWorker(error);
|
| 5879 |
+
return this._requireDecisionRuntime().getDecisionCapabilities();
|
| 5880 |
+
}
|
| 5881 |
+
}
|
| 5882 |
+
/**
|
| 5883 |
+
* @param {string | ArrayBuffer | ArrayBufferView} source
|
| 5884 |
+
* @param {{ configJson?: string | null, onProgress?: (progress: { loaded: number, total: number }) => void }} [options]
|
| 5885 |
+
*/
|
| 5886 |
+
async loadDecisionHead(source, options = {}) {
|
| 5887 |
+
return this._runExclusive(
|
| 5888 |
+
() => this._loadDecisionHeadUnlocked(source, options),
|
| 5889 |
+
{ kind: "decision-head-load" }
|
| 5890 |
+
);
|
| 5891 |
+
}
|
| 5892 |
+
/**
|
| 5893 |
+
* @param {string | ArrayBuffer | ArrayBufferView} source
|
| 5894 |
+
* @param {{ configJson?: string | null, onProgress?: (progress: { loaded: number, total: number }) => void }} [options]
|
| 5895 |
+
*/
|
| 5896 |
+
async _loadDecisionHeadUnlocked(source, options = {}) {
|
| 5897 |
+
const loadInRuntime = async () => {
|
| 5898 |
+
const runtime = this._requireDecisionRuntime();
|
| 5899 |
+
return this._registerDecisionHead(
|
| 5900 |
+
runtime,
|
| 5901 |
+
await runtime.loadDecisionHead(source, options)
|
| 5902 |
+
);
|
| 5903 |
+
};
|
| 5904 |
+
if (!this._workerProxy) {
|
| 5905 |
+
return loadInRuntime();
|
| 5906 |
+
}
|
| 5907 |
+
const proxy = this._workerProxy;
|
| 5908 |
+
const workerOptions = { configJson: options?.configJson ?? null };
|
| 5909 |
+
let workerSource = source;
|
| 5910 |
+
const transferList = [];
|
| 5911 |
+
if (typeof source === "string") {
|
| 5912 |
+
workerSource = source.length > 0 ? normalizeAbsoluteUrl(source) : source;
|
| 5913 |
+
} else {
|
| 5914 |
+
const bytes = decisionHeadBytes(source);
|
| 5915 |
+
if (bytes) {
|
| 5916 |
+
const copy = new Uint8Array(bytes);
|
| 5917 |
+
workerSource = copy;
|
| 5918 |
+
transferList.push(copy.buffer);
|
| 5919 |
+
}
|
| 5920 |
+
}
|
| 5921 |
+
try {
|
| 5922 |
+
const info = await this._callWorker(
|
| 5923 |
+
"loadDecisionHead",
|
| 5924 |
+
[workerSource, workerOptions],
|
| 5925 |
+
(event) => {
|
| 5926 |
+
if (event.event === "progress") {
|
| 5927 |
+
options?.onProgress?.(event.payload || {});
|
| 5928 |
+
}
|
| 5929 |
+
},
|
| 5930 |
+
transferList
|
| 5931 |
+
);
|
| 5932 |
+
return this._registerDecisionHead(proxy, info);
|
| 5933 |
+
} catch (error) {
|
| 5934 |
+
this._throwIfOperationCancelled(error, "Decision head load was cancelled.");
|
| 5935 |
+
if (!this._shouldFallbackToMainThread(error)) {
|
| 5936 |
+
throw error;
|
| 5937 |
+
}
|
| 5938 |
+
await this._recoverDecisionWorker(error);
|
| 5939 |
+
return loadInRuntime();
|
| 5940 |
+
}
|
| 5941 |
+
}
|
| 5942 |
+
/**
|
| 5943 |
+
* @param {number} handle
|
| 5944 |
+
* @param {readonly import('./llama_webgpu_bridge.d.ts').DecisionSequence[]} sequences
|
| 5945 |
+
*/
|
| 5946 |
+
async runDecision(handle, sequences) {
|
| 5947 |
+
return this._runExclusive(
|
| 5948 |
+
() => this._runDecisionUnlocked(handle, sequences),
|
| 5949 |
+
{ kind: "decision-run" }
|
| 5950 |
+
);
|
| 5951 |
+
}
|
| 5952 |
+
/**
|
| 5953 |
+
* @param {number} handle
|
| 5954 |
+
* @param {readonly import('./llama_webgpu_bridge.d.ts').DecisionSequence[]} sequences
|
| 5955 |
+
*/
|
| 5956 |
+
async _runDecisionUnlocked(handle, sequences) {
|
| 5957 |
+
const entry = this._resolveDecisionHead(handle);
|
| 5958 |
+
if (!entry) {
|
| 5959 |
+
throw this._staleDecisionHeadError(handle);
|
| 5960 |
+
}
|
| 5961 |
+
const normalized = normalizeDecisionSequences(sequences);
|
| 5962 |
+
if (!this._workerProxy) {
|
| 5963 |
+
return this._requireDecisionRuntime().runDecision(entry.handle, normalized);
|
| 5964 |
+
}
|
| 5965 |
+
try {
|
| 5966 |
+
return await this._callWorker("runDecision", [entry.handle, normalized]);
|
| 5967 |
+
} catch (error) {
|
| 5968 |
+
this._throwIfOperationCancelled(error, "Decision run was cancelled.");
|
| 5969 |
+
if (!this._shouldFallbackToMainThread(error)) {
|
| 5970 |
+
throw error;
|
| 5971 |
+
}
|
| 5972 |
+
this._decisionHeadMap().delete(handle);
|
| 5973 |
+
await this._recoverDecisionWorker(error);
|
| 5974 |
+
throw new Error(
|
| 5975 |
+
`Decision head ${handle} was lost when the bridge worker failed (${serializeWorkerError(error)}). Load the decision head again.`
|
| 5976 |
+
);
|
| 5977 |
+
}
|
| 5978 |
+
}
|
| 5979 |
+
/** @param {number} handle */
|
| 5980 |
+
async freeDecisionHead(handle) {
|
| 5981 |
+
return this._runExclusive(
|
| 5982 |
+
() => this._freeDecisionHeadUnlocked(handle),
|
| 5983 |
+
{ kind: "decision-head-free" }
|
| 5984 |
+
);
|
| 5985 |
+
}
|
| 5986 |
+
/** @param {number} handle */
|
| 5987 |
+
async _freeDecisionHeadUnlocked(handle) {
|
| 5988 |
+
const entry = this._resolveDecisionHead(handle);
|
| 5989 |
+
if (!entry) {
|
| 5990 |
+
return;
|
| 5991 |
+
}
|
| 5992 |
+
this._decisionHeadMap().delete(handle);
|
| 5993 |
+
if (!this._workerProxy) {
|
| 5994 |
+
await this._requireDecisionRuntime().freeDecisionHead(entry.handle);
|
| 5995 |
+
return;
|
| 5996 |
+
}
|
| 5997 |
+
try {
|
| 5998 |
+
await this._callWorker("freeDecisionHead", [entry.handle]);
|
| 5999 |
+
} catch (error) {
|
| 6000 |
+
this._throwIfOperationCancelled(error, "Decision head free was cancelled.");
|
| 6001 |
+
if (!this._shouldFallbackToMainThread(error)) {
|
| 6002 |
+
throw error;
|
| 6003 |
+
}
|
| 6004 |
+
await this._recoverDecisionWorker(error);
|
| 6005 |
+
}
|
| 6006 |
+
}
|
| 6007 |
async tokenize(text, addSpecial = true) {
|
| 6008 |
return this._runExclusive(
|
| 6009 |
() => this._tokenizeUnlocked(text, addSpecial),
|
|
|
|
| 6280 |
this._loadedMmProjUrl = null;
|
| 6281 |
this._workerFallbackReason = null;
|
| 6282 |
this._multimodalWorkerCpuMode = false;
|
| 6283 |
+
this._decisionHeads?.clear();
|
| 6284 |
this._lifecycleState = "disposed";
|
| 6285 |
}
|
| 6286 |
}
|
webgpu_bridge/llama_webgpu_core.js
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
webgpu_bridge/llama_webgpu_core.wasm
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4c2e81f5c44808367aa3f484776e7e4faa9f3841511d6a7ad2a39e6ec063d4a9
|
| 3 |
+
size 9170142
|
webgpu_bridge/llama_webgpu_core_mem64.js
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
webgpu_bridge/llama_webgpu_core_mem64.wasm
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a6de570070c13c73d90666e903c4770f5eeb2d24be7fc630444de6d6609133a9
|
| 3 |
+
size 9410357
|
webgpu_bridge/manifest.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
| 1 |
{
|
| 2 |
"artifacts": {
|
| 3 |
"llama_webgpu_bridge.d.ts": {
|
| 4 |
-
"sha256": "
|
| 5 |
-
"size_bytes":
|
| 6 |
},
|
| 7 |
"llama_webgpu_bridge.js": {
|
| 8 |
-
"sha256": "
|
| 9 |
-
"size_bytes":
|
| 10 |
},
|
| 11 |
"llama_webgpu_bridge_worker.js": {
|
| 12 |
"sha256": "47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca",
|
| 13 |
"size_bytes": 257
|
| 14 |
},
|
| 15 |
"llama_webgpu_core.js": {
|
| 16 |
-
"sha256": "
|
| 17 |
-
"size_bytes":
|
| 18 |
},
|
| 19 |
"llama_webgpu_core.wasm": {
|
| 20 |
-
"sha256": "
|
| 21 |
-
"size_bytes":
|
| 22 |
},
|
| 23 |
"llama_webgpu_core_mem64.js": {
|
| 24 |
-
"sha256": "
|
| 25 |
-
"size_bytes":
|
| 26 |
},
|
| 27 |
"llama_webgpu_core_mem64.wasm": {
|
| 28 |
-
"sha256": "
|
| 29 |
-
"size_bytes":
|
| 30 |
}
|
| 31 |
},
|
| 32 |
"assets_repository": "leehack/llama-web-bridge-assets",
|
| 33 |
-
"bridge_assets_tag": "v0.1.
|
| 34 |
-
"bridge_commit": "
|
| 35 |
"bridge_repository": "leehack/llama-web-bridge",
|
| 36 |
"capabilities": {
|
| 37 |
"memory64": true,
|
|
@@ -62,43 +62,43 @@
|
|
| 62 |
"emscripten_version": "6.0.8",
|
| 63 |
"files": {
|
| 64 |
"llama_webgpu_bridge.d.ts": {
|
| 65 |
-
"sha256": "
|
| 66 |
-
"size_bytes":
|
| 67 |
},
|
| 68 |
"llama_webgpu_bridge.js": {
|
| 69 |
-
"sha256": "
|
| 70 |
-
"size_bytes":
|
| 71 |
},
|
| 72 |
"llama_webgpu_bridge_worker.js": {
|
| 73 |
"sha256": "47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca",
|
| 74 |
"size_bytes": 257
|
| 75 |
},
|
| 76 |
"llama_webgpu_core.js": {
|
| 77 |
-
"sha256": "
|
| 78 |
-
"size_bytes":
|
| 79 |
},
|
| 80 |
"llama_webgpu_core.wasm": {
|
| 81 |
-
"sha256": "
|
| 82 |
-
"size_bytes":
|
| 83 |
},
|
| 84 |
"llama_webgpu_core_mem64.js": {
|
| 85 |
-
"sha256": "
|
| 86 |
-
"size_bytes":
|
| 87 |
},
|
| 88 |
"llama_webgpu_core_mem64.wasm": {
|
| 89 |
-
"sha256": "
|
| 90 |
-
"size_bytes":
|
| 91 |
}
|
| 92 |
},
|
| 93 |
-
"github_run_id": "
|
| 94 |
-
"github_run_url": "https://github.com/leehack/llama-web-bridge/actions/runs/
|
| 95 |
"llama_cpp_commit": "b29c606e28a01b1bc8c1351026a0fa6e616bf6c4",
|
| 96 |
"llama_cpp_tag": "v0.4.1",
|
| 97 |
"native_commit": "a4ee6b9fa71127d6cdf625e26d82ca5ab7b1d102",
|
| 98 |
"native_manifest_sha256": "d8dc86fcb55e566ee04aa9ed235716bd0e7a48cdaecb17822c098b074ec33d3e",
|
| 99 |
"native_release_tag": "v0.4.1",
|
| 100 |
"native_repository": "leehack/llamadart-native",
|
| 101 |
-
"orchestrator_correlation_id": "auto-stable-v0.4.1-d8dc86fcb55e566e-build-
|
| 102 |
"qualification_gates": {
|
| 103 |
"multimodal": "passed",
|
| 104 |
"speech_to_text": "required-automated-qualification",
|
|
@@ -107,9 +107,9 @@
|
|
| 107 |
},
|
| 108 |
"release_channel": "stable",
|
| 109 |
"release_rebuild": 0,
|
| 110 |
-
"release_tag": "v0.1.
|
| 111 |
"schema_version": 2,
|
| 112 |
-
"source_commit": "
|
| 113 |
"source_repository": "leehack/llama-web-bridge",
|
| 114 |
"unproven_capabilities": {
|
| 115 |
"hardware_gpu_acceleration": "unavailable-on-hosted-runners",
|
|
|
|
| 1 |
{
|
| 2 |
"artifacts": {
|
| 3 |
"llama_webgpu_bridge.d.ts": {
|
| 4 |
+
"sha256": "d8fa58ab587bb79c44dff40714fa8fa130da8ead160c8aa33f9254ed75055837",
|
| 5 |
+
"size_bytes": 7810
|
| 6 |
},
|
| 7 |
"llama_webgpu_bridge.js": {
|
| 8 |
+
"sha256": "eaa670759e559ca7ee7182fe8d5440872b6861aa6c3a5e8b7ec7f6e55c604254",
|
| 9 |
+
"size_bytes": 227520
|
| 10 |
},
|
| 11 |
"llama_webgpu_bridge_worker.js": {
|
| 12 |
"sha256": "47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca",
|
| 13 |
"size_bytes": 257
|
| 14 |
},
|
| 15 |
"llama_webgpu_core.js": {
|
| 16 |
+
"sha256": "7e0617766b459bd1d1e398705716730e472bdfc0147f54212a5eb113b75b8a43",
|
| 17 |
+
"size_bytes": 114678
|
| 18 |
},
|
| 19 |
"llama_webgpu_core.wasm": {
|
| 20 |
+
"sha256": "4c2e81f5c44808367aa3f484776e7e4faa9f3841511d6a7ad2a39e6ec063d4a9",
|
| 21 |
+
"size_bytes": 9170142
|
| 22 |
},
|
| 23 |
"llama_webgpu_core_mem64.js": {
|
| 24 |
+
"sha256": "3f9c7e8738588b043ba69688df836feefd1a95a211a281d9ae5ba6ac181f3bb2",
|
| 25 |
+
"size_bytes": 131595
|
| 26 |
},
|
| 27 |
"llama_webgpu_core_mem64.wasm": {
|
| 28 |
+
"sha256": "a6de570070c13c73d90666e903c4770f5eeb2d24be7fc630444de6d6609133a9",
|
| 29 |
+
"size_bytes": 9410357
|
| 30 |
}
|
| 31 |
},
|
| 32 |
"assets_repository": "leehack/llama-web-bridge-assets",
|
| 33 |
+
"bridge_assets_tag": "v0.1.47",
|
| 34 |
+
"bridge_commit": "64ba8250871bf2472cc2064c6a00fff050783f02",
|
| 35 |
"bridge_repository": "leehack/llama-web-bridge",
|
| 36 |
"capabilities": {
|
| 37 |
"memory64": true,
|
|
|
|
| 62 |
"emscripten_version": "6.0.8",
|
| 63 |
"files": {
|
| 64 |
"llama_webgpu_bridge.d.ts": {
|
| 65 |
+
"sha256": "d8fa58ab587bb79c44dff40714fa8fa130da8ead160c8aa33f9254ed75055837",
|
| 66 |
+
"size_bytes": 7810
|
| 67 |
},
|
| 68 |
"llama_webgpu_bridge.js": {
|
| 69 |
+
"sha256": "eaa670759e559ca7ee7182fe8d5440872b6861aa6c3a5e8b7ec7f6e55c604254",
|
| 70 |
+
"size_bytes": 227520
|
| 71 |
},
|
| 72 |
"llama_webgpu_bridge_worker.js": {
|
| 73 |
"sha256": "47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca",
|
| 74 |
"size_bytes": 257
|
| 75 |
},
|
| 76 |
"llama_webgpu_core.js": {
|
| 77 |
+
"sha256": "7e0617766b459bd1d1e398705716730e472bdfc0147f54212a5eb113b75b8a43",
|
| 78 |
+
"size_bytes": 114678
|
| 79 |
},
|
| 80 |
"llama_webgpu_core.wasm": {
|
| 81 |
+
"sha256": "4c2e81f5c44808367aa3f484776e7e4faa9f3841511d6a7ad2a39e6ec063d4a9",
|
| 82 |
+
"size_bytes": 9170142
|
| 83 |
},
|
| 84 |
"llama_webgpu_core_mem64.js": {
|
| 85 |
+
"sha256": "3f9c7e8738588b043ba69688df836feefd1a95a211a281d9ae5ba6ac181f3bb2",
|
| 86 |
+
"size_bytes": 131595
|
| 87 |
},
|
| 88 |
"llama_webgpu_core_mem64.wasm": {
|
| 89 |
+
"sha256": "a6de570070c13c73d90666e903c4770f5eeb2d24be7fc630444de6d6609133a9",
|
| 90 |
+
"size_bytes": 9410357
|
| 91 |
}
|
| 92 |
},
|
| 93 |
+
"github_run_id": "35904377401",
|
| 94 |
+
"github_run_url": "https://github.com/leehack/llama-web-bridge/actions/runs/35904377401",
|
| 95 |
"llama_cpp_commit": "b29c606e28a01b1bc8c1351026a0fa6e616bf6c4",
|
| 96 |
"llama_cpp_tag": "v0.4.1",
|
| 97 |
"native_commit": "a4ee6b9fa71127d6cdf625e26d82ca5ab7b1d102",
|
| 98 |
"native_manifest_sha256": "d8dc86fcb55e566ee04aa9ed235716bd0e7a48cdaecb17822c098b074ec33d3e",
|
| 99 |
"native_release_tag": "v0.4.1",
|
| 100 |
"native_repository": "leehack/llamadart-native",
|
| 101 |
+
"orchestrator_correlation_id": "auto-stable-v0.4.1-d8dc86fcb55e566e-build-64ba8250871bf247",
|
| 102 |
"qualification_gates": {
|
| 103 |
"multimodal": "passed",
|
| 104 |
"speech_to_text": "required-automated-qualification",
|
|
|
|
| 107 |
},
|
| 108 |
"release_channel": "stable",
|
| 109 |
"release_rebuild": 0,
|
| 110 |
+
"release_tag": "v0.1.47",
|
| 111 |
"schema_version": 2,
|
| 112 |
+
"source_commit": "64ba8250871bf2472cc2064c6a00fff050783f02",
|
| 113 |
"source_repository": "leehack/llama-web-bridge",
|
| 114 |
"unproven_capabilities": {
|
| 115 |
"hardware_gpu_acceleration": "unavailable-on-hosted-runners",
|
webgpu_bridge/sha256sums.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca llama_webgpu_bridge_worker.js
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
|
|
|
| 1 |
+
eaa670759e559ca7ee7182fe8d5440872b6861aa6c3a5e8b7ec7f6e55c604254 llama_webgpu_bridge.js
|
| 2 |
+
7e0617766b459bd1d1e398705716730e472bdfc0147f54212a5eb113b75b8a43 llama_webgpu_core.js
|
| 3 |
+
4c2e81f5c44808367aa3f484776e7e4faa9f3841511d6a7ad2a39e6ec063d4a9 llama_webgpu_core.wasm
|
| 4 |
47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca llama_webgpu_bridge_worker.js
|
| 5 |
+
d8fa58ab587bb79c44dff40714fa8fa130da8ead160c8aa33f9254ed75055837 llama_webgpu_bridge.d.ts
|
| 6 |
+
3f9c7e8738588b043ba69688df836feefd1a95a211a281d9ae5ba6ac181f3bb2 llama_webgpu_core_mem64.js
|
| 7 |
+
a6de570070c13c73d90666e903c4770f5eeb2d24be7fc630444de6d6609133a9 llama_webgpu_core_mem64.wasm
|