|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>YAML Config Generator</title> |
|
<link rel="stylesheet" type="text/css" href="styles.css"> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<h1>YAML Config Generator</h1> |
|
<p style="font-weight: bold">Credit: mlabonne</p> |
|
<form id="configForm"> |
|
<div> |
|
<label for="totalLayers">Total Layers:</label> |
|
<input type="number" id="totalLayers" name="totalLayers" required placeholder="Total number of layers (e.g. 126)"> |
|
</div> |
|
<div class="checkbox-container"> |
|
<label for="autoRangeSize">Auto Range Size:</label> |
|
<input type="checkbox" id="autoRangeSize" name="autoRangeSize"> |
|
</div> |
|
<div id="range-size-input" style="display: block;"> |
|
<label for="rangeSize">Range Size:</label> |
|
<input type="number" id="rangeSize" name="rangeSize" placeholder="Range size (e.g. 42)"> |
|
</div> |
|
<div> |
|
<label for="nbParameters">Number of Parameters (B):</label> |
|
<input type="number" id="nbParameters" name="nbParameters" step="0.01" required placeholder="Number of parameters in the model (e.g. 410.0)"> |
|
</div> |
|
<div> |
|
<label for="model">Model:</label> |
|
<input type="text" id="model" name="model" required placeholder="Model name (e.g. meta-llama/Meta-Llama-3.1-405B-Instruct)"> |
|
</div> |
|
<div class="checkbox-container" id="god-mode"> |
|
<label for="doWhatISay">Do what I say:</label> |
|
<input type="checkbox" id="doWhatISay" name="doWhatISay"> |
|
</div> |
|
<button type="submit">Generate Config</button> |
|
</form> |
|
<div id="error" style="display: none;"></div> |
|
<div id="result" style="display: none;"> |
|
<h2>Results:</h2> |
|
<p id="newSize"></p> |
|
<p id="newParam"></p> |
|
<div id="yaml-config-section" style="display: none;"> |
|
<h3>YAML Config:</h3> |
|
<pre id="yamlOutput"></pre> |
|
</div> |
|
</div> |
|
<div id="possible-range-sizes" style="display: none;"> |
|
<h2>Possible Range Sizes:</h2> |
|
<ul id="possible-range-sizes-list"></ul> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
document.getElementById('configForm').addEventListener('submit', function(e) { |
|
e.preventDefault(); |
|
|
|
const totalLayers = parseInt(document.getElementById('totalLayers').value); |
|
const autoRangeSize = document.getElementById('autoRangeSize').checked; |
|
const rangeSize = autoRangeSize? null : parseInt(document.getElementById('rangeSize').value); |
|
const nbParameters = parseFloat(document.getElementById('nbParameters').value); |
|
const model = document.getElementById('model').value; |
|
const doWhatISay = document.getElementById('doWhatISay').checked; |
|
|
|
const errorDiv = document.getElementById('error'); |
|
const resultDiv = document.getElementById('result'); |
|
const possibleRangeSizesDiv = document.getElementById('possible-range-sizes'); |
|
errorDiv.innerHTML = ''; |
|
errorDiv.style.display = 'none'; |
|
resultDiv.style.display = 'none'; |
|
possibleRangeSizesDiv.style.display = 'none'; |
|
|
|
const errors = []; |
|
|
|
if (isNaN(totalLayers) || totalLayers <= 0 ||!Number.isInteger(totalLayers)) { |
|
errors.push("Total Layers must be a positive integer."); |
|
} |
|
|
|
if (!autoRangeSize) { |
|
if (isNaN(rangeSize) || rangeSize <= 0 ||!Number.isInteger(rangeSize)) { |
|
errors.push("Range Size must be a positive integer."); |
|
} |
|
|
|
if (rangeSize > totalLayers) { |
|
errors.push("Range Size cannot be greater than Total Layers."); |
|
} |
|
} |
|
|
|
if (isNaN(nbParameters) || nbParameters <= 0) { |
|
errors.push("Number of Parameters must be a positive number."); |
|
} |
|
|
|
if (model.trim() === "") { |
|
errors.push("Model name cannot be empty."); |
|
} |
|
|
|
if (!doWhatISay && totalLayers % (autoRangeSize? calculatePossibleRangeSize(totalLayers, doWhatISay)[0] : rangeSize)!== 0) { |
|
errors.push("There are layers left after the main loop."); |
|
} |
|
|
|
if (errors.length > 0) { |
|
errorDiv.innerHTML = errors.join('<br>'); |
|
errorDiv.style.display = 'block'; |
|
return; |
|
} |
|
|
|
if (autoRangeSize) { |
|
const possibleRangeSizes = calculatePossibleRangeSize(totalLayers, doWhatISay); |
|
const possibleRangeSizesList = document.getElementById('possible-range-sizes-list'); |
|
possibleRangeSizesList.innerHTML = ''; |
|
possibleRangeSizes.forEach(size => { |
|
const listItem = document.createElement('li'); |
|
const link = document.createElement('a'); |
|
link.textContent = `${size}`; |
|
link.className = 'clickable'; |
|
link.addEventListener('click', function() { |
|
generateConfig(totalLayers, size, nbParameters, model, doWhatISay); |
|
possibleRangeSizesDiv.style.display = 'none'; |
|
}); |
|
listItem.appendChild(link); |
|
possibleRangeSizesList.appendChild(listItem); |
|
}); |
|
possibleRangeSizesDiv.style.display = 'block'; |
|
} else { |
|
generateConfig(totalLayers, rangeSize, nbParameters, model, doWhatISay); |
|
} |
|
}); |
|
|
|
function calculatePossibleRangeSize(num) { |
|
const divisors = []; |
|
for (let i = 1; i <= num; i++) { |
|
const quotient = num / i; |
|
if (Number.isInteger(quotient) || (quotient % 0.5 === 0 && !Number.isInteger(quotient))) { |
|
divisors.push(i); |
|
} |
|
} |
|
return divisors.sort((a, b) => a - b); |
|
} |
|
|
|
function generateConfig(totalLayers, rangeSize, nbParameters, model, doWhatISay) { |
|
let newSize = totalLayers + totalLayers - rangeSize; |
|
let newParam = (nbParameters / totalLayers) * newSize; |
|
|
|
let yamlStr = "slices:\n"; |
|
|
|
for (let i = 0; i <= totalLayers - rangeSize; i += rangeSize / 2) { |
|
let start = i; |
|
if (!doWhatISay &&!Number.isInteger(start)) { |
|
console.error("The layer range contains non integer"); |
|
} else { |
|
let end = Math.min(start + rangeSize, totalLayers); |
|
yamlStr += `- sources:\n`; |
|
yamlStr += ` - layer_range: [${start}, ${end}]\n`; |
|
yamlStr += ` model: ${model}\n`; |
|
} |
|
} |
|
|
|
|
|
const quotient = totalLayers / rangeSize; |
|
if (Number.isInteger(quotient) || !(quotient % 0.5 === 0 && !Number.isInteger(quotient))) { |
|
let start = totalLayers - (totalLayers % rangeSize); |
|
let end = totalLayers; |
|
yamlStr += `- sources:\n`; |
|
yamlStr += ` - layer_range: [${start}, ${end}]\n`; |
|
yamlStr += ` model: ${model}\n`; |
|
} |
|
|
|
yamlStr += "merge_method: passthrough\n"; |
|
yamlStr += "dtype: bfloat16\n"; |
|
|
|
document.getElementById('newSize').textContent = `New size = ${newSize} layers`; |
|
document.getElementById('newParam').textContent = `New parameters = ${newParam.toFixed(2)}B`; |
|
document.getElementById('yamlOutput').textContent = yamlStr; |
|
document.getElementById('yaml-config-section').style.display = 'block'; |
|
document.getElementById('result').style.display = 'block'; |
|
} |
|
|
|
document.getElementById('autoRangeSize').addEventListener('change', function() { |
|
if (this.checked) { |
|
document.getElementById('range-size-input').style.display = 'none'; |
|
document.getElementById('god-mode').style.display = 'none'; |
|
} else { |
|
document.getElementById('range-size-input').style.display = 'block'; |
|
document.getElementById('god-mode').style.display = 'flex'; |
|
|
|
} |
|
}); |
|
</script> |
|
</body> |
|
</html> |