@fgv/ts-extras-transformers 5.1.0-30 → 5.1.0-31
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/.rush/temp/{cd93d90e14a92e09f4170d920f4cb801515f627b.tar.log → 68c2ac21917fe0732986270e7582d872fc12e9b8.tar.log} +2 -2
- package/.rush/temp/chunked-rush-logs/ts-extras-transformers.build.chunks.jsonl +2 -2
- package/.rush/temp/operation/build/all.log +2 -2
- package/.rush/temp/operation/build/log-chunks.jsonl +2 -2
- package/.rush/temp/operation/build/state.json +1 -1
- package/dist/index.js +27 -3
- package/dist/index.js.map +1 -1
- package/dist/test/unit/transformers.test.js +38 -1
- package/dist/test/unit/transformers.test.js.map +1 -1
- package/dist/ts-extras-transformers.d.ts +32 -3
- package/etc/ts-extras-transformers.api.md +9 -0
- package/lib/index.d.ts +27 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +28 -3
- package/lib/index.js.map +1 -1
- package/lib/test/unit/transformers.test.js +37 -0
- package/lib/test/unit/transformers.test.js.map +1 -1
- package/package.json +5 -5
- package/rush-logs/ts-extras-transformers.build.cache.log +1 -1
- package/rush-logs/ts-extras-transformers.build.log +2 -2
- package/src/index.ts +36 -3
- package/src/test/unit/transformers.test.ts +53 -0
- package/temp/build/lint/_eslint-5eVG3S6w.json +2 -2
- package/temp/build/typescript/ts_8nwakTlr.json +1 -1
- package/temp/ts-extras-transformers.api.json +116 -1
- package/temp/ts-extras-transformers.api.md +9 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
Start time:
|
|
2
|
-
Invoking "/usr/bin/tar -c -f /home/runner/work/fgv/fgv/common/temp/build-cache/
|
|
1
|
+
Start time: Tue May 26 2026 04:54:58 GMT+0000 (Coordinated Universal Time)
|
|
2
|
+
Invoking "/usr/bin/tar -c -f /home/runner/work/fgv/fgv/common/temp/build-cache/68c2ac21917fe0732986270e7582d872fc12e9b8-502b68d4c5d1194b.temp -z --files-from=-"
|
|
3
3
|
|
|
4
4
|
======= BEGIN PROCESS INPUT ======
|
|
5
5
|
.rush/temp/operation/build/all.log
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
{"kind":"O","text":"[build:lint] Using ESLint version 9.39.4\n"}
|
|
6
6
|
{"kind":"O","text":"[build:api-extractor] Using API Extractor version 7.58.7\n"}
|
|
7
7
|
{"kind":"O","text":"[build:api-extractor] Analysis will use the bundled TypeScript version 5.9.3\n"}
|
|
8
|
-
{"kind":"O","text":" ---- build finished (
|
|
9
|
-
{"kind":"O","text":"-------------------- Finished (
|
|
8
|
+
{"kind":"O","text":" ---- build finished (9.932s) ---- \n"}
|
|
9
|
+
{"kind":"O","text":"-------------------- Finished (9.94s) --------------------\n"}
|
|
@@ -5,5 +5,5 @@ Invoking: heft build --clean
|
|
|
5
5
|
[build:lint] Using ESLint version 9.39.4
|
|
6
6
|
[build:api-extractor] Using API Extractor version 7.58.7
|
|
7
7
|
[build:api-extractor] Analysis will use the bundled TypeScript version 5.9.3
|
|
8
|
-
---- build finished (
|
|
9
|
-
-------------------- Finished (
|
|
8
|
+
---- build finished (9.932s) ----
|
|
9
|
+
-------------------- Finished (9.94s) --------------------
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
{"kind":"O","text":"[build:lint] Using ESLint version 9.39.4\n"}
|
|
6
6
|
{"kind":"O","text":"[build:api-extractor] Using API Extractor version 7.58.7\n"}
|
|
7
7
|
{"kind":"O","text":"[build:api-extractor] Analysis will use the bundled TypeScript version 5.9.3\n"}
|
|
8
|
-
{"kind":"O","text":" ---- build finished (
|
|
9
|
-
{"kind":"O","text":"-------------------- Finished (
|
|
8
|
+
{"kind":"O","text":" ---- build finished (9.932s) ---- \n"}
|
|
9
|
+
{"kind":"O","text":"-------------------- Finished (9.94s) --------------------\n"}
|
package/dist/index.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* mirroring the discipline established by `@fgv/ts-extras-webauthn`: one-line `captureAsyncResult`
|
|
7
7
|
* wrappers around upstream primitives with **no opinionated orchestration** above the boundary.
|
|
8
8
|
*
|
|
9
|
-
* **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed` — the
|
|
10
|
-
*
|
|
11
|
-
* concrete consumer use case surfaces (
|
|
9
|
+
* **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed`, `summarize` — the task types
|
|
10
|
+
* exercised by real consumers so far. The general `generate` primitive is explicitly deferred
|
|
11
|
+
* until a concrete consumer use case surfaces (summarization is its own task-specific primitive).
|
|
12
12
|
*
|
|
13
13
|
* **Explicitly NOT in scope:**
|
|
14
14
|
* - Pipeline cache / lifecycle management
|
|
@@ -134,4 +134,28 @@ export async function classifyAll(classifier, text, options) {
|
|
|
134
134
|
export async function embed(extractor, text, options) {
|
|
135
135
|
return captureAsyncResult(() => extractor(text, options));
|
|
136
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Result-integration wrapper that invokes a `SummarizationPipeline` on a single text input.
|
|
139
|
+
* Returns the upstream `SummarizationOutput` Result-wrapped (an array of `{ summary_text }`
|
|
140
|
+
* entries; one for a single-string input).
|
|
141
|
+
*
|
|
142
|
+
* Callers should retrieve the summarizer via `loadPipeline('summarization', modelId)` — e.g.
|
|
143
|
+
* `Xenova/distilbart-cnn-6-6` for a small, local-friendly model. This facade applies no opinionated
|
|
144
|
+
* orchestration (no length policy, no local-vs-cloud routing) — `options` are passed through
|
|
145
|
+
* verbatim and the caller owns any escalation decision.
|
|
146
|
+
*
|
|
147
|
+
* Returns `Promise<Result<SummarizationOutput>>`; upstream errors (inference failures, tokenisation
|
|
148
|
+
* errors) are captured as `Failure` with the original message.
|
|
149
|
+
*
|
|
150
|
+
* @param summarizer - A `SummarizationPipeline` obtained from `loadPipeline`.
|
|
151
|
+
* @param text - The text to summarize.
|
|
152
|
+
* @param options - Optional upstream summarization options (e.g. `min_length`, `max_length`,
|
|
153
|
+
* `max_new_tokens`). Passed through verbatim to the pipeline call.
|
|
154
|
+
*
|
|
155
|
+
* @see https://huggingface.co/docs/transformers.js
|
|
156
|
+
* @public
|
|
157
|
+
*/
|
|
158
|
+
export async function summarize(summarizer, text, options) {
|
|
159
|
+
return captureAsyncResult(() => summarizer(text, options));
|
|
160
|
+
}
|
|
137
161
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,QAAQ,IAAI,SAAS,EAOtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAe,MAAM,eAAe,CAAC;AAahE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAO,EACP,KAAc,EACd,OAAyC;IAEzC,OAAO,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CACtB,MAA6D;IAE7D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,OAAO,MAAkC,CAAC;IAC5C,CAAC;IACD,yEAAyE;IACzE,OAAQ,MAAgD,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAAsC,EACtC,IAAY,EACZ,OAAmD;IAEnD,OAAO,kBAAkB,CAAC,KAAK,IAAI,EAAE;QACnC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAAsC,EACtC,IAAY,EACZ,OAAmD;IAEnD,OAAO,QAAQ,CAAC,UAAU,EAAE,IAAI,kCAAO,OAAO,KAAE,KAAK,EAAE,IAAI,IAAG,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,SAAoC,EACpC,IAAuB,EACvB,OAA2D;IAE3D,OAAO,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC","sourcesContent":["/**\n * `@fgv/ts-extras-transformers` — Result-integration boundary over `@huggingface/transformers`\n * (Node-side).\n *\n * A thin facade that wraps `@huggingface/transformers` calls in `Result<T>` from `@fgv/ts-utils`,\n * mirroring the discipline established by `@fgv/ts-extras-webauthn`: one-line `captureAsyncResult`\n * wrappers around upstream primitives with **no opinionated orchestration** above the boundary.\n *\n * **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed` — the surface needed by the\n * B-3/B-4a local-classifier and embedding scenarios. `generate` is explicitly deferred until a\n * concrete consumer use case surfaces (see `phase-b2-result.md`).\n *\n * **Explicitly NOT in scope:**\n * - Pipeline cache / lifecycle management\n * - Model registry or download management\n * - GPU/CPU device selection policy\n * - Quantization selection\n * - Embedding-store integration\n * - Classifier label allowlists\n * - Request batching\n * - Pipeline dispose semantics\n *\n * For any of the above, use `@huggingface/transformers` directly (with `captureAsyncResult` for\n * your own Result wrapping).\n *\n * @packageDocumentation\n */\n\nimport {\n pipeline as _pipeline,\n type TextClassificationPipeline,\n type TextClassificationOutput,\n type FeatureExtractionPipeline,\n type Tensor,\n type AllTasks,\n type PipelineType\n} from '@huggingface/transformers';\nimport { captureAsyncResult, type Result } from '@fgv/ts-utils';\n\nexport type {\n TextClassificationPipeline,\n TextClassificationOutput,\n FeatureExtractionPipeline,\n Tensor,\n AllTasks,\n PipelineType\n};\n\nexport type { PretrainedModelOptions } from '@huggingface/transformers';\n\n/**\n * Result-integration wrapper around `@huggingface/transformers`'s `pipeline` factory.\n * Loads a model and returns a ready-to-use pipeline object.\n *\n * The returned pipeline is the upstream `AllTasks[T]` instance — consumers retain full access\n * to the upstream API. Lifecycle management (caching, disposal, GPU/CPU selection) is the\n * consumer's responsibility.\n *\n * Returns `Promise<Result<AllTasks[T]>>`; upstream errors (network, model-not-found, ONNX\n * initialization failures) are captured as `Failure` with the original message.\n *\n * @param task - The pipeline task type (e.g. `'text-classification'`, `'feature-extraction'`).\n * @param model - The model identifier (HuggingFace Hub ID or local path). If omitted, the\n * upstream default for the task is used.\n * @param options - Optional `PretrainedModelOptions` (device, dtype, cache_dir, etc.). Passed\n * through verbatim to the upstream `pipeline()` call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function loadPipeline<T extends PipelineType>(\n task: T,\n model?: string,\n options?: Parameters<typeof _pipeline>[2]\n): Promise<Result<AllTasks[T]>> {\n return captureAsyncResult(() => _pipeline(task, model, options));\n}\n\n/**\n * Normalises the upstream pipeline's output to a flat `TextClassificationOutput`.\n *\n * The upstream `TextClassificationPipeline` has an overloaded call signature: a single-string\n * input returns `TextClassificationOutput` (flat array), while a string-array input returns\n * `TextClassificationOutput[]` (array-of-arrays). Since `classify` always passes a single\n * string, the flat-array path is the live path. The nested-array branch is defensive and\n * ensures consumers always receive a flat array even if the upstream type union leaks through.\n */\nfunction flattenIfNeeded(\n result: TextClassificationOutput | TextClassificationOutput[]\n): TextClassificationOutput {\n if (Array.isArray(result) && result.length > 0 && !Array.isArray(result[0])) {\n return result as TextClassificationOutput;\n }\n // Defensive: if somehow an array-of-arrays came back, flatten one level.\n return (result as unknown as TextClassificationOutput[]).flat();\n}\n\n/**\n * Result-integration wrapper that invokes a `TextClassificationPipeline` on a single text input.\n * Returns the classification results as a flat `TextClassificationOutput` (array of\n * `{ label: string; score: number }` entries).\n *\n * Callers should retrieve the pipeline via `loadPipeline('text-classification', modelId)` (or the\n * `'sentiment-analysis'` alias). This helper always passes a single string to the upstream\n * pipeline and normalises the result to `TextClassificationOutput` so consumers don't need to\n * handle the `string | string[]` overload union.\n *\n * Returns `Promise<Result<TextClassificationOutput>>`; upstream errors (inference failures,\n * tokenisation errors) are captured as `Failure` with the original message.\n *\n * @param classifier - A `TextClassificationPipeline` obtained from `loadPipeline`.\n * @param text - The text to classify.\n * @param options - Optional upstream classification options (e.g. `{ top_k: null }` to return\n * all labels). Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function classify(\n classifier: TextClassificationPipeline,\n text: string,\n options?: Parameters<TextClassificationPipeline>[1]\n): Promise<Result<TextClassificationOutput>> {\n return captureAsyncResult(async () => {\n const result = await classifier(text, options);\n return flattenIfNeeded(result);\n });\n}\n\n/**\n * Convenience wrapper over `classify` that forces `top_k: null` so the full per-label vector\n * is returned for every call. Callers no longer need to remember to pass `{ top_k: null }`.\n *\n * Any caller-supplied options are honoured except `top_k`, which is always overridden to `null`.\n *\n * Returns `Promise<Result<TextClassificationOutput>>`; upstream errors are captured as `Failure`\n * with the original message.\n *\n * @param classifier - A `TextClassificationPipeline` obtained from `loadPipeline`.\n * @param text - The text to classify.\n * @param options - Optional upstream classification options. `top_k` is always set to `null`\n * regardless of any value supplied here.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function classifyAll(\n classifier: TextClassificationPipeline,\n text: string,\n options?: Parameters<TextClassificationPipeline>[1]\n): Promise<Result<TextClassificationOutput>> {\n return classify(classifier, text, { ...options, top_k: null });\n}\n\n/**\n * Result-integration wrapper that invokes a `FeatureExtractionPipeline` on a text input.\n * Returns the upstream `Tensor` Result-wrapped — no pooling, normalisation, or reshaping is\n * applied. Callers receive the raw output and are responsible for any downstream processing.\n *\n * Callers should retrieve the extractor via `loadPipeline('feature-extraction', modelId)`.\n *\n * Returns `Promise<Result<Tensor>>`; upstream errors (inference failures, tokenisation errors)\n * are captured as `Failure` with the original message.\n *\n * @param extractor - A `FeatureExtractionPipeline` obtained from `loadPipeline`.\n * @param text - The text (or texts) to embed.\n * @param options - Optional upstream feature-extraction options (e.g. `pooling`, `normalize`).\n * Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function embed(\n extractor: FeatureExtractionPipeline,\n text: string | string[],\n options?: Parameters<FeatureExtractionPipeline['_call']>[1]\n): Promise<Result<Tensor>> {\n return captureAsyncResult(() => extractor(text, options));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,QAAQ,IAAI,SAAS,EAStB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAe,MAAM,eAAe,CAAC;AAehE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAO,EACP,KAAc,EACd,OAAyC;IAEzC,OAAO,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CACtB,MAA6D;IAE7D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,OAAO,MAAkC,CAAC;IAC5C,CAAC;IACD,yEAAyE;IACzE,OAAQ,MAAgD,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAAsC,EACtC,IAAY,EACZ,OAAmD;IAEnD,OAAO,kBAAkB,CAAC,KAAK,IAAI,EAAE;QACnC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAAsC,EACtC,IAAY,EACZ,OAAmD;IAEnD,OAAO,QAAQ,CAAC,UAAU,EAAE,IAAI,kCAAO,OAAO,KAAE,KAAK,EAAE,IAAI,IAAG,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,SAAoC,EACpC,IAAuB,EACvB,OAA2D;IAE3D,OAAO,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,UAAiC,EACjC,IAAY,EACZ,OAA8C;IAE9C,OAAO,kBAAkB,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC","sourcesContent":["/**\n * `@fgv/ts-extras-transformers` — Result-integration boundary over `@huggingface/transformers`\n * (Node-side).\n *\n * A thin facade that wraps `@huggingface/transformers` calls in `Result<T>` from `@fgv/ts-utils`,\n * mirroring the discipline established by `@fgv/ts-extras-webauthn`: one-line `captureAsyncResult`\n * wrappers around upstream primitives with **no opinionated orchestration** above the boundary.\n *\n * **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed`, `summarize` — the task types\n * exercised by real consumers so far. The general `generate` primitive is explicitly deferred\n * until a concrete consumer use case surfaces (summarization is its own task-specific primitive).\n *\n * **Explicitly NOT in scope:**\n * - Pipeline cache / lifecycle management\n * - Model registry or download management\n * - GPU/CPU device selection policy\n * - Quantization selection\n * - Embedding-store integration\n * - Classifier label allowlists\n * - Request batching\n * - Pipeline dispose semantics\n *\n * For any of the above, use `@huggingface/transformers` directly (with `captureAsyncResult` for\n * your own Result wrapping).\n *\n * @packageDocumentation\n */\n\nimport {\n pipeline as _pipeline,\n type TextClassificationPipeline,\n type TextClassificationOutput,\n type FeatureExtractionPipeline,\n type SummarizationPipeline,\n type SummarizationOutput,\n type Tensor,\n type AllTasks,\n type PipelineType\n} from '@huggingface/transformers';\nimport { captureAsyncResult, type Result } from '@fgv/ts-utils';\n\nexport type {\n TextClassificationPipeline,\n TextClassificationOutput,\n FeatureExtractionPipeline,\n SummarizationPipeline,\n SummarizationOutput,\n Tensor,\n AllTasks,\n PipelineType\n};\n\nexport type { PretrainedModelOptions } from '@huggingface/transformers';\n\n/**\n * Result-integration wrapper around `@huggingface/transformers`'s `pipeline` factory.\n * Loads a model and returns a ready-to-use pipeline object.\n *\n * The returned pipeline is the upstream `AllTasks[T]` instance — consumers retain full access\n * to the upstream API. Lifecycle management (caching, disposal, GPU/CPU selection) is the\n * consumer's responsibility.\n *\n * Returns `Promise<Result<AllTasks[T]>>`; upstream errors (network, model-not-found, ONNX\n * initialization failures) are captured as `Failure` with the original message.\n *\n * @param task - The pipeline task type (e.g. `'text-classification'`, `'feature-extraction'`).\n * @param model - The model identifier (HuggingFace Hub ID or local path). If omitted, the\n * upstream default for the task is used.\n * @param options - Optional `PretrainedModelOptions` (device, dtype, cache_dir, etc.). Passed\n * through verbatim to the upstream `pipeline()` call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function loadPipeline<T extends PipelineType>(\n task: T,\n model?: string,\n options?: Parameters<typeof _pipeline>[2]\n): Promise<Result<AllTasks[T]>> {\n return captureAsyncResult(() => _pipeline(task, model, options));\n}\n\n/**\n * Normalises the upstream pipeline's output to a flat `TextClassificationOutput`.\n *\n * The upstream `TextClassificationPipeline` has an overloaded call signature: a single-string\n * input returns `TextClassificationOutput` (flat array), while a string-array input returns\n * `TextClassificationOutput[]` (array-of-arrays). Since `classify` always passes a single\n * string, the flat-array path is the live path. The nested-array branch is defensive and\n * ensures consumers always receive a flat array even if the upstream type union leaks through.\n */\nfunction flattenIfNeeded(\n result: TextClassificationOutput | TextClassificationOutput[]\n): TextClassificationOutput {\n if (Array.isArray(result) && result.length > 0 && !Array.isArray(result[0])) {\n return result as TextClassificationOutput;\n }\n // Defensive: if somehow an array-of-arrays came back, flatten one level.\n return (result as unknown as TextClassificationOutput[]).flat();\n}\n\n/**\n * Result-integration wrapper that invokes a `TextClassificationPipeline` on a single text input.\n * Returns the classification results as a flat `TextClassificationOutput` (array of\n * `{ label: string; score: number }` entries).\n *\n * Callers should retrieve the pipeline via `loadPipeline('text-classification', modelId)` (or the\n * `'sentiment-analysis'` alias). This helper always passes a single string to the upstream\n * pipeline and normalises the result to `TextClassificationOutput` so consumers don't need to\n * handle the `string | string[]` overload union.\n *\n * Returns `Promise<Result<TextClassificationOutput>>`; upstream errors (inference failures,\n * tokenisation errors) are captured as `Failure` with the original message.\n *\n * @param classifier - A `TextClassificationPipeline` obtained from `loadPipeline`.\n * @param text - The text to classify.\n * @param options - Optional upstream classification options (e.g. `{ top_k: null }` to return\n * all labels). Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function classify(\n classifier: TextClassificationPipeline,\n text: string,\n options?: Parameters<TextClassificationPipeline>[1]\n): Promise<Result<TextClassificationOutput>> {\n return captureAsyncResult(async () => {\n const result = await classifier(text, options);\n return flattenIfNeeded(result);\n });\n}\n\n/**\n * Convenience wrapper over `classify` that forces `top_k: null` so the full per-label vector\n * is returned for every call. Callers no longer need to remember to pass `{ top_k: null }`.\n *\n * Any caller-supplied options are honoured except `top_k`, which is always overridden to `null`.\n *\n * Returns `Promise<Result<TextClassificationOutput>>`; upstream errors are captured as `Failure`\n * with the original message.\n *\n * @param classifier - A `TextClassificationPipeline` obtained from `loadPipeline`.\n * @param text - The text to classify.\n * @param options - Optional upstream classification options. `top_k` is always set to `null`\n * regardless of any value supplied here.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function classifyAll(\n classifier: TextClassificationPipeline,\n text: string,\n options?: Parameters<TextClassificationPipeline>[1]\n): Promise<Result<TextClassificationOutput>> {\n return classify(classifier, text, { ...options, top_k: null });\n}\n\n/**\n * Result-integration wrapper that invokes a `FeatureExtractionPipeline` on a text input.\n * Returns the upstream `Tensor` Result-wrapped — no pooling, normalisation, or reshaping is\n * applied. Callers receive the raw output and are responsible for any downstream processing.\n *\n * Callers should retrieve the extractor via `loadPipeline('feature-extraction', modelId)`.\n *\n * Returns `Promise<Result<Tensor>>`; upstream errors (inference failures, tokenisation errors)\n * are captured as `Failure` with the original message.\n *\n * @param extractor - A `FeatureExtractionPipeline` obtained from `loadPipeline`.\n * @param text - The text (or texts) to embed.\n * @param options - Optional upstream feature-extraction options (e.g. `pooling`, `normalize`).\n * Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function embed(\n extractor: FeatureExtractionPipeline,\n text: string | string[],\n options?: Parameters<FeatureExtractionPipeline['_call']>[1]\n): Promise<Result<Tensor>> {\n return captureAsyncResult(() => extractor(text, options));\n}\n\n/**\n * Result-integration wrapper that invokes a `SummarizationPipeline` on a single text input.\n * Returns the upstream `SummarizationOutput` Result-wrapped (an array of `{ summary_text }`\n * entries; one for a single-string input).\n *\n * Callers should retrieve the summarizer via `loadPipeline('summarization', modelId)` — e.g.\n * `Xenova/distilbart-cnn-6-6` for a small, local-friendly model. This facade applies no opinionated\n * orchestration (no length policy, no local-vs-cloud routing) — `options` are passed through\n * verbatim and the caller owns any escalation decision.\n *\n * Returns `Promise<Result<SummarizationOutput>>`; upstream errors (inference failures, tokenisation\n * errors) are captured as `Failure` with the original message.\n *\n * @param summarizer - A `SummarizationPipeline` obtained from `loadPipeline`.\n * @param text - The text to summarize.\n * @param options - Optional upstream summarization options (e.g. `min_length`, `max_length`,\n * `max_new_tokens`). Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function summarize(\n summarizer: SummarizationPipeline,\n text: string,\n options?: Parameters<SummarizationPipeline>[1]\n): Promise<Result<SummarizationOutput>> {\n return captureAsyncResult(() => summarizer(text, options));\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
jest.mock('@huggingface/transformers');
|
|
2
2
|
import '@fgv/ts-utils-jest';
|
|
3
3
|
import * as upstream from '@huggingface/transformers';
|
|
4
|
-
import { loadPipeline, classify, classifyAll, embed } from '../../index';
|
|
4
|
+
import { loadPipeline, classify, classifyAll, embed, summarize } from '../../index';
|
|
5
5
|
// ─── loadPipeline ──────────────────────────────────────────────────────────────
|
|
6
6
|
describe('loadPipeline', () => {
|
|
7
7
|
beforeEach(() => {
|
|
@@ -194,4 +194,41 @@ describe('embed', () => {
|
|
|
194
194
|
expect(result).toFailWith(/tokenisation failed/i);
|
|
195
195
|
});
|
|
196
196
|
});
|
|
197
|
+
// ─── summarize ──────────────────────────────────────────────────────────────────
|
|
198
|
+
describe('summarize', () => {
|
|
199
|
+
let mockSummarizer;
|
|
200
|
+
beforeEach(() => {
|
|
201
|
+
jest.resetAllMocks();
|
|
202
|
+
mockSummarizer = jest.fn();
|
|
203
|
+
});
|
|
204
|
+
test('returns Success wrapping SummarizationOutput on success', async () => {
|
|
205
|
+
const mockOutput = [{ summary_text: 'A short summary.' }];
|
|
206
|
+
mockSummarizer.mockResolvedValueOnce(mockOutput);
|
|
207
|
+
const result = await summarize(mockSummarizer, 'A long article that needs summarizing.');
|
|
208
|
+
expect(result).toSucceedWith(mockOutput);
|
|
209
|
+
});
|
|
210
|
+
test('passes text to the upstream summarizer', async () => {
|
|
211
|
+
const mockOutput = [{ summary_text: 'Summary.' }];
|
|
212
|
+
mockSummarizer.mockResolvedValueOnce(mockOutput);
|
|
213
|
+
await summarize(mockSummarizer, 'some long document');
|
|
214
|
+
expect(mockSummarizer).toHaveBeenCalledWith('some long document', undefined);
|
|
215
|
+
});
|
|
216
|
+
test('passes options through to the upstream summarizer', async () => {
|
|
217
|
+
const mockOutput = [{ summary_text: 'Bounded summary.' }];
|
|
218
|
+
mockSummarizer.mockResolvedValueOnce(mockOutput);
|
|
219
|
+
const opts = { min_length: 10, max_length: 50 };
|
|
220
|
+
await summarize(mockSummarizer, 'a document', opts);
|
|
221
|
+
expect(mockSummarizer).toHaveBeenCalledWith('a document', opts);
|
|
222
|
+
});
|
|
223
|
+
test('returns Failure capturing upstream inference error', async () => {
|
|
224
|
+
mockSummarizer.mockRejectedValueOnce(new Error('Inference session error: out of memory'));
|
|
225
|
+
const result = await summarize(mockSummarizer, 'some text');
|
|
226
|
+
expect(result).toFailWith(/inference session error/i);
|
|
227
|
+
});
|
|
228
|
+
test('returns Failure capturing upstream tokenisation error', async () => {
|
|
229
|
+
mockSummarizer.mockRejectedValueOnce(new Error('Tokenisation failed: input too long'));
|
|
230
|
+
const result = await summarize(mockSummarizer, 'bad input');
|
|
231
|
+
expect(result).toFailWith(/tokenisation failed/i);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
197
234
|
//# sourceMappingURL=transformers.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformers.test.js","sourceRoot":"","sources":["../../../src/test/unit/transformers.test.ts"],"names":[],"mappings":"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","sourcesContent":["jest.mock('@huggingface/transformers');\n\nimport '@fgv/ts-utils-jest';\nimport * as upstream from '@huggingface/transformers';\nimport {\n loadPipeline,\n classify,\n classifyAll,\n embed,\n type TextClassificationPipeline,\n type TextClassificationOutput,\n type FeatureExtractionPipeline,\n type Tensor,\n type AllTasks\n} from '../../index';\n\n// ─── loadPipeline ──────────────────────────────────────────────────────────────\n\ndescribe('loadPipeline', () => {\n beforeEach(() => {\n jest.resetAllMocks();\n });\n\n test('returns Success wrapping the upstream pipeline on success', async () => {\n const mockPipeline = jest.fn() as unknown as AllTasks['text-classification'];\n jest.mocked(upstream.pipeline).mockResolvedValueOnce(mockPipeline);\n\n const result = await loadPipeline(\n 'text-classification',\n 'Xenova/distilbert-base-uncased-finetuned-sst-2-english'\n );\n expect(result).toSucceedWith(mockPipeline);\n });\n\n test('passes task and model to the upstream pipeline factory', async () => {\n const mockPipeline = jest.fn() as unknown as AllTasks['text-classification'];\n jest.mocked(upstream.pipeline).mockResolvedValueOnce(mockPipeline);\n\n await loadPipeline('text-classification', 'some-model-id');\n expect(upstream.pipeline).toHaveBeenCalledWith('text-classification', 'some-model-id', undefined);\n });\n\n test('passes options through to the upstream pipeline factory', async () => {\n const mockPipeline = jest.fn() as unknown as AllTasks['text-classification'];\n jest.mocked(upstream.pipeline).mockResolvedValueOnce(mockPipeline);\n\n const opts = { device: 'cpu' } as Parameters<typeof upstream.pipeline>[2];\n await loadPipeline('text-classification', 'some-model-id', opts);\n expect(upstream.pipeline).toHaveBeenCalledWith('text-classification', 'some-model-id', opts);\n });\n\n test('returns Success when model is omitted', async () => {\n const mockPipeline = jest.fn() as unknown as AllTasks['feature-extraction'];\n jest.mocked(upstream.pipeline).mockResolvedValueOnce(mockPipeline);\n\n const result = await loadPipeline('feature-extraction');\n expect(result).toSucceed();\n expect(upstream.pipeline).toHaveBeenCalledWith('feature-extraction', undefined, undefined);\n });\n\n test('returns Failure capturing upstream error message on network failure', async () => {\n jest\n .mocked(upstream.pipeline)\n .mockRejectedValueOnce(new Error('Could not locate the model: model-not-found'));\n\n const result = await loadPipeline('text-classification', 'model-not-found');\n expect(result).toFailWith(/could not locate the model/i);\n });\n\n test('returns Failure capturing upstream error on ONNX init failure', async () => {\n jest.mocked(upstream.pipeline).mockRejectedValueOnce(new Error('Failed to initialize ONNX runtime'));\n\n const result = await loadPipeline('text-classification', 'some-model');\n expect(result).toFailWith(/failed to initialize onnx runtime/i);\n });\n});\n\n// ─── classify ─────────────────────────────────────────────────────────────────\n\ndescribe('classify', () => {\n let mockClassifier: jest.MockedFunction<TextClassificationPipeline>;\n\n beforeEach(() => {\n jest.resetAllMocks();\n mockClassifier = jest.fn() as unknown as jest.MockedFunction<TextClassificationPipeline>;\n });\n\n test('returns Success wrapping TextClassificationOutput on success', async () => {\n const mockOutput: TextClassificationOutput = [{ label: 'POSITIVE', score: 0.9998 }];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n const result = await classify(mockClassifier, 'I love transformers!');\n expect(result).toSucceedWith(mockOutput);\n });\n\n test('passes text to the upstream classifier', async () => {\n const mockOutput: TextClassificationOutput = [{ label: 'NEGATIVE', score: 0.9997 }];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n await classify(mockClassifier, 'I hate bugs');\n expect(mockClassifier).toHaveBeenCalledWith('I hate bugs', undefined);\n });\n\n test('passes options through to the upstream classifier', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'POSITIVE', score: 0.9998 },\n { label: 'NEGATIVE', score: 0.0002 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n const opts = { top_k: null };\n await classify(mockClassifier, 'Hello world', opts);\n expect(mockClassifier).toHaveBeenCalledWith('Hello world', opts);\n });\n\n test('normalises flat array result correctly', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'SAFE', score: 0.95 },\n { label: 'UNSAFE', score: 0.05 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n expect(await classify(mockClassifier, 'hello')).toSucceedWith(mockOutput);\n });\n\n test('normalises nested array result by flattening one level', async () => {\n // When upstream returns array-of-arrays (e.g. batch input path leaked through),\n // we flatten one level so consumers always receive a flat TextClassificationOutput.\n const inner: TextClassificationOutput = [{ label: 'POSITIVE', score: 0.9 }];\n mockClassifier.mockResolvedValueOnce([inner] as unknown as TextClassificationOutput);\n\n expect(await classify(mockClassifier, 'hello')).toSucceedAndSatisfy((output) => {\n expect(output).toEqual([{ label: 'POSITIVE', score: 0.9 }]);\n });\n });\n\n test('returns Failure capturing upstream error on inference failure', async () => {\n mockClassifier.mockRejectedValueOnce(new Error('Inference session error: out of memory'));\n\n const result = await classify(mockClassifier, 'some text');\n expect(result).toFailWith(/inference session error/i);\n });\n\n test('returns Failure capturing upstream tokenisation error', async () => {\n mockClassifier.mockRejectedValueOnce(new Error('Tokenisation failed: unexpected token'));\n\n const result = await classify(mockClassifier, 'bad input');\n expect(result).toFailWith(/tokenisation failed/i);\n });\n});\n\n// ─── classifyAll ──────────────────────────────────────────────────────────────\n\ndescribe('classifyAll', () => {\n let mockClassifier: jest.MockedFunction<TextClassificationPipeline>;\n\n beforeEach(() => {\n jest.resetAllMocks();\n mockClassifier = jest.fn() as unknown as jest.MockedFunction<TextClassificationPipeline>;\n });\n\n test('forces top_k: null on the underlying classify call', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'POSITIVE', score: 0.9998 },\n { label: 'NEGATIVE', score: 0.0002 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n await classifyAll(mockClassifier, 'hello');\n expect(mockClassifier).toHaveBeenCalledWith('hello', { top_k: null });\n });\n\n test('overrides caller-supplied top_k with null', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'POSITIVE', score: 0.9998 },\n { label: 'NEGATIVE', score: 0.0002 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n await classifyAll(mockClassifier, 'hello', { top_k: 1 });\n expect(mockClassifier).toHaveBeenCalledWith('hello', { top_k: null });\n });\n\n test('returns all labels on success', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'POSITIVE', score: 0.9998 },\n { label: 'NEGATIVE', score: 0.0002 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n const result = await classifyAll(mockClassifier, 'I love transformers!');\n expect(result).toSucceedWith(mockOutput);\n });\n\n test('propagates upstream inference failure as Failure', async () => {\n mockClassifier.mockRejectedValueOnce(new Error('Inference session error: out of memory'));\n\n const result = await classifyAll(mockClassifier, 'some text');\n expect(result).toFailWith(/inference session error/i);\n });\n});\n\n// ─── embed ────────────────────────────────────────────────────────────────────\n\ndescribe('embed', () => {\n let mockExtractor: jest.MockedFunction<FeatureExtractionPipeline>;\n\n beforeEach(() => {\n jest.resetAllMocks();\n mockExtractor = jest.fn() as unknown as jest.MockedFunction<FeatureExtractionPipeline>;\n });\n\n test('returns Success wrapping the upstream Tensor on success', async () => {\n const mockTensor = {\n type: 'float32',\n data: new Float32Array([0.1, 0.2, 0.3]),\n dims: [1, 3]\n } as unknown as Tensor;\n mockExtractor.mockResolvedValueOnce(mockTensor);\n\n const result = await embed(mockExtractor, 'This is a test.');\n expect(result).toSucceedWith(mockTensor);\n });\n\n test('passes text to the upstream extractor', async () => {\n const mockTensor = { type: 'float32', data: new Float32Array([0.1]), dims: [1, 1] } as unknown as Tensor;\n mockExtractor.mockResolvedValueOnce(mockTensor);\n\n await embed(mockExtractor, 'hello world');\n expect(mockExtractor).toHaveBeenCalledWith('hello world', undefined);\n });\n\n test('passes string array to the upstream extractor', async () => {\n const mockTensor = {\n type: 'float32',\n data: new Float32Array([0.1, 0.2]),\n dims: [2, 1]\n } as unknown as Tensor;\n mockExtractor.mockResolvedValueOnce(mockTensor);\n\n await embed(mockExtractor, ['text one', 'text two']);\n expect(mockExtractor).toHaveBeenCalledWith(['text one', 'text two'], undefined);\n });\n\n test('passes options through to the upstream extractor', async () => {\n const mockTensor = { type: 'float32', data: new Float32Array([0.5]), dims: [1, 1] } as unknown as Tensor;\n mockExtractor.mockResolvedValueOnce(mockTensor);\n\n const opts = { pooling: 'mean' as const, normalize: true };\n await embed(mockExtractor, 'some text', opts);\n expect(mockExtractor).toHaveBeenCalledWith('some text', opts);\n });\n\n test('returns Failure capturing upstream inference error', async () => {\n mockExtractor.mockRejectedValueOnce(new Error('Inference session error: out of memory'));\n\n const result = await embed(mockExtractor, 'some text');\n expect(result).toFailWith(/inference session error/i);\n });\n\n test('returns Failure capturing upstream tokenisation error', async () => {\n mockExtractor.mockRejectedValueOnce(new Error('Tokenisation failed: input too long'));\n\n const result = await embed(mockExtractor, 'bad input');\n expect(result).toFailWith(/tokenisation failed/i);\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"transformers.test.js","sourceRoot":"","sources":["../../../src/test/unit/transformers.test.ts"],"names":[],"mappings":"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","sourcesContent":["jest.mock('@huggingface/transformers');\n\nimport '@fgv/ts-utils-jest';\nimport * as upstream from '@huggingface/transformers';\nimport {\n loadPipeline,\n classify,\n classifyAll,\n embed,\n summarize,\n type TextClassificationPipeline,\n type TextClassificationOutput,\n type FeatureExtractionPipeline,\n type SummarizationPipeline,\n type SummarizationOutput,\n type Tensor,\n type AllTasks\n} from '../../index';\n\n// ─── loadPipeline ──────────────────────────────────────────────────────────────\n\ndescribe('loadPipeline', () => {\n beforeEach(() => {\n jest.resetAllMocks();\n });\n\n test('returns Success wrapping the upstream pipeline on success', async () => {\n const mockPipeline = jest.fn() as unknown as AllTasks['text-classification'];\n jest.mocked(upstream.pipeline).mockResolvedValueOnce(mockPipeline);\n\n const result = await loadPipeline(\n 'text-classification',\n 'Xenova/distilbert-base-uncased-finetuned-sst-2-english'\n );\n expect(result).toSucceedWith(mockPipeline);\n });\n\n test('passes task and model to the upstream pipeline factory', async () => {\n const mockPipeline = jest.fn() as unknown as AllTasks['text-classification'];\n jest.mocked(upstream.pipeline).mockResolvedValueOnce(mockPipeline);\n\n await loadPipeline('text-classification', 'some-model-id');\n expect(upstream.pipeline).toHaveBeenCalledWith('text-classification', 'some-model-id', undefined);\n });\n\n test('passes options through to the upstream pipeline factory', async () => {\n const mockPipeline = jest.fn() as unknown as AllTasks['text-classification'];\n jest.mocked(upstream.pipeline).mockResolvedValueOnce(mockPipeline);\n\n const opts = { device: 'cpu' } as Parameters<typeof upstream.pipeline>[2];\n await loadPipeline('text-classification', 'some-model-id', opts);\n expect(upstream.pipeline).toHaveBeenCalledWith('text-classification', 'some-model-id', opts);\n });\n\n test('returns Success when model is omitted', async () => {\n const mockPipeline = jest.fn() as unknown as AllTasks['feature-extraction'];\n jest.mocked(upstream.pipeline).mockResolvedValueOnce(mockPipeline);\n\n const result = await loadPipeline('feature-extraction');\n expect(result).toSucceed();\n expect(upstream.pipeline).toHaveBeenCalledWith('feature-extraction', undefined, undefined);\n });\n\n test('returns Failure capturing upstream error message on network failure', async () => {\n jest\n .mocked(upstream.pipeline)\n .mockRejectedValueOnce(new Error('Could not locate the model: model-not-found'));\n\n const result = await loadPipeline('text-classification', 'model-not-found');\n expect(result).toFailWith(/could not locate the model/i);\n });\n\n test('returns Failure capturing upstream error on ONNX init failure', async () => {\n jest.mocked(upstream.pipeline).mockRejectedValueOnce(new Error('Failed to initialize ONNX runtime'));\n\n const result = await loadPipeline('text-classification', 'some-model');\n expect(result).toFailWith(/failed to initialize onnx runtime/i);\n });\n});\n\n// ─── classify ─────────────────────────────────────────────────────────────────\n\ndescribe('classify', () => {\n let mockClassifier: jest.MockedFunction<TextClassificationPipeline>;\n\n beforeEach(() => {\n jest.resetAllMocks();\n mockClassifier = jest.fn() as unknown as jest.MockedFunction<TextClassificationPipeline>;\n });\n\n test('returns Success wrapping TextClassificationOutput on success', async () => {\n const mockOutput: TextClassificationOutput = [{ label: 'POSITIVE', score: 0.9998 }];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n const result = await classify(mockClassifier, 'I love transformers!');\n expect(result).toSucceedWith(mockOutput);\n });\n\n test('passes text to the upstream classifier', async () => {\n const mockOutput: TextClassificationOutput = [{ label: 'NEGATIVE', score: 0.9997 }];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n await classify(mockClassifier, 'I hate bugs');\n expect(mockClassifier).toHaveBeenCalledWith('I hate bugs', undefined);\n });\n\n test('passes options through to the upstream classifier', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'POSITIVE', score: 0.9998 },\n { label: 'NEGATIVE', score: 0.0002 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n const opts = { top_k: null };\n await classify(mockClassifier, 'Hello world', opts);\n expect(mockClassifier).toHaveBeenCalledWith('Hello world', opts);\n });\n\n test('normalises flat array result correctly', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'SAFE', score: 0.95 },\n { label: 'UNSAFE', score: 0.05 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n expect(await classify(mockClassifier, 'hello')).toSucceedWith(mockOutput);\n });\n\n test('normalises nested array result by flattening one level', async () => {\n // When upstream returns array-of-arrays (e.g. batch input path leaked through),\n // we flatten one level so consumers always receive a flat TextClassificationOutput.\n const inner: TextClassificationOutput = [{ label: 'POSITIVE', score: 0.9 }];\n mockClassifier.mockResolvedValueOnce([inner] as unknown as TextClassificationOutput);\n\n expect(await classify(mockClassifier, 'hello')).toSucceedAndSatisfy((output) => {\n expect(output).toEqual([{ label: 'POSITIVE', score: 0.9 }]);\n });\n });\n\n test('returns Failure capturing upstream error on inference failure', async () => {\n mockClassifier.mockRejectedValueOnce(new Error('Inference session error: out of memory'));\n\n const result = await classify(mockClassifier, 'some text');\n expect(result).toFailWith(/inference session error/i);\n });\n\n test('returns Failure capturing upstream tokenisation error', async () => {\n mockClassifier.mockRejectedValueOnce(new Error('Tokenisation failed: unexpected token'));\n\n const result = await classify(mockClassifier, 'bad input');\n expect(result).toFailWith(/tokenisation failed/i);\n });\n});\n\n// ─── classifyAll ──────────────────────────────────────────────────────────────\n\ndescribe('classifyAll', () => {\n let mockClassifier: jest.MockedFunction<TextClassificationPipeline>;\n\n beforeEach(() => {\n jest.resetAllMocks();\n mockClassifier = jest.fn() as unknown as jest.MockedFunction<TextClassificationPipeline>;\n });\n\n test('forces top_k: null on the underlying classify call', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'POSITIVE', score: 0.9998 },\n { label: 'NEGATIVE', score: 0.0002 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n await classifyAll(mockClassifier, 'hello');\n expect(mockClassifier).toHaveBeenCalledWith('hello', { top_k: null });\n });\n\n test('overrides caller-supplied top_k with null', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'POSITIVE', score: 0.9998 },\n { label: 'NEGATIVE', score: 0.0002 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n await classifyAll(mockClassifier, 'hello', { top_k: 1 });\n expect(mockClassifier).toHaveBeenCalledWith('hello', { top_k: null });\n });\n\n test('returns all labels on success', async () => {\n const mockOutput: TextClassificationOutput = [\n { label: 'POSITIVE', score: 0.9998 },\n { label: 'NEGATIVE', score: 0.0002 }\n ];\n mockClassifier.mockResolvedValueOnce(mockOutput);\n\n const result = await classifyAll(mockClassifier, 'I love transformers!');\n expect(result).toSucceedWith(mockOutput);\n });\n\n test('propagates upstream inference failure as Failure', async () => {\n mockClassifier.mockRejectedValueOnce(new Error('Inference session error: out of memory'));\n\n const result = await classifyAll(mockClassifier, 'some text');\n expect(result).toFailWith(/inference session error/i);\n });\n});\n\n// ─── embed ────────────────────────────────────────────────────────────────────\n\ndescribe('embed', () => {\n let mockExtractor: jest.MockedFunction<FeatureExtractionPipeline>;\n\n beforeEach(() => {\n jest.resetAllMocks();\n mockExtractor = jest.fn() as unknown as jest.MockedFunction<FeatureExtractionPipeline>;\n });\n\n test('returns Success wrapping the upstream Tensor on success', async () => {\n const mockTensor = {\n type: 'float32',\n data: new Float32Array([0.1, 0.2, 0.3]),\n dims: [1, 3]\n } as unknown as Tensor;\n mockExtractor.mockResolvedValueOnce(mockTensor);\n\n const result = await embed(mockExtractor, 'This is a test.');\n expect(result).toSucceedWith(mockTensor);\n });\n\n test('passes text to the upstream extractor', async () => {\n const mockTensor = { type: 'float32', data: new Float32Array([0.1]), dims: [1, 1] } as unknown as Tensor;\n mockExtractor.mockResolvedValueOnce(mockTensor);\n\n await embed(mockExtractor, 'hello world');\n expect(mockExtractor).toHaveBeenCalledWith('hello world', undefined);\n });\n\n test('passes string array to the upstream extractor', async () => {\n const mockTensor = {\n type: 'float32',\n data: new Float32Array([0.1, 0.2]),\n dims: [2, 1]\n } as unknown as Tensor;\n mockExtractor.mockResolvedValueOnce(mockTensor);\n\n await embed(mockExtractor, ['text one', 'text two']);\n expect(mockExtractor).toHaveBeenCalledWith(['text one', 'text two'], undefined);\n });\n\n test('passes options through to the upstream extractor', async () => {\n const mockTensor = { type: 'float32', data: new Float32Array([0.5]), dims: [1, 1] } as unknown as Tensor;\n mockExtractor.mockResolvedValueOnce(mockTensor);\n\n const opts = { pooling: 'mean' as const, normalize: true };\n await embed(mockExtractor, 'some text', opts);\n expect(mockExtractor).toHaveBeenCalledWith('some text', opts);\n });\n\n test('returns Failure capturing upstream inference error', async () => {\n mockExtractor.mockRejectedValueOnce(new Error('Inference session error: out of memory'));\n\n const result = await embed(mockExtractor, 'some text');\n expect(result).toFailWith(/inference session error/i);\n });\n\n test('returns Failure capturing upstream tokenisation error', async () => {\n mockExtractor.mockRejectedValueOnce(new Error('Tokenisation failed: input too long'));\n\n const result = await embed(mockExtractor, 'bad input');\n expect(result).toFailWith(/tokenisation failed/i);\n });\n});\n\n// ─── summarize ──────────────────────────────────────────────────────────────────\n\ndescribe('summarize', () => {\n let mockSummarizer: jest.MockedFunction<SummarizationPipeline>;\n\n beforeEach(() => {\n jest.resetAllMocks();\n mockSummarizer = jest.fn() as unknown as jest.MockedFunction<SummarizationPipeline>;\n });\n\n test('returns Success wrapping SummarizationOutput on success', async () => {\n const mockOutput: SummarizationOutput = [{ summary_text: 'A short summary.' }];\n mockSummarizer.mockResolvedValueOnce(mockOutput);\n\n const result = await summarize(mockSummarizer, 'A long article that needs summarizing.');\n expect(result).toSucceedWith(mockOutput);\n });\n\n test('passes text to the upstream summarizer', async () => {\n const mockOutput: SummarizationOutput = [{ summary_text: 'Summary.' }];\n mockSummarizer.mockResolvedValueOnce(mockOutput);\n\n await summarize(mockSummarizer, 'some long document');\n expect(mockSummarizer).toHaveBeenCalledWith('some long document', undefined);\n });\n\n test('passes options through to the upstream summarizer', async () => {\n const mockOutput: SummarizationOutput = [{ summary_text: 'Bounded summary.' }];\n mockSummarizer.mockResolvedValueOnce(mockOutput);\n\n const opts = { min_length: 10, max_length: 50 };\n await summarize(mockSummarizer, 'a document', opts);\n expect(mockSummarizer).toHaveBeenCalledWith('a document', opts);\n });\n\n test('returns Failure capturing upstream inference error', async () => {\n mockSummarizer.mockRejectedValueOnce(new Error('Inference session error: out of memory'));\n\n const result = await summarize(mockSummarizer, 'some text');\n expect(result).toFailWith(/inference session error/i);\n });\n\n test('returns Failure capturing upstream tokenisation error', async () => {\n mockSummarizer.mockRejectedValueOnce(new Error('Tokenisation failed: input too long'));\n\n const result = await summarize(mockSummarizer, 'bad input');\n expect(result).toFailWith(/tokenisation failed/i);\n });\n});\n"]}
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* mirroring the discipline established by `@fgv/ts-extras-webauthn`: one-line `captureAsyncResult`
|
|
7
7
|
* wrappers around upstream primitives with **no opinionated orchestration** above the boundary.
|
|
8
8
|
*
|
|
9
|
-
* **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed` — the
|
|
10
|
-
*
|
|
11
|
-
* concrete consumer use case surfaces (
|
|
9
|
+
* **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed`, `summarize` — the task types
|
|
10
|
+
* exercised by real consumers so far. The general `generate` primitive is explicitly deferred
|
|
11
|
+
* until a concrete consumer use case surfaces (summarization is its own task-specific primitive).
|
|
12
12
|
*
|
|
13
13
|
* **Explicitly NOT in scope:**
|
|
14
14
|
* - Pipeline cache / lifecycle management
|
|
@@ -32,6 +32,8 @@ import { pipeline } from '@huggingface/transformers';
|
|
|
32
32
|
import { PipelineType } from '@huggingface/transformers';
|
|
33
33
|
import { PretrainedModelOptions } from '@huggingface/transformers';
|
|
34
34
|
import { Result } from '@fgv/ts-utils';
|
|
35
|
+
import { SummarizationOutput } from '@huggingface/transformers';
|
|
36
|
+
import { SummarizationPipeline } from '@huggingface/transformers';
|
|
35
37
|
import { Tensor } from '@huggingface/transformers';
|
|
36
38
|
import { TextClassificationOutput } from '@huggingface/transformers';
|
|
37
39
|
import { TextClassificationPipeline } from '@huggingface/transformers';
|
|
@@ -128,6 +130,33 @@ export { PipelineType }
|
|
|
128
130
|
|
|
129
131
|
export { PretrainedModelOptions }
|
|
130
132
|
|
|
133
|
+
export { SummarizationOutput }
|
|
134
|
+
|
|
135
|
+
export { SummarizationPipeline }
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Result-integration wrapper that invokes a `SummarizationPipeline` on a single text input.
|
|
139
|
+
* Returns the upstream `SummarizationOutput` Result-wrapped (an array of `{ summary_text }`
|
|
140
|
+
* entries; one for a single-string input).
|
|
141
|
+
*
|
|
142
|
+
* Callers should retrieve the summarizer via `loadPipeline('summarization', modelId)` — e.g.
|
|
143
|
+
* `Xenova/distilbart-cnn-6-6` for a small, local-friendly model. This facade applies no opinionated
|
|
144
|
+
* orchestration (no length policy, no local-vs-cloud routing) — `options` are passed through
|
|
145
|
+
* verbatim and the caller owns any escalation decision.
|
|
146
|
+
*
|
|
147
|
+
* Returns `Promise<Result<SummarizationOutput>>`; upstream errors (inference failures, tokenisation
|
|
148
|
+
* errors) are captured as `Failure` with the original message.
|
|
149
|
+
*
|
|
150
|
+
* @param summarizer - A `SummarizationPipeline` obtained from `loadPipeline`.
|
|
151
|
+
* @param text - The text to summarize.
|
|
152
|
+
* @param options - Optional upstream summarization options (e.g. `min_length`, `max_length`,
|
|
153
|
+
* `max_new_tokens`). Passed through verbatim to the pipeline call.
|
|
154
|
+
*
|
|
155
|
+
* @see https://huggingface.co/docs/transformers.js
|
|
156
|
+
* @public
|
|
157
|
+
*/
|
|
158
|
+
export declare function summarize(summarizer: SummarizationPipeline, text: string, options?: Parameters<SummarizationPipeline>[1]): Promise<Result<SummarizationOutput>>;
|
|
159
|
+
|
|
131
160
|
export { Tensor }
|
|
132
161
|
|
|
133
162
|
export { TextClassificationOutput }
|
|
@@ -10,6 +10,8 @@ import { pipeline } from '@huggingface/transformers';
|
|
|
10
10
|
import { PipelineType } from '@huggingface/transformers';
|
|
11
11
|
import { PretrainedModelOptions } from '@huggingface/transformers';
|
|
12
12
|
import { Result } from '@fgv/ts-utils';
|
|
13
|
+
import { SummarizationOutput } from '@huggingface/transformers';
|
|
14
|
+
import { SummarizationPipeline } from '@huggingface/transformers';
|
|
13
15
|
import { Tensor } from '@huggingface/transformers';
|
|
14
16
|
import { TextClassificationOutput } from '@huggingface/transformers';
|
|
15
17
|
import { TextClassificationPipeline } from '@huggingface/transformers';
|
|
@@ -34,6 +36,13 @@ export { PipelineType }
|
|
|
34
36
|
|
|
35
37
|
export { PretrainedModelOptions }
|
|
36
38
|
|
|
39
|
+
export { SummarizationOutput }
|
|
40
|
+
|
|
41
|
+
export { SummarizationPipeline }
|
|
42
|
+
|
|
43
|
+
// @public
|
|
44
|
+
export function summarize(summarizer: SummarizationPipeline, text: string, options?: Parameters<SummarizationPipeline>[1]): Promise<Result<SummarizationOutput>>;
|
|
45
|
+
|
|
37
46
|
export { Tensor }
|
|
38
47
|
|
|
39
48
|
export { TextClassificationOutput }
|
package/lib/index.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* mirroring the discipline established by `@fgv/ts-extras-webauthn`: one-line `captureAsyncResult`
|
|
7
7
|
* wrappers around upstream primitives with **no opinionated orchestration** above the boundary.
|
|
8
8
|
*
|
|
9
|
-
* **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed` — the
|
|
10
|
-
*
|
|
11
|
-
* concrete consumer use case surfaces (
|
|
9
|
+
* **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed`, `summarize` — the task types
|
|
10
|
+
* exercised by real consumers so far. The general `generate` primitive is explicitly deferred
|
|
11
|
+
* until a concrete consumer use case surfaces (summarization is its own task-specific primitive).
|
|
12
12
|
*
|
|
13
13
|
* **Explicitly NOT in scope:**
|
|
14
14
|
* - Pipeline cache / lifecycle management
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
*
|
|
26
26
|
* @packageDocumentation
|
|
27
27
|
*/
|
|
28
|
-
import { pipeline as _pipeline, type TextClassificationPipeline, type TextClassificationOutput, type FeatureExtractionPipeline, type Tensor, type AllTasks, type PipelineType } from '@huggingface/transformers';
|
|
28
|
+
import { pipeline as _pipeline, type TextClassificationPipeline, type TextClassificationOutput, type FeatureExtractionPipeline, type SummarizationPipeline, type SummarizationOutput, type Tensor, type AllTasks, type PipelineType } from '@huggingface/transformers';
|
|
29
29
|
import { type Result } from '@fgv/ts-utils';
|
|
30
|
-
export type { TextClassificationPipeline, TextClassificationOutput, FeatureExtractionPipeline, Tensor, AllTasks, PipelineType };
|
|
30
|
+
export type { TextClassificationPipeline, TextClassificationOutput, FeatureExtractionPipeline, SummarizationPipeline, SummarizationOutput, Tensor, AllTasks, PipelineType };
|
|
31
31
|
export type { PretrainedModelOptions } from '@huggingface/transformers';
|
|
32
32
|
/**
|
|
33
33
|
* Result-integration wrapper around `@huggingface/transformers`'s `pipeline` factory.
|
|
@@ -109,4 +109,26 @@ export declare function classifyAll(classifier: TextClassificationPipeline, text
|
|
|
109
109
|
* @public
|
|
110
110
|
*/
|
|
111
111
|
export declare function embed(extractor: FeatureExtractionPipeline, text: string | string[], options?: Parameters<FeatureExtractionPipeline['_call']>[1]): Promise<Result<Tensor>>;
|
|
112
|
+
/**
|
|
113
|
+
* Result-integration wrapper that invokes a `SummarizationPipeline` on a single text input.
|
|
114
|
+
* Returns the upstream `SummarizationOutput` Result-wrapped (an array of `{ summary_text }`
|
|
115
|
+
* entries; one for a single-string input).
|
|
116
|
+
*
|
|
117
|
+
* Callers should retrieve the summarizer via `loadPipeline('summarization', modelId)` — e.g.
|
|
118
|
+
* `Xenova/distilbart-cnn-6-6` for a small, local-friendly model. This facade applies no opinionated
|
|
119
|
+
* orchestration (no length policy, no local-vs-cloud routing) — `options` are passed through
|
|
120
|
+
* verbatim and the caller owns any escalation decision.
|
|
121
|
+
*
|
|
122
|
+
* Returns `Promise<Result<SummarizationOutput>>`; upstream errors (inference failures, tokenisation
|
|
123
|
+
* errors) are captured as `Failure` with the original message.
|
|
124
|
+
*
|
|
125
|
+
* @param summarizer - A `SummarizationPipeline` obtained from `loadPipeline`.
|
|
126
|
+
* @param text - The text to summarize.
|
|
127
|
+
* @param options - Optional upstream summarization options (e.g. `min_length`, `max_length`,
|
|
128
|
+
* `max_new_tokens`). Passed through verbatim to the pipeline call.
|
|
129
|
+
*
|
|
130
|
+
* @see https://huggingface.co/docs/transformers.js
|
|
131
|
+
* @public
|
|
132
|
+
*/
|
|
133
|
+
export declare function summarize(summarizer: SummarizationPipeline, text: string, options?: Parameters<SummarizationPipeline>[1]): Promise<Result<SummarizationOutput>>;
|
|
112
134
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,QAAQ,IAAI,SAAS,EACrB,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,YAAY,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAsB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAEhE,YAAY,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,MAAM,EACN,QAAQ,EACR,YAAY,EACb,CAAC;AAEF,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAExE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,YAAY,EACvD,IAAI,EAAE,CAAC,EACP,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAE9B;AAqBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,0BAA0B,EACtC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,UAAU,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAK3C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,WAAW,CAC/B,UAAU,EAAE,0BAA0B,EACtC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,UAAU,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAE3C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,KAAK,CACzB,SAAS,EAAE,yBAAyB,EACpC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,UAAU,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAC1D,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAEzB"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,QAAQ,IAAI,SAAS,EACrB,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,YAAY,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAsB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAEhE,YAAY,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,MAAM,EACN,QAAQ,EACR,YAAY,EACb,CAAC;AAEF,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAExE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,YAAY,EACvD,IAAI,EAAE,CAAC,EACP,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAE9B;AAqBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,0BAA0B,EACtC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,UAAU,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAK3C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,WAAW,CAC/B,UAAU,EAAE,0BAA0B,EACtC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,UAAU,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAE3C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,KAAK,CACzB,SAAS,EAAE,yBAAyB,EACpC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,UAAU,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAC1D,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAEzB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,qBAAqB,EACjC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAEtC"}
|
package/lib/index.js
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* mirroring the discipline established by `@fgv/ts-extras-webauthn`: one-line `captureAsyncResult`
|
|
8
8
|
* wrappers around upstream primitives with **no opinionated orchestration** above the boundary.
|
|
9
9
|
*
|
|
10
|
-
* **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed` — the
|
|
11
|
-
*
|
|
12
|
-
* concrete consumer use case surfaces (
|
|
10
|
+
* **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed`, `summarize` — the task types
|
|
11
|
+
* exercised by real consumers so far. The general `generate` primitive is explicitly deferred
|
|
12
|
+
* until a concrete consumer use case surfaces (summarization is its own task-specific primitive).
|
|
13
13
|
*
|
|
14
14
|
* **Explicitly NOT in scope:**
|
|
15
15
|
* - Pipeline cache / lifecycle management
|
|
@@ -31,6 +31,7 @@ exports.loadPipeline = loadPipeline;
|
|
|
31
31
|
exports.classify = classify;
|
|
32
32
|
exports.classifyAll = classifyAll;
|
|
33
33
|
exports.embed = embed;
|
|
34
|
+
exports.summarize = summarize;
|
|
34
35
|
const transformers_1 = require("@huggingface/transformers");
|
|
35
36
|
const ts_utils_1 = require("@fgv/ts-utils");
|
|
36
37
|
/**
|
|
@@ -140,4 +141,28 @@ async function classifyAll(classifier, text, options) {
|
|
|
140
141
|
async function embed(extractor, text, options) {
|
|
141
142
|
return (0, ts_utils_1.captureAsyncResult)(() => extractor(text, options));
|
|
142
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Result-integration wrapper that invokes a `SummarizationPipeline` on a single text input.
|
|
146
|
+
* Returns the upstream `SummarizationOutput` Result-wrapped (an array of `{ summary_text }`
|
|
147
|
+
* entries; one for a single-string input).
|
|
148
|
+
*
|
|
149
|
+
* Callers should retrieve the summarizer via `loadPipeline('summarization', modelId)` — e.g.
|
|
150
|
+
* `Xenova/distilbart-cnn-6-6` for a small, local-friendly model. This facade applies no opinionated
|
|
151
|
+
* orchestration (no length policy, no local-vs-cloud routing) — `options` are passed through
|
|
152
|
+
* verbatim and the caller owns any escalation decision.
|
|
153
|
+
*
|
|
154
|
+
* Returns `Promise<Result<SummarizationOutput>>`; upstream errors (inference failures, tokenisation
|
|
155
|
+
* errors) are captured as `Failure` with the original message.
|
|
156
|
+
*
|
|
157
|
+
* @param summarizer - A `SummarizationPipeline` obtained from `loadPipeline`.
|
|
158
|
+
* @param text - The text to summarize.
|
|
159
|
+
* @param options - Optional upstream summarization options (e.g. `min_length`, `max_length`,
|
|
160
|
+
* `max_new_tokens`). Passed through verbatim to the pipeline call.
|
|
161
|
+
*
|
|
162
|
+
* @see https://huggingface.co/docs/transformers.js
|
|
163
|
+
* @public
|
|
164
|
+
*/
|
|
165
|
+
async function summarize(summarizer, text, options) {
|
|
166
|
+
return (0, ts_utils_1.captureAsyncResult)(() => summarizer(text, options));
|
|
167
|
+
}
|
|
143
168
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;AA4CH,oCAMC;AA0CD,4BASC;AAmBD,kCAMC;AAoBD,sBAMC;AAtJD,4DAQmC;AACnC,4CAAgE;AAahE;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,YAAY,CAChC,IAAO,EACP,KAAc,EACd,OAAyC;IAEzC,OAAO,IAAA,6BAAkB,EAAC,GAAG,EAAE,CAAC,IAAA,uBAAS,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CACtB,MAA6D;IAE7D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,OAAO,MAAkC,CAAC;IAC5C,CAAC;IACD,yEAAyE;IACzE,OAAQ,MAAgD,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACI,KAAK,UAAU,QAAQ,CAC5B,UAAsC,EACtC,IAAY,EACZ,OAAmD;IAEnD,OAAO,IAAA,6BAAkB,EAAC,KAAK,IAAI,EAAE;QACnC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,WAAW,CAC/B,UAAsC,EACtC,IAAY,EACZ,OAAmD;IAEnD,OAAO,QAAQ,CAAC,UAAU,EAAE,IAAI,kCAAO,OAAO,KAAE,KAAK,EAAE,IAAI,IAAG,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACI,KAAK,UAAU,KAAK,CACzB,SAAoC,EACpC,IAAuB,EACvB,OAA2D;IAE3D,OAAO,IAAA,6BAAkB,EAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC","sourcesContent":["/**\n * `@fgv/ts-extras-transformers` — Result-integration boundary over `@huggingface/transformers`\n * (Node-side).\n *\n * A thin facade that wraps `@huggingface/transformers` calls in `Result<T>` from `@fgv/ts-utils`,\n * mirroring the discipline established by `@fgv/ts-extras-webauthn`: one-line `captureAsyncResult`\n * wrappers around upstream primitives with **no opinionated orchestration** above the boundary.\n *\n * **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed` — the surface needed by the\n * B-3/B-4a local-classifier and embedding scenarios. `generate` is explicitly deferred until a\n * concrete consumer use case surfaces (see `phase-b2-result.md`).\n *\n * **Explicitly NOT in scope:**\n * - Pipeline cache / lifecycle management\n * - Model registry or download management\n * - GPU/CPU device selection policy\n * - Quantization selection\n * - Embedding-store integration\n * - Classifier label allowlists\n * - Request batching\n * - Pipeline dispose semantics\n *\n * For any of the above, use `@huggingface/transformers` directly (with `captureAsyncResult` for\n * your own Result wrapping).\n *\n * @packageDocumentation\n */\n\nimport {\n pipeline as _pipeline,\n type TextClassificationPipeline,\n type TextClassificationOutput,\n type FeatureExtractionPipeline,\n type Tensor,\n type AllTasks,\n type PipelineType\n} from '@huggingface/transformers';\nimport { captureAsyncResult, type Result } from '@fgv/ts-utils';\n\nexport type {\n TextClassificationPipeline,\n TextClassificationOutput,\n FeatureExtractionPipeline,\n Tensor,\n AllTasks,\n PipelineType\n};\n\nexport type { PretrainedModelOptions } from '@huggingface/transformers';\n\n/**\n * Result-integration wrapper around `@huggingface/transformers`'s `pipeline` factory.\n * Loads a model and returns a ready-to-use pipeline object.\n *\n * The returned pipeline is the upstream `AllTasks[T]` instance — consumers retain full access\n * to the upstream API. Lifecycle management (caching, disposal, GPU/CPU selection) is the\n * consumer's responsibility.\n *\n * Returns `Promise<Result<AllTasks[T]>>`; upstream errors (network, model-not-found, ONNX\n * initialization failures) are captured as `Failure` with the original message.\n *\n * @param task - The pipeline task type (e.g. `'text-classification'`, `'feature-extraction'`).\n * @param model - The model identifier (HuggingFace Hub ID or local path). If omitted, the\n * upstream default for the task is used.\n * @param options - Optional `PretrainedModelOptions` (device, dtype, cache_dir, etc.). Passed\n * through verbatim to the upstream `pipeline()` call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function loadPipeline<T extends PipelineType>(\n task: T,\n model?: string,\n options?: Parameters<typeof _pipeline>[2]\n): Promise<Result<AllTasks[T]>> {\n return captureAsyncResult(() => _pipeline(task, model, options));\n}\n\n/**\n * Normalises the upstream pipeline's output to a flat `TextClassificationOutput`.\n *\n * The upstream `TextClassificationPipeline` has an overloaded call signature: a single-string\n * input returns `TextClassificationOutput` (flat array), while a string-array input returns\n * `TextClassificationOutput[]` (array-of-arrays). Since `classify` always passes a single\n * string, the flat-array path is the live path. The nested-array branch is defensive and\n * ensures consumers always receive a flat array even if the upstream type union leaks through.\n */\nfunction flattenIfNeeded(\n result: TextClassificationOutput | TextClassificationOutput[]\n): TextClassificationOutput {\n if (Array.isArray(result) && result.length > 0 && !Array.isArray(result[0])) {\n return result as TextClassificationOutput;\n }\n // Defensive: if somehow an array-of-arrays came back, flatten one level.\n return (result as unknown as TextClassificationOutput[]).flat();\n}\n\n/**\n * Result-integration wrapper that invokes a `TextClassificationPipeline` on a single text input.\n * Returns the classification results as a flat `TextClassificationOutput` (array of\n * `{ label: string; score: number }` entries).\n *\n * Callers should retrieve the pipeline via `loadPipeline('text-classification', modelId)` (or the\n * `'sentiment-analysis'` alias). This helper always passes a single string to the upstream\n * pipeline and normalises the result to `TextClassificationOutput` so consumers don't need to\n * handle the `string | string[]` overload union.\n *\n * Returns `Promise<Result<TextClassificationOutput>>`; upstream errors (inference failures,\n * tokenisation errors) are captured as `Failure` with the original message.\n *\n * @param classifier - A `TextClassificationPipeline` obtained from `loadPipeline`.\n * @param text - The text to classify.\n * @param options - Optional upstream classification options (e.g. `{ top_k: null }` to return\n * all labels). Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function classify(\n classifier: TextClassificationPipeline,\n text: string,\n options?: Parameters<TextClassificationPipeline>[1]\n): Promise<Result<TextClassificationOutput>> {\n return captureAsyncResult(async () => {\n const result = await classifier(text, options);\n return flattenIfNeeded(result);\n });\n}\n\n/**\n * Convenience wrapper over `classify` that forces `top_k: null` so the full per-label vector\n * is returned for every call. Callers no longer need to remember to pass `{ top_k: null }`.\n *\n * Any caller-supplied options are honoured except `top_k`, which is always overridden to `null`.\n *\n * Returns `Promise<Result<TextClassificationOutput>>`; upstream errors are captured as `Failure`\n * with the original message.\n *\n * @param classifier - A `TextClassificationPipeline` obtained from `loadPipeline`.\n * @param text - The text to classify.\n * @param options - Optional upstream classification options. `top_k` is always set to `null`\n * regardless of any value supplied here.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function classifyAll(\n classifier: TextClassificationPipeline,\n text: string,\n options?: Parameters<TextClassificationPipeline>[1]\n): Promise<Result<TextClassificationOutput>> {\n return classify(classifier, text, { ...options, top_k: null });\n}\n\n/**\n * Result-integration wrapper that invokes a `FeatureExtractionPipeline` on a text input.\n * Returns the upstream `Tensor` Result-wrapped — no pooling, normalisation, or reshaping is\n * applied. Callers receive the raw output and are responsible for any downstream processing.\n *\n * Callers should retrieve the extractor via `loadPipeline('feature-extraction', modelId)`.\n *\n * Returns `Promise<Result<Tensor>>`; upstream errors (inference failures, tokenisation errors)\n * are captured as `Failure` with the original message.\n *\n * @param extractor - A `FeatureExtractionPipeline` obtained from `loadPipeline`.\n * @param text - The text (or texts) to embed.\n * @param options - Optional upstream feature-extraction options (e.g. `pooling`, `normalize`).\n * Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function embed(\n extractor: FeatureExtractionPipeline,\n text: string | string[],\n options?: Parameters<FeatureExtractionPipeline['_call']>[1]\n): Promise<Result<Tensor>> {\n return captureAsyncResult(() => extractor(text, options));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;AAgDH,oCAMC;AA0CD,4BASC;AAmBD,kCAMC;AAoBD,sBAMC;AAuBD,8BAMC;AAvLD,4DAUmC;AACnC,4CAAgE;AAehE;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,YAAY,CAChC,IAAO,EACP,KAAc,EACd,OAAyC;IAEzC,OAAO,IAAA,6BAAkB,EAAC,GAAG,EAAE,CAAC,IAAA,uBAAS,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CACtB,MAA6D;IAE7D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,OAAO,MAAkC,CAAC;IAC5C,CAAC;IACD,yEAAyE;IACzE,OAAQ,MAAgD,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACI,KAAK,UAAU,QAAQ,CAC5B,UAAsC,EACtC,IAAY,EACZ,OAAmD;IAEnD,OAAO,IAAA,6BAAkB,EAAC,KAAK,IAAI,EAAE;QACnC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,WAAW,CAC/B,UAAsC,EACtC,IAAY,EACZ,OAAmD;IAEnD,OAAO,QAAQ,CAAC,UAAU,EAAE,IAAI,kCAAO,OAAO,KAAE,KAAK,EAAE,IAAI,IAAG,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACI,KAAK,UAAU,KAAK,CACzB,SAAoC,EACpC,IAAuB,EACvB,OAA2D;IAE3D,OAAO,IAAA,6BAAkB,EAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACI,KAAK,UAAU,SAAS,CAC7B,UAAiC,EACjC,IAAY,EACZ,OAA8C;IAE9C,OAAO,IAAA,6BAAkB,EAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC","sourcesContent":["/**\n * `@fgv/ts-extras-transformers` — Result-integration boundary over `@huggingface/transformers`\n * (Node-side).\n *\n * A thin facade that wraps `@huggingface/transformers` calls in `Result<T>` from `@fgv/ts-utils`,\n * mirroring the discipline established by `@fgv/ts-extras-webauthn`: one-line `captureAsyncResult`\n * wrappers around upstream primitives with **no opinionated orchestration** above the boundary.\n *\n * **In scope:** `loadPipeline`, `classify`, `classifyAll`, `embed`, `summarize` — the task types\n * exercised by real consumers so far. The general `generate` primitive is explicitly deferred\n * until a concrete consumer use case surfaces (summarization is its own task-specific primitive).\n *\n * **Explicitly NOT in scope:**\n * - Pipeline cache / lifecycle management\n * - Model registry or download management\n * - GPU/CPU device selection policy\n * - Quantization selection\n * - Embedding-store integration\n * - Classifier label allowlists\n * - Request batching\n * - Pipeline dispose semantics\n *\n * For any of the above, use `@huggingface/transformers` directly (with `captureAsyncResult` for\n * your own Result wrapping).\n *\n * @packageDocumentation\n */\n\nimport {\n pipeline as _pipeline,\n type TextClassificationPipeline,\n type TextClassificationOutput,\n type FeatureExtractionPipeline,\n type SummarizationPipeline,\n type SummarizationOutput,\n type Tensor,\n type AllTasks,\n type PipelineType\n} from '@huggingface/transformers';\nimport { captureAsyncResult, type Result } from '@fgv/ts-utils';\n\nexport type {\n TextClassificationPipeline,\n TextClassificationOutput,\n FeatureExtractionPipeline,\n SummarizationPipeline,\n SummarizationOutput,\n Tensor,\n AllTasks,\n PipelineType\n};\n\nexport type { PretrainedModelOptions } from '@huggingface/transformers';\n\n/**\n * Result-integration wrapper around `@huggingface/transformers`'s `pipeline` factory.\n * Loads a model and returns a ready-to-use pipeline object.\n *\n * The returned pipeline is the upstream `AllTasks[T]` instance — consumers retain full access\n * to the upstream API. Lifecycle management (caching, disposal, GPU/CPU selection) is the\n * consumer's responsibility.\n *\n * Returns `Promise<Result<AllTasks[T]>>`; upstream errors (network, model-not-found, ONNX\n * initialization failures) are captured as `Failure` with the original message.\n *\n * @param task - The pipeline task type (e.g. `'text-classification'`, `'feature-extraction'`).\n * @param model - The model identifier (HuggingFace Hub ID or local path). If omitted, the\n * upstream default for the task is used.\n * @param options - Optional `PretrainedModelOptions` (device, dtype, cache_dir, etc.). Passed\n * through verbatim to the upstream `pipeline()` call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function loadPipeline<T extends PipelineType>(\n task: T,\n model?: string,\n options?: Parameters<typeof _pipeline>[2]\n): Promise<Result<AllTasks[T]>> {\n return captureAsyncResult(() => _pipeline(task, model, options));\n}\n\n/**\n * Normalises the upstream pipeline's output to a flat `TextClassificationOutput`.\n *\n * The upstream `TextClassificationPipeline` has an overloaded call signature: a single-string\n * input returns `TextClassificationOutput` (flat array), while a string-array input returns\n * `TextClassificationOutput[]` (array-of-arrays). Since `classify` always passes a single\n * string, the flat-array path is the live path. The nested-array branch is defensive and\n * ensures consumers always receive a flat array even if the upstream type union leaks through.\n */\nfunction flattenIfNeeded(\n result: TextClassificationOutput | TextClassificationOutput[]\n): TextClassificationOutput {\n if (Array.isArray(result) && result.length > 0 && !Array.isArray(result[0])) {\n return result as TextClassificationOutput;\n }\n // Defensive: if somehow an array-of-arrays came back, flatten one level.\n return (result as unknown as TextClassificationOutput[]).flat();\n}\n\n/**\n * Result-integration wrapper that invokes a `TextClassificationPipeline` on a single text input.\n * Returns the classification results as a flat `TextClassificationOutput` (array of\n * `{ label: string; score: number }` entries).\n *\n * Callers should retrieve the pipeline via `loadPipeline('text-classification', modelId)` (or the\n * `'sentiment-analysis'` alias). This helper always passes a single string to the upstream\n * pipeline and normalises the result to `TextClassificationOutput` so consumers don't need to\n * handle the `string | string[]` overload union.\n *\n * Returns `Promise<Result<TextClassificationOutput>>`; upstream errors (inference failures,\n * tokenisation errors) are captured as `Failure` with the original message.\n *\n * @param classifier - A `TextClassificationPipeline` obtained from `loadPipeline`.\n * @param text - The text to classify.\n * @param options - Optional upstream classification options (e.g. `{ top_k: null }` to return\n * all labels). Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function classify(\n classifier: TextClassificationPipeline,\n text: string,\n options?: Parameters<TextClassificationPipeline>[1]\n): Promise<Result<TextClassificationOutput>> {\n return captureAsyncResult(async () => {\n const result = await classifier(text, options);\n return flattenIfNeeded(result);\n });\n}\n\n/**\n * Convenience wrapper over `classify` that forces `top_k: null` so the full per-label vector\n * is returned for every call. Callers no longer need to remember to pass `{ top_k: null }`.\n *\n * Any caller-supplied options are honoured except `top_k`, which is always overridden to `null`.\n *\n * Returns `Promise<Result<TextClassificationOutput>>`; upstream errors are captured as `Failure`\n * with the original message.\n *\n * @param classifier - A `TextClassificationPipeline` obtained from `loadPipeline`.\n * @param text - The text to classify.\n * @param options - Optional upstream classification options. `top_k` is always set to `null`\n * regardless of any value supplied here.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function classifyAll(\n classifier: TextClassificationPipeline,\n text: string,\n options?: Parameters<TextClassificationPipeline>[1]\n): Promise<Result<TextClassificationOutput>> {\n return classify(classifier, text, { ...options, top_k: null });\n}\n\n/**\n * Result-integration wrapper that invokes a `FeatureExtractionPipeline` on a text input.\n * Returns the upstream `Tensor` Result-wrapped — no pooling, normalisation, or reshaping is\n * applied. Callers receive the raw output and are responsible for any downstream processing.\n *\n * Callers should retrieve the extractor via `loadPipeline('feature-extraction', modelId)`.\n *\n * Returns `Promise<Result<Tensor>>`; upstream errors (inference failures, tokenisation errors)\n * are captured as `Failure` with the original message.\n *\n * @param extractor - A `FeatureExtractionPipeline` obtained from `loadPipeline`.\n * @param text - The text (or texts) to embed.\n * @param options - Optional upstream feature-extraction options (e.g. `pooling`, `normalize`).\n * Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function embed(\n extractor: FeatureExtractionPipeline,\n text: string | string[],\n options?: Parameters<FeatureExtractionPipeline['_call']>[1]\n): Promise<Result<Tensor>> {\n return captureAsyncResult(() => extractor(text, options));\n}\n\n/**\n * Result-integration wrapper that invokes a `SummarizationPipeline` on a single text input.\n * Returns the upstream `SummarizationOutput` Result-wrapped (an array of `{ summary_text }`\n * entries; one for a single-string input).\n *\n * Callers should retrieve the summarizer via `loadPipeline('summarization', modelId)` — e.g.\n * `Xenova/distilbart-cnn-6-6` for a small, local-friendly model. This facade applies no opinionated\n * orchestration (no length policy, no local-vs-cloud routing) — `options` are passed through\n * verbatim and the caller owns any escalation decision.\n *\n * Returns `Promise<Result<SummarizationOutput>>`; upstream errors (inference failures, tokenisation\n * errors) are captured as `Failure` with the original message.\n *\n * @param summarizer - A `SummarizationPipeline` obtained from `loadPipeline`.\n * @param text - The text to summarize.\n * @param options - Optional upstream summarization options (e.g. `min_length`, `max_length`,\n * `max_new_tokens`). Passed through verbatim to the pipeline call.\n *\n * @see https://huggingface.co/docs/transformers.js\n * @public\n */\nexport async function summarize(\n summarizer: SummarizationPipeline,\n text: string,\n options?: Parameters<SummarizationPipeline>[1]\n): Promise<Result<SummarizationOutput>> {\n return captureAsyncResult(() => summarizer(text, options));\n}\n"]}
|
|
@@ -229,4 +229,41 @@ describe('embed', () => {
|
|
|
229
229
|
expect(result).toFailWith(/tokenisation failed/i);
|
|
230
230
|
});
|
|
231
231
|
});
|
|
232
|
+
// ─── summarize ──────────────────────────────────────────────────────────────────
|
|
233
|
+
describe('summarize', () => {
|
|
234
|
+
let mockSummarizer;
|
|
235
|
+
beforeEach(() => {
|
|
236
|
+
jest.resetAllMocks();
|
|
237
|
+
mockSummarizer = jest.fn();
|
|
238
|
+
});
|
|
239
|
+
test('returns Success wrapping SummarizationOutput on success', async () => {
|
|
240
|
+
const mockOutput = [{ summary_text: 'A short summary.' }];
|
|
241
|
+
mockSummarizer.mockResolvedValueOnce(mockOutput);
|
|
242
|
+
const result = await (0, index_1.summarize)(mockSummarizer, 'A long article that needs summarizing.');
|
|
243
|
+
expect(result).toSucceedWith(mockOutput);
|
|
244
|
+
});
|
|
245
|
+
test('passes text to the upstream summarizer', async () => {
|
|
246
|
+
const mockOutput = [{ summary_text: 'Summary.' }];
|
|
247
|
+
mockSummarizer.mockResolvedValueOnce(mockOutput);
|
|
248
|
+
await (0, index_1.summarize)(mockSummarizer, 'some long document');
|
|
249
|
+
expect(mockSummarizer).toHaveBeenCalledWith('some long document', undefined);
|
|
250
|
+
});
|
|
251
|
+
test('passes options through to the upstream summarizer', async () => {
|
|
252
|
+
const mockOutput = [{ summary_text: 'Bounded summary.' }];
|
|
253
|
+
mockSummarizer.mockResolvedValueOnce(mockOutput);
|
|
254
|
+
const opts = { min_length: 10, max_length: 50 };
|
|
255
|
+
await (0, index_1.summarize)(mockSummarizer, 'a document', opts);
|
|
256
|
+
expect(mockSummarizer).toHaveBeenCalledWith('a document', opts);
|
|
257
|
+
});
|
|
258
|
+
test('returns Failure capturing upstream inference error', async () => {
|
|
259
|
+
mockSummarizer.mockRejectedValueOnce(new Error('Inference session error: out of memory'));
|
|
260
|
+
const result = await (0, index_1.summarize)(mockSummarizer, 'some text');
|
|
261
|
+
expect(result).toFailWith(/inference session error/i);
|
|
262
|
+
});
|
|
263
|
+
test('returns Failure capturing upstream tokenisation error', async () => {
|
|
264
|
+
mockSummarizer.mockRejectedValueOnce(new Error('Tokenisation failed: input too long'));
|
|
265
|
+
const result = await (0, index_1.summarize)(mockSummarizer, 'bad input');
|
|
266
|
+
expect(result).toFailWith(/tokenisation failed/i);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
232
269
|
//# sourceMappingURL=transformers.test.js.map
|