From 8f242dcafa1ed8a3886a447ba2500704f1b16147 Mon Sep 17 00:00:00 2001 From: coyotte508 Date: Fri, 3 May 2024 14:29:43 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9E=95=20Add=20@huggingface/tasks=20as?= =?UTF-8?q?=20a=20dep=20of=20@huggingface/inference?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only for TS types. Later let's do it without, cc https://github.com/huggingface/huggingface.js/issues/584#issuecomment-2022180989 --- packages/inference/package.json | 4 +- .../inference/src/tasks/nlp/textGeneration.ts | 204 +----------------- .../src/tasks/nlp/textGenerationStream.ts | 2 +- 3 files changed, 5 insertions(+), 205 deletions(-) diff --git a/packages/inference/package.json b/packages/inference/package.json index e01f556eeb..d14c285a57 100644 --- a/packages/inference/package.json +++ b/packages/inference/package.json @@ -51,8 +51,10 @@ "test:browser": "vitest run --browser.name=chrome --browser.headless --config vitest.config.mts", "check": "tsc" }, + "dependencies": { + "@huggingface/tasks": "workspace:^" + }, "devDependencies": { - "@huggingface/tasks": "workspace:^", "@types/node": "18.13.0" }, "resolutions": {} diff --git a/packages/inference/src/tasks/nlp/textGeneration.ts b/packages/inference/src/tasks/nlp/textGeneration.ts index 72a671c07c..df64af67fd 100644 --- a/packages/inference/src/tasks/nlp/textGeneration.ts +++ b/packages/inference/src/tasks/nlp/textGeneration.ts @@ -1,210 +1,8 @@ +import type { TextGenerationInput, TextGenerationOutput } from "@huggingface/tasks"; import { InferenceOutputError } from "../../lib/InferenceOutputError"; import type { BaseArgs, Options } from "../../types"; import { request } from "../custom/request"; -/** - * Inputs for Text Generation inference - */ -export interface TextGenerationInput { - /** - * The text to initialize generation with - */ - inputs: string; - /** - * Additional inference parameters - */ - parameters?: TextGenerationParameters; - /** - * Whether to stream output tokens - */ - stream?: boolean; - [property: string]: unknown; -} - -/** - * Additional inference parameters - * - * Additional inference parameters for Text Generation - */ -export interface TextGenerationParameters { - /** - * The number of sampling queries to run. Only the best one (in terms of total logprob) will - * be returned. - */ - best_of?: number; - /** - * Whether or not to output decoder input details - */ - decoder_input_details?: boolean; - /** - * Whether or not to output details - */ - details?: boolean; - /** - * Whether to use logits sampling instead of greedy decoding when generating new tokens. - */ - do_sample?: boolean; - /** - * The maximum number of tokens to generate. - */ - max_new_tokens?: number; - /** - * The parameter for repetition penalty. A value of 1.0 means no penalty. See [this - * paper](https://hf.co/papers/1909.05858) for more details. - */ - repetition_penalty?: number; - /** - * Whether to prepend the prompt to the generated text. - */ - return_full_text?: boolean; - /** - * The random sampling seed. - */ - seed?: number; - /** - * Stop generating tokens if a member of `stop_sequences` is generated. - */ - stop_sequences?: string[]; - /** - * The value used to modulate the logits distribution. - */ - temperature?: number; - /** - * The number of highest probability vocabulary tokens to keep for top-k-filtering. - */ - top_k?: number; - /** - * If set to < 1, only the smallest set of most probable tokens with probabilities that add - * up to `top_p` or higher are kept for generation. - */ - top_p?: number; - /** - * Truncate input tokens to the given size. - */ - truncate?: number; - /** - * Typical Decoding mass. See [Typical Decoding for Natural Language - * Generation](https://hf.co/papers/2202.00666) for more information - */ - typical_p?: number; - /** - * Watermarking with [A Watermark for Large Language Models](https://hf.co/papers/2301.10226) - */ - watermark?: boolean; - [property: string]: unknown; -} - -/** - * Outputs for Text Generation inference - */ -export interface TextGenerationOutput { - /** - * When enabled, details about the generation - */ - details?: TextGenerationOutputDetails; - /** - * The generated text - */ - generated_text: string; - [property: string]: unknown; -} - -/** - * When enabled, details about the generation - */ -export interface TextGenerationOutputDetails { - /** - * Details about additional sequences when best_of is provided - */ - best_of_sequences?: TextGenerationOutputSequenceDetails[]; - /** - * The reason why the generation was stopped. - */ - finish_reason: TextGenerationFinishReason; - /** - * The number of generated tokens - */ - generated_tokens: number; - prefill: TextGenerationPrefillToken[]; - /** - * The random seed used for generation - */ - seed?: number; - /** - * The generated tokens and associated details - */ - tokens: TextGenerationOutputToken[]; - /** - * Most likely tokens - */ - top_tokens?: Array; - [property: string]: unknown; -} - -export interface TextGenerationOutputSequenceDetails { - finish_reason: TextGenerationFinishReason; - /** - * The generated text - */ - generated_text: string; - /** - * The number of generated tokens - */ - generated_tokens: number; - prefill: TextGenerationPrefillToken[]; - /** - * The random seed used for generation - */ - seed?: number; - /** - * The generated tokens and associated details - */ - tokens: TextGenerationOutputToken[]; - /** - * Most likely tokens - */ - top_tokens?: Array; - [property: string]: unknown; -} - -export interface TextGenerationPrefillToken { - id: number; - logprob: number; - /** - * The text associated with that token - */ - text: string; - [property: string]: unknown; -} - -/** - * Generated token. - */ -export interface TextGenerationOutputToken { - id: number; - logprob?: number; - /** - * Whether or not that token is a special one - */ - special: boolean; - /** - * The text associated with that token - */ - text: string; - [property: string]: unknown; -} - -/** - * The reason why the generation was stopped. - * - * length: The generated sequence reached the maximum allowed length - * - * eos_token: The model generated an end-of-sentence (EOS) token - * - * stop_sequence: One of the sequence in stop_sequences was generated - */ -export type TextGenerationFinishReason = "length" | "eos_token" | "stop_sequence"; - /** * Use to continue text from a prompt. This is a very generic task. Recommended model: gpt2 (it’s a simple model, but fun to play with). */ diff --git a/packages/inference/src/tasks/nlp/textGenerationStream.ts b/packages/inference/src/tasks/nlp/textGenerationStream.ts index 827083fcf8..f935bc34e8 100644 --- a/packages/inference/src/tasks/nlp/textGenerationStream.ts +++ b/packages/inference/src/tasks/nlp/textGenerationStream.ts @@ -1,6 +1,6 @@ +import type { TextGenerationInput } from "@huggingface/tasks"; import type { BaseArgs, Options } from "../../types"; import { streamingRequest } from "../custom/streamingRequest"; -import type { TextGenerationInput } from "./textGeneration"; export interface TextGenerationStreamToken { /** Token ID from the model tokenizer */ From 95fb7ba7ba87c860b3dac8aa88dcb68ab93af84a Mon Sep 17 00:00:00 2001 From: coyotte508 Date: Fri, 3 May 2024 14:31:05 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=91=B7=20Add=20CI=20check=20that=20ta?= =?UTF-8?q?sks=20is=20published?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/inference-publish.yml | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/.github/workflows/inference-publish.yml b/.github/workflows/inference-publish.yml index bbf0a9c0f9..5ba3876456 100644 --- a/.github/workflows/inference-publish.yml +++ b/.github/workflows/inference-publish.yml @@ -52,6 +52,44 @@ jobs: git add ../.. git commit -m "🔖 @hugginface/inference $BUMPED_VERSION" git tag "inference-v$BUMPED_VERSION" + + - name: Make sure that the latest version of @huggingface/tasks is consistent with the local version + run: | + LOCAL_TASKS_VERSION=$(node -p "require('./package.json').version") + REMOTE_TASKS_VERSION=$(npm view @huggingface/tasks version) + + # If the versions are different, error + if [ "$LOCAL_TASKS_VERSION" != "$REMOTE_TASKS_VERSION" ]; then + echo "Error: The local @huggingface/tasks package version ($LOCAL_TASKS_VERSION) differs from the remote version ($REMOTE_TASKS_VERSION). Release halted." + exit 1 + fi + + npm pack @huggingface/tasks + mv huggingface-tasks-$LOCAL_TASKS_VERSION.tgz tasks-local.tgz + + npm pack @huggingface/tasks@$REMOTE_TASKS_VERSION + mv huggingface-tasks-$REMOTE_TASKS_VERSION.tgz tasks-remote.tgz + + # Compute checksum of local tar. We need to extract both tar since the remote compression might be different + tar -xf tasks-local.tgz + LOCAL_CHECKSUM=$(cd package && tar --mtime='1970-01-01' --mode=755 -cf - . | sha256sum | cut -d' ' -f1) + echo "Local package checksum: $LOCAL_CHECKSUM" + + rm -Rf package + + tar -xf tasks-remote.tgz + REMOTE_CHECKSUM=$(cd package && tar --mtime='1970-01-01' --mode=755 -cf - . | sha256sum | cut -d' ' -f1) + echo "Remote package checksum: $REMOTE_CHECKSUM" + + rm -Rf package + + if [ "$LOCAL_CHECKSUM" != "$REMOTE_CHECKSUM" ]; then + echo "Checksum Verification Failed: The local @huggingface/tasks package differs from the remote version. Release halted. Local Checksum: $LOCAL_CHECKSUM, Remote Checksum: $REMOTE_CHECKSUM" + exit 1 + fi + echo "Checksum Verification Successful: The local and remote @huggingface/tasks packages are consistent. Proceeding with the @huggingface/widgets package release. Local Checksum: $LOCAL_CHECKSUM, Remote Checksum: $REMOTE_CHECKSUM." + working-directory: packages/tasks + - run: pnpm publish --no-git-checks . env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} From 7059f5fca3d5534b1ad085e6e9db5f3909196987 Mon Sep 17 00:00:00 2001 From: coyotte508 Date: Fri, 3 May 2024 14:32:28 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=94=A7=20Reexport=20helper=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/inference/src/tasks/nlp/textGeneration.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/inference/src/tasks/nlp/textGeneration.ts b/packages/inference/src/tasks/nlp/textGeneration.ts index df64af67fd..cf6f30ab10 100644 --- a/packages/inference/src/tasks/nlp/textGeneration.ts +++ b/packages/inference/src/tasks/nlp/textGeneration.ts @@ -3,6 +3,8 @@ import { InferenceOutputError } from "../../lib/InferenceOutputError"; import type { BaseArgs, Options } from "../../types"; import { request } from "../custom/request"; +export type { TextGenerationInput, TextGenerationOutput }; + /** * Use to continue text from a prompt. This is a very generic task. Recommended model: gpt2 (it’s a simple model, but fun to play with). */ From b1f0555081cb47980956facc740ca122619e6a06 Mon Sep 17 00:00:00 2001 From: coyotte508 Date: Fri, 3 May 2024 14:33:29 +0200 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=93=A6=20Update=20lockfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/inference/pnpm-lock.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/inference/pnpm-lock.yaml b/packages/inference/pnpm-lock.yaml index ff6f90f72f..5bb56da2d1 100644 --- a/packages/inference/pnpm-lock.yaml +++ b/packages/inference/pnpm-lock.yaml @@ -4,10 +4,12 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -devDependencies: +dependencies: '@huggingface/tasks': specifier: workspace:^ version: link:../tasks + +devDependencies: '@types/node': specifier: 18.13.0 version: 18.13.0 From 08f339141fd8208889b0cc72cefaff00bb13c800 Mon Sep 17 00:00:00 2001 From: coyotte508 Date: Fri, 3 May 2024 15:46:17 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=91=B7=20Also=20publish=20tasks=20in?= =?UTF-8?q?=20the=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 158851022d..99df0df100 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,7 +59,7 @@ jobs: run: | sleep 3 pnpm i --filter inference... --filter hub... --frozen-lockfile - pnpm --filter inference --filter hub publish --force --no-git-checks --registry http://localhost:4874/ + pnpm --filter inference --filter hub --filter tasks publish --force --no-git-checks --registry http://localhost:4874/ - name: E2E test - test yarn install working-directory: e2e/ts From 04ded1bf5de952e19ba3e1ea63a40e8f107707fc Mon Sep 17 00:00:00 2001 From: coyotte508 Date: Fri, 3 May 2024 16:25:22 +0200 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=91=B7=20Update=20generate-dts=20to?= =?UTF-8?q?=20import=20tasks=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/inference/package.json | 2 +- packages/inference/scripts/generate-dts.ts | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/inference/package.json b/packages/inference/package.json index d14c285a57..a5a26d1026 100644 --- a/packages/inference/package.json +++ b/packages/inference/package.json @@ -40,7 +40,7 @@ "type": "module", "scripts": { "build": "tsup src/index.ts --format cjs,esm --clean && pnpm run dts", - "dts": "tsx scripts/generate-dts.ts", + "dts": "tsx scripts/generate-dts.ts && tsc --noEmit dist/index.d.ts", "lint": "eslint --quiet --fix --ext .cjs,.ts .", "lint:check": "eslint --ext .cjs,.ts .", "format": "prettier --write .", diff --git a/packages/inference/scripts/generate-dts.ts b/packages/inference/scripts/generate-dts.ts index 82b732e85d..35427d5236 100644 --- a/packages/inference/scripts/generate-dts.ts +++ b/packages/inference/scripts/generate-dts.ts @@ -3,6 +3,8 @@ import { readFileSync, writeFileSync, appendFileSync, readdirSync } from "node:fs"; import { TASKS_DATA } from "@huggingface/tasks"; +const taskImports = new Set(); + const tasks = Object.keys(TASKS_DATA) .sort() .filter((task) => task !== "other"); @@ -36,6 +38,16 @@ for (const dir of dirs) { const fileContent = readFileSync(`./src/tasks/${dir}/${file}`, "utf-8"); + // detect imports from @huggingface/tasks + for (const imports of fileContent.matchAll(/import type {(.*)} from "@huggingface\/tasks";/g)) { + // Convert A, B, C to ["A", "B", "C"] + const imported = imports[1].split(",").map((x) => x.trim()); + + for (const imp of imported) { + taskImports.add(imp); + } + } + for (const type of extractTypesAndInterfaces(fileContent)) { appendFileSync("./dist/index.d.ts", type + "\n"); } @@ -87,6 +99,13 @@ appendFileSync( "\n}\n" ); +// Prepend import from @huggingface/tasks +writeFileSync( + "./dist/index.d.ts", + `import type { ${[...taskImports].join(", ")} } from "@huggingface/tasks";\n` + + readFileSync("./dist/index.d.ts", "utf-8") +); + function* extractTypesAndInterfaces(fileContent: string): Iterable { let index = 0;