mafzaal's picture
Refactor Dockerfile and update README for FastAPI RAG application
7a1c9d6
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RAG Chat Application</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
background-color: #282c34;
color: white;
padding: 20px;
text-align: center;
}
header h1 {
margin: 0;
}
.upload-container {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 30px;
margin: 30px 0;
text-align: center;
}
.upload-container.hidden {
display: none;
}
.chat-container {
display: none;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
height: 70vh;
display: flex;
flex-direction: column;
}
.chat-container.visible {
display: flex;
}
.file-info {
background-color: #f1f1f1;
padding: 10px 20px;
border-bottom: 1px solid #e0e0e0;
text-align: left;
}
.chat-messages {
flex-grow: 1;
overflow-y: auto;
padding: 20px;
}
.welcome-message {
text-align: center;
color: #555;
margin: 30px 0;
}
.message {
max-width: 70%;
margin-bottom: 15px;
padding: 10px 15px;
border-radius: 8px;
font-size: 14px;
line-height: 1.5;
position: relative;
}
.user-message {
background-color: #2196F3;
color: white;
border-bottom-right-radius: 0;
margin-left: auto;
}
.ai-message {
background-color: #f1f1f1;
color: #333;
border-bottom-left-radius: 0;
}
.message.error {
background-color: #ffebee;
color: #d32f2f;
}
.message-sender {
font-weight: bold;
margin-bottom: 5px;
font-size: 12px;
}
.chat-input-form {
display: flex;
padding: 15px;
border-top: 1px solid #e0e0e0;
}
.chat-input {
flex-grow: 1;
padding: 12px 15px;
border: 1px solid #e0e0e0;
border-radius: 4px;
font-size: 14px;
}
.send-button {
background-color: #2196F3;
color: white;
border: none;
border-radius: 4px;
padding: 0 20px;
margin-left: 10px;
cursor: pointer;
font-size: 14px;
}
.send-button:disabled {
background-color: #ccc;
}
.file-input {
display: none;
}
.file-label {
display: inline-block;
padding: 12px 20px;
background-color: #4CAF50;
color: white;
border-radius: 4px;
cursor: pointer;
margin-bottom: 20px;
}
.upload-button {
padding: 12px 30px;
background-color: #2196F3;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.upload-button:disabled {
background-color: #ccc;
}
.error-message {
color: #d32f2f;
margin: 10px 0;
}
.loading {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
margin-bottom: 15px;
}
.loading .dot {
width: 8px;
height: 8px;
background-color: #2196F3;
border-radius: 50%;
animation: bounce 1.4s infinite ease-in-out both;
}
.loading .dot:nth-child(1) {
animation-delay: -0.32s;
}
.loading .dot:nth-child(2) {
animation-delay: -0.16s;
}
@keyframes bounce {
0%, 80%, 100% {
transform: scale(0);
}
40% {
transform: scale(1);
}
}
</style>
</head>
<body>
<header>
<h1>RAG Chat Application</h1>
</header>
<div class="container">
<div id="upload-container" class="upload-container">
<h2>Upload a Document</h2>
<p>Upload a text or PDF file to start chatting</p>
<div>
<input type="file" id="file-input" class="file-input" accept=".txt,.pdf">
<label for="file-input" class="file-label" id="file-label">Choose a file</label>
</div>
<div id="error-message" class="error-message"></div>
<button id="upload-button" class="upload-button" disabled>Upload</button>
</div>
<div id="chat-container" class="chat-container">
<div class="file-info">
<p>Using file: <strong id="filename-display"></strong></p>
</div>
<div id="chat-messages" class="chat-messages">
<div class="welcome-message">
<h3>Welcome to the RAG Chat!</h3>
<p>Ask questions about the document you uploaded.</p>
</div>
</div>
<form id="chat-form" class="chat-input-form">
<input type="text" id="chat-input" class="chat-input" placeholder="Ask a question about your document...">
<button type="submit" id="send-button" class="send-button">Send</button>
</form>
</div>
</div>
<script>
// Generate a session ID
const sessionId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
// DOM elements
const uploadContainer = document.getElementById('upload-container');
const chatContainer = document.getElementById('chat-container');
const fileInput = document.getElementById('file-input');
const fileLabel = document.getElementById('file-label');
const uploadButton = document.getElementById('upload-button');
const errorMessage = document.getElementById('error-message');
const filenameDisplay = document.getElementById('filename-display');
const chatMessages = document.getElementById('chat-messages');
const chatForm = document.getElementById('chat-form');
const chatInput = document.getElementById('chat-input');
const sendButton = document.getElementById('send-button');
// Event listeners
fileInput.addEventListener('change', handleFileChange);
uploadButton.addEventListener('click', handleUpload);
chatForm.addEventListener('submit', handleChatSubmit);
// Handle file selection
function handleFileChange(e) {
const file = e.target.files[0];
if (!file) {
fileLabel.textContent = 'Choose a file';
uploadButton.disabled = true;
return;
}
// Check file type
if (file.type !== 'text/plain' && file.type !== 'application/pdf') {
errorMessage.textContent = 'Please select a text or PDF file';
fileLabel.textContent = 'Choose a file';
uploadButton.disabled = true;
return;
}
// Check file size (2MB max)
if (file.size > 2 * 1024 * 1024) {
errorMessage.textContent = 'File size must be less than 2MB';
fileLabel.textContent = 'Choose a file';
uploadButton.disabled = true;
return;
}
fileLabel.textContent = file.name;
errorMessage.textContent = '';
uploadButton.disabled = false;
}
// Handle file upload
async function handleUpload() {
const file = fileInput.files[0];
if (!file) {
errorMessage.textContent = 'Please select a file';
return;
}
// Disable upload button and show loading state
uploadButton.disabled = true;
uploadButton.textContent = 'Uploading...';
errorMessage.textContent = '';
const formData = new FormData();
formData.append('file', file);
formData.append('session_id', sessionId);
try {
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.status === 'success') {
// Show chat container and hide upload container
uploadContainer.style.display = 'none';
chatContainer.style.display = 'flex';
filenameDisplay.textContent = file.name;
} else {
errorMessage.textContent = data.message || 'Failed to upload file';
}
} catch (error) {
console.error('Error uploading file:', error);
errorMessage.textContent = 'Failed to upload file';
} finally {
uploadButton.textContent = 'Upload';
uploadButton.disabled = false;
}
}
// Handle chat submission
async function handleChatSubmit(e) {
e.preventDefault();
const message = chatInput.value.trim();
if (!message) {
return;
}
// Disable input and button
chatInput.disabled = true;
sendButton.disabled = true;
// Add user message to chat
addMessage(message, 'user');
// Clear input
chatInput.value = '';
// Add loading indicator
const loadingElement = document.createElement('div');
loadingElement.className = 'loading';
loadingElement.innerHTML = `
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
`;
chatMessages.appendChild(loadingElement);
chatMessages.scrollTop = chatMessages.scrollHeight;
try {
const response = await fetch('/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
session_id: sessionId,
query: message
})
});
const data = await response.json();
// Remove loading indicator
chatMessages.removeChild(loadingElement);
// Add AI response to chat
addMessage(data.response, 'ai');
} catch (error) {
console.error('Error getting response:', error);
// Remove loading indicator
chatMessages.removeChild(loadingElement);
// Add error message
addMessage('Sorry, there was an error processing your request.', 'ai', true);
} finally {
chatInput.disabled = false;
sendButton.disabled = false;
chatInput.focus();
}
}
// Add message to chat
function addMessage(text, sender, isError = false) {
// Remove welcome message if it exists
const welcomeMessage = document.querySelector('.welcome-message');
if (welcomeMessage) {
chatMessages.removeChild(welcomeMessage);
}
const messageElement = document.createElement('div');
messageElement.className = `message ${sender}-message${isError ? ' error' : ''}`;
const senderElement = document.createElement('div');
senderElement.className = 'message-sender';
senderElement.textContent = sender === 'user' ? 'You' : 'AI';
const textElement = document.createElement('div');
textElement.className = 'message-text';
textElement.textContent = text;
messageElement.appendChild(senderElement);
messageElement.appendChild(textElement);
chatMessages.appendChild(messageElement);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
</script>
</body>
</html>