Spaces:
Runtime error
Runtime error
Batch command
Browse files- client/.env.example +8 -0
- client/.gitignore +2 -0
- client/package-lock.json +106 -0
- client/package.json +4 -0
- client/src/hf-api.ts +65 -0
- client/src/index.ts +182 -0
client/.env.example
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# HuggingFace API Token (optional)
|
| 2 |
+
# Get your token from https://huggingface.co/settings/tokens
|
| 3 |
+
# Required for accessing private models or higher API rate limits
|
| 4 |
+
HF_TOKEN=your_token_here
|
| 5 |
+
|
| 6 |
+
# Benchmark Server URL (optional)
|
| 7 |
+
# Default: http://localhost:7860
|
| 8 |
+
BENCH_SERVER_URL=http://localhost:7860
|
client/.gitignore
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
node_modules/
|
| 2 |
+
.env
|
client/package-lock.json
CHANGED
|
@@ -8,6 +8,10 @@
|
|
| 8 |
"name": "client",
|
| 9 |
"version": "0.0.1",
|
| 10 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
"table": "^6.9.0",
|
| 12 |
"yargs": "^17.7.2"
|
| 13 |
},
|
|
@@ -459,6 +463,49 @@
|
|
| 459 |
"node": ">=18"
|
| 460 |
}
|
| 461 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 462 |
"node_modules/@types/yargs": {
|
| 463 |
"version": "17.0.33",
|
| 464 |
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
|
@@ -525,6 +572,19 @@
|
|
| 525 |
"node": ">=8"
|
| 526 |
}
|
| 527 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 528 |
"node_modules/cliui": {
|
| 529 |
"version": "8.0.1",
|
| 530 |
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
|
@@ -557,6 +617,18 @@
|
|
| 557 |
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
| 558 |
"license": "MIT"
|
| 559 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 560 |
"node_modules/emoji-regex": {
|
| 561 |
"version": "8.0.0",
|
| 562 |
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
|
@@ -688,12 +760,34 @@
|
|
| 688 |
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
| 689 |
"license": "MIT"
|
| 690 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 691 |
"node_modules/lodash.truncate": {
|
| 692 |
"version": "4.4.2",
|
| 693 |
"resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
|
| 694 |
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
|
| 695 |
"license": "MIT"
|
| 696 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 697 |
"node_modules/require-directory": {
|
| 698 |
"version": "2.1.1",
|
| 699 |
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
|
@@ -722,6 +816,12 @@
|
|
| 722 |
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
| 723 |
}
|
| 724 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 725 |
"node_modules/slice-ansi": {
|
| 726 |
"version": "4.0.0",
|
| 727 |
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
|
|
@@ -815,6 +915,12 @@
|
|
| 815 |
"node": ">=14.17"
|
| 816 |
}
|
| 817 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 818 |
"node_modules/wrap-ansi": {
|
| 819 |
"version": "7.0.0",
|
| 820 |
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
|
|
|
| 8 |
"name": "client",
|
| 9 |
"version": "0.0.1",
|
| 10 |
"dependencies": {
|
| 11 |
+
"@huggingface/hub": "^2.6.12",
|
| 12 |
+
"@types/prompts": "^2.4.9",
|
| 13 |
+
"dotenv": "^17.2.3",
|
| 14 |
+
"prompts": "^2.4.2",
|
| 15 |
"table": "^6.9.0",
|
| 16 |
"yargs": "^17.7.2"
|
| 17 |
},
|
|
|
|
| 463 |
"node": ">=18"
|
| 464 |
}
|
| 465 |
},
|
| 466 |
+
"node_modules/@huggingface/hub": {
|
| 467 |
+
"version": "2.6.12",
|
| 468 |
+
"resolved": "https://registry.npmjs.org/@huggingface/hub/-/hub-2.6.12.tgz",
|
| 469 |
+
"integrity": "sha512-/AZN2LAtrt4B8S83/Ru4wMorHY4NPwIYXo60SkuD6c/Mr135t1UqffD1vqcqtDYVf0hhLiyVmm1LMU1CXi8iKQ==",
|
| 470 |
+
"license": "MIT",
|
| 471 |
+
"dependencies": {
|
| 472 |
+
"@huggingface/tasks": "^0.19.50"
|
| 473 |
+
},
|
| 474 |
+
"bin": {
|
| 475 |
+
"hfjs": "dist/cli.js"
|
| 476 |
+
},
|
| 477 |
+
"engines": {
|
| 478 |
+
"node": ">=18"
|
| 479 |
+
},
|
| 480 |
+
"optionalDependencies": {
|
| 481 |
+
"cli-progress": "^3.12.0"
|
| 482 |
+
}
|
| 483 |
+
},
|
| 484 |
+
"node_modules/@huggingface/tasks": {
|
| 485 |
+
"version": "0.19.50",
|
| 486 |
+
"resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.19.50.tgz",
|
| 487 |
+
"integrity": "sha512-kHrfiDsJttkuwpdp7PgFiFHaK9rj+COJTIZ+221gk9vdF4B5QySW7hQT4aOGkwwZP+4qbXGhjMNGg/bxOq+LwA==",
|
| 488 |
+
"license": "MIT"
|
| 489 |
+
},
|
| 490 |
+
"node_modules/@types/node": {
|
| 491 |
+
"version": "24.7.2",
|
| 492 |
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.2.tgz",
|
| 493 |
+
"integrity": "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==",
|
| 494 |
+
"license": "MIT",
|
| 495 |
+
"dependencies": {
|
| 496 |
+
"undici-types": "~7.14.0"
|
| 497 |
+
}
|
| 498 |
+
},
|
| 499 |
+
"node_modules/@types/prompts": {
|
| 500 |
+
"version": "2.4.9",
|
| 501 |
+
"resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.9.tgz",
|
| 502 |
+
"integrity": "sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==",
|
| 503 |
+
"license": "MIT",
|
| 504 |
+
"dependencies": {
|
| 505 |
+
"@types/node": "*",
|
| 506 |
+
"kleur": "^3.0.3"
|
| 507 |
+
}
|
| 508 |
+
},
|
| 509 |
"node_modules/@types/yargs": {
|
| 510 |
"version": "17.0.33",
|
| 511 |
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
|
|
|
| 572 |
"node": ">=8"
|
| 573 |
}
|
| 574 |
},
|
| 575 |
+
"node_modules/cli-progress": {
|
| 576 |
+
"version": "3.12.0",
|
| 577 |
+
"resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz",
|
| 578 |
+
"integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==",
|
| 579 |
+
"license": "MIT",
|
| 580 |
+
"optional": true,
|
| 581 |
+
"dependencies": {
|
| 582 |
+
"string-width": "^4.2.3"
|
| 583 |
+
},
|
| 584 |
+
"engines": {
|
| 585 |
+
"node": ">=4"
|
| 586 |
+
}
|
| 587 |
+
},
|
| 588 |
"node_modules/cliui": {
|
| 589 |
"version": "8.0.1",
|
| 590 |
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
|
|
|
| 617 |
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
| 618 |
"license": "MIT"
|
| 619 |
},
|
| 620 |
+
"node_modules/dotenv": {
|
| 621 |
+
"version": "17.2.3",
|
| 622 |
+
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
|
| 623 |
+
"integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
|
| 624 |
+
"license": "BSD-2-Clause",
|
| 625 |
+
"engines": {
|
| 626 |
+
"node": ">=12"
|
| 627 |
+
},
|
| 628 |
+
"funding": {
|
| 629 |
+
"url": "https://dotenvx.com"
|
| 630 |
+
}
|
| 631 |
+
},
|
| 632 |
"node_modules/emoji-regex": {
|
| 633 |
"version": "8.0.0",
|
| 634 |
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
|
|
|
| 760 |
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
| 761 |
"license": "MIT"
|
| 762 |
},
|
| 763 |
+
"node_modules/kleur": {
|
| 764 |
+
"version": "3.0.3",
|
| 765 |
+
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
| 766 |
+
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
| 767 |
+
"license": "MIT",
|
| 768 |
+
"engines": {
|
| 769 |
+
"node": ">=6"
|
| 770 |
+
}
|
| 771 |
+
},
|
| 772 |
"node_modules/lodash.truncate": {
|
| 773 |
"version": "4.4.2",
|
| 774 |
"resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
|
| 775 |
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
|
| 776 |
"license": "MIT"
|
| 777 |
},
|
| 778 |
+
"node_modules/prompts": {
|
| 779 |
+
"version": "2.4.2",
|
| 780 |
+
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
|
| 781 |
+
"integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
|
| 782 |
+
"license": "MIT",
|
| 783 |
+
"dependencies": {
|
| 784 |
+
"kleur": "^3.0.3",
|
| 785 |
+
"sisteransi": "^1.0.5"
|
| 786 |
+
},
|
| 787 |
+
"engines": {
|
| 788 |
+
"node": ">= 6"
|
| 789 |
+
}
|
| 790 |
+
},
|
| 791 |
"node_modules/require-directory": {
|
| 792 |
"version": "2.1.1",
|
| 793 |
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
|
|
|
| 816 |
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
| 817 |
}
|
| 818 |
},
|
| 819 |
+
"node_modules/sisteransi": {
|
| 820 |
+
"version": "1.0.5",
|
| 821 |
+
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
| 822 |
+
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
|
| 823 |
+
"license": "MIT"
|
| 824 |
+
},
|
| 825 |
"node_modules/slice-ansi": {
|
| 826 |
"version": "4.0.0",
|
| 827 |
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
|
|
|
|
| 915 |
"node": ">=14.17"
|
| 916 |
}
|
| 917 |
},
|
| 918 |
+
"node_modules/undici-types": {
|
| 919 |
+
"version": "7.14.0",
|
| 920 |
+
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz",
|
| 921 |
+
"integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==",
|
| 922 |
+
"license": "MIT"
|
| 923 |
+
},
|
| 924 |
"node_modules/wrap-ansi": {
|
| 925 |
"version": "7.0.0",
|
| 926 |
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
client/package.json
CHANGED
|
@@ -7,6 +7,10 @@
|
|
| 7 |
"cli": "tsx src/index.ts"
|
| 8 |
},
|
| 9 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
"table": "^6.9.0",
|
| 11 |
"yargs": "^17.7.2"
|
| 12 |
},
|
|
|
|
| 7 |
"cli": "tsx src/index.ts"
|
| 8 |
},
|
| 9 |
"dependencies": {
|
| 10 |
+
"@huggingface/hub": "^2.6.12",
|
| 11 |
+
"@types/prompts": "^2.4.9",
|
| 12 |
+
"dotenv": "^17.2.3",
|
| 13 |
+
"prompts": "^2.4.2",
|
| 14 |
"table": "^6.9.0",
|
| 15 |
"yargs": "^17.7.2"
|
| 16 |
},
|
client/src/hf-api.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* Hugging Face API Client
|
| 3 |
+
*
|
| 4 |
+
* Uses the official @huggingface/hub library to search and retrieve models
|
| 5 |
+
*/
|
| 6 |
+
|
| 7 |
+
import { listModels } from "@huggingface/hub";
|
| 8 |
+
import type { ModelEntry, PipelineType } from "@huggingface/hub";
|
| 9 |
+
import { config as dotenvConfig } from "dotenv";
|
| 10 |
+
|
| 11 |
+
// Load environment variables from .env file
|
| 12 |
+
dotenvConfig();
|
| 13 |
+
|
| 14 |
+
export interface SearchModelsOptions {
|
| 15 |
+
task?: PipelineType;
|
| 16 |
+
search?: string;
|
| 17 |
+
limit?: number;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
/**
|
| 21 |
+
* Search models on Hugging Face Hub
|
| 22 |
+
*/
|
| 23 |
+
export async function searchModels(options: SearchModelsOptions = {}): Promise<ModelEntry[]> {
|
| 24 |
+
const { task, search, limit } = options;
|
| 25 |
+
|
| 26 |
+
const resultGenerator = listModels({
|
| 27 |
+
search: {
|
| 28 |
+
task: task,
|
| 29 |
+
query: search,
|
| 30 |
+
tags: ["transformers.js"]
|
| 31 |
+
},
|
| 32 |
+
limit: limit,
|
| 33 |
+
credentials: {
|
| 34 |
+
accessToken: process.env.HF_TOKEN,
|
| 35 |
+
},
|
| 36 |
+
});
|
| 37 |
+
|
| 38 |
+
const models: ModelEntry[] = [];
|
| 39 |
+
// Fetch models using the official HF Hub library
|
| 40 |
+
for await (const model of resultGenerator) {
|
| 41 |
+
// Filter out private and gated models
|
| 42 |
+
if (!model.private && !model.gated) {
|
| 43 |
+
models.push(model);
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
// Stop when we reach the limit (if specified)
|
| 47 |
+
if (limit !== undefined && models.length >= limit) {
|
| 48 |
+
break;
|
| 49 |
+
}
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
return models;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
/**
|
| 56 |
+
* Format model for display
|
| 57 |
+
*/
|
| 58 |
+
export function formatModel(model: ModelEntry): string {
|
| 59 |
+
const downloads = model.downloads ? `${(model.downloads / 1000).toFixed(1)}k` : "N/A";
|
| 60 |
+
const likes = model.likes || 0;
|
| 61 |
+
const task = model.task || "unknown";
|
| 62 |
+
const name = model.name || model.id;
|
| 63 |
+
|
| 64 |
+
return `${name} | Task: ${task} | Downloads: ${downloads} | Likes: ${likes}`;
|
| 65 |
+
}
|
client/src/index.ts
CHANGED
|
@@ -3,6 +3,9 @@
|
|
| 3 |
import yargs from "yargs";
|
| 4 |
import { hideBin } from "yargs/helpers";
|
| 5 |
import { table } from "table";
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
const SERVER_URL = process.env.BENCH_SERVER_URL || "http://localhost:7860";
|
| 8 |
|
|
@@ -264,6 +267,185 @@ yargs(hideBin(process.argv))
|
|
| 264 |
}
|
| 265 |
}
|
| 266 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 267 |
.demandCommand(1, "You need to specify a command")
|
| 268 |
.help()
|
| 269 |
.alias("h", "help")
|
|
|
|
| 3 |
import yargs from "yargs";
|
| 4 |
import { hideBin } from "yargs/helpers";
|
| 5 |
import { table } from "table";
|
| 6 |
+
import prompts from "prompts";
|
| 7 |
+
import { searchModels, formatModel } from "./hf-api.js";
|
| 8 |
+
import type { ModelEntry } from "@huggingface/hub";
|
| 9 |
|
| 10 |
const SERVER_URL = process.env.BENCH_SERVER_URL || "http://localhost:7860";
|
| 11 |
|
|
|
|
| 267 |
}
|
| 268 |
}
|
| 269 |
)
|
| 270 |
+
.command(
|
| 271 |
+
"batch <task> [query]",
|
| 272 |
+
"Search HuggingFace models and submit benchmarks for them",
|
| 273 |
+
(yargs) => {
|
| 274 |
+
return yargs
|
| 275 |
+
.positional("task", {
|
| 276 |
+
describe: "Task type (e.g., feature-extraction, text-classification, fill-mask)",
|
| 277 |
+
type: "string",
|
| 278 |
+
demandOption: true,
|
| 279 |
+
})
|
| 280 |
+
.positional("query", {
|
| 281 |
+
describe: "Optional search query to filter model names",
|
| 282 |
+
type: "string",
|
| 283 |
+
})
|
| 284 |
+
.option("limit", {
|
| 285 |
+
describe: "Maximum number of models to benchmark",
|
| 286 |
+
type: "number",
|
| 287 |
+
})
|
| 288 |
+
.option("sort", {
|
| 289 |
+
describe: "Sort models by",
|
| 290 |
+
choices: ["downloads", "likes", "lastModified", "trending"] as const,
|
| 291 |
+
default: "downloads" as const,
|
| 292 |
+
})
|
| 293 |
+
.option("platform", {
|
| 294 |
+
describe: "Platform(s) to run on (can specify multiple)",
|
| 295 |
+
type: "array",
|
| 296 |
+
default: ["node"],
|
| 297 |
+
})
|
| 298 |
+
.option("mode", {
|
| 299 |
+
describe: "Cache mode(s) (can specify multiple)",
|
| 300 |
+
type: "array",
|
| 301 |
+
default: ["warm"],
|
| 302 |
+
})
|
| 303 |
+
.option("repeats", {
|
| 304 |
+
describe: "Number of times to repeat the benchmark",
|
| 305 |
+
type: "number",
|
| 306 |
+
default: 3,
|
| 307 |
+
})
|
| 308 |
+
.option("batch-size", {
|
| 309 |
+
describe: "Batch size(s) for inference (can specify multiple)",
|
| 310 |
+
type: "array",
|
| 311 |
+
default: [1],
|
| 312 |
+
})
|
| 313 |
+
.option("device", {
|
| 314 |
+
describe: "Device(s) for platform (can specify multiple)",
|
| 315 |
+
type: "array",
|
| 316 |
+
default: ["webgpu"],
|
| 317 |
+
})
|
| 318 |
+
.option("browser", {
|
| 319 |
+
describe: "Browser(s) for web platform (can specify multiple)",
|
| 320 |
+
type: "array",
|
| 321 |
+
default: ["chromium"],
|
| 322 |
+
})
|
| 323 |
+
.option("yes", {
|
| 324 |
+
alias: "y",
|
| 325 |
+
describe: "Skip confirmation prompt",
|
| 326 |
+
type: "boolean",
|
| 327 |
+
default: false,
|
| 328 |
+
});
|
| 329 |
+
},
|
| 330 |
+
async (argv) => {
|
| 331 |
+
console.log(`Searching for ${argv.task} models${argv.query ? ` matching "${argv.query}"` : ""}...\n`);
|
| 332 |
+
|
| 333 |
+
const models = await searchModels({
|
| 334 |
+
task: argv.task,
|
| 335 |
+
search: argv.query,
|
| 336 |
+
limit: argv.limit,
|
| 337 |
+
sort: argv.sort,
|
| 338 |
+
});
|
| 339 |
+
|
| 340 |
+
if (models.length === 0) {
|
| 341 |
+
console.log("No models found.");
|
| 342 |
+
return;
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
console.log(`Found ${models.length} models:\n`);
|
| 346 |
+
models.forEach((model, index) => {
|
| 347 |
+
console.log(`${index + 1}. ${formatModel(model)}`);
|
| 348 |
+
});
|
| 349 |
+
|
| 350 |
+
// Generate all combinations
|
| 351 |
+
const platforms = argv.platform as string[];
|
| 352 |
+
const modes = argv.mode as string[];
|
| 353 |
+
const batchSizes = argv.batchSize as number[];
|
| 354 |
+
const devices = argv.device as string[];
|
| 355 |
+
const browsers = argv.browser as string[];
|
| 356 |
+
|
| 357 |
+
const combinations: Array<{
|
| 358 |
+
modelId: string;
|
| 359 |
+
platform: string;
|
| 360 |
+
mode: string;
|
| 361 |
+
batchSize: number;
|
| 362 |
+
device: string;
|
| 363 |
+
browser: string;
|
| 364 |
+
}> = [];
|
| 365 |
+
|
| 366 |
+
for (const model of models) {
|
| 367 |
+
for (const platform of platforms) {
|
| 368 |
+
for (const mode of modes) {
|
| 369 |
+
for (const batchSize of batchSizes) {
|
| 370 |
+
for (const device of devices) {
|
| 371 |
+
for (const browser of browsers) {
|
| 372 |
+
combinations.push({
|
| 373 |
+
modelId: (model as any).name || model.id,
|
| 374 |
+
platform,
|
| 375 |
+
mode,
|
| 376 |
+
batchSize,
|
| 377 |
+
device,
|
| 378 |
+
browser,
|
| 379 |
+
});
|
| 380 |
+
}
|
| 381 |
+
}
|
| 382 |
+
}
|
| 383 |
+
}
|
| 384 |
+
}
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
console.log(`\nπ Benchmark Plan:`);
|
| 388 |
+
console.log(` Models: ${models.length}`);
|
| 389 |
+
console.log(` Platforms: ${platforms.join(", ")}`);
|
| 390 |
+
console.log(` Modes: ${modes.join(", ")}`);
|
| 391 |
+
console.log(` Batch Sizes: ${batchSizes.join(", ")}`);
|
| 392 |
+
console.log(` Devices: ${devices.join(", ")}`);
|
| 393 |
+
console.log(` Browsers: ${browsers.join(", ")}`);
|
| 394 |
+
console.log(` Total benchmarks: ${combinations.length}`);
|
| 395 |
+
|
| 396 |
+
// Ask for confirmation unless -y flag is used
|
| 397 |
+
if (!argv.yes) {
|
| 398 |
+
const response = await prompts({
|
| 399 |
+
type: "confirm",
|
| 400 |
+
name: "proceed",
|
| 401 |
+
message: `Proceed with submitting ${combinations.length} benchmark(s)?`,
|
| 402 |
+
initial: true,
|
| 403 |
+
});
|
| 404 |
+
|
| 405 |
+
if (!response.proceed) {
|
| 406 |
+
console.log("\nCancelled.");
|
| 407 |
+
return;
|
| 408 |
+
}
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
console.log(`\nSubmitting ${combinations.length} benchmarks...`);
|
| 412 |
+
|
| 413 |
+
const submitted: string[] = [];
|
| 414 |
+
const failed: Array<{ combo: string; error: string }> = [];
|
| 415 |
+
|
| 416 |
+
for (const combo of combinations) {
|
| 417 |
+
try {
|
| 418 |
+
const options: SubmitOptions = {
|
| 419 |
+
modelId: combo.modelId,
|
| 420 |
+
task: argv.task,
|
| 421 |
+
platform: combo.platform as "node" | "web",
|
| 422 |
+
mode: combo.mode as "warm" | "cold",
|
| 423 |
+
repeats: argv.repeats,
|
| 424 |
+
batchSize: combo.batchSize,
|
| 425 |
+
device: combo.device,
|
| 426 |
+
browser: combo.browser as "chromium" | "firefox" | "webkit",
|
| 427 |
+
};
|
| 428 |
+
|
| 429 |
+
const result = await submitBenchmark(options);
|
| 430 |
+
const desc = `${combo.modelId} [${combo.platform}/${combo.device}/${combo.mode}/b${combo.batchSize}]`;
|
| 431 |
+
submitted.push(desc);
|
| 432 |
+
console.log(`β Queued: ${desc} (${result.id})`);
|
| 433 |
+
} catch (error: any) {
|
| 434 |
+
const desc = `${combo.modelId} [${combo.platform}/${combo.device}]`;
|
| 435 |
+
failed.push({ combo: desc, error: error.message });
|
| 436 |
+
console.log(`β Failed: ${desc} - ${error.message}`);
|
| 437 |
+
}
|
| 438 |
+
}
|
| 439 |
+
|
| 440 |
+
console.log(`\nπ Summary:`);
|
| 441 |
+
console.log(` β Submitted: ${submitted.length}`);
|
| 442 |
+
console.log(` β Failed: ${failed.length}`);
|
| 443 |
+
|
| 444 |
+
if (submitted.length > 0) {
|
| 445 |
+
console.log(`\nCheck status with: bench-client queue`);
|
| 446 |
+
}
|
| 447 |
+
}
|
| 448 |
+
)
|
| 449 |
.demandCommand(1, "You need to specify a command")
|
| 450 |
.help()
|
| 451 |
.alias("h", "help")
|