AdrienB134's picture
Update templates/chat.html
0800c82 verified
<!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;
}
/* Scrollbar styling */
.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;
}
/* Add these new styles */
.main-container {
display: flex;
gap: 20px;
height: calc(100vh - 100px);
/* Adjust for nav and padding */
}
.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="logo-container">
<img src="./static/Matriv-white.png" alt="Matriv Logo" style="width: 100px; height: auto;">
</div>
<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 = '';
// Add loading message
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();
// Remove loading message
chatContainer.removeChild(loadingDiv);
if (data.error) {
addMessage(data.error, false);
return;
}
// Create a temporary div to render markdown
const tempDiv = document.createElement('div');
tempDiv.innerHTML = marked.parse(data.answer[0]);
// Create message div with markdown content
const messageDiv = document.createElement('div');
messageDiv.className = 'message bot-message';
messageDiv.innerHTML = tempDiv.innerHTML;
chatContainer.appendChild(messageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
// Update sources if they exist in the response
if (data.answer[1]) {
updateSources(data.answer[1]);
}
} catch (error) {
// Remove loading message
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>