@workglow/ai-provider 0.0.70 → 0.0.71
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/dist/hf-transformers/common/HFT_JobRunFns.d.ts +3 -1
- package/dist/hf-transformers/common/HFT_JobRunFns.d.ts.map +1 -1
- package/dist/hf-transformers/registry/HFT_Client_RegisterJobFns.d.ts.map +1 -1
- package/dist/hf-transformers/registry/HFT_Inline_RegisterJobFns.d.ts.map +1 -1
- package/dist/hf-transformers/registry/HFT_Worker_RegisterJobFns.d.ts.map +1 -1
- package/dist/index.js +112 -37
- package/dist/index.js.map +7 -7
- package/dist/tf-mediapipe/common/TFMP_JobRunFns.d.ts +2 -2
- package/dist/tf-mediapipe/common/TFMP_JobRunFns.d.ts.map +1 -1
- package/package.json +11 -11
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Copyright 2025 Steven Roussey <sroussey@gmail.com>
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { AiProviderRunFn, DownloadModelTaskExecuteInput, DownloadModelTaskExecuteOutput, TextClassifierTaskExecuteInput, TextClassifierTaskExecuteOutput, TextEmbeddingTaskExecuteInput, TextEmbeddingTaskExecuteOutput, TextGenerationTaskExecuteInput, TextGenerationTaskExecuteOutput, TextLanguageDetectionTaskExecuteInput, TextLanguageDetectionTaskExecuteOutput, TextQuestionAnswerTaskExecuteInput, TextQuestionAnswerTaskExecuteOutput, TextRewriterTaskExecuteInput, TextRewriterTaskExecuteOutput, TextSummaryTaskExecuteInput, TextSummaryTaskExecuteOutput, TextTranslationTaskExecuteInput, TextTranslationTaskExecuteOutput, UnloadModelTaskExecuteInput, UnloadModelTaskExecuteOutput } from "@workglow/ai";
|
|
6
|
+
import { AiProviderRunFn, DownloadModelTaskExecuteInput, DownloadModelTaskExecuteOutput, TextClassifierTaskExecuteInput, TextClassifierTaskExecuteOutput, TextEmbeddingTaskExecuteInput, TextEmbeddingTaskExecuteOutput, TextFillMaskTaskExecuteInput, TextFillMaskTaskExecuteOutput, TextGenerationTaskExecuteInput, TextGenerationTaskExecuteOutput, TextLanguageDetectionTaskExecuteInput, TextLanguageDetectionTaskExecuteOutput, TextNamedEntityRecognitionTaskExecuteInput, TextNamedEntityRecognitionTaskExecuteOutput, TextQuestionAnswerTaskExecuteInput, TextQuestionAnswerTaskExecuteOutput, TextRewriterTaskExecuteInput, TextRewriterTaskExecuteOutput, TextSummaryTaskExecuteInput, TextSummaryTaskExecuteOutput, TextTranslationTaskExecuteInput, TextTranslationTaskExecuteOutput, UnloadModelTaskExecuteInput, UnloadModelTaskExecuteOutput } from "@workglow/ai";
|
|
7
7
|
import { HfTransformersOnnxModelRecord } from "./HFT_ModelSchema";
|
|
8
8
|
/**
|
|
9
9
|
* Core implementation for downloading and caching a Hugging Face Transformers model.
|
|
@@ -22,6 +22,8 @@ export declare const HFT_Unload: AiProviderRunFn<UnloadModelTaskExecuteInput, Un
|
|
|
22
22
|
export declare const HFT_TextEmbedding: AiProviderRunFn<TextEmbeddingTaskExecuteInput, TextEmbeddingTaskExecuteOutput, HfTransformersOnnxModelRecord>;
|
|
23
23
|
export declare const HFT_TextClassifier: AiProviderRunFn<TextClassifierTaskExecuteInput, TextClassifierTaskExecuteOutput, HfTransformersOnnxModelRecord>;
|
|
24
24
|
export declare const HFT_TextLanguageDetection: AiProviderRunFn<TextLanguageDetectionTaskExecuteInput, TextLanguageDetectionTaskExecuteOutput, HfTransformersOnnxModelRecord>;
|
|
25
|
+
export declare const HFT_TextNamedEntityRecognition: AiProviderRunFn<TextNamedEntityRecognitionTaskExecuteInput, TextNamedEntityRecognitionTaskExecuteOutput, HfTransformersOnnxModelRecord>;
|
|
26
|
+
export declare const HFT_TextFillMask: AiProviderRunFn<TextFillMaskTaskExecuteInput, TextFillMaskTaskExecuteOutput, HfTransformersOnnxModelRecord>;
|
|
25
27
|
/**
|
|
26
28
|
* Core implementation for text generation using Hugging Face Transformers.
|
|
27
29
|
* This is shared between inline and worker implementations.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HFT_JobRunFns.d.ts","sourceRoot":"","sources":["../../../src/hf-transformers/common/HFT_JobRunFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"HFT_JobRunFns.d.ts","sourceRoot":"","sources":["../../../src/hf-transformers/common/HFT_JobRunFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuBH,OAAO,EACL,eAAe,EACf,6BAA6B,EAC7B,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,EAC/B,6BAA6B,EAC7B,8BAA8B,EAC9B,4BAA4B,EAC5B,6BAA6B,EAC7B,8BAA8B,EAC9B,+BAA+B,EAC/B,qCAAqC,EACrC,sCAAsC,EACtC,0CAA0C,EAC1C,2CAA2C,EAC3C,kCAAkC,EAClC,mCAAmC,EACnC,4BAA4B,EAC5B,6BAA6B,EAC7B,2BAA2B,EAC3B,4BAA4B,EAC5B,+BAA+B,EAC/B,gCAAgC,EAEhC,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,cAAc,CAAC;AAItB,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAqVlE;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,eAAe,CACxC,6BAA6B,EAC7B,8BAA8B,EAC9B,6BAA6B,CAS9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,eAAe,CACtC,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,CAgB9B,CAAC;AAwCF;;;GAGG;AAEH,eAAO,MAAM,iBAAiB,EAAE,eAAe,CAC7C,6BAA6B,EAC7B,8BAA8B,EAC9B,6BAA6B,CA0B9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,eAAe,CAC9C,8BAA8B,EAC9B,+BAA+B,EAC/B,6BAA6B,CAyB9B,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,eAAe,CACrD,qCAAqC,EACrC,sCAAsC,EACtC,6BAA6B,CAyB9B,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,eAAe,CAC1D,0CAA0C,EAC1C,2CAA2C,EAC3C,6BAA6B,CA0B9B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,eAAe,CAC5C,4BAA4B,EAC5B,6BAA6B,EAC7B,6BAA6B,CAmB9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAAe,CAC9C,8BAA8B,EAC9B,+BAA+B,EAC/B,6BAA6B,CAwB9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,eAAe,CAC/C,+BAA+B,EAC/B,gCAAgC,EAChC,6BAA6B,CAyB9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAAe,CAC5C,4BAA4B,EAC5B,6BAA6B,EAC7B,6BAA6B,CA+B9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,eAAe,CAC3C,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,CAsB9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,eAAe,CAClD,kCAAkC,EAClC,mCAAmC,EACnC,6BAA6B,CAuB9B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HFT_Client_RegisterJobFns.d.ts","sourceRoot":"","sources":["../../../src/hf-transformers/registry/HFT_Client_RegisterJobFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAS,UAAU,EAAyB,MAAM,cAAc,CAAC;AACxE,OAAO,EAAsB,cAAc,EAAkB,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAAwB,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAInF;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"HFT_Client_RegisterJobFns.d.ts","sourceRoot":"","sources":["../../../src/hf-transformers/registry/HFT_Client_RegisterJobFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAS,UAAU,EAAyB,MAAM,cAAc,CAAC;AACxE,OAAO,EAAsB,cAAc,EAAkB,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAAwB,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAInF;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HFT_Inline_RegisterJobFns.d.ts","sourceRoot":"","sources":["../../../src/hf-transformers/registry/HFT_Inline_RegisterJobFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAS,UAAU,EAA0C,MAAM,cAAc,CAAC;AACzF,OAAO,EAAsB,cAAc,EAAkB,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAAwB,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"HFT_Inline_RegisterJobFns.d.ts","sourceRoot":"","sources":["../../../src/hf-transformers/registry/HFT_Inline_RegisterJobFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAS,UAAU,EAA0C,MAAM,cAAc,CAAC;AACzF,OAAO,EAAsB,cAAc,EAAkB,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAAwB,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAiBnF;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HFT_Worker_RegisterJobFns.d.ts","sourceRoot":"","sources":["../../../src/hf-transformers/registry/HFT_Worker_RegisterJobFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"HFT_Worker_RegisterJobFns.d.ts","sourceRoot":"","sources":["../../../src/hf-transformers/registry/HFT_Worker_RegisterJobFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuBH,eAAO,MAAM,iBAAiB,gDAA+C,CAAC;AAE9E,eAAO,MAAM,0BAA0B,MAqBtC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -376,6 +376,47 @@ var HFT_TextLanguageDetection = async (input, model, onProgress, signal) => {
|
|
|
376
376
|
}))
|
|
377
377
|
};
|
|
378
378
|
};
|
|
379
|
+
var HFT_TextNamedEntityRecognition = async (input, model, onProgress, signal) => {
|
|
380
|
+
const textNamedEntityRecognition = await getPipeline(model, onProgress, {
|
|
381
|
+
abort_signal: signal
|
|
382
|
+
});
|
|
383
|
+
let results = await textNamedEntityRecognition(input.text, {
|
|
384
|
+
ignore_labels: input.blockList,
|
|
385
|
+
...signal ? { abort_signal: signal } : {}
|
|
386
|
+
});
|
|
387
|
+
let entities = [];
|
|
388
|
+
if (!Array.isArray(results)) {
|
|
389
|
+
entities = [results];
|
|
390
|
+
} else {
|
|
391
|
+
entities = results;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
entities: entities.map((entity) => ({
|
|
395
|
+
entity: entity.entity,
|
|
396
|
+
score: entity.score,
|
|
397
|
+
word: entity.word
|
|
398
|
+
}))
|
|
399
|
+
};
|
|
400
|
+
};
|
|
401
|
+
var HFT_TextFillMask = async (input, model, onProgress, signal) => {
|
|
402
|
+
const unmasker = await getPipeline(model, onProgress, {
|
|
403
|
+
abort_signal: signal
|
|
404
|
+
});
|
|
405
|
+
let results = await unmasker(input.text);
|
|
406
|
+
let predictions = [];
|
|
407
|
+
if (!Array.isArray(results)) {
|
|
408
|
+
predictions = [results];
|
|
409
|
+
} else {
|
|
410
|
+
predictions = results;
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
predictions: predictions.map((prediction) => ({
|
|
414
|
+
entity: prediction.token_str,
|
|
415
|
+
score: prediction.score,
|
|
416
|
+
sequence: prediction.sequence
|
|
417
|
+
}))
|
|
418
|
+
};
|
|
419
|
+
};
|
|
379
420
|
var HFT_TextGeneration = async (input, model, onProgress, signal) => {
|
|
380
421
|
const generateText = await getPipeline(model, onProgress, {
|
|
381
422
|
abort_signal: signal
|
|
@@ -602,6 +643,8 @@ async function register_HFT_ClientJobFns(worker, client) {
|
|
|
602
643
|
"TextEmbeddingTask",
|
|
603
644
|
"TextLanguageDetectionTask",
|
|
604
645
|
"TextClassifierTask",
|
|
646
|
+
"TextFillMaskTask",
|
|
647
|
+
"TextNamedEntityRecognitionTask",
|
|
605
648
|
"TextGenerationTask",
|
|
606
649
|
"TextTranslationTask",
|
|
607
650
|
"TextRewriterTask",
|
|
@@ -643,6 +686,8 @@ async function register_HFT_InlineJobFns(client) {
|
|
|
643
686
|
["TextQuestionAnswerTask"]: HFT_TextQuestionAnswer,
|
|
644
687
|
["TextLanguageDetectionTask"]: HFT_TextLanguageDetection,
|
|
645
688
|
["TextClassifierTask"]: HFT_TextClassifier,
|
|
689
|
+
["TextFillMaskTask"]: HFT_TextFillMask,
|
|
690
|
+
["TextNamedEntityRecognitionTask"]: HFT_TextNamedEntityRecognition,
|
|
646
691
|
["TextRewriterTask"]: HFT_TextRewriter,
|
|
647
692
|
["TextSummaryTask"]: HFT_TextSummary,
|
|
648
693
|
["TextTranslationTask"]: HFT_TextTranslation
|
|
@@ -683,6 +728,8 @@ var HFT_WORKER_JOBRUN_REGISTER = globalServiceRegistry2.register(HFT_WORKER_JOBR
|
|
|
683
728
|
workerServer.registerFunction("TextGenerationTask", HFT_TextGeneration);
|
|
684
729
|
workerServer.registerFunction("TextLanguageDetectionTask", HFT_TextLanguageDetection);
|
|
685
730
|
workerServer.registerFunction("TextClassifierTask", HFT_TextClassifier);
|
|
731
|
+
workerServer.registerFunction("TextFillMaskTask", HFT_TextFillMask);
|
|
732
|
+
workerServer.registerFunction("TextNamedEntityRecognitionTask", HFT_TextNamedEntityRecognition);
|
|
686
733
|
workerServer.registerFunction("TextTranslationTask", HFT_TextTranslation);
|
|
687
734
|
workerServer.registerFunction("TextRewriterTask", HFT_TextRewriter);
|
|
688
735
|
workerServer.registerFunction("TextSummaryTask", HFT_TextSummary);
|
|
@@ -754,55 +801,80 @@ var getWasmTask = async (model, onProgress, signal) => {
|
|
|
754
801
|
return wasmFileset;
|
|
755
802
|
};
|
|
756
803
|
var modelTaskCache = new Map;
|
|
757
|
-
var
|
|
804
|
+
var optionsMatch = (opts1, opts2) => {
|
|
805
|
+
const keys1 = Object.keys(opts1).sort();
|
|
806
|
+
const keys2 = Object.keys(opts2).sort();
|
|
807
|
+
if (keys1.length !== keys2.length)
|
|
808
|
+
return false;
|
|
809
|
+
return keys1.every((key) => {
|
|
810
|
+
const val1 = opts1[key];
|
|
811
|
+
const val2 = opts2[key];
|
|
812
|
+
if (Array.isArray(val1) && Array.isArray(val2)) {
|
|
813
|
+
return JSON.stringify(val1) === JSON.stringify(val2);
|
|
814
|
+
}
|
|
815
|
+
return val1 === val2;
|
|
816
|
+
});
|
|
817
|
+
};
|
|
818
|
+
var getModelTask = async (model, options, onProgress, signal, TaskType) => {
|
|
758
819
|
const modelPath = model.providerConfig.modelPath;
|
|
759
820
|
const taskEngine = model.providerConfig.taskEngine;
|
|
760
|
-
|
|
761
|
-
|
|
821
|
+
const cachedTasks = modelTaskCache.get(modelPath);
|
|
822
|
+
if (cachedTasks) {
|
|
823
|
+
const matchedTask = cachedTasks.find((cached) => optionsMatch(cached.options, options));
|
|
824
|
+
if (matchedTask) {
|
|
825
|
+
return matchedTask.task;
|
|
826
|
+
}
|
|
762
827
|
}
|
|
763
828
|
const wasmFileset = await getWasmTask(model, onProgress, signal);
|
|
764
829
|
onProgress(0.2, "Creating model task");
|
|
765
830
|
const task = await TaskType.createFromOptions(wasmFileset, {
|
|
766
831
|
baseOptions: {
|
|
767
832
|
modelAssetPath: modelPath
|
|
768
|
-
}
|
|
833
|
+
},
|
|
834
|
+
...options
|
|
769
835
|
});
|
|
770
|
-
|
|
771
|
-
|
|
836
|
+
const cachedTask = { task, options, taskEngine };
|
|
837
|
+
if (!modelTaskCache.has(modelPath)) {
|
|
838
|
+
modelTaskCache.set(modelPath, []);
|
|
839
|
+
}
|
|
840
|
+
modelTaskCache.get(modelPath).push(cachedTask);
|
|
772
841
|
wasm_reference_counts.set(taskEngine, (wasm_reference_counts.get(taskEngine) || 0) + 1);
|
|
773
842
|
return task;
|
|
774
843
|
};
|
|
775
|
-
var getTextEmbedder = async (model, onProgress, signal) => {
|
|
776
|
-
return getModelTask(model, onProgress, signal, TextEmbedder);
|
|
844
|
+
var getTextEmbedder = async (model, options, onProgress, signal) => {
|
|
845
|
+
return getModelTask(model, options, onProgress, signal, TextEmbedder);
|
|
777
846
|
};
|
|
778
|
-
var getTextClassifier = async (model, onProgress, signal) => {
|
|
779
|
-
return getModelTask(model, onProgress, signal, TextClassifier);
|
|
847
|
+
var getTextClassifier = async (model, options, onProgress, signal) => {
|
|
848
|
+
return getModelTask(model, options, onProgress, signal, TextClassifier);
|
|
780
849
|
};
|
|
781
|
-
var getTextLanguageDetector = async (model, onProgress, signal) => {
|
|
782
|
-
return getModelTask(model, onProgress, signal, LanguageDetector);
|
|
850
|
+
var getTextLanguageDetector = async (model, options, onProgress, signal) => {
|
|
851
|
+
return getModelTask(model, options, onProgress, signal, LanguageDetector);
|
|
783
852
|
};
|
|
784
853
|
var TFMP_Download = async (input, model, onProgress, signal) => {
|
|
854
|
+
let task;
|
|
785
855
|
switch (model?.providerConfig.pipeline) {
|
|
786
856
|
case "text-embedder":
|
|
787
|
-
await getTextEmbedder(model, onProgress, signal);
|
|
857
|
+
task = await getTextEmbedder(model, {}, onProgress, signal);
|
|
788
858
|
break;
|
|
789
859
|
case "text-classifier":
|
|
790
|
-
await getTextClassifier(model, onProgress, signal);
|
|
860
|
+
task = await getTextClassifier(model, {}, onProgress, signal);
|
|
791
861
|
break;
|
|
792
862
|
case "text-language-detector":
|
|
793
|
-
await getTextLanguageDetector(model, onProgress, signal);
|
|
863
|
+
task = await getTextLanguageDetector(model, {}, onProgress, signal);
|
|
794
864
|
break;
|
|
795
865
|
default:
|
|
796
866
|
throw new PermanentJobError2("Invalid pipeline");
|
|
797
867
|
}
|
|
798
868
|
onProgress(0.9, "Pipeline loaded");
|
|
869
|
+
task.close();
|
|
870
|
+
const taskEngine = model?.providerConfig.taskEngine;
|
|
871
|
+
wasm_reference_counts.set(taskEngine, wasm_reference_counts.get(taskEngine) - 1);
|
|
799
872
|
return {
|
|
800
873
|
model: input.model
|
|
801
874
|
};
|
|
802
875
|
};
|
|
803
876
|
var TFMP_TextEmbedding = async (input, model, onProgress, signal) => {
|
|
804
|
-
|
|
805
|
-
const textEmbedder = await getTextEmbedder(model, onProgress, signal);
|
|
877
|
+
const textEmbedder = await getTextEmbedder(model, {}, onProgress, signal);
|
|
806
878
|
const result = textEmbedder.embed(input.text);
|
|
807
879
|
if (!result.embeddings?.[0]?.floatEmbedding) {
|
|
808
880
|
throw new PermanentJobError2("Failed to generate embedding: Empty result");
|
|
@@ -813,8 +885,9 @@ var TFMP_TextEmbedding = async (input, model, onProgress, signal) => {
|
|
|
813
885
|
};
|
|
814
886
|
};
|
|
815
887
|
var TFMP_TextClassifier = async (input, model, onProgress, signal) => {
|
|
816
|
-
|
|
817
|
-
|
|
888
|
+
const textClassifier = await getTextClassifier(model, {
|
|
889
|
+
maxCategories: input.maxCategories
|
|
890
|
+
}, onProgress, signal);
|
|
818
891
|
const result = textClassifier.classify(input.text);
|
|
819
892
|
if (!result.classifications?.[0]?.categories) {
|
|
820
893
|
throw new PermanentJobError2("Failed to classify text: Empty result");
|
|
@@ -828,8 +901,10 @@ var TFMP_TextClassifier = async (input, model, onProgress, signal) => {
|
|
|
828
901
|
};
|
|
829
902
|
};
|
|
830
903
|
var TFMP_TextLanguageDetection = async (input, model, onProgress, signal) => {
|
|
831
|
-
|
|
832
|
-
const textLanguageDetector = await getTextLanguageDetector(model,
|
|
904
|
+
const maxLanguages = input.maxLanguages === 0 ? -1 : input.maxLanguages;
|
|
905
|
+
const textLanguageDetector = await getTextLanguageDetector(model, {
|
|
906
|
+
maxLanguages
|
|
907
|
+
}, onProgress, signal);
|
|
833
908
|
const result = textLanguageDetector.detect(input.text);
|
|
834
909
|
if (!result.languages?.[0]?.languageCode) {
|
|
835
910
|
throw new PermanentJobError2("Failed to detect language: Empty result");
|
|
@@ -845,24 +920,22 @@ var TFMP_TextLanguageDetection = async (input, model, onProgress, signal) => {
|
|
|
845
920
|
var TFMP_Unload = async (input, model, onProgress, signal) => {
|
|
846
921
|
const modelPath = model.providerConfig.modelPath;
|
|
847
922
|
if (modelTaskCache.has(modelPath)) {
|
|
848
|
-
const
|
|
849
|
-
|
|
850
|
-
|
|
923
|
+
const cachedTasks = modelTaskCache.get(modelPath);
|
|
924
|
+
for (const cachedTask of cachedTasks) {
|
|
925
|
+
const task = cachedTask.task;
|
|
926
|
+
task.close();
|
|
927
|
+
const taskEngine = cachedTask.taskEngine;
|
|
928
|
+
const currentCount = wasm_reference_counts.get(taskEngine) || 0;
|
|
929
|
+
const newCount = currentCount - 1;
|
|
930
|
+
if (newCount <= 0) {
|
|
931
|
+
wasm_tasks.delete(taskEngine);
|
|
932
|
+
wasm_reference_counts.delete(taskEngine);
|
|
933
|
+
} else {
|
|
934
|
+
wasm_reference_counts.set(taskEngine, newCount);
|
|
935
|
+
}
|
|
851
936
|
}
|
|
852
937
|
modelTaskCache.delete(modelPath);
|
|
853
938
|
}
|
|
854
|
-
const taskEngine = model_to_wasm_mapping.get(modelPath);
|
|
855
|
-
if (taskEngine) {
|
|
856
|
-
const currentCount = wasm_reference_counts.get(taskEngine) || 0;
|
|
857
|
-
const newCount = currentCount - 1;
|
|
858
|
-
if (newCount <= 0) {
|
|
859
|
-
wasm_tasks.delete(taskEngine);
|
|
860
|
-
wasm_reference_counts.delete(taskEngine);
|
|
861
|
-
} else {
|
|
862
|
-
wasm_reference_counts.set(taskEngine, newCount);
|
|
863
|
-
}
|
|
864
|
-
model_to_wasm_mapping.delete(modelPath);
|
|
865
|
-
}
|
|
866
939
|
return {
|
|
867
940
|
model: input.model
|
|
868
941
|
};
|
|
@@ -1026,12 +1099,14 @@ export {
|
|
|
1026
1099
|
HFT_TextSummary,
|
|
1027
1100
|
HFT_TextRewriter,
|
|
1028
1101
|
HFT_TextQuestionAnswer,
|
|
1102
|
+
HFT_TextNamedEntityRecognition,
|
|
1029
1103
|
HFT_TextLanguageDetection,
|
|
1030
1104
|
HFT_TextGeneration,
|
|
1105
|
+
HFT_TextFillMask,
|
|
1031
1106
|
HFT_TextEmbedding,
|
|
1032
1107
|
HFT_TextClassifier,
|
|
1033
1108
|
HFT_Download,
|
|
1034
1109
|
AudioPipelineUseCase
|
|
1035
1110
|
};
|
|
1036
1111
|
|
|
1037
|
-
//# debugId=
|
|
1112
|
+
//# debugId=AED2FBB7924C48F164756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
"sources": ["../src/hf-transformers/common/HFT_Constants.ts", "../src/hf-transformers/common/HFT_JobRunFns.ts", "../src/hf-transformers/common/HFT_ModelSchema.ts", "../src/hf-transformers/registry/HFT_Client_RegisterJobFns.ts", "../src/hf-transformers/registry/HFT_Inline_RegisterJobFns.ts", "../src/hf-transformers/registry/HFT_Worker_RegisterJobFns.ts", "../src/tf-mediapipe/common/TFMP_Constants.ts", "../src/tf-mediapipe/common/TFMP_JobRunFns.ts", "../src/tf-mediapipe/common/TFMP_ModelSchema.ts", "../src/tf-mediapipe/registry/TFMP_Client_RegisterJobFns.ts", "../src/tf-mediapipe/registry/TFMP_Inline_RegisterJobFns.ts", "../src/tf-mediapipe/registry/TFMP_Worker_RegisterJobFns.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport const HF_TRANSFORMERS_ONNX = \"HF_TRANSFORMERS_ONNX\";\nexport const HTF_CACHE_NAME = \"transformers-cache\";\n\nexport type QuantizationDataType =\n | \"auto\" // Auto-detect based on environment\n | \"fp32\"\n | \"fp16\"\n | \"q8\"\n | \"int8\"\n | \"uint8\"\n | \"q4\"\n | \"bnb4\"\n | \"q4f16\"; // fp16 model with int4 block weight quantization\n\nexport const QuantizationDataType = {\n auto: \"auto\",\n fp32: \"fp32\",\n fp16: \"fp16\",\n q8: \"q8\",\n int8: \"int8\",\n uint8: \"uint8\",\n q4: \"q4\",\n bnb4: \"bnb4\",\n q4f16: \"q4f16\",\n} as const satisfies Record<QuantizationDataType, QuantizationDataType>;\n\nexport type TextPipelineUseCase =\n | \"fill-mask\" // https://huggingface.co/tasks/fill-mask\n | \"token-classification\" // https://huggingface.co/tasks/token-classification\n | \"text-generation\" // https://huggingface.co/tasks/text-generation#completion-generation-models\n | \"text2text-generation\" // https://huggingface.co/tasks/text-generation#text-to-text-generation-models\n | \"text-classification\" // https://huggingface.co/tasks/text-classification\n | \"summarization\" // https://huggingface.co/tasks/sentence-similarity\n | \"translation\" // https://huggingface.co/tasks/translation\n | \"feature-extraction\" // https://huggingface.co/tasks/feature-extraction\n | \"zero-shot-classification\" // https://huggingface.co/tasks/zero-shot-classification\n | \"question-answering\"; // https://huggingface.co/tasks/question-answering\n\nexport const TextPipelineUseCase = {\n \"fill-mask\": \"fill-mask\",\n \"token-classification\": \"token-classification\",\n \"text-generation\": \"text-generation\",\n \"text2text-generation\": \"text2text-generation\",\n \"text-classification\": \"text-classification\",\n summarization: \"summarization\",\n translation: \"translation\",\n \"feature-extraction\": \"feature-extraction\",\n \"zero-shot-classification\": \"zero-shot-classification\",\n \"question-answering\": \"question-answering\",\n} as const satisfies Record<TextPipelineUseCase, TextPipelineUseCase>;\n\nexport type VisionPipelineUseCase =\n | \"background-removal\" // https://huggingface.co/tasks/image-segmentation#background-removal\n | \"image-segmentation\" // https://huggingface.co/tasks/image-segmentation\n | \"depth-estimation\" // https://huggingface.co/tasks/depth-estimation\n | \"image-classification\" // https://huggingface.co/tasks/image-classification\n | \"image-to-image\" // https://huggingface.co/tasks/image-to-image\n | \"object-detection\" // https://huggingface.co/tasks/object-detection\n | \"image-feature-extraction\"; // https://huggingface.co/tasks/image-feature-extraction\n\nexport const VisionPipelineUseCase = {\n \"background-removal\": \"background-removal\",\n \"image-segmentation\": \"image-segmentation\",\n \"depth-estimation\": \"depth-estimation\",\n \"image-classification\": \"image-classification\",\n \"image-to-image\": \"image-to-image\",\n \"object-detection\": \"object-detection\",\n \"image-feature-extraction\": \"image-feature-extraction\",\n} as const satisfies Record<VisionPipelineUseCase, VisionPipelineUseCase>;\n\nexport type AudioPipelineUseCase =\n | \"audio-classification\" // https://huggingface.co/tasks/audio-classification\n | \"automatic-speech-recognition\" // https://huggingface.co/tasks/automatic-speech-recognition\n | \"text-to-speech\"; // https://huggingface.co/tasks/text-to-speech\n\nexport const AudioPipelineUseCase = {\n \"audio-classification\": \"audio-classification\",\n \"automatic-speech-recognition\": \"automatic-speech-recognition\",\n \"text-to-speech\": \"text-to-speech\",\n} as const satisfies Record<AudioPipelineUseCase, AudioPipelineUseCase>;\n\nexport type MultimodalPipelineUseCase =\n | \"document-question-answering\" // https://huggingface.co/tasks/document-question-answering\n | \"image-to-text\" // https://huggingface.co/tasks/image-to-text\n | \"zero-shot-audio-classification\" // https://huggingface.co/tasks/zero-shot-audio-classification\n | \"zero-shot-image-classification\" // https://huggingface.co/tasks/zero-shot-image-classification\n | \"zero-shot-object-detection\"; // https://huggingface.co/tasks/zero-shot-object-detection\n\nexport const MultimodalPipelineUseCase = {\n \"document-question-answering\": \"document-question-answering\",\n \"image-to-text\": \"image-to-text\",\n \"zero-shot-audio-classification\": \"zero-shot-audio-classification\",\n \"zero-shot-image-classification\": \"zero-shot-image-classification\",\n \"zero-shot-object-detection\": \"zero-shot-object-detection\",\n} as const satisfies Record<MultimodalPipelineUseCase, MultimodalPipelineUseCase>;\n\nexport type PipelineUseCase =\n | TextPipelineUseCase\n | VisionPipelineUseCase\n | AudioPipelineUseCase\n | MultimodalPipelineUseCase;\n\nexport const PipelineUseCase = {\n ...TextPipelineUseCase,\n ...VisionPipelineUseCase,\n ...AudioPipelineUseCase,\n ...MultimodalPipelineUseCase,\n} as const satisfies Record<PipelineUseCase, PipelineUseCase>;\n",
|
|
6
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n DocumentQuestionAnsweringSingle,\n type FeatureExtractionPipeline,\n pipeline,\n // @ts-ignore temporary \"fix\"\n type PretrainedModelOptions,\n QuestionAnsweringPipeline,\n SummarizationPipeline,\n SummarizationSingle,\n TextClassificationOutput,\n TextClassificationPipeline,\n type TextGenerationPipeline,\n TextGenerationSingle,\n TextStreamer,\n TranslationPipeline,\n TranslationSingle,\n} from \"@sroussey/transformers\";\nimport {\n AiProviderRunFn,\n DownloadModelTaskExecuteInput,\n DownloadModelTaskExecuteOutput,\n TextClassifierTaskExecuteInput,\n TextClassifierTaskExecuteOutput,\n TextEmbeddingTaskExecuteInput,\n TextEmbeddingTaskExecuteOutput,\n TextGenerationTaskExecuteInput,\n TextGenerationTaskExecuteOutput,\n TextLanguageDetectionTaskExecuteInput,\n TextLanguageDetectionTaskExecuteOutput,\n TextQuestionAnswerTaskExecuteInput,\n TextQuestionAnswerTaskExecuteOutput,\n TextRewriterTaskExecuteInput,\n TextRewriterTaskExecuteOutput,\n TextSummaryTaskExecuteInput,\n TextSummaryTaskExecuteOutput,\n TextTranslationTaskExecuteInput,\n TextTranslationTaskExecuteOutput,\n TypedArray,\n UnloadModelTaskExecuteInput,\n UnloadModelTaskExecuteOutput,\n} from \"@workglow/ai\";\nimport { PermanentJobError } from \"@workglow/job-queue\";\nimport { CallbackStatus } from \"./HFT_CallbackStatus\";\nimport { HTF_CACHE_NAME } from \"./HFT_Constants\";\nimport { HfTransformersOnnxModelRecord } from \"./HFT_ModelSchema\";\n\nconst pipelines = new Map<string, any>();\n\n/**\n * Helper function to get a pipeline for a model\n * @param progressScaleMax - Maximum progress value for download phase (100 for download-only, 10 for download+run)\n */\nconst getPipeline = async (\n model: HfTransformersOnnxModelRecord,\n onProgress: (progress: number, message?: string, details?: any) => void,\n options: PretrainedModelOptions = {},\n progressScaleMax: number = 10\n) => {\n if (pipelines.has(model.model_id)) {\n return pipelines.get(model.model_id);\n }\n\n // Track file sizes and progress for weighted calculation\n const fileSizes = new Map<string, number>();\n const fileProgress = new Map<string, number>();\n const fileCompleted = new Set<string>();\n const fileFirstSent = new Set<string>();\n const fileLastSent = new Set<string>();\n const fileLastEventTime = new Map<string, number>();\n const pendingProgressByFile = new Map<\n string,\n { progress: number; file: string; fileProgress: number }\n >();\n let throttleTimer: ReturnType<typeof setTimeout> | null = null;\n const THROTTLE_MS = 160;\n\n // Pre-estimate total download size based on typical model structure:\n // 3 tiny files (~1KB each) + 1 medium file (~20MB) + 0-2 large files (~1GB each if present)\n const estimatedTinyFiles = 3;\n const estimatedMediumFiles = 1;\n const estimatedTinySize = 1024; // 1KB\n const estimatedMediumSize = 20 * 1024 * 1024; // 20MB\n const estimatedLargeSize = 1024 * 1024 * 1024; // 1GB\n\n // Start with minimum estimate (4 files), add large files dynamically as we discover them\n const baseEstimate =\n estimatedTinyFiles * estimatedTinySize + estimatedMediumFiles * estimatedMediumSize;\n\n /**\n * Sends a progress event, respecting throttling but always sending first/last per file\n */\n const sendProgress = (\n overallProgress: number,\n file: string,\n fileProgressValue: number,\n isFirst: boolean,\n isLast: boolean\n ): void => {\n const now = Date.now();\n const lastTime = fileLastEventTime.get(file) || 0;\n const timeSinceLastEvent = now - lastTime;\n const shouldThrottle = !isFirst && !isLast && timeSinceLastEvent < THROTTLE_MS;\n\n if (shouldThrottle) {\n // Store pending progress for this file\n pendingProgressByFile.set(file, {\n progress: overallProgress,\n file,\n fileProgress: fileProgressValue,\n });\n // Schedule sending if not already scheduled\n if (!throttleTimer) {\n const timeRemaining = Math.max(1, THROTTLE_MS - timeSinceLastEvent);\n throttleTimer = setTimeout(() => {\n // Send all pending progress events\n for (const [pendingFile, pending] of pendingProgressByFile.entries()) {\n onProgress(Math.round(pending.progress), \"Downloading model\", {\n file: pendingFile,\n progress: pending.fileProgress,\n });\n fileLastEventTime.set(pendingFile, Date.now());\n }\n pendingProgressByFile.clear();\n throttleTimer = null;\n }, timeRemaining);\n }\n return;\n }\n\n // Send immediately\n onProgress(Math.round(overallProgress), \"Downloading model\", {\n file,\n progress: fileProgressValue,\n });\n fileLastEventTime.set(file, now);\n // Clear any pending progress for this file since we're sending it now\n pendingProgressByFile.delete(file);\n if (throttleTimer && pendingProgressByFile.size === 0) {\n clearTimeout(throttleTimer);\n throttleTimer = null;\n }\n };\n\n // Track whether we've seen a substantial file (to avoid premature progress reports for tiny config files)\n let hasSeenSubstantialFile = false;\n const substantialFileThreshold = 1024 * 1024; // 1MB - files larger than this are substantial\n\n // Get the abort signal from options if provided\n const abortSignal = options.abort_signal;\n\n // Create a callback status object for progress tracking\n const progressCallback = (status: CallbackStatus) => {\n // Check if operation has been aborted before processing progress\n if (abortSignal?.aborted) {\n return; // Don't process progress for aborted operations\n }\n\n if (status.status === \"progress\") {\n const file = status.file;\n const fileTotal = status.total;\n const fileProgressValue = status.progress;\n\n // Track file size on first progress event\n if (!fileSizes.has(file)) {\n fileSizes.set(file, fileTotal);\n fileProgress.set(file, 0);\n\n // Check if this is a substantial file\n if (fileTotal >= substantialFileThreshold) {\n hasSeenSubstantialFile = true;\n }\n }\n\n // Update file progress\n fileProgress.set(file, fileProgressValue);\n\n // Check if file is complete\n const isComplete = fileProgressValue >= 100;\n if (isComplete && !fileCompleted.has(file)) {\n fileCompleted.add(file);\n fileProgress.set(file, 100);\n }\n\n // Calculate actual loaded bytes and adjust estimated total\n let actualLoadedSize = 0;\n let actualTotalSize = 0;\n\n // Categorize seen files and track their actual sizes\n const tinyThreshold = 100 * 1024; // 100KB - files smaller are config/vocab\n const mediumThreshold = 100 * 1024 * 1024; // 100MB - tokenizer and small models\n let seenTinyCount = 0;\n let seenMediumCount = 0;\n let seenLargeCount = 0;\n\n for (const [trackedFile, size] of fileSizes.entries()) {\n actualTotalSize += size;\n const progress = fileProgress.get(trackedFile) || 0;\n actualLoadedSize += (size * progress) / 100;\n\n // Categorize file\n if (size < tinyThreshold) {\n seenTinyCount++;\n } else if (size < mediumThreshold) {\n seenMediumCount++;\n } else {\n seenLargeCount++;\n }\n }\n\n // Adjust estimated total size:\n // - Start with actual sizes of seen files\n // - Add estimates for unseen tiny/medium files\n // - For large files: conservatively assume 1 until we've seen all expected files\n const unseenTinyFiles = Math.max(0, estimatedTinyFiles - seenTinyCount);\n const unseenMediumFiles = Math.max(0, estimatedMediumFiles - seenMediumCount);\n\n // Dynamically estimate large files:\n // - If we've seen a large file, assume up to 2 total\n // - Otherwise, conservatively assume 1 large file might exist to prevent premature 100% progress\n // - This prevents the progress from jumping when a large file appears unexpectedly\n let estimatedLargeFiles: number;\n if (seenLargeCount > 0) {\n estimatedLargeFiles = 2; // We've seen at least one, expect up to 2\n } else {\n estimatedLargeFiles = 1; // Haven't seen any large files yet, but assume 1 might exist\n }\n const unseenLargeFiles = Math.max(0, estimatedLargeFiles - seenLargeCount);\n\n const adjustedTotalSize =\n actualTotalSize +\n unseenTinyFiles * estimatedTinySize +\n unseenMediumFiles * estimatedMediumSize +\n unseenLargeFiles * estimatedLargeSize;\n\n // Scale progress to the configured range (0-100 for download-only, 0-10 for download+run)\n const rawProgress = adjustedTotalSize > 0 ? (actualLoadedSize / adjustedTotalSize) * 100 : 0;\n const overallProgress = (rawProgress * progressScaleMax) / 100;\n\n // Determine if this is first or last event for this file\n const isFirst = !fileFirstSent.has(file);\n const isLast = isComplete && !fileLastSent.has(file);\n\n if (isFirst) {\n fileFirstSent.add(file);\n }\n if (isLast) {\n fileLastSent.add(file);\n }\n\n // Only report progress if we've seen a substantial file (to avoid premature 100% for tiny config files)\n if (hasSeenSubstantialFile) {\n sendProgress(overallProgress, file, fileProgressValue, isFirst, isLast);\n }\n } else if (status.status === \"done\" || status.status === \"download\") {\n // Handle file completion from bookend events\n const file = status.file;\n\n // Check if this file should mark the start of substantial downloads\n const fileSize = fileSizes.get(file) || 0;\n if (fileSize >= substantialFileThreshold) {\n hasSeenSubstantialFile = true;\n }\n\n if (!fileCompleted.has(file)) {\n fileCompleted.add(file);\n fileProgress.set(file, 100);\n\n // Recalculate overall progress using same logic as progress handler\n let actualLoadedSize = 0;\n let actualTotalSize = 0;\n\n const tinyThreshold = 100 * 1024; // 100KB - files smaller are config/vocab\n const mediumThreshold = 100 * 1024 * 1024; // 100MB - tokenizer and small models\n let seenTinyCount = 0;\n let seenMediumCount = 0;\n let seenLargeCount = 0;\n\n for (const [trackedFile, size] of fileSizes.entries()) {\n actualTotalSize += size;\n const progress = fileProgress.get(trackedFile) || 0;\n actualLoadedSize += (size * progress) / 100;\n\n // Categorize file\n if (size < tinyThreshold) {\n seenTinyCount++;\n } else if (size < mediumThreshold) {\n seenMediumCount++;\n } else {\n seenLargeCount++;\n }\n }\n\n // Adjust estimated total size (same logic as progress handler)\n const unseenTinyFiles = Math.max(0, estimatedTinyFiles - seenTinyCount);\n const unseenMediumFiles = Math.max(0, estimatedMediumFiles - seenMediumCount);\n\n // Dynamically estimate large files (same logic as progress handler)\n let estimatedLargeFiles: number;\n if (seenLargeCount > 0) {\n estimatedLargeFiles = 2;\n } else {\n estimatedLargeFiles = 1;\n }\n const unseenLargeFiles = Math.max(0, estimatedLargeFiles - seenLargeCount);\n\n const adjustedTotalSize =\n actualTotalSize +\n unseenTinyFiles * estimatedTinySize +\n unseenMediumFiles * estimatedMediumSize +\n unseenLargeFiles * estimatedLargeSize;\n\n // Scale progress to the configured range (0-100 for download-only, 0-10 for download+run)\n const rawProgress =\n adjustedTotalSize > 0 ? (actualLoadedSize / adjustedTotalSize) * 100 : 0;\n const overallProgress = (rawProgress * progressScaleMax) / 100;\n const isLast = !fileLastSent.has(file);\n if (isLast) {\n fileLastSent.add(file);\n // Only report if we've seen a substantial file\n if (hasSeenSubstantialFile) {\n sendProgress(overallProgress, file, 100, false, true);\n }\n }\n }\n }\n };\n\n const pipelineOptions: PretrainedModelOptions = {\n dtype: model.providerConfig.dType || \"q8\",\n ...(model.providerConfig.useExternalDataFormat\n ? { use_external_data_format: model.providerConfig.useExternalDataFormat }\n : {}),\n ...(model.providerConfig.device ? { device: model.providerConfig.device as any } : {}),\n ...options,\n progress_callback: progressCallback,\n };\n\n // Check if already aborted before starting\n if (abortSignal?.aborted) {\n throw new Error(\"Operation aborted before pipeline creation\");\n }\n\n const pipelineType = model.providerConfig.pipeline;\n\n // Wrap the pipeline call with abort handling\n // Create a promise that rejects when aborted\n const abortPromise = new Promise<never>((_, reject) => {\n if (abortSignal) {\n const handleAbort = () => {\n reject(new Error(\"Pipeline download aborted\"));\n };\n\n if (abortSignal.aborted) {\n handleAbort();\n } else {\n abortSignal.addEventListener(\"abort\", handleAbort, { once: true });\n }\n }\n });\n\n // Race between pipeline creation and abort\n const pipelinePromise = pipeline(pipelineType, model.providerConfig.modelPath, pipelineOptions);\n\n try {\n const result = await (abortSignal\n ? Promise.race([pipelinePromise, abortPromise])\n : pipelinePromise);\n\n // Check if aborted after pipeline creation\n if (abortSignal?.aborted) {\n throw new Error(\"Operation aborted after pipeline creation\");\n }\n\n pipelines.set(model.model_id, result);\n return result;\n } catch (error: any) {\n // If aborted, throw a clean abort error rather than internal stream errors\n if (abortSignal?.aborted) {\n throw new Error(\"Pipeline download aborted\");\n }\n // Otherwise, re-throw the original error\n throw error;\n }\n};\n\n/**\n * Core implementation for downloading and caching a Hugging Face Transformers model.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_Download: AiProviderRunFn<\n DownloadModelTaskExecuteInput,\n DownloadModelTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n // Download the model by creating a pipeline\n // Use 100 as progressScaleMax since this is download-only (0-100%)\n await getPipeline(model!, onProgress, { abort_signal: signal }, 100);\n\n return {\n model: input.model!,\n };\n};\n\n/**\n * Core implementation for unloading a Hugging Face Transformers model.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_Unload: AiProviderRunFn<\n UnloadModelTaskExecuteInput,\n UnloadModelTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n // Delete the pipeline from the in-memory map\n if (pipelines.has(model!.model_id)) {\n pipelines.delete(model!.model_id);\n onProgress(50, \"Pipeline removed from memory\");\n }\n\n // Delete model cache entries\n const modelPath = model!.providerConfig.modelPath;\n await deleteModelCache(modelPath);\n onProgress(100, \"Model cache deleted\");\n\n return {\n model: input.model!,\n };\n};\n\n/**\n * Deletes all cache entries for a given model path\n * @param modelPath - The model path to delete from cache\n */\nconst deleteModelCache = async (modelPath: string): Promise<void> => {\n const cache = await caches.open(HTF_CACHE_NAME);\n const keys = await cache.keys();\n const prefix = `/${modelPath}/`;\n\n // Collect all matching requests first\n const requestsToDelete: Request[] = [];\n for (const request of keys) {\n const url = new URL(request.url);\n if (url.pathname.startsWith(prefix)) {\n requestsToDelete.push(request);\n }\n }\n\n // Delete all matching requests\n let deletedCount = 0;\n for (const request of requestsToDelete) {\n try {\n const deleted = await cache.delete(request);\n if (deleted) {\n deletedCount++;\n } else {\n // If delete returns false, try with URL string as fallback\n const deletedByUrl = await cache.delete(request.url);\n if (deletedByUrl) {\n deletedCount++;\n }\n }\n } catch (error) {\n console.error(`Failed to delete cache entry: ${request.url}`, error);\n }\n }\n};\n\n/**\n * Core implementation for text embedding using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\n\nexport const HFT_TextEmbedding: AiProviderRunFn<\n TextEmbeddingTaskExecuteInput,\n TextEmbeddingTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const generateEmbedding: FeatureExtractionPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n\n // Generate the embedding\n const hfVector = await generateEmbedding(input.text, {\n pooling: \"mean\",\n normalize: model?.providerConfig.normalize,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n // Validate the embedding dimensions\n if (hfVector.size !== model?.providerConfig.nativeDimensions) {\n console.warn(\n `HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${model?.providerConfig.nativeDimensions}`,\n input,\n hfVector\n );\n throw new PermanentJobError(\n `HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${model?.providerConfig.nativeDimensions}`\n );\n }\n\n return { vector: hfVector.data as TypedArray };\n};\n\nexport const HFT_TextClassifier: AiProviderRunFn<\n TextClassifierTaskExecuteInput,\n TextClassifierTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const textClassifier: TextClassificationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const result = await textClassifier(input.text, {\n top_k: input.maxCategories || undefined,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n if (Array.isArray(result[0])) {\n return {\n categories: result[0].map((category) => ({\n label: category.label,\n score: category.score,\n })),\n };\n }\n\n return {\n categories: (result as TextClassificationOutput).map((category) => ({\n label: category.label,\n score: category.score,\n })),\n };\n};\n\nexport const HFT_TextLanguageDetection: AiProviderRunFn<\n TextLanguageDetectionTaskExecuteInput,\n TextLanguageDetectionTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const textClassifier: TextClassificationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const result = await textClassifier(input.text, {\n top_k: input.maxLanguages || undefined,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n if (Array.isArray(result[0])) {\n return {\n languages: result[0].map((category) => ({\n language: category.label,\n score: category.score,\n })),\n };\n }\n\n return {\n languages: (result as TextClassificationOutput).map((category) => ({\n language: category.label,\n score: category.score,\n })),\n };\n};\n\n/**\n * Core implementation for text generation using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextGeneration: AiProviderRunFn<\n TextGenerationTaskExecuteInput,\n TextGenerationTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const generateText: TextGenerationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n\n const streamer = createTextStreamer(generateText.tokenizer, onProgress, signal);\n\n let results = await generateText(input.prompt, {\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n if (!Array.isArray(results)) {\n results = [results];\n }\n let text = (results[0] as TextGenerationSingle)?.generated_text;\n\n if (Array.isArray(text)) {\n text = text[text.length - 1]?.content;\n }\n return {\n text,\n };\n};\n\n/**\n * Core implementation for text translation using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextTranslation: AiProviderRunFn<\n TextTranslationTaskExecuteInput,\n TextTranslationTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const translate: TranslationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const streamer = createTextStreamer(translate.tokenizer, onProgress);\n\n const result = await translate(input.text, {\n src_lang: input.source_lang,\n tgt_lang: input.target_lang,\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n } as any);\n\n let translatedText: string | string[] = \"\";\n if (Array.isArray(result)) {\n translatedText = result.map((r) => (r as TranslationSingle)?.translation_text || \"\");\n } else {\n translatedText = (result as TranslationSingle)?.translation_text || \"\";\n }\n\n return {\n text: translatedText,\n target_lang: input.target_lang,\n };\n};\n\n/**\n * Core implementation for text rewriting using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextRewriter: AiProviderRunFn<\n TextRewriterTaskExecuteInput,\n TextRewriterTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const generateText: TextGenerationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const streamer = createTextStreamer(generateText.tokenizer, onProgress);\n\n // This lib doesn't support this kind of rewriting with a separate prompt vs text\n const promptedText = (input.prompt ? input.prompt + \"\\n\" : \"\") + input.text;\n\n let results = await generateText(promptedText, {\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n if (!Array.isArray(results)) {\n results = [results];\n }\n\n let text = (results[0] as TextGenerationSingle)?.generated_text;\n if (Array.isArray(text)) {\n text = text[text.length - 1]?.content;\n }\n\n if (text === promptedText) {\n throw new PermanentJobError(\"Rewriter failed to generate new text\");\n }\n\n return {\n text,\n };\n};\n\n/**\n * Core implementation for text summarization using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextSummary: AiProviderRunFn<\n TextSummaryTaskExecuteInput,\n TextSummaryTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const generateSummary: SummarizationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const streamer = createTextStreamer(generateSummary.tokenizer, onProgress);\n\n let result = await generateSummary(input.text, {\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n } as any);\n\n let summaryText = \"\";\n if (Array.isArray(result)) {\n summaryText = (result[0] as SummarizationSingle)?.summary_text || \"\";\n } else {\n summaryText = (result as SummarizationSingle)?.summary_text || \"\";\n }\n\n return {\n text: summaryText,\n };\n};\n\n/**\n * Core implementation for question answering using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextQuestionAnswer: AiProviderRunFn<\n TextQuestionAnswerTaskExecuteInput,\n TextQuestionAnswerTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n // Get the question answering pipeline\n const generateAnswer: QuestionAnsweringPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const streamer = createTextStreamer(generateAnswer.tokenizer, onProgress);\n\n const result = await generateAnswer(input.question, input.context, {\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n } as any);\n\n let answerText = \"\";\n if (Array.isArray(result)) {\n answerText = (result[0] as DocumentQuestionAnsweringSingle)?.answer || \"\";\n } else {\n answerText = (result as DocumentQuestionAnsweringSingle)?.answer || \"\";\n }\n\n return {\n text: answerText,\n };\n};\n\n/**\n * Create a text streamer for a given tokenizer and update progress function\n * @param tokenizer - The tokenizer to use for the streamer\n * @param updateProgress - The function to call to update the progress\n * @param signal - The signal to use for the streamer for aborting\n * @returns The text streamer\n */\nfunction createTextStreamer(\n tokenizer: any,\n updateProgress: (progress: number, message?: string, details?: any) => void,\n signal?: AbortSignal\n) {\n let count = 0;\n return new TextStreamer(tokenizer, {\n skip_prompt: true,\n decode_kwargs: { skip_special_tokens: true },\n callback_function: (text: string) => {\n count++;\n const result = 100 * (1 - Math.exp(-0.05 * count));\n const progress = Math.round(Math.min(result, 100));\n updateProgress(progress, \"Generating\", { text, progress });\n },\n ...(signal ? { abort_signal: signal } : {}),\n });\n}\n",
|
|
6
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n DocumentQuestionAnsweringSingle,\n type FeatureExtractionPipeline,\n FillMaskPipeline,\n FillMaskSingle,\n pipeline,\n // @ts-ignore temporary \"fix\"\n type PretrainedModelOptions,\n QuestionAnsweringPipeline,\n SummarizationPipeline,\n SummarizationSingle,\n TextClassificationOutput,\n TextClassificationPipeline,\n type TextGenerationPipeline,\n TextGenerationSingle,\n TextStreamer,\n TokenClassificationPipeline,\n TokenClassificationSingle,\n TranslationPipeline,\n TranslationSingle,\n} from \"@sroussey/transformers\";\nimport {\n AiProviderRunFn,\n DownloadModelTaskExecuteInput,\n DownloadModelTaskExecuteOutput,\n TextClassifierTaskExecuteInput,\n TextClassifierTaskExecuteOutput,\n TextEmbeddingTaskExecuteInput,\n TextEmbeddingTaskExecuteOutput,\n TextFillMaskTaskExecuteInput,\n TextFillMaskTaskExecuteOutput,\n TextGenerationTaskExecuteInput,\n TextGenerationTaskExecuteOutput,\n TextLanguageDetectionTaskExecuteInput,\n TextLanguageDetectionTaskExecuteOutput,\n TextNamedEntityRecognitionTaskExecuteInput,\n TextNamedEntityRecognitionTaskExecuteOutput,\n TextQuestionAnswerTaskExecuteInput,\n TextQuestionAnswerTaskExecuteOutput,\n TextRewriterTaskExecuteInput,\n TextRewriterTaskExecuteOutput,\n TextSummaryTaskExecuteInput,\n TextSummaryTaskExecuteOutput,\n TextTranslationTaskExecuteInput,\n TextTranslationTaskExecuteOutput,\n TypedArray,\n UnloadModelTaskExecuteInput,\n UnloadModelTaskExecuteOutput,\n} from \"@workglow/ai\";\nimport { PermanentJobError } from \"@workglow/job-queue\";\nimport { CallbackStatus } from \"./HFT_CallbackStatus\";\nimport { HTF_CACHE_NAME } from \"./HFT_Constants\";\nimport { HfTransformersOnnxModelRecord } from \"./HFT_ModelSchema\";\n\nconst pipelines = new Map<string, any>();\n\n/**\n * Helper function to get a pipeline for a model\n * @param progressScaleMax - Maximum progress value for download phase (100 for download-only, 10 for download+run)\n */\nconst getPipeline = async (\n model: HfTransformersOnnxModelRecord,\n onProgress: (progress: number, message?: string, details?: any) => void,\n options: PretrainedModelOptions = {},\n progressScaleMax: number = 10\n) => {\n if (pipelines.has(model.model_id)) {\n return pipelines.get(model.model_id);\n }\n\n // Track file sizes and progress for weighted calculation\n const fileSizes = new Map<string, number>();\n const fileProgress = new Map<string, number>();\n const fileCompleted = new Set<string>();\n const fileFirstSent = new Set<string>();\n const fileLastSent = new Set<string>();\n const fileLastEventTime = new Map<string, number>();\n const pendingProgressByFile = new Map<\n string,\n { progress: number; file: string; fileProgress: number }\n >();\n let throttleTimer: ReturnType<typeof setTimeout> | null = null;\n const THROTTLE_MS = 160;\n\n // Pre-estimate total download size based on typical model structure:\n // 3 tiny files (~1KB each) + 1 medium file (~20MB) + 0-2 large files (~1GB each if present)\n const estimatedTinyFiles = 3;\n const estimatedMediumFiles = 1;\n const estimatedTinySize = 1024; // 1KB\n const estimatedMediumSize = 20 * 1024 * 1024; // 20MB\n const estimatedLargeSize = 1024 * 1024 * 1024; // 1GB\n\n // Start with minimum estimate (4 files), add large files dynamically as we discover them\n const baseEstimate =\n estimatedTinyFiles * estimatedTinySize + estimatedMediumFiles * estimatedMediumSize;\n\n /**\n * Sends a progress event, respecting throttling but always sending first/last per file\n */\n const sendProgress = (\n overallProgress: number,\n file: string,\n fileProgressValue: number,\n isFirst: boolean,\n isLast: boolean\n ): void => {\n const now = Date.now();\n const lastTime = fileLastEventTime.get(file) || 0;\n const timeSinceLastEvent = now - lastTime;\n const shouldThrottle = !isFirst && !isLast && timeSinceLastEvent < THROTTLE_MS;\n\n if (shouldThrottle) {\n // Store pending progress for this file\n pendingProgressByFile.set(file, {\n progress: overallProgress,\n file,\n fileProgress: fileProgressValue,\n });\n // Schedule sending if not already scheduled\n if (!throttleTimer) {\n const timeRemaining = Math.max(1, THROTTLE_MS - timeSinceLastEvent);\n throttleTimer = setTimeout(() => {\n // Send all pending progress events\n for (const [pendingFile, pending] of pendingProgressByFile.entries()) {\n onProgress(Math.round(pending.progress), \"Downloading model\", {\n file: pendingFile,\n progress: pending.fileProgress,\n });\n fileLastEventTime.set(pendingFile, Date.now());\n }\n pendingProgressByFile.clear();\n throttleTimer = null;\n }, timeRemaining);\n }\n return;\n }\n\n // Send immediately\n onProgress(Math.round(overallProgress), \"Downloading model\", {\n file,\n progress: fileProgressValue,\n });\n fileLastEventTime.set(file, now);\n // Clear any pending progress for this file since we're sending it now\n pendingProgressByFile.delete(file);\n if (throttleTimer && pendingProgressByFile.size === 0) {\n clearTimeout(throttleTimer);\n throttleTimer = null;\n }\n };\n\n // Track whether we've seen a substantial file (to avoid premature progress reports for tiny config files)\n let hasSeenSubstantialFile = false;\n const substantialFileThreshold = 1024 * 1024; // 1MB - files larger than this are substantial\n\n // Get the abort signal from options if provided\n const abortSignal = options.abort_signal;\n\n // Create a callback status object for progress tracking\n const progressCallback = (status: CallbackStatus) => {\n // Check if operation has been aborted before processing progress\n if (abortSignal?.aborted) {\n return; // Don't process progress for aborted operations\n }\n\n if (status.status === \"progress\") {\n const file = status.file;\n const fileTotal = status.total;\n const fileProgressValue = status.progress;\n\n // Track file size on first progress event\n if (!fileSizes.has(file)) {\n fileSizes.set(file, fileTotal);\n fileProgress.set(file, 0);\n\n // Check if this is a substantial file\n if (fileTotal >= substantialFileThreshold) {\n hasSeenSubstantialFile = true;\n }\n }\n\n // Update file progress\n fileProgress.set(file, fileProgressValue);\n\n // Check if file is complete\n const isComplete = fileProgressValue >= 100;\n if (isComplete && !fileCompleted.has(file)) {\n fileCompleted.add(file);\n fileProgress.set(file, 100);\n }\n\n // Calculate actual loaded bytes and adjust estimated total\n let actualLoadedSize = 0;\n let actualTotalSize = 0;\n\n // Categorize seen files and track their actual sizes\n const tinyThreshold = 100 * 1024; // 100KB - files smaller are config/vocab\n const mediumThreshold = 100 * 1024 * 1024; // 100MB - tokenizer and small models\n let seenTinyCount = 0;\n let seenMediumCount = 0;\n let seenLargeCount = 0;\n\n for (const [trackedFile, size] of fileSizes.entries()) {\n actualTotalSize += size;\n const progress = fileProgress.get(trackedFile) || 0;\n actualLoadedSize += (size * progress) / 100;\n\n // Categorize file\n if (size < tinyThreshold) {\n seenTinyCount++;\n } else if (size < mediumThreshold) {\n seenMediumCount++;\n } else {\n seenLargeCount++;\n }\n }\n\n // Adjust estimated total size:\n // - Start with actual sizes of seen files\n // - Add estimates for unseen tiny/medium files\n // - For large files: conservatively assume 1 until we've seen all expected files\n const unseenTinyFiles = Math.max(0, estimatedTinyFiles - seenTinyCount);\n const unseenMediumFiles = Math.max(0, estimatedMediumFiles - seenMediumCount);\n\n // Dynamically estimate large files:\n // - If we've seen a large file, assume up to 2 total\n // - Otherwise, conservatively assume 1 large file might exist to prevent premature 100% progress\n // - This prevents the progress from jumping when a large file appears unexpectedly\n let estimatedLargeFiles: number;\n if (seenLargeCount > 0) {\n estimatedLargeFiles = 2; // We've seen at least one, expect up to 2\n } else {\n estimatedLargeFiles = 1; // Haven't seen any large files yet, but assume 1 might exist\n }\n const unseenLargeFiles = Math.max(0, estimatedLargeFiles - seenLargeCount);\n\n const adjustedTotalSize =\n actualTotalSize +\n unseenTinyFiles * estimatedTinySize +\n unseenMediumFiles * estimatedMediumSize +\n unseenLargeFiles * estimatedLargeSize;\n\n // Scale progress to the configured range (0-100 for download-only, 0-10 for download+run)\n const rawProgress = adjustedTotalSize > 0 ? (actualLoadedSize / adjustedTotalSize) * 100 : 0;\n const overallProgress = (rawProgress * progressScaleMax) / 100;\n\n // Determine if this is first or last event for this file\n const isFirst = !fileFirstSent.has(file);\n const isLast = isComplete && !fileLastSent.has(file);\n\n if (isFirst) {\n fileFirstSent.add(file);\n }\n if (isLast) {\n fileLastSent.add(file);\n }\n\n // Only report progress if we've seen a substantial file (to avoid premature 100% for tiny config files)\n if (hasSeenSubstantialFile) {\n sendProgress(overallProgress, file, fileProgressValue, isFirst, isLast);\n }\n } else if (status.status === \"done\" || status.status === \"download\") {\n // Handle file completion from bookend events\n const file = status.file;\n\n // Check if this file should mark the start of substantial downloads\n const fileSize = fileSizes.get(file) || 0;\n if (fileSize >= substantialFileThreshold) {\n hasSeenSubstantialFile = true;\n }\n\n if (!fileCompleted.has(file)) {\n fileCompleted.add(file);\n fileProgress.set(file, 100);\n\n // Recalculate overall progress using same logic as progress handler\n let actualLoadedSize = 0;\n let actualTotalSize = 0;\n\n const tinyThreshold = 100 * 1024; // 100KB - files smaller are config/vocab\n const mediumThreshold = 100 * 1024 * 1024; // 100MB - tokenizer and small models\n let seenTinyCount = 0;\n let seenMediumCount = 0;\n let seenLargeCount = 0;\n\n for (const [trackedFile, size] of fileSizes.entries()) {\n actualTotalSize += size;\n const progress = fileProgress.get(trackedFile) || 0;\n actualLoadedSize += (size * progress) / 100;\n\n // Categorize file\n if (size < tinyThreshold) {\n seenTinyCount++;\n } else if (size < mediumThreshold) {\n seenMediumCount++;\n } else {\n seenLargeCount++;\n }\n }\n\n // Adjust estimated total size (same logic as progress handler)\n const unseenTinyFiles = Math.max(0, estimatedTinyFiles - seenTinyCount);\n const unseenMediumFiles = Math.max(0, estimatedMediumFiles - seenMediumCount);\n\n // Dynamically estimate large files (same logic as progress handler)\n let estimatedLargeFiles: number;\n if (seenLargeCount > 0) {\n estimatedLargeFiles = 2;\n } else {\n estimatedLargeFiles = 1;\n }\n const unseenLargeFiles = Math.max(0, estimatedLargeFiles - seenLargeCount);\n\n const adjustedTotalSize =\n actualTotalSize +\n unseenTinyFiles * estimatedTinySize +\n unseenMediumFiles * estimatedMediumSize +\n unseenLargeFiles * estimatedLargeSize;\n\n // Scale progress to the configured range (0-100 for download-only, 0-10 for download+run)\n const rawProgress =\n adjustedTotalSize > 0 ? (actualLoadedSize / adjustedTotalSize) * 100 : 0;\n const overallProgress = (rawProgress * progressScaleMax) / 100;\n const isLast = !fileLastSent.has(file);\n if (isLast) {\n fileLastSent.add(file);\n // Only report if we've seen a substantial file\n if (hasSeenSubstantialFile) {\n sendProgress(overallProgress, file, 100, false, true);\n }\n }\n }\n }\n };\n\n const pipelineOptions: PretrainedModelOptions = {\n dtype: model.providerConfig.dType || \"q8\",\n ...(model.providerConfig.useExternalDataFormat\n ? { use_external_data_format: model.providerConfig.useExternalDataFormat }\n : {}),\n ...(model.providerConfig.device ? { device: model.providerConfig.device as any } : {}),\n ...options,\n progress_callback: progressCallback,\n };\n\n // Check if already aborted before starting\n if (abortSignal?.aborted) {\n throw new Error(\"Operation aborted before pipeline creation\");\n }\n\n const pipelineType = model.providerConfig.pipeline;\n\n // Wrap the pipeline call with abort handling\n // Create a promise that rejects when aborted\n const abortPromise = new Promise<never>((_, reject) => {\n if (abortSignal) {\n const handleAbort = () => {\n reject(new Error(\"Pipeline download aborted\"));\n };\n\n if (abortSignal.aborted) {\n handleAbort();\n } else {\n abortSignal.addEventListener(\"abort\", handleAbort, { once: true });\n }\n }\n });\n\n // Race between pipeline creation and abort\n const pipelinePromise = pipeline(pipelineType, model.providerConfig.modelPath, pipelineOptions);\n\n try {\n const result = await (abortSignal\n ? Promise.race([pipelinePromise, abortPromise])\n : pipelinePromise);\n\n // Check if aborted after pipeline creation\n if (abortSignal?.aborted) {\n throw new Error(\"Operation aborted after pipeline creation\");\n }\n\n pipelines.set(model.model_id, result);\n return result;\n } catch (error: any) {\n // If aborted, throw a clean abort error rather than internal stream errors\n if (abortSignal?.aborted) {\n throw new Error(\"Pipeline download aborted\");\n }\n // Otherwise, re-throw the original error\n throw error;\n }\n};\n\n/**\n * Core implementation for downloading and caching a Hugging Face Transformers model.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_Download: AiProviderRunFn<\n DownloadModelTaskExecuteInput,\n DownloadModelTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n // Download the model by creating a pipeline\n // Use 100 as progressScaleMax since this is download-only (0-100%)\n await getPipeline(model!, onProgress, { abort_signal: signal }, 100);\n\n return {\n model: input.model!,\n };\n};\n\n/**\n * Core implementation for unloading a Hugging Face Transformers model.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_Unload: AiProviderRunFn<\n UnloadModelTaskExecuteInput,\n UnloadModelTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n // Delete the pipeline from the in-memory map\n if (pipelines.has(model!.model_id)) {\n pipelines.delete(model!.model_id);\n onProgress(50, \"Pipeline removed from memory\");\n }\n\n // Delete model cache entries\n const modelPath = model!.providerConfig.modelPath;\n await deleteModelCache(modelPath);\n onProgress(100, \"Model cache deleted\");\n\n return {\n model: input.model!,\n };\n};\n\n/**\n * Deletes all cache entries for a given model path\n * @param modelPath - The model path to delete from cache\n */\nconst deleteModelCache = async (modelPath: string): Promise<void> => {\n const cache = await caches.open(HTF_CACHE_NAME);\n const keys = await cache.keys();\n const prefix = `/${modelPath}/`;\n\n // Collect all matching requests first\n const requestsToDelete: Request[] = [];\n for (const request of keys) {\n const url = new URL(request.url);\n if (url.pathname.startsWith(prefix)) {\n requestsToDelete.push(request);\n }\n }\n\n // Delete all matching requests\n let deletedCount = 0;\n for (const request of requestsToDelete) {\n try {\n const deleted = await cache.delete(request);\n if (deleted) {\n deletedCount++;\n } else {\n // If delete returns false, try with URL string as fallback\n const deletedByUrl = await cache.delete(request.url);\n if (deletedByUrl) {\n deletedCount++;\n }\n }\n } catch (error) {\n console.error(`Failed to delete cache entry: ${request.url}`, error);\n }\n }\n};\n\n/**\n * Core implementation for text embedding using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\n\nexport const HFT_TextEmbedding: AiProviderRunFn<\n TextEmbeddingTaskExecuteInput,\n TextEmbeddingTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const generateEmbedding: FeatureExtractionPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n\n // Generate the embedding\n const hfVector = await generateEmbedding(input.text, {\n pooling: \"mean\",\n normalize: model?.providerConfig.normalize,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n // Validate the embedding dimensions\n if (hfVector.size !== model?.providerConfig.nativeDimensions) {\n console.warn(\n `HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${model?.providerConfig.nativeDimensions}`,\n input,\n hfVector\n );\n throw new PermanentJobError(\n `HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${model?.providerConfig.nativeDimensions}`\n );\n }\n\n return { vector: hfVector.data as TypedArray };\n};\n\nexport const HFT_TextClassifier: AiProviderRunFn<\n TextClassifierTaskExecuteInput,\n TextClassifierTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const textClassifier: TextClassificationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const result = await textClassifier(input.text, {\n top_k: input.maxCategories || undefined,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n if (Array.isArray(result[0])) {\n return {\n categories: result[0].map((category) => ({\n label: category.label,\n score: category.score,\n })),\n };\n }\n\n return {\n categories: (result as TextClassificationOutput).map((category) => ({\n label: category.label,\n score: category.score,\n })),\n };\n};\n\nexport const HFT_TextLanguageDetection: AiProviderRunFn<\n TextLanguageDetectionTaskExecuteInput,\n TextLanguageDetectionTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const textClassifier: TextClassificationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const result = await textClassifier(input.text, {\n top_k: input.maxLanguages || undefined,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n if (Array.isArray(result[0])) {\n return {\n languages: result[0].map((category) => ({\n language: category.label,\n score: category.score,\n })),\n };\n }\n\n return {\n languages: (result as TextClassificationOutput).map((category) => ({\n language: category.label,\n score: category.score,\n })),\n };\n};\n\nexport const HFT_TextNamedEntityRecognition: AiProviderRunFn<\n TextNamedEntityRecognitionTaskExecuteInput,\n TextNamedEntityRecognitionTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const textNamedEntityRecognition: TokenClassificationPipeline = await getPipeline(\n model!,\n onProgress,\n {\n abort_signal: signal,\n }\n );\n let results = await textNamedEntityRecognition(input.text, {\n ignore_labels: input.blockList as string[] | undefined,\n ...(signal ? { abort_signal: signal } : {}),\n });\n let entities: TokenClassificationSingle[] = [];\n if (!Array.isArray(results)) {\n entities = [results];\n } else {\n entities = results as TokenClassificationSingle[];\n }\n return {\n entities: entities.map((entity) => ({\n entity: entity.entity,\n score: entity.score,\n word: entity.word,\n })),\n };\n};\n\nexport const HFT_TextFillMask: AiProviderRunFn<\n TextFillMaskTaskExecuteInput,\n TextFillMaskTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const unmasker: FillMaskPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n let results = await unmasker(input.text);\n let predictions: FillMaskSingle[] = [];\n if (!Array.isArray(results)) {\n predictions = [results];\n } else {\n predictions = results as FillMaskSingle[];\n }\n return {\n predictions: predictions.map((prediction) => ({\n entity: prediction.token_str,\n score: prediction.score,\n sequence: prediction.sequence,\n })),\n };\n};\n\n/**\n * Core implementation for text generation using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextGeneration: AiProviderRunFn<\n TextGenerationTaskExecuteInput,\n TextGenerationTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const generateText: TextGenerationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n\n const streamer = createTextStreamer(generateText.tokenizer, onProgress, signal);\n\n let results = await generateText(input.prompt, {\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n if (!Array.isArray(results)) {\n results = [results];\n }\n let text = (results[0] as TextGenerationSingle)?.generated_text;\n\n if (Array.isArray(text)) {\n text = text[text.length - 1]?.content;\n }\n return {\n text,\n };\n};\n\n/**\n * Core implementation for text translation using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextTranslation: AiProviderRunFn<\n TextTranslationTaskExecuteInput,\n TextTranslationTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const translate: TranslationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const streamer = createTextStreamer(translate.tokenizer, onProgress);\n\n const result = await translate(input.text, {\n src_lang: input.source_lang,\n tgt_lang: input.target_lang,\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n } as any);\n\n let translatedText: string | string[] = \"\";\n if (Array.isArray(result)) {\n translatedText = result.map((r) => (r as TranslationSingle)?.translation_text || \"\");\n } else {\n translatedText = (result as TranslationSingle)?.translation_text || \"\";\n }\n\n return {\n text: translatedText,\n target_lang: input.target_lang,\n };\n};\n\n/**\n * Core implementation for text rewriting using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextRewriter: AiProviderRunFn<\n TextRewriterTaskExecuteInput,\n TextRewriterTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const generateText: TextGenerationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const streamer = createTextStreamer(generateText.tokenizer, onProgress);\n\n // This lib doesn't support this kind of rewriting with a separate prompt vs text\n const promptedText = (input.prompt ? input.prompt + \"\\n\" : \"\") + input.text;\n\n let results = await generateText(promptedText, {\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n });\n\n if (!Array.isArray(results)) {\n results = [results];\n }\n\n let text = (results[0] as TextGenerationSingle)?.generated_text;\n if (Array.isArray(text)) {\n text = text[text.length - 1]?.content;\n }\n\n if (text === promptedText) {\n throw new PermanentJobError(\"Rewriter failed to generate new text\");\n }\n\n return {\n text,\n };\n};\n\n/**\n * Core implementation for text summarization using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextSummary: AiProviderRunFn<\n TextSummaryTaskExecuteInput,\n TextSummaryTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n const generateSummary: SummarizationPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const streamer = createTextStreamer(generateSummary.tokenizer, onProgress);\n\n let result = await generateSummary(input.text, {\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n } as any);\n\n let summaryText = \"\";\n if (Array.isArray(result)) {\n summaryText = (result[0] as SummarizationSingle)?.summary_text || \"\";\n } else {\n summaryText = (result as SummarizationSingle)?.summary_text || \"\";\n }\n\n return {\n text: summaryText,\n };\n};\n\n/**\n * Core implementation for question answering using Hugging Face Transformers.\n * This is shared between inline and worker implementations.\n */\nexport const HFT_TextQuestionAnswer: AiProviderRunFn<\n TextQuestionAnswerTaskExecuteInput,\n TextQuestionAnswerTaskExecuteOutput,\n HfTransformersOnnxModelRecord\n> = async (input, model, onProgress, signal) => {\n // Get the question answering pipeline\n const generateAnswer: QuestionAnsweringPipeline = await getPipeline(model!, onProgress, {\n abort_signal: signal,\n });\n const streamer = createTextStreamer(generateAnswer.tokenizer, onProgress);\n\n const result = await generateAnswer(input.question, input.context, {\n streamer,\n ...(signal ? { abort_signal: signal } : {}),\n } as any);\n\n let answerText = \"\";\n if (Array.isArray(result)) {\n answerText = (result[0] as DocumentQuestionAnsweringSingle)?.answer || \"\";\n } else {\n answerText = (result as DocumentQuestionAnsweringSingle)?.answer || \"\";\n }\n\n return {\n text: answerText,\n };\n};\n\n/**\n * Create a text streamer for a given tokenizer and update progress function\n * @param tokenizer - The tokenizer to use for the streamer\n * @param updateProgress - The function to call to update the progress\n * @param signal - The signal to use for the streamer for aborting\n * @returns The text streamer\n */\nfunction createTextStreamer(\n tokenizer: any,\n updateProgress: (progress: number, message?: string, details?: any) => void,\n signal?: AbortSignal\n) {\n let count = 0;\n return new TextStreamer(tokenizer, {\n skip_prompt: true,\n decode_kwargs: { skip_special_tokens: true },\n callback_function: (text: string) => {\n count++;\n const result = 100 * (1 - Math.exp(-0.05 * count));\n const progress = Math.round(Math.min(result, 100));\n updateProgress(progress, \"Generating\", { text, progress });\n },\n ...(signal ? { abort_signal: signal } : {}),\n });\n}\n",
|
|
7
7
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { ModelSchema } from \"@workglow/ai\";\nimport { DataPortSchemaObject, FromSchema } from \"@workglow/util\";\nimport { HF_TRANSFORMERS_ONNX, PipelineUseCase, QuantizationDataType } from \"./HFT_Constants\";\n\nexport const HfTransformersOnnxModelSchema = {\n type: \"object\",\n properties: {\n provider: {\n const: HF_TRANSFORMERS_ONNX,\n description: \"Discriminator: ONNX runtime backend.\",\n },\n providerConfig: {\n type: \"object\",\n description: \"ONNX runtime-specific options.\",\n properties: {\n pipeline: {\n type: \"string\",\n enum: Object.values(PipelineUseCase),\n description: \"Pipeline type for the ONNX model.\",\n default: \"text-generation\",\n },\n modelPath: {\n type: \"string\",\n description: \"Filesystem path or URI for the ONNX model.\",\n },\n dType: {\n type: \"string\",\n enum: Object.values(QuantizationDataType),\n description: \"Data type for the ONNX model.\",\n default: \"float32\",\n },\n device: {\n type: \"string\",\n enum: [\"cpu\", \"gpu\", \"webgpu\", \"wasm\", \"metal\"],\n description: \"High-level device selection.\",\n default: \"webgpu\",\n },\n executionProviders: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Raw ONNX Runtime execution provider identifiers.\",\n },\n intraOpNumThreads: {\n type: \"integer\",\n minimum: 1,\n },\n interOpNumThreads: {\n type: \"integer\",\n minimum: 1,\n },\n useExternalDataFormat: {\n type: \"boolean\",\n description: \"Whether the model uses external data format.\",\n },\n nativeDimensions: {\n type: \"integer\",\n description: \"The native dimensions of the model.\",\n },\n normalize: {\n type: \"boolean\",\n description: \"Whether the model uses normalization.\",\n },\n languageStyle: {\n type: \"string\",\n description: \"The language style of the model.\",\n },\n },\n required: [\"modelPath\", \"pipeline\"],\n additionalProperties: false,\n if: {\n properties: {\n pipeline: {\n const: \"feature-extraction\",\n },\n },\n },\n then: {\n required: [\"nativeDimensions\"],\n },\n },\n },\n required: [\"provider\", \"providerConfig\"],\n additionalProperties: true,\n} as const satisfies DataPortSchemaObject;\n\nconst ExtendedModelSchema = {\n type: \"object\",\n properties: {\n ...ModelSchema.properties,\n ...HfTransformersOnnxModelSchema.properties,\n },\n required: [...ModelSchema.required, ...HfTransformersOnnxModelSchema.required],\n additionalProperties: false,\n} as const satisfies DataPortSchemaObject;\n\nexport type HfTransformersOnnxModelRecord = FromSchema<typeof ExtendedModelSchema>;\n",
|
|
8
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { AiJob, AiJobInput, getAiProviderRegistry } from \"@workglow/ai\";\nimport { ConcurrencyLimiter, JobQueueClient, JobQueueServer } from \"@workglow/job-queue\";\nimport { InMemoryQueueStorage } from \"@workglow/storage\";\nimport { getTaskQueueRegistry, TaskInput, TaskOutput } from \"@workglow/task-graph\";\nimport { globalServiceRegistry, WORKER_MANAGER } from \"@workglow/util\";\nimport { HF_TRANSFORMERS_ONNX } from \"../common/HFT_Constants\";\n\n/**\n * Registers the HuggingFace Transformers client job functions with a web worker.\n * If no client is provided, creates a default in-memory queue and registers it.\n *\n * @param worker - The web worker to use for job execution\n * @param client - Optional existing JobQueueClient. If not provided, creates a default in-memory queue.\n */\nexport async function register_HFT_ClientJobFns(\n worker: Worker,\n client?: JobQueueClient<AiJobInput<TaskInput>, TaskOutput>\n): Promise<void> {\n const workerManager = globalServiceRegistry.get(WORKER_MANAGER);\n\n workerManager.registerWorker(HF_TRANSFORMERS_ONNX, worker);\n\n const ProviderRegistry = getAiProviderRegistry();\n const names = [\n \"DownloadModelTask\",\n \"UnloadModelTask\",\n \"TextEmbeddingTask\",\n \"TextLanguageDetectionTask\",\n \"TextClassifierTask\",\n \"TextGenerationTask\",\n \"TextTranslationTask\",\n \"TextRewriterTask\",\n \"TextSummaryTask\",\n \"TextQuestionAnswerTask\",\n ];\n for (const name of names) {\n ProviderRegistry.registerAsWorkerRunFn(HF_TRANSFORMERS_ONNX, name);\n }\n // If no client provided, create a default in-memory queue\n if (!client) {\n const storage = new InMemoryQueueStorage<AiJobInput<TaskInput>, TaskOutput>(\n HF_TRANSFORMERS_ONNX\n );\n\n const server = new JobQueueServer<AiJobInput<TaskInput>, TaskOutput>(AiJob, {\n storage,\n queueName: HF_TRANSFORMERS_ONNX,\n limiter: new ConcurrencyLimiter(1, 100),\n });\n\n client = new JobQueueClient<AiJobInput<TaskInput>, TaskOutput>({\n storage,\n queueName: HF_TRANSFORMERS_ONNX,\n });\n\n client.attach(server);\n\n getTaskQueueRegistry().registerQueue({ server, client, storage });\n // await server.start();\n }\n}\n",
|
|
9
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { env } from \"@sroussey/transformers\";\nimport { AiJob, AiJobInput, AiProviderRunFn, getAiProviderRegistry } from \"@workglow/ai\";\nimport { ConcurrencyLimiter, JobQueueClient, JobQueueServer } from \"@workglow/job-queue\";\nimport { InMemoryQueueStorage } from \"@workglow/storage\";\nimport { getTaskQueueRegistry, TaskInput, TaskOutput } from \"@workglow/task-graph\";\nimport { HF_TRANSFORMERS_ONNX } from \"../common/HFT_Constants\";\nimport {\n HFT_Download,\n HFT_TextClassifier,\n HFT_TextEmbedding,\n HFT_TextGeneration,\n HFT_TextLanguageDetection,\n HFT_TextQuestionAnswer,\n HFT_TextRewriter,\n HFT_TextSummary,\n HFT_TextTranslation,\n HFT_Unload,\n} from \"../common/HFT_JobRunFns\";\n\n/**\n * Registers the HuggingFace Transformers inline job functions for same-thread execution.\n * If no client is provided, creates a default in-memory queue and registers it.\n *\n * @param client - Optional existing JobQueueClient. If not provided, creates a default in-memory queue.\n */\nexport async function register_HFT_InlineJobFns(\n client?: JobQueueClient<AiJobInput<TaskInput>, TaskOutput>\n): Promise<void> {\n // @ts-ignore\n env.backends.onnx.wasm.proxy = true;\n const ProviderRegistry = getAiProviderRegistry();\n const fns: Record<string, AiProviderRunFn<any, any, any>> = {\n [\"DownloadModelTask\"]: HFT_Download,\n [\"UnloadModelTask\"]: HFT_Unload,\n [\"TextEmbeddingTask\"]: HFT_TextEmbedding,\n [\"TextGenerationTask\"]: HFT_TextGeneration,\n [\"TextQuestionAnswerTask\"]: HFT_TextQuestionAnswer,\n [\"TextLanguageDetectionTask\"]: HFT_TextLanguageDetection,\n [\"TextClassifierTask\"]: HFT_TextClassifier,\n [\"TextRewriterTask\"]: HFT_TextRewriter,\n [\"TextSummaryTask\"]: HFT_TextSummary,\n [\"TextTranslationTask\"]: HFT_TextTranslation,\n };\n for (const [jobName, fn] of Object.entries(fns)) {\n ProviderRegistry.registerRunFn<any, any>(HF_TRANSFORMERS_ONNX, jobName, fn);\n }\n\n // If no client provided, create a default in-memory queue\n if (!client) {\n const storage = new InMemoryQueueStorage<AiJobInput<TaskInput>, TaskOutput>(\n HF_TRANSFORMERS_ONNX\n );\n await storage.setupDatabase();\n\n const server = new JobQueueServer<AiJobInput<TaskInput>, TaskOutput>(AiJob, {\n storage,\n queueName: HF_TRANSFORMERS_ONNX,\n limiter: new ConcurrencyLimiter(1, 100),\n });\n\n client = new JobQueueClient<AiJobInput<TaskInput>, TaskOutput>({\n storage,\n queueName: HF_TRANSFORMERS_ONNX,\n });\n\n client.attach(server);\n\n getTaskQueueRegistry().registerQueue({ server, client, storage });\n await server.start();\n }\n}\n",
|
|
10
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n createServiceToken,\n globalServiceRegistry,\n parentPort,\n WORKER_SERVER,\n} from \"@workglow/util\";\nimport {\n HFT_Download,\n HFT_TextClassifier,\n HFT_TextEmbedding,\n HFT_TextGeneration,\n HFT_TextLanguageDetection,\n HFT_TextQuestionAnswer,\n HFT_TextRewriter,\n HFT_TextSummary,\n HFT_TextTranslation,\n HFT_Unload,\n} from \"../common/HFT_JobRunFns\";\n\nexport const HFT_WORKER_JOBRUN = createServiceToken(\"worker.ai-provider.hft\");\n\nexport const HFT_WORKER_JOBRUN_REGISTER = globalServiceRegistry.register(\n HFT_WORKER_JOBRUN,\n () => {\n const workerServer = globalServiceRegistry.get(WORKER_SERVER);\n workerServer.registerFunction(\"DownloadModelTask\", HFT_Download);\n workerServer.registerFunction(\"UnloadModelTask\", HFT_Unload);\n workerServer.registerFunction(\"TextEmbeddingTask\", HFT_TextEmbedding);\n workerServer.registerFunction(\"TextGenerationTask\", HFT_TextGeneration);\n workerServer.registerFunction(\"TextLanguageDetectionTask\", HFT_TextLanguageDetection);\n workerServer.registerFunction(\"TextClassifierTask\", HFT_TextClassifier);\n workerServer.registerFunction(\"TextTranslationTask\", HFT_TextTranslation);\n workerServer.registerFunction(\"TextRewriterTask\", HFT_TextRewriter);\n workerServer.registerFunction(\"TextSummaryTask\", HFT_TextSummary);\n workerServer.registerFunction(\"TextQuestionAnswerTask\", HFT_TextQuestionAnswer);\n parentPort.postMessage({ type: \"ready\" });\n console.log(\"HFT_WORKER_JOBRUN registered\");\n return workerServer;\n },\n true\n);\n",
|
|
8
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { AiJob, AiJobInput, getAiProviderRegistry } from \"@workglow/ai\";\nimport { ConcurrencyLimiter, JobQueueClient, JobQueueServer } from \"@workglow/job-queue\";\nimport { InMemoryQueueStorage } from \"@workglow/storage\";\nimport { getTaskQueueRegistry, TaskInput, TaskOutput } from \"@workglow/task-graph\";\nimport { globalServiceRegistry, WORKER_MANAGER } from \"@workglow/util\";\nimport { HF_TRANSFORMERS_ONNX } from \"../common/HFT_Constants\";\n\n/**\n * Registers the HuggingFace Transformers client job functions with a web worker.\n * If no client is provided, creates a default in-memory queue and registers it.\n *\n * @param worker - The web worker to use for job execution\n * @param client - Optional existing JobQueueClient. If not provided, creates a default in-memory queue.\n */\nexport async function register_HFT_ClientJobFns(\n worker: Worker,\n client?: JobQueueClient<AiJobInput<TaskInput>, TaskOutput>\n): Promise<void> {\n const workerManager = globalServiceRegistry.get(WORKER_MANAGER);\n\n workerManager.registerWorker(HF_TRANSFORMERS_ONNX, worker);\n\n const ProviderRegistry = getAiProviderRegistry();\n const names = [\n \"DownloadModelTask\",\n \"UnloadModelTask\",\n \"TextEmbeddingTask\",\n \"TextLanguageDetectionTask\",\n \"TextClassifierTask\",\n \"TextFillMaskTask\",\n \"TextNamedEntityRecognitionTask\",\n \"TextGenerationTask\",\n \"TextTranslationTask\",\n \"TextRewriterTask\",\n \"TextSummaryTask\",\n \"TextQuestionAnswerTask\",\n ];\n for (const name of names) {\n ProviderRegistry.registerAsWorkerRunFn(HF_TRANSFORMERS_ONNX, name);\n }\n // If no client provided, create a default in-memory queue\n if (!client) {\n const storage = new InMemoryQueueStorage<AiJobInput<TaskInput>, TaskOutput>(\n HF_TRANSFORMERS_ONNX\n );\n\n const server = new JobQueueServer<AiJobInput<TaskInput>, TaskOutput>(AiJob, {\n storage,\n queueName: HF_TRANSFORMERS_ONNX,\n limiter: new ConcurrencyLimiter(1, 100),\n });\n\n client = new JobQueueClient<AiJobInput<TaskInput>, TaskOutput>({\n storage,\n queueName: HF_TRANSFORMERS_ONNX,\n });\n\n client.attach(server);\n\n getTaskQueueRegistry().registerQueue({ server, client, storage });\n // await server.start();\n }\n}\n",
|
|
9
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { env } from \"@sroussey/transformers\";\nimport { AiJob, AiJobInput, AiProviderRunFn, getAiProviderRegistry } from \"@workglow/ai\";\nimport { ConcurrencyLimiter, JobQueueClient, JobQueueServer } from \"@workglow/job-queue\";\nimport { InMemoryQueueStorage } from \"@workglow/storage\";\nimport { getTaskQueueRegistry, TaskInput, TaskOutput } from \"@workglow/task-graph\";\nimport { HF_TRANSFORMERS_ONNX } from \"../common/HFT_Constants\";\nimport {\n HFT_Download,\n HFT_TextClassifier,\n HFT_TextEmbedding,\n HFT_TextFillMask,\n HFT_TextGeneration,\n HFT_TextLanguageDetection,\n HFT_TextNamedEntityRecognition,\n HFT_TextQuestionAnswer,\n HFT_TextRewriter,\n HFT_TextSummary,\n HFT_TextTranslation,\n HFT_Unload,\n} from \"../common/HFT_JobRunFns\";\n\n/**\n * Registers the HuggingFace Transformers inline job functions for same-thread execution.\n * If no client is provided, creates a default in-memory queue and registers it.\n *\n * @param client - Optional existing JobQueueClient. If not provided, creates a default in-memory queue.\n */\nexport async function register_HFT_InlineJobFns(\n client?: JobQueueClient<AiJobInput<TaskInput>, TaskOutput>\n): Promise<void> {\n // @ts-ignore\n env.backends.onnx.wasm.proxy = true;\n const ProviderRegistry = getAiProviderRegistry();\n const fns: Record<string, AiProviderRunFn<any, any, any>> = {\n [\"DownloadModelTask\"]: HFT_Download,\n [\"UnloadModelTask\"]: HFT_Unload,\n [\"TextEmbeddingTask\"]: HFT_TextEmbedding,\n [\"TextGenerationTask\"]: HFT_TextGeneration,\n [\"TextQuestionAnswerTask\"]: HFT_TextQuestionAnswer,\n [\"TextLanguageDetectionTask\"]: HFT_TextLanguageDetection,\n [\"TextClassifierTask\"]: HFT_TextClassifier,\n [\"TextFillMaskTask\"]: HFT_TextFillMask,\n [\"TextNamedEntityRecognitionTask\"]: HFT_TextNamedEntityRecognition,\n [\"TextRewriterTask\"]: HFT_TextRewriter,\n [\"TextSummaryTask\"]: HFT_TextSummary,\n [\"TextTranslationTask\"]: HFT_TextTranslation,\n };\n for (const [jobName, fn] of Object.entries(fns)) {\n ProviderRegistry.registerRunFn<any, any>(HF_TRANSFORMERS_ONNX, jobName, fn);\n }\n\n // If no client provided, create a default in-memory queue\n if (!client) {\n const storage = new InMemoryQueueStorage<AiJobInput<TaskInput>, TaskOutput>(\n HF_TRANSFORMERS_ONNX\n );\n await storage.setupDatabase();\n\n const server = new JobQueueServer<AiJobInput<TaskInput>, TaskOutput>(AiJob, {\n storage,\n queueName: HF_TRANSFORMERS_ONNX,\n limiter: new ConcurrencyLimiter(1, 100),\n });\n\n client = new JobQueueClient<AiJobInput<TaskInput>, TaskOutput>({\n storage,\n queueName: HF_TRANSFORMERS_ONNX,\n });\n\n client.attach(server);\n\n getTaskQueueRegistry().registerQueue({ server, client, storage });\n await server.start();\n }\n}\n",
|
|
10
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n createServiceToken,\n globalServiceRegistry,\n parentPort,\n WORKER_SERVER,\n} from \"@workglow/util\";\nimport {\n HFT_Download,\n HFT_TextClassifier,\n HFT_TextEmbedding,\n HFT_TextFillMask,\n HFT_TextGeneration,\n HFT_TextLanguageDetection,\n HFT_TextNamedEntityRecognition,\n HFT_TextQuestionAnswer,\n HFT_TextRewriter,\n HFT_TextSummary,\n HFT_TextTranslation,\n HFT_Unload,\n} from \"../common/HFT_JobRunFns\";\n\nexport const HFT_WORKER_JOBRUN = createServiceToken(\"worker.ai-provider.hft\");\n\nexport const HFT_WORKER_JOBRUN_REGISTER = globalServiceRegistry.register(\n HFT_WORKER_JOBRUN,\n () => {\n const workerServer = globalServiceRegistry.get(WORKER_SERVER);\n workerServer.registerFunction(\"DownloadModelTask\", HFT_Download);\n workerServer.registerFunction(\"UnloadModelTask\", HFT_Unload);\n workerServer.registerFunction(\"TextEmbeddingTask\", HFT_TextEmbedding);\n workerServer.registerFunction(\"TextGenerationTask\", HFT_TextGeneration);\n workerServer.registerFunction(\"TextLanguageDetectionTask\", HFT_TextLanguageDetection);\n workerServer.registerFunction(\"TextClassifierTask\", HFT_TextClassifier);\n workerServer.registerFunction(\"TextFillMaskTask\", HFT_TextFillMask);\n workerServer.registerFunction(\"TextNamedEntityRecognitionTask\", HFT_TextNamedEntityRecognition);\n workerServer.registerFunction(\"TextTranslationTask\", HFT_TextTranslation);\n workerServer.registerFunction(\"TextRewriterTask\", HFT_TextRewriter);\n workerServer.registerFunction(\"TextSummaryTask\", HFT_TextSummary);\n workerServer.registerFunction(\"TextQuestionAnswerTask\", HFT_TextQuestionAnswer);\n parentPort.postMessage({ type: \"ready\" });\n console.log(\"HFT_WORKER_JOBRUN registered\");\n return workerServer;\n },\n true\n);\n",
|
|
11
11
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport const TENSORFLOW_MEDIAPIPE = \"TENSORFLOW_MEDIAPIPE\";\n\nexport type TextPipelineTask =\n | \"text-embedder\"\n | \"text-classifier\"\n | \"text-language-detector\"\n | \"genai-text\"\n | \"audio-classifier\"\n | \"audio-embedder\"\n | \"vision-face-detector\"\n | \"vision-face-landmarker\"\n | \"vision-face-stylizer\"\n | \"vision-gesture-recognizer\"\n | \"vision-hand-landmarker\"\n | \"vision-holistic-landmarker\"\n | \"vision-image-classifier\"\n | \"vision-image-embedder\"\n | \"vision-image-segmenter\"\n | \"vision-image-interactive-segmenter\"\n | \"vision-object-detector\"\n | \"vision-pose-landmarker\";\n\nexport const TextPipelineTask = {\n \"text-embedder\": \"text-embedder\",\n \"text-classifier\": \"text-classifier\",\n \"text-language-detector\": \"text-language-detector\",\n \"genai-text\": \"genai-text\",\n \"audio-classifier\": \"audio-classifier\",\n \"audio-embedder\": \"audio-embedder\",\n \"vision-face-detector\": \"vision-face-detector\",\n \"vision-face-landmarker\": \"vision-face-landmarker\",\n \"vision-face-stylizer\": \"vision-face-stylizer\",\n \"vision-gesture-recognizer\": \"vision-gesture-recognizer\",\n \"vision-hand-landmarker\": \"vision-hand-landmarker\",\n \"vision-holistic-landmarker\": \"vision-holistic-landmarker\",\n \"vision-image-classifier\": \"vision-image-classifier\",\n \"vision-image-embedder\": \"vision-image-embedder\",\n \"vision-image-segmenter\": \"vision-image-segmenter\",\n \"vision-image-interactive-segmenter\": \"vision-image-interactive-segmenter\",\n \"vision-object-detector\": \"vision-object-detector\",\n \"vision-pose-landmarker\": \"vision-pose-landmarker\",\n} as const satisfies Record<TextPipelineTask, TextPipelineTask>;\n",
|
|
12
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n FilesetResolver,\n LanguageDetector,\n TextClassifier,\n TextEmbedder,\n} from \"@mediapipe/tasks-text\";\nimport type {\n AiProviderRunFn,\n DownloadModelTaskExecuteInput,\n DownloadModelTaskExecuteOutput,\n TextClassifierTaskExecuteInput,\n TextClassifierTaskExecuteOutput,\n TextEmbeddingTaskExecuteInput,\n TextEmbeddingTaskExecuteOutput,\n TextLanguageDetectionTaskExecuteInput,\n TextLanguageDetectionTaskExecuteOutput,\n UnloadModelTaskExecuteInput,\n UnloadModelTaskExecuteOutput,\n} from \"@workglow/ai\";\nimport { PermanentJobError } from \"@workglow/job-queue\";\nimport { TFMPModelRecord } from \"./TFMP_ModelSchema\";\n\ninterface TFMPWasmFileset {\n /** The path to the Wasm loader script. */\n wasmLoaderPath: string;\n /** The path to the Wasm binary. */\n wasmBinaryPath: string;\n /** The optional path to the asset loader script. */\n assetLoaderPath?: string;\n /** The optional path to the assets binary. */\n assetBinaryPath?: string;\n}\n\n/**\n * Cache for WASM filesets by task engine (text, audio, vision, genai).\n * Multiple models may share the same WASM fileset.\n */\nconst wasm_tasks = new Map<string, TFMPWasmFileset>();\n\n/**\n * Reference counts tracking how many models are using each WASM fileset.\n * When count reaches 0, the WASM fileset can be safely unloaded.\n */\nconst wasm_reference_counts = new Map<string, number>();\n\n/**\n * Maps model paths to their corresponding task engine.\n * Used to determine which WASM fileset to decrement when a model is unloaded.\n */\nconst model_to_wasm_mapping = new Map<string, string>();\n\n/**\n * Helper function to get a WASM task for a model\n */\nconst getWasmTask = async (\n model: TFMPModelRecord,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal\n): Promise<TFMPWasmFileset> => {\n const taskEngine = model.providerConfig.taskEngine;\n\n if (wasm_tasks.has(taskEngine)) {\n return wasm_tasks.get(taskEngine)!;\n }\n\n if (signal.aborted) {\n throw new PermanentJobError(\"Aborted job\");\n }\n\n onProgress(0.1, \"Loading WASM task\");\n\n let wasmFileset: TFMPWasmFileset;\n\n switch (taskEngine) {\n case \"text\":\n wasmFileset = await FilesetResolver.forTextTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-text@latest/wasm\"\n );\n break;\n case \"audio\":\n wasmFileset = await FilesetResolver.forAudioTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-audio@latest/wasm\"\n );\n break;\n case \"vision\":\n wasmFileset = await FilesetResolver.forVisionTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm\"\n );\n break;\n case \"genai\":\n wasmFileset = await FilesetResolver.forGenAiTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm\"\n );\n break;\n default:\n throw new PermanentJobError(\"Invalid task engine\");\n }\n\n wasm_tasks.set(taskEngine, wasmFileset);\n return wasmFileset;\n};\n\nconst modelTaskCache = new Map<string, TextEmbedder | TextClassifier | LanguageDetector>();\n\ntype InferTaskInstance<T> = T extends typeof TextEmbedder\n ? TextEmbedder\n : T extends typeof TextClassifier\n ? TextClassifier\n : T extends typeof LanguageDetector\n ? LanguageDetector\n : never;\n\nconst getModelTask = async <\n T extends typeof TextEmbedder | typeof TextClassifier | typeof LanguageDetector,\n>(\n model: TFMPModelRecord,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal,\n TaskType: T\n): Promise<InferTaskInstance<T>> => {\n const modelPath = model.providerConfig.modelPath;\n const taskEngine = model.providerConfig.taskEngine;\n\n if (modelTaskCache.has(modelPath)) {\n return modelTaskCache.get(modelPath)! as any;\n }\n\n // Load WASM if needed\n const wasmFileset = await getWasmTask(model, onProgress, signal);\n\n onProgress(0.2, \"Creating model task\");\n\n // Create new model instance\n const task = await TaskType.createFromOptions(wasmFileset, {\n baseOptions: {\n modelAssetPath: modelPath,\n },\n });\n\n // Cache the model\n modelTaskCache.set(modelPath, task);\n\n // Track WASM usage for this model and increment reference count\n model_to_wasm_mapping.set(modelPath, taskEngine);\n wasm_reference_counts.set(taskEngine, (wasm_reference_counts.get(taskEngine) || 0) + 1);\n\n return task as any;\n};\n\nconst getTextEmbedder = async (\n model: TFMPModelRecord,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal\n): Promise<TextEmbedder> => {\n return getModelTask(model, onProgress, signal, TextEmbedder);\n};\n\nconst getTextClassifier = async (\n model: TFMPModelRecord,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal\n): Promise<TextClassifier> => {\n return getModelTask(model, onProgress, signal, TextClassifier);\n};\n\nconst getTextLanguageDetector = async (\n model: TFMPModelRecord,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal\n): Promise<LanguageDetector> => {\n return getModelTask(model, onProgress, signal, LanguageDetector);\n};\n\n/**\n * Core implementation for downloading and caching a MediaPipe TFJS model.\n * This is shared between inline and worker implementations.\n */\nexport const TFMP_Download: AiProviderRunFn<\n DownloadModelTaskExecuteInput,\n DownloadModelTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n switch (model?.providerConfig.pipeline) {\n case \"text-embedder\":\n await getTextEmbedder(model, onProgress, signal);\n break;\n case \"text-classifier\":\n await getTextClassifier(model, onProgress, signal);\n break;\n case \"text-language-detector\":\n await getTextLanguageDetector(model, onProgress, signal);\n break;\n default:\n throw new PermanentJobError(\"Invalid pipeline\");\n }\n onProgress(0.9, \"Pipeline loaded\");\n\n return {\n model: input.model,\n };\n};\n\n/**\n * Core implementation for text embedding using MediaPipe TFJS.\n * This is shared between inline and worker implementations.\n */\nexport const TFMP_TextEmbedding: AiProviderRunFn<\n TextEmbeddingTaskExecuteInput,\n TextEmbeddingTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n onProgress(0.1, \"Model loaded\");\n\n const textEmbedder = await getTextEmbedder(model!, onProgress, signal);\n const result = textEmbedder.embed(input.text);\n\n if (!result.embeddings?.[0]?.floatEmbedding) {\n throw new PermanentJobError(\"Failed to generate embedding: Empty result\");\n }\n\n const embedding = Float32Array.from(result.embeddings[0].floatEmbedding);\n\n return {\n vector: embedding,\n };\n};\n\n/**\n * Core implementation for text classification using MediaPipe TFJS.\n * This is shared between inline and worker implementations.\n */\nexport const TFMP_TextClassifier: AiProviderRunFn<\n TextClassifierTaskExecuteInput,\n TextClassifierTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n onProgress(0.1, \"Model loaded\");\n\n const textClassifier = await getTextClassifier(model!, onProgress, signal);\n const result = textClassifier.classify(input.text);\n\n if (!result.classifications?.[0]?.categories) {\n throw new PermanentJobError(\"Failed to classify text: Empty result\");\n }\n\n const categories = result.classifications[0].categories.map((category) => ({\n label: category.categoryName,\n score: category.score,\n }));\n\n return {\n categories,\n };\n};\n\n/**\n * Core implementation for language detection using MediaPipe TFJS.\n * This is shared between inline and worker implementations.\n */\nexport const TFMP_TextLanguageDetection: AiProviderRunFn<\n TextLanguageDetectionTaskExecuteInput,\n TextLanguageDetectionTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n onProgress(0.1, \"Model loaded\");\n\n const textLanguageDetector = await getTextLanguageDetector(model!, onProgress, signal);\n const result = textLanguageDetector.detect(input.text);\n\n if (!result.languages?.[0]?.languageCode) {\n throw new PermanentJobError(\"Failed to detect language: Empty result\");\n }\n\n const languages = result.languages.map((language) => ({\n language: language.languageCode,\n score: language.probability,\n }));\n\n return {\n languages,\n };\n};\n\n/**\n * Core implementation for unloading a MediaPipe TFJS model.\n * This is shared between inline and worker implementations.\n *\n * When a model is unloaded, this function:\n * 1. Disposes of the model instance\n * 2. Decrements the reference count for the associated WASM fileset\n * 3. If no other models are using the WASM fileset (count reaches 0), unloads the WASM\n */\nexport const TFMP_Unload: AiProviderRunFn<\n UnloadModelTaskExecuteInput,\n UnloadModelTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n const modelPath = model!.providerConfig.modelPath;\n\n // Dispose of the model task if it exists\n if (modelTaskCache.has(modelPath)) {\n const item = modelTaskCache.get(modelPath)!;\n if (\"dispose\" in item && typeof item.dispose === \"function\") {\n item.dispose();\n }\n modelTaskCache.delete(modelPath);\n }\n\n // Decrease reference count for WASM fileset\n const taskEngine = model_to_wasm_mapping.get(modelPath);\n if (taskEngine) {\n const currentCount = wasm_reference_counts.get(taskEngine) || 0;\n const newCount = currentCount - 1;\n\n if (newCount <= 0) {\n // No more models using this WASM fileset, unload it\n wasm_tasks.delete(taskEngine);\n wasm_reference_counts.delete(taskEngine);\n } else {\n wasm_reference_counts.set(taskEngine, newCount);\n }\n\n model_to_wasm_mapping.delete(modelPath);\n }\n\n return {\n model: input.model,\n };\n};\n",
|
|
12
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n FilesetResolver,\n LanguageDetector,\n TextClassifier,\n TextEmbedder,\n} from \"@mediapipe/tasks-text\";\nimport type {\n AiProviderRunFn,\n DownloadModelTaskExecuteInput,\n DownloadModelTaskExecuteOutput,\n TextClassifierTaskExecuteInput,\n TextClassifierTaskExecuteOutput,\n TextEmbeddingTaskExecuteInput,\n TextEmbeddingTaskExecuteOutput,\n TextLanguageDetectionTaskExecuteInput,\n TextLanguageDetectionTaskExecuteOutput,\n UnloadModelTaskExecuteInput,\n UnloadModelTaskExecuteOutput,\n} from \"@workglow/ai\";\nimport { PermanentJobError } from \"@workglow/job-queue\";\nimport { TFMPModelRecord } from \"./TFMP_ModelSchema\";\n\ninterface TFMPWasmFileset {\n /** The path to the Wasm loader script. */\n wasmLoaderPath: string;\n /** The path to the Wasm binary. */\n wasmBinaryPath: string;\n /** The optional path to the asset loader script. */\n assetLoaderPath?: string;\n /** The optional path to the assets binary. */\n assetBinaryPath?: string;\n}\n\n/**\n * Cache for WASM filesets by task engine (text, audio, vision, genai).\n * Multiple models may share the same WASM fileset.\n */\nconst wasm_tasks = new Map<string, TFMPWasmFileset>();\n\n/**\n * Reference counts tracking how many models are using each WASM fileset.\n * When count reaches 0, the WASM fileset can be safely unloaded.\n */\nconst wasm_reference_counts = new Map<string, number>();\n\n/**\n * Maps model paths to their corresponding task engine.\n * Used to determine which WASM fileset to decrement when a model is unloaded.\n */\nconst model_to_wasm_mapping = new Map<string, string>();\n\n/**\n * Helper function to get a WASM task for a model\n */\nconst getWasmTask = async (\n model: TFMPModelRecord,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal\n): Promise<TFMPWasmFileset> => {\n const taskEngine = model.providerConfig.taskEngine;\n\n if (wasm_tasks.has(taskEngine)) {\n return wasm_tasks.get(taskEngine)!;\n }\n\n if (signal.aborted) {\n throw new PermanentJobError(\"Aborted job\");\n }\n\n onProgress(0.1, \"Loading WASM task\");\n\n let wasmFileset: TFMPWasmFileset;\n\n switch (taskEngine) {\n case \"text\":\n wasmFileset = await FilesetResolver.forTextTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-text@latest/wasm\"\n );\n break;\n case \"audio\":\n wasmFileset = await FilesetResolver.forAudioTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-audio@latest/wasm\"\n );\n break;\n case \"vision\":\n wasmFileset = await FilesetResolver.forVisionTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm\"\n );\n break;\n case \"genai\":\n wasmFileset = await FilesetResolver.forGenAiTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@latest/wasm\"\n );\n break;\n default:\n throw new PermanentJobError(\"Invalid task engine\");\n }\n\n wasm_tasks.set(taskEngine, wasmFileset);\n return wasmFileset;\n};\n\ninterface CachedModelTask {\n readonly task: TextEmbedder | TextClassifier | LanguageDetector;\n readonly options: Record<string, unknown>;\n readonly taskEngine: string;\n}\n\nconst modelTaskCache = new Map<string, CachedModelTask[]>();\n\ntype InferTaskInstance<T> = T extends typeof TextEmbedder\n ? TextEmbedder\n : T extends typeof TextClassifier\n ? TextClassifier\n : T extends typeof LanguageDetector\n ? LanguageDetector\n : never;\n\n/**\n * Checks if two option objects are deeply equal.\n */\nconst optionsMatch = (opts1: Record<string, unknown>, opts2: Record<string, unknown>): boolean => {\n const keys1 = Object.keys(opts1).sort();\n const keys2 = Object.keys(opts2).sort();\n\n if (keys1.length !== keys2.length) return false;\n\n return keys1.every((key) => {\n const val1 = opts1[key];\n const val2 = opts2[key];\n\n if (Array.isArray(val1) && Array.isArray(val2)) {\n return JSON.stringify(val1) === JSON.stringify(val2);\n }\n\n return val1 === val2;\n });\n};\n\nconst getModelTask = async <\n T extends typeof TextEmbedder | typeof TextClassifier | typeof LanguageDetector,\n>(\n model: TFMPModelRecord,\n options: Record<string, unknown>,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal,\n TaskType: T\n): Promise<InferTaskInstance<T>> => {\n const modelPath = model.providerConfig.modelPath;\n const taskEngine = model.providerConfig.taskEngine;\n\n // Check if we have a cached instance with matching options\n const cachedTasks = modelTaskCache.get(modelPath);\n if (cachedTasks) {\n const matchedTask = cachedTasks.find((cached) => optionsMatch(cached.options, options));\n if (matchedTask) {\n return matchedTask.task as InferTaskInstance<T>;\n }\n }\n\n // Load WASM if needed\n const wasmFileset = await getWasmTask(model, onProgress, signal);\n\n onProgress(0.2, \"Creating model task\");\n\n // Create new model instance\n const task = await TaskType.createFromOptions(wasmFileset, {\n baseOptions: {\n modelAssetPath: modelPath,\n },\n ...options,\n });\n\n // Cache the task with its options and task engine\n const cachedTask: CachedModelTask = { task, options, taskEngine };\n if (!modelTaskCache.has(modelPath)) {\n modelTaskCache.set(modelPath, []);\n }\n modelTaskCache.get(modelPath)!.push(cachedTask);\n\n // Increment WASM reference count for this cached task\n wasm_reference_counts.set(taskEngine, (wasm_reference_counts.get(taskEngine) || 0) + 1);\n\n return task as any;\n};\n\nconst getTextEmbedder = async (\n model: TFMPModelRecord,\n options: Record<string, unknown>,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal\n): Promise<TextEmbedder> => {\n return getModelTask(model, options, onProgress, signal, TextEmbedder);\n};\n\nconst getTextClassifier = async (\n model: TFMPModelRecord,\n options: Record<string, unknown>,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal\n): Promise<TextClassifier> => {\n return getModelTask(model, options, onProgress, signal, TextClassifier);\n};\n\nconst getTextLanguageDetector = async (\n model: TFMPModelRecord,\n options: Record<string, unknown>,\n onProgress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal\n): Promise<LanguageDetector> => {\n return getModelTask(model, options, onProgress, signal, LanguageDetector);\n};\n\n/**\n * Core implementation for downloading and caching a MediaPipe TFJS model.\n * This is shared between inline and worker implementations.\n */\nexport const TFMP_Download: AiProviderRunFn<\n DownloadModelTaskExecuteInput,\n DownloadModelTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n let task: TextEmbedder | TextClassifier | LanguageDetector;\n switch (model?.providerConfig.pipeline) {\n case \"text-embedder\":\n task = await getTextEmbedder(model, {}, onProgress, signal);\n break;\n case \"text-classifier\":\n task = await getTextClassifier(model, {}, onProgress, signal);\n break;\n case \"text-language-detector\":\n task = await getTextLanguageDetector(model, {}, onProgress, signal);\n break;\n default:\n throw new PermanentJobError(\"Invalid pipeline\");\n }\n onProgress(0.9, \"Pipeline loaded\");\n task.close(); // Close the task to release the resources, but it is still in the browser cache\n // Decrease reference count for WASM fileset for this cached task since this is a fake model cache entry\n const taskEngine = model?.providerConfig.taskEngine;\n wasm_reference_counts.set(taskEngine, wasm_reference_counts.get(taskEngine)! - 1);\n\n return {\n model: input.model,\n };\n};\n\n/**\n * Core implementation for text embedding using MediaPipe TFJS.\n * This is shared between inline and worker implementations.\n */\nexport const TFMP_TextEmbedding: AiProviderRunFn<\n TextEmbeddingTaskExecuteInput,\n TextEmbeddingTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n const textEmbedder = await getTextEmbedder(model!, {}, onProgress, signal);\n const result = textEmbedder.embed(input.text);\n\n if (!result.embeddings?.[0]?.floatEmbedding) {\n throw new PermanentJobError(\"Failed to generate embedding: Empty result\");\n }\n\n const embedding = Float32Array.from(result.embeddings[0].floatEmbedding);\n\n return {\n vector: embedding,\n };\n};\n\n/**\n * Core implementation for text classification using MediaPipe TFJS.\n * This is shared between inline and worker implementations.\n */\nexport const TFMP_TextClassifier: AiProviderRunFn<\n TextClassifierTaskExecuteInput,\n TextClassifierTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n const textClassifier = await getTextClassifier(\n model!,\n {\n maxCategories: input.maxCategories,\n // scoreThreshold: input.scoreThreshold,\n // allowList: input.allowList,\n // blockList: input.blockList,\n },\n onProgress,\n signal\n );\n const result = textClassifier.classify(input.text);\n\n if (!result.classifications?.[0]?.categories) {\n throw new PermanentJobError(\"Failed to classify text: Empty result\");\n }\n\n const categories = result.classifications[0].categories.map((category) => ({\n label: category.categoryName,\n score: category.score,\n }));\n\n return {\n categories,\n };\n};\n\n/**\n * Core implementation for language detection using MediaPipe TFJS.\n * This is shared between inline and worker implementations.\n */\nexport const TFMP_TextLanguageDetection: AiProviderRunFn<\n TextLanguageDetectionTaskExecuteInput,\n TextLanguageDetectionTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n const maxLanguages = input.maxLanguages === 0 ? -1 : input.maxLanguages;\n\n const textLanguageDetector = await getTextLanguageDetector(\n model!,\n {\n maxLanguages,\n // scoreThreshold: input.scoreThreshold,\n // allowList: input.allowList,\n // blockList: input.blockList,\n },\n onProgress,\n signal\n );\n const result = textLanguageDetector.detect(input.text);\n\n if (!result.languages?.[0]?.languageCode) {\n throw new PermanentJobError(\"Failed to detect language: Empty result\");\n }\n\n const languages = result.languages.map((language) => ({\n language: language.languageCode,\n score: language.probability,\n }));\n\n return {\n languages,\n };\n};\n\n/**\n * Core implementation for unloading a MediaPipe TFJS model.\n * This is shared between inline and worker implementations.\n *\n * When a model is unloaded, this function:\n * 1. Disposes of all cached model instances for the given model path\n * 2. Decrements the reference count for the associated WASM fileset for each instance\n * 3. If no other models are using the WASM fileset (count reaches 0), unloads the WASM\n */\nexport const TFMP_Unload: AiProviderRunFn<\n UnloadModelTaskExecuteInput,\n UnloadModelTaskExecuteOutput,\n TFMPModelRecord\n> = async (input, model, onProgress, signal) => {\n const modelPath = model!.providerConfig.modelPath;\n\n // Dispose of all cached model tasks if they exist\n if (modelTaskCache.has(modelPath)) {\n const cachedTasks = modelTaskCache.get(modelPath)!;\n\n for (const cachedTask of cachedTasks) {\n const task = cachedTask.task;\n task.close();\n\n // Decrease reference count for WASM fileset for this cached task\n const taskEngine = cachedTask.taskEngine;\n const currentCount = wasm_reference_counts.get(taskEngine) || 0;\n const newCount = currentCount - 1;\n\n if (newCount <= 0) {\n // No more models using this WASM fileset, unload it\n wasm_tasks.delete(taskEngine);\n wasm_reference_counts.delete(taskEngine);\n } else {\n wasm_reference_counts.set(taskEngine, newCount);\n }\n }\n\n modelTaskCache.delete(modelPath);\n }\n\n return {\n model: input.model,\n };\n};\n",
|
|
13
13
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { ModelSchema } from \"@workglow/ai\";\nimport { DataPortSchemaObject, FromSchema } from \"@workglow/util\";\nimport { TENSORFLOW_MEDIAPIPE, TextPipelineTask } from \"../common/TFMP_Constants\";\n\nexport const TFMPModelSchema = {\n type: \"object\",\n properties: {\n provider: {\n const: TENSORFLOW_MEDIAPIPE,\n description: \"Discriminator: TensorFlow MediaPipe backend.\",\n },\n providerConfig: {\n type: \"object\",\n description: \"TensorFlow MediaPipe-specific options.\",\n properties: {\n modelPath: {\n type: \"string\",\n description: \"Filesystem path or URI for the ONNX model.\",\n },\n taskEngine: {\n type: \"string\",\n enum: [\"text\", \"audio\", \"vision\", \"genai\"],\n description: \"Task engine for the MediaPipe model.\",\n },\n pipeline: {\n type: \"string\",\n enum: Object.values(TextPipelineTask),\n description: \"Pipeline task type for the MediaPipe model.\",\n },\n },\n required: [\"modelPath\", \"taskEngine\", \"pipeline\"],\n additionalProperties: false,\n },\n },\n required: [\"provider\", \"providerConfig\"],\n additionalProperties: true,\n} as const satisfies DataPortSchemaObject;\n\nconst ExtendedModelSchema = {\n type: \"object\",\n properties: {\n ...ModelSchema.properties,\n ...TFMPModelSchema.properties,\n },\n required: [...ModelSchema.required, ...TFMPModelSchema.required],\n additionalProperties: false,\n} as const satisfies DataPortSchemaObject;\n\nexport type TFMPModelRecord = FromSchema<typeof ExtendedModelSchema>;\n",
|
|
14
14
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { AiJob, AiJobInput, getAiProviderRegistry } from \"@workglow/ai\";\nimport { ConcurrencyLimiter, JobQueueClient, JobQueueServer } from \"@workglow/job-queue\";\nimport { InMemoryQueueStorage } from \"@workglow/storage\";\nimport { getTaskQueueRegistry, TaskInput, TaskOutput } from \"@workglow/task-graph\";\nimport { globalServiceRegistry, WORKER_MANAGER } from \"@workglow/util\";\nimport { TENSORFLOW_MEDIAPIPE } from \"../common/TFMP_Constants\";\n\n/**\n * Registers the TensorFlow MediaPipe client job functions with a web worker.\n * If no client is provided, creates a default in-memory queue and registers it.\n *\n * @param worker - The web worker to use for job execution\n * @param client - Optional existing JobQueueClient. If not provided, creates a default in-memory queue.\n */\nexport async function register_TFMP_ClientJobFns(\n worker: Worker,\n client?: JobQueueClient<AiJobInput<TaskInput>, TaskOutput>\n): Promise<void> {\n const workerManager = globalServiceRegistry.get(WORKER_MANAGER);\n workerManager.registerWorker(TENSORFLOW_MEDIAPIPE, worker);\n\n const aiProviderRegistry = getAiProviderRegistry();\n const names = [\n \"DownloadModelTask\",\n \"UnloadModelTask\",\n \"TextEmbeddingTask\",\n \"TextLanguageDetectionTask\",\n \"TextClassifierTask\",\n ];\n for (const name of names) {\n aiProviderRegistry.registerAsWorkerRunFn(TENSORFLOW_MEDIAPIPE, name);\n }\n\n // If no client provided, create a default in-memory queue\n if (!client) {\n const storage = new InMemoryQueueStorage<AiJobInput<TaskInput>, TaskOutput>(\n TENSORFLOW_MEDIAPIPE\n );\n await storage.setupDatabase();\n\n const server = new JobQueueServer<AiJobInput<TaskInput>, TaskOutput>(AiJob, {\n storage,\n queueName: TENSORFLOW_MEDIAPIPE,\n limiter: new ConcurrencyLimiter(1, 100),\n });\n\n client = new JobQueueClient<AiJobInput<TaskInput>, TaskOutput>({\n storage,\n queueName: TENSORFLOW_MEDIAPIPE,\n });\n\n client.attach(server);\n\n getTaskQueueRegistry().registerQueue({ server, client, storage });\n await server.start();\n }\n}\n",
|
|
15
15
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { AiJob, AiJobInput, getAiProviderRegistry } from \"@workglow/ai\";\nimport { ConcurrencyLimiter, JobQueueClient, JobQueueServer } from \"@workglow/job-queue\";\nimport { InMemoryQueueStorage } from \"@workglow/storage\";\nimport { getTaskQueueRegistry, TaskInput, TaskOutput } from \"@workglow/task-graph\";\nimport { TENSORFLOW_MEDIAPIPE } from \"../common/TFMP_Constants\";\nimport {\n TFMP_Download,\n TFMP_TextClassifier,\n TFMP_TextEmbedding,\n TFMP_TextLanguageDetection,\n TFMP_Unload,\n} from \"../common/TFMP_JobRunFns\";\n\n/**\n * Registers the TensorFlow MediaPipe inline job functions for same-thread execution.\n * If no client is provided, creates a default in-memory queue and registers it.\n *\n * @param client - Optional existing JobQueueClient. If not provided, creates a default in-memory queue.\n */\nexport async function register_TFMP_InlineJobFns(\n client?: JobQueueClient<AiJobInput<TaskInput>, TaskOutput>\n): Promise<void> {\n const aiProviderRegistry = getAiProviderRegistry();\n\n aiProviderRegistry.registerRunFn<any, any>(\n TENSORFLOW_MEDIAPIPE,\n \"DownloadModelTask\",\n TFMP_Download as any\n );\n aiProviderRegistry.registerRunFn<any, any>(\n TENSORFLOW_MEDIAPIPE,\n \"UnloadModelTask\",\n TFMP_Unload as any\n );\n aiProviderRegistry.registerRunFn<any, any>(\n TENSORFLOW_MEDIAPIPE,\n \"TextEmbeddingTask\",\n TFMP_TextEmbedding as any\n );\n aiProviderRegistry.registerRunFn<any, any>(\n TENSORFLOW_MEDIAPIPE,\n \"TextLanguageDetectionTask\",\n TFMP_TextLanguageDetection as any\n );\n aiProviderRegistry.registerRunFn<any, any>(\n TENSORFLOW_MEDIAPIPE,\n \"TextClassifierTask\",\n TFMP_TextClassifier as any\n );\n\n // If no client provided, create a default in-memory queue\n if (!client) {\n const storage = new InMemoryQueueStorage<AiJobInput<TaskInput>, TaskOutput>(\n TENSORFLOW_MEDIAPIPE\n );\n await storage.setupDatabase();\n\n const server = new JobQueueServer<AiJobInput<TaskInput>, TaskOutput>(AiJob, {\n storage,\n queueName: TENSORFLOW_MEDIAPIPE,\n limiter: new ConcurrencyLimiter(1, 100),\n });\n\n client = new JobQueueClient<AiJobInput<TaskInput>, TaskOutput>({\n storage,\n queueName: TENSORFLOW_MEDIAPIPE,\n });\n\n client.attach(server);\n\n getTaskQueueRegistry().registerQueue({ server, client, storage });\n await server.start();\n }\n}\n",
|
|
16
16
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n createServiceToken,\n globalServiceRegistry,\n parentPort,\n WORKER_SERVER,\n} from \"@workglow/util\";\nimport {\n TFMP_Download,\n TFMP_TextClassifier,\n TFMP_TextEmbedding,\n TFMP_TextLanguageDetection,\n TFMP_Unload,\n} from \"../common/TFMP_JobRunFns\";\n\n// Register the worker functions\nexport const TFMP_WORKER_JOBRUN = createServiceToken(\"worker.ai-provider.tfmp\");\n\nexport const TFMP_WORKER_JOBRUN_REGISTER = globalServiceRegistry.register(\n TFMP_WORKER_JOBRUN,\n () => {\n const workerServer = globalServiceRegistry.get(WORKER_SERVER);\n workerServer.registerFunction(\"DownloadModelTask\", TFMP_Download);\n workerServer.registerFunction(\"UnloadModelTask\", TFMP_Unload);\n workerServer.registerFunction(\"TextEmbeddingTask\", TFMP_TextEmbedding);\n workerServer.registerFunction(\"TextLanguageDetectionTask\", TFMP_TextLanguageDetection);\n workerServer.registerFunction(\"TextClassifierTask\", TFMP_TextClassifier);\n parentPort.postMessage({ type: \"ready\" });\n console.log(\"TFMP_WORKER_JOBRUN registered\");\n return workerServer;\n },\n true\n);\n"
|
|
17
17
|
],
|
|
18
|
-
"mappings": "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",
|
|
19
|
-
"debugId": "
|
|
18
|
+
"mappings": "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",
|
|
19
|
+
"debugId": "AED2FBB7924C48F164756E2164756E21",
|
|
20
20
|
"names": []
|
|
21
21
|
}
|
|
@@ -30,8 +30,8 @@ export declare const TFMP_TextLanguageDetection: AiProviderRunFn<TextLanguageDet
|
|
|
30
30
|
* This is shared between inline and worker implementations.
|
|
31
31
|
*
|
|
32
32
|
* When a model is unloaded, this function:
|
|
33
|
-
* 1. Disposes of the model
|
|
34
|
-
* 2. Decrements the reference count for the associated WASM fileset
|
|
33
|
+
* 1. Disposes of all cached model instances for the given model path
|
|
34
|
+
* 2. Decrements the reference count for the associated WASM fileset for each instance
|
|
35
35
|
* 3. If no other models are using the WASM fileset (count reaches 0), unloads the WASM
|
|
36
36
|
*/
|
|
37
37
|
export declare const TFMP_Unload: AiProviderRunFn<UnloadModelTaskExecuteInput, UnloadModelTaskExecuteOutput, TFMPModelRecord>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TFMP_JobRunFns.d.ts","sourceRoot":"","sources":["../../../src/tf-mediapipe/common/TFMP_JobRunFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EACV,eAAe,EACf,6BAA6B,EAC7B,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,EAC/B,6BAA6B,EAC7B,8BAA8B,EAC9B,qCAAqC,EACrC,sCAAsC,EACtC,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"TFMP_JobRunFns.d.ts","sourceRoot":"","sources":["../../../src/tf-mediapipe/common/TFMP_JobRunFns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EACV,eAAe,EACf,6BAA6B,EAC7B,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,EAC/B,6BAA6B,EAC7B,8BAA8B,EAC9B,qCAAqC,EACrC,sCAAsC,EACtC,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAiMrD;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,eAAe,CACzC,6BAA6B,EAC7B,8BAA8B,EAC9B,eAAe,CAyBhB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAAe,CAC9C,6BAA6B,EAC7B,8BAA8B,EAC9B,eAAe,CAchB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,eAAe,CAC/C,8BAA8B,EAC9B,+BAA+B,EAC/B,eAAe,CA2BhB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,eAAe,CACtD,qCAAqC,EACrC,sCAAsC,EACtC,eAAe,CA6BhB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,eAAe,CACvC,2BAA2B,EAC3B,4BAA4B,EAC5B,eAAe,CAgChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workglow/ai-provider",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.71",
|
|
5
5
|
"description": "AI provider integrations for Workglow, supporting OpenAI, Hugging Face Transformers, MediaPipe, and GGML models.",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"watch": "concurrently -c 'auto' 'bun:watch-*'",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@workglow/ai": "0.0.
|
|
34
|
-
"@workglow/job-queue": "0.0.
|
|
35
|
-
"@workglow/storage": "0.0.
|
|
36
|
-
"@workglow/task-graph": "0.0.
|
|
37
|
-
"@workglow/util": "0.0.
|
|
33
|
+
"@workglow/ai": "0.0.71",
|
|
34
|
+
"@workglow/job-queue": "0.0.71",
|
|
35
|
+
"@workglow/storage": "0.0.71",
|
|
36
|
+
"@workglow/task-graph": "0.0.71",
|
|
37
|
+
"@workglow/util": "0.0.71",
|
|
38
38
|
"@sroussey/transformers": "3.8.2",
|
|
39
39
|
"@mediapipe/tasks-text": "^0.10.22-rc.20250304",
|
|
40
40
|
"@mediapipe/tasks-vision": "^0.10.22-rc.20250304",
|
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
}
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@workglow/ai": "0.0.
|
|
63
|
-
"@workglow/job-queue": "0.0.
|
|
64
|
-
"@workglow/storage": "0.0.
|
|
65
|
-
"@workglow/task-graph": "0.0.
|
|
66
|
-
"@workglow/util": "0.0.
|
|
62
|
+
"@workglow/ai": "0.0.71",
|
|
63
|
+
"@workglow/job-queue": "0.0.71",
|
|
64
|
+
"@workglow/storage": "0.0.71",
|
|
65
|
+
"@workglow/task-graph": "0.0.71",
|
|
66
|
+
"@workglow/util": "0.0.71",
|
|
67
67
|
"@sroussey/transformers": "3.8.2",
|
|
68
68
|
"@mediapipe/tasks-text": "^0.10.22-rc.20250304",
|
|
69
69
|
"@mediapipe/tasks-vision": "^0.10.22-rc.20250304",
|