radames commited on
Commit
9f3b1ae
1 Parent(s): aab2154

Upload 7 files

Browse files
Files changed (7) hide show
  1. build/m.d.ts +71 -0
  2. build/m.js +493 -0
  3. build/m_bg.wasm +3 -0
  4. build/m_bg.wasm.d.ts +15 -0
  5. code.js +258 -0
  6. index.html +302 -17
  7. moondreamWorker.js +200 -0
build/m.d.ts ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /**
4
+ */
5
+ export class Model {
6
+ free(): void;
7
+ /**
8
+ * @param {Uint8Array} weights
9
+ * @param {Uint8Array} tokenizer
10
+ * @param {boolean} quantized
11
+ */
12
+ constructor(weights: Uint8Array, tokenizer: Uint8Array, quantized: boolean);
13
+ /**
14
+ * @param {Uint8Array} image
15
+ */
16
+ set_image_embeddings(image: Uint8Array): void;
17
+ /**
18
+ * @param {string} prompt
19
+ * @param {bigint} seed
20
+ * @param {number} temp
21
+ * @param {number} top_p
22
+ * @param {number} repeat_penalty
23
+ * @param {number} repeat_last_n
24
+ * @param {boolean} verbose_prompt
25
+ * @returns {string}
26
+ */
27
+ init_with_image_prompt(prompt: string, seed: bigint, temp: number, top_p: number, repeat_penalty: number, repeat_last_n: number, verbose_prompt: boolean): string;
28
+ /**
29
+ * @returns {string}
30
+ */
31
+ next_token(): string;
32
+ }
33
+
34
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
35
+
36
+ export interface InitOutput {
37
+ readonly memory: WebAssembly.Memory;
38
+ readonly __wbg_model_free: (a: number) => void;
39
+ readonly model_load: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
40
+ readonly model_set_image_embeddings: (a: number, b: number, c: number, d: number) => void;
41
+ readonly model_init_with_image_prompt: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void;
42
+ readonly model_next_token: (a: number, b: number) => void;
43
+ readonly main: (a: number, b: number) => number;
44
+ readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
45
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
46
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
47
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
48
+ readonly __wbindgen_exn_store: (a: number) => void;
49
+ readonly __wbindgen_start: () => void;
50
+ }
51
+
52
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
53
+ /**
54
+ * Instantiates the given `module`, which can either be bytes or
55
+ * a precompiled `WebAssembly.Module`.
56
+ *
57
+ * @param {SyncInitInput} module
58
+ *
59
+ * @returns {InitOutput}
60
+ */
61
+ export function initSync(module: SyncInitInput): InitOutput;
62
+
63
+ /**
64
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
65
+ * for everything else, calls `WebAssembly.instantiate` directly.
66
+ *
67
+ * @param {InitInput | Promise<InitInput>} module_or_path
68
+ *
69
+ * @returns {Promise<InitOutput>}
70
+ */
71
+ export default function __wbg_init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
build/m.js ADDED
@@ -0,0 +1,493 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let wasm;
2
+
3
+ const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
4
+
5
+ if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
6
+
7
+ let cachedUint8Memory0 = null;
8
+
9
+ function getUint8Memory0() {
10
+ if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
11
+ cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
12
+ }
13
+ return cachedUint8Memory0;
14
+ }
15
+
16
+ function getStringFromWasm0(ptr, len) {
17
+ ptr = ptr >>> 0;
18
+ return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
19
+ }
20
+
21
+ const heap = new Array(128).fill(undefined);
22
+
23
+ heap.push(undefined, null, true, false);
24
+
25
+ let heap_next = heap.length;
26
+
27
+ function addHeapObject(obj) {
28
+ if (heap_next === heap.length) heap.push(heap.length + 1);
29
+ const idx = heap_next;
30
+ heap_next = heap[idx];
31
+
32
+ heap[idx] = obj;
33
+ return idx;
34
+ }
35
+
36
+ function getObject(idx) { return heap[idx]; }
37
+
38
+ function dropObject(idx) {
39
+ if (idx < 132) return;
40
+ heap[idx] = heap_next;
41
+ heap_next = idx;
42
+ }
43
+
44
+ function takeObject(idx) {
45
+ const ret = getObject(idx);
46
+ dropObject(idx);
47
+ return ret;
48
+ }
49
+
50
+ let WASM_VECTOR_LEN = 0;
51
+
52
+ function passArray8ToWasm0(arg, malloc) {
53
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
54
+ getUint8Memory0().set(arg, ptr / 1);
55
+ WASM_VECTOR_LEN = arg.length;
56
+ return ptr;
57
+ }
58
+
59
+ let cachedInt32Memory0 = null;
60
+
61
+ function getInt32Memory0() {
62
+ if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
63
+ cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
64
+ }
65
+ return cachedInt32Memory0;
66
+ }
67
+
68
+ const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
69
+
70
+ const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
71
+ ? function (arg, view) {
72
+ return cachedTextEncoder.encodeInto(arg, view);
73
+ }
74
+ : function (arg, view) {
75
+ const buf = cachedTextEncoder.encode(arg);
76
+ view.set(buf);
77
+ return {
78
+ read: arg.length,
79
+ written: buf.length
80
+ };
81
+ });
82
+
83
+ function passStringToWasm0(arg, malloc, realloc) {
84
+
85
+ if (realloc === undefined) {
86
+ const buf = cachedTextEncoder.encode(arg);
87
+ const ptr = malloc(buf.length, 1) >>> 0;
88
+ getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
89
+ WASM_VECTOR_LEN = buf.length;
90
+ return ptr;
91
+ }
92
+
93
+ let len = arg.length;
94
+ let ptr = malloc(len, 1) >>> 0;
95
+
96
+ const mem = getUint8Memory0();
97
+
98
+ let offset = 0;
99
+
100
+ for (; offset < len; offset++) {
101
+ const code = arg.charCodeAt(offset);
102
+ if (code > 0x7F) break;
103
+ mem[ptr + offset] = code;
104
+ }
105
+
106
+ if (offset !== len) {
107
+ if (offset !== 0) {
108
+ arg = arg.slice(offset);
109
+ }
110
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
111
+ const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
112
+ const ret = encodeString(arg, view);
113
+
114
+ offset += ret.written;
115
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
116
+ }
117
+
118
+ WASM_VECTOR_LEN = offset;
119
+ return ptr;
120
+ }
121
+
122
+ function handleError(f, args) {
123
+ try {
124
+ return f.apply(this, args);
125
+ } catch (e) {
126
+ wasm.__wbindgen_exn_store(addHeapObject(e));
127
+ }
128
+ }
129
+
130
+ const ModelFinalization = (typeof FinalizationRegistry === 'undefined')
131
+ ? { register: () => {}, unregister: () => {} }
132
+ : new FinalizationRegistry(ptr => wasm.__wbg_model_free(ptr >>> 0));
133
+ /**
134
+ */
135
+ export class Model {
136
+
137
+ __destroy_into_raw() {
138
+ const ptr = this.__wbg_ptr;
139
+ this.__wbg_ptr = 0;
140
+ ModelFinalization.unregister(this);
141
+ return ptr;
142
+ }
143
+
144
+ free() {
145
+ const ptr = this.__destroy_into_raw();
146
+ wasm.__wbg_model_free(ptr);
147
+ }
148
+ /**
149
+ * @param {Uint8Array} weights
150
+ * @param {Uint8Array} tokenizer
151
+ * @param {boolean} quantized
152
+ */
153
+ constructor(weights, tokenizer, quantized) {
154
+ try {
155
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
156
+ const ptr0 = passArray8ToWasm0(weights, wasm.__wbindgen_malloc);
157
+ const len0 = WASM_VECTOR_LEN;
158
+ const ptr1 = passArray8ToWasm0(tokenizer, wasm.__wbindgen_malloc);
159
+ const len1 = WASM_VECTOR_LEN;
160
+ wasm.model_load(retptr, ptr0, len0, ptr1, len1, quantized);
161
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
162
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
163
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
164
+ if (r2) {
165
+ throw takeObject(r1);
166
+ }
167
+ this.__wbg_ptr = r0 >>> 0;
168
+ return this;
169
+ } finally {
170
+ wasm.__wbindgen_add_to_stack_pointer(16);
171
+ }
172
+ }
173
+ /**
174
+ * @param {Uint8Array} image
175
+ */
176
+ set_image_embeddings(image) {
177
+ try {
178
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
179
+ const ptr0 = passArray8ToWasm0(image, wasm.__wbindgen_malloc);
180
+ const len0 = WASM_VECTOR_LEN;
181
+ wasm.model_set_image_embeddings(retptr, this.__wbg_ptr, ptr0, len0);
182
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
183
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
184
+ if (r1) {
185
+ throw takeObject(r0);
186
+ }
187
+ } finally {
188
+ wasm.__wbindgen_add_to_stack_pointer(16);
189
+ }
190
+ }
191
+ /**
192
+ * @param {string} prompt
193
+ * @param {bigint} seed
194
+ * @param {number} temp
195
+ * @param {number} top_p
196
+ * @param {number} repeat_penalty
197
+ * @param {number} repeat_last_n
198
+ * @param {boolean} verbose_prompt
199
+ * @returns {string}
200
+ */
201
+ init_with_image_prompt(prompt, seed, temp, top_p, repeat_penalty, repeat_last_n, verbose_prompt) {
202
+ let deferred3_0;
203
+ let deferred3_1;
204
+ try {
205
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
206
+ const ptr0 = passStringToWasm0(prompt, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
207
+ const len0 = WASM_VECTOR_LEN;
208
+ wasm.model_init_with_image_prompt(retptr, this.__wbg_ptr, ptr0, len0, seed, temp, top_p, repeat_penalty, repeat_last_n, verbose_prompt);
209
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
210
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
211
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
212
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
213
+ var ptr2 = r0;
214
+ var len2 = r1;
215
+ if (r3) {
216
+ ptr2 = 0; len2 = 0;
217
+ throw takeObject(r2);
218
+ }
219
+ deferred3_0 = ptr2;
220
+ deferred3_1 = len2;
221
+ return getStringFromWasm0(ptr2, len2);
222
+ } finally {
223
+ wasm.__wbindgen_add_to_stack_pointer(16);
224
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
225
+ }
226
+ }
227
+ /**
228
+ * @returns {string}
229
+ */
230
+ next_token() {
231
+ let deferred2_0;
232
+ let deferred2_1;
233
+ try {
234
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
235
+ wasm.model_next_token(retptr, this.__wbg_ptr);
236
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
237
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
238
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
239
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
240
+ var ptr1 = r0;
241
+ var len1 = r1;
242
+ if (r3) {
243
+ ptr1 = 0; len1 = 0;
244
+ throw takeObject(r2);
245
+ }
246
+ deferred2_0 = ptr1;
247
+ deferred2_1 = len1;
248
+ return getStringFromWasm0(ptr1, len1);
249
+ } finally {
250
+ wasm.__wbindgen_add_to_stack_pointer(16);
251
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
252
+ }
253
+ }
254
+ }
255
+
256
+ async function __wbg_load(module, imports) {
257
+ if (typeof Response === 'function' && module instanceof Response) {
258
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
259
+ try {
260
+ return await WebAssembly.instantiateStreaming(module, imports);
261
+
262
+ } catch (e) {
263
+ if (module.headers.get('Content-Type') != 'application/wasm') {
264
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
265
+
266
+ } else {
267
+ throw e;
268
+ }
269
+ }
270
+ }
271
+
272
+ const bytes = await module.arrayBuffer();
273
+ return await WebAssembly.instantiate(bytes, imports);
274
+
275
+ } else {
276
+ const instance = await WebAssembly.instantiate(module, imports);
277
+
278
+ if (instance instanceof WebAssembly.Instance) {
279
+ return { instance, module };
280
+
281
+ } else {
282
+ return instance;
283
+ }
284
+ }
285
+ }
286
+
287
+ function __wbg_get_imports() {
288
+ const imports = {};
289
+ imports.wbg = {};
290
+ imports.wbg.__wbindgen_error_new = function(arg0, arg1) {
291
+ const ret = new Error(getStringFromWasm0(arg0, arg1));
292
+ return addHeapObject(ret);
293
+ };
294
+ imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
295
+ takeObject(arg0);
296
+ };
297
+ imports.wbg.__wbg_new_abda76e883ba8a5f = function() {
298
+ const ret = new Error();
299
+ return addHeapObject(ret);
300
+ };
301
+ imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) {
302
+ const ret = getObject(arg1).stack;
303
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
304
+ const len1 = WASM_VECTOR_LEN;
305
+ getInt32Memory0()[arg0 / 4 + 1] = len1;
306
+ getInt32Memory0()[arg0 / 4 + 0] = ptr1;
307
+ };
308
+ imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) {
309
+ let deferred0_0;
310
+ let deferred0_1;
311
+ try {
312
+ deferred0_0 = arg0;
313
+ deferred0_1 = arg1;
314
+ console.error(getStringFromWasm0(arg0, arg1));
315
+ } finally {
316
+ wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
317
+ }
318
+ };
319
+ imports.wbg.__wbg_log_7046c2cfad7a244f = function(arg0, arg1) {
320
+ console.log(getStringFromWasm0(arg0, arg1));
321
+ };
322
+ imports.wbg.__wbg_crypto_c48a774b022d20ac = function(arg0) {
323
+ const ret = getObject(arg0).crypto;
324
+ return addHeapObject(ret);
325
+ };
326
+ imports.wbg.__wbindgen_is_object = function(arg0) {
327
+ const val = getObject(arg0);
328
+ const ret = typeof(val) === 'object' && val !== null;
329
+ return ret;
330
+ };
331
+ imports.wbg.__wbg_process_298734cf255a885d = function(arg0) {
332
+ const ret = getObject(arg0).process;
333
+ return addHeapObject(ret);
334
+ };
335
+ imports.wbg.__wbg_versions_e2e78e134e3e5d01 = function(arg0) {
336
+ const ret = getObject(arg0).versions;
337
+ return addHeapObject(ret);
338
+ };
339
+ imports.wbg.__wbg_node_1cd7a5d853dbea79 = function(arg0) {
340
+ const ret = getObject(arg0).node;
341
+ return addHeapObject(ret);
342
+ };
343
+ imports.wbg.__wbindgen_is_string = function(arg0) {
344
+ const ret = typeof(getObject(arg0)) === 'string';
345
+ return ret;
346
+ };
347
+ imports.wbg.__wbg_msCrypto_bcb970640f50a1e8 = function(arg0) {
348
+ const ret = getObject(arg0).msCrypto;
349
+ return addHeapObject(ret);
350
+ };
351
+ imports.wbg.__wbg_require_8f08ceecec0f4fee = function() { return handleError(function () {
352
+ const ret = module.require;
353
+ return addHeapObject(ret);
354
+ }, arguments) };
355
+ imports.wbg.__wbindgen_is_function = function(arg0) {
356
+ const ret = typeof(getObject(arg0)) === 'function';
357
+ return ret;
358
+ };
359
+ imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
360
+ const ret = getStringFromWasm0(arg0, arg1);
361
+ return addHeapObject(ret);
362
+ };
363
+ imports.wbg.__wbg_getRandomValues_37fa2ca9e4e07fab = function() { return handleError(function (arg0, arg1) {
364
+ getObject(arg0).getRandomValues(getObject(arg1));
365
+ }, arguments) };
366
+ imports.wbg.__wbg_randomFillSync_dc1e9a60c158336d = function() { return handleError(function (arg0, arg1) {
367
+ getObject(arg0).randomFillSync(takeObject(arg1));
368
+ }, arguments) };
369
+ imports.wbg.__wbg_newnoargs_581967eacc0e2604 = function(arg0, arg1) {
370
+ const ret = new Function(getStringFromWasm0(arg0, arg1));
371
+ return addHeapObject(ret);
372
+ };
373
+ imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) {
374
+ const ret = getObject(arg0).call(getObject(arg1));
375
+ return addHeapObject(ret);
376
+ }, arguments) };
377
+ imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
378
+ const ret = getObject(arg0);
379
+ return addHeapObject(ret);
380
+ };
381
+ imports.wbg.__wbg_self_1ff1d729e9aae938 = function() { return handleError(function () {
382
+ const ret = self.self;
383
+ return addHeapObject(ret);
384
+ }, arguments) };
385
+ imports.wbg.__wbg_window_5f4faef6c12b79ec = function() { return handleError(function () {
386
+ const ret = window.window;
387
+ return addHeapObject(ret);
388
+ }, arguments) };
389
+ imports.wbg.__wbg_globalThis_1d39714405582d3c = function() { return handleError(function () {
390
+ const ret = globalThis.globalThis;
391
+ return addHeapObject(ret);
392
+ }, arguments) };
393
+ imports.wbg.__wbg_global_651f05c6a0944d1c = function() { return handleError(function () {
394
+ const ret = global.global;
395
+ return addHeapObject(ret);
396
+ }, arguments) };
397
+ imports.wbg.__wbindgen_is_undefined = function(arg0) {
398
+ const ret = getObject(arg0) === undefined;
399
+ return ret;
400
+ };
401
+ imports.wbg.__wbg_call_01734de55d61e11d = function() { return handleError(function (arg0, arg1, arg2) {
402
+ const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
403
+ return addHeapObject(ret);
404
+ }, arguments) };
405
+ imports.wbg.__wbg_now_9c5990bda04c7e53 = function() {
406
+ const ret = Date.now();
407
+ return ret;
408
+ };
409
+ imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) {
410
+ const ret = getObject(arg0).buffer;
411
+ return addHeapObject(ret);
412
+ };
413
+ imports.wbg.__wbg_newwithbyteoffsetandlength_6da8e527659b86aa = function(arg0, arg1, arg2) {
414
+ const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
415
+ return addHeapObject(ret);
416
+ };
417
+ imports.wbg.__wbg_new_8125e318e6245eed = function(arg0) {
418
+ const ret = new Uint8Array(getObject(arg0));
419
+ return addHeapObject(ret);
420
+ };
421
+ imports.wbg.__wbg_set_5cf90238115182c3 = function(arg0, arg1, arg2) {
422
+ getObject(arg0).set(getObject(arg1), arg2 >>> 0);
423
+ };
424
+ imports.wbg.__wbg_newwithlength_e5d69174d6984cd7 = function(arg0) {
425
+ const ret = new Uint8Array(arg0 >>> 0);
426
+ return addHeapObject(ret);
427
+ };
428
+ imports.wbg.__wbg_subarray_13db269f57aa838d = function(arg0, arg1, arg2) {
429
+ const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
430
+ return addHeapObject(ret);
431
+ };
432
+ imports.wbg.__wbindgen_throw = function(arg0, arg1) {
433
+ throw new Error(getStringFromWasm0(arg0, arg1));
434
+ };
435
+ imports.wbg.__wbindgen_memory = function() {
436
+ const ret = wasm.memory;
437
+ return addHeapObject(ret);
438
+ };
439
+
440
+ return imports;
441
+ }
442
+
443
+ function __wbg_init_memory(imports, maybe_memory) {
444
+
445
+ }
446
+
447
+ function __wbg_finalize_init(instance, module) {
448
+ wasm = instance.exports;
449
+ __wbg_init.__wbindgen_wasm_module = module;
450
+ cachedInt32Memory0 = null;
451
+ cachedUint8Memory0 = null;
452
+
453
+ wasm.__wbindgen_start();
454
+ return wasm;
455
+ }
456
+
457
+ function initSync(module) {
458
+ if (wasm !== undefined) return wasm;
459
+
460
+ const imports = __wbg_get_imports();
461
+
462
+ __wbg_init_memory(imports);
463
+
464
+ if (!(module instanceof WebAssembly.Module)) {
465
+ module = new WebAssembly.Module(module);
466
+ }
467
+
468
+ const instance = new WebAssembly.Instance(module, imports);
469
+
470
+ return __wbg_finalize_init(instance, module);
471
+ }
472
+
473
+ async function __wbg_init(input) {
474
+ if (wasm !== undefined) return wasm;
475
+
476
+ if (typeof input === 'undefined') {
477
+ input = new URL('m_bg.wasm', import.meta.url);
478
+ }
479
+ const imports = __wbg_get_imports();
480
+
481
+ if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
482
+ input = fetch(input);
483
+ }
484
+
485
+ __wbg_init_memory(imports);
486
+
487
+ const { instance, module } = await __wbg_load(await input, imports);
488
+
489
+ return __wbg_finalize_init(instance, module);
490
+ }
491
+
492
+ export { initSync }
493
+ export default __wbg_init;
build/m_bg.wasm ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cc90fd24ffcce78fb09eb775c93e3a6b6147ecf5410f4612be62ddd0d9d78f7a
3
+ size 5352500
build/m_bg.wasm.d.ts ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export function __wbg_model_free(a: number): void;
5
+ export function model_load(a: number, b: number, c: number, d: number, e: number, f: number): void;
6
+ export function model_set_image_embeddings(a: number, b: number, c: number, d: number): void;
7
+ export function model_init_with_image_prompt(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number): void;
8
+ export function model_next_token(a: number, b: number): void;
9
+ export function main(a: number, b: number): number;
10
+ export function __wbindgen_add_to_stack_pointer(a: number): number;
11
+ export function __wbindgen_malloc(a: number, b: number): number;
12
+ export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
13
+ export function __wbindgen_free(a: number, b: number, c: number): void;
14
+ export function __wbindgen_exn_store(a: number): void;
15
+ export function __wbindgen_start(): void;
code.js ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import snarkdown from "https://cdn.skypack.dev/snarkdown";
2
+ import hljs from "https://cdn.skypack.dev/highlight.js";
3
+ // models base url
4
+ const MODELS = {
5
+ moondream2_q4k: {
6
+ base_url:
7
+ "https://huggingface.co/santiagomed/candle-moondream/resolve/main/",
8
+ model: "model-q4_0.gguf",
9
+ tokenizer: "tokenizer.json",
10
+ quantized: true,
11
+ size: "1.51 GB",
12
+ },
13
+ };
14
+
15
+ const moodreamWorker = new Worker("./moondreamWorker.js", {
16
+ type: "module",
17
+ });
18
+
19
+ async function generateSequence(controller) {
20
+ const getValue = (id) => document.querySelector(`#${id}`).value;
21
+ const modelID = getValue("model");
22
+ const model = MODELS[modelID];
23
+ const weightsURL =
24
+ model.model instanceof Array
25
+ ? model.model.map((m) => model.base_url + m)
26
+ : model.base_url + model.model;
27
+ const tokenizerURL = model.base_url + model.tokenizer;
28
+
29
+ const prompt = getValue("prompt").trim();
30
+ const temperature = getValue("temperature");
31
+ const topP = getValue("top-p");
32
+ const repeatPenalty = getValue("repeat_penalty");
33
+ const seed = getValue("seed");
34
+ const maxSeqLen = getValue("max-seq");
35
+
36
+ function updateStatus(data) {
37
+ const outStatus = document.querySelector("#output-status");
38
+ const outGen = document.querySelector("#output-generation");
39
+ const outCounter = document.querySelector("#output-counter");
40
+
41
+ switch (data.status) {
42
+ case "loading":
43
+ outStatus.hidden = false;
44
+ outStatus.textContent = data.message;
45
+ outGen.hidden = true;
46
+ outCounter.hidden = true;
47
+ break;
48
+ case "generating":
49
+ const { message, prompt, sentence, tokensSec, totalTime } = data;
50
+ outStatus.hidden = true;
51
+ outCounter.hidden = false;
52
+ outGen.hidden = false;
53
+ outGen.innerHTML = snarkdown(prompt + sentence);
54
+ outCounter.innerHTML = `${(totalTime / 1000).toFixed(
55
+ 2
56
+ )}s (${tokensSec.toFixed(2)} tok/s)`;
57
+ hljs.highlightAll();
58
+ break;
59
+ case "complete":
60
+ outStatus.hidden = true;
61
+ outGen.hidden = false;
62
+ break;
63
+ }
64
+ }
65
+
66
+ return new Promise((resolve, reject) => {
67
+ moodreamWorker.postMessage({
68
+ weightsURL,
69
+ modelID,
70
+ tokenizerURL,
71
+ quantized: model.quantized,
72
+ imageURL: currentImageURL,
73
+ prompt,
74
+ temp: temperature,
75
+ top_p: topP,
76
+ repeatPenalty,
77
+ seed: seed,
78
+ maxSeqLen,
79
+ verbose_prompt: false,
80
+ command: "start",
81
+ });
82
+
83
+ const handleAbort = () => {
84
+ moodreamWorker.postMessage({ command: "abort" });
85
+ };
86
+ const handleMessage = (event) => {
87
+ const { status, error, message, prompt, sentence } = event.data;
88
+ if (status) updateStatus(event.data);
89
+ if (error) {
90
+ moodreamWorker.removeEventListener("message", handleMessage);
91
+ reject(new Error(error));
92
+ }
93
+ if (status === "aborted") {
94
+ moodreamWorker.removeEventListener("message", handleMessage);
95
+ resolve(event.data);
96
+ }
97
+ if (status === "complete") {
98
+ moodreamWorker.removeEventListener("message", handleMessage);
99
+ resolve(event.data);
100
+ }
101
+ };
102
+
103
+ controller.signal.addEventListener("abort", handleAbort);
104
+ moodreamWorker.addEventListener("message", handleMessage);
105
+ });
106
+ }
107
+
108
+ const form = document.querySelector("#form");
109
+ const prompt = document.querySelector("#prompt");
110
+ const runBtn = document.querySelector("#run");
111
+ const modelSelect = document.querySelector("#model");
112
+ const dropArea = document.querySelector("#drop-area");
113
+ const canvas = document.querySelector("#canvas");
114
+ const ctxCanvas = canvas.getContext("2d");
115
+ const fileUpload = document.querySelector("#file-upload");
116
+ const clearImgBtn = document.querySelector("#clear-img-btn");
117
+ const imagesExamples = document.querySelector("#image-select");
118
+
119
+ let currentImageURL = null;
120
+ let runController = new AbortController();
121
+ let isRunning = false;
122
+
123
+ document.addEventListener("DOMContentLoaded", () => {
124
+ for (const [id, model] of Object.entries(MODELS)) {
125
+ const option = document.createElement("option");
126
+ option.value = id;
127
+ option.innerText = `${id} (${model.size})`;
128
+ modelSelect.appendChild(option);
129
+ }
130
+ const query = new URLSearchParams(window.location.search);
131
+ const modelID = query.get("model");
132
+ if (modelID) {
133
+ modelSelect.value = modelID;
134
+ } else {
135
+ modelSelect.value = "moondream2_q4k";
136
+ }
137
+ });
138
+
139
+ imagesExamples.addEventListener("click", (e) => {
140
+ // if (isEmbedding || isSegmenting) {
141
+ // return;
142
+ // }
143
+ const target = e.target;
144
+ if (target.nodeName === "IMG") {
145
+ const href = target.src;
146
+ clearImageCanvas();
147
+ currentImageURL = href;
148
+ drawImageCanvas(href);
149
+ }
150
+ });
151
+ modelSelect.addEventListener("change", (e) => {
152
+ const query = new URLSearchParams(window.location.search);
153
+ query.set("model", e.target.value);
154
+ window.history.replaceState({}, "", `${window.location.pathname}?${query}`);
155
+ window.parent.postMessage({ queryString: "?" + query }, "*");
156
+ const model = MODELS[e.target.value];
157
+ document.querySelector("#max-seq").max = model.seq_len;
158
+ document.querySelector("#max-seq").nextElementSibling.value = 200;
159
+ });
160
+
161
+ clearImgBtn.addEventListener("click", () => {
162
+ clearImageCanvas();
163
+ });
164
+
165
+ //add event listener to file input
166
+ fileUpload.addEventListener("input", async (e) => {
167
+ const target = e.target;
168
+ if (target.files.length > 0 && !target.files[0].type.includes("svg")) {
169
+ const href = URL.createObjectURL(target.files[0]);
170
+ clearImageCanvas();
171
+ await drawImageCanvas(href);
172
+ }
173
+ });
174
+ // add event listener to drop-area
175
+ dropArea.addEventListener("dragenter", (e) => {
176
+ e.preventDefault();
177
+ dropArea.classList.add("border-blue-700");
178
+ });
179
+ dropArea.addEventListener("dragleave", (e) => {
180
+ e.preventDefault();
181
+ dropArea.classList.remove("border-blue-700");
182
+ });
183
+ dropArea.addEventListener("dragover", (e) => {
184
+ e.preventDefault();
185
+ });
186
+ dropArea.addEventListener("drop", async (e) => {
187
+ e.preventDefault();
188
+ dropArea.classList.remove("border-blue-700");
189
+ const url = e.dataTransfer.getData("text/uri-list");
190
+ const files = e.dataTransfer.files;
191
+ if (files.length > 0) {
192
+ const href = URL.createObjectURL(files[0]);
193
+ clearImageCanvas();
194
+ await drawImageCanvas(href);
195
+ } else if (url) {
196
+ clearImageCanvas();
197
+ await drawImageCanvas(url);
198
+ }
199
+ });
200
+
201
+ form.addEventListener("submit", async (e) => {
202
+ e.preventDefault();
203
+ if (isRunning) {
204
+ stopRunning();
205
+ } else {
206
+ startRunning();
207
+ await generateSequence(runController);
208
+ stopRunning();
209
+ }
210
+ });
211
+
212
+ async function drawImageCanvas(imgURL) {
213
+ if (!imgURL) {
214
+ throw new Error("No image URL provided");
215
+ }
216
+ return new Promise((resolve, reject) => {
217
+ ctxCanvas.clearRect(0, 0, canvas.width, canvas.height);
218
+ ctxCanvas.clearRect(0, 0, canvas.width, canvas.height);
219
+ const img = new Image();
220
+ img.crossOrigin = "anonymous";
221
+ img.onload = () => {
222
+ canvas.width = img.width;
223
+ canvas.height = img.height;
224
+ ctxCanvas.drawImage(img, 0, 0);
225
+ clearImgBtn.disabled = false;
226
+ resolve(img);
227
+ };
228
+ img.src = imgURL;
229
+ currentImageURL = imgURL;
230
+ });
231
+ }
232
+
233
+ function clearImageCanvas() {
234
+ ctxCanvas.clearRect(0, 0, canvas.width, canvas.height);
235
+ clearImgBtn.disabled = true;
236
+ canvas.parentElement.style.height = "auto";
237
+ currentImageURL = null;
238
+ canvas.width = 0;
239
+ canvas.height = 0;
240
+ }
241
+
242
+ function startRunning() {
243
+ isRunning = true;
244
+ runBtn.textContent = "Stop";
245
+ prompt.disabled = true;
246
+ }
247
+
248
+ function stopRunning() {
249
+ runController.abort();
250
+ runController = new AbortController();
251
+ runBtn.textContent = "Run";
252
+ isRunning = false;
253
+ prompt.disabled = false;
254
+ }
255
+
256
+ prompt.addEventListener("input", (e) => {
257
+ runBtn.disabled = false;
258
+ });
index.html CHANGED
@@ -1,19 +1,304 @@
1
- <!doctype html>
2
  <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
 
1
  <html>
2
+ <head>
3
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
4
+ <title>Candle Moondream Rust/WASM</title>
5
+ </head>
6
+ <body></body>
7
+ </html>
8
+
9
+ <!DOCTYPE html>
10
+ <html>
11
+ <head>
12
+ <meta charset="UTF-8" />
13
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
14
+ <link
15
+ rel="stylesheet"
16
+ href="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/default.min.css"
17
+ />
18
+ <style>
19
+ @import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@200;300;400&family=Source+Sans+3:wght@100;200;300;400;500;600;700;800;900&display=swap");
20
+ html,
21
+ body {
22
+ font-family: "Source Sans 3", sans-serif;
23
+ }
24
+ code,
25
+ output,
26
+ select,
27
+ pre {
28
+ font-family: "Source Code Pro", monospace;
29
+ }
30
+ </style>
31
+ <style type="text/tailwindcss">
32
+ .link {
33
+ @apply underline hover:text-blue-500 hover:no-underline;
34
+ }
35
+ </style>
36
+ <script src="https://cdn.tailwindcss.com/3.4.3"></script>
37
+ <script type="module" src="./code.js"></script>
38
+ </head>
39
+ <body class="container max-w-4xl mx-auto p-4 text-gray-800">
40
+ <main class="grid grid-cols-1 gap-8 relative">
41
+ <span class="absolute text-5xl -ml-[1em]"> 🕯️ </span>
42
+ <div>
43
+ <h1 class="text-5xl font-bold">Candle Moondream 2</h1>
44
+ <h2 class="text-2xl font-bold">Rust/WASM Demo</h2>
45
+ <p class="max-w-lg">
46
+ <a
47
+ href="https://huggingface.co/vikhyatk/moondream2"
48
+ class="link"
49
+ target="_blank"
50
+ >Moondream 2</a
51
+ >
52
+ by
53
+ <a href=" https://huggingface.co/vikhyatk" class="link">Vik</a>
54
+ and model implementation on Candle by
55
+ <a href="https://huggingface.co/santiagomed" class="link"
56
+ >Santiago Medina
57
+ </a>
58
+ </p>
59
+ </div>
60
+
61
+ <div>
62
+ <p class="text-xs italic max-w-lg">
63
+ <b>Note:</b>
64
+ When first run, the app will download and cache the model, which could
65
+ take a few minutes. Then, the embeddings and generation will take a
66
+ few minutes to start 😔.
67
+ </p>
68
+ </div>
69
+ <div>
70
+ <label for="model" class="font-medium">Models Options: </label>
71
+ <select
72
+ id="model"
73
+ class="border-2 border-gray-500 rounded-md font-light"
74
+ ></select>
75
+ </div>
76
+ <form
77
+ id="form"
78
+ class="flex text-normal px-1 py-1 border border-gray-700 rounded-md items-center"
79
+ >
80
+ <input type="submit" hidden />
81
+ <input
82
+ type="text"
83
+ id="prompt"
84
+ class="font-light text-lg w-full px-3 py-2 mx-1 resize-none outline-none"
85
+ placeholder="Add your prompt here..."
86
+ />
87
+ <button
88
+ id="run"
89
+ class="bg-gray-700 hover:bg-gray-800 text-white font-normal py-2 w-16 rounded disabled:bg-gray-300 disabled:cursor-not-allowed"
90
+ >
91
+ Run
92
+ </button>
93
+ </form>
94
+
95
+ <details>
96
+ <summary class="font-medium cursor-pointer">Advanced Options</summary>
97
+
98
+ <div class="grid grid-cols-3 max-w-md items-center gap-3 py-3">
99
+ <label class="text-sm font-medium" for="max-seq"
100
+ >Maximum length
101
+ </label>
102
+ <input
103
+ type="range"
104
+ id="max-seq"
105
+ name="max-seq"
106
+ min="1"
107
+ max="2048"
108
+ step="1"
109
+ value="200"
110
+ oninput="this.nextElementSibling.value = Number(this.value)"
111
+ />
112
+ <output
113
+ class="text-xs w-[50px] text-center font-light px-1 py-1 border border-gray-700 rounded-md"
114
+ >
115
+ 200</output
116
+ >
117
+ <label class="text-sm font-medium" for="temperature"
118
+ >Temperature</label
119
+ >
120
+ <input
121
+ type="range"
122
+ id="temperature"
123
+ name="temperature"
124
+ min="0"
125
+ max="2"
126
+ step="0.01"
127
+ value="0.00"
128
+ oninput="this.nextElementSibling.value = Number(this.value).toFixed(2)"
129
+ />
130
+ <output
131
+ class="text-xs w-[50px] text-center font-light px-1 py-1 border border-gray-700 rounded-md"
132
+ >
133
+ 0.00</output
134
+ >
135
+ <label class="text-sm font-medium" for="top-p">Top-p</label>
136
+ <input
137
+ type="range"
138
+ id="top-p"
139
+ name="top-p"
140
+ min="0"
141
+ max="1"
142
+ step="0.01"
143
+ value="1.00"
144
+ oninput="this.nextElementSibling.value = Number(this.value).toFixed(2)"
145
+ />
146
+ <output
147
+ class="text-xs w-[50px] text-center font-light px-1 py-1 border border-gray-700 rounded-md"
148
+ >
149
+ 1.00</output
150
+ >
151
+
152
+ <label class="text-sm font-medium" for="repeat_penalty"
153
+ >Repeat Penalty</label
154
+ >
155
+
156
+ <input
157
+ type="range"
158
+ id="repeat_penalty"
159
+ name="repeat_penalty"
160
+ min="1"
161
+ max="2"
162
+ step="0.01"
163
+ value="1.10"
164
+ oninput="this.nextElementSibling.value = Number(this.value).toFixed(2)"
165
+ />
166
+ <output
167
+ class="text-xs w-[50px] text-center font-light px-1 py-1 border border-gray-700 rounded-md"
168
+ >1.10</output
169
+ >
170
+ <label class="text-sm font-medium" for="seed">Seed</label>
171
+ <input
172
+ type="number"
173
+ id="seed"
174
+ name="seed"
175
+ value="299792458"
176
+ class="font-light border border-gray-700 text-right rounded-md p-2"
177
+ />
178
+ <button
179
+ id="run"
180
+ onclick="document.querySelector('#seed').value = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)"
181
+ class="bg-gray-700 hover:bg-gray-800 text-white font-normal py-1 w-[50px] rounded disabled:bg-gray-300 disabled:cursor-not-allowed text-sm"
182
+ >
183
+ Rand
184
+ </button>
185
+ </div>
186
+ </details>
187
+
188
+ <div class="grid md:grid-cols-2 gap-4 items-start">
189
+ <div>
190
+ <div class="relative md:mt-6">
191
+ <div
192
+ class="absolute w-full bottom-full flex justify-between items-center"
193
+ >
194
+ <div class="flex gap-2 w-full">
195
+ <button
196
+ id="clear-img-btn"
197
+ disabled
198
+ title="Clear Image"
199
+ class="ml-auto text-xs py-1 bg-white rounded-md disabled:opacity-20 flex gap-1 items-center"
200
+ >
201
+ <svg
202
+ class=""
203
+ xmlns="http://www.w3.org/2000/svg"
204
+ viewBox="0 0 13 12"
205
+ height="1em"
206
+ >
207
+ <path
208
+ d="M1.6.7 12 11.1M12 .7 1.6 11.1"
209
+ stroke="#2E3036"
210
+ stroke-width="2"
211
+ />
212
+ </svg>
213
+ </button>
214
+ </div>
215
+ </div>
216
+ <div
217
+ id="drop-area"
218
+ class="min-h-[250px] flex flex-col items-center justify-center border-2 border-gray-300 border-dashed rounded-xl relative w-full overflow-hidden"
219
+ >
220
+ <div
221
+ class="absolute flex flex-col items-center justify-center space-y-1 text-center"
222
+ >
223
+ <svg
224
+ width="25"
225
+ height="25"
226
+ viewBox="0 0 25 25"
227
+ fill="none"
228
+ xmlns="http://www.w3.org/2000/svg"
229
+ >
230
+ <path
231
+ d="M3.5 24.3a3 3 0 0 1-1.9-.8c-.5-.5-.8-1.2-.8-1.9V2.9c0-.7.3-1.3.8-1.9.6-.5 1.2-.7 2-.7h18.6c.7 0 1.3.2 1.9.7.5.6.7 1.2.7 2v18.6c0 .7-.2 1.4-.7 1.9a3 3 0 0 1-2 .8H3.6Zm0-2.7h18.7V2.9H3.5v18.7Zm2.7-2.7h13.3c.3 0 .5 0 .6-.3v-.7l-3.7-5a.6.6 0 0 0-.6-.2c-.2 0-.4 0-.5.3l-3.5 4.6-2.4-3.3a.6.6 0 0 0-.6-.3c-.2 0-.4.1-.5.3l-2.7 3.6c-.1.2-.2.4 0 .7.1.2.3.3.6.3Z"
232
+ fill="#000"
233
+ />
234
+ </svg>
235
+ <div class="flex text-sm text-gray-600">
236
+ <label
237
+ for="file-upload"
238
+ class="relative cursor-pointer bg-white rounded-md font-medium text-blue-950 hover:text-blue-700"
239
+ >
240
+ <span>Drag and drop the image here</span>
241
+ <span class="block text-xs">or</span>
242
+ <span class="block text-xs">Click to upload</span>
243
+ </label>
244
+ </div>
245
+ <input
246
+ id="file-upload"
247
+ name="file-upload"
248
+ type="file"
249
+ accept="image/*"
250
+ class="sr-only"
251
+ />
252
+ </div>
253
+ <canvas
254
+ id="canvas"
255
+ class="z-10 pointer-events-none w-full"
256
+ ></canvas>
257
+ </div>
258
+ </div>
259
+ </div>
260
+ <div>
261
+ <h3 class="font-medium">Generation:</h3>
262
+ <div
263
+ class="min-h-[250px] bg-slate-100 text-gray-500 p-4 rounded-md flex flex-col gap-2"
264
+ >
265
+ <div
266
+ id="output-counter"
267
+ hidden
268
+ class="ml-auto font-semibold grid-rows-1"
269
+ ></div>
270
+ <p hidden id="output-generation" class="grid-rows-2 text-lg"></p>
271
+ <span id="output-status" class="m-auto font-light"
272
+ >No output yet</span
273
+ >
274
+ </div>
275
+ </div>
276
+ </div>
277
+ <div>
278
+ <div
279
+ class="flex gap-3 items-center overflow-x-scroll"
280
+ id="image-select"
281
+ >
282
+ <h3 class="font-medium">Examples:</h3>
283
+
284
+ <img
285
+ src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/candle/examples/sf.jpg"
286
+ class="cursor-pointer w-24 h-24 object-cover"
287
+ />
288
+ <img
289
+ src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/candle/examples/bike.jpeg"
290
+ class="cursor-pointer w-24 h-24 object-cover"
291
+ />
292
+ <img
293
+ src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/candle/examples/000000000077.jpg"
294
+ class="cursor-pointer w-24 h-24 object-cover"
295
+ />
296
+ <img
297
+ src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/candle/examples/demo-1.jpg"
298
+ class="cursor-pointer w-24 h-24 object-cover"
299
+ />
300
+ </div>
301
+ </div>
302
+ </main>
303
+ </body>
304
  </html>
moondreamWorker.js ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import init, { Model } from "./build/m.js";
2
+
3
+ async function fetchArrayBuffer(url, cacheModel = true) {
4
+ if (!cacheModel)
5
+ return new Uint8Array(await (await fetch(url)).arrayBuffer());
6
+ const cacheName = "moondream-candle-cache";
7
+ const cache = await caches.open(cacheName);
8
+ const cachedResponse = await cache.match(url);
9
+ if (cachedResponse) {
10
+ const data = await cachedResponse.arrayBuffer();
11
+ return new Uint8Array(data);
12
+ }
13
+ const res = await fetch(url, { cache: "force-cache" });
14
+ cache.put(url, res.clone());
15
+ return new Uint8Array(await res.arrayBuffer());
16
+ }
17
+
18
+ async function concatenateArrayBuffers(urls) {
19
+ const arrayBuffers = await Promise.all(
20
+ urls.map((url) => fetchArrayBuffer(url))
21
+ );
22
+
23
+ let totalLength = arrayBuffers.reduce(
24
+ (acc, arrayBuffer) => acc + arrayBuffer.byteLength,
25
+ 0
26
+ );
27
+ let concatenatedBuffer = new Uint8Array(totalLength);
28
+
29
+ let offset = 0;
30
+ arrayBuffers.forEach((buffer) => {
31
+ concatenatedBuffer.set(new Uint8Array(buffer), offset);
32
+ offset += buffer.byteLength;
33
+ });
34
+ return concatenatedBuffer;
35
+ }
36
+
37
+ class Moondream {
38
+ static imageArrayHash = {};
39
+ static instance = {};
40
+ static currentModelID = null;
41
+
42
+ static async getInstance(weightsURL, modelID, tokenizerURL, quantized) {
43
+ // load individual modelID only once
44
+ if (!this.instance[modelID]) {
45
+ await init();
46
+
47
+ self.postMessage({ status: "loading", message: "Loading Model" });
48
+ const [weightsArrayU8, tokenizerArrayU8] = await Promise.all([
49
+ weightsURL instanceof Array
50
+ ? concatenateArrayBuffers(weightsURL)
51
+ : fetchArrayBuffer(weightsURL),
52
+ fetchArrayBuffer(tokenizerURL),
53
+ ]);
54
+
55
+ this.instance[modelID] = new Model(
56
+ weightsArrayU8,
57
+ tokenizerArrayU8,
58
+ quantized
59
+ );
60
+ }
61
+ this.currentModelID = modelID;
62
+ return this.instance[modelID];
63
+ }
64
+
65
+ // Remove the modelID parameter from setImageEmbeddings
66
+ static setImageEmbeddings(imageArrayU8) {
67
+ // check if image embeddings are already set for this image and model
68
+ const imageArrayHash = this.getSimpleHash(imageArrayU8);
69
+ if (
70
+ this.imageArrayHash[this.currentModelID] === imageArrayHash &&
71
+ this.instance[this.currentModelID]
72
+ ) {
73
+ self.postMessage({
74
+ status: "embedding",
75
+ message: "Embeddings Already Set",
76
+ });
77
+ return;
78
+ }
79
+ this.imageArrayHash[this.currentModelID] = imageArrayHash;
80
+ this.instance[this.currentModelID].set_image_embeddings(imageArrayU8);
81
+ self.postMessage({ status: "embedding", message: "Embeddings Set" });
82
+ }
83
+
84
+ static getSimpleHash(imageArrayU8) {
85
+ // get simple hash of imageArrayU8
86
+ let imageArrayHash = 0;
87
+ for (let i = 0; i < imageArrayU8.length; i += 100) {
88
+ imageArrayHash ^= imageArrayU8[i];
89
+ }
90
+ return imageArrayHash.toString(16);
91
+ }
92
+ }
93
+
94
+ let controller = null;
95
+ self.addEventListener("message", (event) => {
96
+ if (event.data.command === "start") {
97
+ controller = new AbortController();
98
+ generate(event.data);
99
+ } else if (event.data.command === "abort") {
100
+ controller.abort();
101
+ }
102
+ });
103
+
104
+ async function generate(data) {
105
+ const {
106
+ weightsURL,
107
+ modelID,
108
+ tokenizerURL,
109
+ quantized,
110
+ imageURL,
111
+ prompt,
112
+ seed,
113
+ temp,
114
+ top_p,
115
+ repeatPenalty,
116
+ maxSeqLen,
117
+ verbose_prompt,
118
+ } = data;
119
+ try {
120
+ self.postMessage({ status: "loading", message: "Starting Moondream" });
121
+ const model = await Moondream.getInstance(
122
+ weightsURL,
123
+ modelID,
124
+ tokenizerURL,
125
+ quantized
126
+ );
127
+
128
+ self.postMessage({ status: "loading", message: "Initializing model" });
129
+
130
+ self.postMessage({ status: "loading", message: "Loading Image" });
131
+ const imageArrayU8 = await fetchArrayBuffer(imageURL, false);
132
+
133
+ self.postMessage({ status: "embedding", message: "Creating Embeddings" });
134
+ Moondream.setImageEmbeddings(imageArrayU8);
135
+ self.postMessage({
136
+ status: "complete-embedding",
137
+ message: "Embeddings Complete",
138
+ });
139
+ const firstToken = model.init_with_image_prompt(
140
+ prompt,
141
+ BigInt(seed),
142
+ temp,
143
+ top_p,
144
+ repeatPenalty,
145
+ 64, //repeat_last_n
146
+ verbose_prompt
147
+ );
148
+ const seq_len = 2048;
149
+
150
+ let sentence = firstToken;
151
+ let maxTokens = maxSeqLen ? maxSeqLen : seq_len - prompt.length - 1;
152
+ let startTime = performance.now();
153
+ let tokensCount = 0;
154
+ while (tokensCount < maxTokens) {
155
+ await new Promise(async (resolve) => {
156
+ if (controller && controller.signal.aborted) {
157
+ console.log("Aborted");
158
+ self.postMessage({
159
+ status: "aborted",
160
+ message: "Aborted",
161
+ output: prompt + sentence,
162
+ });
163
+ return;
164
+ }
165
+ const token = await model.next_token();
166
+ console.log("Token: ", token);
167
+ if (token === "<|endoftext|>") {
168
+ self.postMessage({
169
+ status: "complete",
170
+ message: "complete",
171
+ output: prompt + sentence,
172
+ });
173
+ return;
174
+ }
175
+ const tokensSec =
176
+ ((tokensCount + 1) / (performance.now() - startTime)) * 1000;
177
+
178
+ sentence += token;
179
+ self.postMessage({
180
+ status: "generating",
181
+ message: "Generating token",
182
+ token: token,
183
+ sentence: sentence,
184
+ totalTime: performance.now() - startTime,
185
+ tokensSec,
186
+ prompt: prompt,
187
+ });
188
+ setTimeout(resolve, 0);
189
+ });
190
+ tokensCount++;
191
+ }
192
+ self.postMessage({
193
+ status: "complete",
194
+ message: "complete",
195
+ output: prompt + sentence,
196
+ });
197
+ } catch (e) {
198
+ self.postMessage({ error: e });
199
+ }
200
+ }