kuro223 commited on
Commit
9f6e9e1
·
1 Parent(s): 5e9e9c2

jojdgldsopp

Browse files
Files changed (3) hide show
  1. app.py +33 -4
  2. templates/index.html +26 -7
  3. test_frontend.html +128 -0
app.py CHANGED
@@ -174,6 +174,25 @@ def chat():
174
  return
175
 
176
  print(f"Démarrage du streaming pour conversation {conversation_id}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  response_stream = chat.send_message_stream(
178
  message,
179
  config=generation_config
@@ -206,8 +225,13 @@ def chat():
206
  except Exception as e:
207
  print(f"ERREUR lors du streaming: {e}")
208
  yield f"data: {json.dumps({'type': 'error', 'content': f'Erreur API: {str(e)}'})}\n\n"
209
-
210
- return Response(generate(), mimetype='text/plain')
 
 
 
 
 
211
 
212
  except Exception as e:
213
  return jsonify({'error': str(e)}), 500
@@ -336,8 +360,13 @@ def chat_with_file():
336
  except Exception as e:
337
  print(f"ERREUR lors du streaming avec fichiers: {e}")
338
  yield f"data: {json.dumps({'type': 'error', 'content': f'Erreur API avec fichiers: {str(e)}'})}\n\n"
339
-
340
- return Response(generate(), mimetype='text/plain')
 
 
 
 
 
341
 
342
  except Exception as e:
343
  return jsonify({'error': str(e)}), 500
 
174
  return
175
 
176
  print(f"Démarrage du streaming pour conversation {conversation_id}")
177
+
178
+ # TEST: Simulation de réponse pour debug
179
+ import time
180
+ test_response = "Bonjour ! Je suis Mariam, votre assistant IA. Comment puis-je vous aider aujourd'hui ?"
181
+ for i, char in enumerate(test_response):
182
+ yield f"data: {json.dumps({'type': 'text', 'content': char})}\n\n"
183
+ time.sleep(0.01) # Petit délai pour simuler le streaming
184
+
185
+ print(f"Test streaming terminé, réponse complète: {len(test_response)} caractères")
186
+
187
+ # Ajouter la réponse de l'assistant à l'historique
188
+ add_message_to_history(conversation_id, 'assistant', test_response)
189
+
190
+ # Signal de fin
191
+ yield f"data: {json.dumps({'type': 'end'})}\n\n"
192
+
193
+ return
194
+
195
+ # CODE ORIGINAL COMMENTÉ POUR TEST
196
  response_stream = chat.send_message_stream(
197
  message,
198
  config=generation_config
 
225
  except Exception as e:
226
  print(f"ERREUR lors du streaming: {e}")
227
  yield f"data: {json.dumps({'type': 'error', 'content': f'Erreur API: {str(e)}'})}\n\n"
228
+
229
+ return Response(generate(), mimetype='text/event-stream', headers={
230
+ 'Cache-Control': 'no-cache',
231
+ 'Connection': 'keep-alive',
232
+ 'Access-Control-Allow-Origin': '*',
233
+ 'Access-Control-Allow-Headers': 'Content-Type',
234
+ })
235
 
236
  except Exception as e:
237
  return jsonify({'error': str(e)}), 500
 
360
  except Exception as e:
361
  print(f"ERREUR lors du streaming avec fichiers: {e}")
362
  yield f"data: {json.dumps({'type': 'error', 'content': f'Erreur API avec fichiers: {str(e)}'})}\n\n"
363
+
364
+ return Response(generate(), mimetype='text/event-stream', headers={
365
+ 'Cache-Control': 'no-cache',
366
+ 'Connection': 'keep-alive',
367
+ 'Access-Control-Allow-Origin': '*',
368
+ 'Access-Control-Allow-Headers': 'Content-Type',
369
+ })
370
 
371
  except Exception as e:
372
  return jsonify({'error': str(e)}), 500
templates/index.html CHANGED
@@ -27,7 +27,7 @@
27
  <style>
28
  /* Configuration Marked pour le markdown */
29
  .markdown-content {
30
- @apply text-dark-text leading-relaxed;
31
  }
32
  .markdown-content h1, .markdown-content h2, .markdown-content h3 {
33
  @apply font-bold mb-2 mt-4;
@@ -311,16 +311,29 @@
311
  if (line.startsWith('data: ')) {
312
  try {
313
  const data = JSON.parse(line.substring(6));
314
-
 
315
  if (data.type === 'text') {
 
316
  messageContent += data.content;
317
  if (!messageElement) {
318
  messageElement = addMessage('assistant', '');
 
319
  }
320
  // Rendu markdown en temps réel
321
  const markdownHtml = marked.parse(messageContent);
322
- messageElement.querySelector('.markdown-content').innerHTML = markdownHtml;
 
 
 
 
 
 
 
 
 
323
  } else if (data.type === 'thought' && thinkingEnabled) {
 
324
  thoughtsContent += data.content;
325
  if (!thoughtsContainer) {
326
  thoughtsContainer = addThoughtsContainer();
@@ -329,8 +342,10 @@
329
  const thoughtsHtml = marked.parse(thoughtsContent);
330
  thoughtsContainer.querySelector('.thoughts-content .markdown-content').innerHTML = thoughtsHtml;
331
  } else if (data.type === 'error') {
 
332
  showError(data.content);
333
  } else if (data.type === 'end') {
 
334
  typingIndicator.classList.add('hidden');
335
  typingIndicator.classList.remove('flex');
336
  messageInput.disabled = false;
@@ -338,6 +353,8 @@
338
  messageInput.focus();
339
  removeFile();
340
  return;
 
 
341
  }
342
 
343
  const messagesContainer = document.getElementById('messages');
@@ -364,6 +381,7 @@
364
  }
365
 
366
  function addMessage(role, content, fileData = null) {
 
367
  const messagesContainer = document.getElementById('messages');
368
  const messageDiv = document.createElement('div');
369
 
@@ -379,10 +397,10 @@
379
  });
380
  }
381
 
382
- if (content) {
383
- const markdownHtml = marked.parse(content);
384
- messageContent += `<div class="markdown-content">${markdownHtml}</div>`;
385
- }
386
 
387
  if (role === 'user') {
388
  messageDiv.className = 'max-w-[85%] p-4 rounded-2xl bg-gray-600 text-gray-100 self-end rounded-br-sm animate-fade-in';
@@ -391,6 +409,7 @@
391
  }
392
 
393
  messageDiv.innerHTML = messageContent;
 
394
 
395
  messagesContainer.appendChild(messageDiv);
396
  messagesContainer.scrollTop = messagesContainer.scrollHeight;
 
27
  <style>
28
  /* Configuration Marked pour le markdown */
29
  .markdown-content {
30
+ @apply text-white leading-relaxed; /* Changé temporairement pour debug */
31
  }
32
  .markdown-content h1, .markdown-content h2, .markdown-content h3 {
33
  @apply font-bold mb-2 mt-4;
 
311
  if (line.startsWith('data: ')) {
312
  try {
313
  const data = JSON.parse(line.substring(6));
314
+ console.log('Received data:', data);
315
+
316
  if (data.type === 'text') {
317
+ console.log('Processing text:', data.content);
318
  messageContent += data.content;
319
  if (!messageElement) {
320
  messageElement = addMessage('assistant', '');
321
+ console.log('Created message element:', messageElement);
322
  }
323
  // Rendu markdown en temps réel
324
  const markdownHtml = marked.parse(messageContent);
325
+ const markdownElement = messageElement.querySelector('.markdown-content');
326
+ if (markdownElement) {
327
+ markdownElement.innerHTML = markdownHtml;
328
+ console.log('Updated markdown content to:', markdownHtml);
329
+ // Forcer un re-render
330
+ markdownElement.style.display = 'block';
331
+ } else {
332
+ console.error('No .markdown-content element found');
333
+ console.log('Message element HTML:', messageElement.innerHTML);
334
+ }
335
  } else if (data.type === 'thought' && thinkingEnabled) {
336
+ console.log('Processing thought:', data.content);
337
  thoughtsContent += data.content;
338
  if (!thoughtsContainer) {
339
  thoughtsContainer = addThoughtsContainer();
 
342
  const thoughtsHtml = marked.parse(thoughtsContent);
343
  thoughtsContainer.querySelector('.thoughts-content .markdown-content').innerHTML = thoughtsHtml;
344
  } else if (data.type === 'error') {
345
+ console.log('Received error:', data.content);
346
  showError(data.content);
347
  } else if (data.type === 'end') {
348
+ console.log('Stream ended');
349
  typingIndicator.classList.add('hidden');
350
  typingIndicator.classList.remove('flex');
351
  messageInput.disabled = false;
 
353
  messageInput.focus();
354
  removeFile();
355
  return;
356
+ } else {
357
+ console.log('Unknown data type:', data.type);
358
  }
359
 
360
  const messagesContainer = document.getElementById('messages');
 
381
  }
382
 
383
  function addMessage(role, content, fileData = null) {
384
+ console.log('addMessage called with role:', role, 'content:', content);
385
  const messagesContainer = document.getElementById('messages');
386
  const messageDiv = document.createElement('div');
387
 
 
397
  });
398
  }
399
 
400
+ // Toujours créer la structure markdown-content, même si content est vide
401
+ const markdownHtml = marked.parse(content || '');
402
+ messageContent += `<div class="markdown-content">${markdownHtml}</div>`;
403
+ console.log('Message content HTML:', messageContent);
404
 
405
  if (role === 'user') {
406
  messageDiv.className = 'max-w-[85%] p-4 rounded-2xl bg-gray-600 text-gray-100 self-end rounded-br-sm animate-fade-in';
 
409
  }
410
 
411
  messageDiv.innerHTML = messageContent;
412
+ console.log('Message div created:', messageDiv);
413
 
414
  messagesContainer.appendChild(messageDiv);
415
  messagesContainer.scrollTop = messagesContainer.scrollHeight;
test_frontend.html ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Test Frontend</title>
5
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.3.0/marked.min.js"></script>
6
+ </head>
7
+ <body>
8
+ <h1>Test du streaming comme le frontend réel</h1>
9
+ <button onclick="testStream()">Tester le stream</button>
10
+ <div id="messages" style="border: 1px solid black; padding: 10px; min-height: 200px;"></div>
11
+ <div id="output"></div>
12
+
13
+ <script>
14
+ marked.setOptions({
15
+ breaks: true,
16
+ gfm: true
17
+ });
18
+
19
+ function addMessage(role, content) {
20
+ console.log('addMessage called with role:', role, 'content:', content);
21
+ const messagesContainer = document.getElementById('messages');
22
+ const messageDiv = document.createElement('div');
23
+
24
+ let messageContent = '';
25
+
26
+ // Toujours créer la structure markdown-content, même si content est vide
27
+ const markdownHtml = marked.parse(content || '');
28
+ messageContent += `<div class="markdown-content">${markdownHtml}</div>`;
29
+ console.log('Message content HTML:', messageContent);
30
+
31
+ if (role === 'user') {
32
+ messageDiv.style.cssText = 'max-width: 85%; padding: 1rem; background: #4a5568; color: #f7fafc; margin: 0.5rem 0; border-radius: 1rem; margin-left: auto; margin-right: 0;';
33
+ } else {
34
+ messageDiv.style.cssText = 'max-width: 85%; padding: 1rem; background: #2d3748; color: #e2e8f0; margin: 0.5rem 0; border-radius: 1rem; margin-right: auto; margin-left: 0;';
35
+ }
36
+
37
+ messageDiv.innerHTML = messageContent;
38
+ console.log('Message div created:', messageDiv);
39
+
40
+ messagesContainer.appendChild(messageDiv);
41
+ return messageDiv;
42
+ }
43
+
44
+ function testStream() {
45
+ const output = document.getElementById('output');
46
+ output.innerHTML = 'Connexion...<br>';
47
+
48
+ fetch('http://localhost:5000/chat', {
49
+ method: 'POST',
50
+ headers: { 'Content-Type': 'application/json' },
51
+ body: JSON.stringify({
52
+ message: 'Bonjour',
53
+ thinking_enabled: true,
54
+ conversation_id: 'test'
55
+ })
56
+ })
57
+ .then(response => {
58
+ if (!response.ok) {
59
+ throw new Error(`Erreur: ${response.status}`);
60
+ }
61
+
62
+ const reader = response.body.getReader();
63
+ const decoder = new TextDecoder();
64
+ let buffer = '';
65
+ let messageElement = null;
66
+ let messageContent = '';
67
+
68
+ function processStream() {
69
+ return reader.read().then(({ done, value }) => {
70
+ if (done) {
71
+ output.innerHTML += 'Stream terminé<br>';
72
+ return;
73
+ }
74
+
75
+ buffer += decoder.decode(value, { stream: true });
76
+ const lines = buffer.split('\n');
77
+ buffer = lines.pop() || '';
78
+
79
+ for (const line of lines) {
80
+ output.innerHTML += `Ligne: ${line}<br>`;
81
+ if (line.startsWith('data: ')) {
82
+ try {
83
+ const data = JSON.parse(line.substring(6));
84
+ output.innerHTML += `Données: ${JSON.stringify(data)}<br>`;
85
+ console.log('Received data:', data);
86
+
87
+ if (data.type === 'text') {
88
+ console.log('Processing text:', data.content);
89
+ messageContent += data.content;
90
+ if (!messageElement) {
91
+ messageElement = addMessage('assistant', '');
92
+ console.log('Created message element:', messageElement);
93
+ }
94
+ // Rendu markdown en temps réel
95
+ const markdownHtml = marked.parse(messageContent);
96
+ const markdownElement = messageElement.querySelector('.markdown-content');
97
+ if (markdownElement) {
98
+ markdownElement.innerHTML = markdownHtml;
99
+ console.log('Updated markdown content');
100
+ output.innerHTML += `Contenu mis à jour: ${messageContent}<br>`;
101
+ } else {
102
+ console.error('No .markdown-content element found');
103
+ output.innerHTML += `ERREUR: Pas d'élément .markdown-content trouvé<br>`;
104
+ }
105
+ } else if (data.type === 'end') {
106
+ output.innerHTML += 'Fin du stream<br>';
107
+ return;
108
+ }
109
+ } catch (e) {
110
+ output.innerHTML += `Erreur parsing: ${e}<br>`;
111
+ console.error('Erreur parsing JSON:', e, "Ligne reçue:", line);
112
+ }
113
+ }
114
+ }
115
+
116
+ return processStream();
117
+ });
118
+ }
119
+
120
+ return processStream();
121
+ })
122
+ .catch(error => {
123
+ output.innerHTML += `Erreur: ${error.message}<br>`;
124
+ });
125
+ }
126
+ </script>
127
+ </body>
128
+ </html>