sd-parsers
Version:
A library to read metadata from images created by Stable Diffusion
121 lines • 5.14 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AUTOMATIC1111Parser = void 0;
const parser_1 = require("./parser");
const data_1 = require("../data");
const exceptions_1 = require("../exceptions");
const SAMPLER_PARAMS = ['Sampler', 'CFG scale', 'Seed', 'Steps', 'ENSD', 'Schedule type', 'Denoising strength', 'Clip skip'];
const REPLACEMENT_RULES = [
['Schedule type', 'scheduler'],
['CFG scale', 'cfg_scale'],
['Seed', 'seed'],
['Steps', 'steps'],
['Denoising strength', 'denoising_strength'],
['Clip skip', 'clip_skip']
];
/**
* Parser for images generated by AUTOMATIC1111's stable-diffusion-webui or similar
*/
class AUTOMATIC1111Parser extends parser_1.Parser {
constructor() {
super(...arguments);
this.generator = data_1.Generators.AUTOMATIC1111;
}
async parse(parameters) {
let lines;
try {
if (!parameters.parameters || typeof parameters.parameters !== 'string') {
throw new Error('parameters field is missing or not a string');
}
lines = parameters.parameters.split('\n');
}
catch (error) {
throw new exceptions_1.ParserError(`Error reading parameter string: ${error}`);
}
try {
const { infoIndex, samplerInfo, metadata } = getSamplerInfo(lines);
const prompts = lines.slice(0, infoIndex).join('\n').split('Negative prompt:');
const prompt = prompts[0]?.trim() || '';
const negativePrompt = prompts[1]?.trim() || '';
const samplerParams = Object.fromEntries((0, parser_1.popKeys)(SAMPLER_PARAMS, samplerInfo));
const samplerName = samplerParams.Sampler || 'unknown';
delete samplerParams.Sampler;
const normalizedParams = this.normalizeParameters(samplerParams, REPLACEMENT_RULES);
const modelName = metadata.Model;
const modelHash = metadata['Model hash'];
delete metadata.Model;
delete metadata['Model hash'];
const model = (modelName || modelHash) ? (0, data_1.createModel)({ name: modelName, hash: modelHash }) : undefined;
const promptList = prompt ? [(0, data_1.createPrompt)(prompt)] : [];
const negativePromptList = negativePrompt ? [(0, data_1.createPrompt)(negativePrompt)] : [];
const sampler = (0, data_1.createSampler)(samplerName, normalizedParams, {
model,
prompts: promptList,
negativePrompts: negativePromptList
});
return (0, data_1.createPromptInfo)(this.generator, [sampler], metadata, parameters);
}
catch (error) {
// Fallback: if no sampler info found, treat entire string as prompt
const fullText = lines.join('\n');
const prompts = fullText.split('Negative prompt:');
const prompt = prompts[0]?.trim() || '';
const negativePrompt = prompts[1]?.trim() || '';
const promptList = prompt ? [(0, data_1.createPrompt)(prompt)] : [];
const negativePromptList = negativePrompt ? [(0, data_1.createPrompt)(negativePrompt)] : [];
const sampler = (0, data_1.createSampler)('unknown', {}, {
prompts: promptList,
negativePrompts: negativePromptList
});
return (0, data_1.createPromptInfo)(this.generator, [sampler], {}, parameters);
}
}
}
exports.AUTOMATIC1111Parser = AUTOMATIC1111Parser;
/**
* Extract sampler information from parameter lines
*/
function getSamplerInfo(lines) {
for (let index = lines.length - 1; index >= 0; index--) {
const line = lines[index];
const metadata = extractMetadata(line);
const samplerInfo = Object.fromEntries((0, parser_1.popKeys)(SAMPLER_PARAMS, { ...metadata }));
if (Object.keys(samplerInfo).length >= 3) {
return { infoIndex: index, samplerInfo, metadata };
}
}
throw new exceptions_1.ParserError('No sampler information found');
}
/**
* Extract metadata from a parameter line
*/
function extractMetadata(line) {
const metadata = {};
// Try to extract hashes
const hashMatch = line.match(/(?:,\s*)?Hashes:\s*(\{[^}]*\})\s*/);
if (hashMatch) {
try {
metadata.Hashes = JSON.parse(hashMatch[1]);
line = line.substring(0, hashMatch.index) + line.substring(hashMatch.index + hashMatch[0].length);
}
catch (error) {
// Ignore JSON parse errors
}
}
// Extract key-value pairs
for (const item of line.split(',')) {
try {
const colonIndex = item.indexOf(':');
if (colonIndex > 0) {
const key = item.substring(0, colonIndex).trim();
const value = item.substring(colonIndex + 1).trim();
metadata[key] = value;
}
}
catch (error) {
// Ignore parsing errors for individual items
}
}
return metadata;
}
//# sourceMappingURL=automatic1111.js.map