@workglow/huggingface-transformers 0.2.34 → 0.2.35
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/ai/HuggingFaceTransformersProvider.d.ts +9 -8
- package/dist/ai/HuggingFaceTransformersProvider.d.ts.map +1 -1
- package/dist/ai/HuggingFaceTransformersQueuedProvider.d.ts +10 -8
- package/dist/ai/HuggingFaceTransformersQueuedProvider.d.ts.map +1 -1
- package/dist/ai/common/HFT_BackgroundRemoval.d.ts.map +1 -1
- package/dist/ai/common/HFT_Capabilities.d.ts +28 -0
- package/dist/ai/common/HFT_Capabilities.d.ts.map +1 -0
- package/dist/ai/common/HFT_CapabilitySets.d.ts +39 -0
- package/dist/ai/common/HFT_CapabilitySets.d.ts.map +1 -0
- package/dist/ai/common/HFT_Chat.d.ts +1 -2
- package/dist/ai/common/HFT_Chat.d.ts.map +1 -1
- package/dist/ai/common/HFT_CountTokens.d.ts.map +1 -1
- package/dist/ai/common/HFT_Download.d.ts +7 -2
- package/dist/ai/common/HFT_Download.d.ts.map +1 -1
- package/dist/ai/common/{HFT_Unload.d.ts → HFT_DownloadRemove.d.ts} +3 -3
- package/dist/ai/common/HFT_DownloadRemove.d.ts.map +1 -0
- package/dist/ai/common/HFT_ImageClassification.d.ts.map +1 -1
- package/dist/ai/common/HFT_ImageEmbedding.d.ts.map +1 -1
- package/dist/ai/common/HFT_ImageSegmentation.d.ts.map +1 -1
- package/dist/ai/common/HFT_ImageToText.d.ts.map +1 -1
- package/dist/ai/common/HFT_JobRunFns.d.ts +9 -9
- package/dist/ai/common/HFT_JobRunFns.d.ts.map +1 -1
- package/dist/ai/common/HFT_ModelInfo.d.ts.map +1 -1
- package/dist/ai/common/HFT_ModelSchema.d.ts +3 -3
- package/dist/ai/common/HFT_ObjectDetection.d.ts.map +1 -1
- package/dist/ai/common/HFT_Pipeline.d.ts +30 -4
- package/dist/ai/common/HFT_Pipeline.d.ts.map +1 -1
- package/dist/ai/common/HFT_Streaming.d.ts +5 -12
- package/dist/ai/common/HFT_Streaming.d.ts.map +1 -1
- package/dist/ai/common/HFT_StructuredGeneration.d.ts +1 -2
- package/dist/ai/common/HFT_StructuredGeneration.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextClassification.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextEmbedding.d.ts +4 -0
- package/dist/ai/common/HFT_TextEmbedding.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextFillMask.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextGeneration.d.ts +1 -6
- package/dist/ai/common/HFT_TextGeneration.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextLanguageDetection.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextNamedEntityRecognition.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextQuestionAnswer.d.ts +1 -6
- package/dist/ai/common/HFT_TextQuestionAnswer.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextRewriter.d.ts +1 -6
- package/dist/ai/common/HFT_TextRewriter.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextSummary.d.ts +1 -6
- package/dist/ai/common/HFT_TextSummary.d.ts.map +1 -1
- package/dist/ai/common/HFT_TextTranslation.d.ts +1 -6
- package/dist/ai/common/HFT_TextTranslation.d.ts.map +1 -1
- package/dist/ai/common/HFT_ToolCalling.d.ts +1 -2
- package/dist/ai/common/HFT_ToolCalling.d.ts.map +1 -1
- package/dist/ai/index.d.ts +53 -2
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/registerHuggingFaceTransformersInline.d.ts.map +1 -1
- package/dist/ai/registerHuggingFaceTransformersWorker.d.ts.map +1 -1
- package/dist/ai/runtime.d.ts.map +1 -1
- package/dist/ai-runtime.d.ts.map +1 -1
- package/dist/ai-runtime.js +602 -848
- package/dist/ai-runtime.js.map +37 -36
- package/dist/ai.d.ts.map +1 -1
- package/dist/ai.js +1383 -183
- package/dist/ai.js.map +37 -8
- package/package.json +12 -13
- 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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
283
|
-
|
|
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
|
-
|
|
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
|
|
311
|
-
|
|
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
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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,1350 @@ 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_FILL_MASK = ["text.fill-mask"];
|
|
740
|
+
var HFT_TEXT_NER = ["text.ner"];
|
|
741
|
+
var HFT_IMAGE_CLASSIFICATION = ["image.classification"];
|
|
742
|
+
var HFT_IMAGE_EMBEDDING = ["image.embedding"];
|
|
743
|
+
var HFT_IMAGE_SEGMENTATION = ["image.segmentation"];
|
|
744
|
+
var HFT_IMAGE_TO_TEXT = ["image.to-text"];
|
|
745
|
+
var HFT_IMAGE_BACKGROUND_REMOVAL = [
|
|
746
|
+
"image.background-removal"
|
|
747
|
+
];
|
|
748
|
+
var HFT_IMAGE_OBJECT_DETECTION = [
|
|
749
|
+
"image.object-detection"
|
|
750
|
+
];
|
|
751
|
+
var HFT_COUNT_TOKENS = ["model.count-tokens"];
|
|
752
|
+
var HFT_MODEL_DOWNLOAD_REMOVE = ["model.download-remove"];
|
|
753
|
+
var HFT_MODEL_DOWNLOAD = ["model.download"];
|
|
754
|
+
var HFT_MODEL_SEARCH = ["model.search"];
|
|
755
|
+
var HFT_MODEL_INFO = ["model.info"];
|
|
756
|
+
var HFT_CAPABILITY_SETS = [
|
|
757
|
+
HFT_TEXT_GENERATION,
|
|
758
|
+
HFT_TOOL_USE,
|
|
759
|
+
HFT_JSON_MODE,
|
|
760
|
+
HFT_TEXT_REWRITER,
|
|
761
|
+
HFT_TEXT_SUMMARY,
|
|
762
|
+
HFT_TEXT_TRANSLATION,
|
|
763
|
+
HFT_TEXT_QUESTION_ANSWERING,
|
|
764
|
+
HFT_TEXT_EMBEDDING,
|
|
765
|
+
HFT_TEXT_CLASSIFICATION,
|
|
766
|
+
HFT_TEXT_LANGUAGE_DETECTION,
|
|
767
|
+
HFT_TEXT_FILL_MASK,
|
|
768
|
+
HFT_TEXT_NER,
|
|
769
|
+
HFT_IMAGE_CLASSIFICATION,
|
|
770
|
+
HFT_IMAGE_EMBEDDING,
|
|
771
|
+
HFT_IMAGE_SEGMENTATION,
|
|
772
|
+
HFT_IMAGE_TO_TEXT,
|
|
773
|
+
HFT_IMAGE_BACKGROUND_REMOVAL,
|
|
774
|
+
HFT_IMAGE_OBJECT_DETECTION,
|
|
775
|
+
HFT_COUNT_TOKENS,
|
|
776
|
+
HFT_MODEL_DOWNLOAD_REMOVE,
|
|
777
|
+
HFT_MODEL_DOWNLOAD,
|
|
778
|
+
HFT_MODEL_SEARCH,
|
|
779
|
+
HFT_MODEL_INFO
|
|
780
|
+
];
|
|
781
|
+
|
|
782
|
+
// src/ai/common/HFT_Capabilities.ts
|
|
783
|
+
var HFT_RUN_FN_SPECS = HFT_CAPABILITY_SETS.map((serves) => ({ serves }));
|
|
784
|
+
function hftWorkerRunFnSpecs() {
|
|
785
|
+
return HFT_RUN_FN_SPECS;
|
|
786
|
+
}
|
|
787
|
+
function inferHftCapabilities(model) {
|
|
788
|
+
const declared = model.capabilities ?? [];
|
|
789
|
+
if (declared.length > 0)
|
|
790
|
+
return declared;
|
|
791
|
+
const id = String(model.model_id ?? model.provider_config?.model_path ?? model.provider_config?.model_name ?? "");
|
|
792
|
+
const pipelineTask = model.provider_config?.pipeline_task ?? "";
|
|
793
|
+
switch (pipelineTask) {
|
|
794
|
+
case "text-generation":
|
|
795
|
+
return [
|
|
796
|
+
"text.generation",
|
|
797
|
+
"text.rewriter",
|
|
798
|
+
"text.summary",
|
|
799
|
+
"tool-use",
|
|
800
|
+
"model.count-tokens",
|
|
801
|
+
"model.download-remove",
|
|
802
|
+
"model.info",
|
|
803
|
+
"model.search"
|
|
804
|
+
];
|
|
805
|
+
case "feature-extraction":
|
|
806
|
+
case "sentence-similarity":
|
|
807
|
+
return ["text.embedding", "model.download-remove", "model.info", "model.search"];
|
|
808
|
+
case "text-classification":
|
|
809
|
+
return ["text.classification", "model.download-remove", "model.info", "model.search"];
|
|
810
|
+
case "token-classification":
|
|
811
|
+
return ["text.ner", "model.download-remove", "model.info", "model.search"];
|
|
812
|
+
case "fill-mask":
|
|
813
|
+
return ["text.fill-mask", "model.download-remove", "model.info", "model.search"];
|
|
814
|
+
case "translation":
|
|
815
|
+
return ["text.translation", "model.download-remove", "model.info", "model.search"];
|
|
816
|
+
case "summarization":
|
|
817
|
+
return ["text.summary", "model.download-remove", "model.info", "model.search"];
|
|
818
|
+
case "question-answering":
|
|
819
|
+
return ["text.question-answering", "model.download-remove", "model.info", "model.search"];
|
|
820
|
+
case "image-classification":
|
|
821
|
+
return ["image.classification", "model.download-remove", "model.info", "model.search"];
|
|
822
|
+
case "image-segmentation":
|
|
823
|
+
return ["image.segmentation", "model.download-remove", "model.info", "model.search"];
|
|
824
|
+
case "image-to-text":
|
|
825
|
+
return ["image.to-text", "model.download-remove", "model.info", "model.search"];
|
|
826
|
+
case "object-detection":
|
|
827
|
+
return ["image.object-detection", "model.download-remove", "model.info", "model.search"];
|
|
828
|
+
case "zero-shot-image-classification":
|
|
829
|
+
return [
|
|
830
|
+
"image.classification",
|
|
831
|
+
"image.embedding",
|
|
832
|
+
"model.download-remove",
|
|
833
|
+
"model.info",
|
|
834
|
+
"model.search"
|
|
835
|
+
];
|
|
836
|
+
}
|
|
837
|
+
const baseName = id.split("/").pop() ?? id;
|
|
838
|
+
if (/embed|minilm|bge-|gte-|e5-/i.test(baseName)) {
|
|
839
|
+
return ["text.embedding", "model.download-remove", "model.info", "model.search"];
|
|
840
|
+
}
|
|
841
|
+
if (/clip|siglip/i.test(baseName)) {
|
|
842
|
+
return [
|
|
843
|
+
"image.classification",
|
|
844
|
+
"image.embedding",
|
|
845
|
+
"model.download-remove",
|
|
846
|
+
"model.info",
|
|
847
|
+
"model.search"
|
|
848
|
+
];
|
|
849
|
+
}
|
|
850
|
+
if (/yolo|detr|owl/i.test(baseName)) {
|
|
851
|
+
return ["image.object-detection", "model.download-remove", "model.info", "model.search"];
|
|
852
|
+
}
|
|
853
|
+
if (/sam|segformer|mask/i.test(baseName)) {
|
|
854
|
+
return ["image.segmentation", "model.download-remove", "model.info", "model.search"];
|
|
855
|
+
}
|
|
856
|
+
if (/blip|llava|vision/i.test(baseName)) {
|
|
857
|
+
return ["image.to-text", "model.download-remove", "model.info", "model.search"];
|
|
858
|
+
}
|
|
859
|
+
if (/llama|mistral|gemma|phi|qwen|tinyllama|smollm/i.test(baseName)) {
|
|
860
|
+
return [
|
|
861
|
+
"text.generation",
|
|
862
|
+
"text.rewriter",
|
|
863
|
+
"text.summary",
|
|
864
|
+
"tool-use",
|
|
865
|
+
"model.count-tokens",
|
|
866
|
+
"model.download-remove",
|
|
867
|
+
"model.info",
|
|
868
|
+
"model.search"
|
|
869
|
+
];
|
|
870
|
+
}
|
|
871
|
+
return ["model.search", "model.info"];
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// src/ai/HuggingFaceTransformersProvider.ts
|
|
875
|
+
init_HFT_Pipeline();
|
|
876
|
+
|
|
877
|
+
class HuggingFaceTransformersProvider extends AiProvider {
|
|
878
|
+
name = HF_TRANSFORMERS_ONNX;
|
|
879
|
+
displayName = "Hugging Face Transformers (ONNX)";
|
|
880
|
+
isLocal = true;
|
|
881
|
+
supportsBrowser = true;
|
|
882
|
+
constructor(promiseRunFns, previewTasks) {
|
|
883
|
+
super(promiseRunFns, previewTasks);
|
|
884
|
+
}
|
|
885
|
+
inferCapabilities(model) {
|
|
886
|
+
return inferHftCapabilities(model);
|
|
887
|
+
}
|
|
888
|
+
workerRunFnSpecs() {
|
|
889
|
+
return hftWorkerRunFnSpecs();
|
|
890
|
+
}
|
|
891
|
+
createSession(_model) {
|
|
892
|
+
return crypto.randomUUID();
|
|
893
|
+
}
|
|
894
|
+
async disposeSession(sessionId) {
|
|
895
|
+
deleteHftSession(sessionId);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
// src/ai/HuggingFaceTransformersQueuedProvider.ts
|
|
899
|
+
import { QueuedAiProvider } from "@workglow/ai";
|
|
900
|
+
init_HFT_Pipeline();
|
|
901
|
+
var GPU_DEVICES = new Set(["webgpu", "gpu", "metal"]);
|
|
902
|
+
var HFT_CPU_QUEUE_CONCURRENCY_PRODUCTION = 4;
|
|
903
|
+
function hftIsAutomatedTestEnvironment() {
|
|
904
|
+
if (typeof process === "undefined") {
|
|
905
|
+
return false;
|
|
906
|
+
}
|
|
907
|
+
const e = process.env;
|
|
908
|
+
return e.VITEST === "true" || e.NODE_ENV === "test" || e.BUN_TEST === "1" || e.JEST_WORKER_ID !== undefined;
|
|
909
|
+
}
|
|
910
|
+
function hftDefaultCpuQueueConcurrency() {
|
|
911
|
+
return hftIsAutomatedTestEnvironment() ? 1 : HFT_CPU_QUEUE_CONCURRENCY_PRODUCTION;
|
|
912
|
+
}
|
|
913
|
+
function resolveHftCpuQueueConcurrency(concurrency, defaultCpu) {
|
|
914
|
+
if (concurrency === undefined) {
|
|
915
|
+
return defaultCpu();
|
|
916
|
+
}
|
|
917
|
+
if (typeof concurrency === "number") {
|
|
918
|
+
return defaultCpu();
|
|
919
|
+
}
|
|
920
|
+
return concurrency.cpu ?? defaultCpu();
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
class HuggingFaceTransformersQueuedProvider extends QueuedAiProvider {
|
|
924
|
+
name = HF_TRANSFORMERS_ONNX;
|
|
925
|
+
displayName = "Hugging Face Transformers (ONNX)";
|
|
926
|
+
isLocal = true;
|
|
927
|
+
supportsBrowser = true;
|
|
928
|
+
cpuStrategy;
|
|
929
|
+
constructor(promiseRunFns, previewTasks) {
|
|
930
|
+
super(promiseRunFns, previewTasks);
|
|
931
|
+
}
|
|
932
|
+
inferCapabilities(model) {
|
|
933
|
+
return inferHftCapabilities(model);
|
|
934
|
+
}
|
|
935
|
+
workerRunFnSpecs() {
|
|
936
|
+
return hftWorkerRunFnSpecs();
|
|
937
|
+
}
|
|
938
|
+
createSession(_model) {
|
|
939
|
+
return crypto.randomUUID();
|
|
940
|
+
}
|
|
941
|
+
async disposeSession(sessionId) {
|
|
942
|
+
deleteHftSession(sessionId);
|
|
943
|
+
}
|
|
944
|
+
async afterRegister(options) {
|
|
945
|
+
await super.afterRegister(options);
|
|
946
|
+
this.cpuStrategy = this.createQueuedStrategy(HF_TRANSFORMERS_ONNX_CPU, resolveHftCpuQueueConcurrency(options.queue?.concurrency, hftDefaultCpuQueueConcurrency), options);
|
|
947
|
+
}
|
|
948
|
+
getStrategyForModel(model) {
|
|
949
|
+
const device = model.provider_config?.device;
|
|
950
|
+
if (device && GPU_DEVICES.has(device)) {
|
|
951
|
+
return this.queuedStrategy;
|
|
952
|
+
}
|
|
953
|
+
return this.cpuStrategy;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
// src/ai/registerHuggingFaceTransformers.ts
|
|
957
|
+
import { registerProviderWithWorker } from "@workglow/ai/provider-utils";
|
|
958
|
+
async function registerHuggingFaceTransformers(options) {
|
|
959
|
+
await registerProviderWithWorker(new HuggingFaceTransformersQueuedProvider, "HuggingFaceTransformers", options);
|
|
960
|
+
}
|
|
961
|
+
// src/ai/common/HFT_BackgroundRemoval.ts
|
|
962
|
+
init_HFT_Pipeline();
|
|
963
|
+
import { dataUriToImageValue, imageValueToBlob } from "@workglow/ai/provider-utils";
|
|
964
|
+
function rawImageToBase64Png(image) {
|
|
965
|
+
const fn = image.toBase64;
|
|
966
|
+
if (typeof fn !== "function") {
|
|
967
|
+
throw new Error("HFT_BackgroundRemoval: RawImage.toBase64 unavailable in this transformers version");
|
|
968
|
+
}
|
|
969
|
+
return fn.call(image);
|
|
970
|
+
}
|
|
971
|
+
var HFT_BackgroundRemoval = async (input, model, signal, emit) => {
|
|
972
|
+
const remover = await getPipeline(model, emit, {}, signal);
|
|
973
|
+
const imageArg = await imageValueToBlob(input.image);
|
|
974
|
+
const result = await remover(imageArg);
|
|
975
|
+
const resultImage = Array.isArray(result) ? result[0] : result;
|
|
976
|
+
const dataUri = `data:image/png;base64,${rawImageToBase64Png(resultImage)}`;
|
|
977
|
+
emit({
|
|
978
|
+
type: "finish",
|
|
979
|
+
data: {
|
|
980
|
+
image: await dataUriToImageValue(dataUri)
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
// src/ai/common/HFT_Chat.ts
|
|
986
|
+
init_HFT_Pipeline();
|
|
987
|
+
|
|
988
|
+
// src/ai/common/HFT_ToolCalling.ts
|
|
989
|
+
init_HFT_Pipeline();
|
|
990
|
+
import {
|
|
991
|
+
buildToolDescription,
|
|
992
|
+
filterValidToolCalls,
|
|
993
|
+
toTextFlatMessages
|
|
994
|
+
} from "@workglow/ai/worker";
|
|
995
|
+
import {
|
|
996
|
+
adaptParserResult,
|
|
997
|
+
forcedToolSelection,
|
|
998
|
+
getAvailableParsers,
|
|
999
|
+
getGenerationPrefix,
|
|
1000
|
+
parseToolCalls
|
|
1001
|
+
} from "@workglow/ai/provider-utils";
|
|
1002
|
+
|
|
1003
|
+
// src/ai/common/HFT_Streaming.ts
|
|
1004
|
+
function createStreamingTextStreamer(tokenizer, onText, textStreamer) {
|
|
1005
|
+
return new textStreamer(tokenizer, {
|
|
1006
|
+
skip_prompt: true,
|
|
1007
|
+
decode_kwargs: { skip_special_tokens: true },
|
|
1008
|
+
callback_function: onText
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
function createTextStreamer(tokenizer, updateProgress, textStreamer) {
|
|
1012
|
+
let count = 0;
|
|
1013
|
+
return new textStreamer(tokenizer, {
|
|
1014
|
+
skip_prompt: true,
|
|
1015
|
+
decode_kwargs: { skip_special_tokens: true },
|
|
1016
|
+
callback_function: (text) => {
|
|
1017
|
+
count++;
|
|
1018
|
+
const result = 100 * (1 - Math.exp(-0.05 * count));
|
|
1019
|
+
const progress = Math.round(Math.min(result, 100));
|
|
1020
|
+
updateProgress(progress, "Generating", { text, progress });
|
|
1021
|
+
}
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// src/ai/common/HFT_ToolCalling.ts
|
|
1026
|
+
function getModelTextCandidates(model) {
|
|
1027
|
+
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());
|
|
1028
|
+
}
|
|
1029
|
+
function detectModelFamilyFromConfig(model) {
|
|
1030
|
+
const candidates = getModelTextCandidates(model);
|
|
1031
|
+
const families = getAvailableParsers();
|
|
1032
|
+
for (const candidate of candidates) {
|
|
1033
|
+
for (const family of families) {
|
|
1034
|
+
if (candidate.includes(family)) {
|
|
1035
|
+
return family;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
return null;
|
|
1040
|
+
}
|
|
1041
|
+
function normalizeParsedToolCalls(input, toolCalls) {
|
|
1042
|
+
const forcedToolName = forcedToolSelection(input);
|
|
1043
|
+
return toolCalls.map((toolCall) => toolCall.name ? toolCall : {
|
|
1044
|
+
...toolCall,
|
|
1045
|
+
name: forcedToolName ?? toolCall.name
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
function mapHFTTools(tools) {
|
|
1049
|
+
return tools.map((t) => ({
|
|
1050
|
+
type: "function",
|
|
1051
|
+
function: {
|
|
1052
|
+
name: t.name,
|
|
1053
|
+
description: buildToolDescription(t),
|
|
1054
|
+
parameters: t.inputSchema
|
|
1055
|
+
}
|
|
1056
|
+
}));
|
|
1057
|
+
}
|
|
1058
|
+
function resolveHFTToolsAndMessages(input, messages) {
|
|
1059
|
+
if (input.toolChoice === "none") {
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
if (input.toolChoice === "required") {
|
|
1063
|
+
const requiredInstruction = "You must call at least one tool from the provided tool list when answering.";
|
|
1064
|
+
if (messages.length > 0 && messages[0].role === "system") {
|
|
1065
|
+
messages[0] = { ...messages[0], content: `${messages[0].content}
|
|
1066
|
+
|
|
1067
|
+
${requiredInstruction}` };
|
|
1068
|
+
} else {
|
|
1069
|
+
messages.unshift({ role: "system", content: requiredInstruction });
|
|
1070
|
+
}
|
|
1071
|
+
return mapHFTTools(input.tools);
|
|
1072
|
+
}
|
|
1073
|
+
if (typeof input.toolChoice === "string" && input.toolChoice !== "auto") {
|
|
1074
|
+
const selectedTools = input.tools?.filter((tool) => tool.name === input.toolChoice);
|
|
1075
|
+
const toolsToMap = selectedTools && selectedTools.length > 0 ? selectedTools : input.tools;
|
|
1076
|
+
return mapHFTTools(toolsToMap);
|
|
1077
|
+
}
|
|
1078
|
+
return mapHFTTools(input.tools);
|
|
1079
|
+
}
|
|
1080
|
+
function buildHFTMessages(messages, systemPrompt, prompt, toolChoice) {
|
|
1081
|
+
const out = [];
|
|
1082
|
+
if (systemPrompt) {
|
|
1083
|
+
out.push({ role: "system", content: systemPrompt });
|
|
1084
|
+
}
|
|
1085
|
+
if (toolChoice === "required") {
|
|
1086
|
+
out.push({
|
|
1087
|
+
role: "system",
|
|
1088
|
+
content: "You MUST call one of the provided tools in this turn."
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
if (!messages || messages.length === 0) {
|
|
1092
|
+
out.push({ role: "user", content: extractPromptText(prompt) });
|
|
1093
|
+
return out;
|
|
1094
|
+
}
|
|
1095
|
+
for (const msg of messages) {
|
|
1096
|
+
if (msg.role === "user") {
|
|
1097
|
+
const text = msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
1098
|
+
out.push({ role: "user", content: text });
|
|
1099
|
+
} else if (msg.role === "assistant") {
|
|
1100
|
+
const text = msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
1101
|
+
const toolCalls = msg.content.filter((b) => b.type === "tool_use").map((b) => {
|
|
1102
|
+
const tu = b;
|
|
1103
|
+
return { id: tu.id, name: tu.name, arguments: tu.input };
|
|
1104
|
+
});
|
|
1105
|
+
const entry = { role: "assistant", content: text };
|
|
1106
|
+
if (toolCalls.length > 0)
|
|
1107
|
+
entry.tool_calls = toolCalls;
|
|
1108
|
+
out.push(entry);
|
|
1109
|
+
} else if (msg.role === "tool") {
|
|
1110
|
+
for (const b of msg.content) {
|
|
1111
|
+
if (b.type !== "tool_result")
|
|
1112
|
+
continue;
|
|
1113
|
+
const text = b.content.filter((inner) => inner.type === "text").map((inner) => inner.text).join("");
|
|
1114
|
+
out.push({
|
|
1115
|
+
role: "tool",
|
|
1116
|
+
content: text,
|
|
1117
|
+
tool_call_id: b.tool_use_id
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
return out;
|
|
1123
|
+
}
|
|
1124
|
+
function extractPromptText(prompt) {
|
|
1125
|
+
if (typeof prompt === "string")
|
|
1126
|
+
return prompt;
|
|
1127
|
+
if (!Array.isArray(prompt))
|
|
1128
|
+
return String(prompt ?? "");
|
|
1129
|
+
return prompt.map((item) => {
|
|
1130
|
+
if (typeof item === "string")
|
|
1131
|
+
return item;
|
|
1132
|
+
if (item && typeof item === "object" && item.type === "text") {
|
|
1133
|
+
return item.text;
|
|
1134
|
+
}
|
|
1135
|
+
return "";
|
|
1136
|
+
}).filter((s) => s).join(`
|
|
1137
|
+
`);
|
|
1138
|
+
}
|
|
1139
|
+
function selectHFTTools(input) {
|
|
1140
|
+
if (input.toolChoice === "none")
|
|
1141
|
+
return;
|
|
1142
|
+
if (typeof input.toolChoice === "string" && input.toolChoice !== "auto" && input.toolChoice !== "required") {
|
|
1143
|
+
const selected = input.tools.filter((t) => t.name === input.toolChoice);
|
|
1144
|
+
return mapHFTTools(selected.length > 0 ? selected : input.tools);
|
|
1145
|
+
}
|
|
1146
|
+
return mapHFTTools(input.tools);
|
|
1147
|
+
}
|
|
1148
|
+
function hasToolMessages(input) {
|
|
1149
|
+
return input.messages?.some((m) => m.role === "tool") ?? false;
|
|
1150
|
+
}
|
|
1151
|
+
function buildPromptAndPrefix(tokenizer, input, modelFamily) {
|
|
1152
|
+
let basePrompt;
|
|
1153
|
+
if (hasToolMessages(input)) {
|
|
1154
|
+
const messages = buildHFTMessages(input.messages, input.systemPrompt, input.prompt, input.toolChoice);
|
|
1155
|
+
const tools = selectHFTTools(input);
|
|
1156
|
+
basePrompt = tokenizer.apply_chat_template(messages, {
|
|
1157
|
+
tools,
|
|
1158
|
+
tokenize: false,
|
|
1159
|
+
add_generation_prompt: true
|
|
1160
|
+
});
|
|
1161
|
+
} else {
|
|
1162
|
+
const messages = toTextFlatMessages(input);
|
|
1163
|
+
const tools = resolveHFTToolsAndMessages(input, messages);
|
|
1164
|
+
basePrompt = tokenizer.apply_chat_template(messages, {
|
|
1165
|
+
tools,
|
|
1166
|
+
tokenize: false,
|
|
1167
|
+
add_generation_prompt: true
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
const responsePrefix = input.toolChoice === "none" || hasToolMessages(input) ? undefined : getGenerationPrefix(modelFamily, forcedToolSelection(input));
|
|
1171
|
+
return {
|
|
1172
|
+
prompt: responsePrefix ? `${basePrompt}${responsePrefix}` : basePrompt,
|
|
1173
|
+
responsePrefix
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
var HFT_ToolCalling = async (input, model, signal, emit, _outputSchema, sessionId) => {
|
|
1177
|
+
const generateText = await getPipeline(model, emit, {}, signal);
|
|
1178
|
+
const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
|
|
1179
|
+
const modelFamily = detectModelFamilyFromConfig(model);
|
|
1180
|
+
const { prompt, responsePrefix } = buildPromptAndPrefix(generateText.tokenizer, input, modelFamily);
|
|
1181
|
+
let fullText = "";
|
|
1182
|
+
const filter = createToolCallMarkupFilter((text) => {
|
|
1183
|
+
emit({ type: "text-delta", port: "text", textDelta: text });
|
|
1184
|
+
});
|
|
1185
|
+
const streamer = createStreamingTextStreamer(generateText.tokenizer, (text) => {
|
|
1186
|
+
fullText += text;
|
|
1187
|
+
filter.feed(text);
|
|
1188
|
+
}, TextStreamer);
|
|
1189
|
+
const stopping_criteria = new InterruptableStoppingCriteria;
|
|
1190
|
+
if (signal) {
|
|
1191
|
+
signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
|
|
1192
|
+
}
|
|
1193
|
+
const modelPath = model.provider_config.model_path;
|
|
1194
|
+
let session = sessionId ? getHftSession(sessionId) : undefined;
|
|
1195
|
+
let past_key_values = undefined;
|
|
1196
|
+
if (sessionId && !session) {
|
|
1197
|
+
const { DynamicCache } = await loadTransformersSDK();
|
|
1198
|
+
const hfModel = generateText.model;
|
|
1199
|
+
const hfTokenizer = generateText.tokenizer;
|
|
1200
|
+
const cache = new DynamicCache;
|
|
1201
|
+
const tokenized = hfTokenizer(prompt);
|
|
1202
|
+
await hfModel.generate({
|
|
1203
|
+
...tokenized,
|
|
1204
|
+
max_new_tokens: 0,
|
|
1205
|
+
past_key_values: cache
|
|
1206
|
+
});
|
|
1207
|
+
const baseEntries = {};
|
|
1208
|
+
for (const key of Object.keys(cache)) {
|
|
1209
|
+
baseEntries[key] = cache[key];
|
|
1210
|
+
}
|
|
1211
|
+
const newSession = {
|
|
1212
|
+
mode: "prefix-rewind",
|
|
1213
|
+
baseEntries,
|
|
1214
|
+
baseSeqLength: cache.get_seq_length(),
|
|
1215
|
+
modelPath
|
|
1216
|
+
};
|
|
1217
|
+
setHftSession(sessionId, newSession);
|
|
1218
|
+
session = newSession;
|
|
1219
|
+
}
|
|
1220
|
+
if (session?.mode === "prefix-rewind") {
|
|
1221
|
+
const { DynamicCache } = await loadTransformersSDK();
|
|
1222
|
+
past_key_values = new DynamicCache(session.baseEntries);
|
|
1223
|
+
}
|
|
1224
|
+
try {
|
|
1225
|
+
await generateText(prompt, {
|
|
1226
|
+
max_new_tokens: input.maxTokens ?? 1024,
|
|
1227
|
+
temperature: input.temperature ?? undefined,
|
|
1228
|
+
return_full_text: false,
|
|
1229
|
+
streamer,
|
|
1230
|
+
stopping_criteria: [stopping_criteria],
|
|
1231
|
+
...past_key_values ? { past_key_values } : {}
|
|
1232
|
+
});
|
|
1233
|
+
} finally {
|
|
1234
|
+
filter.flush();
|
|
1235
|
+
}
|
|
1236
|
+
const parseableFullText = responsePrefix ? `${responsePrefix}${fullText}` : fullText;
|
|
1237
|
+
const { text: cleanedText, toolCalls } = adaptParserResult(parseToolCalls(parseableFullText, { parser: modelFamily }));
|
|
1238
|
+
const validToolCalls = filterValidToolCalls(normalizeParsedToolCalls(input, toolCalls), input.tools);
|
|
1239
|
+
if (validToolCalls.length > 0) {
|
|
1240
|
+
emit({ type: "object-delta", port: "toolCalls", objectDelta: [...validToolCalls] });
|
|
1241
|
+
}
|
|
1242
|
+
emit({
|
|
1243
|
+
type: "finish",
|
|
1244
|
+
data: { text: cleanedText, toolCalls: validToolCalls }
|
|
1245
|
+
});
|
|
1246
|
+
};
|
|
1247
|
+
|
|
1248
|
+
// src/ai/common/HFT_Chat.ts
|
|
1249
|
+
async function generateTurn(input, model, sessionId, emit, signal, onDelta) {
|
|
1250
|
+
const generateText = await getPipeline(model, emit, {}, signal);
|
|
1251
|
+
const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
|
|
1252
|
+
const hfTokenizer = generateText.tokenizer;
|
|
1253
|
+
const hfModel = generateText.model;
|
|
1254
|
+
const stopping_criteria = new InterruptableStoppingCriteria;
|
|
1255
|
+
if (signal) {
|
|
1256
|
+
signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
|
|
1257
|
+
}
|
|
1258
|
+
const messages = buildHFTMessages(input.messages, input.systemPrompt, input.prompt, undefined);
|
|
1259
|
+
const prompt = hfTokenizer.apply_chat_template(messages, {
|
|
1260
|
+
tokenize: false,
|
|
1261
|
+
add_generation_prompt: true
|
|
1262
|
+
});
|
|
1263
|
+
const inputs = hfTokenizer(prompt);
|
|
1264
|
+
const promptLen = inputs.input_ids.dims[1];
|
|
1265
|
+
const modelPath = model.provider_config.model_path;
|
|
1266
|
+
let session = sessionId ? getHftSession(sessionId) : undefined;
|
|
1267
|
+
let past_key_values = undefined;
|
|
1268
|
+
if (session?.mode === "prefix-rewind" && session.modelPath === modelPath) {
|
|
1269
|
+
const { DynamicCache } = await loadTransformersSDK();
|
|
1270
|
+
past_key_values = new DynamicCache(session.baseEntries);
|
|
1271
|
+
}
|
|
1272
|
+
let accumulated = "";
|
|
1273
|
+
let streamer;
|
|
1274
|
+
if (onDelta) {
|
|
1275
|
+
streamer = createStreamingTextStreamer(hfTokenizer, (text) => {
|
|
1276
|
+
accumulated += text;
|
|
1277
|
+
onDelta(text);
|
|
1278
|
+
}, TextStreamer);
|
|
1279
|
+
} else {
|
|
1280
|
+
streamer = createTextStreamer(hfTokenizer, (progress, message) => emit({ type: "phase", message: message ?? "", progress }), TextStreamer);
|
|
1281
|
+
}
|
|
1282
|
+
const output = await hfModel.generate({
|
|
1283
|
+
...inputs,
|
|
1284
|
+
max_new_tokens: input.maxTokens ?? 1024,
|
|
1285
|
+
temperature: input.temperature ?? undefined,
|
|
1286
|
+
streamer,
|
|
1287
|
+
stopping_criteria: [stopping_criteria],
|
|
1288
|
+
...past_key_values ? { past_key_values } : {}
|
|
1289
|
+
});
|
|
1290
|
+
if (!onDelta) {
|
|
1291
|
+
const seqLen = output.dims[1];
|
|
1292
|
+
const newTokens = output.slice(0, [promptLen, seqLen], null);
|
|
1293
|
+
accumulated = hfTokenizer.decode(newTokens, { skip_special_tokens: true });
|
|
1294
|
+
}
|
|
1295
|
+
if (sessionId) {
|
|
1296
|
+
let outputCache;
|
|
1297
|
+
if (past_key_values) {
|
|
1298
|
+
outputCache = past_key_values;
|
|
1299
|
+
} else if (output.past_key_values) {
|
|
1300
|
+
outputCache = output.past_key_values;
|
|
1301
|
+
}
|
|
1302
|
+
if (outputCache) {
|
|
1303
|
+
const baseEntries = {};
|
|
1304
|
+
for (const key of Object.keys(outputCache)) {
|
|
1305
|
+
baseEntries[key] = outputCache[key];
|
|
1306
|
+
}
|
|
1307
|
+
const newSession = {
|
|
1308
|
+
mode: "prefix-rewind",
|
|
1309
|
+
baseEntries,
|
|
1310
|
+
baseSeqLength: outputCache.get_seq_length ? outputCache.get_seq_length() : 0,
|
|
1311
|
+
modelPath
|
|
1312
|
+
};
|
|
1313
|
+
setHftSession(sessionId, newSession);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
return accumulated;
|
|
1317
|
+
}
|
|
1318
|
+
var HFT_Chat = async (input, model, signal, emit, _outputSchema, sessionId) => {
|
|
1319
|
+
await generateTurn(input, model, sessionId, emit, signal, (piece) => {
|
|
1320
|
+
emit({ type: "text-delta", port: "text", textDelta: piece });
|
|
1321
|
+
});
|
|
1322
|
+
emit({ type: "finish", data: {} });
|
|
1323
|
+
};
|
|
1324
|
+
|
|
1325
|
+
// src/ai/common/HFT_CountTokens.ts
|
|
1326
|
+
init_HFT_Pipeline();
|
|
1327
|
+
async function countTokens(input, model) {
|
|
1328
|
+
const { AutoTokenizer } = await loadTransformersSDK();
|
|
1329
|
+
const tokenizer = await AutoTokenizer.from_pretrained(model.provider_config.model_path, {});
|
|
1330
|
+
const tokenIds = tokenizer.encode(input.text);
|
|
1331
|
+
return { count: tokenIds.length };
|
|
1332
|
+
}
|
|
1333
|
+
var HFT_CountTokens = async (input, model, _signal, emit) => {
|
|
1334
|
+
const data = await countTokens(input, model);
|
|
1335
|
+
emit({ type: "finish", data });
|
|
1336
|
+
};
|
|
1337
|
+
var HFT_CountTokens_Preview = async (input, model) => {
|
|
1338
|
+
return countTokens(input, model);
|
|
1339
|
+
};
|
|
1340
|
+
|
|
1341
|
+
// src/ai/common/HFT_Download.ts
|
|
1342
|
+
init_HFT_Pipeline();
|
|
1343
|
+
import { getLogger as getLogger2 } from "@workglow/util/worker";
|
|
1344
|
+
var HFT_Download = async (input, model, signal, emit) => {
|
|
1345
|
+
const logger = getLogger2();
|
|
1346
|
+
const timerLabel = `hft:Download:${model?.provider_config.model_path}`;
|
|
1347
|
+
logger.time(timerLabel, { model: model?.provider_config.model_path });
|
|
1348
|
+
await getPipeline(model, emit, {}, signal, 100);
|
|
1349
|
+
logger.timeEnd(timerLabel, { model: model?.provider_config.model_path });
|
|
1350
|
+
emit({ type: "finish", data: { model: input.model } });
|
|
1351
|
+
};
|
|
1352
|
+
|
|
1353
|
+
// src/ai/common/HFT_DownloadRemove.ts
|
|
1354
|
+
init_HFT_Pipeline();
|
|
1355
|
+
function hasBrowserCacheStorage() {
|
|
1356
|
+
return typeof globalThis !== "undefined" && "caches" in globalThis && typeof globalThis.caches?.open === "function";
|
|
1357
|
+
}
|
|
1358
|
+
async function deleteModelCacheFromBrowser(model_path) {
|
|
1359
|
+
const cachesApi = globalThis.caches;
|
|
1360
|
+
const cache = await cachesApi.open(HTF_CACHE_NAME);
|
|
1361
|
+
const keys = await cache.keys();
|
|
1362
|
+
const prefix = `/${model_path}/`;
|
|
1363
|
+
const requestsToDelete = [];
|
|
1364
|
+
for (const request of keys) {
|
|
1365
|
+
const url = new URL(request.url);
|
|
1366
|
+
if (url.pathname.startsWith(prefix)) {
|
|
1367
|
+
requestsToDelete.push(request);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
for (const request of requestsToDelete) {
|
|
1371
|
+
try {
|
|
1372
|
+
const deleted = await cache.delete(request);
|
|
1373
|
+
if (!deleted) {
|
|
1374
|
+
const deletedByUrl = await cache.delete(request.url);
|
|
1375
|
+
if (!deletedByUrl) {}
|
|
1376
|
+
}
|
|
1377
|
+
} catch (error) {
|
|
1378
|
+
console.error(`Failed to delete cache entry: ${request.url}`, error);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
async function deleteModelCacheFromFilesystem(model) {
|
|
1383
|
+
const { ModelRegistry } = await loadTransformersSDK();
|
|
1384
|
+
const { pipeline: pipelineType, model_path, dtype } = model.provider_config;
|
|
1385
|
+
await ModelRegistry.clear_pipeline_cache(pipelineType, model_path, {
|
|
1386
|
+
...dtype ? { dtype } : {}
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
var HFT_DownloadRemove = async (input, model, _signal, emit) => {
|
|
1390
|
+
const cacheKey = getPipelineCacheKey(model);
|
|
1391
|
+
await removeCachedPipeline(cacheKey);
|
|
1392
|
+
const model_path = model.provider_config.model_path;
|
|
1393
|
+
disposeHftSessionsForModel(model_path);
|
|
1394
|
+
if (hasBrowserCacheStorage()) {
|
|
1395
|
+
await deleteModelCacheFromBrowser(model_path);
|
|
1396
|
+
} else {
|
|
1397
|
+
await deleteModelCacheFromFilesystem(model);
|
|
1398
|
+
}
|
|
1399
|
+
emit({ type: "finish", data: { model: input.model } });
|
|
1400
|
+
};
|
|
1401
|
+
|
|
1402
|
+
// src/ai/common/HFT_ImageClassification.ts
|
|
1403
|
+
init_HFT_Pipeline();
|
|
1404
|
+
import { imageValueToBlob as imageValueToBlob2 } from "@workglow/ai/provider-utils";
|
|
1405
|
+
var HFT_ImageClassification = async (input, model, signal, emit) => {
|
|
1406
|
+
if (model?.provider_config?.pipeline === "zero-shot-image-classification") {
|
|
1407
|
+
if (!input.categories || !Array.isArray(input.categories) || input.categories.length === 0) {
|
|
1408
|
+
console.warn("Zero-shot image classification requires categories", input);
|
|
1409
|
+
throw new Error("Zero-shot image classification requires categories");
|
|
1410
|
+
}
|
|
1411
|
+
const zeroShotClassifier = await getPipeline(model, emit, {}, signal);
|
|
1412
|
+
const imageArg2 = await imageValueToBlob2(input.image);
|
|
1413
|
+
const result2 = await zeroShotClassifier(imageArg2, input.categories, {});
|
|
1414
|
+
const results2 = Array.isArray(result2) ? result2 : [result2];
|
|
1415
|
+
emit({
|
|
1416
|
+
type: "finish",
|
|
1417
|
+
data: {
|
|
1418
|
+
categories: results2.map((r) => ({
|
|
1419
|
+
label: r.label,
|
|
1420
|
+
score: r.score
|
|
1421
|
+
}))
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
return;
|
|
1425
|
+
}
|
|
1426
|
+
const classifier = await getPipeline(model, emit, {}, signal);
|
|
1427
|
+
const imageArg = await imageValueToBlob2(input.image);
|
|
1428
|
+
const result = await classifier(imageArg, {
|
|
1429
|
+
top_k: input.maxCategories
|
|
1430
|
+
});
|
|
1431
|
+
const results = Array.isArray(result) ? result : [result];
|
|
1432
|
+
emit({
|
|
1433
|
+
type: "finish",
|
|
1434
|
+
data: {
|
|
1435
|
+
categories: results.map((r) => ({
|
|
1436
|
+
label: r.label,
|
|
1437
|
+
score: r.score
|
|
1438
|
+
}))
|
|
1439
|
+
}
|
|
1440
|
+
});
|
|
1441
|
+
};
|
|
1442
|
+
|
|
1443
|
+
// src/ai/common/HFT_ImageEmbedding.ts
|
|
1444
|
+
init_HFT_Pipeline();
|
|
1445
|
+
import { getLogger as getLogger3 } from "@workglow/util/worker";
|
|
1446
|
+
import { imageValueToBlob as imageValueToBlob3 } from "@workglow/ai/provider-utils";
|
|
1447
|
+
var HFT_ImageEmbedding = async (input, model, signal, emit) => {
|
|
1448
|
+
const logger = getLogger3();
|
|
1449
|
+
const timerLabel = `hft:ImageEmbedding:${model?.provider_config.model_path}`;
|
|
1450
|
+
logger.time(timerLabel, { model: model?.provider_config.model_path });
|
|
1451
|
+
const embedder = await getPipeline(model, emit, {}, signal);
|
|
1452
|
+
logger.debug("HFT ImageEmbedding: pipeline ready, generating embedding", {
|
|
1453
|
+
model: model?.provider_config.model_path
|
|
1454
|
+
});
|
|
1455
|
+
if (Array.isArray(input.image)) {
|
|
1456
|
+
const vectors = [];
|
|
1457
|
+
for (const image of input.image) {
|
|
1458
|
+
const imageArg2 = await imageValueToBlob3(image);
|
|
1459
|
+
const result2 = await embedder(imageArg2);
|
|
1460
|
+
vectors.push(result2.data);
|
|
1461
|
+
}
|
|
1462
|
+
logger.timeEnd(timerLabel, { count: vectors.length });
|
|
1463
|
+
emit({ type: "finish", data: { vector: vectors } });
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
const imageArg = await imageValueToBlob3(input.image);
|
|
1467
|
+
const result = await embedder(imageArg);
|
|
1468
|
+
logger.timeEnd(timerLabel, { dimensions: result?.data?.length });
|
|
1469
|
+
emit({
|
|
1470
|
+
type: "finish",
|
|
1471
|
+
data: { vector: result.data }
|
|
1472
|
+
});
|
|
1473
|
+
};
|
|
1474
|
+
|
|
1475
|
+
// src/ai/common/HFT_ImageSegmentation.ts
|
|
1476
|
+
init_HFT_Pipeline();
|
|
1477
|
+
import { imageValueToBlob as imageValueToBlob4 } from "@workglow/ai/provider-utils";
|
|
1478
|
+
var HFT_ImageSegmentation = async (input, model, signal, emit) => {
|
|
1479
|
+
const segmenter = await getPipeline(model, emit, {}, signal);
|
|
1480
|
+
const imageArg = await imageValueToBlob4(input.image);
|
|
1481
|
+
const result = await segmenter(imageArg, {
|
|
1482
|
+
threshold: input.threshold,
|
|
1483
|
+
mask_threshold: input.maskThreshold
|
|
1484
|
+
});
|
|
1485
|
+
const masks = Array.isArray(result) ? result : [result];
|
|
1486
|
+
const processedMasks = await Promise.all(masks.map(async (mask) => ({
|
|
1487
|
+
label: mask.label || "",
|
|
1488
|
+
score: mask.score || 0,
|
|
1489
|
+
mask: {}
|
|
1490
|
+
})));
|
|
1491
|
+
emit({
|
|
1492
|
+
type: "finish",
|
|
1493
|
+
data: {
|
|
1494
|
+
masks: processedMasks
|
|
1495
|
+
}
|
|
1496
|
+
});
|
|
1497
|
+
};
|
|
1498
|
+
|
|
1499
|
+
// src/ai/common/HFT_ImageToText.ts
|
|
1500
|
+
init_HFT_Pipeline();
|
|
1501
|
+
import { imageValueToBlob as imageValueToBlob5 } from "@workglow/ai/provider-utils";
|
|
1502
|
+
var HFT_ImageToText = async (input, model, signal, emit) => {
|
|
1503
|
+
const captioner = await getPipeline(model, emit, {}, signal);
|
|
1504
|
+
const imageArg = await imageValueToBlob5(input.image);
|
|
1505
|
+
const result = await captioner(imageArg, {
|
|
1506
|
+
max_new_tokens: input.maxTokens
|
|
1507
|
+
});
|
|
1508
|
+
const text = Array.isArray(result[0]) ? result[0][0]?.generated_text : result[0]?.generated_text;
|
|
1509
|
+
emit({
|
|
1510
|
+
type: "finish",
|
|
1511
|
+
data: {
|
|
1512
|
+
text: text || ""
|
|
1513
|
+
}
|
|
1514
|
+
});
|
|
1515
|
+
};
|
|
1516
|
+
|
|
1517
|
+
// src/ai/common/HFT_ModelInfo.ts
|
|
1518
|
+
import { getLogger as getLogger4 } from "@workglow/util/worker";
|
|
1519
|
+
init_HFT_Pipeline();
|
|
1520
|
+
var HFT_ModelInfo = async (input, model, _signal, emit) => {
|
|
1521
|
+
if (input.detail === "dimensions") {
|
|
1522
|
+
if (!model)
|
|
1523
|
+
throw new Error("Model config is required for ModelInfoTask.");
|
|
1524
|
+
const pc = model.provider_config;
|
|
1525
|
+
let native_dimensions = typeof pc.native_dimensions === "number" ? pc.native_dimensions : undefined;
|
|
1526
|
+
const mrl = typeof pc.mrl === "boolean" ? pc.mrl : false;
|
|
1527
|
+
if (native_dimensions === undefined && typeof pc.model_path === "string") {
|
|
1528
|
+
try {
|
|
1529
|
+
const response = await fetch(`https://huggingface.co/${pc.model_path}/resolve/${pc.revision ?? "main"}/config.json`);
|
|
1530
|
+
if (response.ok) {
|
|
1531
|
+
const config = await response.json();
|
|
1532
|
+
if (typeof config.hidden_size === "number") {
|
|
1533
|
+
native_dimensions = config.hidden_size;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
} catch {}
|
|
1537
|
+
}
|
|
1538
|
+
emit({
|
|
1539
|
+
type: "finish",
|
|
1540
|
+
data: {
|
|
1541
|
+
model: input.model,
|
|
1542
|
+
is_local: true,
|
|
1543
|
+
is_remote: false,
|
|
1544
|
+
supports_browser: true,
|
|
1545
|
+
supports_node: true,
|
|
1546
|
+
is_cached: false,
|
|
1547
|
+
is_loaded: false,
|
|
1548
|
+
file_sizes: null,
|
|
1549
|
+
...native_dimensions !== undefined ? { native_dimensions } : {},
|
|
1550
|
+
...mrl ? { mrl } : {}
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
const logger = getLogger4();
|
|
1556
|
+
const { ModelRegistry } = await loadTransformersSDK();
|
|
1557
|
+
const timerLabel = `hft:ModelInfo:${model?.provider_config.model_path}`;
|
|
1558
|
+
logger.time(timerLabel, { model: model?.provider_config.model_path });
|
|
1559
|
+
const detail = input.detail;
|
|
1560
|
+
const is_loaded = hasCachedPipeline(getPipelineCacheKey(model));
|
|
1561
|
+
const { pipeline: pipelineType, model_path, dtype, device } = model.provider_config;
|
|
1562
|
+
const cacheOptions = {
|
|
1563
|
+
...dtype ? { dtype } : {},
|
|
1564
|
+
...device ? { device } : {}
|
|
1565
|
+
};
|
|
1566
|
+
const cacheStatus = await ModelRegistry.is_pipeline_cached_files(pipelineType, model_path, cacheOptions);
|
|
1567
|
+
logger.debug("is_pipeline_cached", {
|
|
1568
|
+
input: [pipelineType, model_path, cacheOptions],
|
|
1569
|
+
result: cacheStatus
|
|
1570
|
+
});
|
|
1571
|
+
const is_cached = is_loaded || cacheStatus.allCached;
|
|
1572
|
+
let file_sizes = null;
|
|
1573
|
+
if (detail === "files" && cacheStatus.files.length > 0) {
|
|
1574
|
+
const sizes = {};
|
|
1575
|
+
for (const { file } of cacheStatus.files) {
|
|
1576
|
+
sizes[file] = 0;
|
|
1577
|
+
}
|
|
1578
|
+
file_sizes = sizes;
|
|
1579
|
+
} else if (detail === "files_with_metadata" && cacheStatus.files.length > 0) {
|
|
1580
|
+
const sizes = {};
|
|
1581
|
+
await Promise.all(cacheStatus.files.map(async ({ file }) => {
|
|
1582
|
+
const metadata = await ModelRegistry.get_file_metadata(model_path, file);
|
|
1583
|
+
if (metadata.exists && metadata.size !== undefined) {
|
|
1584
|
+
sizes[file] = metadata.size;
|
|
1585
|
+
}
|
|
1586
|
+
}));
|
|
1587
|
+
if (Object.keys(sizes).length > 0) {
|
|
1588
|
+
file_sizes = sizes;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
let quantizations;
|
|
1592
|
+
if (cacheStatus.files.length > 0) {
|
|
1593
|
+
const filePaths = cacheStatus.files.map((f) => f.file);
|
|
1594
|
+
const quantizations_parsed = parseOnnxQuantizations({ filePaths });
|
|
1595
|
+
if (quantizations_parsed.length > 0) {
|
|
1596
|
+
quantizations = quantizations_parsed;
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
logger.timeEnd(timerLabel, { model: model?.provider_config.model_path });
|
|
1600
|
+
emit({
|
|
1601
|
+
type: "finish",
|
|
1602
|
+
data: {
|
|
1603
|
+
model: input.model,
|
|
1604
|
+
is_local: true,
|
|
1605
|
+
is_remote: false,
|
|
1606
|
+
supports_browser: true,
|
|
1607
|
+
supports_node: true,
|
|
1608
|
+
is_cached,
|
|
1609
|
+
is_loaded,
|
|
1610
|
+
file_sizes,
|
|
1611
|
+
...quantizations ? { quantizations } : {}
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1614
|
+
};
|
|
1615
|
+
|
|
1616
|
+
// src/ai/common/HFT_ModelSearch.ts
|
|
1617
|
+
import { searchHfModels, mapHfModelResult } from "@workglow/ai/provider-utils";
|
|
1618
|
+
var HFT_ModelSearch = async (input, _model, signal, emit) => {
|
|
1619
|
+
const entries = await searchHfModels(input.query?.trim() ?? "", { filter: "onnx" }, ["siblings"], signal);
|
|
1620
|
+
const results = entries.map((entry) => {
|
|
1621
|
+
const item = mapHfModelResult(entry, HF_TRANSFORMERS_ONNX);
|
|
1622
|
+
if (entry.siblings && entry.siblings.length > 0) {
|
|
1623
|
+
const filePaths = entry.siblings.map((s) => s.rfilename);
|
|
1624
|
+
const quantizations = parseOnnxQuantizations({ filePaths });
|
|
1625
|
+
if (quantizations.length > 0) {
|
|
1626
|
+
const record = item.record;
|
|
1627
|
+
const providerConfig = record.provider_config ?? {};
|
|
1628
|
+
providerConfig.quantizations = quantizations;
|
|
1629
|
+
record.provider_config = providerConfig;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
const raw = item.raw;
|
|
1633
|
+
delete raw.siblings;
|
|
1634
|
+
return item;
|
|
1635
|
+
});
|
|
1636
|
+
emit({ type: "finish", data: { results } });
|
|
1637
|
+
};
|
|
1638
|
+
|
|
1639
|
+
// src/ai/common/HFT_ObjectDetection.ts
|
|
1640
|
+
init_HFT_Pipeline();
|
|
1641
|
+
import { imageValueToBlob as imageValueToBlob6 } from "@workglow/ai/provider-utils";
|
|
1642
|
+
var HFT_ObjectDetection = async (input, model, signal, emit) => {
|
|
1643
|
+
if (model?.provider_config?.pipeline === "zero-shot-object-detection") {
|
|
1644
|
+
if (!input.labels || !Array.isArray(input.labels) || input.labels.length === 0) {
|
|
1645
|
+
throw new Error("Zero-shot object detection requires labels");
|
|
1646
|
+
}
|
|
1647
|
+
const zeroShotDetector = await getPipeline(model, emit, {}, signal);
|
|
1648
|
+
const imageArg2 = await imageValueToBlob6(input.image);
|
|
1649
|
+
const result = await zeroShotDetector(imageArg2, Array.from(input.labels), {
|
|
1650
|
+
threshold: input.threshold
|
|
1651
|
+
});
|
|
1652
|
+
emit({
|
|
1653
|
+
type: "finish",
|
|
1654
|
+
data: {
|
|
1655
|
+
detections: result.map((d) => ({
|
|
1656
|
+
label: d.label,
|
|
1657
|
+
score: d.score,
|
|
1658
|
+
box: d.box
|
|
1659
|
+
}))
|
|
1660
|
+
}
|
|
1661
|
+
});
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
const detector = await getPipeline(model, emit, {}, signal);
|
|
1665
|
+
const imageArg = await imageValueToBlob6(input.image);
|
|
1666
|
+
const detections = await detector(imageArg, {
|
|
1667
|
+
threshold: input.threshold
|
|
1668
|
+
});
|
|
1669
|
+
emit({
|
|
1670
|
+
type: "finish",
|
|
1671
|
+
data: {
|
|
1672
|
+
detections: detections.map((d) => ({
|
|
1673
|
+
label: d.label,
|
|
1674
|
+
score: d.score,
|
|
1675
|
+
box: d.box
|
|
1676
|
+
}))
|
|
1677
|
+
}
|
|
1678
|
+
});
|
|
1679
|
+
};
|
|
1680
|
+
|
|
1681
|
+
// src/ai/common/HFT_StructuredGeneration.ts
|
|
1682
|
+
init_HFT_Pipeline();
|
|
1683
|
+
import { parsePartialJson } from "@workglow/util/worker";
|
|
1684
|
+
function buildStructuredGenerationPrompt(input) {
|
|
1685
|
+
const schemaStr = JSON.stringify(input.outputSchema, null, 2);
|
|
1686
|
+
return `${input.prompt}
|
|
1687
|
+
|
|
1688
|
+
` + `You MUST respond with ONLY a valid JSON object conforming to this JSON schema:
|
|
1689
|
+
${schemaStr}
|
|
1690
|
+
|
|
1691
|
+
` + `Output ONLY the JSON object, no other text.`;
|
|
1692
|
+
}
|
|
1693
|
+
function stripThinkingAndSpecialTokens(text) {
|
|
1694
|
+
return text.replace(/<think>[\s\S]*?<\/think>/g, "").replace(/<\|[a-z_]+\|>/g, "").trim();
|
|
1695
|
+
}
|
|
1696
|
+
function extractJsonFromText(text) {
|
|
1697
|
+
const cleaned = stripThinkingAndSpecialTokens(text);
|
|
1698
|
+
try {
|
|
1699
|
+
return JSON.parse(cleaned);
|
|
1700
|
+
} catch {
|
|
1701
|
+
const match = cleaned.match(/\{[\s\S]*\}/);
|
|
1702
|
+
if (match) {
|
|
1703
|
+
try {
|
|
1704
|
+
return JSON.parse(match[0]);
|
|
1705
|
+
} catch {
|
|
1706
|
+
return parsePartialJson(match[0]) ?? {};
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
return {};
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
var HFT_StructuredGeneration = async (input, model, signal, emit) => {
|
|
1713
|
+
const generateText = await getPipeline(model, emit, {}, signal);
|
|
1714
|
+
const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
|
|
1715
|
+
const prompt = buildStructuredGenerationPrompt(input);
|
|
1716
|
+
const messages = [{ role: "user", content: prompt }];
|
|
1717
|
+
const formattedPrompt = generateText.tokenizer.apply_chat_template(messages, {
|
|
1718
|
+
tokenize: false,
|
|
1719
|
+
add_generation_prompt: true
|
|
1720
|
+
});
|
|
1721
|
+
let fullText = "";
|
|
1722
|
+
let cleanedText = "";
|
|
1723
|
+
let inThinkBlock = false;
|
|
1724
|
+
let jsonStart = -1;
|
|
1725
|
+
const streamer = createStreamingTextStreamer(generateText.tokenizer, (delta) => {
|
|
1726
|
+
fullText += delta;
|
|
1727
|
+
let remaining = delta;
|
|
1728
|
+
while (remaining.length > 0) {
|
|
1729
|
+
if (inThinkBlock) {
|
|
1730
|
+
const closeIdx = remaining.indexOf("</think>");
|
|
1731
|
+
if (closeIdx !== -1) {
|
|
1732
|
+
inThinkBlock = false;
|
|
1733
|
+
remaining = remaining.slice(closeIdx + "</think>".length);
|
|
1734
|
+
} else {
|
|
1735
|
+
remaining = "";
|
|
1736
|
+
}
|
|
1737
|
+
} else {
|
|
1738
|
+
const openIdx = remaining.indexOf("<think>");
|
|
1739
|
+
if (openIdx !== -1) {
|
|
1740
|
+
cleanedText += remaining.slice(0, openIdx).replace(/<\|[a-z_]+\|>/g, "");
|
|
1741
|
+
inThinkBlock = true;
|
|
1742
|
+
remaining = remaining.slice(openIdx + "<think>".length);
|
|
1743
|
+
} else {
|
|
1744
|
+
cleanedText += remaining.replace(/<\|[a-z_]+\|>/g, "");
|
|
1745
|
+
remaining = "";
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
if (jsonStart === -1) {
|
|
1750
|
+
jsonStart = cleanedText.indexOf("{");
|
|
1751
|
+
}
|
|
1752
|
+
if (jsonStart !== -1) {
|
|
1753
|
+
const partial = parsePartialJson(cleanedText.slice(jsonStart));
|
|
1754
|
+
if (partial !== undefined) {
|
|
1755
|
+
emit({ type: "object-delta", port: "object", objectDelta: partial });
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
emit({ type: "text-delta", port: "text", textDelta: delta });
|
|
1760
|
+
}, TextStreamer);
|
|
1761
|
+
const stopping_criteria = new InterruptableStoppingCriteria;
|
|
1762
|
+
if (signal) {
|
|
1763
|
+
signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
|
|
1764
|
+
}
|
|
1765
|
+
await generateText(formattedPrompt, {
|
|
1766
|
+
max_new_tokens: input.maxTokens ?? 1024,
|
|
1767
|
+
temperature: input.temperature ?? undefined,
|
|
1768
|
+
return_full_text: false,
|
|
1769
|
+
streamer,
|
|
1770
|
+
stopping_criteria: [stopping_criteria]
|
|
1771
|
+
});
|
|
1772
|
+
const object = extractJsonFromText(fullText);
|
|
1773
|
+
emit({ type: "finish", data: { object } });
|
|
1774
|
+
};
|
|
1775
|
+
|
|
1776
|
+
// src/ai/common/HFT_TextClassification.ts
|
|
1777
|
+
init_HFT_Pipeline();
|
|
1778
|
+
var HFT_TextClassification = async (input, model, signal, emit) => {
|
|
1779
|
+
if (model?.provider_config?.pipeline === "zero-shot-classification") {
|
|
1780
|
+
if (!input.candidateLabels || !Array.isArray(input.candidateLabels) || input.candidateLabels.length === 0) {
|
|
1781
|
+
throw new Error("Zero-shot text classification requires candidate labels");
|
|
1782
|
+
}
|
|
1783
|
+
const zeroShotClassifier = await getPipeline(model, emit, {}, signal);
|
|
1784
|
+
const result2 = await zeroShotClassifier(input.text, input.candidateLabels, {});
|
|
1785
|
+
emit({
|
|
1786
|
+
type: "finish",
|
|
1787
|
+
data: {
|
|
1788
|
+
categories: result2.labels.map((label, idx) => ({
|
|
1789
|
+
label,
|
|
1790
|
+
score: result2.scores[idx]
|
|
1791
|
+
}))
|
|
1792
|
+
}
|
|
1793
|
+
});
|
|
1794
|
+
return;
|
|
1795
|
+
}
|
|
1796
|
+
const TextClassification = await getPipeline(model, emit, {}, signal);
|
|
1797
|
+
const result = await TextClassification(input.text, {
|
|
1798
|
+
top_k: input.maxCategories || undefined
|
|
1799
|
+
});
|
|
1800
|
+
emit({
|
|
1801
|
+
type: "finish",
|
|
1802
|
+
data: {
|
|
1803
|
+
categories: result.map((category) => ({
|
|
1804
|
+
label: category.label,
|
|
1805
|
+
score: category.score
|
|
1806
|
+
}))
|
|
1807
|
+
}
|
|
1808
|
+
});
|
|
1809
|
+
};
|
|
1810
|
+
|
|
1811
|
+
// src/ai/common/HFT_TextEmbedding.ts
|
|
1812
|
+
init_HFT_Pipeline();
|
|
1813
|
+
import { getLogger as getLogger5 } from "@workglow/util/worker";
|
|
1814
|
+
var HFT_TextEmbedding = async (input, model, signal, emit) => {
|
|
1815
|
+
const logger = getLogger5();
|
|
1816
|
+
const uuid = crypto.randomUUID();
|
|
1817
|
+
const timerLabel = `hft:TextEmbedding:${model?.provider_config.model_path}:${uuid}`;
|
|
1818
|
+
logger.time(timerLabel, { model: model?.provider_config.model_path });
|
|
1819
|
+
const generateEmbedding = await getPipeline(model, emit, {}, signal);
|
|
1820
|
+
logger.debug("HFT TextEmbedding: pipeline ready, generating embedding", {
|
|
1821
|
+
model: model?.provider_config.model_path,
|
|
1822
|
+
inputLength: Array.isArray(input.text) ? input.text.length : input.text?.length
|
|
1823
|
+
});
|
|
1824
|
+
const hfVector = await generateEmbedding(input.text, {
|
|
1825
|
+
pooling: model?.provider_config.pooling || "mean",
|
|
1826
|
+
normalize: model?.provider_config.normalize
|
|
1827
|
+
});
|
|
1828
|
+
const isArrayInput = Array.isArray(input.text);
|
|
1829
|
+
const embeddingDim = model?.provider_config.native_dimensions;
|
|
1830
|
+
if (isArrayInput && hfVector.dims.length > 1) {
|
|
1831
|
+
const [numTexts, vectorDim] = hfVector.dims;
|
|
1832
|
+
if (numTexts !== input.text.length) {
|
|
1833
|
+
throw new Error(`HuggingFace Embedding tensor batch size does not match input array length: ${numTexts} != ${input.text.length}`);
|
|
1834
|
+
}
|
|
1835
|
+
if (vectorDim !== embeddingDim) {
|
|
1836
|
+
throw new Error(`HuggingFace Embedding vector dimension does not match model dimensions: ${vectorDim} != ${embeddingDim}`);
|
|
1837
|
+
}
|
|
1838
|
+
const vectors = Array.from({ length: numTexts }, (_, i) => hfVector[i].data.slice());
|
|
1839
|
+
logger.timeEnd(timerLabel, { batchSize: numTexts, dimensions: vectorDim });
|
|
1840
|
+
emit({ type: "finish", data: { vector: vectors } });
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
if (hfVector.size !== embeddingDim) {
|
|
1844
|
+
logger.timeEnd(timerLabel, { status: "error", reason: "dimension mismatch" });
|
|
1845
|
+
console.warn(`HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${embeddingDim}`, input, hfVector);
|
|
1846
|
+
throw new Error(`HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${embeddingDim}`);
|
|
1847
|
+
}
|
|
1848
|
+
logger.timeEnd(timerLabel, { dimensions: hfVector.size });
|
|
1849
|
+
emit({ type: "finish", data: { vector: hfVector.data } });
|
|
1850
|
+
};
|
|
1851
|
+
|
|
1852
|
+
// src/ai/common/HFT_TextFillMask.ts
|
|
1853
|
+
init_HFT_Pipeline();
|
|
1854
|
+
var HFT_TextFillMask = async (input, model, signal, emit) => {
|
|
1855
|
+
const unmasker = await getPipeline(model, emit, {}, signal);
|
|
1856
|
+
const predictions = await unmasker(input.text);
|
|
1857
|
+
emit({
|
|
1858
|
+
type: "finish",
|
|
1859
|
+
data: {
|
|
1860
|
+
predictions: predictions.map((prediction) => ({
|
|
1861
|
+
entity: prediction.token_str,
|
|
1862
|
+
score: prediction.score,
|
|
1863
|
+
sequence: prediction.sequence
|
|
1864
|
+
}))
|
|
1865
|
+
}
|
|
1866
|
+
});
|
|
1867
|
+
};
|
|
1868
|
+
|
|
1869
|
+
// src/ai/common/HFT_TextGeneration.ts
|
|
1870
|
+
init_HFT_Pipeline();
|
|
1871
|
+
var HFT_TextGeneration = async (input, model, signal, emit, _outputSchema, sessionId) => {
|
|
1872
|
+
const generateText = await getPipeline(model, emit, {}, signal);
|
|
1873
|
+
const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
|
|
1874
|
+
const streamer = createStreamingTextStreamer(generateText.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
|
|
1875
|
+
const stopping_criteria = new InterruptableStoppingCriteria;
|
|
1876
|
+
if (signal) {
|
|
1877
|
+
signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
|
|
1878
|
+
}
|
|
1879
|
+
const modelPath = model.provider_config.model_path;
|
|
1880
|
+
let session = sessionId ? getHftSession(sessionId) : undefined;
|
|
1881
|
+
let past_key_values = undefined;
|
|
1882
|
+
if (sessionId && !session) {
|
|
1883
|
+
const sdk = await loadTransformersSDK();
|
|
1884
|
+
const cache = new sdk.DynamicCache;
|
|
1885
|
+
const newSession = {
|
|
1886
|
+
mode: "progressive",
|
|
1887
|
+
cache,
|
|
1888
|
+
modelPath
|
|
1889
|
+
};
|
|
1890
|
+
setHftSession(sessionId, newSession);
|
|
1891
|
+
session = newSession;
|
|
1892
|
+
}
|
|
1893
|
+
if (session?.mode === "progressive") {
|
|
1894
|
+
past_key_values = session.cache;
|
|
1895
|
+
}
|
|
1896
|
+
const messages = [{ role: "user", content: input.prompt }];
|
|
1897
|
+
await generateText(messages, {
|
|
1898
|
+
streamer,
|
|
1899
|
+
do_sample: false,
|
|
1900
|
+
max_new_tokens: input.maxTokens ?? 4 * 1024,
|
|
1901
|
+
stopping_criteria: [stopping_criteria],
|
|
1902
|
+
...past_key_values ? { past_key_values } : {}
|
|
1903
|
+
});
|
|
1904
|
+
emit({ type: "finish", data: {} });
|
|
1905
|
+
};
|
|
1906
|
+
|
|
1907
|
+
// src/ai/common/HFT_TextLanguageDetection.ts
|
|
1908
|
+
init_HFT_Pipeline();
|
|
1909
|
+
var HFT_TextLanguageDetection = async (input, model, signal, emit) => {
|
|
1910
|
+
const TextClassification = await getPipeline(model, emit, {}, signal);
|
|
1911
|
+
const result = await TextClassification(input.text, {
|
|
1912
|
+
top_k: input.maxLanguages || undefined
|
|
1913
|
+
});
|
|
1914
|
+
emit({
|
|
1915
|
+
type: "finish",
|
|
1916
|
+
data: {
|
|
1917
|
+
languages: result.map((category) => ({
|
|
1918
|
+
language: category.label,
|
|
1919
|
+
score: category.score
|
|
1920
|
+
}))
|
|
1921
|
+
}
|
|
1922
|
+
});
|
|
1923
|
+
};
|
|
1924
|
+
|
|
1925
|
+
// src/ai/common/HFT_TextNamedEntityRecognition.ts
|
|
1926
|
+
init_HFT_Pipeline();
|
|
1927
|
+
var HFT_TextNamedEntityRecognition = async (input, model, signal, emit) => {
|
|
1928
|
+
const textNamedEntityRecognition = await getPipeline(model, emit, {}, signal);
|
|
1929
|
+
const results = await textNamedEntityRecognition(input.text, {
|
|
1930
|
+
ignore_labels: input.blockList
|
|
1931
|
+
});
|
|
1932
|
+
emit({
|
|
1933
|
+
type: "finish",
|
|
1934
|
+
data: {
|
|
1935
|
+
entities: results.map((entity) => ({
|
|
1936
|
+
entity: entity.entity,
|
|
1937
|
+
score: entity.score,
|
|
1938
|
+
word: entity.word
|
|
1939
|
+
}))
|
|
1940
|
+
}
|
|
1941
|
+
});
|
|
1942
|
+
};
|
|
1943
|
+
|
|
1944
|
+
// src/ai/common/HFT_TextQuestionAnswer.ts
|
|
1945
|
+
init_HFT_Pipeline();
|
|
1946
|
+
var HFT_TextQuestionAnswer = async (input, model, signal, emit) => {
|
|
1947
|
+
const generateAnswer = await getPipeline(model, emit, {}, signal);
|
|
1948
|
+
const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
|
|
1949
|
+
const streamer = createStreamingTextStreamer(generateAnswer.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
|
|
1950
|
+
const stopping_criteria = new InterruptableStoppingCriteria;
|
|
1951
|
+
if (signal) {
|
|
1952
|
+
signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
|
|
1953
|
+
}
|
|
1954
|
+
const pipelineResult = await generateAnswer(input.question, input.context, {
|
|
1955
|
+
streamer,
|
|
1956
|
+
stopping_criteria: [stopping_criteria]
|
|
1957
|
+
});
|
|
1958
|
+
const answerText = Array.isArray(pipelineResult) ? pipelineResult[0]?.answer ?? "" : pipelineResult?.answer ?? "";
|
|
1959
|
+
emit({ type: "finish", data: { text: answerText } });
|
|
1960
|
+
};
|
|
1961
|
+
|
|
1962
|
+
// src/ai/common/HFT_TextRewriter.ts
|
|
1963
|
+
init_HFT_Pipeline();
|
|
1964
|
+
var HFT_TextRewriter = async (input, model, signal, emit) => {
|
|
1965
|
+
const generateText = await getPipeline(model, emit, {}, signal);
|
|
1966
|
+
const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
|
|
1967
|
+
const streamer = createStreamingTextStreamer(generateText.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
|
|
1968
|
+
const stopping_criteria = new InterruptableStoppingCriteria;
|
|
1969
|
+
if (signal) {
|
|
1970
|
+
signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
|
|
1971
|
+
}
|
|
1972
|
+
const promptedText = (input.prompt ? input.prompt + `
|
|
1973
|
+
` : "") + input.text;
|
|
1974
|
+
await generateText(promptedText, {
|
|
1975
|
+
streamer,
|
|
1976
|
+
stopping_criteria: [stopping_criteria]
|
|
1977
|
+
});
|
|
1978
|
+
emit({ type: "finish", data: {} });
|
|
1979
|
+
};
|
|
1980
|
+
|
|
1981
|
+
// src/ai/common/HFT_TextSummary.ts
|
|
1982
|
+
init_HFT_Pipeline();
|
|
1983
|
+
var HFT_TextSummary = async (input, model, signal, emit) => {
|
|
1984
|
+
const generateSummary = await getPipeline(model, emit, {}, signal);
|
|
1985
|
+
const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
|
|
1986
|
+
const streamer = createStreamingTextStreamer(generateSummary.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
|
|
1987
|
+
const stopping_criteria = new InterruptableStoppingCriteria;
|
|
1988
|
+
if (signal) {
|
|
1989
|
+
signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
|
|
1990
|
+
}
|
|
1991
|
+
await generateSummary(input.text, {
|
|
1992
|
+
streamer,
|
|
1993
|
+
stopping_criteria: [stopping_criteria]
|
|
1994
|
+
});
|
|
1995
|
+
emit({ type: "finish", data: {} });
|
|
1996
|
+
};
|
|
1997
|
+
|
|
1998
|
+
// src/ai/common/HFT_TextTranslation.ts
|
|
1999
|
+
init_HFT_Pipeline();
|
|
2000
|
+
var HFT_TextTranslation = async (input, model, signal, emit) => {
|
|
2001
|
+
const translate = await getPipeline(model, emit, {}, signal);
|
|
2002
|
+
const { TextStreamer, InterruptableStoppingCriteria } = await loadTransformersSDK();
|
|
2003
|
+
const streamer = createStreamingTextStreamer(translate.tokenizer, (text) => emit({ type: "text-delta", port: "text", textDelta: text }), TextStreamer);
|
|
2004
|
+
const stopping_criteria = new InterruptableStoppingCriteria;
|
|
2005
|
+
if (signal) {
|
|
2006
|
+
signal.addEventListener("abort", () => stopping_criteria.interrupt(), { once: true });
|
|
2007
|
+
}
|
|
2008
|
+
await translate(input.text, {
|
|
2009
|
+
src_lang: input.source_lang,
|
|
2010
|
+
tgt_lang: input.target_lang,
|
|
2011
|
+
streamer,
|
|
2012
|
+
stopping_criteria: [stopping_criteria]
|
|
2013
|
+
});
|
|
2014
|
+
emit({ type: "finish", data: { target_lang: input.target_lang } });
|
|
2015
|
+
};
|
|
2016
|
+
|
|
2017
|
+
// src/ai/common/HFT_JobRunFns.ts
|
|
2018
|
+
var HFT_TextGeneration_Unified = async (input, model, signal, emit, outputSchema, sessionId) => {
|
|
2019
|
+
const maybeMessages = input.messages;
|
|
2020
|
+
if (Array.isArray(maybeMessages) && maybeMessages.length > 0) {
|
|
2021
|
+
await HFT_Chat(input, model, signal, emit, outputSchema, sessionId);
|
|
2022
|
+
} else {
|
|
2023
|
+
await HFT_TextGeneration(input, model, signal, emit, outputSchema, sessionId);
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
2026
|
+
var HFT_RUN_FNS = [
|
|
2027
|
+
{ serves: HFT_TEXT_GENERATION, runFn: HFT_TextGeneration_Unified },
|
|
2028
|
+
{ serves: HFT_TOOL_USE, runFn: HFT_ToolCalling },
|
|
2029
|
+
{ serves: HFT_JSON_MODE, runFn: HFT_StructuredGeneration },
|
|
2030
|
+
{ serves: HFT_TEXT_REWRITER, runFn: HFT_TextRewriter },
|
|
2031
|
+
{ serves: HFT_TEXT_SUMMARY, runFn: HFT_TextSummary },
|
|
2032
|
+
{ serves: HFT_TEXT_TRANSLATION, runFn: HFT_TextTranslation },
|
|
2033
|
+
{ serves: HFT_TEXT_QUESTION_ANSWERING, runFn: HFT_TextQuestionAnswer },
|
|
2034
|
+
{ serves: HFT_TEXT_EMBEDDING, runFn: HFT_TextEmbedding },
|
|
2035
|
+
{ serves: HFT_TEXT_CLASSIFICATION, runFn: HFT_TextClassification },
|
|
2036
|
+
{ serves: HFT_TEXT_LANGUAGE_DETECTION, runFn: HFT_TextLanguageDetection },
|
|
2037
|
+
{ serves: HFT_TEXT_FILL_MASK, runFn: HFT_TextFillMask },
|
|
2038
|
+
{ serves: HFT_TEXT_NER, runFn: HFT_TextNamedEntityRecognition },
|
|
2039
|
+
{ serves: HFT_IMAGE_CLASSIFICATION, runFn: HFT_ImageClassification },
|
|
2040
|
+
{ serves: HFT_IMAGE_EMBEDDING, runFn: HFT_ImageEmbedding },
|
|
2041
|
+
{ serves: HFT_IMAGE_SEGMENTATION, runFn: HFT_ImageSegmentation },
|
|
2042
|
+
{ serves: HFT_IMAGE_TO_TEXT, runFn: HFT_ImageToText },
|
|
2043
|
+
{ serves: HFT_IMAGE_BACKGROUND_REMOVAL, runFn: HFT_BackgroundRemoval },
|
|
2044
|
+
{ serves: HFT_IMAGE_OBJECT_DETECTION, runFn: HFT_ObjectDetection },
|
|
2045
|
+
{ serves: HFT_COUNT_TOKENS, runFn: HFT_CountTokens },
|
|
2046
|
+
{ serves: HFT_MODEL_DOWNLOAD_REMOVE, runFn: HFT_DownloadRemove },
|
|
2047
|
+
{ serves: HFT_MODEL_DOWNLOAD, runFn: HFT_Download },
|
|
2048
|
+
{ serves: HFT_MODEL_SEARCH, runFn: HFT_ModelSearch },
|
|
2049
|
+
{ serves: HFT_MODEL_INFO, runFn: HFT_ModelInfo }
|
|
2050
|
+
];
|
|
2051
|
+
var HFT_PREVIEW_TASKS = {
|
|
2052
|
+
CountTokensTask: HFT_CountTokens_Preview
|
|
2053
|
+
};
|
|
2054
|
+
|
|
2055
|
+
// src/ai/index.ts
|
|
2056
|
+
var _testOnly = {
|
|
2057
|
+
HFT_RUN_FN_SPECS,
|
|
2058
|
+
HFT_RUN_FNS
|
|
2059
|
+
};
|
|
861
2060
|
export {
|
|
862
2061
|
registerHuggingFaceTransformers,
|
|
863
2062
|
parseOnnxQuantizations,
|
|
864
2063
|
createToolCallMarkupFilter,
|
|
2064
|
+
_testOnly,
|
|
865
2065
|
QuantizationDataType,
|
|
866
2066
|
PipelineUseCase,
|
|
867
2067
|
ONNX_QUANTIZATION_SUFFIX_MAPPING,
|
|
@@ -876,4 +2076,4 @@ export {
|
|
|
876
2076
|
HF_TRANSFORMERS_ONNX
|
|
877
2077
|
};
|
|
878
2078
|
|
|
879
|
-
//# debugId=
|
|
2079
|
+
//# debugId=F0665A2512C7736664756E2164756E21
|