@juspay/neurolink
Version:
Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio
95 lines (94 loc) • 3.35 kB
JavaScript
/**
* Deterministic experiment log parser.
*
* Extracts metrics from run.log output. Never throws — returns
* crashed/timedOut summary on parse failure.
*/
/**
* Parse experiment output into a structured summary.
*
* This function is deterministic and pure — no side effects, no throws.
*/
export function parseExperimentSummary(logContent, metricConfig, memoryConfig, options) {
const lines = logContent.split("\n");
const tailLines = lines.slice(-50);
const rawTail = tailLines.join("\n");
// Check for crash indicators (only if not already determined by exit code)
let crashed = options?.exitCode !== undefined &&
options.exitCode !== 0 &&
!options?.timedOut;
if (!crashed) {
const lastMeaningfulLine = [...lines]
.reverse()
.find((l) => l.trim().length > 0)
?.trim() ?? "";
crashed =
lastMeaningfulLine === "FAIL" ||
lastMeaningfulLine.toLowerCase().includes("traceback") ||
lastMeaningfulLine.toLowerCase().includes("error:");
}
// Parse primary metric
let metric = null;
try {
const regex = new RegExp(metricConfig.pattern, "m");
const match = regex.exec(logContent);
if (match && match[1]) {
const parsed = parseFloat(match[1]);
if (!isNaN(parsed) && isFinite(parsed)) {
metric = parsed;
}
}
}
catch {
// Invalid regex — treat as parse failure
}
// Parse memory metric
let memoryValue = null;
if (memoryConfig) {
try {
const regex = new RegExp(memoryConfig.pattern, "m");
const match = regex.exec(logContent);
if (match && match[1]) {
const parsed = parseFloat(match[1]);
if (!isNaN(parsed) && isFinite(parsed)) {
memoryValue = parsed;
// Convert MB to GB if the name suggests MB.
// Uses binary divisor (1024 = MiB→GiB). For decimal MB→GB use 1000.
// The 1024 convention matches GPU monitoring tools (nvidia-smi, etc.).
const MIB_TO_GIB_DIVISOR = 1024;
if (memoryConfig.name.toLowerCase().includes("mb")) {
memoryValue =
Math.round((memoryValue / MIB_TO_GIB_DIVISOR) * 100) / 100;
}
}
}
}
catch {
// Invalid regex — treat as parse failure
}
}
// Parse training time
let trainingSeconds = null;
try {
const timeRegex = /^training_seconds:\s+([\d.]+)/m;
const match = timeRegex.exec(logContent);
if (match && match[1]) {
trainingSeconds = parseFloat(match[1]);
}
}
catch {
// Ignore
}
// Only treat as timeout if explicitly signaled by the runner — don't infer from missing metric
const timedOut = options?.timedOut ?? false;
// Missing metric without explicit timeout is a crash (regex failure, spawn error, etc.)
const finalCrashed = crashed || (metric === null && !timedOut);
return {
crashed: finalCrashed,
timedOut,
metric,
memoryValue,
trainingSeconds,
rawTail,
};
}