@missionsquad/browserai 0.1.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/LICENSE +15 -0
- package/README.md +229 -0
- package/dist/audio/clip.d.ts +51 -0
- package/dist/audio/clip.d.ts.map +1 -0
- package/dist/audio/clip.js +71 -0
- package/dist/audio/clip.js.map +1 -0
- package/dist/audio/decode.d.ts +7 -0
- package/dist/audio/decode.d.ts.map +1 -0
- package/dist/audio/decode.js +19 -0
- package/dist/audio/decode.js.map +1 -0
- package/dist/audio/pcm.d.ts +13 -0
- package/dist/audio/pcm.d.ts.map +1 -0
- package/dist/audio/pcm.js +66 -0
- package/dist/audio/pcm.js.map +1 -0
- package/dist/audio/recorder.d.ts +40 -0
- package/dist/audio/recorder.d.ts.map +1 -0
- package/dist/audio/recorder.js +127 -0
- package/dist/audio/recorder.js.map +1 -0
- package/dist/audio/streaming-player.d.ts +29 -0
- package/dist/audio/streaming-player.d.ts.map +1 -0
- package/dist/audio/streaming-player.js +82 -0
- package/dist/audio/streaming-player.js.map +1 -0
- package/dist/client.d.ts +195 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +638 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +81 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +52 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +74 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +18 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +43 -0
- package/dist/events.js.map +1 -0
- package/dist/generation.d.ts +12 -0
- package/dist/generation.d.ts.map +1 -0
- package/dist/generation.js +30 -0
- package/dist/generation.js.map +1 -0
- package/dist/hardware.d.ts +23 -0
- package/dist/hardware.d.ts.map +1 -0
- package/dist/hardware.js +150 -0
- package/dist/hardware.js.map +1 -0
- package/dist/history.d.ts +81 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +193 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/inference.d.ts +89 -0
- package/dist/inference.d.ts.map +1 -0
- package/dist/inference.js +411 -0
- package/dist/inference.js.map +1 -0
- package/dist/json.d.ts +22 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +145 -0
- package/dist/json.js.map +1 -0
- package/dist/metrics.d.ts +18 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +59 -0
- package/dist/metrics.js.map +1 -0
- package/dist/model-cache.d.ts +49 -0
- package/dist/model-cache.d.ts.map +1 -0
- package/dist/model-cache.js +511 -0
- package/dist/model-cache.js.map +1 -0
- package/dist/model-source.d.ts +27 -0
- package/dist/model-source.d.ts.map +1 -0
- package/dist/model-source.js +110 -0
- package/dist/model-source.js.map +1 -0
- package/dist/models.d.ts +103 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +1052 -0
- package/dist/models.js.map +1 -0
- package/dist/multimodal.d.ts +261 -0
- package/dist/multimodal.d.ts.map +1 -0
- package/dist/multimodal.js +506 -0
- package/dist/multimodal.js.map +1 -0
- package/dist/prompt.d.ts +13 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +32 -0
- package/dist/prompt.js.map +1 -0
- package/dist/proxy-verify.d.ts +10 -0
- package/dist/proxy-verify.d.ts.map +1 -0
- package/dist/proxy-verify.js +98 -0
- package/dist/proxy-verify.js.map +1 -0
- package/dist/schema-validator.d.ts +6 -0
- package/dist/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator.js +104 -0
- package/dist/schema-validator.js.map +1 -0
- package/dist/schema.d.ts +98 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +115 -0
- package/dist/schema.js.map +1 -0
- package/dist/text-utils.d.ts +8 -0
- package/dist/text-utils.d.ts.map +1 -0
- package/dist/text-utils.js +14 -0
- package/dist/text-utils.js.map +1 -0
- package/dist/voice/helpers.d.ts +35 -0
- package/dist/voice/helpers.d.ts.map +1 -0
- package/dist/voice/helpers.js +49 -0
- package/dist/voice/helpers.js.map +1 -0
- package/dist/voice/voice-pipeline.d.ts +155 -0
- package/dist/voice/voice-pipeline.d.ts.map +1 -0
- package/dist/voice/voice-pipeline.js +407 -0
- package/dist/voice/voice-pipeline.js.map +1 -0
- package/dist/webllm.worker.d.ts +2 -0
- package/dist/webllm.worker.d.ts.map +1 -0
- package/dist/webllm.worker.js +8 -0
- package/dist/webllm.worker.js.map +1 -0
- package/package.json +62 -0
- package/src/audio/clip.ts +94 -0
- package/src/audio/decode.ts +19 -0
- package/src/audio/pcm.ts +62 -0
- package/src/audio/recorder.ts +146 -0
- package/src/audio/streaming-player.ts +99 -0
- package/src/client.ts +784 -0
- package/src/config.ts +104 -0
- package/src/errors.ts +81 -0
- package/src/events.ts +53 -0
- package/src/generation.ts +39 -0
- package/src/hardware.ts +193 -0
- package/src/history.ts +257 -0
- package/src/index.ts +203 -0
- package/src/inference.ts +579 -0
- package/src/json.ts +169 -0
- package/src/metrics.ts +63 -0
- package/src/model-cache.ts +637 -0
- package/src/model-source.ts +142 -0
- package/src/models.ts +1171 -0
- package/src/multimodal.ts +697 -0
- package/src/prompt.ts +33 -0
- package/src/proxy-verify.ts +113 -0
- package/src/schema-validator.ts +117 -0
- package/src/schema.ts +118 -0
- package/src/text-utils.ts +12 -0
- package/src/voice/helpers.ts +59 -0
- package/src/voice/voice-pipeline.ts +513 -0
- package/src/webllm.worker.ts +9 -0
- package/worker-template/README.md +39 -0
- package/worker-template/cloudflare-worker.ts +389 -0
- package/worker-template/wrangler.jsonc +19 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { buildResponseFormat } from "./generation.js";
|
|
2
|
+
import { formatError } from "./errors.js";
|
|
3
|
+
/** Sentinel substituted for blank model output; exported so callers can detect/skip it (e.g. TTS). */
|
|
4
|
+
export const EMPTY_RESPONSE = "[empty response]";
|
|
5
|
+
/**
|
|
6
|
+
* Run one generation against whichever backend is loaded and return the text plus normalized stats.
|
|
7
|
+
* Dispatches to WebLLM (streaming or blocking) or Transformers.js. Throws if no engine is loaded.
|
|
8
|
+
*/
|
|
9
|
+
export async function generate(handles, messages, runtime, preset, options = {}) {
|
|
10
|
+
const started = performance.now();
|
|
11
|
+
if (handles.backend === "transformers-js") {
|
|
12
|
+
if (!handles.transformersGenerator)
|
|
13
|
+
throw new Error("Transformers.js pipeline is not loaded.");
|
|
14
|
+
const telemetry = await runTransformers(handles, messages, runtime, preset, options.onDelta, started);
|
|
15
|
+
const ended = performance.now();
|
|
16
|
+
const text = telemetry.text || EMPTY_RESPONSE;
|
|
17
|
+
const stats = collectTransformersStats(preset.id, runtime, telemetry, started, ended);
|
|
18
|
+
return { text, stats };
|
|
19
|
+
}
|
|
20
|
+
if (!handles.engine)
|
|
21
|
+
throw new Error("WebLLM engine is not loaded.");
|
|
22
|
+
if (options.resetChat !== false) {
|
|
23
|
+
await handles.engine.resetChat(false);
|
|
24
|
+
}
|
|
25
|
+
const responseFormat = options.schema !== undefined ? buildResponseFormat(runtime.jsonMode, options.schema) : undefined;
|
|
26
|
+
const extraBody = buildExtraBody(runtime, preset);
|
|
27
|
+
const outcome = options.onDelta
|
|
28
|
+
? await runWebLLMStream(handles.engine, messages, runtime, responseFormat, extraBody, options.onDelta)
|
|
29
|
+
: await runWebLLMBlocking(handles.engine, messages, runtime, responseFormat, extraBody);
|
|
30
|
+
const ended = performance.now();
|
|
31
|
+
const stats = await collectWebLLMStats(handles, outcome.usage, outcome.finishReason, started, ended, outcome.firstTokenMs);
|
|
32
|
+
return { text: outcome.text || EMPTY_RESPONSE, stats };
|
|
33
|
+
}
|
|
34
|
+
function buildExtraBody(runtime, preset) {
|
|
35
|
+
const extraBody = {};
|
|
36
|
+
if (preset.disableThinkingSupported) {
|
|
37
|
+
extraBody.enable_thinking = runtime.disableThinking === false;
|
|
38
|
+
}
|
|
39
|
+
if (runtime.latencyBreakdown) {
|
|
40
|
+
extraBody.enable_latency_breakdown = true;
|
|
41
|
+
}
|
|
42
|
+
return Object.keys(extraBody).length > 0 ? extraBody : undefined;
|
|
43
|
+
}
|
|
44
|
+
async function runWebLLMBlocking(engine, messages, runtime, responseFormat, extraBody) {
|
|
45
|
+
const response = await engine.chat.completions.create({
|
|
46
|
+
messages,
|
|
47
|
+
stream: false,
|
|
48
|
+
n: 1,
|
|
49
|
+
temperature: runtime.temperature,
|
|
50
|
+
top_p: runtime.topP,
|
|
51
|
+
max_tokens: runtime.maxTokens,
|
|
52
|
+
repetition_penalty: runtime.repetitionPenalty,
|
|
53
|
+
frequency_penalty: runtime.frequencyPenalty,
|
|
54
|
+
presence_penalty: runtime.presencePenalty,
|
|
55
|
+
seed: runtime.seed ?? undefined,
|
|
56
|
+
response_format: responseFormat,
|
|
57
|
+
extra_body: extraBody,
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
text: response.choices[0]?.message?.content ?? "",
|
|
61
|
+
finishReason: response.choices[0]?.finish_reason ?? "unknown",
|
|
62
|
+
usage: response.usage,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async function runWebLLMStream(engine, messages, runtime, responseFormat, extraBody, onDelta) {
|
|
66
|
+
const stream = await engine.chat.completions.create({
|
|
67
|
+
messages,
|
|
68
|
+
stream: true,
|
|
69
|
+
stream_options: { include_usage: true },
|
|
70
|
+
temperature: runtime.temperature,
|
|
71
|
+
top_p: runtime.topP,
|
|
72
|
+
max_tokens: runtime.maxTokens,
|
|
73
|
+
repetition_penalty: runtime.repetitionPenalty,
|
|
74
|
+
frequency_penalty: runtime.frequencyPenalty,
|
|
75
|
+
presence_penalty: runtime.presencePenalty,
|
|
76
|
+
seed: runtime.seed ?? undefined,
|
|
77
|
+
response_format: responseFormat,
|
|
78
|
+
extra_body: extraBody,
|
|
79
|
+
});
|
|
80
|
+
let text = "";
|
|
81
|
+
let finishReason = "unknown";
|
|
82
|
+
let usage;
|
|
83
|
+
let firstTokenMs;
|
|
84
|
+
for await (const chunk of stream) {
|
|
85
|
+
const choice = chunk.choices[0];
|
|
86
|
+
const delta = choice?.delta?.content ?? "";
|
|
87
|
+
if (delta) {
|
|
88
|
+
if (firstTokenMs === undefined)
|
|
89
|
+
firstTokenMs = performance.now();
|
|
90
|
+
text += delta;
|
|
91
|
+
onDelta(text);
|
|
92
|
+
}
|
|
93
|
+
if (choice?.finish_reason)
|
|
94
|
+
finishReason = choice.finish_reason;
|
|
95
|
+
if (chunk.usage)
|
|
96
|
+
usage = chunk.usage;
|
|
97
|
+
}
|
|
98
|
+
return { text, finishReason, usage, firstTokenMs };
|
|
99
|
+
}
|
|
100
|
+
async function collectWebLLMStats(handles, usage, finishReason, started, ended, firstTokenMs) {
|
|
101
|
+
const elapsedMs = ended - started;
|
|
102
|
+
const completionTokens = usage?.completion_tokens;
|
|
103
|
+
const measured = typeof completionTokens === "number" && elapsedMs > 0 ? completionTokens / (elapsedMs / 1000) : undefined;
|
|
104
|
+
// Prefer the engine's telemetry. When it is absent (some engine/model combos omit usage.extra),
|
|
105
|
+
// synthesize the headline metrics from what we measured so they never blank out.
|
|
106
|
+
const extra = usage?.extra
|
|
107
|
+
? { ...usage.extra, latencyBreakdown: normalizeLatencyBreakdown(usage.extra.latencyBreakdown) }
|
|
108
|
+
: measured !== undefined || firstTokenMs !== undefined
|
|
109
|
+
? {
|
|
110
|
+
decode_tokens_per_s: measured,
|
|
111
|
+
e2e_latency_s: elapsedMs / 1000,
|
|
112
|
+
time_to_first_token_s: firstTokenMs !== undefined ? Math.max(0, (firstTokenMs - started) / 1000) : undefined,
|
|
113
|
+
}
|
|
114
|
+
: undefined;
|
|
115
|
+
let legacyStats;
|
|
116
|
+
if (handles.engine && handles.modelId) {
|
|
117
|
+
try {
|
|
118
|
+
const engineStats = await handles.engine.runtimeStatsText(handles.modelId);
|
|
119
|
+
legacyStats = engineStats.trim() || undefined;
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
legacyStats = `unavailable: ${formatError(error)}`;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const stats = {
|
|
126
|
+
rawText: "",
|
|
127
|
+
model: handles.modelId ?? "n/a",
|
|
128
|
+
backend: "webllm",
|
|
129
|
+
finishReason,
|
|
130
|
+
measuredElapsedMs: elapsedMs,
|
|
131
|
+
promptTokens: usage?.prompt_tokens,
|
|
132
|
+
completionTokens: usage?.completion_tokens,
|
|
133
|
+
totalTokens: usage?.total_tokens,
|
|
134
|
+
measuredCompletionTokensPerSecond: measured,
|
|
135
|
+
extra,
|
|
136
|
+
latencyBreakdown: extra?.latencyBreakdown,
|
|
137
|
+
legacyStats,
|
|
138
|
+
};
|
|
139
|
+
stats.rawText = buildRuntimeStatsText(stats);
|
|
140
|
+
return stats;
|
|
141
|
+
}
|
|
142
|
+
async function runTransformers(handles, messages, runtime, preset, onDelta,
|
|
143
|
+
// Origin clock shared with generate()'s `started` so TTFT and e2e latency are measured consistently.
|
|
144
|
+
startedMs) {
|
|
145
|
+
const generator = handles.transformersGenerator;
|
|
146
|
+
const tokenizer = handles.transformersTokenizer ?? generator.tokenizer ?? null;
|
|
147
|
+
const telemetry = {
|
|
148
|
+
promptTokens: countPromptTokens(tokenizer, messages),
|
|
149
|
+
tokenCallbackIntervalSeconds: [],
|
|
150
|
+
tokenCallbackCount: 0,
|
|
151
|
+
tokenCountSource: "unavailable",
|
|
152
|
+
};
|
|
153
|
+
const tokenTimesMs = [];
|
|
154
|
+
const generationOptions = {
|
|
155
|
+
max_new_tokens: runtime.maxTokens,
|
|
156
|
+
do_sample: runtime.temperature > 0,
|
|
157
|
+
top_p: runtime.topP,
|
|
158
|
+
repetition_penalty: runtime.repetitionPenalty,
|
|
159
|
+
return_full_text: false,
|
|
160
|
+
};
|
|
161
|
+
if (runtime.temperature > 0)
|
|
162
|
+
generationOptions.temperature = runtime.temperature;
|
|
163
|
+
if (runtime.seed !== null)
|
|
164
|
+
generationOptions.seed = runtime.seed;
|
|
165
|
+
if (preset.disableThinkingSupported) {
|
|
166
|
+
generationOptions.tokenizer_encode_kwargs = { enable_thinking: !runtime.disableThinking };
|
|
167
|
+
}
|
|
168
|
+
const Streamer = handles.transformersModule?.TextStreamer;
|
|
169
|
+
let streamedText = "";
|
|
170
|
+
if (tokenizer && Streamer) {
|
|
171
|
+
generationOptions.streamer = new Streamer(tokenizer, {
|
|
172
|
+
skip_prompt: true,
|
|
173
|
+
skip_special_tokens: true,
|
|
174
|
+
callback_function: (chunk) => {
|
|
175
|
+
if (typeof chunk === "string" && onDelta) {
|
|
176
|
+
streamedText += chunk;
|
|
177
|
+
onDelta(streamedText);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
token_callback_function: (tokens) => {
|
|
181
|
+
const now = performance.now();
|
|
182
|
+
const count = Math.max(1, countTokenItems(tokens));
|
|
183
|
+
for (let index = 0; index < count; index += 1)
|
|
184
|
+
tokenTimesMs.push(now);
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const output = await generator(messages, generationOptions);
|
|
189
|
+
const text = extractGeneratedText(output) || EMPTY_RESPONSE;
|
|
190
|
+
if (tokenTimesMs.length > 0) {
|
|
191
|
+
telemetry.tokenCallbackCount = tokenTimesMs.length;
|
|
192
|
+
telemetry.tokenCountSource = "streamer";
|
|
193
|
+
telemetry.completionTokens = tokenTimesMs.length;
|
|
194
|
+
telemetry.firstTokenOffsetMs = Math.max(0, tokenTimesMs[0] - startedMs);
|
|
195
|
+
telemetry.tokenCallbackIntervalSeconds = tokenTimesMs.slice(1).map((time, index) => Math.max(0, (time - tokenTimesMs[index]) / 1000));
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
const fallback = countCompletionTokens(tokenizer, text);
|
|
199
|
+
if (typeof fallback === "number") {
|
|
200
|
+
telemetry.completionTokens = fallback;
|
|
201
|
+
telemetry.tokenCountSource = "tokenizer";
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return { ...telemetry, text };
|
|
205
|
+
}
|
|
206
|
+
function collectTransformersStats(model, runtime, telemetry, started, ended) {
|
|
207
|
+
const elapsedMs = ended - started;
|
|
208
|
+
const completionTokens = telemetry.completionTokens;
|
|
209
|
+
const measured = typeof completionTokens === "number" && elapsedMs > 0 ? completionTokens / (elapsedMs / 1000) : undefined;
|
|
210
|
+
const decodeSeconds = typeof telemetry.firstTokenOffsetMs === "number" ? Math.max(0, (elapsedMs - telemetry.firstTokenOffsetMs) / 1000) : undefined;
|
|
211
|
+
const decode = typeof completionTokens === "number" && typeof decodeSeconds === "number" && decodeSeconds > 0 ? completionTokens / decodeSeconds : measured;
|
|
212
|
+
const prefill = typeof telemetry.promptTokens === "number" && typeof telemetry.firstTokenOffsetMs === "number" && telemetry.firstTokenOffsetMs > 0
|
|
213
|
+
? telemetry.promptTokens / (telemetry.firstTokenOffsetMs / 1000)
|
|
214
|
+
: undefined;
|
|
215
|
+
const tpot = telemetry.tokenCallbackIntervalSeconds.length > 0
|
|
216
|
+
? telemetry.tokenCallbackIntervalSeconds.reduce((sum, value) => sum + value, 0) / telemetry.tokenCallbackIntervalSeconds.length
|
|
217
|
+
: typeof completionTokens === "number" && completionTokens > 0
|
|
218
|
+
? elapsedMs / 1000 / completionTokens
|
|
219
|
+
: undefined;
|
|
220
|
+
const totalTokens = typeof telemetry.promptTokens === "number" && typeof completionTokens === "number" ? telemetry.promptTokens + completionTokens : undefined;
|
|
221
|
+
const finishReason = typeof completionTokens === "number" && completionTokens >= runtime.maxTokens ? "length (estimated)" : "stop/unknown";
|
|
222
|
+
const latencyBreakdown = telemetry.tokenCallbackIntervalSeconds.length > 0 ? { transformersTokenIntervalTime: telemetry.tokenCallbackIntervalSeconds } : undefined;
|
|
223
|
+
const stats = {
|
|
224
|
+
rawText: "",
|
|
225
|
+
model,
|
|
226
|
+
backend: "transformers-js",
|
|
227
|
+
finishReason,
|
|
228
|
+
measuredElapsedMs: elapsedMs,
|
|
229
|
+
promptTokens: telemetry.promptTokens,
|
|
230
|
+
completionTokens,
|
|
231
|
+
totalTokens,
|
|
232
|
+
measuredCompletionTokensPerSecond: measured,
|
|
233
|
+
extra: {
|
|
234
|
+
e2e_latency_s: elapsedMs / 1000,
|
|
235
|
+
prefill_tokens_per_s: prefill,
|
|
236
|
+
decode_tokens_per_s: decode,
|
|
237
|
+
time_to_first_token_s: typeof telemetry.firstTokenOffsetMs === "number" ? telemetry.firstTokenOffsetMs / 1000 : undefined,
|
|
238
|
+
time_per_output_token_s: tpot,
|
|
239
|
+
latencyBreakdown,
|
|
240
|
+
token_count_source: telemetry.tokenCountSource,
|
|
241
|
+
},
|
|
242
|
+
latencyBreakdown,
|
|
243
|
+
};
|
|
244
|
+
stats.rawText = buildRuntimeStatsText(stats);
|
|
245
|
+
return stats;
|
|
246
|
+
}
|
|
247
|
+
export function collectGenericStats(model, backend, started, ended, error) {
|
|
248
|
+
const stats = {
|
|
249
|
+
rawText: "",
|
|
250
|
+
model,
|
|
251
|
+
backend,
|
|
252
|
+
finishReason: "error",
|
|
253
|
+
measuredElapsedMs: ended - started,
|
|
254
|
+
error,
|
|
255
|
+
};
|
|
256
|
+
stats.rawText = buildRuntimeStatsText(stats);
|
|
257
|
+
return stats;
|
|
258
|
+
}
|
|
259
|
+
/* ------------------------------------------------------------------ */
|
|
260
|
+
/* Shared helpers */
|
|
261
|
+
/* ------------------------------------------------------------------ */
|
|
262
|
+
export function buildRuntimeStatsText(stats) {
|
|
263
|
+
const backendLabel = stats.backend === "transformers-js" ? "Transformers.js" : stats.backend === "webllm" ? "WebLLM" : "unknown";
|
|
264
|
+
const lines = [
|
|
265
|
+
`model: ${stats.model}`,
|
|
266
|
+
`backend: ${backendLabel}`,
|
|
267
|
+
`finish_reason: ${stats.finishReason}`,
|
|
268
|
+
`measured_elapsed_ms: ${stats.measuredElapsedMs.toFixed(0)}`,
|
|
269
|
+
"",
|
|
270
|
+
"Token usage:",
|
|
271
|
+
` prompt_tokens: ${stats.promptTokens ?? "n/a"}`,
|
|
272
|
+
` completion_tokens: ${stats.completionTokens ?? "n/a"}`,
|
|
273
|
+
` total_tokens: ${stats.totalTokens ?? "n/a"}`,
|
|
274
|
+
` measured_completion_tokens_per_second: ${stats.measuredCompletionTokensPerSecond?.toFixed(2) ?? "n/a"}`,
|
|
275
|
+
];
|
|
276
|
+
if (stats.extra) {
|
|
277
|
+
lines.push("", stats.backend === "transformers-js" ? "Transformers.js measured telemetry:" : "WebLLM usage.extra:", ` e2e_latency_s: ${formatMaybe(stats.extra.e2e_latency_s, 3)}`, ` prefill_tokens_per_s: ${formatMaybe(stats.extra.prefill_tokens_per_s, 2)}`, ` decode_tokens_per_s: ${formatMaybe(stats.extra.decode_tokens_per_s, 2)}`, ` time_to_first_token_s: ${formatMaybe(stats.extra.time_to_first_token_s, 3)}`, ` time_per_output_token_s: ${formatMaybe(stats.extra.time_per_output_token_s, 4)}`);
|
|
278
|
+
if (typeof stats.extra.grammar_init_s === "number")
|
|
279
|
+
lines.push(` grammar_init_s: ${stats.extra.grammar_init_s.toFixed(3)}`);
|
|
280
|
+
if (typeof stats.extra.grammar_per_token_s === "number")
|
|
281
|
+
lines.push(` grammar_per_token_s: ${stats.extra.grammar_per_token_s.toFixed(6)}`);
|
|
282
|
+
if (stats.backend === "transformers-js" && typeof stats.extra.token_count_source === "string") {
|
|
283
|
+
lines.push(` token_count_source: ${stats.extra.token_count_source}`);
|
|
284
|
+
}
|
|
285
|
+
if (stats.latencyBreakdown && Object.keys(stats.latencyBreakdown).length > 0) {
|
|
286
|
+
lines.push("", "Latency breakdown:", JSON.stringify(stats.latencyBreakdown, null, 2));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
lines.push("", `${backendLabel} backend telemetry: n/a`);
|
|
291
|
+
}
|
|
292
|
+
if (stats.error)
|
|
293
|
+
lines.push("", `error: ${stats.error}`);
|
|
294
|
+
if (stats.legacyStats)
|
|
295
|
+
lines.push("", "Legacy WebLLM runtimeStatsText:", stats.legacyStats);
|
|
296
|
+
return lines.join("\n");
|
|
297
|
+
}
|
|
298
|
+
export function normalizeLatencyBreakdown(value) {
|
|
299
|
+
if (!value || typeof value !== "object")
|
|
300
|
+
return undefined;
|
|
301
|
+
const result = {};
|
|
302
|
+
for (const [key, child] of Object.entries(value)) {
|
|
303
|
+
if (Array.isArray(child)) {
|
|
304
|
+
const numbers = child.filter((item) => typeof item === "number" && Number.isFinite(item));
|
|
305
|
+
if (numbers.length > 0)
|
|
306
|
+
result[key] = numbers;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
310
|
+
}
|
|
311
|
+
function extractGeneratedText(output) {
|
|
312
|
+
if (typeof output === "string")
|
|
313
|
+
return output;
|
|
314
|
+
if (Array.isArray(output))
|
|
315
|
+
return output.map(extractGeneratedText).filter(Boolean).join("\n");
|
|
316
|
+
if (!output || typeof output !== "object")
|
|
317
|
+
return "";
|
|
318
|
+
const record = output;
|
|
319
|
+
const generated = record.generated_text;
|
|
320
|
+
if (typeof generated === "string")
|
|
321
|
+
return generated;
|
|
322
|
+
if (Array.isArray(generated)) {
|
|
323
|
+
const assistant = generated
|
|
324
|
+
.filter((item) => Boolean(item) && typeof item === "object")
|
|
325
|
+
.filter((item) => item.role === "assistant" && typeof item.content === "string");
|
|
326
|
+
const last = assistant.at(-1);
|
|
327
|
+
if (typeof last?.content === "string")
|
|
328
|
+
return last.content;
|
|
329
|
+
return generated.map(extractGeneratedText).filter(Boolean).join("\n");
|
|
330
|
+
}
|
|
331
|
+
for (const key of ["text", "content", "answer"]) {
|
|
332
|
+
if (typeof record[key] === "string")
|
|
333
|
+
return record[key];
|
|
334
|
+
}
|
|
335
|
+
return JSON.stringify(output, null, 2);
|
|
336
|
+
}
|
|
337
|
+
function countPromptTokens(tokenizer, messages) {
|
|
338
|
+
if (!tokenizer)
|
|
339
|
+
return undefined;
|
|
340
|
+
try {
|
|
341
|
+
if (typeof tokenizer.apply_chat_template === "function") {
|
|
342
|
+
const tokenized = tokenizer.apply_chat_template(messages, { tokenize: true, add_generation_prompt: true });
|
|
343
|
+
const count = extractTokenCount(tokenized);
|
|
344
|
+
if (typeof count === "number")
|
|
345
|
+
return count;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
// Fall through to plain-text tokenization.
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
const prompt = messages.map((message) => `${message.role}: ${message.content}`).join("\n\n") + "\n\nassistant:";
|
|
353
|
+
if (typeof tokenizer.encode === "function") {
|
|
354
|
+
const count = extractTokenCount(tokenizer.encode(prompt, { add_special_tokens: true }));
|
|
355
|
+
if (typeof count === "number")
|
|
356
|
+
return count;
|
|
357
|
+
}
|
|
358
|
+
return extractTokenCount(tokenizer(prompt, { add_special_tokens: true }));
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
return undefined;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
function countCompletionTokens(tokenizer, text) {
|
|
365
|
+
if (!tokenizer || !text || text === EMPTY_RESPONSE)
|
|
366
|
+
return undefined;
|
|
367
|
+
try {
|
|
368
|
+
if (typeof tokenizer.encode === "function")
|
|
369
|
+
return extractTokenCount(tokenizer.encode(text, { add_special_tokens: false }));
|
|
370
|
+
return extractTokenCount(tokenizer(text, { add_special_tokens: false }));
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
function countTokenItems(value) {
|
|
377
|
+
return extractTokenCount(value) ?? 1;
|
|
378
|
+
}
|
|
379
|
+
function extractTokenCount(value) {
|
|
380
|
+
if (value == null)
|
|
381
|
+
return undefined;
|
|
382
|
+
if (typeof value === "number" || typeof value === "bigint")
|
|
383
|
+
return 1;
|
|
384
|
+
if (ArrayBuffer.isView(value))
|
|
385
|
+
return value.length;
|
|
386
|
+
if (Array.isArray(value)) {
|
|
387
|
+
if (value.length === 0)
|
|
388
|
+
return 0;
|
|
389
|
+
if (value.every((item) => typeof item === "number" || typeof item === "bigint"))
|
|
390
|
+
return value.length;
|
|
391
|
+
const childCounts = value.map(extractTokenCount).filter((count) => typeof count === "number");
|
|
392
|
+
return childCounts.length > 0 ? childCounts.reduce((sum, count) => sum + count, 0) : value.length;
|
|
393
|
+
}
|
|
394
|
+
if (typeof value !== "object")
|
|
395
|
+
return undefined;
|
|
396
|
+
const record = value;
|
|
397
|
+
for (const key of ["input_ids", "data", "tokens", "ids"]) {
|
|
398
|
+
const count = extractTokenCount(record[key]);
|
|
399
|
+
if (typeof count === "number")
|
|
400
|
+
return count;
|
|
401
|
+
}
|
|
402
|
+
const dims = record.dims;
|
|
403
|
+
if (Array.isArray(dims) && dims.every((dimension) => typeof dimension === "number")) {
|
|
404
|
+
return dims.reduce((product, dimension) => product * dimension, 1);
|
|
405
|
+
}
|
|
406
|
+
return undefined;
|
|
407
|
+
}
|
|
408
|
+
function formatMaybe(value, digits) {
|
|
409
|
+
return typeof value === "number" && Number.isFinite(value) ? value.toFixed(digits) : "n/a";
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=inference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inference.js","sourceRoot":"","sources":["../src/inference.ts"],"names":[],"mappings":"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"}
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type JsonParseResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
value: unknown;
|
|
4
|
+
rawJson: string;
|
|
5
|
+
warnings: string[];
|
|
6
|
+
} | {
|
|
7
|
+
ok: false;
|
|
8
|
+
error: string;
|
|
9
|
+
rawJson: string;
|
|
10
|
+
warnings: string[];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Some models wrap JSON in Markdown or thinking tags despite instructions. WebLLM JSON mode should
|
|
14
|
+
* not do this, but these helpers make output handling robust across different models/settings.
|
|
15
|
+
* (Schema validation lives in schema-validator.ts — one validator for the whole SDK.)
|
|
16
|
+
*/
|
|
17
|
+
export declare function normalizeModelText(text: string): string;
|
|
18
|
+
export declare function extractJsonCandidate(text: string): string;
|
|
19
|
+
export declare function parseJsonFromModel(text: string): JsonParseResult;
|
|
20
|
+
export declare function prettyJson(value: unknown): string;
|
|
21
|
+
export declare function detectLikelyRepetition(text: string): string[];
|
|
22
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACjE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAOtE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CA0ChE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjD;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA+B7D"}
|
package/dist/json.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Some models wrap JSON in Markdown or thinking tags despite instructions. WebLLM JSON mode should
|
|
3
|
+
* not do this, but these helpers make output handling robust across different models/settings.
|
|
4
|
+
* (Schema validation lives in schema-validator.ts — one validator for the whole SDK.)
|
|
5
|
+
*/
|
|
6
|
+
export function normalizeModelText(text) {
|
|
7
|
+
const trimmed = text.trim();
|
|
8
|
+
const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
|
|
9
|
+
const withoutFence = fenced?.[1] ? fenced[1].trim() : trimmed;
|
|
10
|
+
return withoutFence.replace(/<think>[\s\S]*?<\/think>/gi, "").trim();
|
|
11
|
+
}
|
|
12
|
+
export function extractJsonCandidate(text) {
|
|
13
|
+
const cleaned = normalizeModelText(text);
|
|
14
|
+
return findFirstBalancedJson(cleaned)?.rawJson ?? cleaned;
|
|
15
|
+
}
|
|
16
|
+
export function parseJsonFromModel(text) {
|
|
17
|
+
const cleaned = normalizeModelText(text);
|
|
18
|
+
const warnings = [];
|
|
19
|
+
try {
|
|
20
|
+
return { ok: true, value: JSON.parse(cleaned), rawJson: cleaned, warnings };
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Continue below. A common small-model failure is valid JSON followed by repeated
|
|
24
|
+
// text. In that case we parse the first complete JSON value and warn the caller.
|
|
25
|
+
}
|
|
26
|
+
const balanced = findFirstBalancedJson(cleaned);
|
|
27
|
+
if (balanced) {
|
|
28
|
+
if (balanced.hadPrefixOrSuffix) {
|
|
29
|
+
warnings.push("Parsed the first complete JSON value, but the model also produced prefix/suffix text. Tighten generation parameters or lower max tokens if this repeats.");
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return {
|
|
33
|
+
ok: true,
|
|
34
|
+
value: JSON.parse(balanced.rawJson),
|
|
35
|
+
rawJson: balanced.rawJson,
|
|
36
|
+
warnings,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
rawJson: balanced.rawJson,
|
|
43
|
+
warnings,
|
|
44
|
+
error: error instanceof Error ? error.message : String(error),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
rawJson: cleaned,
|
|
51
|
+
warnings,
|
|
52
|
+
error: "No complete balanced JSON object or array was found.",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function prettyJson(value) {
|
|
56
|
+
return JSON.stringify(value, null, 2);
|
|
57
|
+
}
|
|
58
|
+
export function detectLikelyRepetition(text) {
|
|
59
|
+
const warnings = [];
|
|
60
|
+
const normalized = text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
61
|
+
if (!normalized)
|
|
62
|
+
return warnings;
|
|
63
|
+
const words = normalized.split(" ").filter((word) => word.length > 2);
|
|
64
|
+
const ngramCounts = new Map();
|
|
65
|
+
for (let i = 0; i <= words.length - 3; i += 1) {
|
|
66
|
+
const ngram = words.slice(i, i + 3).join(" ");
|
|
67
|
+
ngramCounts.set(ngram, (ngramCounts.get(ngram) ?? 0) + 1);
|
|
68
|
+
}
|
|
69
|
+
const repeated = Array.from(ngramCounts.entries()).find(([, count]) => count >= 3);
|
|
70
|
+
if (repeated) {
|
|
71
|
+
warnings.push(`Likely repetition detected: "${repeated[0]}" appeared ${repeated[1]} times.`);
|
|
72
|
+
}
|
|
73
|
+
const fragments = normalized
|
|
74
|
+
.split(/[{}\[\],]/)
|
|
75
|
+
.map((line) => line.trim())
|
|
76
|
+
.filter((line) => line.length > 20);
|
|
77
|
+
const fragmentCounts = new Map();
|
|
78
|
+
for (const fragment of fragments) {
|
|
79
|
+
fragmentCounts.set(fragment, (fragmentCounts.get(fragment) ?? 0) + 1);
|
|
80
|
+
}
|
|
81
|
+
const repeatedFragment = Array.from(fragmentCounts.entries()).find(([, count]) => count >= 3);
|
|
82
|
+
if (repeatedFragment) {
|
|
83
|
+
warnings.push("Repeated JSON fragments detected in the raw output.");
|
|
84
|
+
}
|
|
85
|
+
return warnings;
|
|
86
|
+
}
|
|
87
|
+
function findFirstBalancedJson(text) {
|
|
88
|
+
const start = findJsonStart(text);
|
|
89
|
+
if (start < 0)
|
|
90
|
+
return null;
|
|
91
|
+
const stack = [];
|
|
92
|
+
let inString = false;
|
|
93
|
+
let escaped = false;
|
|
94
|
+
for (let i = start; i < text.length; i += 1) {
|
|
95
|
+
const char = text[i];
|
|
96
|
+
if (inString) {
|
|
97
|
+
if (escaped) {
|
|
98
|
+
escaped = false;
|
|
99
|
+
}
|
|
100
|
+
else if (char === "\\") {
|
|
101
|
+
escaped = true;
|
|
102
|
+
}
|
|
103
|
+
else if (char === '"') {
|
|
104
|
+
inString = false;
|
|
105
|
+
}
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (char === '"') {
|
|
109
|
+
inString = true;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (char === "{") {
|
|
113
|
+
stack.push("}");
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (char === "[") {
|
|
117
|
+
stack.push("]");
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (char === "}" || char === "]") {
|
|
121
|
+
const expected = stack.pop();
|
|
122
|
+
if (expected !== char)
|
|
123
|
+
return null;
|
|
124
|
+
if (stack.length === 0) {
|
|
125
|
+
const rawJson = text.slice(start, i + 1).trim();
|
|
126
|
+
const suffix = text.slice(i + 1).trim();
|
|
127
|
+
return {
|
|
128
|
+
rawJson,
|
|
129
|
+
hadPrefixOrSuffix: start > 0 || suffix.length > 0,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
function findJsonStart(text) {
|
|
137
|
+
const objectStart = text.indexOf("{");
|
|
138
|
+
const arrayStart = text.indexOf("[");
|
|
139
|
+
if (objectStart === -1)
|
|
140
|
+
return arrayStart;
|
|
141
|
+
if (arrayStart === -1)
|
|
142
|
+
return objectStart;
|
|
143
|
+
return Math.min(objectStart, arrayStart);
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=json.js.map
|
package/dist/json.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { GenStats } from "./multimodal.js";
|
|
2
|
+
import type { RuntimeStats } from "./inference.js";
|
|
3
|
+
import type { RunRecord } from "./history.js";
|
|
4
|
+
/** Build a RuntimeStats record from multimodal generation telemetry (tokens + first-token time). */
|
|
5
|
+
export declare function buildMultimodalStats(gen: GenStats, modelId: string): RuntimeStats;
|
|
6
|
+
/**
|
|
7
|
+
* Map a generation's RuntimeStats to a persistable RunRecord, attributing the run to the model that
|
|
8
|
+
* produced the stats (not whatever is currently selected). Returns null for stats without a model
|
|
9
|
+
* (error placeholders) so failed runs never pollute history.
|
|
10
|
+
*/
|
|
11
|
+
export declare function runRecordFromStats(caseKey: string, stats: RuntimeStats): RunRecord | null;
|
|
12
|
+
/**
|
|
13
|
+
* Word-count proxy for non-generative transcription runs: ASR pipelines (Whisper/Moonshine) produce
|
|
14
|
+
* no token telemetry, so callers may log `{ completionTokens: wordCount }` instead. Exposed as an
|
|
15
|
+
* explicit helper so the unit substitution is a visible policy, not a silent one.
|
|
16
|
+
*/
|
|
17
|
+
export declare function wordCountGenStats(text: string, startedMs: number, endedMs: number): GenStats;
|
|
18
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAqBjF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAiBzF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAG5F"}
|