@pie-project/server-web 0.5.2 → 0.6.1
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/dist/pie.mjs +61 -41
- package/dist/pie_browser_bg.wasm +0 -0
- package/dist/precompile.mjs +1238 -0
- package/dist/worker.mjs +33 -29
- package/index.d.ts +13 -6
- package/package.json +6 -5
- package/src/pie.mjs +35 -17
- package/src/precompile.mjs +37 -0
- package/src/worker.mjs +4 -4
- package/README.md +0 -91
package/dist/worker.mjs
CHANGED
|
@@ -81,20 +81,24 @@ function pie_init(log_filter) {
|
|
|
81
81
|
var len0 = WASM_VECTOR_LEN;
|
|
82
82
|
wasm2.pie_init(ptr0, len0);
|
|
83
83
|
}
|
|
84
|
-
function pie_install_language(language, component) {
|
|
84
|
+
function pie_install_language(language, component, precompiled) {
|
|
85
85
|
const ptr0 = passStringToWasm0(language, wasm2.__wbindgen_export, wasm2.__wbindgen_export2);
|
|
86
86
|
const len0 = WASM_VECTOR_LEN;
|
|
87
87
|
const ptr1 = passArray8ToWasm0(component, wasm2.__wbindgen_export);
|
|
88
88
|
const len1 = WASM_VECTOR_LEN;
|
|
89
|
-
|
|
89
|
+
var ptr2 = isLikeNone(precompiled) ? 0 : passArray8ToWasm0(precompiled, wasm2.__wbindgen_export);
|
|
90
|
+
var len2 = WASM_VECTOR_LEN;
|
|
91
|
+
const ret = wasm2.pie_install_language(ptr0, len0, ptr1, len1, ptr2, len2);
|
|
90
92
|
return takeObject(ret);
|
|
91
93
|
}
|
|
92
|
-
function pie_install_program(
|
|
93
|
-
const ptr0 = passArray8ToWasm0(
|
|
94
|
+
function pie_install_program(bytes, file, version) {
|
|
95
|
+
const ptr0 = passArray8ToWasm0(bytes, wasm2.__wbindgen_export);
|
|
94
96
|
const len0 = WASM_VECTOR_LEN;
|
|
95
|
-
const ptr1 = passStringToWasm0(
|
|
97
|
+
const ptr1 = passStringToWasm0(file, wasm2.__wbindgen_export, wasm2.__wbindgen_export2);
|
|
96
98
|
const len1 = WASM_VECTOR_LEN;
|
|
97
|
-
|
|
99
|
+
var ptr2 = isLikeNone(version) ? 0 : passStringToWasm0(version, wasm2.__wbindgen_export, wasm2.__wbindgen_export2);
|
|
100
|
+
var len2 = WASM_VECTOR_LEN;
|
|
101
|
+
const ret = wasm2.pie_install_program(ptr0, len0, ptr1, len1, ptr2, len2);
|
|
98
102
|
return takeObject(ret);
|
|
99
103
|
}
|
|
100
104
|
function pie_open_session() {
|
|
@@ -297,7 +301,7 @@ function __wbg_get_imports() {
|
|
|
297
301
|
const ret = getObject(arg0).features;
|
|
298
302
|
return addHeapObject(ret);
|
|
299
303
|
},
|
|
300
|
-
|
|
304
|
+
__wbg_fetchRange_837bbd1b92ceed92: function(arg0, arg1, arg2) {
|
|
301
305
|
__pieHost.fetchRange(arg0, arg1, arg2 >>> 0);
|
|
302
306
|
},
|
|
303
307
|
__wbg_finish_09ec094c10f41e7b: function(arg0) {
|
|
@@ -557,7 +561,7 @@ function __wbg_get_imports() {
|
|
|
557
561
|
const a = state0.a;
|
|
558
562
|
state0.a = 0;
|
|
559
563
|
try {
|
|
560
|
-
return
|
|
564
|
+
return __wasm_bindgen_func_elem_55690(a, state0.b, arg02, arg12);
|
|
561
565
|
} finally {
|
|
562
566
|
state0.a = a;
|
|
563
567
|
}
|
|
@@ -898,23 +902,23 @@ function __wbg_get_imports() {
|
|
|
898
902
|
}, arguments);
|
|
899
903
|
},
|
|
900
904
|
__wbindgen_generic_0000000000000001: function(arg0, arg1) {
|
|
901
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
905
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_55688);
|
|
902
906
|
return addHeapObject(ret);
|
|
903
907
|
},
|
|
904
908
|
__wbindgen_generic_0000000000000002: function(arg0, arg1) {
|
|
905
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
909
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_11414);
|
|
906
910
|
return addHeapObject(ret);
|
|
907
911
|
},
|
|
908
912
|
__wbindgen_generic_0000000000000003: function(arg0, arg1) {
|
|
909
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
913
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_11415);
|
|
910
914
|
return addHeapObject(ret);
|
|
911
915
|
},
|
|
912
916
|
__wbindgen_generic_0000000000000004: function(arg0, arg1) {
|
|
913
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
917
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_11414_15);
|
|
914
918
|
return addHeapObject(ret);
|
|
915
919
|
},
|
|
916
920
|
__wbindgen_generic_0000000000000005: function(arg0, arg1) {
|
|
917
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
921
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_11414_16);
|
|
918
922
|
return addHeapObject(ret);
|
|
919
923
|
},
|
|
920
924
|
__wbindgen_generic_0000000000000006: function(arg0) {
|
|
@@ -946,16 +950,16 @@ function __wbg_get_imports() {
|
|
|
946
950
|
"./platform.mjs": platform_exports
|
|
947
951
|
};
|
|
948
952
|
}
|
|
949
|
-
function
|
|
950
|
-
wasm2.
|
|
953
|
+
function __wasm_bindgen_func_elem_11415(arg0, arg1, arg2) {
|
|
954
|
+
wasm2.__wasm_bindgen_func_elem_11415(arg0, arg1, addHeapObject(arg2));
|
|
951
955
|
}
|
|
952
|
-
function
|
|
953
|
-
wasm2.
|
|
956
|
+
function __wasm_bindgen_func_elem_55690(arg0, arg1, arg2, arg3) {
|
|
957
|
+
wasm2.__wasm_bindgen_func_elem_55690(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
|
954
958
|
}
|
|
955
|
-
function
|
|
959
|
+
function __wasm_bindgen_func_elem_55688(arg0, arg1, arg2) {
|
|
956
960
|
try {
|
|
957
961
|
const retptr = wasm2.__wbindgen_add_to_stack_pointer(-16);
|
|
958
|
-
wasm2.
|
|
962
|
+
wasm2.__wasm_bindgen_func_elem_55688(retptr, arg0, arg1, addHeapObject(arg2));
|
|
959
963
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
960
964
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
961
965
|
if (r1) {
|
|
@@ -965,10 +969,10 @@ function __wasm_bindgen_func_elem_12285(arg0, arg1, arg2) {
|
|
|
965
969
|
wasm2.__wbindgen_add_to_stack_pointer(16);
|
|
966
970
|
}
|
|
967
971
|
}
|
|
968
|
-
function
|
|
972
|
+
function __wasm_bindgen_func_elem_11414(arg0, arg1, arg2) {
|
|
969
973
|
try {
|
|
970
974
|
const retptr = wasm2.__wbindgen_add_to_stack_pointer(-16);
|
|
971
|
-
wasm2.
|
|
975
|
+
wasm2.__wasm_bindgen_func_elem_11414(retptr, arg0, arg1, addHeapObject(arg2));
|
|
972
976
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
973
977
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
974
978
|
if (r1) {
|
|
@@ -978,10 +982,10 @@ function __wasm_bindgen_func_elem_10965(arg0, arg1, arg2) {
|
|
|
978
982
|
wasm2.__wbindgen_add_to_stack_pointer(16);
|
|
979
983
|
}
|
|
980
984
|
}
|
|
981
|
-
function
|
|
985
|
+
function __wasm_bindgen_func_elem_11414_15(arg0, arg1, arg2) {
|
|
982
986
|
try {
|
|
983
987
|
const retptr = wasm2.__wbindgen_add_to_stack_pointer(-16);
|
|
984
|
-
wasm2.
|
|
988
|
+
wasm2.__wasm_bindgen_func_elem_11414_15(retptr, arg0, arg1, addHeapObject(arg2));
|
|
985
989
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
986
990
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
987
991
|
if (r1) {
|
|
@@ -991,10 +995,10 @@ function __wasm_bindgen_func_elem_10965_14(arg0, arg1, arg2) {
|
|
|
991
995
|
wasm2.__wbindgen_add_to_stack_pointer(16);
|
|
992
996
|
}
|
|
993
997
|
}
|
|
994
|
-
function
|
|
998
|
+
function __wasm_bindgen_func_elem_11414_16(arg0, arg1, arg2) {
|
|
995
999
|
try {
|
|
996
1000
|
const retptr = wasm2.__wbindgen_add_to_stack_pointer(-16);
|
|
997
|
-
wasm2.
|
|
1001
|
+
wasm2.__wasm_bindgen_func_elem_11414_16(retptr, arg0, arg1, addHeapObject(arg2));
|
|
998
1002
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
999
1003
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1000
1004
|
if (r1) {
|
|
@@ -1477,11 +1481,11 @@ var host = {
|
|
|
1477
1481
|
async awaitCache() {
|
|
1478
1482
|
await cacheFill;
|
|
1479
1483
|
},
|
|
1480
|
-
async installLanguage(language, wasmBytes) {
|
|
1481
|
-
return await driven(pie_install_language(language, wasmBytes));
|
|
1484
|
+
async installLanguage(language, wasmBytes, precompiled) {
|
|
1485
|
+
return await driven(pie_install_language(language, wasmBytes, precompiled));
|
|
1482
1486
|
},
|
|
1483
|
-
async install(
|
|
1484
|
-
return await driven(pie_install_program(
|
|
1487
|
+
async install(bytes, file, version) {
|
|
1488
|
+
return await driven(pie_install_program(bytes, file, version ?? void 0));
|
|
1485
1489
|
},
|
|
1486
1490
|
async memoryBytes() {
|
|
1487
1491
|
return wasm3.memory.buffer.byteLength;
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { PieClient } from "@pie-project/client";
|
|
1
|
+
import { PieClient, programFile } from "@pie-project/client";
|
|
2
2
|
|
|
3
|
-
export { PieClient };
|
|
3
|
+
export { PieClient, programFile };
|
|
4
4
|
|
|
5
5
|
export interface LoadInfo {
|
|
6
6
|
worker: boolean;
|
|
@@ -15,7 +15,7 @@ export interface LoadOptions {
|
|
|
15
15
|
|
|
16
16
|
export interface BootSummary {
|
|
17
17
|
model: string;
|
|
18
|
-
|
|
18
|
+
deployment: string;
|
|
19
19
|
trace: string;
|
|
20
20
|
weight_bytes: number;
|
|
21
21
|
kv_pages: number;
|
|
@@ -32,7 +32,7 @@ export function bootLazy(
|
|
|
32
32
|
|
|
33
33
|
export function awaitCache(): Promise<void>;
|
|
34
34
|
|
|
35
|
-
export function install(
|
|
35
|
+
export function install(bytes: Uint8Array | ArrayBuffer, file: string, version?: string | null): Promise<string>;
|
|
36
36
|
|
|
37
37
|
export function client(): PieClient;
|
|
38
38
|
|
|
@@ -56,8 +56,15 @@ export class Server {
|
|
|
56
56
|
readonly summary: BootSummary;
|
|
57
57
|
readonly url: string;
|
|
58
58
|
readonly running: boolean;
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
/** `precompiled` is the same component from `precompileComponent` (the
|
|
60
|
+
* `precompile` entry point) on this same build; it spares the first
|
|
61
|
+
* script inferlet compiling the component, which takes seconds in a tab. */
|
|
62
|
+
installLanguage(
|
|
63
|
+
language: "python" | "javascript" | string,
|
|
64
|
+
source: Uint8Array | ArrayBuffer | URL | string,
|
|
65
|
+
options?: { precompiled?: Uint8Array | ArrayBuffer | URL | string },
|
|
66
|
+
): Promise<string>;
|
|
67
|
+
install(source: Uint8Array | ArrayBuffer | URL | string, file?: string | null, version?: string | null): Promise<string>;
|
|
61
68
|
connect(): Promise<PieClient>;
|
|
62
69
|
memoryBytes(): Promise<number>;
|
|
63
70
|
awaitCache(): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-project/server-web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "The browser half of @pie-project/server: the runtime and the WebGPU engine as wasm, reached through `import { Server } from \"@pie-project/server\"` under a bundler.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/pie.mjs",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"./languages": {
|
|
14
14
|
"types": "./src/languages.d.ts",
|
|
15
15
|
"default": "./src/languages.mjs"
|
|
16
|
-
}
|
|
16
|
+
},
|
|
17
|
+
"./precompile": "./dist/precompile.mjs"
|
|
17
18
|
},
|
|
18
19
|
"files": [
|
|
19
20
|
"dist",
|
|
@@ -22,10 +23,10 @@
|
|
|
22
23
|
],
|
|
23
24
|
"scripts": {
|
|
24
25
|
"build": "./build.sh release",
|
|
25
|
-
"bundle": "esbuild src/pie.mjs src/worker.mjs --bundle --format=esm --outdir=dist --out-extension:.js=.mjs --external:./worker.mjs --external:fs --define:__PIE_WASM__='\"./pie_browser_bg.wasm\"' --log-level=warning --log-override:duplicate-object-key=silent && cp pkg/pie_browser_bg.wasm dist/"
|
|
26
|
+
"bundle": "esbuild src/pie.mjs src/worker.mjs src/precompile.mjs --bundle --format=esm --outdir=dist --out-extension:.js=.mjs --external:./worker.mjs --external:fs --external:path --external:node:fs --external:node:url --define:__PIE_WASM__='\"./pie_browser_bg.wasm\"' --log-level=warning --log-override:duplicate-object-key=silent && cp pkg/pie_browser_bg.wasm dist/"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@pie-project/client": "^0.
|
|
29
|
+
"@pie-project/client": "^0.6.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"esbuild": "^0.28.2"
|
|
@@ -33,6 +34,6 @@
|
|
|
33
34
|
"repository": {
|
|
34
35
|
"type": "git",
|
|
35
36
|
"url": "https://github.com/pie-project/pie",
|
|
36
|
-
"directory": "javascript/server-web"
|
|
37
|
+
"directory": "packages/javascript/server-web"
|
|
37
38
|
}
|
|
38
39
|
}
|
package/src/pie.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { PieClient } from "@pie-project/client";
|
|
1
|
+
import { PieClient, programFile } from "@pie-project/client";
|
|
2
2
|
|
|
3
3
|
import { socketClass } from "./transport.mjs";
|
|
4
4
|
import { attachLanguages } from "./languages.mjs";
|
|
5
5
|
|
|
6
|
-
export { PieClient };
|
|
6
|
+
export { PieClient, programFile };
|
|
7
7
|
|
|
8
8
|
const WASM_PATH = typeof __PIE_WASM__ === "undefined" ? "../pkg/pie_browser_bg.wasm" : __PIE_WASM__;
|
|
9
9
|
|
|
@@ -93,16 +93,22 @@ export async function connect() {
|
|
|
93
93
|
return c;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
export async function install(
|
|
97
|
-
const copy = new Uint8Array(
|
|
98
|
-
return await ready().call("install", [copy,
|
|
96
|
+
export async function install(bytes, file, version = null) {
|
|
97
|
+
const copy = new Uint8Array(bytes).slice();
|
|
98
|
+
return await ready().call("install", [copy, file, version], { transfer: [copy.buffer] });
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
/** Hand the runtime a language component (`"python"`, `"javascript"`)
|
|
102
|
-
* from bytes; a script inferlet in that language can run once this has.
|
|
103
|
-
|
|
102
|
+
* from bytes; a script inferlet in that language can run once this has.
|
|
103
|
+
* `precompiled`, from `precompileComponent` on this same build, spares the
|
|
104
|
+
* first such inferlet compiling the component; one the runtime refuses is
|
|
105
|
+
* ignored and the source compiled instead. */
|
|
106
|
+
export async function installLanguage(language, wasmBytes, precompiled) {
|
|
104
107
|
const copy = new Uint8Array(wasmBytes).slice();
|
|
105
|
-
|
|
108
|
+
const ready_ = precompiled ? new Uint8Array(precompiled).slice() : undefined;
|
|
109
|
+
return await ready().call("installLanguage", [language, copy, ready_], {
|
|
110
|
+
transfer: ready_ ? [copy.buffer, ready_.buffer] : [copy.buffer],
|
|
111
|
+
});
|
|
106
112
|
}
|
|
107
113
|
|
|
108
114
|
export async function memoryBytes() {
|
|
@@ -117,9 +123,12 @@ export async function awaitCache() {
|
|
|
117
123
|
return await ready().call("awaitCache", []);
|
|
118
124
|
}
|
|
119
125
|
|
|
126
|
+
function isBytes(source) {
|
|
127
|
+
return source instanceof Uint8Array || source instanceof ArrayBuffer;
|
|
128
|
+
}
|
|
129
|
+
|
|
120
130
|
async function bytesOf(source) {
|
|
121
|
-
if (source
|
|
122
|
-
if (source instanceof ArrayBuffer) return new Uint8Array(source);
|
|
131
|
+
if (isBytes(source)) return new Uint8Array(source);
|
|
123
132
|
const response = await fetch(source);
|
|
124
133
|
if (!response.ok) throw new Error(`pie: ${source}: ${response.status} ${response.statusText}`);
|
|
125
134
|
return new Uint8Array(await response.arrayBuffer());
|
|
@@ -150,7 +159,7 @@ export class Server {
|
|
|
150
159
|
return server;
|
|
151
160
|
}
|
|
152
161
|
|
|
153
|
-
/** What the boot found: model,
|
|
162
|
+
/** What the boot found: model, deployment, weight bytes, kv pages. */
|
|
154
163
|
get summary() {
|
|
155
164
|
return this.#summary;
|
|
156
165
|
}
|
|
@@ -165,16 +174,25 @@ export class Server {
|
|
|
165
174
|
return this.#open && backend !== null;
|
|
166
175
|
}
|
|
167
176
|
|
|
168
|
-
/** A language component (`python`, `javascript`) from bytes or a URL
|
|
169
|
-
|
|
177
|
+
/** A language component (`python`, `javascript`) from bytes or a URL,
|
|
178
|
+
* and optionally the same component precompiled for this build. A
|
|
179
|
+
* precompiled one that fails to fetch is skipped, not fatal. */
|
|
180
|
+
async installLanguage(language, source, { precompiled } = {}) {
|
|
170
181
|
this.#alive();
|
|
171
|
-
|
|
182
|
+
const [bytes, ready_] = await Promise.all([
|
|
183
|
+
bytesOf(source),
|
|
184
|
+
precompiled ? bytesOf(precompiled).catch(() => undefined) : undefined,
|
|
185
|
+
]);
|
|
186
|
+
return installLanguage(language, bytes, ready_);
|
|
172
187
|
}
|
|
173
188
|
|
|
174
|
-
|
|
175
|
-
async install(source, manifest) {
|
|
189
|
+
async install(source, file = null, version = null) {
|
|
176
190
|
this.#alive();
|
|
177
|
-
|
|
191
|
+
if (!file) {
|
|
192
|
+
if (isBytes(source)) throw new Error("Server.install: bytes need `file`, the program's file name (`x.wasm`, `x.py`, `x.js`)");
|
|
193
|
+
file = programFile(new URL(source, location.href));
|
|
194
|
+
}
|
|
195
|
+
return install(await bytesOf(source), file, version);
|
|
178
196
|
}
|
|
179
197
|
|
|
180
198
|
/** A `PieClient` connected in-page. */
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Precompile a language component for the engine a tab runs inferlets on.
|
|
2
|
+
// A tab compiles the Python language component (37 MB) on its first Python
|
|
3
|
+
// inferlet, which takes seconds; a site can run this once at build time and
|
|
4
|
+
// serve the result beside the source, for `Server.installLanguage(language,
|
|
5
|
+
// source, { precompiled })`. The result fits only this exact build of
|
|
6
|
+
// pie_browser_bg.wasm, so run the copy that ships with the page.
|
|
7
|
+
//
|
|
8
|
+
// node precompile.mjs python.wasm python.pulley.cwasm
|
|
9
|
+
//
|
|
10
|
+
// Needs no GPU: it builds the inferlet engine, not a server.
|
|
11
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { initSync, pie_precompile_component } from "../pkg/pie_browser.js";
|
|
14
|
+
|
|
15
|
+
let ready = false;
|
|
16
|
+
|
|
17
|
+
/** The component's bytes, precompiled for this build's engine. */
|
|
18
|
+
export function precompileComponent(component) {
|
|
19
|
+
if (!ready) {
|
|
20
|
+
initSync({ module: readFileSync(new URL(__PIE_WASM__, import.meta.url)) });
|
|
21
|
+
ready = true;
|
|
22
|
+
}
|
|
23
|
+
return pie_precompile_component(new Uint8Array(component));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
27
|
+
const [source, out] = process.argv.slice(2);
|
|
28
|
+
if (!source || !out) {
|
|
29
|
+
console.error("usage: node precompile.mjs <component.wasm> <out.cwasm>");
|
|
30
|
+
process.exit(2);
|
|
31
|
+
}
|
|
32
|
+
const started = performance.now();
|
|
33
|
+
const precompiled = precompileComponent(readFileSync(source));
|
|
34
|
+
writeFileSync(out, precompiled);
|
|
35
|
+
const seconds = ((performance.now() - started) / 1000).toFixed(1);
|
|
36
|
+
console.log(`${out}: ${(precompiled.length / 1048576).toFixed(1)} MiB in ${seconds} s`);
|
|
37
|
+
}
|
package/src/worker.mjs
CHANGED
|
@@ -180,11 +180,11 @@ export const host = {
|
|
|
180
180
|
await cacheFill;
|
|
181
181
|
},
|
|
182
182
|
|
|
183
|
-
async installLanguage(language, wasmBytes) {
|
|
184
|
-
return await driven(bindings.pie_install_language(language, wasmBytes));
|
|
183
|
+
async installLanguage(language, wasmBytes, precompiled) {
|
|
184
|
+
return await driven(bindings.pie_install_language(language, wasmBytes, precompiled));
|
|
185
185
|
},
|
|
186
|
-
async install(
|
|
187
|
-
return await driven(bindings.pie_install_program(
|
|
186
|
+
async install(bytes, file, version) {
|
|
187
|
+
return await driven(bindings.pie_install_program(bytes, file, version ?? undefined));
|
|
188
188
|
},
|
|
189
189
|
|
|
190
190
|
async memoryBytes() {
|
package/README.md
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# @pie-project/server-web
|
|
2
|
-
|
|
3
|
-
The browser half of `@pie-project/server`: the same runtime, WebGPU engine
|
|
4
|
-
and inferlet sandbox as `pie serve`, compiled to `wasm32-unknown-unknown`.
|
|
5
|
-
No server-side inference: the page fetches a `.wgpu.zt` artifact, the
|
|
6
|
-
weights land in WebGPU buffers, and inferlets run under wasmtime's Pulley
|
|
7
|
-
interpreter inside the same module. A bundler reaches it through
|
|
8
|
-
`@pie-project/server`'s `browser` export condition; nothing imports it by
|
|
9
|
-
name.
|
|
10
|
-
|
|
11
|
-
## Use
|
|
12
|
-
|
|
13
|
-
The package ships the wasm and a self-contained bundle (`dist/pie.mjs`,
|
|
14
|
-
`dist/worker.mjs`, `dist/pie_browser_bg.wasm`); the client
|
|
15
|
-
(`@pie-project/client`) is bundled in and re-exported. The worker and the
|
|
16
|
-
wasm are fetched relative to the module, so serve them from your own origin
|
|
17
|
-
(a bundler that understands `new URL(…, import.meta.url)` — Vite, webpack 5 —
|
|
18
|
-
does this by itself; without one, copy `dist/` next to your page).
|
|
19
|
-
|
|
20
|
-
```js
|
|
21
|
-
import { Server } from "@pie-project/server"; // resolves here under a bundler
|
|
22
|
-
import "@pie-project/language-python";
|
|
23
|
-
|
|
24
|
-
const server = await Server.start({ model: "/models/qwen3.5-0.8b.wgpu.zt" }); // served with Range support
|
|
25
|
-
const program = await server.install(inferletBytes, manifestToml);
|
|
26
|
-
const client = await server.connect(); // a PieClient, as for `pie serve`
|
|
27
|
-
const proc = await client.launchProcess(program, { prompt: "The capital of France is", max_tokens: 16 });
|
|
28
|
-
for (;;) {
|
|
29
|
-
const { event, value } = await proc.recv();
|
|
30
|
-
if (event === "return" || event === "error") break;
|
|
31
|
-
}
|
|
32
|
-
await server.shutdown();
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
The page-level functions behind the class (`load`, `bootLazy`, `install`,
|
|
36
|
-
`installLanguage`, `connect`, `awaitCache`, `memoryBytes`) are exported as
|
|
37
|
-
well; `tests/browser` drives them directly.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- The page must be cross-origin isolated (`Cross-Origin-Opener-Policy:
|
|
41
|
-
same-origin`, `Cross-Origin-Embedder-Policy: require-corp`), and the
|
|
42
|
-
browser needs WebGPU and JSPI: Chrome 137+, Firefox 153+ (Firefox on
|
|
43
|
-
Linux has no WebGPU, so the engine cannot boot there).
|
|
44
|
-
- `bootLazy` never holds the artifact in the tab: the loader's reads are
|
|
45
|
-
served as 8 MiB-aligned `Range` requests, and after a boot from the
|
|
46
|
-
network the artifact is copied into the origin's private file system
|
|
47
|
-
(files up to about 2 GB) so the next visit reads it from there;
|
|
48
|
-
`awaitCache()` waits for that copy. Peak wasm memory is a few times the
|
|
49
|
-
largest tensor: 0.8B boots in 285 MiB, 9B in 4 bits in 1.5 GiB.
|
|
50
|
-
- The engine cannot ask WebGPU how much device memory there is and assumes
|
|
51
|
-
8 GiB; a large model with the default pools is refused ("raise the device
|
|
52
|
-
weight budget") — pass `device_memory_mb = 20480` (or a smaller
|
|
53
|
-
`max_total_pages`) in the boot config. `BootConfig` in
|
|
54
|
-
`crates/browser/src/boot.rs` lists the keys.
|
|
55
|
-
- Rust, JavaScript and Python inferlets run. Not available in a tab: MoE
|
|
56
|
-
host-tier expert streaming, Python inferlet snapshots, telemetry, and
|
|
57
|
-
outbound HTTP or files from inferlets (the WASI interfaces link, a call
|
|
58
|
-
fails).
|
|
59
|
-
- `index.d.ts` carries the types.
|
|
60
|
-
|
|
61
|
-
## Build
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
rustup target add wasm32-unknown-unknown
|
|
65
|
-
cargo install wasm-bindgen-cli --version 0.2.128 --locked # must match Cargo.lock
|
|
66
|
-
./javascript/server-web/build.sh # release; `min` for the 23 MB shipping build, `dev` for debug
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
`build.sh` builds `crates/browser`, runs wasm-bindgen into `pkg/`, and bundles
|
|
70
|
-
`src/` with esbuild into `dist/` (`npm run bundle`). The package's own
|
|
71
|
-
dependencies are installed on the first run. Tests, benchmarks and CI gates
|
|
72
|
-
live under `tests/browser` (see its README).
|
|
73
|
-
|
|
74
|
-
## How it fits together
|
|
75
|
-
|
|
76
|
-
| piece | what it does |
|
|
77
|
-
|---|---|
|
|
78
|
-
| `crates/browser` | The wasm-bindgen host: boot, install, sessions speaking the MessagePack frames `pie serve`'s WebSocket carries, `pie_tick`. |
|
|
79
|
-
| `crates/wasmtime-web` | wasmtime in a tab: heap-backed "virtual memory", TLS slots, fibers implemented by the page's JSPI glue (`src/platform.mjs`), and the WASI host for the inferlet's imports (cli, io, clocks, random; 0.2 linked by hand, the 0.3 clocks from `crates/inferlet/wit`). The 0.2 filesystem and http interfaces a JavaScript or Python guest runtime imports regardless are stubbed per component, so they link and only a call fails. |
|
|
80
|
-
| `crates/web-std` | The executor the page ticks, timers over `performance.now()`, crossbeam-shaped channels, and green threads on fibers. The runtime's scheduler and engine lanes run on those unchanged; `crates/runtime`'s `rt` facade names it on wasm32. |
|
|
81
|
-
| `crates/engine-wgpu` | The same engine on both hosts, written for the browser: no GPU wait blocks, every step lands by callback, guests run from the landing. What differs by host sits in `device/host.rs`. |
|
|
82
|
-
| `src/worker.mjs` | The host: wasm init, the tick loop, sessions, the artifact served by byte range. Runs in a Web Worker so the page stays responsive through the inferlet's in-browser compile and every forward pass; `load({ worker: false })` runs it on the page for debugging. |
|
|
83
|
-
| `src/pie.mjs` | The page-side API: the `Server` class over `load`, `bootLazy`, `install`, `connect`. |
|
|
84
|
-
| `src/languages.mjs` | The language registry `@pie-project/server/languages` re-exports: what a language package calls on import. |
|
|
85
|
-
| `src/platform.mjs` | Fibers (JSPI), the clock, the wake hook the wasm imports. |
|
|
86
|
-
| `src/transport.mjs` | The client's in-page socket over the runtime's frame API. |
|
|
87
|
-
|
|
88
|
-
The native wgpu server is the engine's test host rather than a production
|
|
89
|
-
backend: it runs the browser's code path over Vulkan, Metal or DX12 with a
|
|
90
|
-
poll thread standing in for the page's event loop, so what the browser suite
|
|
91
|
-
exercises is exercised natively too, and the two produce identical tokens.
|