Zeggai Abdellah
fix the index.html
778a327
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Générateur de Questions sur les Vaccins</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 font-sans">
<div class="container mx-auto p-6">
<!-- Header -->
<h1 class="text-3xl font-bold text-center mb-8">🧬 Générateur de Questions sur les Vaccins</h1>
<!-- API Keys Status Section -->
<section class="bg-white p-6 rounded-lg shadow-md mb-8">
<h2 class="text-2xl font-semibold mb-4">🔑 État des Clés API</h2>
<div id="api-keys-status" class="text-gray-700">
Vérification des clés API...
</div>
<button id="check-api-keys" class="mt-4 bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
Vérifier les Clés
</button>
</section>
<!-- Question Generation Section -->
<section class="bg-white p-6 rounded-lg shadow-md mb-8">
<h2 class="text-2xl font-semibold mb-4">🚀 Génération de Questions</h2>
<p class="mb-4">Générez des questions à partir du guide de vaccination avec gestion multi-clés et suivi en temps réel.</p>
<div class="flex space-x-4">
<button id="generate-questions" class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600">
Générer des Questions
</button>
<a id="download-progress" class="bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600" href="#" style="display: none;">
Télécharger Progrès
</a>
<button id="view-failed-chunks" class="bg-red-500 text-white px-4 py-2 rounded hover:bg-red-600">
Voir Échecs
</button>
</div>
<!-- Generation Status -->
<div id="generation-status" class="mt-4 text-gray-700">
Initialisation de la génération...
</div>
<!-- Progress Bar -->
<div class="mt-4">
<div class="w-full bg-gray-200 rounded-full h-4">
<div id="progress-bar" class="bg-blue-500 h-4 rounded-full" style="width: 0%;"></div>
</div>
<p id="progress-text" class="text-center mt-2">0%</p>
</div>
<!-- Generation Details -->
<div id="generation-details" class="mt-4 text-gray-700">
<p>Chunks traités: <span id="processed-chunks">0</span>/<span id="total-chunks">0</span></p>
<p>Questions générées: <span id="questions-generated">0</span></p>
<p>Clé API actuelle: <span id="current-api-key">-</span></p>
<p>Échecs: <span id="failed-chunks-count">0</span></p>
</div>
<!-- Estimated Time -->
<div id="estimated-time" class="mt-4 text-gray-700">
⏱️ Temps estimé restant: Calcul en cours...
</div>
<!-- Failed Chunks -->
<div id="failed-chunks" class="mt-4 hidden">
<h3 class="text-lg font-semibold">❌ Chunks Échoués</h3>
<ul id="failed-chunks-list" class="list-disc pl-5"></ul>
<button id="retry-failed" class="mt-4 bg-yellow-500 text-white px-4 py-2 rounded hover:bg-yellow-600">
Réessayer les Chunks Échoués
</button>
</div>
</section>
<!-- Results Section -->
<section class="bg-white p-6 rounded-lg shadow-md">
<h2 class="text-2xl font-semibold mb-4">📊 Résultats de Génération</h2>
<div id="results-status" class="text-gray-700 mb-4">
Aucun résultat disponible pour le moment.
</div>
<a id="download-results" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" href="#" style="display: none;">
📥 Télécharger le Dataset Complet
</a>
<!-- Questions Preview -->
<h3 class="text-lg font-semibold mt-6">👀 Aperçu des Questions</h3>
<table class="w-full mt-4 border-collapse">
<thead>
<tr class="bg-gray-200">
<th class="border p-2">Question</th>
<th class="border p-2">Type</th>
<th class="border p-2">Difficulté</th>
<th class="border p-2">But d'Entraînement</th>
<th class="border p-2">Chunk ID</th>
<th class="border p-2">Clé API</th>
</tr>
</thead>
<tbody id="questions-table"></tbody>
</table>
</section>
</div>
<script>
// Utility function to fetch data from API
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return await response.json();
} catch (error) {
console.error('Error fetching data:', error);
return null;
}
}
// Update API Keys Status
async function updateApiKeysStatus() {
const statusDiv = document.getElementById('api-keys-status');
const data = await fetchData('/api-keys-status');
if (data && data.status === 'success') {
statusDiv.innerHTML = `${data.total_keys} clés API configurées pour rotation. Clé actuelle: ${data.current_key_index}`;
} else {
statusDiv.innerHTML = `Erreur: ${data?.message || 'Impossible de vérifier les clés API'}`;
}
}
// Update Generation Status
async function updateGenerationStatus() {
const data = await fetchData('/generation-status');
if (!data) return;
const statusDiv = document.getElementById('generation-status');
const progressBar = document.getElementById('progress-bar');
const progressText = document.getElementById('progress-text');
const processedChunks = document.getElementById('processed-chunks');
const totalChunks = document.getElementById('total-chunks');
const questionsGenerated = document.getElementById('questions-generated');
const currentApiKey = document.getElementById('current-api-key');
const failedChunksCount = document.getElementById('failed-chunks-count');
const estimatedTime = document.getElementById('estimated-time');
const downloadProgress = document.getElementById('download-progress');
const failedChunksDiv = document.getElementById('failed-chunks');
const failedChunksList = document.getElementById('failed-chunks-list');
if (data.is_running) {
statusDiv.innerHTML = 'Génération en cours...';
} else if (data.completed) {
statusDiv.innerHTML = 'Génération terminée!';
} else if (data.error) {
statusDiv.innerHTML = `Erreur: ${data.error}`;
} else {
statusDiv.innerHTML = 'Prêt à générer des questions.';
}
progressBar.style.width = `${data.progress_percentage || 0}%`;
progressText.innerText = `${data.progress_percentage || 0}%`;
processedChunks.innerText = data.processed_chunks || 0;
totalChunks.innerText = data.total_chunks || 0;
questionsGenerated.innerText = data.questions_generated || 0;
currentApiKey.innerText = data.current_api_key_index || '-';
failedChunksCount.innerText = data.failed_chunks?.length || 0;
if (data.estimated_remaining_minutes) {
estimatedTime.innerHTML = `⏱️ Temps estimé restant: ${data.estimated_remaining_minutes} minutes`;
} else {
estimatedTime.innerHTML = '⏱️ Temps estimé restant: Calcul en cours...';
}
// Update download progress link
if (data.progress_file) {
downloadProgress.href = `/download/${data.progress_file}`;
downloadProgress.style.display = 'inline-block';
} else {
downloadProgress.style.display = 'none';
}
// Update failed chunks
if (data.failed_chunks?.length > 0) {
failedChunksDiv.classList.remove('hidden');
failedChunksList.innerHTML = data.failed_chunks.map(chunk =>
`<li>Chunk ${chunk.chunk_id}: ${chunk.error} (Tentatives: ${chunk.attempts})</li>`
).join('');
} else {
failedChunksDiv.classList.add('hidden');
}
// Update results
updateResults(data);
}
// Update Results and Questions Preview
async function updateResults(statusData) {
const resultsStatus = document.getElementById('results-status');
const downloadResults = document.getElementById('download-results');
const questionsTable = document.getElementById('questions-table');
if (statusData.completed && statusData.result_file) {
resultsStatus.innerHTML = `Dataset généré avec ${statusData.questions_generated} questions.`;
downloadResults.href = `/download/${statusData.result_file}`;
downloadResults.style.display = 'inline-block';
} else if (statusData.partial_results?.length > 0) {
resultsStatus.innerHTML = `Résultats partiels disponibles (${statusData.partial_results.length} questions).`;
downloadResults.style.display = 'none';
} else {
resultsStatus.innerHTML = 'Aucun résultat disponible pour le moment.';
downloadResults.style.display = 'none';
}
// Update questions preview
questionsTable.innerHTML = statusData.partial_results?.slice(0, 10).map(q => `
<tr>
<td class="border p-2">${q.question}</td>
<td class="border p-2">${q.type}</td>
<td class="border p-2">${q.difficulty}</td>
<td class="border p-2">${q.training_purpose}</td>
<td class="border p-2">${q.chunk_id}</td>
<td class="border p-2">${q.api_key_used}</td>
</tr>
`).join('') || '';
}
// Start Generation
async function startGeneration() {
const generateButton = document.getElementById('generate-questions');
generateButton.disabled = true;
generateButton.innerText = 'Génération en cours...';
const response = await fetchData('/generate-questions');
if (response && response.status === 'started') {
alert(response.message);
// Start polling for status
const interval = setInterval(() => {
updateGenerationStatus().then(() => {
if (!response.is_running && response.completed) {
clearInterval(interval);
generateButton.disabled = false;
generateButton.innerText = 'Générer des Questions';
}
});
}, 5000);
} else {
alert(response?.message || 'Erreur lors du démarrage de la génération.');
generateButton.disabled = false;
generateButton.innerText = 'Générer des Questions';
}
}
// Retry Failed Chunks
async function retryFailedChunks() {
const retryButton = document.getElementById('retry-failed');
retryButton.disabled = true;
const response = await fetchData('/retry-failed');
alert(response.message);
retryButton.disabled = false;
updateGenerationStatus();
}
// Event Listeners
document.getElementById('check-api-keys').addEventListener('click', updateApiKeysStatus);
document.getElementById('generate-questions').addEventListener('click', startGeneration);
document.getElementById('view-failed-chunks').addEventListener('click', () => {
document.getElementById('failed-chunks').classList.toggle('hidden');
});
document.getElementById('retry-failed').addEventListener('click', retryFailedChunks);
// Initial Load
updateApiKeysStatus();
updateGenerationStatus();
</script>
</body>
</html>