File size: 13,020 Bytes
944616a
 
 
 
 
778a327
 
944616a
778a327
 
 
 
 
 
 
 
 
 
3552aba
778a327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8517947
778a327
 
 
 
8517947
778a327
 
 
 
 
3552aba
778a327
3552aba
778a327
 
 
 
 
 
 
3552aba
778a327
 
 
 
8517947
778a327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
944616a
778a327
 
 
 
 
 
 
944616a
 
778a327
944616a
778a327
944616a
 
 
778a327
 
3552aba
778a327
 
 
3552aba
778a327
 
3552aba
 
778a327
 
 
 
 
 
 
 
 
3552aba
944616a
778a327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3552aba
778a327
 
 
 
 
 
 
 
 
 
 
 
 
944616a
778a327
 
 
 
 
 
 
3552aba
778a327
 
 
 
 
 
 
 
 
3552aba
778a327
 
 
3552aba
778a327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3552aba
778a327
 
 
 
 
 
 
 
 
 
 
 
3552aba
778a327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
944616a
 
778a327
 
 
 
 
 
 
 
 
3552aba
778a327
 
 
 
 
 
 
 
 
 
 
 
944616a
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
<!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>