@workglow/huggingface-transformers 0.2.34 → 0.2.36

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.
Files changed (65) hide show
  1. package/dist/ai/HuggingFaceTransformersProvider.d.ts +9 -8
  2. package/dist/ai/HuggingFaceTransformersProvider.d.ts.map +1 -1
  3. package/dist/ai/HuggingFaceTransformersQueuedProvider.d.ts +10 -8
  4. package/dist/ai/HuggingFaceTransformersQueuedProvider.d.ts.map +1 -1
  5. package/dist/ai/common/HFT_BackgroundRemoval.d.ts.map +1 -1
  6. package/dist/ai/common/HFT_Capabilities.d.ts +28 -0
  7. package/dist/ai/common/HFT_Capabilities.d.ts.map +1 -0
  8. package/dist/ai/common/HFT_CapabilitySets.d.ts +40 -0
  9. package/dist/ai/common/HFT_CapabilitySets.d.ts.map +1 -0
  10. package/dist/ai/common/HFT_Chat.d.ts +1 -2
  11. package/dist/ai/common/HFT_Chat.d.ts.map +1 -1
  12. package/dist/ai/common/HFT_CountTokens.d.ts.map +1 -1
  13. package/dist/ai/common/HFT_Download.d.ts +7 -2
  14. package/dist/ai/common/HFT_Download.d.ts.map +1 -1
  15. package/dist/ai/common/{HFT_Unload.d.ts → HFT_DownloadRemove.d.ts} +3 -3
  16. package/dist/ai/common/HFT_DownloadRemove.d.ts.map +1 -0
  17. package/dist/ai/common/HFT_ImageClassification.d.ts.map +1 -1
  18. package/dist/ai/common/HFT_ImageEmbedding.d.ts.map +1 -1
  19. package/dist/ai/common/HFT_ImageSegmentation.d.ts.map +1 -1
  20. package/dist/ai/common/HFT_ImageToText.d.ts.map +1 -1
  21. package/dist/ai/common/HFT_JobRunFns.d.ts +9 -9
  22. package/dist/ai/common/HFT_JobRunFns.d.ts.map +1 -1
  23. package/dist/ai/common/HFT_ModelInfo.d.ts.map +1 -1
  24. package/dist/ai/common/HFT_ModelSchema.d.ts +3 -3
  25. package/dist/ai/common/HFT_ObjectDetection.d.ts.map +1 -1
  26. package/dist/ai/common/HFT_Pipeline.d.ts +30 -4
  27. package/dist/ai/common/HFT_Pipeline.d.ts.map +1 -1
  28. package/dist/ai/common/HFT_Streaming.d.ts +5 -12
  29. package/dist/ai/common/HFT_Streaming.d.ts.map +1 -1
  30. package/dist/ai/common/HFT_StructuredGeneration.d.ts +1 -2
  31. package/dist/ai/common/HFT_StructuredGeneration.d.ts.map +1 -1
  32. package/dist/ai/common/HFT_TextClassification.d.ts.map +1 -1
  33. package/dist/ai/common/HFT_TextEmbedding.d.ts +4 -0
  34. package/dist/ai/common/HFT_TextEmbedding.d.ts.map +1 -1
  35. package/dist/ai/common/HFT_TextFillMask.d.ts.map +1 -1
  36. package/dist/ai/common/HFT_TextGeneration.d.ts +1 -6
  37. package/dist/ai/common/HFT_TextGeneration.d.ts.map +1 -1
  38. package/dist/ai/common/HFT_TextLanguageDetection.d.ts.map +1 -1
  39. package/dist/ai/common/HFT_TextNamedEntityRecognition.d.ts.map +1 -1
  40. package/dist/ai/common/HFT_TextQuestionAnswer.d.ts +1 -6
  41. package/dist/ai/common/HFT_TextQuestionAnswer.d.ts.map +1 -1
  42. package/dist/ai/common/HFT_TextReranker.d.ts +42 -0
  43. package/dist/ai/common/HFT_TextReranker.d.ts.map +1 -0
  44. package/dist/ai/common/HFT_TextRewriter.d.ts +1 -6
  45. package/dist/ai/common/HFT_TextRewriter.d.ts.map +1 -1
  46. package/dist/ai/common/HFT_TextSummary.d.ts +1 -6
  47. package/dist/ai/common/HFT_TextSummary.d.ts.map +1 -1
  48. package/dist/ai/common/HFT_TextTranslation.d.ts +1 -6
  49. package/dist/ai/common/HFT_TextTranslation.d.ts.map +1 -1
  50. package/dist/ai/common/HFT_ToolCalling.d.ts +1 -2
  51. package/dist/ai/common/HFT_ToolCalling.d.ts.map +1 -1
  52. package/dist/ai/index.d.ts +53 -2
  53. package/dist/ai/index.d.ts.map +1 -1
  54. package/dist/ai/registerHuggingFaceTransformersInline.d.ts.map +1 -1
  55. package/dist/ai/registerHuggingFaceTransformersWorker.d.ts.map +1 -1
  56. package/dist/ai/runtime.d.ts +1 -0
  57. package/dist/ai/runtime.d.ts.map +1 -1
  58. package/dist/ai-runtime.d.ts.map +1 -1
  59. package/dist/ai-runtime.js +665 -858
  60. package/dist/ai-runtime.js.map +38 -36
  61. package/dist/ai.d.ts.map +1 -1
  62. package/dist/ai.js +1434 -183
  63. package/dist/ai.js.map +38 -8
  64. package/package.json +12 -13
  65. package/dist/ai/common/HFT_Unload.d.ts.map +0 -1
package/dist/ai.js CHANGED
@@ -197,14 +197,29 @@ function disposeHftSessionsForModel(modelPath) {
197
197
  }
198
198
  }
199
199
  }
200
- function clearPipelineCache() {
200
+ async function clearPipelineCache() {
201
+ const snapshot = Array.from(pipelines.values());
201
202
  pipelines.clear();
203
+ await Promise.allSettled(snapshot.map(async (pipeline) => {
204
+ try {
205
+ const model = pipeline?.model;
206
+ await model?.dispose?.();
207
+ } catch {}
208
+ }));
202
209
  }
203
210
  function hasCachedPipeline(cacheKey) {
204
211
  return pipelines.has(cacheKey);
205
212
  }
206
- function removeCachedPipeline(cacheKey) {
207
- return pipelines.delete(cacheKey);
213
+ async function removeCachedPipeline(cacheKey) {
214
+ const pipeline = pipelines.get(cacheKey);
215
+ const deleted = pipelines.delete(cacheKey);
216
+ if (pipeline) {
217
+ try {
218
+ const model = pipeline?.model;
219
+ await model?.dispose?.();
220
+ } catch {}
221
+ }
222
+ return deleted;
208
223
  }
209
224
  function isBrowserEnv() {
210
225
  if (typeof globalThis === "undefined")
@@ -221,7 +236,10 @@ function getPipelineCacheKey(model) {
221
236
  const revision = model.provider_config.revision || "main";
222
237
  return `${model.provider_config.model_path}:${model.provider_config.pipeline}:${dtype}:${device}:${revision}`;
223
238
  }
224
- async function getPipeline(model, onProgress, options = {}, signal, progressScaleMax = 10) {
239
+ async function getPipeline(model, emit, options = {}, signal, progressScaleMax = 10) {
240
+ if (signal?.aborted) {
241
+ throw signal?.reason ?? new Error("Aborted");
242
+ }
225
243
  const cacheKey = getPipelineCacheKey(model);
226
244
  if (pipelines.has(cacheKey)) {
227
245
  getLogger().debug("HFT pipeline cache hit", { cacheKey });
@@ -236,28 +254,18 @@ async function getPipeline(model, onProgress, options = {}, signal, progressScal
236
254
  if (cached)
237
255
  return cached;
238
256
  }
239
- const loadPromise = doGetPipeline(model, onProgress, options, progressScaleMax, cacheKey, signal).finally(() => {
257
+ const loadPromise = doGetPipeline(model, emit, options, progressScaleMax, cacheKey, signal).finally(() => {
240
258
  pipelineLoadPromises.delete(cacheKey);
241
259
  });
242
260
  pipelineLoadPromises.set(cacheKey, loadPromise);
243
261
  return loadPromise;
244
262
  }
245
- var _transformersSdk, _cacheDir, _loadPromise, modelAbortControllers, pipelines, hftSessions, pipelineLoadPromises, IMAGE_PIPELINE_TYPES, HFT_NULL_PROCESSOR_PREFIX = "HFT_NULL_PROCESSOR:", doGetPipeline = async (model, onProgress, options, progressScaleMax, cacheKey, signal) => {
263
+ var _transformersSdk, _cacheDir, _loadPromise, modelAbortControllers, pipelines, hftSessions, pipelineLoadPromises, IMAGE_PIPELINE_TYPES, HFT_NULL_PROCESSOR_PREFIX = "HFT_NULL_PROCESSOR:", doGetPipeline = async (model, emit, options, progressScaleMax, cacheKey, signal) => {
246
264
  let lastProgressTime = 0;
247
265
  let pendingProgress = null;
248
266
  let throttleTimer = null;
249
267
  const THROTTLE_MS = 160;
250
- const buildProgressDetails = (file, fileProgress, filesMap) => {
251
- const details = {
252
- file,
253
- progress: fileProgress
254
- };
255
- if (filesMap && Object.keys(filesMap).length > 0) {
256
- details.files = filesMap;
257
- }
258
- return details;
259
- };
260
- const sendProgress = (progress, file, fileProgress, filesMap) => {
268
+ const sendProgress = (progress) => {
261
269
  const now = Date.now();
262
270
  const timeSinceLastEvent = now - lastProgressTime;
263
271
  const isFirst = lastProgressTime === 0;
@@ -268,19 +276,22 @@ var _transformersSdk, _cacheDir, _loadPromise, modelAbortControllers, pipelines,
268
276
  throttleTimer = null;
269
277
  }
270
278
  pendingProgress = null;
271
- onProgress(Math.round(progress), "Downloading model", buildProgressDetails(file, fileProgress, filesMap));
279
+ emit({ type: "phase", message: "Downloading model", progress: Math.round(progress) });
272
280
  lastProgressTime = now;
273
281
  return;
274
282
  }
275
283
  if (timeSinceLastEvent < THROTTLE_MS) {
276
- pendingProgress = { progress, file, fileProgress, filesMap };
284
+ pendingProgress = progress;
277
285
  if (!throttleTimer) {
278
286
  const timeRemaining = Math.max(1, THROTTLE_MS - timeSinceLastEvent);
279
287
  throttleTimer = setTimeout(() => {
280
288
  throttleTimer = null;
281
- if (pendingProgress) {
282
- const p = pendingProgress;
283
- onProgress(Math.round(p.progress), "Downloading model", buildProgressDetails(p.file, p.fileProgress, p.filesMap));
289
+ if (pendingProgress !== null) {
290
+ emit({
291
+ type: "phase",
292
+ message: "Downloading model",
293
+ progress: Math.round(pendingProgress)
294
+ });
284
295
  lastProgressTime = Date.now();
285
296
  pendingProgress = null;
286
297
  }
@@ -288,7 +299,7 @@ var _transformersSdk, _cacheDir, _loadPromise, modelAbortControllers, pipelines,
288
299
  }
289
300
  return;
290
301
  }
291
- onProgress(Math.round(progress), "Downloading model", buildProgressDetails(file, fileProgress, filesMap));
302
+ emit({ type: "phase", message: "Downloading model", progress: Math.round(progress) });
292
303
  lastProgressTime = now;
293
304
  pendingProgress = null;
294
305
  };
@@ -307,28 +318,8 @@ var _transformersSdk, _cacheDir, _loadPromise, modelAbortControllers, pipelines,
307
318
  if (abortSignal?.aborted)
308
319
  return;
309
320
  if (status.status === "progress_total") {
310
- const totalStatus = status;
311
- const scaledProgress = totalStatus.progress * progressScaleMax / 100;
312
- let activeFile = "";
313
- let activeFileProgress = 0;
314
- const files = totalStatus.files;
315
- if (files) {
316
- for (const [file, info] of Object.entries(files)) {
317
- if (info.loaded < info.total) {
318
- activeFile = file;
319
- activeFileProgress = info.total > 0 ? info.loaded / info.total * 100 : 0;
320
- break;
321
- }
322
- }
323
- if (!activeFile) {
324
- const fileNames = Object.keys(files);
325
- if (fileNames.length > 0) {
326
- activeFile = fileNames[fileNames.length - 1];
327
- activeFileProgress = 100;
328
- }
329
- }
330
- }
331
- sendProgress(scaledProgress, activeFile, activeFileProgress, files);
321
+ const scaledProgress = status.progress * progressScaleMax / 100;
322
+ sendProgress(scaledProgress);
332
323
  }
333
324
  };
334
325
  let device = model.provider_config.device;
@@ -371,9 +362,12 @@ var _transformersSdk, _cacheDir, _loadPromise, modelAbortControllers, pipelines,
371
362
  clearTimeout(throttleTimer);
372
363
  throttleTimer = null;
373
364
  }
374
- const finalPending = pendingProgress;
375
- if (finalPending) {
376
- onProgress(Math.round(finalPending.progress), "Downloading model", buildProgressDetails(finalPending.file, finalPending.fileProgress, finalPending.filesMap));
365
+ if (pendingProgress !== null) {
366
+ emit({
367
+ type: "phase",
368
+ message: "Downloading model",
369
+ progress: Math.round(pendingProgress)
370
+ });
377
371
  pendingProgress = null;
378
372
  }
379
373
  if (abortSignal?.aborted) {
@@ -475,7 +469,6 @@ var PipelineUseCase = {
475
469
  ...AudioPipelineUseCase,
476
470
  ...MultimodalPipelineUseCase
477
471
  };
478
-
479
472
  // src/ai/common/HFT_ModelSchema.ts
480
473
  import { ModelConfigSchema, ModelRecordSchema } from "@workglow/ai/worker";
481
474
  var HfTransformersOnnxModelSchema = {
@@ -599,138 +592,6 @@ var HfTransformersOnnxModelConfigSchema = {
599
592
  required: [...ModelConfigSchema.required, ...HfTransformersOnnxModelSchema.required],
600
593
  additionalProperties: false
601
594
  };
602
-
603
- // src/ai/HuggingFaceTransformersProvider.ts
604
- import { AiProvider } from "@workglow/ai/worker";
605
- init_HFT_Pipeline();
606
-
607
- class HuggingFaceTransformersProvider extends AiProvider {
608
- name = HF_TRANSFORMERS_ONNX;
609
- displayName = "Hugging Face Transformers (ONNX)";
610
- isLocal = true;
611
- supportsBrowser = true;
612
- taskTypes = [
613
- "AiChatTask",
614
- "DownloadModelTask",
615
- "UnloadModelTask",
616
- "ModelInfoTask",
617
- "CountTokensTask",
618
- "TextEmbeddingTask",
619
- "TextGenerationTask",
620
- "TextQuestionAnswerTask",
621
- "TextLanguageDetectionTask",
622
- "TextClassificationTask",
623
- "TextFillMaskTask",
624
- "TextNamedEntityRecognitionTask",
625
- "TextRewriterTask",
626
- "TextSummaryTask",
627
- "TextTranslationTask",
628
- "ImageSegmentationTask",
629
- "ImageToTextTask",
630
- "BackgroundRemovalTask",
631
- "ImageEmbeddingTask",
632
- "ImageClassificationTask",
633
- "ObjectDetectionTask",
634
- "ToolCallingTask",
635
- "StructuredGenerationTask",
636
- "ModelSearchTask"
637
- ];
638
- constructor(tasks, streamTasks, previewTasks) {
639
- super(tasks, streamTasks, previewTasks);
640
- }
641
- createSession(_model) {
642
- return crypto.randomUUID();
643
- }
644
- async disposeSession(sessionId) {
645
- deleteHftSession(sessionId);
646
- }
647
- }
648
-
649
- // src/ai/HuggingFaceTransformersQueuedProvider.ts
650
- import { QueuedAiProvider } from "@workglow/ai";
651
- init_HFT_Pipeline();
652
- var GPU_DEVICES = new Set(["webgpu", "gpu", "metal"]);
653
- var HFT_CPU_QUEUE_CONCURRENCY_PRODUCTION = 4;
654
- function hftIsAutomatedTestEnvironment() {
655
- if (typeof process === "undefined") {
656
- return false;
657
- }
658
- const e = process.env;
659
- return e.VITEST === "true" || e.NODE_ENV === "test" || e.BUN_TEST === "1" || e.JEST_WORKER_ID !== undefined;
660
- }
661
- function hftDefaultCpuQueueConcurrency() {
662
- return hftIsAutomatedTestEnvironment() ? 1 : HFT_CPU_QUEUE_CONCURRENCY_PRODUCTION;
663
- }
664
- function resolveHftCpuQueueConcurrency(concurrency, defaultCpu) {
665
- if (concurrency === undefined) {
666
- return defaultCpu();
667
- }
668
- if (typeof concurrency === "number") {
669
- return defaultCpu();
670
- }
671
- return concurrency.cpu ?? defaultCpu();
672
- }
673
-
674
- class HuggingFaceTransformersQueuedProvider extends QueuedAiProvider {
675
- name = HF_TRANSFORMERS_ONNX;
676
- displayName = "Hugging Face Transformers (ONNX)";
677
- isLocal = true;
678
- supportsBrowser = true;
679
- cpuStrategy;
680
- taskTypes = [
681
- "AiChatTask",
682
- "DownloadModelTask",
683
- "UnloadModelTask",
684
- "ModelInfoTask",
685
- "CountTokensTask",
686
- "TextEmbeddingTask",
687
- "TextGenerationTask",
688
- "TextQuestionAnswerTask",
689
- "TextLanguageDetectionTask",
690
- "TextClassificationTask",
691
- "TextFillMaskTask",
692
- "TextNamedEntityRecognitionTask",
693
- "TextRewriterTask",
694
- "TextSummaryTask",
695
- "TextTranslationTask",
696
- "ImageSegmentationTask",
697
- "ImageToTextTask",
698
- "BackgroundRemovalTask",
699
- "ImageEmbeddingTask",
700
- "ImageClassificationTask",
701
- "ObjectDetectionTask",
702
- "ToolCallingTask",
703
- "StructuredGenerationTask",
704
- "ModelSearchTask"
705
- ];
706
- constructor(tasks, streamTasks, previewTasks) {
707
- super(tasks, streamTasks, previewTasks);
708
- }
709
- createSession(_model) {
710
- return crypto.randomUUID();
711
- }
712
- async disposeSession(sessionId) {
713
- deleteHftSession(sessionId);
714
- }
715
- async afterRegister(options) {
716
- await super.afterRegister(options);
717
- this.cpuStrategy = this.createQueuedStrategy(HF_TRANSFORMERS_ONNX_CPU, resolveHftCpuQueueConcurrency(options.queue?.concurrency, hftDefaultCpuQueueConcurrency), options);
718
- }
719
- getStrategyForModel(model) {
720
- const device = model.provider_config?.device;
721
- if (device && GPU_DEVICES.has(device)) {
722
- return this.queuedStrategy;
723
- }
724
- return this.cpuStrategy;
725
- }
726
- }
727
-
728
- // src/ai/registerHuggingFaceTransformers.ts
729
- import { registerProviderWithWorker } from "@workglow/ai/provider-utils";
730
- async function registerHuggingFaceTransformers(options) {
731
- await registerProviderWithWorker(new HuggingFaceTransformersQueuedProvider, "HuggingFaceTransformers", options);
732
- }
733
-
734
595
  // src/ai/common/HFT_OnnxDtypes.ts
735
596
  var ONNX_QUANTIZATION_SUFFIX_MAPPING = {
736
597
  fp32: "",
@@ -792,7 +653,6 @@ function parseOnnxQuantizations(params) {
792
653
  return set !== undefined && set.size === allBaseNames.size;
793
654
  });
794
655
  }
795
-
796
656
  // src/ai/common/HFT_ToolMarkup.ts
797
657
  function createToolCallMarkupFilter(emit) {
798
658
  const OPEN_TAG = "<tool_call>";
@@ -858,10 +718,1401 @@ function createToolCallMarkupFilter(emit) {
858
718
  }
859
719
  return { feed, flush };
860
720
  }
721
+ // src/ai/HuggingFaceTransformersProvider.ts
722
+ import { AiProvider } from "@workglow/ai/worker";
723
+
724
+ // src/ai/common/HFT_CapabilitySets.ts
725
+ var HFT_TEXT_GENERATION = ["text.generation"];
726
+ var HFT_TOOL_USE = ["text.generation", "tool-use"];
727
+ var HFT_JSON_MODE = ["text.generation", "json-mode"];
728
+ var HFT_TEXT_REWRITER = ["text.rewriter"];
729
+ var HFT_TEXT_SUMMARY = ["text.summary"];
730
+ var HFT_TEXT_TRANSLATION = ["text.translation"];
731
+ var HFT_TEXT_QUESTION_ANSWERING = [
732
+ "text.question-answering"
733
+ ];
734
+ var HFT_TEXT_EMBEDDING = ["text.embedding"];
735
+ var HFT_TEXT_CLASSIFICATION = ["text.classification"];
736
+ var HFT_TEXT_LANGUAGE_DETECTION = [
737
+ "text.language-detection"
738
+ ];
739
+ var HFT_TEXT_RERANKING = ["text.reranking"];
740
+ var HFT_TEXT_FILL_MASK = ["text.fill-mask"];
741
+ var HFT_TEXT_NER = ["text.ner"];
742
+ var HFT_IMAGE_CLASSIFICATION = ["image.classification"];
743
+ var HFT_IMAGE_EMBEDDING = ["image.embedding"];
744
+ var HFT_IMAGE_SEGMENTATION = ["image.segmentation"];
745
+ var HFT_IMAGE_TO_TEXT = ["image.to-text"];
746
+ var HFT_IMAGE_BACKGROUND_REMOVAL = [
747
+ "image.background-removal"
748
+ ];
749
+ var HFT_IMAGE_OBJECT_DETECTION = [
750
+ "image.object-detection"
751
+ ];
752
+ var HFT_COUNT_TOKENS = ["model.count-tokens"];
753
+ var HFT_MODEL_DOWNLOAD_REMOVE = ["model.download-remove"];
754
+ var HFT_MODEL_DOWNLOAD = ["model.download"];
755
+ var HFT_MODEL_SEARCH = ["model.search"];
756
+ var HFT_MODEL_INFO = ["model.info"];
757
+ var HFT_CAPABILITY_SETS = [
758
+ HFT_TEXT_GENERATION,
759
+ HFT_TOOL_USE,
760
+ HFT_JSON_MODE,
761
+ HFT_TEXT_REWRITER,
762
+ HFT_TEXT_SUMMARY,
763
+ HFT_TEXT_TRANSLATION,
764
+ HFT_TEXT_QUESTION_ANSWERING,
765
+ HFT_TEXT_EMBEDDING,
766
+ HFT_TEXT_CLASSIFICATION,
767
+ HFT_TEXT_LANGUAGE_DETECTION,
768
+ HFT_TEXT_RERANKING,
769
+ HFT_TEXT_FILL_MASK,
770
+ HFT_TEXT_NER,
771
+ HFT_IMAGE_CLASSIFICATION,
772
+ HFT_IMAGE_EMBEDDING,
773
+ HFT_IMAGE_SEGMENTATION,
774
+ HFT_IMAGE_TO_TEXT,
775
+ HFT_IMAGE_BACKGROUND_REMOVAL,
776
+ HFT_IMAGE_OBJECT_DETECTION,
777
+ HFT_COUNT_TOKENS,
778
+ HFT_MODEL_DOWNLOAD_REMOVE,
779
+ HFT_MODEL_DOWNLOAD,
780
+ HFT_MODEL_SEARCH,
781
+ HFT_MODEL_INFO
782
+ ];
783
+
784
+ // src/ai/common/HFT_Capabilities.ts
785
+ var HFT_RUN_FN_SPECS = HFT_CAPABILITY_SETS.map((serves) => ({ serves }));
786
+ function hftWorkerRunFnSpecs() {
787
+ return HFT_RUN_FN_SPECS;
788
+ }
789
+ function inferHftCapabilities(model) {
790
+ const declared = model.capabilities ?? [];
791
+ if (declared.length > 0)
792
+ return declared;
793
+ const id = String(model.model_id ?? model.provider_config?.model_path ?? model.provider_config?.model_name ?? "");
794
+ const pipelineTask = model.provider_config?.pipeline_task ?? "";
795
+ switch (pipelineTask) {
796
+ case "text-generation":
797
+ return [
798
+ "text.generation",
799
+ "text.rewriter",
800
+ "text.summary",
801
+ "tool-use",
802
+ "model.count-tokens",
803
+ "model.download-remove",
804
+ "model.info",
805
+ "model.search"
806
+ ];
807
+ case "feature-extraction":
808
+ case "sentence-similarity":
809
+ return ["text.embedding", "model.download-remove", "model.info", "model.search"];
810
+ case "text-classification":
811
+ return ["text.classification", "model.download-remove", "model.info", "model.search"];
812
+ case "token-classification":
813
+ return ["text.ner", "model.download-remove", "model.info", "model.search"];
814
+ case "fill-mask":
815
+ return ["text.fill-mask", "model.download-remove", "model.info", "model.search"];
816
+ case "translation":
817
+ return ["text.translation", "model.download-remove", "model.info", "model.search"];
818
+ case "summarization":
819
+ return ["text.summary", "model.download-remove", "model.info", "model.search"];
820
+ case "question-answering":
821
+ return ["text.question-answering", "model.download-remove", "model.info", "model.search"];
822
+ case "image-classification":
823
+ return ["image.classification", "model.download-remove", "model.info", "model.search"];
824
+ case "image-segmentation":
825
+ return ["image.segmentation", "model.download-remove", "model.info", "model.search"];
826
+ case "image-to-text":
827
+ return ["image.to-text", "model.download-remove", "model.info", "model.search"];
828
+ case "object-detection":
829
+ return ["image.object-detection", "model.download-remove", "model.info", "model.search"];
830
+ case "zero-shot-image-classification":
831
+ return [
832
+ "image.classification",
833
+ "image.embedding",
834
+ "model.download-remove",
835
+ "model.info",
836
+ "model.search"
837
+ ];
838
+ }
839
+ const baseName = id.split("/").pop() ?? id;
840
+ if (/embed|minilm|bge-|gte-|e5-/i.test(baseName)) {
841
+ return ["text.embedding", "model.download-remove", "model.info", "model.search"];
842
+ }
843
+ if (/clip|siglip/i.test(baseName)) {
844
+ return [
845
+ "image.classification",
846
+ "image.embedding",
847
+ "model.download-remove",
848
+ "model.info",
849
+ "model.search"
850
+ ];
851
+ }
852
+ if (/yolo|detr|owl/i.test(baseName)) {
853
+ return ["image.object-detection", "model.download-remove", "model.info", "model.search"];
854
+ }
855
+ if (/sam|segformer|mask/i.test(baseName)) {
856
+ return ["image.segmentation", "model.download-remove", "model.info", "model.search"];
857
+ }
858
+ if (/blip|llava|vision/i.test(baseName)) {
859
+ return ["image.to-text", "model.download-remove", "model.info", "model.search"];
860
+ }
861
+ if (/llama|mistral|gemma|phi|qwen|tinyllama|smollm/i.test(baseName)) {
862
+ return [
863
+ "text.generation",
864
+ "text.rewriter",
865
+ "text.summary",
866
+ "tool-use",
867
+ "model.count-tokens",
868
+ "model.download-remove",
869
+ "model.info",
870
+ "model.search"
871
+ ];
872
+ }
873
+ return ["model.search", "model.info"];
874
+ }
875
+
876
+ // src/ai/HuggingFaceTransformersProvider.ts
877
+ init_HFT_Pipeline();
878
+
879
+ class HuggingFaceTransformersProvider extends AiProvider {
880
+ name = HF_TRANSFORMERS_ONNX;
881
+ displayName = "Hugging Face Transformers (ONNX)";
882
+ isLocal = true;
883
+ supportsBrowser = true;
884
+ constructor(promiseRunFns, previewTasks) {
885
+ super(promiseRunFns, previewTasks);
886
+ }
887
+ inferCapabilities(model) {
888
+ return inferHftCapabilities(model);
889
+ }
890
+ workerRunFnSpecs() {
891
+ return hftWorkerRunFnSpecs();
892
+ }
893
+ createSession(_model) {
894
+ return crypto.randomUUID();
895
+ }
896
+ async disposeSession(sessionId) {
897
+ deleteHftSession(sessionId);
898
+ }
899
+ }
900
+ // src/ai/HuggingFaceTransformersQueuedProvider.ts
901
+ import { QueuedAiProvider } from "@workglow/ai";
902
+ init_HFT_Pipeline();
903
+ var GPU_DEVICES = new Set(["webgpu", "gpu", "metal"]);
904
+ var HFT_CPU_QUEUE_CONCURRENCY_PRODUCTION = 4;
905
+ function hftIsAutomatedTestEnvironment() {
906
+ if (typeof process === "undefined") {
907
+ return false;
908
+ }
909
+ const e = process.env;
910
+ return e.VITEST === "true" || e.NODE_ENV === "test" || e.BUN_TEST === "1" || e.JEST_WORKER_ID !== undefined;
911
+ }
912
+ function hftDefaultCpuQueueConcurrency() {
913
+ return hftIsAutomatedTestEnvironment() ? 1 : HFT_CPU_QUEUE_CONCURRENCY_PRODUCTION;
914
+ }
915
+ function resolveHftCpuQueueConcurrency(concurrency, defaultCpu) {
916
+ if (concurrency === undefined) {
917
+ return defaultCpu();
918
+ }
919
+ if (typeof concurrency === "number") {
920
+ return defaultCpu();
921
+ }
922
+ return concurrency.cpu ?? defaultCpu();
923
+ }
924
+
925
+ class HuggingFaceTransformersQueuedProvider extends QueuedAiProvider {
926
+ name = HF_TRANSFORMERS_ONNX;
927
+ displayName = "Hugging Face Transformers (ONNX)";
928
+ isLocal = true;
929
+ supportsBrowser = true;
930
+ cpuStrategy;
931
+ constructor(promiseRunFns, previewTasks) {
932
+ super(promiseRunFns, previewTasks);
933
+ }
934
+ inferCapabilities(model) {
935
+ return inferHftCapabilities(model);
936
+ }
937
+ workerRunFnSpecs() {
938
+ return hftWorkerRunFnSpecs();
939
+ }
940
+ createSession(_model) {
941
+ return crypto.randomUUID();
942
+ }
943
+ async disposeSession(sessionId) {
944
+ deleteHftSession(sessionId);
945
+ }
946
+ async afterRegister(options) {
947
+ await super.afterRegister(options);
948
+ this.cpuStrategy = this.createQueuedStrategy(HF_TRANSFORMERS_ONNX_CPU, resolveHftCpuQueueConcurrency(options.queue?.concurrency, hftDefaultCpuQueueConcurrency), options);
949
+ }
950
+ getStrategyForModel(model) {
951
+ const device = model.provider_config?.device;
952
+ if (device && GPU_DEVICES.has(device)) {
953
+ return this.queuedStrategy;
954
+ }
955
+ return this.cpuStrategy;
956
+ }
957
+ }
958
+ // src/ai/registerHuggingFaceTransformers.ts
959
+ import { registerProviderWithWorker } from "@workglow/ai/provider-utils";
960
+ async function registerHuggingFaceTransformers(options) {
961
+ await registerProviderWithWorker(new HuggingFaceTransformersQueuedProvider, "HuggingFaceTransformers", options);
962
+ }
963
+ // src/ai/common/HFT_BackgroundRemoval.ts
964
+ init_HFT_Pipeline();
965
+ import { dataUriToImageValue, imageValueToBlob } from "@workglow/ai/provider-utils";
966
+ function rawImageToBase64Png(image) {
967
+ const fn = image.toBase64;
968
+ if (typeof fn !== "function") {
969
+ throw new Error("HFT_BackgroundRemoval: RawImage.toBase64 unavailable in this transformers version");
970
+ }
971
+ return fn.call(image);
972
+ }
973
+ var HFT_BackgroundRemoval = async (input, model, signal, emit) => {
974
+ const remover = await getPipeline(model, emit, {}, signal);
975
+ const imageArg = await imageValueToBlob(input.image);
976
+ const result = await remover(imageArg);
977
+ const resultImage = Array.isArray(result) ? result[0] : result;
978
+ const dataUri = `data:image/png;base64,${rawImageToBase64Png(resultImage)}`;
979
+ emit({
980
+ type: "finish",
981
+ data: {
982
+ image: await dataUriToImageValue(dataUri)
983
+ }
984
+ });
985
+ };
986
+
987
+ // src/ai/common/HFT_Chat.ts
988
+ init_HFT_Pipeline();
989
+
990
+ // src/ai/common/HFT_ToolCalling.ts
991
+ init_HFT_Pipeline();
992
+ import {
993
+ buildToolDescription,
994
+ filterValidToolCalls,
995
+ toTextFlatMessages
996
+ } from "@workglow/ai/worker";
997
+ import {
998
+ adaptParserResult,
999
+ forcedToolSelection,
1000
+ getAvailableParsers,
1001
+ getGenerationPrefix,
1002
+ parseToolCalls
1003
+ } from "@workglow/ai/provider-utils";
1004
+
1005
+ // src/ai/common/HFT_Streaming.ts
1006
+ function createStreamingTextStreamer(tokenizer, onText, textStreamer) {
1007
+ return new textStreamer(tokenizer, {
1008
+ skip_prompt: true,
1009
+ decode_kwargs: { skip_special_tokens: true },
1010
+ callback_function: onText
1011
+ });
1012
+ }
1013
+ function createTextStreamer(tokenizer, updateProgress, textStreamer) {
1014
+ let count = 0;
1015
+ return new textStreamer(tokenizer, {
1016
+ skip_prompt: true,
1017
+ decode_kwargs: { skip_special_tokens: true },
1018
+ callback_function: (text) => {
1019
+ count++;
1020
+ const result = 100 * (1 - Math.exp(-0.05 * count));
1021
+ const progress = Math.round(Math.min(result, 100));
1022
+ updateProgress(progress, "Generating", { text, progress });
1023
+ }
1024
+ });
1025
+ }
1026
+
1027
+ // src/ai/common/HFT_ToolCalling.ts
1028
+ function getModelTextCandidates(model) {
1029
+ return [model.model_id, model.title, model.description, model.provider_config.model_path].filter((value) => typeof value === "string" && value.length > 0).map((value) => value.toLowerCase());
1030
+ }
1031
+ function detectModelFamilyFromConfig(model) {
1032
+ const candidates = getModelTextCandidates(model);
1033
+ const families = getAvailableParsers();
1034
+ for (const candidate of candidates) {
1035
+ for (const family of families) {
1036
+ if (candidate.includes(family)) {
1037
+ return family;
1038
+ }
1039
+ }
1040
+ }
1041
+ return null;
1042
+ }
1043
+ function normalizeParsedToolCalls(input, toolCalls) {
1044
+ const forcedToolName = forcedToolSelection(input);
1045
+ return toolCalls.map((toolCall) => toolCall.name ? toolCall : {
1046
+ ...toolCall,
1047
+ name: forcedToolName ?? toolCall.name
1048
+ });
1049
+ }
1050
+ function mapHFTTools(tools) {
1051
+ return tools.map((t) => ({
1052
+ type: "function",
1053
+ function: {
1054
+ name: t.name,
1055
+ description: buildToolDescription(t),
1056
+ parameters: t.inputSchema
1057
+ }
1058
+ }));
1059
+ }
1060
+ function resolveHFTToolsAndMessages(input, messages) {
1061
+ if (input.toolChoice === "none") {
1062
+ return;
1063
+ }
1064
+ if (input.toolChoice === "required") {
1065
+ const requiredInstruction = "You must call at least one tool from the provided tool list when answering.";
1066
+ if (messages.length > 0 && messages[0].role === "system") {
1067
+ messages[0] = { ...messages[0], content: `${messages[0].content}
1068
+
1069
+ ${requiredInstruction}` };
1070
+ } else {
1071
+ messages.unshift({ role: "system", content: requiredInstruction });
1072
+ }
1073
+ return mapHFTTools(input.tools);
1074
+ }
1075
+ if (typeof input.toolChoice === "string" && input.toolChoice !== "auto") {
1076
+ const selectedTools = input.tools?.filter((tool) => tool.name === input.toolChoice);
1077
+ const toolsToMap = selectedTools && selectedTools.length > 0 ? selectedTools : input.tools;
1078
+ return mapHFTTools(toolsToMap);
1079
+ }
1080
+ return mapHFTTools(input.tools);
1081
+ }
1082
+ function buildHFTMessages(messages, systemPrompt, prompt, toolChoice) {
1083
+ const out = [];
1084
+ if (systemPrompt) {
1085
+ out.push({ role: "system", content: systemPrompt });
1086
+ }
1087
+ if (toolChoice === "required") {
1088
+ out.push({
1089
+ role: "system",
1090
+ content: "You MUST call one of the provided tools in this turn."
1091
+ });
1092
+ }
1093
+ if (!messages || messages.length === 0) {
1094
+ out.push({ role: "user", content: extractPromptText(prompt) });
1095
+ return out;
1096
+ }
1097
+ for (const msg of messages) {
1098
+ if (msg.role === "user") {
1099
+ const text = msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
1100
+ out.push({ role: "user", content: text });
1101
+ } else if (msg.role === "assistant") {
1102
+ const text = msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
1103
+ const toolCalls = msg.content.filter((b) => b.type === "tool_use").map((b) => {
1104
+ const tu = b;
1105
+ return { id: tu.id, name: tu.name, arguments: tu.input };
1106
+ });
1107
+ const entry = { role: "assistant", content: text };
1108
+ if (toolCalls.length > 0)
1109
+ entry.tool_calls = toolCalls;
1110
+ out.push(entry);
1111
+ } else if (msg.role === "tool") {
1112
+ for (const b of msg.content) {
1113
+ if (b.type !== "tool_result")
1114
+ continue;
1115
+ const text = b.content.filter((inner) => inner.type === "text").map((inner) => inner.text).join("");
1116
+ out.push({
1117
+ role: "tool",
1118
+ content: text,
1119
+ tool_call_id: b.tool_use_id
1120
+ });
1121
+ }
1122
+ }
1123
+ }
1124
+ return out;
1125
+ }
1126
+ function extractPromptText(prompt) {
1127
+ if (typeof prompt === "string")
1128
+ return prompt;
1129
+ if (!Array.isArray(prompt))
1130
+ return String(prompt ?? "");
1131
+ return prompt.map((item) => {
1132
+ if (typeof item === "string")
1133
+ return item;
1134
+ if (item && typeof item === "object" && item.type === "text") {
1135
+ return item.text;
1136
+ }
1137
+ return "";
1138
+ }).filter((s) => s).join(`
1139
+ `);
1140
+ }
1141
+ function selectHFTTools(input) {
1142
+ if (input.toolChoice === "none")
1143
+ return;
1144
+ if (typeof input.toolChoice === "string" && input.toolChoice !== "auto" && input.toolChoice !== "required") {
1145
+ const selected = input.tools.filter((t) => t.name === input.toolChoice);
1146
+ return mapHFTTools(selected.length > 0 ? selected : input.tools);
1147
+ }
1148
+ return mapHFTTools(input.tools);
1149
+ }
1150
+ function hasToolMessages(input) {
1151
+ return input.messages?.some((m) => m.role === "tool") ?? false;
1152
+ }
1153
+ function buildPromptAndPrefix(tokenizer, input, modelFamily) {
1154
+ let basePrompt;
1155
+ if (hasToolMessages(input)) {
1156
+ const messages = buildHFTMessages(input.messages, input.systemPrompt, input.prompt, input.toolChoice);
1157
+ const tools = selectHFTTools(input);
1158
+ basePrompt = tokenizer.apply_chat_template(messages, {
1159
+ tools,
1160
+ tokenize: false,
1161
+ add_generation_prompt: true
1162
+ });
1163
+ } else {
1164
+ const messages = toTextFlatMessages(input);
1165
+ const tools = resolveHFTToolsAndMessages(input, messages);
1166
+ basePrompt = tokenizer.apply_chat_template(messages, {
1167
+ tools,
1168
+ tokenize: false,
1169
+ add_generation_prompt: true
1170
+ });
1171
+ }
1172
+ const responsePrefix = input.toolChoice === "none" || hasToolMessages(input) ? undefined : getGenerationPrefix(modelFamily, forcedToolSelection(input));
1173
+ return {
1174
+ prompt: responsePrefix ? `${basePrompt}${responsePrefix}` : basePrompt,
1175
+ responsePrefix
1176
+ };
1177
+ }
1178
+ var HFT_ToolCalling = async (input, model, signal, emit, _outputSchema, sessionId) => {
1179
+ const generateText = await getPipeline(model, emit, {}, signal);
1180
+ const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
1181
+ const modelFamily = detectModelFamilyFromConfig(model);
1182
+ const { prompt, responsePrefix } = buildPromptAndPrefix(generateText.tokenizer, input, modelFamily);
1183
+ let fullText = "";
1184
+ const filter = createToolCallMarkupFilter((text) => {
1185
+ emit({ type: "text-delta", port: "text", textDelta: text });
1186
+ });
1187
+ const streamer = createStreamingTextStreamer(generateText.tokenizer, (text) => {
1188
+ fullText += text;
1189
+ filter.feed(text);
1190
+ }, TextStreamer);
1191
+ const stopping_criteria = new InterruptableStoppingCriteria;
1192
+ if (signal) {
1193
+ signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
1194
+ }
1195
+ const modelPath = model.provider_config.model_path;
1196
+ let session = sessionId ? getHftSession(sessionId) : undefined;
1197
+ let past_key_values = undefined;
1198
+ if (sessionId && !session) {
1199
+ const { DynamicCache } = await loadTransformersSDK();
1200
+ const hfModel = generateText.model;
1201
+ const hfTokenizer = generateText.tokenizer;
1202
+ const cache = new DynamicCache;
1203
+ const tokenized = hfTokenizer(prompt);
1204
+ await hfModel.generate({
1205
+ ...tokenized,
1206
+ max_new_tokens: 0,
1207
+ past_key_values: cache
1208
+ });
1209
+ const baseEntries = {};
1210
+ for (const key of Object.keys(cache)) {
1211
+ baseEntries[key] = cache[key];
1212
+ }
1213
+ const newSession = {
1214
+ mode: "prefix-rewind",
1215
+ baseEntries,
1216
+ baseSeqLength: cache.get_seq_length(),
1217
+ modelPath
1218
+ };
1219
+ setHftSession(sessionId, newSession);
1220
+ session = newSession;
1221
+ }
1222
+ if (session?.mode === "prefix-rewind") {
1223
+ const { DynamicCache } = await loadTransformersSDK();
1224
+ past_key_values = new DynamicCache(session.baseEntries);
1225
+ }
1226
+ try {
1227
+ await generateText(prompt, {
1228
+ max_new_tokens: input.maxTokens ?? 1024,
1229
+ temperature: input.temperature ?? undefined,
1230
+ return_full_text: false,
1231
+ streamer,
1232
+ stopping_criteria: [stopping_criteria],
1233
+ ...past_key_values ? { past_key_values } : {}
1234
+ });
1235
+ } finally {
1236
+ filter.flush();
1237
+ }
1238
+ const parseableFullText = responsePrefix ? `${responsePrefix}${fullText}` : fullText;
1239
+ const { text: cleanedText, toolCalls } = adaptParserResult(parseToolCalls(parseableFullText, { parser: modelFamily }));
1240
+ const validToolCalls = filterValidToolCalls(normalizeParsedToolCalls(input, toolCalls), input.tools);
1241
+ if (validToolCalls.length > 0) {
1242
+ emit({ type: "object-delta", port: "toolCalls", objectDelta: [...validToolCalls] });
1243
+ }
1244
+ emit({
1245
+ type: "finish",
1246
+ data: { text: cleanedText, toolCalls: validToolCalls }
1247
+ });
1248
+ };
1249
+
1250
+ // src/ai/common/HFT_Chat.ts
1251
+ async function generateTurn(input, model, sessionId, emit, signal, onDelta) {
1252
+ const generateText = await getPipeline(model, emit, {}, signal);
1253
+ const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
1254
+ const hfTokenizer = generateText.tokenizer;
1255
+ const hfModel = generateText.model;
1256
+ const stopping_criteria = new InterruptableStoppingCriteria;
1257
+ if (signal) {
1258
+ signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
1259
+ }
1260
+ const messages = buildHFTMessages(input.messages, input.systemPrompt, input.prompt, undefined);
1261
+ const prompt = hfTokenizer.apply_chat_template(messages, {
1262
+ tokenize: false,
1263
+ add_generation_prompt: true
1264
+ });
1265
+ const inputs = hfTokenizer(prompt);
1266
+ const promptLen = inputs.input_ids.dims[1];
1267
+ const modelPath = model.provider_config.model_path;
1268
+ let session = sessionId ? getHftSession(sessionId) : undefined;
1269
+ let past_key_values = undefined;
1270
+ if (session?.mode === "prefix-rewind" && session.modelPath === modelPath) {
1271
+ const { DynamicCache } = await loadTransformersSDK();
1272
+ past_key_values = new DynamicCache(session.baseEntries);
1273
+ }
1274
+ let accumulated = "";
1275
+ let streamer;
1276
+ if (onDelta) {
1277
+ streamer = createStreamingTextStreamer(hfTokenizer, (text) => {
1278
+ accumulated += text;
1279
+ onDelta(text);
1280
+ }, TextStreamer);
1281
+ } else {
1282
+ streamer = createTextStreamer(hfTokenizer, (progress, message) => emit({ type: "phase", message: message ?? "", progress }), TextStreamer);
1283
+ }
1284
+ const output = await hfModel.generate({
1285
+ ...inputs,
1286
+ max_new_tokens: input.maxTokens ?? 1024,
1287
+ temperature: input.temperature ?? undefined,
1288
+ streamer,
1289
+ stopping_criteria: [stopping_criteria],
1290
+ ...past_key_values ? { past_key_values } : {}
1291
+ });
1292
+ if (!onDelta) {
1293
+ const seqLen = output.dims[1];
1294
+ const newTokens = output.slice(0, [promptLen, seqLen], null);
1295
+ accumulated = hfTokenizer.decode(newTokens, { skip_special_tokens: true });
1296
+ }
1297
+ if (sessionId) {
1298
+ let outputCache;
1299
+ if (past_key_values) {
1300
+ outputCache = past_key_values;
1301
+ } else if (output.past_key_values) {
1302
+ outputCache = output.past_key_values;
1303
+ }
1304
+ if (outputCache) {
1305
+ const baseEntries = {};
1306
+ for (const key of Object.keys(outputCache)) {
1307
+ baseEntries[key] = outputCache[key];
1308
+ }
1309
+ const newSession = {
1310
+ mode: "prefix-rewind",
1311
+ baseEntries,
1312
+ baseSeqLength: outputCache.get_seq_length ? outputCache.get_seq_length() : 0,
1313
+ modelPath
1314
+ };
1315
+ setHftSession(sessionId, newSession);
1316
+ }
1317
+ }
1318
+ return accumulated;
1319
+ }
1320
+ var HFT_Chat = async (input, model, signal, emit, _outputSchema, sessionId) => {
1321
+ await generateTurn(input, model, sessionId, emit, signal, (piece) => {
1322
+ emit({ type: "text-delta", port: "text", textDelta: piece });
1323
+ });
1324
+ emit({ type: "finish", data: {} });
1325
+ };
1326
+
1327
+ // src/ai/common/HFT_CountTokens.ts
1328
+ init_HFT_Pipeline();
1329
+ async function countTokens(input, model) {
1330
+ const { AutoTokenizer } = await loadTransformersSDK();
1331
+ const tokenizer = await AutoTokenizer.from_pretrained(model.provider_config.model_path, {});
1332
+ const tokenIds = tokenizer.encode(input.text);
1333
+ return { count: tokenIds.length };
1334
+ }
1335
+ var HFT_CountTokens = async (input, model, _signal, emit) => {
1336
+ const data = await countTokens(input, model);
1337
+ emit({ type: "finish", data });
1338
+ };
1339
+ var HFT_CountTokens_Preview = async (input, model) => {
1340
+ return countTokens(input, model);
1341
+ };
1342
+
1343
+ // src/ai/common/HFT_Download.ts
1344
+ init_HFT_Pipeline();
1345
+ import { getLogger as getLogger2 } from "@workglow/util/worker";
1346
+ var HFT_Download = async (input, model, signal, emit) => {
1347
+ const logger = getLogger2();
1348
+ const timerLabel = `hft:Download:${model?.provider_config.model_path}`;
1349
+ logger.time(timerLabel, { model: model?.provider_config.model_path });
1350
+ await getPipeline(model, emit, {}, signal, 100);
1351
+ logger.timeEnd(timerLabel, { model: model?.provider_config.model_path });
1352
+ emit({ type: "finish", data: { model: input.model } });
1353
+ };
1354
+
1355
+ // src/ai/common/HFT_DownloadRemove.ts
1356
+ init_HFT_Pipeline();
1357
+ function hasBrowserCacheStorage() {
1358
+ return typeof globalThis !== "undefined" && "caches" in globalThis && typeof globalThis.caches?.open === "function";
1359
+ }
1360
+ async function deleteModelCacheFromBrowser(model_path) {
1361
+ const cachesApi = globalThis.caches;
1362
+ const cache = await cachesApi.open(HTF_CACHE_NAME);
1363
+ const keys = await cache.keys();
1364
+ const prefix = `/${model_path}/`;
1365
+ const requestsToDelete = [];
1366
+ for (const request of keys) {
1367
+ const url = new URL(request.url);
1368
+ if (url.pathname.startsWith(prefix)) {
1369
+ requestsToDelete.push(request);
1370
+ }
1371
+ }
1372
+ for (const request of requestsToDelete) {
1373
+ try {
1374
+ const deleted = await cache.delete(request);
1375
+ if (!deleted) {
1376
+ const deletedByUrl = await cache.delete(request.url);
1377
+ if (!deletedByUrl) {}
1378
+ }
1379
+ } catch (error) {
1380
+ console.error(`Failed to delete cache entry: ${request.url}`, error);
1381
+ }
1382
+ }
1383
+ }
1384
+ async function deleteModelCacheFromFilesystem(model) {
1385
+ const { ModelRegistry } = await loadTransformersSDK();
1386
+ const { pipeline: pipelineType, model_path, dtype } = model.provider_config;
1387
+ await ModelRegistry.clear_pipeline_cache(pipelineType, model_path, {
1388
+ ...dtype ? { dtype } : {}
1389
+ });
1390
+ }
1391
+ var HFT_DownloadRemove = async (input, model, _signal, emit) => {
1392
+ const cacheKey = getPipelineCacheKey(model);
1393
+ await removeCachedPipeline(cacheKey);
1394
+ const model_path = model.provider_config.model_path;
1395
+ disposeHftSessionsForModel(model_path);
1396
+ if (hasBrowserCacheStorage()) {
1397
+ await deleteModelCacheFromBrowser(model_path);
1398
+ } else {
1399
+ await deleteModelCacheFromFilesystem(model);
1400
+ }
1401
+ emit({ type: "finish", data: { model: input.model } });
1402
+ };
1403
+
1404
+ // src/ai/common/HFT_ImageClassification.ts
1405
+ init_HFT_Pipeline();
1406
+ import { imageValueToBlob as imageValueToBlob2 } from "@workglow/ai/provider-utils";
1407
+ var HFT_ImageClassification = async (input, model, signal, emit) => {
1408
+ if (model?.provider_config?.pipeline === "zero-shot-image-classification") {
1409
+ if (!input.categories || !Array.isArray(input.categories) || input.categories.length === 0) {
1410
+ console.warn("Zero-shot image classification requires categories", input);
1411
+ throw new Error("Zero-shot image classification requires categories");
1412
+ }
1413
+ const zeroShotClassifier = await getPipeline(model, emit, {}, signal);
1414
+ const imageArg2 = await imageValueToBlob2(input.image);
1415
+ const result2 = await zeroShotClassifier(imageArg2, input.categories, {});
1416
+ const results2 = Array.isArray(result2) ? result2 : [result2];
1417
+ emit({
1418
+ type: "finish",
1419
+ data: {
1420
+ categories: results2.map((r) => ({
1421
+ label: r.label,
1422
+ score: r.score
1423
+ }))
1424
+ }
1425
+ });
1426
+ return;
1427
+ }
1428
+ const classifier = await getPipeline(model, emit, {}, signal);
1429
+ const imageArg = await imageValueToBlob2(input.image);
1430
+ const result = await classifier(imageArg, {
1431
+ top_k: input.maxCategories
1432
+ });
1433
+ const results = Array.isArray(result) ? result : [result];
1434
+ emit({
1435
+ type: "finish",
1436
+ data: {
1437
+ categories: results.map((r) => ({
1438
+ label: r.label,
1439
+ score: r.score
1440
+ }))
1441
+ }
1442
+ });
1443
+ };
1444
+
1445
+ // src/ai/common/HFT_ImageEmbedding.ts
1446
+ init_HFT_Pipeline();
1447
+ import { getLogger as getLogger3 } from "@workglow/util/worker";
1448
+ import { imageValueToBlob as imageValueToBlob3 } from "@workglow/ai/provider-utils";
1449
+ var HFT_ImageEmbedding = async (input, model, signal, emit) => {
1450
+ const logger = getLogger3();
1451
+ const timerLabel = `hft:ImageEmbedding:${model?.provider_config.model_path}`;
1452
+ logger.time(timerLabel, { model: model?.provider_config.model_path });
1453
+ const embedder = await getPipeline(model, emit, {}, signal);
1454
+ logger.debug("HFT ImageEmbedding: pipeline ready, generating embedding", {
1455
+ model: model?.provider_config.model_path
1456
+ });
1457
+ if (Array.isArray(input.image)) {
1458
+ const vectors = [];
1459
+ for (const image of input.image) {
1460
+ const imageArg2 = await imageValueToBlob3(image);
1461
+ const result2 = await embedder(imageArg2);
1462
+ vectors.push(result2.data);
1463
+ }
1464
+ logger.timeEnd(timerLabel, { count: vectors.length });
1465
+ emit({ type: "finish", data: { vector: vectors } });
1466
+ return;
1467
+ }
1468
+ const imageArg = await imageValueToBlob3(input.image);
1469
+ const result = await embedder(imageArg);
1470
+ logger.timeEnd(timerLabel, { dimensions: result?.data?.length });
1471
+ emit({
1472
+ type: "finish",
1473
+ data: { vector: result.data }
1474
+ });
1475
+ };
1476
+
1477
+ // src/ai/common/HFT_ImageSegmentation.ts
1478
+ init_HFT_Pipeline();
1479
+ import { imageValueToBlob as imageValueToBlob4 } from "@workglow/ai/provider-utils";
1480
+ var HFT_ImageSegmentation = async (input, model, signal, emit) => {
1481
+ const segmenter = await getPipeline(model, emit, {}, signal);
1482
+ const imageArg = await imageValueToBlob4(input.image);
1483
+ const result = await segmenter(imageArg, {
1484
+ threshold: input.threshold,
1485
+ mask_threshold: input.maskThreshold
1486
+ });
1487
+ const masks = Array.isArray(result) ? result : [result];
1488
+ const processedMasks = await Promise.all(masks.map(async (mask) => ({
1489
+ label: mask.label || "",
1490
+ score: mask.score || 0,
1491
+ mask: {}
1492
+ })));
1493
+ emit({
1494
+ type: "finish",
1495
+ data: {
1496
+ masks: processedMasks
1497
+ }
1498
+ });
1499
+ };
1500
+
1501
+ // src/ai/common/HFT_ImageToText.ts
1502
+ init_HFT_Pipeline();
1503
+ import { imageValueToBlob as imageValueToBlob5 } from "@workglow/ai/provider-utils";
1504
+ var HFT_ImageToText = async (input, model, signal, emit) => {
1505
+ const captioner = await getPipeline(model, emit, {}, signal);
1506
+ const imageArg = await imageValueToBlob5(input.image);
1507
+ const result = await captioner(imageArg, {
1508
+ max_new_tokens: input.maxTokens
1509
+ });
1510
+ const text = Array.isArray(result[0]) ? result[0][0]?.generated_text : result[0]?.generated_text;
1511
+ emit({
1512
+ type: "finish",
1513
+ data: {
1514
+ text: text || ""
1515
+ }
1516
+ });
1517
+ };
1518
+
1519
+ // src/ai/common/HFT_ModelInfo.ts
1520
+ import { getLogger as getLogger4 } from "@workglow/util/worker";
1521
+ init_HFT_Pipeline();
1522
+ var HFT_ModelInfo = async (input, model, _signal, emit) => {
1523
+ if (input.detail === "dimensions") {
1524
+ if (!model)
1525
+ throw new Error("Model config is required for ModelInfoTask.");
1526
+ const pc = model.provider_config;
1527
+ let native_dimensions = typeof pc.native_dimensions === "number" ? pc.native_dimensions : undefined;
1528
+ const mrl = typeof pc.mrl === "boolean" ? pc.mrl : false;
1529
+ if (native_dimensions === undefined && typeof pc.model_path === "string") {
1530
+ try {
1531
+ const response = await fetch(`https://huggingface.co/${pc.model_path}/resolve/${pc.revision ?? "main"}/config.json`);
1532
+ if (response.ok) {
1533
+ const config = await response.json();
1534
+ if (typeof config.hidden_size === "number") {
1535
+ native_dimensions = config.hidden_size;
1536
+ }
1537
+ }
1538
+ } catch {}
1539
+ }
1540
+ emit({
1541
+ type: "finish",
1542
+ data: {
1543
+ model: input.model,
1544
+ is_local: true,
1545
+ is_remote: false,
1546
+ supports_browser: true,
1547
+ supports_node: true,
1548
+ is_cached: false,
1549
+ is_loaded: false,
1550
+ file_sizes: null,
1551
+ ...native_dimensions !== undefined ? { native_dimensions } : {},
1552
+ ...mrl ? { mrl } : {}
1553
+ }
1554
+ });
1555
+ return;
1556
+ }
1557
+ const logger = getLogger4();
1558
+ const { ModelRegistry } = await loadTransformersSDK();
1559
+ const timerLabel = `hft:ModelInfo:${model?.provider_config.model_path}`;
1560
+ logger.time(timerLabel, { model: model?.provider_config.model_path });
1561
+ const detail = input.detail;
1562
+ const is_loaded = hasCachedPipeline(getPipelineCacheKey(model));
1563
+ const { pipeline: pipelineType, model_path, dtype, device } = model.provider_config;
1564
+ const cacheOptions = {
1565
+ ...dtype ? { dtype } : {},
1566
+ ...device ? { device } : {}
1567
+ };
1568
+ const cacheStatus = await ModelRegistry.is_pipeline_cached_files(pipelineType, model_path, cacheOptions);
1569
+ logger.debug("is_pipeline_cached", {
1570
+ input: [pipelineType, model_path, cacheOptions],
1571
+ result: cacheStatus
1572
+ });
1573
+ const is_cached = is_loaded || cacheStatus.allCached;
1574
+ let file_sizes = null;
1575
+ if (detail === "files" && cacheStatus.files.length > 0) {
1576
+ const sizes = {};
1577
+ for (const { file } of cacheStatus.files) {
1578
+ sizes[file] = 0;
1579
+ }
1580
+ file_sizes = sizes;
1581
+ } else if (detail === "files_with_metadata" && cacheStatus.files.length > 0) {
1582
+ const sizes = {};
1583
+ await Promise.all(cacheStatus.files.map(async ({ file }) => {
1584
+ const metadata = await ModelRegistry.get_file_metadata(model_path, file);
1585
+ if (metadata.exists && metadata.size !== undefined) {
1586
+ sizes[file] = metadata.size;
1587
+ }
1588
+ }));
1589
+ if (Object.keys(sizes).length > 0) {
1590
+ file_sizes = sizes;
1591
+ }
1592
+ }
1593
+ let quantizations;
1594
+ if (cacheStatus.files.length > 0) {
1595
+ const filePaths = cacheStatus.files.map((f) => f.file);
1596
+ const quantizations_parsed = parseOnnxQuantizations({ filePaths });
1597
+ if (quantizations_parsed.length > 0) {
1598
+ quantizations = quantizations_parsed;
1599
+ }
1600
+ }
1601
+ logger.timeEnd(timerLabel, { model: model?.provider_config.model_path });
1602
+ emit({
1603
+ type: "finish",
1604
+ data: {
1605
+ model: input.model,
1606
+ is_local: true,
1607
+ is_remote: false,
1608
+ supports_browser: true,
1609
+ supports_node: true,
1610
+ is_cached,
1611
+ is_loaded,
1612
+ file_sizes,
1613
+ ...quantizations ? { quantizations } : {}
1614
+ }
1615
+ });
1616
+ };
1617
+
1618
+ // src/ai/common/HFT_ModelSearch.ts
1619
+ import { searchHfModels, mapHfModelResult } from "@workglow/ai/provider-utils";
1620
+ var HFT_ModelSearch = async (input, _model, signal, emit) => {
1621
+ const entries = await searchHfModels(input.query?.trim() ?? "", { filter: "onnx" }, ["siblings"], signal);
1622
+ const results = entries.map((entry) => {
1623
+ const item = mapHfModelResult(entry, HF_TRANSFORMERS_ONNX);
1624
+ if (entry.siblings && entry.siblings.length > 0) {
1625
+ const filePaths = entry.siblings.map((s) => s.rfilename);
1626
+ const quantizations = parseOnnxQuantizations({ filePaths });
1627
+ if (quantizations.length > 0) {
1628
+ const record = item.record;
1629
+ const providerConfig = record.provider_config ?? {};
1630
+ providerConfig.quantizations = quantizations;
1631
+ record.provider_config = providerConfig;
1632
+ }
1633
+ }
1634
+ const raw = item.raw;
1635
+ delete raw.siblings;
1636
+ return item;
1637
+ });
1638
+ emit({ type: "finish", data: { results } });
1639
+ };
1640
+
1641
+ // src/ai/common/HFT_ObjectDetection.ts
1642
+ init_HFT_Pipeline();
1643
+ import { imageValueToBlob as imageValueToBlob6 } from "@workglow/ai/provider-utils";
1644
+ var HFT_ObjectDetection = async (input, model, signal, emit) => {
1645
+ if (model?.provider_config?.pipeline === "zero-shot-object-detection") {
1646
+ if (!input.labels || !Array.isArray(input.labels) || input.labels.length === 0) {
1647
+ throw new Error("Zero-shot object detection requires labels");
1648
+ }
1649
+ const zeroShotDetector = await getPipeline(model, emit, {}, signal);
1650
+ const imageArg2 = await imageValueToBlob6(input.image);
1651
+ const result = await zeroShotDetector(imageArg2, Array.from(input.labels), {
1652
+ threshold: input.threshold
1653
+ });
1654
+ emit({
1655
+ type: "finish",
1656
+ data: {
1657
+ detections: result.map((d) => ({
1658
+ label: d.label,
1659
+ score: d.score,
1660
+ box: d.box
1661
+ }))
1662
+ }
1663
+ });
1664
+ return;
1665
+ }
1666
+ const detector = await getPipeline(model, emit, {}, signal);
1667
+ const imageArg = await imageValueToBlob6(input.image);
1668
+ const detections = await detector(imageArg, {
1669
+ threshold: input.threshold
1670
+ });
1671
+ emit({
1672
+ type: "finish",
1673
+ data: {
1674
+ detections: detections.map((d) => ({
1675
+ label: d.label,
1676
+ score: d.score,
1677
+ box: d.box
1678
+ }))
1679
+ }
1680
+ });
1681
+ };
1682
+
1683
+ // src/ai/common/HFT_StructuredGeneration.ts
1684
+ init_HFT_Pipeline();
1685
+ import { parsePartialJson } from "@workglow/util/worker";
1686
+ function buildStructuredGenerationPrompt(input) {
1687
+ const schemaStr = JSON.stringify(input.outputSchema, null, 2);
1688
+ return `${input.prompt}
1689
+
1690
+ ` + `You MUST respond with ONLY a valid JSON object conforming to this JSON schema:
1691
+ ${schemaStr}
1692
+
1693
+ ` + `Output ONLY the JSON object, no other text.`;
1694
+ }
1695
+ function stripThinkingAndSpecialTokens(text) {
1696
+ return text.replace(/<think>[\s\S]*?<\/think>/g, "").replace(/<\|[a-z_]+\|>/g, "").trim();
1697
+ }
1698
+ function extractJsonFromText(text) {
1699
+ const cleaned = stripThinkingAndSpecialTokens(text);
1700
+ try {
1701
+ return JSON.parse(cleaned);
1702
+ } catch {
1703
+ const match = cleaned.match(/\{[\s\S]*\}/);
1704
+ if (match) {
1705
+ try {
1706
+ return JSON.parse(match[0]);
1707
+ } catch {
1708
+ return parsePartialJson(match[0]) ?? {};
1709
+ }
1710
+ }
1711
+ return {};
1712
+ }
1713
+ }
1714
+ var HFT_StructuredGeneration = async (input, model, signal, emit) => {
1715
+ const generateText = await getPipeline(model, emit, {}, signal);
1716
+ const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
1717
+ const prompt = buildStructuredGenerationPrompt(input);
1718
+ const messages = [{ role: "user", content: prompt }];
1719
+ const formattedPrompt = generateText.tokenizer.apply_chat_template(messages, {
1720
+ tokenize: false,
1721
+ add_generation_prompt: true
1722
+ });
1723
+ let fullText = "";
1724
+ let cleanedText = "";
1725
+ let inThinkBlock = false;
1726
+ let jsonStart = -1;
1727
+ const streamer = createStreamingTextStreamer(generateText.tokenizer, (delta) => {
1728
+ fullText += delta;
1729
+ let remaining = delta;
1730
+ while (remaining.length > 0) {
1731
+ if (inThinkBlock) {
1732
+ const closeIdx = remaining.indexOf("</think>");
1733
+ if (closeIdx !== -1) {
1734
+ inThinkBlock = false;
1735
+ remaining = remaining.slice(closeIdx + "</think>".length);
1736
+ } else {
1737
+ remaining = "";
1738
+ }
1739
+ } else {
1740
+ const openIdx = remaining.indexOf("<think>");
1741
+ if (openIdx !== -1) {
1742
+ cleanedText += remaining.slice(0, openIdx).replace(/<\|[a-z_]+\|>/g, "");
1743
+ inThinkBlock = true;
1744
+ remaining = remaining.slice(openIdx + "<think>".length);
1745
+ } else {
1746
+ cleanedText += remaining.replace(/<\|[a-z_]+\|>/g, "");
1747
+ remaining = "";
1748
+ }
1749
+ }
1750
+ }
1751
+ if (jsonStart === -1) {
1752
+ jsonStart = cleanedText.indexOf("{");
1753
+ }
1754
+ if (jsonStart !== -1) {
1755
+ const partial = parsePartialJson(cleanedText.slice(jsonStart));
1756
+ if (partial !== undefined) {
1757
+ emit({ type: "object-delta", port: "object", objectDelta: partial });
1758
+ return;
1759
+ }
1760
+ }
1761
+ emit({ type: "text-delta", port: "text", textDelta: delta });
1762
+ }, TextStreamer);
1763
+ const stopping_criteria = new InterruptableStoppingCriteria;
1764
+ if (signal) {
1765
+ signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
1766
+ }
1767
+ await generateText(formattedPrompt, {
1768
+ max_new_tokens: input.maxTokens ?? 1024,
1769
+ temperature: input.temperature ?? undefined,
1770
+ return_full_text: false,
1771
+ streamer,
1772
+ stopping_criteria: [stopping_criteria]
1773
+ });
1774
+ const object = extractJsonFromText(fullText);
1775
+ emit({ type: "finish", data: { object } });
1776
+ };
1777
+
1778
+ // src/ai/common/HFT_TextClassification.ts
1779
+ init_HFT_Pipeline();
1780
+ var HFT_TextClassification = async (input, model, signal, emit) => {
1781
+ if (model?.provider_config?.pipeline === "zero-shot-classification") {
1782
+ if (!input.candidateLabels || !Array.isArray(input.candidateLabels) || input.candidateLabels.length === 0) {
1783
+ throw new Error("Zero-shot text classification requires candidate labels");
1784
+ }
1785
+ const zeroShotClassifier = await getPipeline(model, emit, {}, signal);
1786
+ const result2 = await zeroShotClassifier(input.text, input.candidateLabels, {});
1787
+ emit({
1788
+ type: "finish",
1789
+ data: {
1790
+ categories: result2.labels.map((label, idx) => ({
1791
+ label,
1792
+ score: result2.scores[idx]
1793
+ }))
1794
+ }
1795
+ });
1796
+ return;
1797
+ }
1798
+ const TextClassification = await getPipeline(model, emit, {}, signal);
1799
+ const result = await TextClassification(input.text, {
1800
+ top_k: input.maxCategories || undefined
1801
+ });
1802
+ emit({
1803
+ type: "finish",
1804
+ data: {
1805
+ categories: result.map((category) => ({
1806
+ label: category.label,
1807
+ score: category.score
1808
+ }))
1809
+ }
1810
+ });
1811
+ };
1812
+
1813
+ // src/ai/common/HFT_TextEmbedding.ts
1814
+ init_HFT_Pipeline();
1815
+ import { getLogger as getLogger5 } from "@workglow/util/worker";
1816
+ var HFT_TextEmbedding = async (input, model, signal, emit) => {
1817
+ const logger = getLogger5();
1818
+ const uuid = crypto.randomUUID();
1819
+ const timerLabel = `hft:TextEmbedding:${model?.provider_config.model_path}:${uuid}`;
1820
+ logger.time(timerLabel, { model: model?.provider_config.model_path });
1821
+ const generateEmbedding = await getPipeline(model, emit, {}, signal);
1822
+ logger.debug("HFT TextEmbedding: pipeline ready, generating embedding", {
1823
+ model: model?.provider_config.model_path,
1824
+ inputLength: Array.isArray(input.text) ? input.text.length : input.text?.length
1825
+ });
1826
+ const hfVector = await generateEmbedding(input.text, {
1827
+ pooling: model?.provider_config.pooling || "mean",
1828
+ normalize: model?.provider_config.normalize
1829
+ });
1830
+ const isArrayInput = Array.isArray(input.text);
1831
+ const embeddingDim = model?.provider_config.native_dimensions;
1832
+ if (isArrayInput && hfVector.dims.length > 1) {
1833
+ const [numTexts, vectorDim] = hfVector.dims;
1834
+ if (numTexts !== input.text.length) {
1835
+ throw new Error(`HuggingFace Embedding tensor batch size does not match input array length: ${numTexts} != ${input.text.length}`);
1836
+ }
1837
+ if (vectorDim !== embeddingDim) {
1838
+ throw new Error(`HuggingFace Embedding vector dimension does not match model dimensions: ${vectorDim} != ${embeddingDim}`);
1839
+ }
1840
+ const vectors = Array.from({ length: numTexts }, (_, i) => hfVector[i].data.slice());
1841
+ logger.timeEnd(timerLabel, { batchSize: numTexts, dimensions: vectorDim });
1842
+ emit({ type: "finish", data: { vector: vectors } });
1843
+ return;
1844
+ }
1845
+ if (hfVector.size !== embeddingDim) {
1846
+ logger.timeEnd(timerLabel, { status: "error", reason: "dimension mismatch" });
1847
+ console.warn(`HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${embeddingDim}`, input, hfVector);
1848
+ throw new Error(`HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${embeddingDim}`);
1849
+ }
1850
+ logger.timeEnd(timerLabel, { dimensions: hfVector.size });
1851
+ emit({ type: "finish", data: { vector: hfVector.data } });
1852
+ };
1853
+
1854
+ // src/ai/common/HFT_TextFillMask.ts
1855
+ init_HFT_Pipeline();
1856
+ var HFT_TextFillMask = async (input, model, signal, emit) => {
1857
+ const unmasker = await getPipeline(model, emit, {}, signal);
1858
+ const predictions = await unmasker(input.text);
1859
+ emit({
1860
+ type: "finish",
1861
+ data: {
1862
+ predictions: predictions.map((prediction) => ({
1863
+ entity: prediction.token_str,
1864
+ score: prediction.score,
1865
+ sequence: prediction.sequence
1866
+ }))
1867
+ }
1868
+ });
1869
+ };
1870
+
1871
+ // src/ai/common/HFT_TextGeneration.ts
1872
+ init_HFT_Pipeline();
1873
+ var HFT_TextGeneration = async (input, model, signal, emit, _outputSchema, sessionId) => {
1874
+ const generateText = await getPipeline(model, emit, {}, signal);
1875
+ const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
1876
+ const streamer = createStreamingTextStreamer(generateText.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
1877
+ const stopping_criteria = new InterruptableStoppingCriteria;
1878
+ if (signal) {
1879
+ signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
1880
+ }
1881
+ const modelPath = model.provider_config.model_path;
1882
+ let session = sessionId ? getHftSession(sessionId) : undefined;
1883
+ let past_key_values = undefined;
1884
+ if (sessionId && !session) {
1885
+ const sdk = await loadTransformersSDK();
1886
+ const cache = new sdk.DynamicCache;
1887
+ const newSession = {
1888
+ mode: "progressive",
1889
+ cache,
1890
+ modelPath
1891
+ };
1892
+ setHftSession(sessionId, newSession);
1893
+ session = newSession;
1894
+ }
1895
+ if (session?.mode === "progressive") {
1896
+ past_key_values = session.cache;
1897
+ }
1898
+ const messages = [{ role: "user", content: input.prompt }];
1899
+ await generateText(messages, {
1900
+ streamer,
1901
+ do_sample: false,
1902
+ max_new_tokens: input.maxTokens ?? 4 * 1024,
1903
+ stopping_criteria: [stopping_criteria],
1904
+ ...past_key_values ? { past_key_values } : {}
1905
+ });
1906
+ emit({ type: "finish", data: {} });
1907
+ };
1908
+
1909
+ // src/ai/common/HFT_TextLanguageDetection.ts
1910
+ init_HFT_Pipeline();
1911
+ var HFT_TextLanguageDetection = async (input, model, signal, emit) => {
1912
+ const TextClassification = await getPipeline(model, emit, {}, signal);
1913
+ const result = await TextClassification(input.text, {
1914
+ top_k: input.maxLanguages || undefined
1915
+ });
1916
+ emit({
1917
+ type: "finish",
1918
+ data: {
1919
+ languages: result.map((category) => ({
1920
+ language: category.label,
1921
+ score: category.score
1922
+ }))
1923
+ }
1924
+ });
1925
+ };
1926
+
1927
+ // src/ai/common/HFT_TextNamedEntityRecognition.ts
1928
+ init_HFT_Pipeline();
1929
+ var HFT_TextNamedEntityRecognition = async (input, model, signal, emit) => {
1930
+ const textNamedEntityRecognition = await getPipeline(model, emit, {}, signal);
1931
+ const results = await textNamedEntityRecognition(input.text, {
1932
+ ignore_labels: input.blockList
1933
+ });
1934
+ emit({
1935
+ type: "finish",
1936
+ data: {
1937
+ entities: results.map((entity) => ({
1938
+ entity: entity.entity,
1939
+ score: entity.score,
1940
+ word: entity.word
1941
+ }))
1942
+ }
1943
+ });
1944
+ };
1945
+
1946
+ // src/ai/common/HFT_TextQuestionAnswer.ts
1947
+ init_HFT_Pipeline();
1948
+ var HFT_TextQuestionAnswer = async (input, model, signal, emit) => {
1949
+ const generateAnswer = await getPipeline(model, emit, {}, signal);
1950
+ const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
1951
+ const streamer = createStreamingTextStreamer(generateAnswer.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
1952
+ const stopping_criteria = new InterruptableStoppingCriteria;
1953
+ if (signal) {
1954
+ signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
1955
+ }
1956
+ const pipelineResult = await generateAnswer(input.question, input.context, {
1957
+ streamer,
1958
+ stopping_criteria: [stopping_criteria]
1959
+ });
1960
+ const answerText = Array.isArray(pipelineResult) ? pipelineResult[0]?.answer ?? "" : pipelineResult?.answer ?? "";
1961
+ emit({ type: "finish", data: { text: answerText } });
1962
+ };
1963
+
1964
+ // src/ai/common/HFT_TextReranker.ts
1965
+ init_HFT_Pipeline();
1966
+ import { KbRerankerOutputError } from "@workglow/ai";
1967
+ import { getLogger as getLogger6 } from "@workglow/util/worker";
1968
+ function isScored(v) {
1969
+ return typeof v === "object" && v !== null && typeof v.score === "number";
1970
+ }
1971
+ function truncateShape(value) {
1972
+ try {
1973
+ const json = JSON.stringify(value);
1974
+ if (typeof json !== "string")
1975
+ return String(value);
1976
+ return json.length > 200 ? `${json.slice(0, 200)}…` : json;
1977
+ } catch {
1978
+ return String(value);
1979
+ }
1980
+ }
1981
+ function validateAndExtractRerankerScores(rawResults, modelPath) {
1982
+ if (!Array.isArray(rawResults)) {
1983
+ throw new KbRerankerOutputError(`HFT_TextReranker: unexpected pipeline output shape for model ${modelPath}`, truncateShape(rawResults));
1984
+ }
1985
+ const scores = new Array(rawResults.length);
1986
+ for (let i = 0;i < rawResults.length; i++) {
1987
+ const entry = rawResults[i];
1988
+ const candidate = Array.isArray(entry) ? entry[0] : entry;
1989
+ if (!isScored(candidate)) {
1990
+ throw new KbRerankerOutputError(`HFT_TextReranker: unexpected pipeline output shape for model ${modelPath}`, truncateShape(entry));
1991
+ }
1992
+ scores[i] = candidate.score;
1993
+ }
1994
+ return scores;
1995
+ }
1996
+ var HFT_TextReranker = async (input, model, signal, emit) => {
1997
+ const logger = getLogger6();
1998
+ const modelPath = model?.provider_config.model_path;
1999
+ const timerLabel = `hft:TextReranker:${modelPath}`;
2000
+ logger.time(timerLabel, { docs: input.documents.length });
2001
+ const reranker = await getPipeline(model, emit, {}, signal);
2002
+ const pairs = input.documents.map((doc) => ({ text: input.query, text_pair: doc }));
2003
+ const callable = reranker;
2004
+ const rawResults = await callable(pairs, { top_k: 1 });
2005
+ const scores = validateAndExtractRerankerScores(rawResults, modelPath);
2006
+ const indices = scores.map((score, idx) => ({ score, idx })).sort((a, b) => b.score - a.score).map((p) => p.idx);
2007
+ const limited = typeof input.topK === "number" ? indices.slice(0, input.topK) : indices;
2008
+ logger.timeEnd(timerLabel, { docs: input.documents.length });
2009
+ emit({ type: "finish", data: { scores, indices: limited } });
2010
+ };
2011
+
2012
+ // src/ai/common/HFT_TextRewriter.ts
2013
+ init_HFT_Pipeline();
2014
+ var HFT_TextRewriter = async (input, model, signal, emit) => {
2015
+ const generateText = await getPipeline(model, emit, {}, signal);
2016
+ const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
2017
+ const streamer = createStreamingTextStreamer(generateText.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
2018
+ const stopping_criteria = new InterruptableStoppingCriteria;
2019
+ if (signal) {
2020
+ signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
2021
+ }
2022
+ const promptedText = (input.prompt ? input.prompt + `
2023
+ ` : "") + input.text;
2024
+ await generateText(promptedText, {
2025
+ streamer,
2026
+ stopping_criteria: [stopping_criteria]
2027
+ });
2028
+ emit({ type: "finish", data: {} });
2029
+ };
2030
+
2031
+ // src/ai/common/HFT_TextSummary.ts
2032
+ init_HFT_Pipeline();
2033
+ var HFT_TextSummary = async (input, model, signal, emit) => {
2034
+ const generateSummary = await getPipeline(model, emit, {}, signal);
2035
+ const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
2036
+ const streamer = createStreamingTextStreamer(generateSummary.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
2037
+ const stopping_criteria = new InterruptableStoppingCriteria;
2038
+ if (signal) {
2039
+ signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
2040
+ }
2041
+ await generateSummary(input.text, {
2042
+ streamer,
2043
+ stopping_criteria: [stopping_criteria]
2044
+ });
2045
+ emit({ type: "finish", data: {} });
2046
+ };
2047
+
2048
+ // src/ai/common/HFT_TextTranslation.ts
2049
+ init_HFT_Pipeline();
2050
+ var HFT_TextTranslation = async (input, model, signal, emit) => {
2051
+ const translate = await getPipeline(model, emit, {}, signal);
2052
+ const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
2053
+ const streamer = createStreamingTextStreamer(translate.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
2054
+ const stopping_criteria = new InterruptableStoppingCriteria;
2055
+ if (signal) {
2056
+ signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
2057
+ }
2058
+ await translate(input.text, {
2059
+ src_lang: input.source_lang,
2060
+ tgt_lang: input.target_lang,
2061
+ streamer,
2062
+ stopping_criteria: [stopping_criteria]
2063
+ });
2064
+ emit({ type: "finish", data: { target_lang: input.target_lang } });
2065
+ };
2066
+
2067
+ // src/ai/common/HFT_JobRunFns.ts
2068
+ var HFT_TextGeneration_Unified = async (input, model, signal, emit, outputSchema, sessionId) => {
2069
+ const maybeMessages = input.messages;
2070
+ if (Array.isArray(maybeMessages) && maybeMessages.length > 0) {
2071
+ await HFT_Chat(input, model, signal, emit, outputSchema, sessionId);
2072
+ } else {
2073
+ await HFT_TextGeneration(input, model, signal, emit, outputSchema, sessionId);
2074
+ }
2075
+ };
2076
+ var HFT_RUN_FNS = [
2077
+ { serves: HFT_TEXT_GENERATION, runFn: HFT_TextGeneration_Unified },
2078
+ { serves: HFT_TOOL_USE, runFn: HFT_ToolCalling },
2079
+ { serves: HFT_JSON_MODE, runFn: HFT_StructuredGeneration },
2080
+ { serves: HFT_TEXT_REWRITER, runFn: HFT_TextRewriter },
2081
+ { serves: HFT_TEXT_SUMMARY, runFn: HFT_TextSummary },
2082
+ { serves: HFT_TEXT_TRANSLATION, runFn: HFT_TextTranslation },
2083
+ { serves: HFT_TEXT_QUESTION_ANSWERING, runFn: HFT_TextQuestionAnswer },
2084
+ { serves: HFT_TEXT_EMBEDDING, runFn: HFT_TextEmbedding },
2085
+ { serves: HFT_TEXT_CLASSIFICATION, runFn: HFT_TextClassification },
2086
+ { serves: HFT_TEXT_LANGUAGE_DETECTION, runFn: HFT_TextLanguageDetection },
2087
+ { serves: HFT_TEXT_RERANKING, runFn: HFT_TextReranker },
2088
+ { serves: HFT_TEXT_FILL_MASK, runFn: HFT_TextFillMask },
2089
+ { serves: HFT_TEXT_NER, runFn: HFT_TextNamedEntityRecognition },
2090
+ { serves: HFT_IMAGE_CLASSIFICATION, runFn: HFT_ImageClassification },
2091
+ { serves: HFT_IMAGE_EMBEDDING, runFn: HFT_ImageEmbedding },
2092
+ { serves: HFT_IMAGE_SEGMENTATION, runFn: HFT_ImageSegmentation },
2093
+ { serves: HFT_IMAGE_TO_TEXT, runFn: HFT_ImageToText },
2094
+ { serves: HFT_IMAGE_BACKGROUND_REMOVAL, runFn: HFT_BackgroundRemoval },
2095
+ { serves: HFT_IMAGE_OBJECT_DETECTION, runFn: HFT_ObjectDetection },
2096
+ { serves: HFT_COUNT_TOKENS, runFn: HFT_CountTokens },
2097
+ { serves: HFT_MODEL_DOWNLOAD_REMOVE, runFn: HFT_DownloadRemove },
2098
+ { serves: HFT_MODEL_DOWNLOAD, runFn: HFT_Download },
2099
+ { serves: HFT_MODEL_SEARCH, runFn: HFT_ModelSearch },
2100
+ { serves: HFT_MODEL_INFO, runFn: HFT_ModelInfo }
2101
+ ];
2102
+ var HFT_PREVIEW_TASKS = {
2103
+ CountTokensTask: HFT_CountTokens_Preview
2104
+ };
2105
+
2106
+ // src/ai/index.ts
2107
+ var _testOnly = {
2108
+ HFT_RUN_FN_SPECS,
2109
+ HFT_RUN_FNS
2110
+ };
861
2111
  export {
862
2112
  registerHuggingFaceTransformers,
863
2113
  parseOnnxQuantizations,
864
2114
  createToolCallMarkupFilter,
2115
+ _testOnly,
865
2116
  QuantizationDataType,
866
2117
  PipelineUseCase,
867
2118
  ONNX_QUANTIZATION_SUFFIX_MAPPING,
@@ -876,4 +2127,4 @@ export {
876
2127
  HF_TRANSFORMERS_ONNX
877
2128
  };
878
2129
 
879
- //# debugId=1F98AB72335DB69764756E2164756E21
2130
+ //# debugId=FC830CCDC8DBF09664756E2164756E21