@workglow/ai-provider 0.0.89 → 0.0.91
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/README.md +45 -45
- package/dist/anthropic/AnthropicProvider.d.ts +39 -0
- package/dist/anthropic/AnthropicProvider.d.ts.map +1 -0
- package/dist/anthropic/Anthropic_Worker.d.ts +7 -0
- package/dist/anthropic/Anthropic_Worker.d.ts.map +1 -0
- package/dist/anthropic/common/Anthropic_Constants.d.ts +7 -0
- package/dist/anthropic/common/Anthropic_Constants.d.ts.map +1 -0
- package/dist/anthropic/common/Anthropic_JobRunFns.d.ts +16 -0
- package/dist/anthropic/common/Anthropic_JobRunFns.d.ts.map +1 -0
- package/dist/anthropic/common/Anthropic_ModelSchema.d.ts +167 -0
- package/dist/anthropic/common/Anthropic_ModelSchema.d.ts.map +1 -0
- package/dist/anthropic/index.d.ts +11 -0
- package/dist/anthropic/index.d.ts.map +1 -0
- package/dist/anthropic/index.js +257 -0
- package/dist/anthropic/index.js.map +14 -0
- package/dist/google-gemini/Gemini_Worker.d.ts +7 -0
- package/dist/google-gemini/Gemini_Worker.d.ts.map +1 -0
- package/dist/google-gemini/GoogleGeminiProvider.d.ts +36 -0
- package/dist/google-gemini/GoogleGeminiProvider.d.ts.map +1 -0
- package/dist/google-gemini/common/Gemini_Constants.d.ts +7 -0
- package/dist/google-gemini/common/Gemini_Constants.d.ts.map +1 -0
- package/dist/google-gemini/common/Gemini_JobRunFns.d.ts +17 -0
- package/dist/google-gemini/common/Gemini_JobRunFns.d.ts.map +1 -0
- package/dist/google-gemini/common/Gemini_ModelSchema.d.ts +164 -0
- package/dist/google-gemini/common/Gemini_ModelSchema.d.ts.map +1 -0
- package/dist/google-gemini/index.d.ts +11 -0
- package/dist/google-gemini/index.d.ts.map +1 -0
- package/dist/google-gemini/index.js +300 -0
- package/dist/google-gemini/index.js.map +14 -0
- package/dist/hf-transformers/HFT_Worker.d.ts +7 -0
- package/dist/hf-transformers/HFT_Worker.d.ts.map +1 -0
- package/dist/hf-transformers/HuggingFaceTransformersProvider.d.ts +41 -0
- package/dist/hf-transformers/HuggingFaceTransformersProvider.d.ts.map +1 -0
- package/dist/hf-transformers/common/HFT_JobRunFns.d.ts +1218 -1
- package/dist/hf-transformers/common/HFT_JobRunFns.d.ts.map +1 -1
- package/dist/hf-transformers/index.d.ts +2 -3
- package/dist/hf-transformers/index.d.ts.map +1 -1
- package/dist/hf-transformers/index.js +1130 -0
- package/dist/hf-transformers/index.js.map +15 -0
- package/dist/index.d.ts +23 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +729 -865
- package/dist/index.js.map +20 -12
- package/dist/provider-ollama/OllamaProvider.d.ts +39 -0
- package/dist/provider-ollama/OllamaProvider.d.ts.map +1 -0
- package/dist/provider-ollama/Ollama_Worker.d.ts +7 -0
- package/dist/provider-ollama/Ollama_Worker.d.ts.map +1 -0
- package/dist/provider-ollama/common/Ollama_Constants.d.ts +8 -0
- package/dist/provider-ollama/common/Ollama_Constants.d.ts.map +1 -0
- package/dist/provider-ollama/common/Ollama_JobRunFns.d.ts +17 -0
- package/dist/provider-ollama/common/Ollama_JobRunFns.d.ts.map +1 -0
- package/dist/provider-ollama/common/Ollama_ModelSchema.d.ts +137 -0
- package/dist/provider-ollama/common/Ollama_ModelSchema.d.ts.map +1 -0
- package/dist/provider-ollama/index.d.ts +11 -0
- package/dist/provider-ollama/index.d.ts.map +1 -0
- package/dist/provider-ollama/index.js +274 -0
- package/dist/provider-ollama/index.js.map +14 -0
- package/dist/provider-openai/OpenAI_Worker.d.ts +7 -0
- package/dist/provider-openai/OpenAI_Worker.d.ts.map +1 -0
- package/dist/provider-openai/OpenAiProvider.d.ts +40 -0
- package/dist/provider-openai/OpenAiProvider.d.ts.map +1 -0
- package/dist/provider-openai/common/OpenAI_Constants.d.ts +7 -0
- package/dist/provider-openai/common/OpenAI_Constants.d.ts.map +1 -0
- package/dist/provider-openai/common/OpenAI_JobRunFns.d.ts +17 -0
- package/dist/provider-openai/common/OpenAI_JobRunFns.d.ts.map +1 -0
- package/dist/provider-openai/common/OpenAI_ModelSchema.d.ts +161 -0
- package/dist/provider-openai/common/OpenAI_ModelSchema.d.ts.map +1 -0
- package/dist/provider-openai/index.d.ts +11 -0
- package/dist/provider-openai/index.d.ts.map +1 -0
- package/dist/provider-openai/index.js +283 -0
- package/dist/provider-openai/index.js.map +14 -0
- package/dist/tf-mediapipe/TFMP_Worker.d.ts +7 -0
- package/dist/tf-mediapipe/TFMP_Worker.d.ts.map +1 -0
- package/dist/tf-mediapipe/TensorFlowMediaPipeProvider.d.ts +39 -0
- package/dist/tf-mediapipe/TensorFlowMediaPipeProvider.d.ts.map +1 -0
- package/dist/tf-mediapipe/common/TFMP_JobRunFns.d.ts +842 -0
- package/dist/tf-mediapipe/common/TFMP_JobRunFns.d.ts.map +1 -1
- package/dist/tf-mediapipe/index.d.ts +2 -3
- package/dist/tf-mediapipe/index.d.ts.map +1 -1
- package/dist/tf-mediapipe/index.js +674 -0
- package/dist/tf-mediapipe/index.js.map +14 -0
- package/package.json +87 -22
- package/dist/hf-transformers/registry/HFT_Client_RegisterJobFns.d.ts +0 -17
- package/dist/hf-transformers/registry/HFT_Client_RegisterJobFns.d.ts.map +0 -1
- package/dist/hf-transformers/registry/HFT_Inline_RegisterJobFns.d.ts +0 -16
- package/dist/hf-transformers/registry/HFT_Inline_RegisterJobFns.d.ts.map +0 -1
- package/dist/hf-transformers/registry/HFT_Worker_RegisterJobFns.d.ts +0 -8
- package/dist/hf-transformers/registry/HFT_Worker_RegisterJobFns.d.ts.map +0 -1
- package/dist/openai/provider/OpenAI_TaskRun.d.ts +0 -2
- package/dist/openai/provider/OpenAI_TaskRun.d.ts.map +0 -1
- package/dist/tf-mediapipe/registry/TFMP_Client_RegisterJobFns.d.ts +0 -17
- package/dist/tf-mediapipe/registry/TFMP_Client_RegisterJobFns.d.ts.map +0 -1
- package/dist/tf-mediapipe/registry/TFMP_Inline_RegisterJobFns.d.ts +0 -16
- package/dist/tf-mediapipe/registry/TFMP_Inline_RegisterJobFns.d.ts.map +0 -1
- package/dist/tf-mediapipe/registry/TFMP_Worker_RegisterJobFns.d.ts +0 -8
- package/dist/tf-mediapipe/registry/TFMP_Worker_RegisterJobFns.d.ts.map +0 -1
|
@@ -0,0 +1,1130 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
13
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
14
|
+
}) : x)(function(x) {
|
|
15
|
+
if (typeof require !== "undefined")
|
|
16
|
+
return require.apply(this, arguments);
|
|
17
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// src/hf-transformers/common/HFT_Constants.ts
|
|
21
|
+
var HF_TRANSFORMERS_ONNX = "HF_TRANSFORMERS_ONNX", HTF_CACHE_NAME = "transformers-cache", QuantizationDataType, TextPipelineUseCase, VisionPipelineUseCase, AudioPipelineUseCase, MultimodalPipelineUseCase, PipelineUseCase;
|
|
22
|
+
var init_HFT_Constants = __esm(() => {
|
|
23
|
+
QuantizationDataType = {
|
|
24
|
+
auto: "auto",
|
|
25
|
+
fp32: "fp32",
|
|
26
|
+
fp16: "fp16",
|
|
27
|
+
q8: "q8",
|
|
28
|
+
int8: "int8",
|
|
29
|
+
uint8: "uint8",
|
|
30
|
+
q4: "q4",
|
|
31
|
+
bnb4: "bnb4",
|
|
32
|
+
q4f16: "q4f16"
|
|
33
|
+
};
|
|
34
|
+
TextPipelineUseCase = {
|
|
35
|
+
"fill-mask": "fill-mask",
|
|
36
|
+
"token-classification": "token-classification",
|
|
37
|
+
"text-generation": "text-generation",
|
|
38
|
+
"text2text-generation": "text2text-generation",
|
|
39
|
+
"text-classification": "text-classification",
|
|
40
|
+
summarization: "summarization",
|
|
41
|
+
translation: "translation",
|
|
42
|
+
"feature-extraction": "feature-extraction",
|
|
43
|
+
"zero-shot-classification": "zero-shot-classification",
|
|
44
|
+
"question-answering": "question-answering"
|
|
45
|
+
};
|
|
46
|
+
VisionPipelineUseCase = {
|
|
47
|
+
"background-removal": "background-removal",
|
|
48
|
+
"image-segmentation": "image-segmentation",
|
|
49
|
+
"depth-estimation": "depth-estimation",
|
|
50
|
+
"image-classification": "image-classification",
|
|
51
|
+
"image-to-image": "image-to-image",
|
|
52
|
+
"object-detection": "object-detection",
|
|
53
|
+
"image-feature-extraction": "image-feature-extraction"
|
|
54
|
+
};
|
|
55
|
+
AudioPipelineUseCase = {
|
|
56
|
+
"audio-classification": "audio-classification",
|
|
57
|
+
"automatic-speech-recognition": "automatic-speech-recognition",
|
|
58
|
+
"text-to-speech": "text-to-speech"
|
|
59
|
+
};
|
|
60
|
+
MultimodalPipelineUseCase = {
|
|
61
|
+
"document-question-answering": "document-question-answering",
|
|
62
|
+
"image-to-text": "image-to-text",
|
|
63
|
+
"zero-shot-audio-classification": "zero-shot-audio-classification",
|
|
64
|
+
"zero-shot-image-classification": "zero-shot-image-classification",
|
|
65
|
+
"zero-shot-object-detection": "zero-shot-object-detection"
|
|
66
|
+
};
|
|
67
|
+
PipelineUseCase = {
|
|
68
|
+
...TextPipelineUseCase,
|
|
69
|
+
...VisionPipelineUseCase,
|
|
70
|
+
...AudioPipelineUseCase,
|
|
71
|
+
...MultimodalPipelineUseCase
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// src/hf-transformers/common/HFT_JobRunFns.ts
|
|
76
|
+
var exports_HFT_JobRunFns = {};
|
|
77
|
+
__export(exports_HFT_JobRunFns, {
|
|
78
|
+
clearPipelineCache: () => clearPipelineCache,
|
|
79
|
+
HFT_Unload: () => HFT_Unload,
|
|
80
|
+
HFT_TextTranslation_Stream: () => HFT_TextTranslation_Stream,
|
|
81
|
+
HFT_TextTranslation: () => HFT_TextTranslation,
|
|
82
|
+
HFT_TextSummary_Stream: () => HFT_TextSummary_Stream,
|
|
83
|
+
HFT_TextSummary: () => HFT_TextSummary,
|
|
84
|
+
HFT_TextRewriter_Stream: () => HFT_TextRewriter_Stream,
|
|
85
|
+
HFT_TextRewriter: () => HFT_TextRewriter,
|
|
86
|
+
HFT_TextQuestionAnswer_Stream: () => HFT_TextQuestionAnswer_Stream,
|
|
87
|
+
HFT_TextQuestionAnswer: () => HFT_TextQuestionAnswer,
|
|
88
|
+
HFT_TextNamedEntityRecognition: () => HFT_TextNamedEntityRecognition,
|
|
89
|
+
HFT_TextLanguageDetection: () => HFT_TextLanguageDetection,
|
|
90
|
+
HFT_TextGeneration_Stream: () => HFT_TextGeneration_Stream,
|
|
91
|
+
HFT_TextGeneration: () => HFT_TextGeneration,
|
|
92
|
+
HFT_TextFillMask: () => HFT_TextFillMask,
|
|
93
|
+
HFT_TextEmbedding: () => HFT_TextEmbedding,
|
|
94
|
+
HFT_TextClassification: () => HFT_TextClassification,
|
|
95
|
+
HFT_TASKS: () => HFT_TASKS,
|
|
96
|
+
HFT_STREAM_TASKS: () => HFT_STREAM_TASKS,
|
|
97
|
+
HFT_ObjectDetection: () => HFT_ObjectDetection,
|
|
98
|
+
HFT_ImageToText: () => HFT_ImageToText,
|
|
99
|
+
HFT_ImageSegmentation: () => HFT_ImageSegmentation,
|
|
100
|
+
HFT_ImageEmbedding: () => HFT_ImageEmbedding,
|
|
101
|
+
HFT_ImageClassification: () => HFT_ImageClassification,
|
|
102
|
+
HFT_Download: () => HFT_Download,
|
|
103
|
+
HFT_BackgroundRemoval: () => HFT_BackgroundRemoval
|
|
104
|
+
});
|
|
105
|
+
async function loadTransformersSDK() {
|
|
106
|
+
if (!_transformersSdk) {
|
|
107
|
+
try {
|
|
108
|
+
_transformersSdk = await import("@sroussey/transformers");
|
|
109
|
+
} catch {
|
|
110
|
+
throw new Error("@sroussey/transformers is required for HuggingFace Transformers tasks. Install it with: bun add @sroussey/transformers");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return _transformersSdk;
|
|
114
|
+
}
|
|
115
|
+
function clearPipelineCache() {
|
|
116
|
+
pipelines.clear();
|
|
117
|
+
}
|
|
118
|
+
function getPipelineCacheKey(model) {
|
|
119
|
+
const dtype = model.provider_config.dtype || "q8";
|
|
120
|
+
const device = model.provider_config.device || "";
|
|
121
|
+
return `${model.provider_config.model_path}:${model.provider_config.pipeline}:${dtype}:${device}`;
|
|
122
|
+
}
|
|
123
|
+
function imageToBase64(image) {
|
|
124
|
+
return image.toBase64?.() || "";
|
|
125
|
+
}
|
|
126
|
+
function createTextStreamer(tokenizer, updateProgress, signal) {
|
|
127
|
+
const { TextStreamer } = _transformersSdk;
|
|
128
|
+
let count = 0;
|
|
129
|
+
return new TextStreamer(tokenizer, {
|
|
130
|
+
skip_prompt: true,
|
|
131
|
+
decode_kwargs: { skip_special_tokens: true },
|
|
132
|
+
callback_function: (text) => {
|
|
133
|
+
count++;
|
|
134
|
+
const result = 100 * (1 - Math.exp(-0.05 * count));
|
|
135
|
+
const progress = Math.round(Math.min(result, 100));
|
|
136
|
+
updateProgress(progress, "Generating", { text, progress });
|
|
137
|
+
},
|
|
138
|
+
...signal ? { abort_signal: signal } : {}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function createStreamEventQueue() {
|
|
142
|
+
const buffer = [];
|
|
143
|
+
let resolve = null;
|
|
144
|
+
let finished = false;
|
|
145
|
+
let err = null;
|
|
146
|
+
const push = (event) => {
|
|
147
|
+
if (resolve) {
|
|
148
|
+
const r = resolve;
|
|
149
|
+
resolve = null;
|
|
150
|
+
r({ value: event, done: false });
|
|
151
|
+
} else {
|
|
152
|
+
buffer.push(event);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const done = () => {
|
|
156
|
+
finished = true;
|
|
157
|
+
if (resolve) {
|
|
158
|
+
const r = resolve;
|
|
159
|
+
resolve = null;
|
|
160
|
+
r({ value: undefined, done: true });
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const error = (e) => {
|
|
164
|
+
err = e;
|
|
165
|
+
if (resolve) {
|
|
166
|
+
const r = resolve;
|
|
167
|
+
resolve = null;
|
|
168
|
+
r({ value: undefined, done: true });
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const iterable = {
|
|
172
|
+
[Symbol.asyncIterator]() {
|
|
173
|
+
return {
|
|
174
|
+
next() {
|
|
175
|
+
if (err)
|
|
176
|
+
return Promise.reject(err);
|
|
177
|
+
if (buffer.length > 0) {
|
|
178
|
+
return Promise.resolve({ value: buffer.shift(), done: false });
|
|
179
|
+
}
|
|
180
|
+
if (finished) {
|
|
181
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
182
|
+
}
|
|
183
|
+
return new Promise((r) => {
|
|
184
|
+
resolve = r;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
return { push, done, error, iterable };
|
|
191
|
+
}
|
|
192
|
+
function createStreamingTextStreamer(tokenizer, queue, signal) {
|
|
193
|
+
const { TextStreamer } = _transformersSdk;
|
|
194
|
+
return new TextStreamer(tokenizer, {
|
|
195
|
+
skip_prompt: true,
|
|
196
|
+
decode_kwargs: { skip_special_tokens: true },
|
|
197
|
+
callback_function: (text) => {
|
|
198
|
+
queue.push({ type: "text-delta", textDelta: text });
|
|
199
|
+
},
|
|
200
|
+
...signal ? { abort_signal: signal } : {}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
var _transformersSdk, pipelines, getPipeline = async (model, onProgress, options = {}, progressScaleMax = 10) => {
|
|
204
|
+
const cacheKey = getPipelineCacheKey(model);
|
|
205
|
+
if (pipelines.has(cacheKey)) {
|
|
206
|
+
return pipelines.get(cacheKey);
|
|
207
|
+
}
|
|
208
|
+
const fileSizes = new Map;
|
|
209
|
+
const fileProgress = new Map;
|
|
210
|
+
const fileCompleted = new Set;
|
|
211
|
+
const fileFirstSent = new Set;
|
|
212
|
+
const fileLastSent = new Set;
|
|
213
|
+
const fileLastEventTime = new Map;
|
|
214
|
+
const pendingProgressByFile = new Map;
|
|
215
|
+
let throttleTimer = null;
|
|
216
|
+
const THROTTLE_MS = 160;
|
|
217
|
+
const estimatedTinyFiles = 3;
|
|
218
|
+
const estimatedMediumFiles = 1;
|
|
219
|
+
const estimatedTinySize = 1024;
|
|
220
|
+
const estimatedMediumSize = 20971520;
|
|
221
|
+
const estimatedLargeSize = 1073741824;
|
|
222
|
+
const baseEstimate = estimatedTinyFiles * estimatedTinySize + estimatedMediumFiles * estimatedMediumSize;
|
|
223
|
+
const sendProgress = (overallProgress, file, fileProgressValue, isFirst, isLast) => {
|
|
224
|
+
const now = Date.now();
|
|
225
|
+
const lastTime = fileLastEventTime.get(file) || 0;
|
|
226
|
+
const timeSinceLastEvent = now - lastTime;
|
|
227
|
+
const shouldThrottle = !isFirst && !isLast && timeSinceLastEvent < THROTTLE_MS;
|
|
228
|
+
if (shouldThrottle) {
|
|
229
|
+
pendingProgressByFile.set(file, {
|
|
230
|
+
progress: overallProgress,
|
|
231
|
+
file,
|
|
232
|
+
fileProgress: fileProgressValue
|
|
233
|
+
});
|
|
234
|
+
if (!throttleTimer) {
|
|
235
|
+
const timeRemaining = Math.max(1, THROTTLE_MS - timeSinceLastEvent);
|
|
236
|
+
throttleTimer = setTimeout(() => {
|
|
237
|
+
for (const [pendingFile, pending] of pendingProgressByFile.entries()) {
|
|
238
|
+
onProgress(Math.round(pending.progress), "Downloading model", {
|
|
239
|
+
file: pendingFile,
|
|
240
|
+
progress: pending.fileProgress
|
|
241
|
+
});
|
|
242
|
+
fileLastEventTime.set(pendingFile, Date.now());
|
|
243
|
+
}
|
|
244
|
+
pendingProgressByFile.clear();
|
|
245
|
+
throttleTimer = null;
|
|
246
|
+
}, timeRemaining);
|
|
247
|
+
}
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
onProgress(Math.round(overallProgress), "Downloading model", {
|
|
251
|
+
file,
|
|
252
|
+
progress: fileProgressValue
|
|
253
|
+
});
|
|
254
|
+
fileLastEventTime.set(file, now);
|
|
255
|
+
pendingProgressByFile.delete(file);
|
|
256
|
+
if (throttleTimer && pendingProgressByFile.size === 0) {
|
|
257
|
+
clearTimeout(throttleTimer);
|
|
258
|
+
throttleTimer = null;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
let hasSeenSubstantialFile = false;
|
|
262
|
+
const substantialFileThreshold = 1048576;
|
|
263
|
+
const abortSignal = options.abort_signal;
|
|
264
|
+
const progressCallback = (status) => {
|
|
265
|
+
if (abortSignal?.aborted) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (status.status === "progress") {
|
|
269
|
+
const file = status.file;
|
|
270
|
+
const fileTotal = status.total;
|
|
271
|
+
const fileProgressValue = status.progress;
|
|
272
|
+
if (!fileSizes.has(file)) {
|
|
273
|
+
fileSizes.set(file, fileTotal);
|
|
274
|
+
fileProgress.set(file, 0);
|
|
275
|
+
if (fileTotal >= substantialFileThreshold) {
|
|
276
|
+
hasSeenSubstantialFile = true;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
fileProgress.set(file, fileProgressValue);
|
|
280
|
+
const isComplete = fileProgressValue >= 100;
|
|
281
|
+
if (isComplete && !fileCompleted.has(file)) {
|
|
282
|
+
fileCompleted.add(file);
|
|
283
|
+
fileProgress.set(file, 100);
|
|
284
|
+
}
|
|
285
|
+
let actualLoadedSize = 0;
|
|
286
|
+
let actualTotalSize = 0;
|
|
287
|
+
const tinyThreshold = 102400;
|
|
288
|
+
const mediumThreshold = 104857600;
|
|
289
|
+
let seenTinyCount = 0;
|
|
290
|
+
let seenMediumCount = 0;
|
|
291
|
+
let seenLargeCount = 0;
|
|
292
|
+
for (const [trackedFile, size] of fileSizes.entries()) {
|
|
293
|
+
actualTotalSize += size;
|
|
294
|
+
const progress = fileProgress.get(trackedFile) || 0;
|
|
295
|
+
actualLoadedSize += size * progress / 100;
|
|
296
|
+
if (size < tinyThreshold) {
|
|
297
|
+
seenTinyCount++;
|
|
298
|
+
} else if (size < mediumThreshold) {
|
|
299
|
+
seenMediumCount++;
|
|
300
|
+
} else {
|
|
301
|
+
seenLargeCount++;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const unseenTinyFiles = Math.max(0, estimatedTinyFiles - seenTinyCount);
|
|
305
|
+
const unseenMediumFiles = Math.max(0, estimatedMediumFiles - seenMediumCount);
|
|
306
|
+
let estimatedLargeFiles;
|
|
307
|
+
if (seenLargeCount > 0) {
|
|
308
|
+
estimatedLargeFiles = 2;
|
|
309
|
+
} else {
|
|
310
|
+
estimatedLargeFiles = 1;
|
|
311
|
+
}
|
|
312
|
+
const unseenLargeFiles = Math.max(0, estimatedLargeFiles - seenLargeCount);
|
|
313
|
+
const adjustedTotalSize = actualTotalSize + unseenTinyFiles * estimatedTinySize + unseenMediumFiles * estimatedMediumSize + unseenLargeFiles * estimatedLargeSize;
|
|
314
|
+
const rawProgress = adjustedTotalSize > 0 ? actualLoadedSize / adjustedTotalSize * 100 : 0;
|
|
315
|
+
const overallProgress = rawProgress * progressScaleMax / 100;
|
|
316
|
+
const isFirst = !fileFirstSent.has(file);
|
|
317
|
+
const isLast = isComplete && !fileLastSent.has(file);
|
|
318
|
+
if (isFirst) {
|
|
319
|
+
fileFirstSent.add(file);
|
|
320
|
+
}
|
|
321
|
+
if (isLast) {
|
|
322
|
+
fileLastSent.add(file);
|
|
323
|
+
}
|
|
324
|
+
if (hasSeenSubstantialFile) {
|
|
325
|
+
sendProgress(overallProgress, file, fileProgressValue, isFirst, isLast);
|
|
326
|
+
}
|
|
327
|
+
} else if (status.status === "done" || status.status === "download") {
|
|
328
|
+
const file = status.file;
|
|
329
|
+
const fileSize = fileSizes.get(file) || 0;
|
|
330
|
+
if (fileSize >= substantialFileThreshold) {
|
|
331
|
+
hasSeenSubstantialFile = true;
|
|
332
|
+
}
|
|
333
|
+
if (!fileCompleted.has(file)) {
|
|
334
|
+
fileCompleted.add(file);
|
|
335
|
+
fileProgress.set(file, 100);
|
|
336
|
+
let actualLoadedSize = 0;
|
|
337
|
+
let actualTotalSize = 0;
|
|
338
|
+
const tinyThreshold = 102400;
|
|
339
|
+
const mediumThreshold = 104857600;
|
|
340
|
+
let seenTinyCount = 0;
|
|
341
|
+
let seenMediumCount = 0;
|
|
342
|
+
let seenLargeCount = 0;
|
|
343
|
+
for (const [trackedFile, size] of fileSizes.entries()) {
|
|
344
|
+
actualTotalSize += size;
|
|
345
|
+
const progress = fileProgress.get(trackedFile) || 0;
|
|
346
|
+
actualLoadedSize += size * progress / 100;
|
|
347
|
+
if (size < tinyThreshold) {
|
|
348
|
+
seenTinyCount++;
|
|
349
|
+
} else if (size < mediumThreshold) {
|
|
350
|
+
seenMediumCount++;
|
|
351
|
+
} else {
|
|
352
|
+
seenLargeCount++;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const unseenTinyFiles = Math.max(0, estimatedTinyFiles - seenTinyCount);
|
|
356
|
+
const unseenMediumFiles = Math.max(0, estimatedMediumFiles - seenMediumCount);
|
|
357
|
+
let estimatedLargeFiles;
|
|
358
|
+
if (seenLargeCount > 0) {
|
|
359
|
+
estimatedLargeFiles = 2;
|
|
360
|
+
} else {
|
|
361
|
+
estimatedLargeFiles = 1;
|
|
362
|
+
}
|
|
363
|
+
const unseenLargeFiles = Math.max(0, estimatedLargeFiles - seenLargeCount);
|
|
364
|
+
const adjustedTotalSize = actualTotalSize + unseenTinyFiles * estimatedTinySize + unseenMediumFiles * estimatedMediumSize + unseenLargeFiles * estimatedLargeSize;
|
|
365
|
+
const rawProgress = adjustedTotalSize > 0 ? actualLoadedSize / adjustedTotalSize * 100 : 0;
|
|
366
|
+
const overallProgress = rawProgress * progressScaleMax / 100;
|
|
367
|
+
const isLast = !fileLastSent.has(file);
|
|
368
|
+
if (isLast) {
|
|
369
|
+
fileLastSent.add(file);
|
|
370
|
+
if (hasSeenSubstantialFile) {
|
|
371
|
+
sendProgress(overallProgress, file, 100, false, true);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
const pipelineOptions = {
|
|
378
|
+
dtype: model.provider_config.dtype || "q8",
|
|
379
|
+
...model.provider_config.use_external_data_format ? { useExternalDataFormat: model.provider_config.use_external_data_format } : {},
|
|
380
|
+
...model.provider_config.device ? { device: model.provider_config.device } : {},
|
|
381
|
+
...options,
|
|
382
|
+
progress_callback: progressCallback
|
|
383
|
+
};
|
|
384
|
+
if (abortSignal?.aborted) {
|
|
385
|
+
throw new Error("Operation aborted before pipeline creation");
|
|
386
|
+
}
|
|
387
|
+
const pipelineType = model.provider_config.pipeline;
|
|
388
|
+
const abortPromise = new Promise((_, reject) => {
|
|
389
|
+
if (abortSignal) {
|
|
390
|
+
const handleAbort = () => {
|
|
391
|
+
reject(new Error("Pipeline download aborted"));
|
|
392
|
+
};
|
|
393
|
+
if (abortSignal.aborted) {
|
|
394
|
+
handleAbort();
|
|
395
|
+
} else {
|
|
396
|
+
abortSignal.addEventListener("abort", handleAbort, { once: true });
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
const { pipeline } = await loadTransformersSDK();
|
|
401
|
+
const pipelinePromise = pipeline(pipelineType, model.provider_config.model_path, pipelineOptions);
|
|
402
|
+
try {
|
|
403
|
+
const result = await (abortSignal ? Promise.race([pipelinePromise, abortPromise]) : pipelinePromise);
|
|
404
|
+
if (abortSignal?.aborted) {
|
|
405
|
+
throw new Error("Operation aborted after pipeline creation");
|
|
406
|
+
}
|
|
407
|
+
pipelines.set(cacheKey, result);
|
|
408
|
+
return result;
|
|
409
|
+
} catch (error) {
|
|
410
|
+
if (abortSignal?.aborted) {
|
|
411
|
+
throw new Error("Pipeline download aborted");
|
|
412
|
+
}
|
|
413
|
+
throw error;
|
|
414
|
+
}
|
|
415
|
+
}, HFT_Download = async (input, model, onProgress, signal) => {
|
|
416
|
+
await getPipeline(model, onProgress, { abort_signal: signal }, 100);
|
|
417
|
+
return {
|
|
418
|
+
model: input.model
|
|
419
|
+
};
|
|
420
|
+
}, HFT_Unload = async (input, model, onProgress, signal) => {
|
|
421
|
+
const cacheKey = getPipelineCacheKey(model);
|
|
422
|
+
if (pipelines.has(cacheKey)) {
|
|
423
|
+
pipelines.delete(cacheKey);
|
|
424
|
+
onProgress(50, "Pipeline removed from memory");
|
|
425
|
+
}
|
|
426
|
+
const model_path = model.provider_config.model_path;
|
|
427
|
+
await deleteModelCache(model_path);
|
|
428
|
+
onProgress(100, "Model cache deleted");
|
|
429
|
+
return {
|
|
430
|
+
model: input.model
|
|
431
|
+
};
|
|
432
|
+
}, deleteModelCache = async (model_path) => {
|
|
433
|
+
const cache = await caches.open(HTF_CACHE_NAME);
|
|
434
|
+
const keys = await cache.keys();
|
|
435
|
+
const prefix = `/${model_path}/`;
|
|
436
|
+
const requestsToDelete = [];
|
|
437
|
+
for (const request of keys) {
|
|
438
|
+
const url = new URL(request.url);
|
|
439
|
+
if (url.pathname.startsWith(prefix)) {
|
|
440
|
+
requestsToDelete.push(request);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
let deletedCount = 0;
|
|
444
|
+
for (const request of requestsToDelete) {
|
|
445
|
+
try {
|
|
446
|
+
const deleted = await cache.delete(request);
|
|
447
|
+
if (deleted) {
|
|
448
|
+
deletedCount++;
|
|
449
|
+
} else {
|
|
450
|
+
const deletedByUrl = await cache.delete(request.url);
|
|
451
|
+
if (deletedByUrl) {
|
|
452
|
+
deletedCount++;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
} catch (error) {
|
|
456
|
+
console.error(`Failed to delete cache entry: ${request.url}`, error);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}, HFT_TextEmbedding = async (input, model, onProgress, signal) => {
|
|
460
|
+
const generateEmbedding = await getPipeline(model, onProgress, {
|
|
461
|
+
abort_signal: signal
|
|
462
|
+
});
|
|
463
|
+
const hfVector = await generateEmbedding(input.text, {
|
|
464
|
+
pooling: model?.provider_config.pooling || "mean",
|
|
465
|
+
normalize: model?.provider_config.normalize,
|
|
466
|
+
...signal ? { abort_signal: signal } : {}
|
|
467
|
+
});
|
|
468
|
+
const isArrayInput = Array.isArray(input.text);
|
|
469
|
+
const embeddingDim = model?.provider_config.native_dimensions;
|
|
470
|
+
if (isArrayInput && hfVector.dims.length > 1) {
|
|
471
|
+
const [numTexts, vectorDim] = hfVector.dims;
|
|
472
|
+
if (numTexts !== input.text.length) {
|
|
473
|
+
throw new Error(`HuggingFace Embedding tensor batch size does not match input array length: ${numTexts} != ${input.text.length}`);
|
|
474
|
+
}
|
|
475
|
+
if (vectorDim !== embeddingDim) {
|
|
476
|
+
throw new Error(`HuggingFace Embedding vector dimension does not match model dimensions: ${vectorDim} != ${embeddingDim}`);
|
|
477
|
+
}
|
|
478
|
+
const vectors = Array.from({ length: numTexts }, (_, i) => hfVector[i].data);
|
|
479
|
+
return { vector: vectors };
|
|
480
|
+
}
|
|
481
|
+
if (hfVector.size !== embeddingDim) {
|
|
482
|
+
console.warn(`HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${embeddingDim}`, input, hfVector);
|
|
483
|
+
throw new Error(`HuggingFace Embedding vector length does not match model dimensions v${hfVector.size} != m${embeddingDim}`);
|
|
484
|
+
}
|
|
485
|
+
return { vector: hfVector.data };
|
|
486
|
+
}, HFT_TextClassification = async (input, model, onProgress, signal) => {
|
|
487
|
+
if (model?.provider_config?.pipeline === "zero-shot-classification") {
|
|
488
|
+
if (!input.candidateLabels || !Array.isArray(input.candidateLabels) || input.candidateLabels.length === 0) {
|
|
489
|
+
throw new Error("Zero-shot text classification requires candidate labels");
|
|
490
|
+
}
|
|
491
|
+
const zeroShotClassifier = await getPipeline(model, onProgress, {
|
|
492
|
+
abort_signal: signal
|
|
493
|
+
});
|
|
494
|
+
const result2 = await zeroShotClassifier(input.text, input.candidateLabels, {});
|
|
495
|
+
return {
|
|
496
|
+
categories: result2.labels.map((label, idx) => ({
|
|
497
|
+
label,
|
|
498
|
+
score: result2.scores[idx]
|
|
499
|
+
}))
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
const TextClassification = await getPipeline(model, onProgress, {
|
|
503
|
+
abort_signal: signal
|
|
504
|
+
});
|
|
505
|
+
const result = await TextClassification(input.text, {
|
|
506
|
+
top_k: input.maxCategories || undefined,
|
|
507
|
+
...signal ? { abort_signal: signal } : {}
|
|
508
|
+
});
|
|
509
|
+
if (Array.isArray(result[0])) {
|
|
510
|
+
return {
|
|
511
|
+
categories: result[0].map((category) => ({
|
|
512
|
+
label: category.label,
|
|
513
|
+
score: category.score
|
|
514
|
+
}))
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
return {
|
|
518
|
+
categories: result.map((category) => ({
|
|
519
|
+
label: category.label,
|
|
520
|
+
score: category.score
|
|
521
|
+
}))
|
|
522
|
+
};
|
|
523
|
+
}, HFT_TextLanguageDetection = async (input, model, onProgress, signal) => {
|
|
524
|
+
const TextClassification = await getPipeline(model, onProgress, {
|
|
525
|
+
abort_signal: signal
|
|
526
|
+
});
|
|
527
|
+
const result = await TextClassification(input.text, {
|
|
528
|
+
top_k: input.maxLanguages || undefined,
|
|
529
|
+
...signal ? { abort_signal: signal } : {}
|
|
530
|
+
});
|
|
531
|
+
if (Array.isArray(result[0])) {
|
|
532
|
+
return {
|
|
533
|
+
languages: result[0].map((category) => ({
|
|
534
|
+
language: category.label,
|
|
535
|
+
score: category.score
|
|
536
|
+
}))
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
return {
|
|
540
|
+
languages: result.map((category) => ({
|
|
541
|
+
language: category.label,
|
|
542
|
+
score: category.score
|
|
543
|
+
}))
|
|
544
|
+
};
|
|
545
|
+
}, HFT_TextNamedEntityRecognition = async (input, model, onProgress, signal) => {
|
|
546
|
+
const textNamedEntityRecognition = await getPipeline(model, onProgress, {
|
|
547
|
+
abort_signal: signal
|
|
548
|
+
});
|
|
549
|
+
let results = await textNamedEntityRecognition(input.text, {
|
|
550
|
+
ignore_labels: input.blockList,
|
|
551
|
+
...signal ? { abort_signal: signal } : {}
|
|
552
|
+
});
|
|
553
|
+
let entities = [];
|
|
554
|
+
if (!Array.isArray(results)) {
|
|
555
|
+
entities = [results];
|
|
556
|
+
} else {
|
|
557
|
+
entities = results;
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
entities: entities.map((entity) => ({
|
|
561
|
+
entity: entity.entity,
|
|
562
|
+
score: entity.score,
|
|
563
|
+
word: entity.word
|
|
564
|
+
}))
|
|
565
|
+
};
|
|
566
|
+
}, HFT_TextFillMask = async (input, model, onProgress, signal) => {
|
|
567
|
+
const unmasker = await getPipeline(model, onProgress, {
|
|
568
|
+
abort_signal: signal
|
|
569
|
+
});
|
|
570
|
+
let results = await unmasker(input.text);
|
|
571
|
+
let predictions = [];
|
|
572
|
+
if (!Array.isArray(results)) {
|
|
573
|
+
predictions = [results];
|
|
574
|
+
} else {
|
|
575
|
+
predictions = results;
|
|
576
|
+
}
|
|
577
|
+
return {
|
|
578
|
+
predictions: predictions.map((prediction) => ({
|
|
579
|
+
entity: prediction.token_str,
|
|
580
|
+
score: prediction.score,
|
|
581
|
+
sequence: prediction.sequence
|
|
582
|
+
}))
|
|
583
|
+
};
|
|
584
|
+
}, HFT_TextGeneration = async (input, model, onProgress, signal) => {
|
|
585
|
+
const generateText = await getPipeline(model, onProgress, {
|
|
586
|
+
abort_signal: signal
|
|
587
|
+
});
|
|
588
|
+
const streamer = createTextStreamer(generateText.tokenizer, onProgress, signal);
|
|
589
|
+
let results = await generateText(input.prompt, {
|
|
590
|
+
streamer,
|
|
591
|
+
...signal ? { abort_signal: signal } : {}
|
|
592
|
+
});
|
|
593
|
+
if (!Array.isArray(results)) {
|
|
594
|
+
results = [results];
|
|
595
|
+
}
|
|
596
|
+
let text = results[0]?.generated_text;
|
|
597
|
+
if (Array.isArray(text)) {
|
|
598
|
+
text = text[text.length - 1]?.content;
|
|
599
|
+
}
|
|
600
|
+
return {
|
|
601
|
+
text
|
|
602
|
+
};
|
|
603
|
+
}, HFT_TextTranslation = async (input, model, onProgress, signal) => {
|
|
604
|
+
const translate = await getPipeline(model, onProgress, {
|
|
605
|
+
abort_signal: signal
|
|
606
|
+
});
|
|
607
|
+
const streamer = createTextStreamer(translate.tokenizer, onProgress);
|
|
608
|
+
const result = await translate(input.text, {
|
|
609
|
+
src_lang: input.source_lang,
|
|
610
|
+
tgt_lang: input.target_lang,
|
|
611
|
+
streamer,
|
|
612
|
+
...signal ? { abort_signal: signal } : {}
|
|
613
|
+
});
|
|
614
|
+
const translatedText = Array.isArray(result) ? result[0]?.translation_text || "" : result?.translation_text || "";
|
|
615
|
+
return {
|
|
616
|
+
text: translatedText,
|
|
617
|
+
target_lang: input.target_lang
|
|
618
|
+
};
|
|
619
|
+
}, HFT_TextRewriter = async (input, model, onProgress, signal) => {
|
|
620
|
+
const generateText = await getPipeline(model, onProgress, {
|
|
621
|
+
abort_signal: signal
|
|
622
|
+
});
|
|
623
|
+
const streamer = createTextStreamer(generateText.tokenizer, onProgress);
|
|
624
|
+
const promptedText = (input.prompt ? input.prompt + `
|
|
625
|
+
` : "") + input.text;
|
|
626
|
+
let results = await generateText(promptedText, {
|
|
627
|
+
streamer,
|
|
628
|
+
...signal ? { abort_signal: signal } : {}
|
|
629
|
+
});
|
|
630
|
+
if (!Array.isArray(results)) {
|
|
631
|
+
results = [results];
|
|
632
|
+
}
|
|
633
|
+
let text = results[0]?.generated_text;
|
|
634
|
+
if (Array.isArray(text)) {
|
|
635
|
+
text = text[text.length - 1]?.content;
|
|
636
|
+
}
|
|
637
|
+
if (text === promptedText) {
|
|
638
|
+
throw new Error("Rewriter failed to generate new text");
|
|
639
|
+
}
|
|
640
|
+
return {
|
|
641
|
+
text
|
|
642
|
+
};
|
|
643
|
+
}, HFT_TextSummary = async (input, model, onProgress, signal) => {
|
|
644
|
+
const generateSummary = await getPipeline(model, onProgress, {
|
|
645
|
+
abort_signal: signal
|
|
646
|
+
});
|
|
647
|
+
const streamer = createTextStreamer(generateSummary.tokenizer, onProgress);
|
|
648
|
+
let result = await generateSummary(input.text, {
|
|
649
|
+
streamer,
|
|
650
|
+
...signal ? { abort_signal: signal } : {}
|
|
651
|
+
});
|
|
652
|
+
let summaryText = "";
|
|
653
|
+
if (Array.isArray(result)) {
|
|
654
|
+
summaryText = result[0]?.summary_text || "";
|
|
655
|
+
} else {
|
|
656
|
+
summaryText = result?.summary_text || "";
|
|
657
|
+
}
|
|
658
|
+
return {
|
|
659
|
+
text: summaryText
|
|
660
|
+
};
|
|
661
|
+
}, HFT_TextQuestionAnswer = async (input, model, onProgress, signal) => {
|
|
662
|
+
const generateAnswer = await getPipeline(model, onProgress, {
|
|
663
|
+
abort_signal: signal
|
|
664
|
+
});
|
|
665
|
+
const streamer = createTextStreamer(generateAnswer.tokenizer, onProgress);
|
|
666
|
+
const result = await generateAnswer(input.question, input.context, {
|
|
667
|
+
streamer,
|
|
668
|
+
...signal ? { abort_signal: signal } : {}
|
|
669
|
+
});
|
|
670
|
+
let answerText = "";
|
|
671
|
+
if (Array.isArray(result)) {
|
|
672
|
+
answerText = result[0]?.answer || "";
|
|
673
|
+
} else {
|
|
674
|
+
answerText = result?.answer || "";
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
text: answerText
|
|
678
|
+
};
|
|
679
|
+
}, HFT_ImageSegmentation = async (input, model, onProgress, signal) => {
|
|
680
|
+
const segmenter = await getPipeline(model, onProgress, {
|
|
681
|
+
abort_signal: signal
|
|
682
|
+
});
|
|
683
|
+
const result = await segmenter(input.image, {
|
|
684
|
+
threshold: input.threshold,
|
|
685
|
+
mask_threshold: input.maskThreshold,
|
|
686
|
+
...signal ? { abort_signal: signal } : {}
|
|
687
|
+
});
|
|
688
|
+
const masks = Array.isArray(result) ? result : [result];
|
|
689
|
+
const processedMasks = await Promise.all(masks.map(async (mask) => ({
|
|
690
|
+
label: mask.label || "",
|
|
691
|
+
score: mask.score || 0,
|
|
692
|
+
mask: {}
|
|
693
|
+
})));
|
|
694
|
+
return {
|
|
695
|
+
masks: processedMasks
|
|
696
|
+
};
|
|
697
|
+
}, HFT_ImageToText = async (input, model, onProgress, signal) => {
|
|
698
|
+
const captioner = await getPipeline(model, onProgress, {
|
|
699
|
+
abort_signal: signal
|
|
700
|
+
});
|
|
701
|
+
const result = await captioner(input.image, {
|
|
702
|
+
max_new_tokens: input.maxTokens,
|
|
703
|
+
...signal ? { abort_signal: signal } : {}
|
|
704
|
+
});
|
|
705
|
+
const text = Array.isArray(result) ? result[0]?.generated_text : result?.generated_text;
|
|
706
|
+
return {
|
|
707
|
+
text: text || ""
|
|
708
|
+
};
|
|
709
|
+
}, HFT_BackgroundRemoval = async (input, model, onProgress, signal) => {
|
|
710
|
+
const remover = await getPipeline(model, onProgress, {
|
|
711
|
+
abort_signal: signal
|
|
712
|
+
});
|
|
713
|
+
const result = await remover(input.image, {
|
|
714
|
+
...signal ? { abort_signal: signal } : {}
|
|
715
|
+
});
|
|
716
|
+
const resultImage = Array.isArray(result) ? result[0] : result;
|
|
717
|
+
return {
|
|
718
|
+
image: imageToBase64(resultImage)
|
|
719
|
+
};
|
|
720
|
+
}, HFT_ImageEmbedding = async (input, model, onProgress, signal) => {
|
|
721
|
+
const embedder = await getPipeline(model, onProgress, {
|
|
722
|
+
abort_signal: signal
|
|
723
|
+
});
|
|
724
|
+
const result = await embedder(input.image);
|
|
725
|
+
return {
|
|
726
|
+
vector: result.data
|
|
727
|
+
};
|
|
728
|
+
}, HFT_ImageClassification = async (input, model, onProgress, signal) => {
|
|
729
|
+
if (model?.provider_config?.pipeline === "zero-shot-image-classification") {
|
|
730
|
+
if (!input.categories || !Array.isArray(input.categories) || input.categories.length === 0) {
|
|
731
|
+
console.warn("Zero-shot image classification requires categories", input);
|
|
732
|
+
throw new Error("Zero-shot image classification requires categories");
|
|
733
|
+
}
|
|
734
|
+
const zeroShotClassifier = await getPipeline(model, onProgress, {
|
|
735
|
+
abort_signal: signal
|
|
736
|
+
});
|
|
737
|
+
const result2 = await zeroShotClassifier(input.image, input.categories, {});
|
|
738
|
+
const results2 = Array.isArray(result2) ? result2 : [result2];
|
|
739
|
+
return {
|
|
740
|
+
categories: results2.map((r) => ({
|
|
741
|
+
label: r.label,
|
|
742
|
+
score: r.score
|
|
743
|
+
}))
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
const classifier = await getPipeline(model, onProgress, {
|
|
747
|
+
abort_signal: signal
|
|
748
|
+
});
|
|
749
|
+
const result = await classifier(input.image, {
|
|
750
|
+
top_k: input.maxCategories,
|
|
751
|
+
...signal ? { abort_signal: signal } : {}
|
|
752
|
+
});
|
|
753
|
+
const results = Array.isArray(result) ? result : [result];
|
|
754
|
+
return {
|
|
755
|
+
categories: results.map((r) => ({
|
|
756
|
+
label: r.label,
|
|
757
|
+
score: r.score
|
|
758
|
+
}))
|
|
759
|
+
};
|
|
760
|
+
}, HFT_ObjectDetection = async (input, model, onProgress, signal) => {
|
|
761
|
+
if (model?.provider_config?.pipeline === "zero-shot-object-detection") {
|
|
762
|
+
if (!input.labels || !Array.isArray(input.labels) || input.labels.length === 0) {
|
|
763
|
+
throw new Error("Zero-shot object detection requires labels");
|
|
764
|
+
}
|
|
765
|
+
const zeroShotDetector = await getPipeline(model, onProgress, {
|
|
766
|
+
abort_signal: signal
|
|
767
|
+
});
|
|
768
|
+
const result2 = await zeroShotDetector(input.image, Array.from(input.labels), {
|
|
769
|
+
threshold: input.threshold
|
|
770
|
+
});
|
|
771
|
+
const detections2 = Array.isArray(result2) ? result2 : [result2];
|
|
772
|
+
return {
|
|
773
|
+
detections: detections2.map((d) => ({
|
|
774
|
+
label: d.label,
|
|
775
|
+
score: d.score,
|
|
776
|
+
box: d.box
|
|
777
|
+
}))
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
const detector = await getPipeline(model, onProgress, {
|
|
781
|
+
abort_signal: signal
|
|
782
|
+
});
|
|
783
|
+
const result = await detector(input.image, {
|
|
784
|
+
threshold: input.threshold,
|
|
785
|
+
...signal ? { abort_signal: signal } : {}
|
|
786
|
+
});
|
|
787
|
+
const detections = Array.isArray(result) ? result : [result];
|
|
788
|
+
return {
|
|
789
|
+
detections: detections.map((d) => ({
|
|
790
|
+
label: d.label,
|
|
791
|
+
score: d.score,
|
|
792
|
+
box: d.box
|
|
793
|
+
}))
|
|
794
|
+
};
|
|
795
|
+
}, HFT_TextGeneration_Stream = async function* (input, model, signal) {
|
|
796
|
+
const noopProgress = () => {};
|
|
797
|
+
const generateText = await getPipeline(model, noopProgress, {
|
|
798
|
+
abort_signal: signal
|
|
799
|
+
});
|
|
800
|
+
const queue = createStreamEventQueue();
|
|
801
|
+
const streamer = createStreamingTextStreamer(generateText.tokenizer, queue, signal);
|
|
802
|
+
const pipelinePromise = generateText(input.prompt, {
|
|
803
|
+
streamer,
|
|
804
|
+
...signal ? { abort_signal: signal } : {}
|
|
805
|
+
}).then(() => queue.done(), (err) => queue.error(err));
|
|
806
|
+
yield* queue.iterable;
|
|
807
|
+
await pipelinePromise;
|
|
808
|
+
yield { type: "finish", data: {} };
|
|
809
|
+
}, HFT_TextRewriter_Stream = async function* (input, model, signal) {
|
|
810
|
+
const noopProgress = () => {};
|
|
811
|
+
const generateText = await getPipeline(model, noopProgress, {
|
|
812
|
+
abort_signal: signal
|
|
813
|
+
});
|
|
814
|
+
const queue = createStreamEventQueue();
|
|
815
|
+
const streamer = createStreamingTextStreamer(generateText.tokenizer, queue);
|
|
816
|
+
const promptedText = (input.prompt ? input.prompt + `
|
|
817
|
+
` : "") + input.text;
|
|
818
|
+
const pipelinePromise = generateText(promptedText, {
|
|
819
|
+
streamer,
|
|
820
|
+
...signal ? { abort_signal: signal } : {}
|
|
821
|
+
}).then(() => queue.done(), (err) => queue.error(err));
|
|
822
|
+
yield* queue.iterable;
|
|
823
|
+
await pipelinePromise;
|
|
824
|
+
yield { type: "finish", data: {} };
|
|
825
|
+
}, HFT_TextSummary_Stream = async function* (input, model, signal) {
|
|
826
|
+
const noopProgress = () => {};
|
|
827
|
+
const generateSummary = await getPipeline(model, noopProgress, {
|
|
828
|
+
abort_signal: signal
|
|
829
|
+
});
|
|
830
|
+
const queue = createStreamEventQueue();
|
|
831
|
+
const streamer = createStreamingTextStreamer(generateSummary.tokenizer, queue);
|
|
832
|
+
const pipelinePromise = generateSummary(input.text, {
|
|
833
|
+
streamer,
|
|
834
|
+
...signal ? { abort_signal: signal } : {}
|
|
835
|
+
}).then(() => queue.done(), (err) => queue.error(err));
|
|
836
|
+
yield* queue.iterable;
|
|
837
|
+
await pipelinePromise;
|
|
838
|
+
yield { type: "finish", data: {} };
|
|
839
|
+
}, HFT_TextQuestionAnswer_Stream = async function* (input, model, signal) {
|
|
840
|
+
const noopProgress = () => {};
|
|
841
|
+
const generateAnswer = await getPipeline(model, noopProgress, {
|
|
842
|
+
abort_signal: signal
|
|
843
|
+
});
|
|
844
|
+
const queue = createStreamEventQueue();
|
|
845
|
+
const streamer = createStreamingTextStreamer(generateAnswer.tokenizer, queue);
|
|
846
|
+
let pipelineResult;
|
|
847
|
+
const pipelinePromise = generateAnswer(input.question, input.context, {
|
|
848
|
+
streamer,
|
|
849
|
+
...signal ? { abort_signal: signal } : {}
|
|
850
|
+
}).then((result) => {
|
|
851
|
+
pipelineResult = result;
|
|
852
|
+
queue.done();
|
|
853
|
+
}, (err) => queue.error(err));
|
|
854
|
+
yield* queue.iterable;
|
|
855
|
+
await pipelinePromise;
|
|
856
|
+
let answerText = "";
|
|
857
|
+
if (pipelineResult !== undefined) {
|
|
858
|
+
if (Array.isArray(pipelineResult)) {
|
|
859
|
+
answerText = pipelineResult[0]?.answer ?? "";
|
|
860
|
+
} else {
|
|
861
|
+
answerText = pipelineResult?.answer ?? "";
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
yield { type: "finish", data: { text: answerText } };
|
|
865
|
+
}, HFT_TextTranslation_Stream = async function* (input, model, signal) {
|
|
866
|
+
const noopProgress = () => {};
|
|
867
|
+
const translate = await getPipeline(model, noopProgress, {
|
|
868
|
+
abort_signal: signal
|
|
869
|
+
});
|
|
870
|
+
const queue = createStreamEventQueue();
|
|
871
|
+
const streamer = createStreamingTextStreamer(translate.tokenizer, queue);
|
|
872
|
+
const pipelinePromise = translate(input.text, {
|
|
873
|
+
src_lang: input.source_lang,
|
|
874
|
+
tgt_lang: input.target_lang,
|
|
875
|
+
streamer,
|
|
876
|
+
...signal ? { abort_signal: signal } : {}
|
|
877
|
+
}).then(() => queue.done(), (err) => queue.error(err));
|
|
878
|
+
yield* queue.iterable;
|
|
879
|
+
await pipelinePromise;
|
|
880
|
+
yield { type: "finish", data: { target_lang: input.target_lang } };
|
|
881
|
+
}, HFT_TASKS, HFT_STREAM_TASKS;
|
|
882
|
+
var init_HFT_JobRunFns = __esm(() => {
|
|
883
|
+
init_HFT_Constants();
|
|
884
|
+
pipelines = new Map;
|
|
885
|
+
HFT_TASKS = {
|
|
886
|
+
DownloadModelTask: HFT_Download,
|
|
887
|
+
UnloadModelTask: HFT_Unload,
|
|
888
|
+
TextEmbeddingTask: HFT_TextEmbedding,
|
|
889
|
+
TextGenerationTask: HFT_TextGeneration,
|
|
890
|
+
TextQuestionAnswerTask: HFT_TextQuestionAnswer,
|
|
891
|
+
TextLanguageDetectionTask: HFT_TextLanguageDetection,
|
|
892
|
+
TextClassificationTask: HFT_TextClassification,
|
|
893
|
+
TextFillMaskTask: HFT_TextFillMask,
|
|
894
|
+
TextNamedEntityRecognitionTask: HFT_TextNamedEntityRecognition,
|
|
895
|
+
TextRewriterTask: HFT_TextRewriter,
|
|
896
|
+
TextSummaryTask: HFT_TextSummary,
|
|
897
|
+
TextTranslationTask: HFT_TextTranslation,
|
|
898
|
+
ImageSegmentationTask: HFT_ImageSegmentation,
|
|
899
|
+
ImageToTextTask: HFT_ImageToText,
|
|
900
|
+
BackgroundRemovalTask: HFT_BackgroundRemoval,
|
|
901
|
+
ImageEmbeddingTask: HFT_ImageEmbedding,
|
|
902
|
+
ImageClassificationTask: HFT_ImageClassification,
|
|
903
|
+
ObjectDetectionTask: HFT_ObjectDetection
|
|
904
|
+
};
|
|
905
|
+
HFT_STREAM_TASKS = {
|
|
906
|
+
TextGenerationTask: HFT_TextGeneration_Stream,
|
|
907
|
+
TextRewriterTask: HFT_TextRewriter_Stream,
|
|
908
|
+
TextSummaryTask: HFT_TextSummary_Stream,
|
|
909
|
+
TextQuestionAnswerTask: HFT_TextQuestionAnswer_Stream,
|
|
910
|
+
TextTranslationTask: HFT_TextTranslation_Stream
|
|
911
|
+
};
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
// src/hf-transformers/index.ts
|
|
915
|
+
init_HFT_Constants();
|
|
916
|
+
init_HFT_JobRunFns();
|
|
917
|
+
|
|
918
|
+
// src/hf-transformers/common/HFT_ModelSchema.ts
|
|
919
|
+
init_HFT_Constants();
|
|
920
|
+
import { ModelConfigSchema, ModelRecordSchema } from "@workglow/ai";
|
|
921
|
+
var HfTransformersOnnxModelSchema = {
|
|
922
|
+
type: "object",
|
|
923
|
+
properties: {
|
|
924
|
+
provider: {
|
|
925
|
+
const: HF_TRANSFORMERS_ONNX,
|
|
926
|
+
description: "Discriminator: ONNX runtime backend."
|
|
927
|
+
},
|
|
928
|
+
provider_config: {
|
|
929
|
+
type: "object",
|
|
930
|
+
description: "ONNX runtime-specific options.",
|
|
931
|
+
properties: {
|
|
932
|
+
pipeline: {
|
|
933
|
+
type: "string",
|
|
934
|
+
enum: Object.values(PipelineUseCase),
|
|
935
|
+
description: "Pipeline type for the ONNX model.",
|
|
936
|
+
default: "text-generation"
|
|
937
|
+
},
|
|
938
|
+
model_path: {
|
|
939
|
+
type: "string",
|
|
940
|
+
description: "Filesystem path or URI for the ONNX model."
|
|
941
|
+
},
|
|
942
|
+
dtype: {
|
|
943
|
+
type: "string",
|
|
944
|
+
enum: Object.values(QuantizationDataType),
|
|
945
|
+
description: "Data type for the ONNX model.",
|
|
946
|
+
default: "auto"
|
|
947
|
+
},
|
|
948
|
+
device: {
|
|
949
|
+
type: "string",
|
|
950
|
+
enum: ["cpu", "gpu", "webgpu", "wasm", "metal"],
|
|
951
|
+
description: "High-level device selection.",
|
|
952
|
+
default: "webgpu"
|
|
953
|
+
},
|
|
954
|
+
execution_providers: {
|
|
955
|
+
type: "array",
|
|
956
|
+
items: { type: "string" },
|
|
957
|
+
description: "Raw ONNX Runtime execution provider identifiers.",
|
|
958
|
+
"x-ui-hidden": true
|
|
959
|
+
},
|
|
960
|
+
intra_op_num_threads: {
|
|
961
|
+
type: "integer",
|
|
962
|
+
minimum: 1
|
|
963
|
+
},
|
|
964
|
+
inter_op_num_threads: {
|
|
965
|
+
type: "integer",
|
|
966
|
+
minimum: 1
|
|
967
|
+
},
|
|
968
|
+
use_external_data_format: {
|
|
969
|
+
type: "boolean",
|
|
970
|
+
description: "Whether the model uses external data format."
|
|
971
|
+
},
|
|
972
|
+
native_dimensions: {
|
|
973
|
+
type: "integer",
|
|
974
|
+
description: "The native dimensions of the model."
|
|
975
|
+
},
|
|
976
|
+
pooling: {
|
|
977
|
+
type: "string",
|
|
978
|
+
enum: ["mean", "last_token", "cls"],
|
|
979
|
+
description: "The pooling strategy to use for the model.",
|
|
980
|
+
default: "mean"
|
|
981
|
+
},
|
|
982
|
+
normalize: {
|
|
983
|
+
type: "boolean",
|
|
984
|
+
description: "Whether the model uses normalization.",
|
|
985
|
+
default: true
|
|
986
|
+
},
|
|
987
|
+
language_style: {
|
|
988
|
+
type: "string",
|
|
989
|
+
description: "The language style of the model."
|
|
990
|
+
},
|
|
991
|
+
mrl: {
|
|
992
|
+
type: "boolean",
|
|
993
|
+
description: "Whether the model uses matryoshka.",
|
|
994
|
+
default: false
|
|
995
|
+
}
|
|
996
|
+
},
|
|
997
|
+
required: ["model_path", "pipeline"],
|
|
998
|
+
additionalProperties: false,
|
|
999
|
+
if: {
|
|
1000
|
+
properties: {
|
|
1001
|
+
pipeline: {
|
|
1002
|
+
const: "feature-extraction"
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
},
|
|
1006
|
+
then: {
|
|
1007
|
+
required: ["native_dimensions"]
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
},
|
|
1011
|
+
required: ["provider", "provider_config"],
|
|
1012
|
+
additionalProperties: true
|
|
1013
|
+
};
|
|
1014
|
+
var HfTransformersOnnxModelRecordSchema = {
|
|
1015
|
+
type: "object",
|
|
1016
|
+
properties: {
|
|
1017
|
+
...ModelRecordSchema.properties,
|
|
1018
|
+
...HfTransformersOnnxModelSchema.properties
|
|
1019
|
+
},
|
|
1020
|
+
required: [...ModelRecordSchema.required, ...HfTransformersOnnxModelSchema.required],
|
|
1021
|
+
additionalProperties: false
|
|
1022
|
+
};
|
|
1023
|
+
var HfTransformersOnnxModelConfigSchema = {
|
|
1024
|
+
type: "object",
|
|
1025
|
+
properties: {
|
|
1026
|
+
...ModelConfigSchema.properties,
|
|
1027
|
+
...HfTransformersOnnxModelSchema.properties
|
|
1028
|
+
},
|
|
1029
|
+
required: [...ModelConfigSchema.required, ...HfTransformersOnnxModelSchema.required],
|
|
1030
|
+
additionalProperties: false
|
|
1031
|
+
};
|
|
1032
|
+
// src/hf-transformers/HFT_Worker.ts
|
|
1033
|
+
init_HFT_JobRunFns();
|
|
1034
|
+
import { globalServiceRegistry, parentPort, WORKER_SERVER } from "@workglow/util";
|
|
1035
|
+
|
|
1036
|
+
// src/hf-transformers/HuggingFaceTransformersProvider.ts
|
|
1037
|
+
init_HFT_Constants();
|
|
1038
|
+
import {
|
|
1039
|
+
AiProvider
|
|
1040
|
+
} from "@workglow/ai";
|
|
1041
|
+
|
|
1042
|
+
class HuggingFaceTransformersProvider extends AiProvider {
|
|
1043
|
+
name = HF_TRANSFORMERS_ONNX;
|
|
1044
|
+
taskTypes = [
|
|
1045
|
+
"DownloadModelTask",
|
|
1046
|
+
"UnloadModelTask",
|
|
1047
|
+
"TextEmbeddingTask",
|
|
1048
|
+
"TextGenerationTask",
|
|
1049
|
+
"TextQuestionAnswerTask",
|
|
1050
|
+
"TextLanguageDetectionTask",
|
|
1051
|
+
"TextClassificationTask",
|
|
1052
|
+
"TextFillMaskTask",
|
|
1053
|
+
"TextNamedEntityRecognitionTask",
|
|
1054
|
+
"TextRewriterTask",
|
|
1055
|
+
"TextSummaryTask",
|
|
1056
|
+
"TextTranslationTask",
|
|
1057
|
+
"ImageSegmentationTask",
|
|
1058
|
+
"ImageToTextTask",
|
|
1059
|
+
"BackgroundRemovalTask",
|
|
1060
|
+
"ImageEmbeddingTask",
|
|
1061
|
+
"ImageClassificationTask",
|
|
1062
|
+
"ObjectDetectionTask"
|
|
1063
|
+
];
|
|
1064
|
+
constructor(tasks, streamTasks) {
|
|
1065
|
+
super(tasks, streamTasks);
|
|
1066
|
+
}
|
|
1067
|
+
async onInitialize(options) {
|
|
1068
|
+
if (options.mode === "inline") {
|
|
1069
|
+
const { env } = await import("@sroussey/transformers");
|
|
1070
|
+
env.backends.onnx.wasm.proxy = true;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
async dispose() {
|
|
1074
|
+
if (this.tasks) {
|
|
1075
|
+
const { clearPipelineCache: clearPipelineCache2 } = await Promise.resolve().then(() => (init_HFT_JobRunFns(), exports_HFT_JobRunFns));
|
|
1076
|
+
clearPipelineCache2();
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// src/hf-transformers/HFT_Worker.ts
|
|
1082
|
+
function HFT_WORKER_JOBRUN_REGISTER() {
|
|
1083
|
+
const workerServer = globalServiceRegistry.get(WORKER_SERVER);
|
|
1084
|
+
new HuggingFaceTransformersProvider(HFT_TASKS, HFT_STREAM_TASKS).registerOnWorkerServer(workerServer);
|
|
1085
|
+
parentPort.postMessage({ type: "ready" });
|
|
1086
|
+
console.log("HFT_WORKER_JOBRUN registered");
|
|
1087
|
+
}
|
|
1088
|
+
export {
|
|
1089
|
+
clearPipelineCache,
|
|
1090
|
+
VisionPipelineUseCase,
|
|
1091
|
+
TextPipelineUseCase,
|
|
1092
|
+
QuantizationDataType,
|
|
1093
|
+
PipelineUseCase,
|
|
1094
|
+
MultimodalPipelineUseCase,
|
|
1095
|
+
HuggingFaceTransformersProvider,
|
|
1096
|
+
HfTransformersOnnxModelSchema,
|
|
1097
|
+
HfTransformersOnnxModelRecordSchema,
|
|
1098
|
+
HfTransformersOnnxModelConfigSchema,
|
|
1099
|
+
HTF_CACHE_NAME,
|
|
1100
|
+
HF_TRANSFORMERS_ONNX,
|
|
1101
|
+
HFT_WORKER_JOBRUN_REGISTER,
|
|
1102
|
+
HFT_Unload,
|
|
1103
|
+
HFT_TextTranslation_Stream,
|
|
1104
|
+
HFT_TextTranslation,
|
|
1105
|
+
HFT_TextSummary_Stream,
|
|
1106
|
+
HFT_TextSummary,
|
|
1107
|
+
HFT_TextRewriter_Stream,
|
|
1108
|
+
HFT_TextRewriter,
|
|
1109
|
+
HFT_TextQuestionAnswer_Stream,
|
|
1110
|
+
HFT_TextQuestionAnswer,
|
|
1111
|
+
HFT_TextNamedEntityRecognition,
|
|
1112
|
+
HFT_TextLanguageDetection,
|
|
1113
|
+
HFT_TextGeneration_Stream,
|
|
1114
|
+
HFT_TextGeneration,
|
|
1115
|
+
HFT_TextFillMask,
|
|
1116
|
+
HFT_TextEmbedding,
|
|
1117
|
+
HFT_TextClassification,
|
|
1118
|
+
HFT_TASKS,
|
|
1119
|
+
HFT_STREAM_TASKS,
|
|
1120
|
+
HFT_ObjectDetection,
|
|
1121
|
+
HFT_ImageToText,
|
|
1122
|
+
HFT_ImageSegmentation,
|
|
1123
|
+
HFT_ImageEmbedding,
|
|
1124
|
+
HFT_ImageClassification,
|
|
1125
|
+
HFT_Download,
|
|
1126
|
+
HFT_BackgroundRemoval,
|
|
1127
|
+
AudioPipelineUseCase
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
//# debugId=778CAE4E83EF216464756E2164756E21
|