File size: 10,420 Bytes
8b150ac 07de6c6 333596d 8b150ac 333596d 07de6c6 333596d 8b150ac 333596d 07de6c6 333596d 07de6c6 8b150ac 333596d 07de6c6 333596d 8b150ac 333596d 8b150ac 333596d 07de6c6 333596d 07de6c6 333596d 8b150ac |
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 |
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> Chat - Analyse PDF</title>
<!-- Tailwind CSS via CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<style>
.chat-container {
height: calc(100vh - 220px);
}
</style>
</head>
<body class="bg-gray-100">
<div class="container mx-auto p-4 max-w-3xl">
<header class="bg-white shadow-md rounded-lg p-4 mb-4">
<h1 class="text-2xl font-bold text-center text-blue-600">Gemini Chat - Analyse PDF</h1>
<p class="text-center text-gray-500">Discutez avec l'IA à propos du document sur la langue Fang</p>
<div class="mt-2 text-center">
<a href="{{ pdf_url }}" target="_blank" class="text-blue-500 hover:underline">
📄 Consulter le PDF analysé
</a>
</div>
{% if error %}
<div class="mt-2 p-2 bg-red-100 text-red-700 rounded">
{{ error }}
</div>
{% endif %}
</header>
<div class="bg-white shadow-md rounded-lg p-4">
<!-- Zone d'historique de chat -->
<div id="chat-history" class="chat-container overflow-y-auto mb-4 p-3 bg-gray-50 rounded-lg">
<div class="text-center text-gray-400 my-4">
<p>Posez des questions sur le document PDF de la langue Fang.</p>
<p class="mt-2 text-sm">Exemples de questions:</p>
<ul class="text-sm mt-1 space-y-1">
<li>• Quelles sont les principales caractéristiques de la langue Fang?</li>
<li>• Expliquez la structure verbale en Fang</li>
<li>• Que dit le document sur la phonologie du Fang?</li>
</ul>
</div>
</div>
<!-- Zone de saisie et boutons -->
<div class="flex flex-col gap-2">
<div class="flex gap-2">
<textarea
id="user-input"
class="flex-grow p-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Posez une question sur le document Fang..."
rows="2"
></textarea>
<button
id="send-button"
class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg"
>
Envoyer
</button>
</div>
<button
id="reset-button"
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-lg self-end"
>
Nouvelle Conversation
</button>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const chatHistory = document.getElementById('chat-history');
const userInput = document.getElementById('user-input');
const sendButton = document.getElementById('send-button');
const resetButton = document.getElementById('reset-button');
// État de chargement
let isLoading = false;
// Fonction pour ajouter un message au chat
function addMessage(role, content, timestamp = getCurrentTime()) {
const messageDiv = document.createElement('div');
messageDiv.className = `my-2 p-3 rounded-lg ${role === 'user' ? 'bg-blue-100 ml-12' : 'bg-gray-100 mr-12'}`;
const header = document.createElement('div');
header.className = 'font-bold text-sm';
header.textContent = role === 'user' ? 'Vous' : 'Gemini';
const timeSpan = document.createElement('span');
timeSpan.className = 'text-xs text-gray-500 ml-2';
timeSpan.textContent = timestamp;
header.appendChild(timeSpan);
const contentDiv = document.createElement('div');
contentDiv.className = 'whitespace-pre-wrap';
contentDiv.textContent = content;
messageDiv.appendChild(header);
messageDiv.appendChild(contentDiv);
chatHistory.appendChild(messageDiv);
// Scroll to bottom
chatHistory.scrollTop = chatHistory.scrollHeight;
}
// Obtenir l'heure actuelle
function getCurrentTime() {
const now = new Date();
return `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
}
// Fonction pour afficher l'indicateur de chargement
function showLoading() {
if (isLoading) return;
isLoading = true;
const loadingDiv = document.createElement('div');
loadingDiv.id = 'loading-indicator';
loadingDiv.className = 'my-2 p-3 bg-gray-100 rounded-lg mr-12 flex items-center';
loadingDiv.innerHTML = `
<div class="font-bold text-sm">Gemini</div>
<div class="ml-2">
<span class="inline-block w-2 h-2 bg-gray-500 rounded-full animate-bounce"></span>
<span class="inline-block w-2 h-2 bg-gray-500 rounded-full animate-bounce" style="animation-delay: 0.2s"></span>
<span class="inline-block w-2 h-2 bg-gray-500 rounded-full animate-bounce" style="animation-delay: 0.4s"></span>
</div>
`;
chatHistory.appendChild(loadingDiv);
chatHistory.scrollTop = chatHistory.scrollHeight;
}
// Fonction pour masquer l'indicateur de chargement
function hideLoading() {
if (!isLoading) return;
const loadingIndicator = document.getElementById('loading-indicator');
if (loadingIndicator) {
loadingIndicator.remove();
}
isLoading = false;
}
// Fonction pour envoyer un message
async function sendMessage() {
const message = userInput.value.trim();
if (!message) return;
// Remplacer le contenu initial si c'est le premier message
if (chatHistory.querySelector('.text-gray-400')) {
chatHistory.innerHTML = '';
}
// Vider l'input et ajouter le message de l'utilisateur
userInput.value = '';
addMessage('user', message);
// Afficher l'indicateur de chargement
showLoading();
try {
// Envoyer la requête au serveur
const response = await fetch('/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message }),
});
if (!response.ok) {
throw new Error('Erreur de communication avec le serveur');
}
const data = await response.json();
// Masquer l'indicateur de chargement
hideLoading();
// Afficher la réponse
addMessage('model', data.response);
} catch (error) {
// Masquer l'indicateur de chargement
hideLoading();
// Afficher l'erreur
addMessage('system', `Erreur: ${error.message}`);
console.error('Erreur:', error);
}
}
// Réinitialiser la conversation
async function resetChat() {
try {
const response = await fetch('/reset', {
method: 'POST',
});
if (!response.ok) {
throw new Error('Erreur lors de la réinitialisation');
}
// Vider l'historique
chatHistory.innerHTML = `
<div class="text-center text-gray-400 my-4">
<p>Posez des questions sur le document PDF de la langue Fang.</p>
<p class="mt-2 text-sm">Exemples de questions:</p>
<ul class="text-sm mt-1 space-y-1">
<li>• Quelles sont les principales caractéristiques de la langue Fang?</li>
<li>• Expliquez la structure verbale en Fang</li>
<li>• Que dit le document sur la phonologie du Fang?</li>
</ul>
</div>
`;
} catch (error) {
console.error('Erreur de réinitialisation:', error);
alert('Impossible de réinitialiser la conversation. Veuillez réessayer.');
}
}
// Écouteurs d'événements
sendButton.addEventListener('click', sendMessage);
userInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
resetButton.addEventListener('click', resetChat);
});
</script>
</body>
</html> |