@camstack/addon-post-analysis 1.2.135 → 1.2.137
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/{dist-kn_4KEmG.js → dist-5kMCMfln.js} +127 -0
- package/dist/{dist-BAN19J7s.mjs → dist-DTdJBWXu.mjs} +127 -0
- package/dist/embedding-encoder/index.js +12 -349
- package/dist/embedding-encoder/index.mjs +11 -348
- package/dist/pipeline-analytics/_stub.js +1 -1
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CnLNNc0Y.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-b6u3Weak.mjs} +3 -3
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CmYGqEiA.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-7L4CyDzy.mjs → hostInit-DDh-f-wy.mjs} +3 -3
- package/dist/pipeline-analytics/index.js +923 -134
- package/dist/pipeline-analytics/index.mjs +923 -134
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-D_xOplZC.mjs +0 -26
|
@@ -2,17 +2,13 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-5kMCMfln.js");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
|
-
let node_fs$1 = require_dist.__toESM(node_fs, 1);
|
|
8
7
|
node_fs = require_dist.__toESM(node_fs);
|
|
9
8
|
let node_path = require("node:path");
|
|
10
|
-
let node_path$1 = require_dist.__toESM(node_path, 1);
|
|
11
9
|
node_path = require_dist.__toESM(node_path);
|
|
12
|
-
require("node:crypto");
|
|
13
10
|
let node_child_process = require("node:child_process");
|
|
14
|
-
let
|
|
15
|
-
let node_zlib = require("node:zlib");
|
|
11
|
+
let _camstack_system_addon_utils = require("@camstack/system/addon-utils");
|
|
16
12
|
//#region src/embedding-encoder/shared/process-memory.ts
|
|
17
13
|
/**
|
|
18
14
|
* Read a child process's memory footprint for the pool memory watchdog.
|
|
@@ -60,294 +56,6 @@ function readViaPs(pid) {
|
|
|
60
56
|
});
|
|
61
57
|
}
|
|
62
58
|
//#endregion
|
|
63
|
-
//#region ../system/dist/file-data-plane-BhKdxJgf.mjs
|
|
64
|
-
function isNonEmptyFile(filePath) {
|
|
65
|
-
return node_fs$1.existsSync(filePath) && node_fs$1.statSync(filePath).size > 0;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Sibling files of a single-file (non-directory) format — extra files the
|
|
69
|
-
* format needs, fetched from the same remote directory as `url` and stored
|
|
70
|
-
* flat alongside the main file in `modelsDir`. Catalog-declared via
|
|
71
|
-
* `formatEntry.files`, e.g. OpenVINO IR lists its `.bin` weights next to the
|
|
72
|
-
* `.xml`. The downloader stays format-agnostic; the convention lives in the
|
|
73
|
-
* catalog data (like `MLPACKAGE_FILES` for the directory case).
|
|
74
|
-
*/
|
|
75
|
-
function siblingFilesFor(formatEntry) {
|
|
76
|
-
return formatEntry.isDirectory ? [] : formatEntry.files ?? [];
|
|
77
|
-
}
|
|
78
|
-
/** Resolve a sibling's remote URL relative to the main file's directory. */
|
|
79
|
-
function siblingUrl(mainUrl, sibling) {
|
|
80
|
-
return mainUrl.replace(/[^/]+$/, sibling);
|
|
81
|
-
}
|
|
82
|
-
/** Build fetch headers, including HF auth token for huggingface.co URLs */
|
|
83
|
-
function buildHeaders(url) {
|
|
84
|
-
const headers = { "User-Agent": "CamStack/1.0" };
|
|
85
|
-
const hfToken = process.env["HF_TOKEN"] ?? process.env["HUGGING_FACE_HUB_TOKEN"];
|
|
86
|
-
if (hfToken && url.includes("huggingface.co")) headers["Authorization"] = `Bearer ${hfToken}`;
|
|
87
|
-
return headers;
|
|
88
|
-
}
|
|
89
|
-
var DEFAULT_MAX_REDIRECTS = 5;
|
|
90
|
-
function normalizeDownloadOptions(third) {
|
|
91
|
-
if (typeof third === "function") return { onProgress: third };
|
|
92
|
-
return third ?? {};
|
|
93
|
-
}
|
|
94
|
-
function isRedirectStatus(status) {
|
|
95
|
-
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
96
|
-
}
|
|
97
|
-
function resolveRedirectUrl(current, location) {
|
|
98
|
-
return new URL(location, current);
|
|
99
|
-
}
|
|
100
|
-
async function downloadFile(url, destPath, onProgressOrOptions) {
|
|
101
|
-
if (node_fs$1.existsSync(destPath)) return destPath;
|
|
102
|
-
const opts = normalizeDownloadOptions(onProgressOrOptions);
|
|
103
|
-
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
104
|
-
const maxRedirects = opts.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
|
|
105
|
-
node_fs$1.mkdirSync(node_path$1.dirname(destPath), { recursive: true });
|
|
106
|
-
const tmpPath = destPath + ".downloading";
|
|
107
|
-
try {
|
|
108
|
-
let current = url;
|
|
109
|
-
const seen = /* @__PURE__ */ new Set();
|
|
110
|
-
let response;
|
|
111
|
-
const manual = opts.redirectPolicy !== void 0;
|
|
112
|
-
for (let hop = 0; hop <= maxRedirects; hop++) {
|
|
113
|
-
const parsed = new URL(current);
|
|
114
|
-
if (opts.redirectPolicy) opts.redirectPolicy(parsed, hop);
|
|
115
|
-
if (seen.has(parsed.href)) throw new Error(`Redirect loop detected at ${parsed.href}`);
|
|
116
|
-
seen.add(parsed.href);
|
|
117
|
-
const controller = opts.timeoutMs !== void 0 ? new AbortController() : void 0;
|
|
118
|
-
const timer = controller && opts.timeoutMs !== void 0 ? setTimeout(() => controller.abort(), opts.timeoutMs) : void 0;
|
|
119
|
-
try {
|
|
120
|
-
response = await fetchImpl(current, {
|
|
121
|
-
redirect: manual ? "manual" : "follow",
|
|
122
|
-
headers: buildHeaders(current),
|
|
123
|
-
...controller ? { signal: controller.signal } : {}
|
|
124
|
-
});
|
|
125
|
-
} finally {
|
|
126
|
-
if (timer) clearTimeout(timer);
|
|
127
|
-
}
|
|
128
|
-
if (manual && isRedirectStatus(response.status)) {
|
|
129
|
-
const location = response.headers.get("location");
|
|
130
|
-
if (!location) throw new Error(`Redirect ${response.status} missing Location header`);
|
|
131
|
-
if (hop >= maxRedirects) throw new Error(`Too many redirects (max ${maxRedirects}) downloading ${url}`);
|
|
132
|
-
current = resolveRedirectUrl(current, location).href;
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
if (!response) throw new Error(`No response downloading ${url}`);
|
|
138
|
-
if (manual && isRedirectStatus(response.status)) throw new Error(`Too many redirects (max ${maxRedirects}) downloading ${url}`);
|
|
139
|
-
if (!response.ok) throw new Error(`HTTP ${response.status} downloading ${url}`);
|
|
140
|
-
if (!response.body) throw new Error(`No response body from ${url}`);
|
|
141
|
-
const total = parseInt(response.headers.get("content-length") ?? "0", 10);
|
|
142
|
-
let downloaded = 0;
|
|
143
|
-
const fileStream = node_fs$1.createWriteStream(tmpPath);
|
|
144
|
-
const reader = response.body.getReader();
|
|
145
|
-
try {
|
|
146
|
-
for (;;) {
|
|
147
|
-
const { done, value } = await reader.read();
|
|
148
|
-
if (done || !value) break;
|
|
149
|
-
downloaded += value.length;
|
|
150
|
-
if (opts.maxBytes !== void 0 && downloaded > opts.maxBytes) throw new Error(`Downloaded ${downloaded} bytes exceeds the ${opts.maxBytes}-byte limit`);
|
|
151
|
-
fileStream.write(value);
|
|
152
|
-
opts.onProgress?.(downloaded, total);
|
|
153
|
-
}
|
|
154
|
-
} finally {
|
|
155
|
-
fileStream.end();
|
|
156
|
-
await new Promise((resolve, reject) => {
|
|
157
|
-
fileStream.on("finish", resolve);
|
|
158
|
-
fileStream.on("error", reject);
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
node_fs$1.renameSync(tmpPath, destPath);
|
|
162
|
-
return destPath;
|
|
163
|
-
} catch (err) {
|
|
164
|
-
try {
|
|
165
|
-
node_fs$1.unlinkSync(tmpPath);
|
|
166
|
-
} catch {}
|
|
167
|
-
throw err;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Fetch JSON from a URL using native fetch().
|
|
172
|
-
*/
|
|
173
|
-
async function fetchJson(url) {
|
|
174
|
-
const response = await fetch(url, {
|
|
175
|
-
redirect: "follow",
|
|
176
|
-
headers: buildHeaders(url)
|
|
177
|
-
});
|
|
178
|
-
if (!response.ok) throw new Error(`HTTP ${response.status} fetching ${url}`);
|
|
179
|
-
return response.json();
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Unified model download service.
|
|
183
|
-
*
|
|
184
|
-
* Handles downloading model files and extra files (labels, dicts) from a
|
|
185
|
-
* catalog of ModelCatalogEntry items. Supports single-file models and
|
|
186
|
-
* directory bundles (e.g., .mlpackage for CoreML).
|
|
187
|
-
*
|
|
188
|
-
* Addons use this via `context.models.ensure(modelId, format)`.
|
|
189
|
-
*/
|
|
190
|
-
var ModelDownloadService = class {
|
|
191
|
-
modelsDir;
|
|
192
|
-
onProgress;
|
|
193
|
-
catalog;
|
|
194
|
-
constructor(modelsDir, catalog, onProgress) {
|
|
195
|
-
this.modelsDir = modelsDir;
|
|
196
|
-
this.onProgress = onProgress;
|
|
197
|
-
const map = /* @__PURE__ */ new Map();
|
|
198
|
-
for (const entry of catalog) map.set(entry.id, entry);
|
|
199
|
-
this.catalog = map;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Ensure a model (and its extra files) is downloaded.
|
|
203
|
-
* Returns the local filesystem path to the model file/directory.
|
|
204
|
-
*/
|
|
205
|
-
async ensure(modelId, format) {
|
|
206
|
-
const entry = this.catalog.get(modelId);
|
|
207
|
-
if (!entry) throw new Error(`ModelDownloadService: unknown model "${modelId}"`);
|
|
208
|
-
const selectedFormat = format ?? this.pickDefaultFormat(entry);
|
|
209
|
-
const formatEntry = entry.formats[selectedFormat];
|
|
210
|
-
if (!formatEntry) throw new Error(`ModelDownloadService: model "${modelId}" has no ${selectedFormat} format`);
|
|
211
|
-
await this.ensureExtraFiles(modelId);
|
|
212
|
-
const modelPath = this.modelFilePath(entry, selectedFormat);
|
|
213
|
-
const siblings = siblingFilesFor(formatEntry);
|
|
214
|
-
if (node_fs$1.existsSync(modelPath)) {
|
|
215
|
-
if (formatEntry.isDirectory) if (!node_fs$1.existsSync(node_path$1.join(modelPath, "Manifest.json"))) node_fs$1.rmSync(modelPath, {
|
|
216
|
-
recursive: true,
|
|
217
|
-
force: true
|
|
218
|
-
});
|
|
219
|
-
else return modelPath;
|
|
220
|
-
else if (siblings.every((f) => isNonEmptyFile(node_path$1.join(this.modelsDir, f)))) return modelPath;
|
|
221
|
-
}
|
|
222
|
-
node_fs$1.mkdirSync(this.modelsDir, { recursive: true });
|
|
223
|
-
if (formatEntry.isDirectory) await this.downloadDirectory(formatEntry.url, modelPath, formatEntry.files, modelId);
|
|
224
|
-
else {
|
|
225
|
-
await downloadFile(formatEntry.url, modelPath, this.onProgress ? (downloaded, total) => this.onProgress(modelId, downloaded, total) : void 0);
|
|
226
|
-
for (const sibling of siblings) await downloadFile(siblingUrl(formatEntry.url, sibling), node_path$1.join(this.modelsDir, sibling));
|
|
227
|
-
}
|
|
228
|
-
return modelPath;
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Ensure extra files for a model are downloaded.
|
|
232
|
-
* Returns the local paths of all extra files.
|
|
233
|
-
*/
|
|
234
|
-
async ensureExtraFiles(modelId) {
|
|
235
|
-
const entry = this.catalog.get(modelId);
|
|
236
|
-
if (!entry) throw new Error(`ModelDownloadService: unknown model "${modelId}"`);
|
|
237
|
-
const extras = entry.extraFiles;
|
|
238
|
-
if (!extras || extras.length === 0) return [];
|
|
239
|
-
const paths = [];
|
|
240
|
-
for (const extra of extras) {
|
|
241
|
-
const destPath = node_path$1.join(this.modelsDir, extra.filename);
|
|
242
|
-
await downloadFile(extra.url, destPath);
|
|
243
|
-
paths.push(destPath);
|
|
244
|
-
}
|
|
245
|
-
return paths;
|
|
246
|
-
}
|
|
247
|
-
/** Absolute path to the shared models directory. */
|
|
248
|
-
getModelsDir() {
|
|
249
|
-
return this.modelsDir;
|
|
250
|
-
}
|
|
251
|
-
/** Check if a model file is already present on disk. */
|
|
252
|
-
isDownloaded(modelId, format) {
|
|
253
|
-
const entry = this.catalog.get(modelId);
|
|
254
|
-
if (!entry) return false;
|
|
255
|
-
const selectedFormat = format ?? this.pickDefaultFormat(entry);
|
|
256
|
-
const formatEntry = entry.formats[selectedFormat];
|
|
257
|
-
if (!formatEntry) return false;
|
|
258
|
-
const modelPath = this.modelFilePath(entry, selectedFormat);
|
|
259
|
-
if (!node_fs$1.existsSync(modelPath)) return false;
|
|
260
|
-
if (formatEntry.isDirectory) return node_fs$1.existsSync(node_path$1.join(modelPath, "Manifest.json"));
|
|
261
|
-
if (node_fs$1.statSync(modelPath).size <= 0) return false;
|
|
262
|
-
return siblingFilesFor(formatEntry).every((f) => isNonEmptyFile(node_path$1.join(this.modelsDir, f)));
|
|
263
|
-
}
|
|
264
|
-
/** Get the catalog entry for a model by ID. */
|
|
265
|
-
getEntry(modelId) {
|
|
266
|
-
return this.catalog.get(modelId);
|
|
267
|
-
}
|
|
268
|
-
pickDefaultFormat(entry) {
|
|
269
|
-
for (const fmt of [
|
|
270
|
-
"onnx",
|
|
271
|
-
"coreml",
|
|
272
|
-
"openvino",
|
|
273
|
-
"tflite",
|
|
274
|
-
"pt"
|
|
275
|
-
]) if (entry.formats[fmt]) return fmt;
|
|
276
|
-
const first = Object.keys(entry.formats)[0];
|
|
277
|
-
if (first) return first;
|
|
278
|
-
throw new Error(`ModelDownloadService: model "${entry.id}" has no formats`);
|
|
279
|
-
}
|
|
280
|
-
modelFilePath(entry, format) {
|
|
281
|
-
const formatEntry = entry.formats[format];
|
|
282
|
-
if (!formatEntry) throw new Error(`Model ${entry.id} has no ${format} format`);
|
|
283
|
-
const urlParts = formatEntry.url.split("/");
|
|
284
|
-
const filename = urlParts[urlParts.length - 1] ?? `${entry.id}.${format}`;
|
|
285
|
-
return node_path$1.join(this.modelsDir, filename);
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Download a directory bundle (e.g., .mlpackage) from HuggingFace.
|
|
289
|
-
* ATOMIC: downloads to temp dir, renames only on complete success.
|
|
290
|
-
*/
|
|
291
|
-
async downloadDirectory(url, destDir, knownFiles, _modelId) {
|
|
292
|
-
const match = url.match(/huggingface\.co\/([^/]+\/[^/]+)\/resolve\/main\/(.+)/);
|
|
293
|
-
if (!match) throw new Error(`Cannot parse HuggingFace URL: ${url}`);
|
|
294
|
-
const [, repo, dirPath] = match;
|
|
295
|
-
let filesToDownload;
|
|
296
|
-
if (knownFiles && knownFiles.length > 0) filesToDownload = knownFiles.map((f) => ({
|
|
297
|
-
relativePath: f,
|
|
298
|
-
fileUrl: `https://huggingface.co/${repo}/resolve/main/${dirPath}/${f}`
|
|
299
|
-
}));
|
|
300
|
-
else {
|
|
301
|
-
const hfFiles = await this.listHfFiles(repo, dirPath);
|
|
302
|
-
if (hfFiles.length === 0) throw new Error(`No files found in HuggingFace directory: ${dirPath}`);
|
|
303
|
-
filesToDownload = hfFiles.map((f) => ({
|
|
304
|
-
relativePath: f.path.substring(dirPath.length + 1),
|
|
305
|
-
fileUrl: `https://huggingface.co/${repo}/resolve/main/${f.path}`
|
|
306
|
-
}));
|
|
307
|
-
}
|
|
308
|
-
const tmpDir = destDir + ".downloading";
|
|
309
|
-
node_fs$1.rmSync(tmpDir, {
|
|
310
|
-
recursive: true,
|
|
311
|
-
force: true
|
|
312
|
-
});
|
|
313
|
-
node_fs$1.mkdirSync(tmpDir, { recursive: true });
|
|
314
|
-
try {
|
|
315
|
-
for (const file of filesToDownload) {
|
|
316
|
-
const destPath = node_path$1.join(tmpDir, file.relativePath);
|
|
317
|
-
node_fs$1.mkdirSync(node_path$1.dirname(destPath), { recursive: true });
|
|
318
|
-
await downloadFile(file.fileUrl, destPath);
|
|
319
|
-
}
|
|
320
|
-
node_fs$1.rmSync(destDir, {
|
|
321
|
-
recursive: true,
|
|
322
|
-
force: true
|
|
323
|
-
});
|
|
324
|
-
node_fs$1.renameSync(tmpDir, destDir);
|
|
325
|
-
} catch (err) {
|
|
326
|
-
node_fs$1.rmSync(tmpDir, {
|
|
327
|
-
recursive: true,
|
|
328
|
-
force: true
|
|
329
|
-
});
|
|
330
|
-
throw err;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
/** Recursively list all files in a HuggingFace directory via API. */
|
|
334
|
-
async listHfFiles(repo, dirPath) {
|
|
335
|
-
const entries = await fetchJson(`https://huggingface.co/api/models/${repo}/tree/main/${dirPath}`);
|
|
336
|
-
const files = [];
|
|
337
|
-
for (const entry of entries) if (entry.type === "file") files.push({
|
|
338
|
-
path: entry.path,
|
|
339
|
-
size: entry.size ?? entry.lfs?.size ?? 0
|
|
340
|
-
});
|
|
341
|
-
else if (entry.type === "directory") {
|
|
342
|
-
const subFiles = await this.listHfFiles(repo, entry.path);
|
|
343
|
-
files.push(...subFiles);
|
|
344
|
-
}
|
|
345
|
-
return files;
|
|
346
|
-
}
|
|
347
|
-
};
|
|
348
|
-
(0, node_util.promisify)(node_zlib.brotliCompress);
|
|
349
|
-
(0, node_util.promisify)(node_zlib.gzip);
|
|
350
|
-
//#endregion
|
|
351
59
|
//#region src/embedding-encoder/catalogs/embedding-models.ts
|
|
352
60
|
var HF_REPO = "camstack/camstack-models";
|
|
353
61
|
var hf = (path) => require_dist.hfModelUrl(HF_REPO, path);
|
|
@@ -835,15 +543,11 @@ var EmbeddingEncoderAddon = class extends require_dist.BaseAddon {
|
|
|
835
543
|
imageEngineInflight = null;
|
|
836
544
|
textEngineInflight = null;
|
|
837
545
|
constructor() {
|
|
838
|
-
super({
|
|
839
|
-
modelId: DEFAULT_CLIP_MODEL,
|
|
840
|
-
runtime: "auto",
|
|
841
|
-
backend: "cpu"
|
|
842
|
-
});
|
|
546
|
+
super({ modelId: DEFAULT_CLIP_MODEL });
|
|
843
547
|
}
|
|
844
548
|
async onInitialize() {
|
|
845
549
|
const modelsDir = await this.resolveModelsDir();
|
|
846
|
-
this.models = new ModelDownloadService(modelsDir, [...CLIP_IMAGE_MODELS, ...CLIP_TEXT_MODELS]);
|
|
550
|
+
this.models = new _camstack_system_addon_utils.ModelDownloadService(modelsDir, [...CLIP_IMAGE_MODELS, ...CLIP_TEXT_MODELS]);
|
|
847
551
|
this.memoryGuard = new require_dist.PoolMemoryWatchdog({
|
|
848
552
|
policy: require_dist.resolvePoolMemoryPolicy(process.env),
|
|
849
553
|
log: this.ctx.logger.child("pool-memory"),
|
|
@@ -983,11 +687,7 @@ var EmbeddingEncoderAddon = class extends require_dist.BaseAddon {
|
|
|
983
687
|
}
|
|
984
688
|
}
|
|
985
689
|
async resolveForEntry(entry, target) {
|
|
986
|
-
const engineLogger = this.ctx.logger.withTags({
|
|
987
|
-
modelId: entry.id,
|
|
988
|
-
runtime: this.config.runtime,
|
|
989
|
-
backend: this.config.backend
|
|
990
|
-
});
|
|
690
|
+
const engineLogger = this.ctx.logger.withTags({ modelId: entry.id });
|
|
991
691
|
const modelPath = await this.models.ensure(entry.id, "onnx");
|
|
992
692
|
const pythonPath = await this.ctx.deps.ensurePython();
|
|
993
693
|
if (!pythonPath) throw new Error("EmbeddingEncoder: embedded Python is unavailable — cannot run ONNX embeddings. ctx.deps.ensurePython() returned null (portable Python download likely failed).");
|
|
@@ -1016,50 +716,13 @@ var EmbeddingEncoderAddon = class extends require_dist.BaseAddon {
|
|
|
1016
716
|
id: "embedding-encoder-settings",
|
|
1017
717
|
title: "Embedding Encoder",
|
|
1018
718
|
columns: 2,
|
|
1019
|
-
fields: [
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
},
|
|
1027
|
-
{
|
|
1028
|
-
type: "select",
|
|
1029
|
-
key: "runtime",
|
|
1030
|
-
label: "Runtime",
|
|
1031
|
-
description: "Inference runtime — ONNX runs in the embedded Python.",
|
|
1032
|
-
default: "auto",
|
|
1033
|
-
options: [{
|
|
1034
|
-
label: "Auto",
|
|
1035
|
-
value: "auto"
|
|
1036
|
-
}, {
|
|
1037
|
-
label: "Python",
|
|
1038
|
-
value: "python"
|
|
1039
|
-
}]
|
|
1040
|
-
},
|
|
1041
|
-
{
|
|
1042
|
-
type: "select",
|
|
1043
|
-
key: "backend",
|
|
1044
|
-
label: "Backend",
|
|
1045
|
-
description: "Hardware backend for inference acceleration",
|
|
1046
|
-
default: "cpu",
|
|
1047
|
-
options: [
|
|
1048
|
-
{
|
|
1049
|
-
label: "CPU",
|
|
1050
|
-
value: "cpu"
|
|
1051
|
-
},
|
|
1052
|
-
{
|
|
1053
|
-
label: "CUDA",
|
|
1054
|
-
value: "cuda"
|
|
1055
|
-
},
|
|
1056
|
-
{
|
|
1057
|
-
label: "CoreML",
|
|
1058
|
-
value: "coreml"
|
|
1059
|
-
}
|
|
1060
|
-
]
|
|
1061
|
-
}
|
|
1062
|
-
]
|
|
719
|
+
fields: [{
|
|
720
|
+
type: "text",
|
|
721
|
+
key: "modelId",
|
|
722
|
+
label: "Model ID",
|
|
723
|
+
description: "CLIP model identifier to use for image/text embedding",
|
|
724
|
+
default: DEFAULT_CLIP_MODEL
|
|
725
|
+
}]
|
|
1063
726
|
}] });
|
|
1064
727
|
}
|
|
1065
728
|
async onConfigChanged() {}
|