kjarni-wasm 0.1.10 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/pkg/kjarni_wasm.d.ts +29 -22
- package/pkg/kjarni_wasm.js +57 -35
- package/pkg/kjarni_wasm_bg.wasm +0 -0
- package/pkg/kjarni_wasm_bg.wasm.d.ts +4 -2
- package/pkg/package.json +1 -1
package/package.json
CHANGED
package/pkg/kjarni_wasm.d.ts
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* A local language model running in the browser.
|
|
6
|
-
*
|
|
7
|
-
* Text generation is synchronous here, and deliberately so. The engine's streaming
|
|
8
|
-
* path builds a background task with `tokio::task::spawn_blocking`, and wasm has no
|
|
9
|
-
* blocking pool for that to run on — it compiles but would fail at runtime. Calling
|
|
10
|
-
* the generation loop directly and draining the channel afterwards avoids the
|
|
11
|
-
* problem entirely.
|
|
12
|
-
*
|
|
13
|
-
* The cost is that a call blocks until the whole response is ready, which for a few
|
|
14
|
-
* hundred tokens is seconds, not milliseconds. Run it in a Web Worker; on the main
|
|
15
|
-
* thread it will freeze the tab.
|
|
16
|
-
*/
|
|
17
4
|
export class WasmChat {
|
|
18
5
|
private constructor();
|
|
19
6
|
free(): void;
|
|
@@ -26,6 +13,20 @@ export class WasmChat {
|
|
|
26
13
|
* The model's context window, in tokens.
|
|
27
14
|
*/
|
|
28
15
|
context_size(): number;
|
|
16
|
+
/**
|
|
17
|
+
* Reuse the KV cache across turns, so a conversation prefills only its newest
|
|
18
|
+
* message instead of replaying the whole transcript.
|
|
19
|
+
*
|
|
20
|
+
* Measured natively on Qwen2.5-0.5B with a long system prompt: turn one is
|
|
21
|
+
* unchanged, turns two and three go from about 2.2s to roughly 0.2s, for
|
|
22
|
+
* identical answers. A browser tab is one conversation, so there is no sharing
|
|
23
|
+
* hazard here.
|
|
24
|
+
*
|
|
25
|
+
* `tokens` is the longest transcript that can be reused, and what the memory
|
|
26
|
+
* cost scales with; pass 0 for [`DEFAULT_WASM_PREFIX_CACHE_TOKENS`]. Longer
|
|
27
|
+
* conversations keep working, they simply stop reusing once they outgrow it.
|
|
28
|
+
*/
|
|
29
|
+
enablePrefixCache(tokens: number): void;
|
|
29
30
|
/**
|
|
30
31
|
* Generate a completion for `prompt`.
|
|
31
32
|
*/
|
|
@@ -45,6 +46,10 @@ export class WasmChat {
|
|
|
45
46
|
* itself is in `generate_stream_core`, which builds and is tested natively.
|
|
46
47
|
*/
|
|
47
48
|
generate_stream(prompt: string, max_new_tokens: number, temperature: number, on_token: Function): string;
|
|
49
|
+
/**
|
|
50
|
+
* Whether prefix reuse is on.
|
|
51
|
+
*/
|
|
52
|
+
hasPrefixCache(): boolean;
|
|
48
53
|
/**
|
|
49
54
|
* Number of messages held, system prompt included.
|
|
50
55
|
*/
|
|
@@ -81,13 +86,6 @@ export class WasmClassifier {
|
|
|
81
86
|
private constructor();
|
|
82
87
|
free(): void;
|
|
83
88
|
[Symbol.dispose](): void;
|
|
84
|
-
/**
|
|
85
|
-
* Classify a batch, returning the single best label for each input.
|
|
86
|
-
*
|
|
87
|
-
* One result per input, in input order, so the caller can line them up with
|
|
88
|
-
* whatever it passed in.
|
|
89
|
-
*/
|
|
90
|
-
classify_batch(texts: string[]): any;
|
|
91
89
|
/**
|
|
92
90
|
* Classify one text, returning every label with its score, highest first.
|
|
93
91
|
*
|
|
@@ -96,6 +94,13 @@ export class WasmClassifier {
|
|
|
96
94
|
* what makes the behaviour testable on the host.
|
|
97
95
|
*/
|
|
98
96
|
classify(text: string): any;
|
|
97
|
+
/**
|
|
98
|
+
* Classify a batch, returning the single best label for each input.
|
|
99
|
+
*
|
|
100
|
+
* One result per input, in input order, so the caller can line them up with
|
|
101
|
+
* whatever it passed in.
|
|
102
|
+
*/
|
|
103
|
+
classify_batch(texts: string[]): any;
|
|
99
104
|
/**
|
|
100
105
|
* The labels this model predicts, in index order.
|
|
101
106
|
*/
|
|
@@ -215,8 +220,10 @@ export interface InitOutput {
|
|
|
215
220
|
readonly set_debug_logging: (a: number) => void;
|
|
216
221
|
readonly wasmchat_clear_history: (a: number) => void;
|
|
217
222
|
readonly wasmchat_context_size: (a: number) => number;
|
|
223
|
+
readonly wasmchat_enablePrefixCache: (a: number, b: number, c: number) => void;
|
|
218
224
|
readonly wasmchat_generate: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
219
225
|
readonly wasmchat_generate_stream: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
226
|
+
readonly wasmchat_hasPrefixCache: (a: number) => number;
|
|
220
227
|
readonly wasmchat_history_len: (a: number) => number;
|
|
221
228
|
readonly wasmchat_load: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
222
229
|
readonly wasmchat_send_stream: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
@@ -248,8 +255,8 @@ export interface InitOutput {
|
|
|
248
255
|
readonly wasmsearch_search_keywords: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
249
256
|
readonly wasmsearch_search_semantic: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
250
257
|
readonly wasmsearch_update_file: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
251
|
-
readonly
|
|
252
|
-
readonly
|
|
258
|
+
readonly __wasm_bindgen_func_elem_5674: (a: number, b: number, c: number, d: number) => void;
|
|
259
|
+
readonly __wasm_bindgen_func_elem_5694: (a: number, b: number, c: number, d: number) => void;
|
|
253
260
|
readonly __wbindgen_export: (a: number, b: number) => number;
|
|
254
261
|
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
255
262
|
readonly __wbindgen_export3: (a: number) => void;
|
package/pkg/kjarni_wasm.js
CHANGED
|
@@ -1,18 +1,5 @@
|
|
|
1
1
|
/* @ts-self-types="./kjarni_wasm.d.ts" */
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* A local language model running in the browser.
|
|
5
|
-
*
|
|
6
|
-
* Text generation is synchronous here, and deliberately so. The engine's streaming
|
|
7
|
-
* path builds a background task with `tokio::task::spawn_blocking`, and wasm has no
|
|
8
|
-
* blocking pool for that to run on — it compiles but would fail at runtime. Calling
|
|
9
|
-
* the generation loop directly and draining the channel afterwards avoids the
|
|
10
|
-
* problem entirely.
|
|
11
|
-
*
|
|
12
|
-
* The cost is that a call blocks until the whole response is ready, which for a few
|
|
13
|
-
* hundred tokens is seconds, not milliseconds. Run it in a Web Worker; on the main
|
|
14
|
-
* thread it will freeze the tab.
|
|
15
|
-
*/
|
|
16
3
|
export class WasmChat {
|
|
17
4
|
static __wrap(ptr) {
|
|
18
5
|
const obj = Object.create(WasmChat.prototype);
|
|
@@ -44,6 +31,33 @@ export class WasmChat {
|
|
|
44
31
|
const ret = wasm.wasmchat_context_size(this.__wbg_ptr);
|
|
45
32
|
return ret >>> 0;
|
|
46
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Reuse the KV cache across turns, so a conversation prefills only its newest
|
|
36
|
+
* message instead of replaying the whole transcript.
|
|
37
|
+
*
|
|
38
|
+
* Measured natively on Qwen2.5-0.5B with a long system prompt: turn one is
|
|
39
|
+
* unchanged, turns two and three go from about 2.2s to roughly 0.2s, for
|
|
40
|
+
* identical answers. A browser tab is one conversation, so there is no sharing
|
|
41
|
+
* hazard here.
|
|
42
|
+
*
|
|
43
|
+
* `tokens` is the longest transcript that can be reused, and what the memory
|
|
44
|
+
* cost scales with; pass 0 for [`DEFAULT_WASM_PREFIX_CACHE_TOKENS`]. Longer
|
|
45
|
+
* conversations keep working, they simply stop reusing once they outgrow it.
|
|
46
|
+
* @param {number} tokens
|
|
47
|
+
*/
|
|
48
|
+
enablePrefixCache(tokens) {
|
|
49
|
+
try {
|
|
50
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
51
|
+
wasm.wasmchat_enablePrefixCache(retptr, this.__wbg_ptr, tokens);
|
|
52
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
53
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
54
|
+
if (r1) {
|
|
55
|
+
throw takeObject(r0);
|
|
56
|
+
}
|
|
57
|
+
} finally {
|
|
58
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
47
61
|
/**
|
|
48
62
|
* Generate a completion for `prompt`.
|
|
49
63
|
* @param {string} prompt
|
|
@@ -123,6 +137,14 @@ export class WasmChat {
|
|
|
123
137
|
wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
|
|
124
138
|
}
|
|
125
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Whether prefix reuse is on.
|
|
142
|
+
* @returns {boolean}
|
|
143
|
+
*/
|
|
144
|
+
hasPrefixCache() {
|
|
145
|
+
const ret = wasm.wasmchat_hasPrefixCache(this.__wbg_ptr);
|
|
146
|
+
return ret !== 0;
|
|
147
|
+
}
|
|
126
148
|
/**
|
|
127
149
|
* Number of messages held, system prompt included.
|
|
128
150
|
* @returns {number}
|
|
@@ -230,19 +252,20 @@ export class WasmClassifier {
|
|
|
230
252
|
wasm.__wbg_wasmclassifier_free(ptr, 0);
|
|
231
253
|
}
|
|
232
254
|
/**
|
|
233
|
-
* Classify
|
|
255
|
+
* Classify one text, returning every label with its score, highest first.
|
|
234
256
|
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
257
|
+
* Serializing to a `JsValue` panics outside wasm32, so the work lives in
|
|
258
|
+
* [`WasmClassifier::classify_core`] and this is only the conversion. That is
|
|
259
|
+
* what makes the behaviour testable on the host.
|
|
260
|
+
* @param {string} text
|
|
238
261
|
* @returns {any}
|
|
239
262
|
*/
|
|
240
|
-
|
|
263
|
+
classify(text) {
|
|
241
264
|
try {
|
|
242
265
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
243
|
-
const ptr0 =
|
|
266
|
+
const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
244
267
|
const len0 = WASM_VECTOR_LEN;
|
|
245
|
-
wasm.
|
|
268
|
+
wasm.wasmclassifier_classify(retptr, this.__wbg_ptr, ptr0, len0);
|
|
246
269
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
247
270
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
248
271
|
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
@@ -255,20 +278,19 @@ export class WasmClassifier {
|
|
|
255
278
|
}
|
|
256
279
|
}
|
|
257
280
|
/**
|
|
258
|
-
* Classify
|
|
281
|
+
* Classify a batch, returning the single best label for each input.
|
|
259
282
|
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* @param {string} text
|
|
283
|
+
* One result per input, in input order, so the caller can line them up with
|
|
284
|
+
* whatever it passed in.
|
|
285
|
+
* @param {string[]} texts
|
|
264
286
|
* @returns {any}
|
|
265
287
|
*/
|
|
266
|
-
|
|
288
|
+
classify_batch(texts) {
|
|
267
289
|
try {
|
|
268
290
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
269
|
-
const ptr0 =
|
|
291
|
+
const ptr0 = passArrayJsValueToWasm0(texts, wasm.__wbindgen_export);
|
|
270
292
|
const len0 = WASM_VECTOR_LEN;
|
|
271
|
-
wasm.
|
|
293
|
+
wasm.wasmclassifier_classify_batch(retptr, this.__wbg_ptr, ptr0, len0);
|
|
272
294
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
273
295
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
274
296
|
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
@@ -1092,7 +1114,7 @@ function __wbg_get_imports() {
|
|
|
1092
1114
|
const a = state0.a;
|
|
1093
1115
|
state0.a = 0;
|
|
1094
1116
|
try {
|
|
1095
|
-
return
|
|
1117
|
+
return __wasm_bindgen_func_elem_5694(a, state0.b, arg0, arg1);
|
|
1096
1118
|
} finally {
|
|
1097
1119
|
state0.a = a;
|
|
1098
1120
|
}
|
|
@@ -1206,8 +1228,8 @@ function __wbg_get_imports() {
|
|
|
1206
1228
|
return addHeapObject(ret);
|
|
1207
1229
|
},
|
|
1208
1230
|
__wbindgen_generic_0000000000000001: function(arg0, arg1) {
|
|
1209
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
1210
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
1231
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 2082, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
1232
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_5674);
|
|
1211
1233
|
return addHeapObject(ret);
|
|
1212
1234
|
},
|
|
1213
1235
|
__wbindgen_generic_0000000000000002: function(arg0) {
|
|
@@ -1244,14 +1266,14 @@ function __wbg_get_imports() {
|
|
|
1244
1266
|
};
|
|
1245
1267
|
}
|
|
1246
1268
|
|
|
1247
|
-
function
|
|
1248
|
-
wasm.
|
|
1269
|
+
function __wasm_bindgen_func_elem_5694(arg0, arg1, arg2, arg3) {
|
|
1270
|
+
wasm.__wasm_bindgen_func_elem_5694(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
|
1249
1271
|
}
|
|
1250
1272
|
|
|
1251
|
-
function
|
|
1273
|
+
function __wasm_bindgen_func_elem_5674(arg0, arg1, arg2) {
|
|
1252
1274
|
try {
|
|
1253
1275
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1254
|
-
wasm.
|
|
1276
|
+
wasm.__wasm_bindgen_func_elem_5674(retptr, arg0, arg1, addHeapObject(arg2));
|
|
1255
1277
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1256
1278
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1257
1279
|
if (r1) {
|
package/pkg/kjarni_wasm_bg.wasm
CHANGED
|
Binary file
|
|
@@ -12,8 +12,10 @@ export const init: () => void;
|
|
|
12
12
|
export const set_debug_logging: (a: number) => void;
|
|
13
13
|
export const wasmchat_clear_history: (a: number) => void;
|
|
14
14
|
export const wasmchat_context_size: (a: number) => number;
|
|
15
|
+
export const wasmchat_enablePrefixCache: (a: number, b: number, c: number) => void;
|
|
15
16
|
export const wasmchat_generate: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
16
17
|
export const wasmchat_generate_stream: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
18
|
+
export const wasmchat_hasPrefixCache: (a: number) => number;
|
|
17
19
|
export const wasmchat_history_len: (a: number) => number;
|
|
18
20
|
export const wasmchat_load: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
19
21
|
export const wasmchat_send_stream: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
@@ -45,8 +47,8 @@ export const wasmsearch_search: (a: number, b: number, c: number, d: number, e:
|
|
|
45
47
|
export const wasmsearch_search_keywords: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
46
48
|
export const wasmsearch_search_semantic: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
47
49
|
export const wasmsearch_update_file: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
48
|
-
export const
|
|
49
|
-
export const
|
|
50
|
+
export const __wasm_bindgen_func_elem_5674: (a: number, b: number, c: number, d: number) => void;
|
|
51
|
+
export const __wasm_bindgen_func_elem_5694: (a: number, b: number, c: number, d: number) => void;
|
|
50
52
|
export const __wbindgen_export: (a: number, b: number) => number;
|
|
51
53
|
export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
52
54
|
export const __wbindgen_export3: (a: number) => void;
|
package/pkg/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"Ólafur Aron Jóhannsson <olafurjohannss@gmail.com>"
|
|
6
6
|
],
|
|
7
7
|
"description": "Local AI inference in the browser: embeddings, classification, reranking, semantic search and chat, compiled to WebAssembly.",
|
|
8
|
-
"version": "0.
|
|
8
|
+
"version": "0.2.0",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|