| <!DOCTYPE html> |
| <html> |
|
|
| <head> |
| <title>RAG Chatbot</title> |
| <style> |
| :root { |
| --primary-color: #a0a0a0; |
| --background-color: #1a1a1a; |
| --card-background: #2d2d2d; |
| --text-color: #e0e0e0; |
| --border-radius: 6px; |
| --shadow: 0 4px 6px rgba(0, 0, 0, 0.3); |
| --input-background: #363636; |
| --input-border: #404040; |
| } |
| |
| body { |
| font-family: 'Segoe UI', Arial, sans-serif; |
| max-width: 1200px; |
| margin: 0 auto; |
| padding: 20px; |
| background-color: var(--background-color); |
| color: var(--text-color); |
| } |
| |
| .card { |
| background: var(--card-background); |
| border-radius: var(--border-radius); |
| box-shadow: var(--shadow); |
| padding: 2rem; |
| margin: 2rem 0; |
| } |
| |
| .chat-container { |
| background: var(--card-background); |
| border-radius: var(--border-radius); |
| padding: 1.5rem; |
| height: 700px; |
| overflow-y: auto; |
| margin-bottom: 1.5rem; |
| box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05); |
| border: 1px solid var(--input-border); |
| } |
| |
| .message { |
| margin-bottom: 1rem; |
| padding: 1rem; |
| border-radius: 4px; |
| max-width: 70%; |
| animation: fadeIn 0.3s ease; |
| } |
| |
| @keyframes fadeIn { |
| from { |
| opacity: 0; |
| transform: translateY(10px); |
| } |
| |
| to { |
| opacity: 1; |
| transform: translateY(0); |
| } |
| } |
| |
| .user-message { |
| background-color: #808080; |
| margin-left: auto; |
| color: #ffffff; |
| box-shadow: 0 2px 4px rgba(128, 128, 128, 0.2); |
| } |
| |
| .bot-message { |
| background-color: #363636; |
| margin-right: auto; |
| color: #e0e0e0; |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); |
| } |
| |
| .loading-dots { |
| display: inline-block; |
| } |
| |
| @keyframes dots { |
| 0% { |
| content: ''; |
| } |
| |
| 25% { |
| content: '.'; |
| } |
| |
| 50% { |
| content: '..'; |
| } |
| |
| 75% { |
| content: '...'; |
| } |
| |
| 100% { |
| content: ''; |
| } |
| } |
| |
| .loading-dots::after { |
| content: ''; |
| animation: dots 2s infinite; |
| display: inline-block; |
| width: 1em; |
| } |
| |
| .input-container { |
| display: flex; |
| gap: 12px; |
| padding: 1rem; |
| background: var(--card-background); |
| border-radius: var(--border-radius); |
| box-shadow: var(--shadow); |
| } |
| |
| .nav { |
| background: var(--card-background); |
| padding: 1rem; |
| border-radius: var(--border-radius); |
| box-shadow: var(--shadow); |
| margin-bottom: 1rem; |
| } |
| |
| .nav a { |
| margin-right: 20px; |
| text-decoration: none; |
| color: var(--primary-color); |
| font-weight: 500; |
| padding: 0.5rem 1rem; |
| border-radius: 4px; |
| transition: all 0.3s ease; |
| } |
| |
| .nav a:hover { |
| background: #363636; |
| } |
| |
| #messageInput { |
| flex-grow: 1; |
| padding: 12px; |
| border: 2px solid var(--input-border); |
| border-radius: 4px; |
| font-size: 1rem; |
| transition: all 0.3s ease; |
| background: var(--input-background); |
| color: var(--text-color); |
| } |
| |
| #messageInput:focus { |
| outline: none; |
| border-color: var(--primary-color); |
| box-shadow: 0 0 0 3px rgba(114, 137, 218, 0.1); |
| } |
| |
| button { |
| background: var(--primary-color); |
| color: white; |
| border: none; |
| padding: 12px 24px; |
| border-radius: 4px; |
| cursor: pointer; |
| font-size: 1rem; |
| transition: all 0.3s ease; |
| } |
| |
| button:hover { |
| background: #909090; |
| transform: translateY(-2px); |
| } |
| |
| h1 { |
| color: var(--primary-color); |
| text-align: center; |
| margin-bottom: 1.5rem; |
| } |
| |
| |
| .chat-container::-webkit-scrollbar { |
| width: 8px; |
| } |
| |
| .chat-container::-webkit-scrollbar-track { |
| background: #363636; |
| } |
| |
| .chat-container::-webkit-scrollbar-thumb { |
| background: #4a4a4a; |
| } |
| |
| .chat-container::-webkit-scrollbar-thumb:hover { |
| background: #5a5a5a; |
| } |
| |
| |
| .main-container { |
| display: flex; |
| gap: 20px; |
| height: calc(100vh - 100px); |
| |
| } |
| |
| .chat-card { |
| flex: 3; |
| background: var(--card-background); |
| border-radius: var(--border-radius); |
| box-shadow: var(--shadow); |
| padding: 2rem; |
| margin: 1rem 0; |
| display: flex; |
| flex-direction: column; |
| height: fit-content; |
| } |
| |
| .sources-card { |
| flex: 1; |
| background: var(--card-background); |
| border-radius: var(--border-radius); |
| box-shadow: var(--shadow); |
| padding: 2rem; |
| margin: 1rem 0; |
| min-width: 250px; |
| display: flex; |
| flex-direction: column; |
| height: auto; |
| } |
| |
| .source-item { |
| padding: 10px; |
| margin-bottom: 10px; |
| background: var(--input-background); |
| border-radius: var(--border-radius); |
| font-size: 0.9rem; |
| border: 1px solid var(--input-border); |
| } |
| |
| .sources-title { |
| color: var(--text-color); |
| font-size: 1.2rem; |
| margin-bottom: 1rem; |
| padding-bottom: 0.5rem; |
| border-bottom: 1px solid var(--input-border); |
| } |
| |
| #sourcesContainer { |
| flex: 1; |
| overflow-y: auto; |
| } |
| |
| .logo-container { |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| margin-bottom: 1rem; |
| } |
| </style> |
| </head> |
|
|
| <body> |
| <div class="nav"> |
| <a href="/">Upload</a> |
| <a href="/chat">Chat</a> |
| </div> |
| <div class="main-container"> |
| <div class="chat-card"> |
| <div class="chat-container" id="chatContainer"> |
| </div> |
| <div class="input-container"> |
| <input type="text" id="messageInput" placeholder="Type your message..."> |
| <button onclick="sendMessage()">Send</button> |
| </div> |
| </div> |
| <div class="sources-card"> |
| <h2 class="sources-title">Sources</h2> |
| <div id="sourcesContainer"></div> |
| </div> |
| </div> |
|
|
| <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> |
| <script> |
| const chatContainer = document.getElementById('chatContainer'); |
| const messageInput = document.getElementById('messageInput'); |
| const sourcesContainer = document.getElementById('sourcesContainer'); |
| |
| function addMessage(message, isUser) { |
| const messageDiv = document.createElement('div'); |
| messageDiv.className = `message ${isUser ? 'user-message' : 'bot-message'}`; |
| messageDiv.textContent = message; |
| chatContainer.appendChild(messageDiv); |
| chatContainer.scrollTop = chatContainer.scrollHeight; |
| return messageDiv; |
| } |
| |
| function updateSources(sources) { |
| sourcesContainer.innerHTML = ''; |
| if (sources && sources.length > 0) { |
| sources.forEach(source => { |
| const sourceDiv = document.createElement('div'); |
| sourceDiv.className = 'source-item'; |
| sourceDiv.textContent = source; |
| sourcesContainer.appendChild(sourceDiv); |
| }); |
| } |
| } |
| |
| async function sendMessage() { |
| const message = messageInput.value.trim(); |
| if (!message) return; |
| |
| addMessage(message, true); |
| messageInput.value = ''; |
| |
| |
| const loadingDiv = document.createElement('div'); |
| loadingDiv.className = 'message bot-message'; |
| const loadingSpan = document.createElement('span'); |
| loadingSpan.className = 'loading-dots'; |
| loadingSpan.textContent = 'Thinking'; |
| loadingDiv.appendChild(loadingSpan); |
| chatContainer.appendChild(loadingDiv); |
| chatContainer.scrollTop = chatContainer.scrollHeight; |
| |
| try { |
| const response = await fetch('/chat', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ question: message }), |
| }); |
| |
| const data = await response.json(); |
| |
| |
| chatContainer.removeChild(loadingDiv); |
| |
| if (data.error) { |
| addMessage(data.error, false); |
| return; |
| } |
| |
| |
| const tempDiv = document.createElement('div'); |
| tempDiv.innerHTML = marked.parse(data.answer[0]); |
| |
| |
| const messageDiv = document.createElement('div'); |
| messageDiv.className = 'message bot-message'; |
| messageDiv.innerHTML = tempDiv.innerHTML; |
| |
| chatContainer.appendChild(messageDiv); |
| chatContainer.scrollTop = chatContainer.scrollHeight; |
| |
| |
| if (data.answer[1]) { |
| updateSources(data.answer[1]); |
| } |
| } catch (error) { |
| |
| chatContainer.removeChild(loadingDiv); |
| console.error('Error:', error); |
| addMessage('Sorry, there was an error processing your message.', false); |
| } |
| } |
| |
| messageInput.addEventListener('keypress', function (e) { |
| if (e.key === 'Enter') { |
| sendMessage(); |
| } |
| }); |
| </script> |
| </body> |
|
|
| </html> |