improved model loading and training
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user