Spaces:
Runtime error
Runtime error
Per-task benchmarks
Browse files- bench/src/core/task-inputs.ts +140 -0
- bench/src/node/benchmark.ts +7 -6
- bench/src/web/benchmark.ts +7 -6
bench/src/core/task-inputs.ts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* Task-specific input generation for benchmarking
|
| 3 |
+
* Based on Transformers.js usage examples
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
export interface TaskInput {
|
| 7 |
+
inputs: any;
|
| 8 |
+
options?: any;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
/**
|
| 12 |
+
* Generate appropriate input for a given task type
|
| 13 |
+
*/
|
| 14 |
+
export function getTaskInput(task: string, batchSize: number = 1): TaskInput {
|
| 15 |
+
// Normalize task name
|
| 16 |
+
const normalizedTask = task.toLowerCase().trim();
|
| 17 |
+
|
| 18 |
+
// Text tasks
|
| 19 |
+
if (normalizedTask === "fill-mask") {
|
| 20 |
+
const inputs = Array(batchSize).fill("The goal of life is [MASK].");
|
| 21 |
+
return { inputs };
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
if (normalizedTask === "question-answering") {
|
| 25 |
+
const question = "Who was Jim Henson?";
|
| 26 |
+
const context = "Jim Henson was a nice puppet.";
|
| 27 |
+
// For batch, repeat the same question-context pair
|
| 28 |
+
const inputs = Array(batchSize).fill({ question, context });
|
| 29 |
+
return { inputs: batchSize === 1 ? { question, context } : inputs };
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
if (normalizedTask === "summarization") {
|
| 33 |
+
const text =
|
| 34 |
+
"The tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, " +
|
| 35 |
+
"and the tallest structure in Paris. Its base is square, measuring 125 metres (410 ft) on each side. " +
|
| 36 |
+
"During its construction, the Eiffel Tower surpassed the Washington Monument to become the tallest " +
|
| 37 |
+
"man-made structure in the world, a title it held for 41 years until the Chrysler Building in New " +
|
| 38 |
+
"York City was finished in 1930.";
|
| 39 |
+
const inputs = Array(batchSize).fill(text);
|
| 40 |
+
return { inputs, options: { max_new_tokens: 100 } };
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
if (normalizedTask === "sentiment-analysis" || normalizedTask === "text-classification") {
|
| 44 |
+
const inputs = Array(batchSize).fill("I love transformers!");
|
| 45 |
+
return { inputs };
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
if (normalizedTask === "text-generation") {
|
| 49 |
+
const inputs = Array(batchSize).fill("Once upon a time, there was");
|
| 50 |
+
return { inputs, options: { max_new_tokens: 10 } };
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
if (normalizedTask === "text2text-generation") {
|
| 54 |
+
const inputs = Array(batchSize).fill("how can I become more healthy?");
|
| 55 |
+
return { inputs, options: { max_new_tokens: 100 } };
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
if (normalizedTask === "token-classification" || normalizedTask === "ner") {
|
| 59 |
+
const inputs = Array(batchSize).fill("My name is Sarah and I live in London");
|
| 60 |
+
return { inputs };
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
if (normalizedTask === "translation") {
|
| 64 |
+
const inputs = Array(batchSize).fill("Life is like a box of chocolate.");
|
| 65 |
+
return { inputs, options: { src_lang: "eng_Latn", tgt_lang: "fra_Latn" } };
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
if (normalizedTask === "zero-shot-classification") {
|
| 69 |
+
const text = "I love transformers!";
|
| 70 |
+
const labels = ["positive", "negative"];
|
| 71 |
+
// For batching, would need to handle differently - for now use single input
|
| 72 |
+
return { inputs: batchSize === 1 ? [text, labels] : Array(batchSize).fill([text, labels]) };
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
if (normalizedTask === "feature-extraction") {
|
| 76 |
+
const inputs = Array(batchSize).fill("This is a simple test.");
|
| 77 |
+
return { inputs };
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
// Vision tasks - use public image URLs
|
| 81 |
+
if (normalizedTask === "background-removal") {
|
| 82 |
+
const url = "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/portrait-of-woman_small.jpg";
|
| 83 |
+
const inputs = Array(batchSize).fill(url);
|
| 84 |
+
return { inputs };
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
if (normalizedTask === "depth-estimation") {
|
| 88 |
+
const url = "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/cats.jpg";
|
| 89 |
+
const inputs = Array(batchSize).fill(url);
|
| 90 |
+
return { inputs };
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
if (normalizedTask === "image-classification") {
|
| 94 |
+
const url = "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/tiger.jpg";
|
| 95 |
+
const inputs = Array(batchSize).fill(url);
|
| 96 |
+
return { inputs };
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
if (normalizedTask === "image-segmentation") {
|
| 100 |
+
const url = "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/cats.jpg";
|
| 101 |
+
const inputs = Array(batchSize).fill(url);
|
| 102 |
+
return { inputs };
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
if (normalizedTask === "image-to-image") {
|
| 106 |
+
const url = "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/tiger.jpg";
|
| 107 |
+
const inputs = Array(batchSize).fill(url);
|
| 108 |
+
return { inputs };
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
if (normalizedTask === "object-detection") {
|
| 112 |
+
const url = "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/cats.jpg";
|
| 113 |
+
const inputs = Array(batchSize).fill(url);
|
| 114 |
+
return { inputs, options: { threshold: 0.9 } };
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
if (normalizedTask === "image-feature-extraction") {
|
| 118 |
+
const url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/cats.png";
|
| 119 |
+
const inputs = Array(batchSize).fill(url);
|
| 120 |
+
return { inputs };
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
// Audio tasks
|
| 124 |
+
if (normalizedTask === "audio-classification") {
|
| 125 |
+
const url = "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/jfk.wav";
|
| 126 |
+
const inputs = Array(batchSize).fill(url);
|
| 127 |
+
return { inputs };
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
if (normalizedTask === "automatic-speech-recognition") {
|
| 131 |
+
const url = "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/jfk.wav";
|
| 132 |
+
const inputs = Array(batchSize).fill(url);
|
| 133 |
+
return { inputs };
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
// Default fallback for unknown tasks - use text
|
| 137 |
+
console.warn(`Unknown task type: ${task}, using default text input`);
|
| 138 |
+
const inputs = Array(batchSize).fill("The quick brown fox jumps over the lazy dog.");
|
| 139 |
+
return { inputs };
|
| 140 |
+
}
|
bench/src/node/benchmark.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { BenchmarkOptions, BenchmarkResult } from "../core/types.js";
|
|
| 5 |
import { BenchmarkRawResult, aggregateMetrics } from "../core/metrics.js";
|
| 6 |
import { ensureEmptyDir } from "./cache.js";
|
| 7 |
import { getSystemInfo } from "../core/sysinfo.js";
|
|
|
|
| 8 |
|
| 9 |
async function benchOnce(
|
| 10 |
modelId: string,
|
|
@@ -18,18 +19,18 @@ async function benchOnce(
|
|
| 18 |
const pipe = await pipeline(task, modelId, options);
|
| 19 |
const t1 = performance.now();
|
| 20 |
|
| 21 |
-
//
|
| 22 |
-
const inputs
|
| 23 |
|
| 24 |
const t2 = performance.now();
|
| 25 |
-
await pipe(inputs);
|
| 26 |
const t3 = performance.now();
|
| 27 |
|
| 28 |
// Run additional inferences to measure subsequent performance
|
| 29 |
const subsequentTimes: number[] = [];
|
| 30 |
for (let i = 0; i < 3; i++) {
|
| 31 |
const t4 = performance.now();
|
| 32 |
-
await pipe(inputs);
|
| 33 |
const t5 = performance.now();
|
| 34 |
subsequentTimes.push(+(t5 - t4).toFixed(1));
|
| 35 |
}
|
|
@@ -63,8 +64,8 @@ export async function runNodeBenchmark(options: BenchmarkOptions): Promise<Bench
|
|
| 63 |
const warmOptions: any = {};
|
| 64 |
if (dtype) warmOptions.dtype = dtype;
|
| 65 |
const warm = await pipeline(task, modelId, warmOptions);
|
| 66 |
-
const warmupInputs =
|
| 67 |
-
await warm(warmupInputs);
|
| 68 |
|
| 69 |
for (let i = 0; i < repeats; i++) {
|
| 70 |
const r = await benchOnce(modelId, task, dtype, batchSize);
|
|
|
|
| 5 |
import { BenchmarkRawResult, aggregateMetrics } from "../core/metrics.js";
|
| 6 |
import { ensureEmptyDir } from "./cache.js";
|
| 7 |
import { getSystemInfo } from "../core/sysinfo.js";
|
| 8 |
+
import { getTaskInput } from "../core/task-inputs.js";
|
| 9 |
|
| 10 |
async function benchOnce(
|
| 11 |
modelId: string,
|
|
|
|
| 19 |
const pipe = await pipeline(task, modelId, options);
|
| 20 |
const t1 = performance.now();
|
| 21 |
|
| 22 |
+
// Get task-appropriate input
|
| 23 |
+
const { inputs, options: taskOptions } = getTaskInput(task, batchSize);
|
| 24 |
|
| 25 |
const t2 = performance.now();
|
| 26 |
+
await pipe(inputs, taskOptions);
|
| 27 |
const t3 = performance.now();
|
| 28 |
|
| 29 |
// Run additional inferences to measure subsequent performance
|
| 30 |
const subsequentTimes: number[] = [];
|
| 31 |
for (let i = 0; i < 3; i++) {
|
| 32 |
const t4 = performance.now();
|
| 33 |
+
await pipe(inputs, taskOptions);
|
| 34 |
const t5 = performance.now();
|
| 35 |
subsequentTimes.push(+(t5 - t4).toFixed(1));
|
| 36 |
}
|
|
|
|
| 64 |
const warmOptions: any = {};
|
| 65 |
if (dtype) warmOptions.dtype = dtype;
|
| 66 |
const warm = await pipeline(task, modelId, warmOptions);
|
| 67 |
+
const { inputs: warmupInputs, options: taskOptions } = getTaskInput(task, batchSize);
|
| 68 |
+
await warm(warmupInputs, taskOptions);
|
| 69 |
|
| 70 |
for (let i = 0; i < repeats; i++) {
|
| 71 |
const r = await benchOnce(modelId, task, dtype, batchSize);
|
bench/src/web/benchmark.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { BenchmarkRawResult, aggregateMetrics } from "../core/metrics.js";
|
|
| 3 |
import { BenchmarkResult } from "../core/types.js";
|
| 4 |
import { clearCaches } from "./cache.js";
|
| 5 |
import { getBrowserEnvInfo } from "./envinfo.js";
|
|
|
|
| 6 |
|
| 7 |
function now() {
|
| 8 |
return performance.now();
|
|
@@ -22,18 +23,18 @@ async function benchOnce(
|
|
| 22 |
const pipe = await pipeline(task, modelId, options);
|
| 23 |
const t1 = now();
|
| 24 |
|
| 25 |
-
//
|
| 26 |
-
const inputs
|
| 27 |
|
| 28 |
const t2 = now();
|
| 29 |
-
await pipe(inputs);
|
| 30 |
const t3 = now();
|
| 31 |
|
| 32 |
// Run additional inferences to measure subsequent performance
|
| 33 |
const subsequentTimes: number[] = [];
|
| 34 |
for (let i = 0; i < 3; i++) {
|
| 35 |
const t4 = now();
|
| 36 |
-
await pipe(inputs);
|
| 37 |
const t5 = now();
|
| 38 |
subsequentTimes.push(+(t5 - t4).toFixed(1));
|
| 39 |
}
|
|
@@ -128,8 +129,8 @@ export async function runWebBenchmarkWarm(
|
|
| 128 |
const options: any = { device };
|
| 129 |
if (dtype) options.dtype = dtype;
|
| 130 |
const p = await pipeline(task, modelId, options);
|
| 131 |
-
const warmupInputs =
|
| 132 |
-
await p(warmupInputs);
|
| 133 |
} catch (err: any) {
|
| 134 |
const errorMessage = err?.message || String(err);
|
| 135 |
let errorType = "runtime_error";
|
|
|
|
| 3 |
import { BenchmarkResult } from "../core/types.js";
|
| 4 |
import { clearCaches } from "./cache.js";
|
| 5 |
import { getBrowserEnvInfo } from "./envinfo.js";
|
| 6 |
+
import { getTaskInput } from "../core/task-inputs.js";
|
| 7 |
|
| 8 |
function now() {
|
| 9 |
return performance.now();
|
|
|
|
| 23 |
const pipe = await pipeline(task, modelId, options);
|
| 24 |
const t1 = now();
|
| 25 |
|
| 26 |
+
// Get task-appropriate input
|
| 27 |
+
const { inputs, options: taskOptions } = getTaskInput(task, batchSize);
|
| 28 |
|
| 29 |
const t2 = now();
|
| 30 |
+
await pipe(inputs, taskOptions);
|
| 31 |
const t3 = now();
|
| 32 |
|
| 33 |
// Run additional inferences to measure subsequent performance
|
| 34 |
const subsequentTimes: number[] = [];
|
| 35 |
for (let i = 0; i < 3; i++) {
|
| 36 |
const t4 = now();
|
| 37 |
+
await pipe(inputs, taskOptions);
|
| 38 |
const t5 = now();
|
| 39 |
subsequentTimes.push(+(t5 - t4).toFixed(1));
|
| 40 |
}
|
|
|
|
| 129 |
const options: any = { device };
|
| 130 |
if (dtype) options.dtype = dtype;
|
| 131 |
const p = await pipeline(task, modelId, options);
|
| 132 |
+
const { inputs: warmupInputs, options: taskOptions } = getTaskInput(task, batchSize);
|
| 133 |
+
await p(warmupInputs, taskOptions);
|
| 134 |
} catch (err: any) {
|
| 135 |
const errorMessage = err?.message || String(err);
|
| 136 |
let errorType = "runtime_error";
|