@agorapete/wllama 3.5.1-q2.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/.gitmodules +3 -0
- package/.prettierignore +38 -0
- package/AGENTS.md +1 -0
- package/CMakeLists.txt +131 -0
- package/LICENCE +21 -0
- package/README-dev.md +178 -0
- package/README.md +225 -0
- package/README_banner.png +0 -0
- package/assets/screenshot_0.png +0 -0
- package/cpp/generate_glue_prototype.js +115 -0
- package/cpp/glue.hpp +664 -0
- package/cpp/test_glue.cpp +80 -0
- package/cpp/wllama-context.h +1172 -0
- package/cpp/wllama-fs.h +148 -0
- package/cpp/wllama.cpp +187 -0
- package/cpp/wllama.h +6 -0
- package/esm/cache-manager.d.ts +130 -0
- package/esm/debug.d.ts +28 -0
- package/esm/glue/glue.d.ts +22 -0
- package/esm/glue/messages.d.ts +146 -0
- package/esm/huggingface.d.ts +31 -0
- package/esm/index.cjs +3406 -0
- package/esm/index.d.ts +8 -0
- package/esm/index.js +3387 -0
- package/esm/index.min.js +1 -0
- package/esm/index.min.js.map +1 -0
- package/esm/model-manager.d.ts +136 -0
- package/esm/storage/cos.d.ts +36 -0
- package/esm/storage/index.d.ts +33 -0
- package/esm/storage/opfs.d.ts +12 -0
- package/esm/types/oai-compat.d.ts +278 -0
- package/esm/types/types.d.ts +112 -0
- package/esm/utils.d.ts +119 -0
- package/esm/wasm/source-map.d.ts +1 -0
- package/esm/wasm/wllama.wasm +0 -0
- package/esm/wasm-from-cdn.d.ts +8 -0
- package/esm/wllama.d.ts +397 -0
- package/esm/worker.d.ts +92 -0
- package/esm/workers-code/generated.d.ts +4 -0
- package/guides/intro-v2.md +132 -0
- package/guides/intro-v3.1.md +40 -0
- package/guides/intro-v3.md +230 -0
- package/index.ts +1 -0
- package/package.json +71 -0
- package/scripts/bisect_test.sh +33 -0
- package/scripts/build_hf_space.sh +26 -0
- package/scripts/build_source_map.js +269 -0
- package/scripts/build_wasm.sh +19 -0
- package/scripts/build_worker.sh +38 -0
- package/scripts/check_debug_build.js +30 -0
- package/scripts/check_package_size.js +25 -0
- package/scripts/docker-compose.yml +76 -0
- package/scripts/generate_wasm_from_cdn.js +24 -0
- package/scripts/http_server.js +44 -0
- package/scripts/post_build.sh +32 -0
- package/src/cache-manager.ts +358 -0
- package/src/debug.ts +111 -0
- package/src/glue/glue.ts +291 -0
- package/src/glue/messages.ts +773 -0
- package/src/huggingface.ts +151 -0
- package/src/index.ts +8 -0
- package/src/mjs.test.ts +44 -0
- package/src/model-manager.test.ts +200 -0
- package/src/model-manager.ts +359 -0
- package/src/storage/cos.test.ts +83 -0
- package/src/storage/cos.ts +171 -0
- package/src/storage/index.ts +40 -0
- package/src/storage/opfs.ts +119 -0
- package/src/types/oai-compat.ts +342 -0
- package/src/types/types.ts +133 -0
- package/src/utils.test.ts +231 -0
- package/src/utils.ts +403 -0
- package/src/wasm/source-map.ts +7 -0
- package/src/wasm/wllama.js +1 -0
- package/src/wasm/wllama.wasm +0 -0
- package/src/wasm-from-cdn.ts +13 -0
- package/src/wllama.test.ts +392 -0
- package/src/wllama.ts +1138 -0
- package/src/wllama.wgpu.test.ts +62 -0
- package/src/worker.ts +443 -0
- package/src/workers-code/generated.ts +11 -0
- package/src/workers-code/llama-cpp.js +511 -0
- package/src/workers-code/opfs-utils.js +150 -0
- package/tsconfig.build.json +34 -0
- package/tsup.config.ts +23 -0
- package/vitest.config.ts +61 -0
package/src/glue/glue.ts
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GLUE_MESSAGE_PROTOTYPES,
|
|
3
|
+
GLUE_VERSION,
|
|
4
|
+
type GlueMsg,
|
|
5
|
+
} from './messages';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Glue is a simple binary protocol for serializing and deserializing messages.
|
|
9
|
+
* It is inspired by protobuf, but much simpler.
|
|
10
|
+
*
|
|
11
|
+
* Interested in extending Glue? Open an issue on GitHub!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
type GlueType =
|
|
15
|
+
| 'str'
|
|
16
|
+
| 'int'
|
|
17
|
+
| 'float'
|
|
18
|
+
| 'bool'
|
|
19
|
+
| 'raw'
|
|
20
|
+
| 'arr_str'
|
|
21
|
+
| 'arr_int'
|
|
22
|
+
| 'arr_float'
|
|
23
|
+
| 'arr_bool'
|
|
24
|
+
| 'arr_raw'
|
|
25
|
+
| 'null';
|
|
26
|
+
|
|
27
|
+
const GLUE_MAGIC = new Uint8Array([71, 76, 85, 69]);
|
|
28
|
+
|
|
29
|
+
export interface GlueField {
|
|
30
|
+
type: GlueType;
|
|
31
|
+
name: string;
|
|
32
|
+
isNullable: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface GlueMessageProto {
|
|
36
|
+
name: string;
|
|
37
|
+
structName: string;
|
|
38
|
+
className: string;
|
|
39
|
+
fields: GlueField[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const GLUE_DTYPE_NULL = 0;
|
|
43
|
+
const GLUE_DTYPE_BOOL = 1;
|
|
44
|
+
const GLUE_DTYPE_INT = 2;
|
|
45
|
+
const GLUE_DTYPE_FLOAT = 3;
|
|
46
|
+
const GLUE_DTYPE_STRING = 4;
|
|
47
|
+
const GLUE_DTYPE_RAW = 5;
|
|
48
|
+
const GLUE_DTYPE_ARRAY_BOOL = 6;
|
|
49
|
+
const GLUE_DTYPE_ARRAY_INT = 7;
|
|
50
|
+
const GLUE_DTYPE_ARRAY_FLOAT = 8;
|
|
51
|
+
const GLUE_DTYPE_ARRAY_STRING = 9;
|
|
52
|
+
const GLUE_DTYPE_ARRAY_RAW = 10;
|
|
53
|
+
|
|
54
|
+
const TYPE_MAP: Record<GlueType, number> = {
|
|
55
|
+
str: GLUE_DTYPE_STRING,
|
|
56
|
+
int: GLUE_DTYPE_INT,
|
|
57
|
+
float: GLUE_DTYPE_FLOAT,
|
|
58
|
+
bool: GLUE_DTYPE_BOOL,
|
|
59
|
+
raw: GLUE_DTYPE_RAW,
|
|
60
|
+
arr_str: GLUE_DTYPE_ARRAY_STRING,
|
|
61
|
+
arr_int: GLUE_DTYPE_ARRAY_INT,
|
|
62
|
+
arr_float: GLUE_DTYPE_ARRAY_FLOAT,
|
|
63
|
+
arr_bool: GLUE_DTYPE_ARRAY_BOOL,
|
|
64
|
+
arr_raw: GLUE_DTYPE_ARRAY_RAW,
|
|
65
|
+
null: GLUE_DTYPE_NULL,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export function glueDeserialize(buf: Uint8Array): GlueMsg {
|
|
69
|
+
let offset = 0;
|
|
70
|
+
const view = new DataView(buf.buffer);
|
|
71
|
+
const readUint32 = () => {
|
|
72
|
+
const value = view.getUint32(offset, true);
|
|
73
|
+
offset += 4;
|
|
74
|
+
return value;
|
|
75
|
+
};
|
|
76
|
+
const readInt32 = () => {
|
|
77
|
+
const value = view.getInt32(offset, true);
|
|
78
|
+
offset += 4;
|
|
79
|
+
return value;
|
|
80
|
+
};
|
|
81
|
+
const readFloat = () => {
|
|
82
|
+
const value = view.getFloat32(offset, true);
|
|
83
|
+
offset += 4;
|
|
84
|
+
return value;
|
|
85
|
+
};
|
|
86
|
+
const readBool = () => {
|
|
87
|
+
return readUint32() !== 0;
|
|
88
|
+
};
|
|
89
|
+
const readString = (customLen?: number) => {
|
|
90
|
+
const length = customLen ?? readUint32();
|
|
91
|
+
const value = new TextDecoder().decode(buf.slice(offset, offset + length));
|
|
92
|
+
offset += length;
|
|
93
|
+
return value;
|
|
94
|
+
};
|
|
95
|
+
const readRaw = () => {
|
|
96
|
+
const length = readUint32();
|
|
97
|
+
const value = buf.slice(offset, offset + length);
|
|
98
|
+
offset += length;
|
|
99
|
+
return value;
|
|
100
|
+
};
|
|
101
|
+
const readArray = (readItem: () => any) => {
|
|
102
|
+
const length = readUint32();
|
|
103
|
+
const value = new Array(length);
|
|
104
|
+
for (let i = 0; i < length; i++) {
|
|
105
|
+
value[i] = readItem();
|
|
106
|
+
}
|
|
107
|
+
return value;
|
|
108
|
+
};
|
|
109
|
+
const readNull = () => null;
|
|
110
|
+
|
|
111
|
+
const readField = (field: GlueField) => {
|
|
112
|
+
switch (field.type) {
|
|
113
|
+
case 'str':
|
|
114
|
+
return readString();
|
|
115
|
+
case 'int':
|
|
116
|
+
return readInt32();
|
|
117
|
+
case 'float':
|
|
118
|
+
return readFloat();
|
|
119
|
+
case 'bool':
|
|
120
|
+
return readBool();
|
|
121
|
+
case 'raw':
|
|
122
|
+
return readRaw();
|
|
123
|
+
case 'arr_str':
|
|
124
|
+
return readArray(readString);
|
|
125
|
+
case 'arr_int':
|
|
126
|
+
return readArray(readInt32);
|
|
127
|
+
case 'arr_float':
|
|
128
|
+
return readArray(readFloat);
|
|
129
|
+
case 'arr_bool':
|
|
130
|
+
return readArray(readBool);
|
|
131
|
+
case 'arr_raw':
|
|
132
|
+
return readArray(readRaw);
|
|
133
|
+
case 'null':
|
|
134
|
+
return readNull();
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const magicValid =
|
|
139
|
+
buf[0] === GLUE_MAGIC[0] &&
|
|
140
|
+
buf[1] === GLUE_MAGIC[1] &&
|
|
141
|
+
buf[2] === GLUE_MAGIC[2] &&
|
|
142
|
+
buf[3] === GLUE_MAGIC[3];
|
|
143
|
+
offset += 4;
|
|
144
|
+
if (!magicValid) {
|
|
145
|
+
throw new Error('Invalid magic number');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const version = readUint32();
|
|
149
|
+
if (version !== GLUE_VERSION) {
|
|
150
|
+
throw new Error('Invalid version number');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const name = readString(8);
|
|
154
|
+
const msgProto = GLUE_MESSAGE_PROTOTYPES[name];
|
|
155
|
+
if (!msgProto) {
|
|
156
|
+
throw new Error(`Unknown message name: ${name}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const output: any = { _name: name };
|
|
160
|
+
for (const field of msgProto.fields) {
|
|
161
|
+
const readType = readUint32();
|
|
162
|
+
if (readType === GLUE_DTYPE_NULL) {
|
|
163
|
+
if (!field.isNullable) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`${name}: Expect field ${field.name} to be non-nullable`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
output[field.name] = null;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (readType !== TYPE_MAP[field.type]) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
`${name}: Expect field ${field.name} to have type ${field.type}`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
output[field.name] = readField(field);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return output;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function glueSerialize(msg: GlueMsg): Uint8Array {
|
|
183
|
+
const msgProto = GLUE_MESSAGE_PROTOTYPES[msg._name];
|
|
184
|
+
if (!msgProto) {
|
|
185
|
+
throw new Error(`Unknown message name: ${msg._name}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const bufs: Uint8Array[] = [];
|
|
189
|
+
|
|
190
|
+
const writeUint32 = (value: number) => {
|
|
191
|
+
const buf = new ArrayBuffer(4);
|
|
192
|
+
new DataView(buf).setUint32(0, value, true);
|
|
193
|
+
bufs.push(new Uint8Array(buf));
|
|
194
|
+
};
|
|
195
|
+
const writeInt32 = (value: number) => {
|
|
196
|
+
const buf = new ArrayBuffer(4);
|
|
197
|
+
new DataView(buf).setInt32(0, value, true);
|
|
198
|
+
bufs.push(new Uint8Array(buf));
|
|
199
|
+
};
|
|
200
|
+
const writeFloat = (value: number) => {
|
|
201
|
+
const buf = new ArrayBuffer(4);
|
|
202
|
+
new DataView(buf).setFloat32(0, value, true);
|
|
203
|
+
bufs.push(new Uint8Array(buf));
|
|
204
|
+
};
|
|
205
|
+
const writeBool = (value: boolean) => {
|
|
206
|
+
writeUint32(value ? 1 : 0);
|
|
207
|
+
};
|
|
208
|
+
const writeString = (value: string) => {
|
|
209
|
+
const utf8 = new TextEncoder().encode(value);
|
|
210
|
+
writeUint32(utf8.byteLength);
|
|
211
|
+
bufs.push(utf8);
|
|
212
|
+
};
|
|
213
|
+
const writeRaw = (value: Uint8Array) => {
|
|
214
|
+
writeUint32(value.byteLength);
|
|
215
|
+
bufs.push(value);
|
|
216
|
+
};
|
|
217
|
+
const writeArray = (value: any[], writeItem: (item: any) => void) => {
|
|
218
|
+
writeUint32(value.length);
|
|
219
|
+
for (const item of value) {
|
|
220
|
+
writeItem(item);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
const writeNull = () => {};
|
|
224
|
+
|
|
225
|
+
//////////////////
|
|
226
|
+
|
|
227
|
+
bufs.push(GLUE_MAGIC);
|
|
228
|
+
writeUint32(GLUE_VERSION);
|
|
229
|
+
{
|
|
230
|
+
// write proto ID
|
|
231
|
+
const utf8 = new TextEncoder().encode(msg._name);
|
|
232
|
+
bufs.push(utf8);
|
|
233
|
+
}
|
|
234
|
+
for (const field of msgProto.fields) {
|
|
235
|
+
const val = (msg as any)[field.name];
|
|
236
|
+
if (!field.isNullable && (val === null || val === undefined)) {
|
|
237
|
+
throw new Error(
|
|
238
|
+
`${msg._name}: Expect field ${field.name} to be non-nullable`
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
if (val === null || val === undefined) {
|
|
242
|
+
writeUint32(GLUE_DTYPE_NULL);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
writeUint32(TYPE_MAP[field.type]);
|
|
246
|
+
switch (field.type) {
|
|
247
|
+
case 'str':
|
|
248
|
+
writeString(val);
|
|
249
|
+
break;
|
|
250
|
+
case 'int':
|
|
251
|
+
writeInt32(val);
|
|
252
|
+
break;
|
|
253
|
+
case 'float':
|
|
254
|
+
writeFloat(val);
|
|
255
|
+
break;
|
|
256
|
+
case 'bool':
|
|
257
|
+
writeBool(val);
|
|
258
|
+
break;
|
|
259
|
+
case 'raw':
|
|
260
|
+
writeRaw(val);
|
|
261
|
+
break;
|
|
262
|
+
case 'arr_str':
|
|
263
|
+
writeArray(val, writeString);
|
|
264
|
+
break;
|
|
265
|
+
case 'arr_int':
|
|
266
|
+
writeArray(val, writeInt32);
|
|
267
|
+
break;
|
|
268
|
+
case 'arr_float':
|
|
269
|
+
writeArray(val, writeFloat);
|
|
270
|
+
break;
|
|
271
|
+
case 'arr_bool':
|
|
272
|
+
writeArray(val, writeBool);
|
|
273
|
+
break;
|
|
274
|
+
case 'arr_raw':
|
|
275
|
+
writeArray(val, writeRaw);
|
|
276
|
+
break;
|
|
277
|
+
case 'null':
|
|
278
|
+
writeNull();
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const totalLength = bufs.reduce((acc, buf) => acc + buf.byteLength, 0);
|
|
284
|
+
const output = new Uint8Array(totalLength);
|
|
285
|
+
let offset = 0;
|
|
286
|
+
for (const buf of bufs) {
|
|
287
|
+
output.set(buf, offset);
|
|
288
|
+
offset += buf.byteLength;
|
|
289
|
+
}
|
|
290
|
+
return output;
|
|
291
|
+
}
|