This commit is contained in:
Christian Mantha
2026-03-02 19:10:52 -05:00
commit 2ca0b9ef7c
28907 changed files with 5233713 additions and 0 deletions

View File

@@ -0,0 +1,263 @@
<!DOCTYPE html>
<html lang="en">
<body>
<style>
@keyframes spin {
to { transform: translate(calc(-50%), calc(50vh - 50%)) rotate(360deg); }
}
.mermaidTooltip {
display: none;
}
.wrapper {
display: flex;
}
.mermaid {
width: 60%;
}
.pane-loading {
font-size: 0;
color: transparent;
}
.pane-loading::after {
content: "";
position: absolute;
inset: 0 50%;
width: 32px;
height: 32px;
transform: translate(calc(-50%), calc(50vh - 50%));
border: 0.25rem solid #9370DB;
border-bottom: 0.25rem solid rgba(0,0,0,0);
border-radius: 50%;
animation: spin 1s linear infinite;
}
#editor {
font-size: 13px;
width: 40%;
position: relative;
}
font {
font-size: 24px;
padding: 24px;
}
.node:hover {
stroke: #2272B4 !important;
color: #0E538B !important;
background-color: #bbdaf4;
}
</style>
<div class="wrapper">
<div class="mermaid pane-loading">
flowchart TD
subgraph " "
recipe([recipe.yaml])
ingestUserCode([steps/ingest.py]) --> ingestMLPStep[["<font>ingest</font>"]]
ingestMLPStep --> dataParquet[(ingested_data)]
ingestScoringUserCode([steps/ingest.py]) --> ingestScoringMLPStep[["<font>ingest_scoring</font>"]]
ingestScoringMLPStep --> dataScoringParquet[(ingested_scoring_data)]
dataScoring[(ingested_scoring_data)] --> predictMLPStep[["<font>predict</font>"]]
predictMLPStep --> dataScored[(scored_data)]
end
data[(ingested_data)] --> splitStep[["<font>split</font>"]]
transformUserCode([steps/transform.py]) --> transformMLPStep
splitUserCode([steps/split.py]) --> splitStep
splitStep --> splitData0[(training_data)]
splitStep --> splitData1[(validation_data)]
splitStep --> splitData2[(test_data)]
splitData0 --> transformMLPStep[["<font>transform</font>"]]
splitData1 --> transformMLPStep[["<font>transform</font>"]]
transformMLPStep --> transformedParquet[(transformed_training_data, <br/> transformed_validation_data)]
transformMLPStep --> transformer{{transformer}}
transformedParquet --> trainMLPStep[["<font>train</font>"]]
trainUserCode([steps/train.py]) --> trainMLPStep
customMetricsUserCode([steps/custom_metrics.py]) --> trainMLPStep
transformer --> trainMLPStep
trainMLPStep --> run{{run}}
trainMLPStep --> model{{model}}
trainMLPStep --> predictedTrainingData[(predicted_training_data)]
model --> evaluateMLPStep[["<font>evaluate</font>"]]
splitData1 --> evaluateMLPStep
splitData2 --> evaluateMLPStep
customMetricsUserCode --> evaluateMLPStep
evaluateMLPStep --> model_validation_status{{model_validation_status}}
run --> registerMLPStep[["<font>register</font>"]]
run --> evaluateMLPStep
model_validation_status --> registerMLPStep
registerMLPStep --> registered_model_version{{registered_model_version}}
click ingestMLPStep renderMoreInformation "{{ingest_step_help}}"
click ingestUserCode renderMoreInformation "{{ingest_user_code_help}}"
click splitStep renderMoreInformation "{{split_step_help}}"
click transformMLPStep renderMoreInformation "{{transform_step_help}}"
click transformUserCode renderMoreInformation "{{transform_user_code_help}}"
click trainMLPStep renderMoreInformation "{{train_step_help}}"
click trainUserCode renderMoreInformation "{{train_user_code_help}}"
click evaluateMLPStep renderMoreInformation "{{evaluate_step_help}}"
click registerMLPStep renderMoreInformation "{{register_step_help}}"
click customMetricsUserCode renderMoreInformation "{{custom_metrics_user_code_help}}"
click splitUserCode renderMoreInformation "{{split_user_code_help}}"
click ingestScoringUserCode renderMoreInformation "{{ingest_user_code_help}}"
click ingestScoringMLPStep renderMoreInformation "{{ingest_scoring_step_help}}"
click predictMLPStep renderMoreInformation "{{predict_step_help}}"
click recipe renderMoreInformation "{{recipe_yaml_help}}"
click dataParquet renderMoreInformation "{{ingested_data_help}}"
click data renderMoreInformation "{{ingested_data_help}}"
click splitData0 renderMoreInformation "{{training_data_help}}"
click splitData1 renderMoreInformation "{{validation_data_help}}"
click splitData2 renderMoreInformation "{{test_data_help}}"
click transformedParquet renderMoreInformation "{{transformed_training_and_validation_data_help}}"
click run renderMoreInformation "{{mlflow_run_help}}"
click model renderMoreInformation "{{fitted_model_help}}"
click predictedTrainingData renderMoreInformation "{{predicted_training_data_help}}"
click transformer renderMoreInformation "{{fitted_transformer_help}}"
click model_validation_status renderMoreInformation "{{model_validation_status_help}}"
click registered_model_version renderMoreInformation "{{registered_model_version_help}}"
click dataScoringParquet renderMoreInformation "{{ingested_scoring_data_help}}"
click dataScoring renderMoreInformation "{{ingested_scoring_data_help}}"
click dataScored renderMoreInformation "{{scored_data_help}}"
</div>
<div id="editor"></div>
</div>
<script src="https://requirejs.org/docs/release/2.1.5/comments/require.js"></script>
<script type="text/javascript">
require.config({
paths: {
"mermaid": "https://cdn.jsdelivr.net/npm/mermaid@9.3.0/dist/mermaid.min",
"ace": "https://cdnjs.cloudflare.com/ajax/libs/ace/1.5.1/",
"python": "https://cdnjs.cloudflare.com/ajax/libs/ace/1.5.1/mode-python.min",
"yaml": "https://cdnjs.cloudflare.com/ajax/libs/ace/1.5.1/mode-yaml.min",
"idle_fingers": "https://cdnjs.cloudflare.com/ajax/libs/ace/1.5.1/theme-idle_fingers.min",
},
});
require(["mermaid"],
function (mermaid) {
const config = {
startOnLoad:true,
securityLevel:'loose',
theme: (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dark" : "default",
themeCSS: ".cluster rect { fill: none; stroke: none; }",
flowchart:{
useMaxWidth:true,
htmlLabels:true,
}
};
document.querySelector('.mermaid.pane-loading').classList.remove('pane-loading');
mermaid.initialize(config);
mermaid.init();
const nodes = document.querySelectorAll(".node");
[...nodes].forEach((node) => {
var nodeInfo = node.getAttribute('title');
// In order to parse the node text as JSON with `help_string` and `help_string_type`
// attributes, single quotes must be replaced with double quotes. However, we also want
// to convert backslashed single quotes to single quotes in the parsed JSON and preserve
// backslashed double quotes in the parsed JSON. Accordingly, we first replace instances
// of the string \' with \\" . Then, we replace all instances of ' with " . Finally, we
// replace instances of \\" with '
nodeInfo = nodeInfo && nodeInfo.replace(/\\'/g, '\\\\"');
nodeInfo = nodeInfo && nodeInfo.replace(/'/g, '"');
nodeInfo = nodeInfo && nodeInfo.replace(/\\\\"/g, "'");
if (nodeInfo) {
const nodeLabel = node.querySelector(".nodeLabel");
nodeLabel.setAttribute("title", JSON.parse(nodeInfo).help_string)
}
})
resetStyles()
window.editor = null;
}
);
var resetStyles = function() {
const allNodes = document.querySelector('.nodes').querySelectorAll('[id^="flowchart-"]');
[...allNodes].forEach(node => {
const rect = node.firstChild
if (rect) {
rect.style.fill = "inherit";
rect.style.stroke = "inherit";
}
node.style.fill = "#F2F5F7";
node.style.stroke = "#CDDAE5";
node.style.color = "#20272E";
const span = node.querySelector('span')
const label = node.querySelector('.label')
span.style.color = "inherit";
label.style.color = "inherit";
});
}
var noOp = function() {}
var renderMoreInformation = function(nodeId) {
resetStyles()
regex = `[id^="flowchart-${nodeId}-"]`
const node = document.querySelector(regex);
var nodeInfo = node.getAttribute('title');
// In order to parse the node text as JSON with `help_string` and `help_string_type`
// attributes, single quotes must be replaced with double quotes. However, we also want
// to convert backslashed single quotes to single quotes in the parsed JSON and preserve
// backslashed double quotes in the parsed JSON. Accordingly, we first replace instances
// of the string \' with \\" . Then, we replace all instances of ' with " . Finally, we
// replace instances of \\" with '
nodeInfo = nodeInfo && nodeInfo.replace(/\\'/g, '\\\\"');
nodeInfo = nodeInfo && nodeInfo.replace(/'/g, '"');
nodeInfo = nodeInfo && nodeInfo.replace(/\\\\"/g, "'");
nodeInfo = JSON.parse(nodeInfo)
const rect = node.firstChild;
rect.style.stroke = "#04355D";
rect.style.fill = "#bbdaf4";
rect.style.color = "#04355D";
document.querySelector("#editor").classList.add('pane-loading');
const hideSpinner = () => document.querySelector("#editor").classList.remove('pane-loading');
require(["ace/ace"],
function (ace) {
require(["python", "yaml", "idle_fingers"],
function () {
hideSpinner();
if (!window.editor) {
const editor = ace.edit("editor");
editor.setTheme("ace/theme/idle_fingers");
// Wrap text lines for readability
editor.session.setUseWrapMode(true);
// Minimize indentation on wrapped lines by setting tab size to 1 character
// (note that 0 characters does not appear to work. TODO: Find a better approach)
editor.setOption("tabSize", 1);
editor.setReadOnly(true);
// Disable active line highlighting
editor.setHighlightActiveLine(false);
// Hide the cursor, the presence of which creates the misconception
// that the text is editable
editor.renderer.$cursorLayer.element.style.display = "none"
// Hide the editor gutter, since the window isn't really an editor and instead
// is intended for displaying text
editor.renderer.setShowGutter(false);
// Disable the line length ruler
editor.setShowPrintMargin(false);
window.editor = editor;
}
// Set the editor value and the editor session value to the text associated with
// the recipe node; setting the session is important in order to avoid
// obtrusive highlighting
window.editor.setValue(nodeInfo.help_string)
window.editor.session.setValue(nodeInfo.help_string)
window.editor.session.setMode(`ace/mode/${nodeInfo.help_string_type}`);
}, hideSpinner
);
}, hideSpinner
);
}
</script>
</body>
</html>