|
<!DOCTYPE html> |
|
<html lang="fr"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Mariam AI</title> |
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet"> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.0.2/marked.min.js"></script> |
|
</head> |
|
<body class="bg-gray-100 h-screen"> |
|
<div class="container mx-auto p-4 h-full flex flex-col"> |
|
|
|
<div class="grid grid-cols-4 gap-4 h-full"> |
|
<div class="bg-white rounded-lg shadow-lg p-4"> |
|
<div class="flex flex-col h-full"> |
|
<button onclick="startNewConversation()" class="w-full bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 mb-4"> |
|
Nouvelle conversation |
|
</button> |
|
<div id="conversationsList" class="flex-1 overflow-y-auto space-y-2"> |
|
|
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="col-span-3 bg-white rounded-lg shadow-lg p-6 flex flex-col"> |
|
|
|
<div class="flex justify-between items-center mb-6"> |
|
<h1 class="text-2xl font-bold">Mariam AI</h1> |
|
<div class="flex space-x-4"> |
|
<label class="flex items-center"> |
|
<input type="checkbox" id="webSearchToggle" class="mr-2"> |
|
Activer la recherche web |
|
</label> |
|
<button onclick="clearChat()" class="bg-red-500 text-white px-4 py-2 rounded hover:bg-red-600"> |
|
Effacer le chat |
|
</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="mb-4"> |
|
<input type="file" id="fileUpload" class="hidden" accept=".jpg,.jpeg,.png,.pdf,.txt,.mp3,.mp4"> |
|
<label for="fileUpload" class="cursor-pointer bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"> |
|
Télécharger un fichier |
|
</label> |
|
<span id="fileName" class="ml-2 text-gray-600"></span> |
|
</div> |
|
|
|
|
|
<div id="chatMessages" class="flex-1 overflow-y-auto mb-4 space-y-4 bg-gray-50 p-4 rounded-lg"> |
|
|
|
</div> |
|
|
|
|
|
<div class="border-t pt-4"> |
|
<div class="flex space-x-4"> |
|
<input type="text" id="messageInput" |
|
class="flex-1 border rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" |
|
placeholder="Écrivez votre message..."> |
|
<button onclick="sendMessage()" |
|
class="bg-blue-500 text-white px-6 py-2 rounded-lg hover:bg-blue-600 transition duration-200"> |
|
Envoyer |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
|
|
const messageInput = document.getElementById('messageInput'); |
|
const chatMessages = document.getElementById('chatMessages'); |
|
const webSearchToggle = document.getElementById('webSearchToggle'); |
|
const fileUpload = document.getElementById('fileUpload'); |
|
const fileName = document.getElementById('fileName'); |
|
const conversationsList = document.getElementById('conversationsList'); |
|
|
|
let conversations = []; |
|
let currentConversationId = null; |
|
|
|
|
|
function startNewConversation() { |
|
const conversationId = Date.now().toString(); |
|
const conversation = { |
|
id: conversationId, |
|
title: `Conversation ${conversations.length + 1}`, |
|
messages: [] |
|
}; |
|
|
|
conversations.push(conversation); |
|
currentConversationId = conversationId; |
|
updateConversationsList(); |
|
clearChatMessages(); |
|
} |
|
|
|
function updateConversationsList() { |
|
conversationsList.innerHTML = ''; |
|
conversations.forEach(conv => { |
|
const convDiv = document.createElement('div'); |
|
convDiv.className = `p-2 rounded cursor-pointer ${conv.id === currentConversationId ? 'bg-blue-100' : 'hover:bg-gray-100'}`; |
|
convDiv.onclick = () => loadConversation(conv.id); |
|
convDiv.textContent = conv.title; |
|
conversationsList.appendChild(convDiv); |
|
}); |
|
} |
|
|
|
|
|
async function loadConversation(conversationId) { |
|
if (conversationId === currentConversationId) return; |
|
|
|
try { |
|
|
|
const response = await fetch('/switch_conversation', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json' |
|
}, |
|
body: JSON.stringify({ |
|
conversation_id: conversationId |
|
}) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.error) { |
|
alert(`Erreur: ${data.error}`); |
|
return; |
|
} |
|
|
|
currentConversationId = conversationId; |
|
const conversation = conversations.find(c => c.id === conversationId); |
|
updateConversationsList(); |
|
|
|
if (conversation) { |
|
clearChatMessages(); |
|
|
|
conversation.messages.forEach(msg => { |
|
const messageDiv = document.createElement('div'); |
|
messageDiv.className = `flex ${msg.isUser ? 'justify-end' : ''}`; |
|
|
|
const innerDiv = document.createElement('div'); |
|
innerDiv.className = `max-w-3/4 p-3 rounded-lg ${msg.isUser ? 'bg-blue-500 text-white' : 'bg-gray-200'}`; |
|
innerDiv.innerHTML = marked.parse(msg.content); |
|
|
|
messageDiv.appendChild(innerDiv); |
|
chatMessages.appendChild(messageDiv); |
|
}); |
|
|
|
chatMessages.scrollTop = chatMessages.scrollHeight; |
|
} |
|
} catch (error) { |
|
alert(`Erreur lors du changement de conversation: ${error.message}`); |
|
} |
|
} |
|
|
|
function clearChatMessages() { |
|
chatMessages.innerHTML = ''; |
|
} |
|
|
|
function addMessage(content, isUser = false) { |
|
const messageDiv = document.createElement('div'); |
|
messageDiv.className = `flex ${isUser ? 'justify-end' : ''}`; |
|
|
|
const innerDiv = document.createElement('div'); |
|
innerDiv.className = `max-w-3/4 p-3 rounded-lg ${isUser ? 'bg-blue-500 text-white' : 'bg-gray-200'}`; |
|
innerDiv.innerHTML = marked.parse(content); |
|
|
|
messageDiv.appendChild(innerDiv); |
|
chatMessages.appendChild(messageDiv); |
|
chatMessages.scrollTop = chatMessages.scrollHeight; |
|
|
|
if (currentConversationId) { |
|
const conversation = conversations.find(c => c.id === currentConversationId); |
|
if (conversation) { |
|
conversation.messages.push({ content, isUser }); |
|
} |
|
} |
|
} |
|
|
|
|
|
async function sendMessage() { |
|
const message = messageInput.value.trim(); |
|
if (!message) return; |
|
|
|
if (!currentConversationId) { |
|
startNewConversation(); |
|
} |
|
|
|
addMessage(message, true); |
|
messageInput.value = ''; |
|
|
|
try { |
|
const response = await fetch('/send_message', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json' |
|
}, |
|
body: JSON.stringify({ |
|
message: message, |
|
web_search: webSearchToggle.checked, |
|
conversation_id: currentConversationId |
|
}) |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.error) { |
|
addMessage(`Erreur: ${data.error}`); |
|
} else { |
|
addMessage(data.response); |
|
} |
|
} catch (error) { |
|
addMessage(`Erreur: ${error.message}`); |
|
} |
|
} |
|
|
|
|
|
fileUpload.addEventListener('change', async (e) => { |
|
const file = e.target.files[0]; |
|
if (!file) return; |
|
|
|
fileName.textContent = file.name; |
|
const formData = new FormData(); |
|
formData.append('file', file); |
|
|
|
try { |
|
const response = await fetch('/upload', { |
|
method: 'POST', |
|
body: formData |
|
}); |
|
|
|
const data = await response.json(); |
|
if (data.error) { |
|
alert(`Erreur: ${data.error}`); |
|
} else { |
|
addMessage(`Fichier téléchargé: ${file.name}`); |
|
} |
|
} catch (error) { |
|
alert(`Erreur: ${error.message}`); |
|
} |
|
}); |
|
|
|
|
|
async function clearChat() { |
|
try { |
|
await fetch('/clear_chat', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json' |
|
}, |
|
body: JSON.stringify({ |
|
conversation_id: currentConversationId |
|
}) |
|
}); |
|
|
|
if (currentConversationId) { |
|
const conversation = conversations.find(c => c.id === currentConversationId); |
|
if (conversation) { |
|
conversation.messages = []; |
|
} |
|
} |
|
clearChatMessages(); |
|
} catch (error) { |
|
alert(`Erreur: ${error.message}`); |
|
} |
|
} |
|
|
|
|
|
messageInput.addEventListener('keypress', (e) => { |
|
if (e.key === 'Enter') { |
|
sendMessage(); |
|
} |
|
}); |
|
|
|
|
|
startNewConversation(); |
|
</script> |
|
</body> |
|
</html> |