@p0u4a/inference-worker 0.0.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/LICENSE +21 -0
- package/README.md +152 -0
- package/dist/client.d.ts +23 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +167 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/worker.d.ts +7 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +222 -0
- package/package.json +37 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 P0u4a
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Inference Worker
|
|
2
|
+
|
|
3
|
+
A generic, extensible Web Worker for running HuggingFace Transformers inference in the browser. Works with any pretrained model, supports WebGPU acceleration, model load progress reporting, cancellation, and optional tool call parsing.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm install @p0u4a/inference-worker
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quickstart
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { InferenceClient } from "@p0u4a/inference-worker";
|
|
15
|
+
|
|
16
|
+
const client = new InferenceClient({
|
|
17
|
+
worker: new URL("@p0u4a/inference-worker/worker", import.meta.url),
|
|
18
|
+
config: {
|
|
19
|
+
modelId: "Qwen/Qwen2.5-0.5B-Instruct",
|
|
20
|
+
dtype: "q4",
|
|
21
|
+
device: "webgpu",
|
|
22
|
+
},
|
|
23
|
+
onProgress: (p) => {
|
|
24
|
+
if (p.status === "progress") {
|
|
25
|
+
console.log(`Loading ${p.file}: ${Math.round(p.progress)}%`);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
await client.init();
|
|
31
|
+
|
|
32
|
+
const result = await client.execute({
|
|
33
|
+
prompt: "Explain quantum computing in one sentence.",
|
|
34
|
+
generationParams: { maxNewTokens: 64 },
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
console.log(result.rawOutput);
|
|
38
|
+
|
|
39
|
+
client.dispose();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## With tool call parsing
|
|
43
|
+
|
|
44
|
+
The `toolCallParser` runs on the main thread after the worker returns raw output. Define any parsing logic you need:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
interface ToolCall {
|
|
48
|
+
name: string;
|
|
49
|
+
arguments: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const client = new InferenceClient<ToolCall[]>({
|
|
53
|
+
worker: new URL("@p0u4a/inference-worker/worker", import.meta.url),
|
|
54
|
+
config: {
|
|
55
|
+
modelId: "Qwen/Qwen2.5-0.5B-Instruct",
|
|
56
|
+
dtype: "q4",
|
|
57
|
+
device: "webgpu",
|
|
58
|
+
},
|
|
59
|
+
toolCallParser: (raw) => {
|
|
60
|
+
// Implement your own parsing logic based on the model's output format
|
|
61
|
+
const match = raw.match(/\{.*\}/s);
|
|
62
|
+
return match ? [JSON.parse(match[0])] : [];
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await client.init();
|
|
67
|
+
|
|
68
|
+
const result = await client.execute({
|
|
69
|
+
prompt: "What is the weather in London?",
|
|
70
|
+
systemPrompt: "You can call functions to get information.",
|
|
71
|
+
tools: [{ type: "function", function: { name: "get_weather", parameters: { location: { type: "string" } } } }],
|
|
72
|
+
generationParams: { maxNewTokens: 128 },
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// result.toolCalls is typed as ToolCall[]
|
|
76
|
+
console.log(result.toolCalls);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
## Cancellation
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const resultPromise = client.execute({ prompt: "Write a long essay..." });
|
|
84
|
+
|
|
85
|
+
// Cancel mid-inference
|
|
86
|
+
client.cancel();
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
await resultPromise;
|
|
90
|
+
} catch (e) {
|
|
91
|
+
if (e instanceof DOMException && e.name === "AbortError") {
|
|
92
|
+
console.log("Cancelled");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Resource cleanup
|
|
98
|
+
|
|
99
|
+
`InferenceClient` implements `Disposable`, so you can use `using` for automatic cleanup:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
using client = new InferenceClient({ ... });
|
|
103
|
+
await client.init();
|
|
104
|
+
const result = await client.execute({ prompt: "Hello" });
|
|
105
|
+
// Worker is terminated when `client` goes out of scope
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Or call `dispose()` manually when done.
|
|
109
|
+
|
|
110
|
+
## API
|
|
111
|
+
|
|
112
|
+
### `InferenceClient<TToolCalls>`
|
|
113
|
+
|
|
114
|
+
| Method | Description |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| `constructor(options)` | Create a client. Accepts a `Worker`, `URL`, or string path for the worker. |
|
|
117
|
+
| `init()` | Load the model. Resolves when ready, rejects on error. |
|
|
118
|
+
| `execute(options)` | Run inference. Returns `{ rawOutput, toolCalls }`. |
|
|
119
|
+
| `cancel()` | Abort the current inference. |
|
|
120
|
+
| `dispose()` | Terminate the worker and release resources. |
|
|
121
|
+
| `status` | Current worker status: `"idle"` | `"loading"` | `"ready"` | `"error"`. |
|
|
122
|
+
|
|
123
|
+
### `WorkerInitConfig`
|
|
124
|
+
|
|
125
|
+
| Field | Type | Default | Description |
|
|
126
|
+
| --- | --- | --- | --- |
|
|
127
|
+
| `modelId` | `string` | required | HuggingFace model ID or path |
|
|
128
|
+
| `modelClass` | `string` | `"AutoModelForCausalLM"` | Auto model class name |
|
|
129
|
+
| `tokenizerClass` | `string` | `"AutoTokenizer"` | Tokenizer class name |
|
|
130
|
+
| `dtype` | `string` | - | Quantization type (`"q4"`, `"fp16"`, `"q8"`) |
|
|
131
|
+
| `device` | `string` | - | Compute device (`"webgpu"`, `"wasm"`, `"cpu"`) |
|
|
132
|
+
| `maxRetryAttempts` | `number` | `3` | Retry count for network errors |
|
|
133
|
+
| `baseRetryDelayMs` | `number` | `1000` | Base delay for exponential backoff |
|
|
134
|
+
|
|
135
|
+
### `ExecuteOptions`
|
|
136
|
+
|
|
137
|
+
| Field | Type | Description |
|
|
138
|
+
| --- | --- | --- |
|
|
139
|
+
| `prompt` | `string` | The user prompt (appended as the final message) |
|
|
140
|
+
| `messages` | `ChatMessage[]` | Conversation history |
|
|
141
|
+
| `systemPrompt` | `string` | System instruction |
|
|
142
|
+
| `tools` | `unknown[]` | Tool schemas for the chat template |
|
|
143
|
+
| `generationParams` | `GenerationParams` | Generation config (`maxNewTokens`, `temperature`, etc.) |
|
|
144
|
+
|
|
145
|
+
### Callbacks
|
|
146
|
+
|
|
147
|
+
Pass these in `InferenceClientOptions`:
|
|
148
|
+
|
|
149
|
+
- `onStatus(status, error?)` - Status changes during init/execution
|
|
150
|
+
- `onProgress(progress)` - Model download progress (file name, bytes loaded/total)
|
|
151
|
+
- `onError(error)` - Error messages from the worker
|
|
152
|
+
- `onRetry(attempt, maxAttempts)` - Retry attempts on network failure
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ExecuteOptions, InferenceClientOptions, InferenceResult, WorkerStatus } from "./types.ts";
|
|
2
|
+
export declare class InferenceClient<TToolCalls = undefined> implements Disposable {
|
|
3
|
+
private readonly worker;
|
|
4
|
+
private readonly ownsWorker;
|
|
5
|
+
private readonly toolCallParser?;
|
|
6
|
+
private readonly onStatusCb?;
|
|
7
|
+
private readonly onProgressCb?;
|
|
8
|
+
private readonly onErrorCb?;
|
|
9
|
+
private readonly onRetryCb?;
|
|
10
|
+
private readonly workerConfig;
|
|
11
|
+
private currentStatus;
|
|
12
|
+
private disposed;
|
|
13
|
+
constructor(options: InferenceClientOptions<TToolCalls>);
|
|
14
|
+
get status(): WorkerStatus;
|
|
15
|
+
init(): Promise<void>;
|
|
16
|
+
execute(options: ExecuteOptions): Promise<InferenceResult<TToolCalls>>;
|
|
17
|
+
cancel(): void;
|
|
18
|
+
dispose(): void;
|
|
19
|
+
[Symbol.dispose](): void;
|
|
20
|
+
private postWorkerMessage;
|
|
21
|
+
private assertNotDisposed;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,eAAe,EAGf,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,qBAAa,eAAe,CAAC,UAAU,GAAG,SAAS,CAAE,YAAW,UAAU;IACxE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAoC;IACpE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAiD;IAC7E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAmD;IACjF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAgD;IAC3E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAgD;IAC3E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+C;IAE5E,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,EAAE,sBAAsB,CAAC,UAAU,CAAC;IAqBvD,IAAI,MAAM,IAAI,YAAY,CAEzB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwCrB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IA+D5E,MAAM,IAAI,IAAI;IAKd,OAAO,IAAI,IAAI;IAQf,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;IAIxB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,iBAAiB;CAK1B"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type { MessageRole, ChatMessage, WorkerInitConfig, GenerationParams, WorkerMessageIn, WorkerMessageOut, WorkerStatus, InferenceResult, StatusCallback, ProgressCallback, ErrorCallback, RetryCallback, InferenceClientOptions, ExecuteOptions, ProgressInfo, } from "./types.ts";
|
|
2
|
+
export { InferenceClient } from "./client.ts";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,sBAAsB,EACtB,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
7
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
8
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
9
|
+
for (let key of __getOwnPropNames(mod))
|
|
10
|
+
if (!__hasOwnProp.call(to, key))
|
|
11
|
+
__defProp(to, key, {
|
|
12
|
+
get: () => mod[key],
|
|
13
|
+
enumerable: true
|
|
14
|
+
});
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
18
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
19
|
+
}) : x)(function(x) {
|
|
20
|
+
if (typeof require !== "undefined")
|
|
21
|
+
return require.apply(this, arguments);
|
|
22
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// src/client.ts
|
|
26
|
+
class InferenceClient {
|
|
27
|
+
worker;
|
|
28
|
+
ownsWorker;
|
|
29
|
+
toolCallParser;
|
|
30
|
+
onStatusCb;
|
|
31
|
+
onProgressCb;
|
|
32
|
+
onErrorCb;
|
|
33
|
+
onRetryCb;
|
|
34
|
+
workerConfig;
|
|
35
|
+
currentStatus = "idle";
|
|
36
|
+
disposed = false;
|
|
37
|
+
constructor(options) {
|
|
38
|
+
this.workerConfig = options.config;
|
|
39
|
+
this.toolCallParser = options.toolCallParser;
|
|
40
|
+
this.onStatusCb = options.onStatus;
|
|
41
|
+
this.onProgressCb = options.onProgress;
|
|
42
|
+
this.onErrorCb = options.onError;
|
|
43
|
+
this.onRetryCb = options.onRetry;
|
|
44
|
+
if (options.worker instanceof Worker) {
|
|
45
|
+
this.worker = options.worker;
|
|
46
|
+
this.ownsWorker = false;
|
|
47
|
+
} else {
|
|
48
|
+
const url = typeof options.worker === "string" ? new URL(options.worker) : options.worker;
|
|
49
|
+
this.worker = new Worker(url, { type: "module" });
|
|
50
|
+
this.ownsWorker = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
get status() {
|
|
54
|
+
return this.currentStatus;
|
|
55
|
+
}
|
|
56
|
+
async init() {
|
|
57
|
+
this.assertNotDisposed();
|
|
58
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
59
|
+
const handler = (event) => {
|
|
60
|
+
const msg = event.data;
|
|
61
|
+
switch (msg.type) {
|
|
62
|
+
case "status":
|
|
63
|
+
this.currentStatus = msg.status;
|
|
64
|
+
this.onStatusCb?.(msg.status, msg.error);
|
|
65
|
+
if (msg.status === "ready") {
|
|
66
|
+
this.worker.removeEventListener("message", handler);
|
|
67
|
+
resolve();
|
|
68
|
+
} else if (msg.status === "error") {
|
|
69
|
+
this.worker.removeEventListener("message", handler);
|
|
70
|
+
reject(new Error(msg.error ?? "Model loading failed"));
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
case "progress":
|
|
74
|
+
this.onProgressCb?.(msg.progress);
|
|
75
|
+
break;
|
|
76
|
+
case "retry":
|
|
77
|
+
this.onRetryCb?.(msg.attempt, msg.maxAttempts);
|
|
78
|
+
break;
|
|
79
|
+
case "error":
|
|
80
|
+
this.onErrorCb?.(msg.error);
|
|
81
|
+
this.worker.removeEventListener("message", handler);
|
|
82
|
+
reject(new Error(msg.error));
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
this.worker.addEventListener("message", handler);
|
|
87
|
+
this.postWorkerMessage({ type: "init", config: this.workerConfig });
|
|
88
|
+
return promise;
|
|
89
|
+
}
|
|
90
|
+
async execute(options) {
|
|
91
|
+
this.assertNotDisposed();
|
|
92
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
93
|
+
const handler = (event) => {
|
|
94
|
+
const msg = event.data;
|
|
95
|
+
switch (msg.type) {
|
|
96
|
+
case "result": {
|
|
97
|
+
this.worker.removeEventListener("message", handler);
|
|
98
|
+
try {
|
|
99
|
+
const toolCalls = this.toolCallParser ? this.toolCallParser(msg.rawOutput) : undefined;
|
|
100
|
+
resolve({
|
|
101
|
+
rawOutput: msg.rawOutput,
|
|
102
|
+
toolCalls
|
|
103
|
+
});
|
|
104
|
+
} catch (e) {
|
|
105
|
+
reject(e);
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case "error":
|
|
110
|
+
this.onErrorCb?.(msg.error);
|
|
111
|
+
this.worker.removeEventListener("message", handler);
|
|
112
|
+
reject(new Error(msg.error));
|
|
113
|
+
break;
|
|
114
|
+
case "cancelled":
|
|
115
|
+
this.worker.removeEventListener("message", handler);
|
|
116
|
+
reject(new DOMException("Inference cancelled", "AbortError"));
|
|
117
|
+
break;
|
|
118
|
+
case "status":
|
|
119
|
+
this.currentStatus = msg.status;
|
|
120
|
+
this.onStatusCb?.(msg.status, msg.error);
|
|
121
|
+
break;
|
|
122
|
+
case "progress":
|
|
123
|
+
this.onProgressCb?.(msg.progress);
|
|
124
|
+
break;
|
|
125
|
+
case "retry":
|
|
126
|
+
this.onRetryCb?.(msg.attempt, msg.maxAttempts);
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
this.worker.addEventListener("message", handler);
|
|
131
|
+
this.postWorkerMessage({
|
|
132
|
+
type: "execute",
|
|
133
|
+
prompt: options.prompt,
|
|
134
|
+
messages: options.messages,
|
|
135
|
+
systemPrompt: options.systemPrompt,
|
|
136
|
+
tools: options.tools,
|
|
137
|
+
generationParams: options.generationParams
|
|
138
|
+
});
|
|
139
|
+
return promise;
|
|
140
|
+
}
|
|
141
|
+
cancel() {
|
|
142
|
+
this.assertNotDisposed();
|
|
143
|
+
this.postWorkerMessage({ type: "cancel" });
|
|
144
|
+
}
|
|
145
|
+
dispose() {
|
|
146
|
+
if (this.disposed)
|
|
147
|
+
return;
|
|
148
|
+
this.disposed = true;
|
|
149
|
+
if (this.ownsWorker) {
|
|
150
|
+
this.worker.terminate();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
[Symbol.dispose]() {
|
|
154
|
+
this.dispose();
|
|
155
|
+
}
|
|
156
|
+
postWorkerMessage(msg) {
|
|
157
|
+
this.worker.postMessage(msg);
|
|
158
|
+
}
|
|
159
|
+
assertNotDisposed() {
|
|
160
|
+
if (this.disposed) {
|
|
161
|
+
throw new Error("InferenceClient has been disposed");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
export {
|
|
166
|
+
InferenceClient
|
|
167
|
+
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { ProgressInfo } from "@huggingface/transformers";
|
|
2
|
+
export type MessageRole = "system" | "assistant" | "user";
|
|
3
|
+
export interface ChatMessage {
|
|
4
|
+
role: MessageRole;
|
|
5
|
+
content: string;
|
|
6
|
+
}
|
|
7
|
+
export interface WorkerInitConfig {
|
|
8
|
+
/** HuggingFace model ID or local path */
|
|
9
|
+
modelId: string;
|
|
10
|
+
/**
|
|
11
|
+
* Auto* model class name from `@huggingface/transformers`.
|
|
12
|
+
* @default "AutoModelForCausalLM"
|
|
13
|
+
*/
|
|
14
|
+
modelClass?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Tokenizer class name from `@huggingface/transformers`.
|
|
17
|
+
* @default "AutoTokenizer"
|
|
18
|
+
*/
|
|
19
|
+
tokenizerClass?: string;
|
|
20
|
+
/** Model quantization dtype (e.g. "q4", "fp16", "q8"). */
|
|
21
|
+
dtype?: string;
|
|
22
|
+
/** Device to run on (e.g. "webgpu", "wasm", "cpu"). */
|
|
23
|
+
device?: string;
|
|
24
|
+
/** Max retry attempts for network errors during model load. @default 3 */
|
|
25
|
+
maxRetryAttempts?: number;
|
|
26
|
+
/** Base delay in ms for exponential backoff. @default 1000 */
|
|
27
|
+
baseRetryDelayMs?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface GenerationParams {
|
|
30
|
+
maxNewTokens?: number;
|
|
31
|
+
doSample?: boolean;
|
|
32
|
+
temperature?: number;
|
|
33
|
+
topK?: number;
|
|
34
|
+
topP?: number;
|
|
35
|
+
repetitionPenalty?: number;
|
|
36
|
+
[key: string]: unknown;
|
|
37
|
+
}
|
|
38
|
+
export type WorkerMessageIn = {
|
|
39
|
+
type: "init";
|
|
40
|
+
config: WorkerInitConfig;
|
|
41
|
+
} | {
|
|
42
|
+
type: "execute";
|
|
43
|
+
prompt: string;
|
|
44
|
+
messages?: ChatMessage[];
|
|
45
|
+
systemPrompt?: string;
|
|
46
|
+
tools?: unknown[];
|
|
47
|
+
generationParams?: GenerationParams;
|
|
48
|
+
} | {
|
|
49
|
+
type: "cancel";
|
|
50
|
+
};
|
|
51
|
+
export type WorkerStatus = "idle" | "loading" | "ready" | "error";
|
|
52
|
+
export type WorkerMessageOut = {
|
|
53
|
+
type: "status";
|
|
54
|
+
status: WorkerStatus;
|
|
55
|
+
error?: string;
|
|
56
|
+
} | {
|
|
57
|
+
type: "progress";
|
|
58
|
+
progress: ProgressInfo;
|
|
59
|
+
} | {
|
|
60
|
+
type: "result";
|
|
61
|
+
rawOutput: string;
|
|
62
|
+
} | {
|
|
63
|
+
type: "error";
|
|
64
|
+
error: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: "cancelled";
|
|
67
|
+
} | {
|
|
68
|
+
type: "retry";
|
|
69
|
+
attempt: number;
|
|
70
|
+
maxAttempts: number;
|
|
71
|
+
};
|
|
72
|
+
export interface InferenceResult<TToolCalls = undefined> {
|
|
73
|
+
rawOutput: string;
|
|
74
|
+
toolCalls: TToolCalls;
|
|
75
|
+
}
|
|
76
|
+
export type StatusCallback = (status: WorkerStatus, error?: string) => void;
|
|
77
|
+
export type ProgressCallback = (progress: ProgressInfo) => void;
|
|
78
|
+
export type ErrorCallback = (error: string) => void;
|
|
79
|
+
export type RetryCallback = (attempt: number, maxAttempts: number) => void;
|
|
80
|
+
export interface InferenceClientOptions<TToolCalls = undefined> {
|
|
81
|
+
/** A Worker instance, URL to worker script, or string path */
|
|
82
|
+
worker: Worker | URL | string;
|
|
83
|
+
/** Model & worker initialization config */
|
|
84
|
+
config: WorkerInitConfig;
|
|
85
|
+
/** Optional parser applied on main thread to extract tool calls from raw output */
|
|
86
|
+
toolCallParser?: (rawOutput: string) => TToolCalls;
|
|
87
|
+
onStatus?: StatusCallback;
|
|
88
|
+
onProgress?: ProgressCallback;
|
|
89
|
+
onError?: ErrorCallback;
|
|
90
|
+
onRetry?: RetryCallback;
|
|
91
|
+
}
|
|
92
|
+
export interface ExecuteOptions {
|
|
93
|
+
prompt: string;
|
|
94
|
+
messages?: ChatMessage[];
|
|
95
|
+
systemPrompt?: string;
|
|
96
|
+
tools?: unknown[];
|
|
97
|
+
generationParams?: GenerationParams;
|
|
98
|
+
}
|
|
99
|
+
export { type ProgressInfo } from "@huggingface/transformers";
|
|
100
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC1C;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,GACD;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEvB,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAElE,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,eAAe,CAAC,UAAU,GAAG,SAAS;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAC5E,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;AAChE,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AACpD,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AAE3E,MAAM,WAAW,sBAAsB,CAAC,UAAU,GAAG,SAAS;IAC5D,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC;IAE9B,2CAA2C;IAC3C,MAAM,EAAE,gBAAgB,CAAC;IAEzB,mFAAmF;IACnF,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,UAAU,CAAC;IAEnD,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAiBlD;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C"}
|
package/dist/worker.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ChatMessage, GenerationParams } from "./types.ts";
|
|
2
|
+
export declare function convertGenerationParams(params: GenerationParams | undefined): Record<string, unknown>;
|
|
3
|
+
export declare function buildConversation(prompt: string, messages?: ChatMessage[], systemPrompt?: string): Array<{
|
|
4
|
+
role: string;
|
|
5
|
+
content: string;
|
|
6
|
+
}>;
|
|
7
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAIjB,MAAM,YAAY,CAAC;AASpB,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,gBAAgB,GAAG,SAAS,GACnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,WAAW,EAAE,EACxB,YAAY,CAAC,EAAE,MAAM,GACpB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgB1C"}
|
package/dist/worker.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
7
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
8
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
9
|
+
for (let key of __getOwnPropNames(mod))
|
|
10
|
+
if (!__hasOwnProp.call(to, key))
|
|
11
|
+
__defProp(to, key, {
|
|
12
|
+
get: () => mod[key],
|
|
13
|
+
enumerable: true
|
|
14
|
+
});
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
18
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
19
|
+
}) : x)(function(x) {
|
|
20
|
+
if (typeof require !== "undefined")
|
|
21
|
+
return require.apply(this, arguments);
|
|
22
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// src/utils.ts
|
|
26
|
+
function isNetworkError(e) {
|
|
27
|
+
if (e instanceof DOMException && e.name === "AbortError")
|
|
28
|
+
return false;
|
|
29
|
+
if (e instanceof TypeError) {
|
|
30
|
+
const msg = e.message.toLowerCase();
|
|
31
|
+
return msg.includes("failed to fetch") || msg.includes("network");
|
|
32
|
+
}
|
|
33
|
+
if (e instanceof Error) {
|
|
34
|
+
const msg = e.message.toLowerCase();
|
|
35
|
+
return msg.includes("network") || msg.includes("fetch") || msg.includes("econnrefused") || msg.includes("enotfound") || msg.includes("timeout");
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
function sleep(ms) {
|
|
40
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
41
|
+
}
|
|
42
|
+
function toSnakeCase(str) {
|
|
43
|
+
return str.replaceAll(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/worker.ts
|
|
47
|
+
var tokenizer = null;
|
|
48
|
+
var model = null;
|
|
49
|
+
var isLoading = false;
|
|
50
|
+
var currentAbortController = null;
|
|
51
|
+
var config = null;
|
|
52
|
+
function convertGenerationParams(params) {
|
|
53
|
+
if (!params)
|
|
54
|
+
return {};
|
|
55
|
+
const result = {};
|
|
56
|
+
for (const [key, value] of Object.entries(params)) {
|
|
57
|
+
if (value !== undefined) {
|
|
58
|
+
result[toSnakeCase(key)] = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
function buildConversation(prompt, messages, systemPrompt) {
|
|
64
|
+
const conversation = [];
|
|
65
|
+
if (systemPrompt) {
|
|
66
|
+
conversation.push({ role: "system", content: systemPrompt });
|
|
67
|
+
}
|
|
68
|
+
if (messages) {
|
|
69
|
+
for (const msg of messages) {
|
|
70
|
+
conversation.push({ role: msg.role, content: msg.content });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
conversation.push({ role: "user", content: prompt });
|
|
74
|
+
return conversation;
|
|
75
|
+
}
|
|
76
|
+
function postMsg(msg) {
|
|
77
|
+
self.postMessage(msg);
|
|
78
|
+
}
|
|
79
|
+
async function resolveClass(className) {
|
|
80
|
+
const transformers = await import("@huggingface/transformers");
|
|
81
|
+
const cls = transformers[className];
|
|
82
|
+
if (!cls) {
|
|
83
|
+
throw new Error(`Class "${className}" not found in @huggingface/transformers`);
|
|
84
|
+
}
|
|
85
|
+
return cls;
|
|
86
|
+
}
|
|
87
|
+
async function loadModel() {
|
|
88
|
+
if (model && tokenizer)
|
|
89
|
+
return;
|
|
90
|
+
if (isLoading)
|
|
91
|
+
return;
|
|
92
|
+
if (!config) {
|
|
93
|
+
postMsg({
|
|
94
|
+
type: "error",
|
|
95
|
+
error: "Worker not initialized: call init first"
|
|
96
|
+
});
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
isLoading = true;
|
|
100
|
+
postMsg({ type: "status", status: "loading" });
|
|
101
|
+
const maxAttempts = config.maxRetryAttempts ?? 3;
|
|
102
|
+
const baseDelay = config.baseRetryDelayMs ?? 1000;
|
|
103
|
+
let lastError;
|
|
104
|
+
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
105
|
+
try {
|
|
106
|
+
const progressCallback = (progress) => {
|
|
107
|
+
postMsg({ type: "progress", progress });
|
|
108
|
+
};
|
|
109
|
+
const modelClassName = config.modelClass ?? "AutoModelForCausalLM";
|
|
110
|
+
const tokenizerClassName = config.tokenizerClass ?? "AutoTokenizer";
|
|
111
|
+
const [TokenizerClass, ModelClass] = await Promise.all([
|
|
112
|
+
resolveClass(tokenizerClassName),
|
|
113
|
+
resolveClass(modelClassName)
|
|
114
|
+
]);
|
|
115
|
+
const modelOptions = {
|
|
116
|
+
progress_callback: progressCallback
|
|
117
|
+
};
|
|
118
|
+
if (config.dtype !== undefined)
|
|
119
|
+
modelOptions.dtype = config.dtype;
|
|
120
|
+
if (config.device !== undefined)
|
|
121
|
+
modelOptions.device = config.device;
|
|
122
|
+
const [loadedTokenizer, loadedModel] = await Promise.all([
|
|
123
|
+
TokenizerClass.from_pretrained(config.modelId, {
|
|
124
|
+
progress_callback: progressCallback
|
|
125
|
+
}),
|
|
126
|
+
ModelClass.from_pretrained(config.modelId, modelOptions)
|
|
127
|
+
]);
|
|
128
|
+
tokenizer = loadedTokenizer;
|
|
129
|
+
model = loadedModel;
|
|
130
|
+
isLoading = false;
|
|
131
|
+
postMsg({ type: "status", status: "ready" });
|
|
132
|
+
return;
|
|
133
|
+
} catch (e) {
|
|
134
|
+
lastError = e;
|
|
135
|
+
if (isNetworkError(e) && attempt < maxAttempts) {
|
|
136
|
+
const delay = baseDelay * Math.pow(2, attempt - 1);
|
|
137
|
+
postMsg({ type: "retry", attempt, maxAttempts });
|
|
138
|
+
await sleep(delay);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
isLoading = false;
|
|
145
|
+
const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);
|
|
146
|
+
postMsg({ type: "status", status: "error", error: errorMessage });
|
|
147
|
+
throw lastError;
|
|
148
|
+
}
|
|
149
|
+
async function execute(prompt, messages, systemPrompt, tools, generationParams) {
|
|
150
|
+
if (!tokenizer || !model) {
|
|
151
|
+
await loadModel();
|
|
152
|
+
}
|
|
153
|
+
if (!tokenizer || !model) {
|
|
154
|
+
postMsg({ type: "error", error: "Model failed to initialize" });
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
currentAbortController = new AbortController;
|
|
158
|
+
try {
|
|
159
|
+
const conversation = buildConversation(prompt, messages, systemPrompt);
|
|
160
|
+
const templateOptions = {
|
|
161
|
+
tokenize: true,
|
|
162
|
+
add_generation_prompt: true,
|
|
163
|
+
return_dict: true
|
|
164
|
+
};
|
|
165
|
+
if (tools !== undefined && tools.length > 0) {
|
|
166
|
+
templateOptions.tools = tools;
|
|
167
|
+
}
|
|
168
|
+
const inputs = tokenizer.apply_chat_template(conversation, templateOptions);
|
|
169
|
+
if (currentAbortController.signal.aborted) {
|
|
170
|
+
postMsg({ type: "cancelled" });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const genParams = convertGenerationParams(generationParams);
|
|
174
|
+
const output = await model.generate({
|
|
175
|
+
...inputs,
|
|
176
|
+
...genParams
|
|
177
|
+
});
|
|
178
|
+
if (currentAbortController.signal.aborted) {
|
|
179
|
+
postMsg({ type: "cancelled" });
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const inputLength = inputs.input_ids.dims[1];
|
|
183
|
+
const outputTokens = output.slice(0, [inputLength, null]);
|
|
184
|
+
const rawOutput = tokenizer.decode(outputTokens, {
|
|
185
|
+
skip_special_tokens: false
|
|
186
|
+
});
|
|
187
|
+
postMsg({ type: "result", rawOutput });
|
|
188
|
+
} catch (e) {
|
|
189
|
+
if (currentAbortController?.signal.aborted) {
|
|
190
|
+
postMsg({ type: "cancelled" });
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
194
|
+
postMsg({ type: "error", error: errorMessage });
|
|
195
|
+
} finally {
|
|
196
|
+
currentAbortController = null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function cancelExecution() {
|
|
200
|
+
if (currentAbortController) {
|
|
201
|
+
currentAbortController.abort();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
globalThis.onmessage = async (event) => {
|
|
205
|
+
const message = event.data;
|
|
206
|
+
switch (message.type) {
|
|
207
|
+
case "init":
|
|
208
|
+
config = message.config;
|
|
209
|
+
await loadModel();
|
|
210
|
+
break;
|
|
211
|
+
case "execute":
|
|
212
|
+
await execute(message.prompt, message.messages, message.systemPrompt, message.tools, message.generationParams);
|
|
213
|
+
break;
|
|
214
|
+
case "cancel":
|
|
215
|
+
cancelExecution();
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
export {
|
|
220
|
+
convertGenerationParams,
|
|
221
|
+
buildConversation
|
|
222
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@p0u4a/inference-worker",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"repository": {
|
|
5
|
+
"url": "https://github.com/P0u4a/inference-worker"
|
|
6
|
+
},
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./worker": {
|
|
16
|
+
"types": "./dist/worker.d.ts",
|
|
17
|
+
"import": "./dist/worker.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "bun run build:js && bun run build:types",
|
|
25
|
+
"build:js": "bun build src/index.ts src/worker.ts --outdir dist --target browser --external @huggingface/transformers",
|
|
26
|
+
"build:types": "tsc -p tsconfig.build.json"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/bun": "latest",
|
|
30
|
+
"@vitest/web-worker": "^4.0.18",
|
|
31
|
+
"vitest": "^4.0.18"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@huggingface/transformers": "^3.8.1",
|
|
35
|
+
"typescript": "^5"
|
|
36
|
+
}
|
|
37
|
+
}
|