improved model loading and training

This commit is contained in:
Dobromir Popov
2025-10-31 01:22:49 +02:00
parent 7ddf98bf18
commit ba91740e4c
7 changed files with 745 additions and 186 deletions

View File

@@ -16,10 +16,14 @@
<!-- Training Controls -->
<div class="mb-3">
<button class="btn btn-primary btn-sm w-100" id="train-model-btn">
<button class="btn btn-primary btn-sm w-100" id="train-model-btn" style="display: none;">
<i class="fas fa-play"></i>
Train Model
</button>
<button class="btn btn-success btn-sm w-100" id="load-model-btn" style="display: none;">
<i class="fas fa-download"></i>
Load Model
</button>
</div>
<!-- Training Status -->
@@ -102,71 +106,95 @@
</div>
<script>
// Load available models on page load with polling for async loading
let modelLoadingPollInterval = null;
// Track model states
let modelStates = [];
let selectedModel = null;
function loadAvailableModels() {
fetch('/api/available-models')
.then(response => response.json())
.then(data => {
console.log('📊 Available models API response:', JSON.stringify(data, null, 2));
const modelSelect = document.getElementById('model-select');
if (data.loading) {
// Models still loading - show loading message and poll
modelSelect.innerHTML = '<option value=""> Loading models...</option>';
// Start polling if not already polling
if (!modelLoadingPollInterval) {
console.log('Models loading in background, will poll for completion...');
modelLoadingPollInterval = setInterval(loadAvailableModels, 2000); // Poll every 2 seconds
}
} else {
// Models loaded - stop polling
if (modelLoadingPollInterval) {
clearInterval(modelLoadingPollInterval);
modelLoadingPollInterval = null;
}
if (data.success && data.models && Array.isArray(data.models)) {
modelStates = data.models;
modelSelect.innerHTML = '';
if (data.success && data.models.length > 0) {
// Show success notification
if (window.showSuccess) {
window.showSuccess(` ${data.models.length} models loaded and ready for training`);
}
data.models.forEach(model => {
const option = document.createElement('option');
option.value = model;
option.textContent = model;
modelSelect.appendChild(option);
});
console.log(` Models loaded: ${data.models.join(', ')}`);
} else {
// Add placeholder option
const placeholder = document.createElement('option');
placeholder.value = '';
placeholder.textContent = 'Select a model...';
modelSelect.appendChild(placeholder);
// Add model options with load status
data.models.forEach((model, index) => {
console.log(` Model ${index}:`, model, 'Type:', typeof model);
// Ensure model is an object with name property
const modelName = (model && typeof model === 'object' && model.name) ? model.name : String(model);
const isLoaded = (model && typeof model === 'object' && 'loaded' in model) ? model.loaded : false;
console.log(` → Name: "${modelName}", Loaded: ${isLoaded}`);
const option = document.createElement('option');
option.value = '';
option.textContent = 'No models available';
option.value = modelName;
option.textContent = modelName + (isLoaded ? ' ✓' : ' (not loaded)');
option.dataset.loaded = isLoaded;
modelSelect.appendChild(option);
}
});
console.log(`✓ Models available: ${data.available_count}, loaded: ${data.loaded_count}`);
// Update button state for currently selected model
updateButtonState();
} else {
console.error('❌ Invalid response format:', data);
modelSelect.innerHTML = '<option value="">No models available</option>';
}
})
.catch(error => {
console.error('Error loading models:', error);
console.error('Error loading models:', error);
const modelSelect = document.getElementById('model-select');
// Don't stop polling on network errors - keep trying
if (!modelLoadingPollInterval) {
modelSelect.innerHTML = '<option value=""> Connection error, retrying...</option>';
// Start polling to retry
modelLoadingPollInterval = setInterval(loadAvailableModels, 3000); // Poll every 3 seconds
} else {
// Already polling, just update the message
modelSelect.innerHTML = '<option value=""> Retrying...</option>';
}
modelSelect.innerHTML = '<option value="">Error loading models</option>';
});
}
function updateButtonState() {
const modelSelect = document.getElementById('model-select');
const trainBtn = document.getElementById('train-model-btn');
const loadBtn = document.getElementById('load-model-btn');
const inferenceBtn = document.getElementById('start-inference-btn');
selectedModel = modelSelect.value;
if (!selectedModel) {
// No model selected
trainBtn.style.display = 'none';
loadBtn.style.display = 'none';
inferenceBtn.disabled = true;
return;
}
// Find model state
const modelState = modelStates.find(m => m.name === selectedModel);
if (modelState && modelState.loaded) {
// Model is loaded - show train/inference buttons
trainBtn.style.display = 'block';
loadBtn.style.display = 'none';
inferenceBtn.disabled = false;
} else {
// Model not loaded - show load button
trainBtn.style.display = 'none';
loadBtn.style.display = 'block';
inferenceBtn.disabled = true;
}
}
// Update button state when model selection changes
document.getElementById('model-select').addEventListener('change', updateButtonState);
// Load models when page loads
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', loadAvailableModels);
@@ -174,6 +202,45 @@
loadAvailableModels();
}
// Load model button handler
document.getElementById('load-model-btn').addEventListener('click', function () {
const modelName = document.getElementById('model-select').value;
if (!modelName) {
showError('Please select a model first');
return;
}
// Disable button and show loading
const loadBtn = this;
loadBtn.disabled = true;
loadBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Loading...';
// Load the model
fetch('/api/load-model', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model_name: modelName })
})
.then(response => response.json())
.then(data => {
if (data.success) {
showSuccess(`${modelName} loaded successfully`);
// Refresh model list to update states
loadAvailableModels();
} else {
showError(`Failed to load ${modelName}: ${data.error}`);
loadBtn.disabled = false;
loadBtn.innerHTML = '<i class="fas fa-download"></i> Load Model';
}
})
.catch(error => {
showError('Network error: ' + error.message);
loadBtn.disabled = false;
loadBtn.innerHTML = '<i class="fas fa-download"></i> Load Model';
});
});
// Train model button
document.getElementById('train-model-btn').addEventListener('click', function () {
const modelName = document.getElementById('model-select').value;