Normalize MoneyPrinter Comfy workflow templates
This commit is contained in:
@@ -42,7 +42,7 @@ function planValue(job: MoneyPrinterJob, key: string) {
|
||||
}
|
||||
|
||||
function workflowPromptFromGraph(graph: any) {
|
||||
return graph?.prompt || graph?.workflow || graph?.comfyPrompt || graph || null;
|
||||
return graph?.prompt || graph?.workflow || graph?.comfyPrompt || graphToComfyPrompt(graph) || graph || null;
|
||||
}
|
||||
|
||||
function mappingFromGraph(graph: any) {
|
||||
@@ -74,6 +74,72 @@ function inferMappingFromPrompt(prompt: any) {
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeParam(classType: string, field: string, value: any) {
|
||||
if (classType === 'KSampler' && field === 'cfg') {
|
||||
return typeof value === 'number' && value >= 0 && value <= 50 ? value : 8;
|
||||
}
|
||||
if (classType === 'KSampler' && field === 'denoise') {
|
||||
const numeric = typeof value === 'number' ? value : Number(value);
|
||||
if (!Number.isFinite(numeric)) return 1;
|
||||
return numeric > 1 ? Math.min(1, numeric / 100) : Math.max(0, numeric);
|
||||
}
|
||||
if (classType === 'KSampler' && field === 'sampler_name') return typeof value === 'string' ? value : 'euler';
|
||||
if (classType === 'KSampler' && field === 'scheduler') return typeof value === 'string' ? value : 'normal';
|
||||
if (classType === 'KSampler' && field === 'seed') return Number.isFinite(Number(value)) ? Math.max(0, Number(value)) : 0;
|
||||
if (classType === 'EmptyLatentImage' && ['width', 'height'].includes(field)) {
|
||||
const numeric = Number(value);
|
||||
return numeric >= 64 && numeric <= 4096 ? numeric : 1024;
|
||||
}
|
||||
if (classType === 'EmptyLatentImage' && field === 'batch_size') {
|
||||
const numeric = Number(value);
|
||||
return numeric >= 1 && numeric <= 16 ? numeric : 1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function graphToComfyPrompt(graph: any) {
|
||||
if (!Array.isArray(graph?.nodes)) return null;
|
||||
const prompt: Record<string, any> = {};
|
||||
for (const node of graph.nodes) {
|
||||
const id = String(node?.id || '');
|
||||
const classType = String(node?.type || node?.class_type || '');
|
||||
if (!id || !classType) continue;
|
||||
const params = node?.params && typeof node.params === 'object' ? node.params : {};
|
||||
const inputs: Record<string, any> = {};
|
||||
for (const [field, value] of Object.entries(params)) {
|
||||
inputs[field] = normalizeParam(classType, field, value);
|
||||
}
|
||||
prompt[id] = { class_type: classType, inputs };
|
||||
}
|
||||
for (const edge of Array.isArray(graph?.edges) ? graph.edges : []) {
|
||||
const from = String(edge?.from || '');
|
||||
const to = String(edge?.to || '');
|
||||
const [fromId] = from.split('.');
|
||||
const [toId, toField] = to.split('.');
|
||||
if (fromId && toId && toField && prompt[toId]?.inputs) {
|
||||
prompt[toId].inputs[toField] = [fromId, 0];
|
||||
}
|
||||
}
|
||||
const firstByType = (type: string) => Object.entries(prompt).find(([, node]) => node.class_type === type)?.[0] || '';
|
||||
const allByType = (type: string) => Object.entries(prompt).filter(([, node]) => node.class_type === type).map(([id]) => id);
|
||||
const checkpoint = firstByType('CheckpointLoaderSimple');
|
||||
const latent = firstByType('EmptyLatentImage');
|
||||
const ksampler = firstByType('KSampler');
|
||||
const textNodes = allByType('CLIPTextEncode');
|
||||
if (ksampler) {
|
||||
if (checkpoint) prompt[ksampler].inputs.model = [checkpoint, 0];
|
||||
if (latent) prompt[ksampler].inputs.latent_image = [latent, 0];
|
||||
if (textNodes[0]) prompt[ksampler].inputs.positive = [textNodes[0], 0];
|
||||
if (textNodes[1] || textNodes[0]) prompt[ksampler].inputs.negative = [textNodes[1] || textNodes[0], 0];
|
||||
}
|
||||
const vaeDecode = firstByType('VAEDecode');
|
||||
if (vaeDecode) {
|
||||
if (ksampler) prompt[vaeDecode].inputs.samples = [ksampler, 0];
|
||||
if (checkpoint) prompt[vaeDecode].inputs.vae = [checkpoint, 2];
|
||||
}
|
||||
return prompt;
|
||||
}
|
||||
|
||||
function templateLabel(workflow: WorkflowSummary) {
|
||||
if (workflow.isTemplate || workflow.visibility === 'template') return '官方模板';
|
||||
if (workflow.visibility === 'public') return '共享模板';
|
||||
|
||||
Reference in New Issue
Block a user