Files
2026-07-13 13:02:44 +08:00

105 lines
3.2 KiB
JavaScript

function coerceFiniteNumber(value) {
if (value === null || value === undefined || value === '') return null;
const parsed = Number(value);
return Number.isFinite(parsed) ? parsed : null;
}
function resolveGenerationSteps(params, model) {
const requested = coerceFiniteNumber(params?.steps);
if (requested !== null && requested > 0) {
return Math.max(1, Math.round(requested));
}
const modelDefault = coerceFiniteNumber(model?.defaultSteps);
if (modelDefault !== null && modelDefault > 0) {
return Math.max(1, Math.round(modelDefault));
}
return 20;
}
function resolveGuidanceScale(params, model) {
const requested = coerceFiniteNumber(params?.guidance_scale);
if (requested !== null) return requested;
const modelDefault = coerceFiniteNumber(model?.defaultGuidance);
if (modelDefault !== null) return modelDefault;
return 7.5;
}
function formatStartupProgressMessage(elapsedMs) {
const seconds = Math.max(0, Math.floor((Number(elapsedMs) || 0) / 1000));
if (seconds < 10) return 'Starting local model...';
if (seconds < 60) return `Loading local model (${seconds}s)...`;
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `Loading local model (${minutes}m ${remainingSeconds}s)...`;
}
function stripAnsiSequences(text) {
return text.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, '');
}
function extractProgressEvents(text) {
const events = [];
const patterns = [
/step\s+(\d+)\s*\/\s*(\d+)/ig,
/(\d+)\s*\/\s*(\d+)\s*-\s*[\d.]+s\/it/ig,
];
for (const pattern of patterns) {
let match = pattern.exec(text);
while (match) {
const step = Number.parseInt(match[1], 10);
const totalSteps = Number.parseInt(match[2], 10);
if (Number.isFinite(step) && Number.isFinite(totalSteps) && totalSteps > 0) {
events.push({
step,
totalSteps,
progress: Math.min(1, step / totalSteps),
});
}
match = pattern.exec(text);
}
}
events.sort((left, right) => {
if (left.totalSteps !== right.totalSteps) return left.totalSteps - right.totalSteps;
return left.step - right.step;
});
return events;
}
function parseGenerationProgressChunk(chunk, state = { tail: '', lastStep: 0, lastTotalSteps: 0 }) {
const normalizedChunk = stripAnsiSequences(String(chunk)).replace(/\r/g, '\n');
const combined = `${state.tail}${normalizedChunk}`;
const events = extractProgressEvents(combined);
const freshEvents = [];
for (const event of events) {
if (event.totalSteps !== state.lastTotalSteps) {
state.lastTotalSteps = event.totalSteps;
state.lastStep = 0;
}
if (event.step > state.lastStep) {
state.lastStep = event.step;
freshEvents.push(event);
}
}
state.tail = combined.slice(-1024);
return freshEvents;
}
module.exports = {
coerceFiniteNumber,
extractProgressEvents,
formatStartupProgressMessage,
parseGenerationProgressChunk,
resolveGenerationSteps,
resolveGuidanceScale,
stripAnsiSequences,
};