Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>RAG Application</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| } | |
| .container { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 20px; | |
| } | |
| .query-section { | |
| display: none; | |
| } | |
| .response-section { | |
| margin-top: 20px; | |
| border-top: 1px solid #ccc; | |
| padding-top: 20px; | |
| } | |
| textarea { | |
| width: 100%; | |
| height: 100px; | |
| } | |
| button { | |
| padding: 10px 20px; | |
| background-color: #007bff; | |
| color: white; | |
| border: none; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| } | |
| button:disabled { | |
| background-color: #ccc; | |
| } | |
| .context { | |
| background-color: #f8f9fa; | |
| padding: 10px; | |
| margin-top: 10px; | |
| border-radius: 4px; | |
| } | |
| .loading { | |
| opacity: 0.5; | |
| pointer-events: none; | |
| } | |
| .spinner { | |
| display: none; | |
| margin-left: 10px; | |
| color: #007bff; | |
| } | |
| .loading .spinner { | |
| display: inline; | |
| } | |
| /* Radio toggle styles */ | |
| .toggle-radio { | |
| display: none; /* Initially hidden */ | |
| align-items: center; | |
| gap: 10px; | |
| margin: 10px 0; | |
| } | |
| .toggle-radio input[type="radio"] { | |
| margin-right: 5px; | |
| } | |
| .toggle-radio label { | |
| display: flex; | |
| align-items: center; | |
| margin-right: 15px; | |
| color: #666; | |
| cursor: pointer; | |
| } | |
| #contextSection { | |
| display: none; /* Initially hidden */ | |
| } | |
| /* Initially hide these sections */ | |
| .query-section, | |
| .response-section, | |
| .toggle-radio, | |
| #contextSection { | |
| display: none; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>RAG Application</h1> | |
| <div class="upload-section"> | |
| <h2>Upload Document</h2> | |
| <input type="file" id="fileInput" accept=".txt,.pdf"> | |
| <button id="uploadButton" onclick="uploadFile()">Upload</button> | |
| <span id="uploadSpinner" class="spinner">Processing...</span> | |
| </div> | |
| <div id="querySection" class="query-section"> | |
| <h2>Ask a Question</h2> | |
| <textarea id="queryInput" placeholder="Enter your question here..."></textarea> | |
| <button id="queryButton" onclick="submitQuery()">Submit Query</button> | |
| <span id="querySpinner" class="spinner">Processing...</span> | |
| </div> | |
| <div id="responseSection" class="response-section"> | |
| <h2>Response</h2> | |
| <div id="answer"></div> | |
| <!-- Add radio toggle --> | |
| <div class="toggle-radio"> | |
| <span>Context: </span> | |
| <label> | |
| <input type="radio" name="contextToggle" value="show" onchange="toggleContext(this)"> Show | |
| </label> | |
| <label> | |
| <input type="radio" name="contextToggle" value="hide" onchange="toggleContext(this)" checked> Hide | |
| </label> | |
| </div> | |
| <div id="contextSection"> | |
| <h3>Context</h3> | |
| <div id="context"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| let currentSessionId = null; | |
| function setLoading(isLoading, action) { | |
| const button = document.getElementById(action === 'upload' ? 'uploadButton' : 'queryButton'); | |
| const spinner = document.getElementById(action === 'upload' ? 'uploadSpinner' : 'querySpinner'); | |
| if (isLoading) { | |
| button.classList.add('loading'); | |
| spinner.style.display = 'inline'; | |
| button.disabled = true; | |
| } else { | |
| button.classList.remove('loading'); | |
| spinner.style.display = 'none'; | |
| button.disabled = false; | |
| } | |
| } | |
| async function uploadFile() { | |
| const fileInput = document.getElementById('fileInput'); | |
| const file = fileInput.files[0]; | |
| if (!file) { | |
| alert('Please select a file first'); | |
| return; | |
| } | |
| setLoading(true, 'upload'); | |
| // Hide all sections during upload and processing | |
| document.getElementById('querySection').style.display = 'none'; | |
| document.getElementById('responseSection').style.display = 'none'; | |
| document.getElementById('contextSection').style.display = 'none'; | |
| document.querySelector('.toggle-radio').style.display = 'none'; | |
| // Clear any previous content | |
| document.getElementById('answer').innerHTML = ''; | |
| document.getElementById('context').innerHTML = ''; | |
| document.getElementById('queryInput').value = ''; | |
| const formData = new FormData(); | |
| formData.append('file', file); | |
| try { | |
| const response = await fetch('/upload', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| currentSessionId = data.session_id; | |
| // Only show query section after successful upload | |
| document.getElementById('querySection').style.display = 'block'; | |
| alert('File uploaded successfully! You can now ask questions.'); | |
| } catch (error) { | |
| console.error('Error:', error); | |
| alert('Error uploading file: ' + error.message); | |
| } finally { | |
| setLoading(false, 'upload'); | |
| } | |
| } | |
| function toggleContext(radio) { | |
| const contextSection = document.getElementById('contextSection'); | |
| contextSection.style.display = radio.value === 'show' ? 'block' : 'none'; | |
| } | |
| async function submitQuery() { | |
| if (!currentSessionId) { | |
| alert('Please upload a document first'); | |
| return; | |
| } | |
| const queryInput = document.getElementById('queryInput'); | |
| const query = queryInput.value.trim(); | |
| if (!query) { | |
| alert('Please enter a query'); | |
| return; | |
| } | |
| setLoading(true, 'query'); | |
| // Show response section but hide context initially | |
| document.getElementById('responseSection').style.display = 'block'; | |
| document.getElementById('contextSection').style.display = 'none'; | |
| document.querySelector('.toggle-radio').style.display = 'none'; | |
| // Reset radio to "Hide" | |
| document.querySelector('input[value="hide"]').checked = true; | |
| try { | |
| const response = await fetch('/query', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ | |
| session_id: currentSessionId, | |
| query: query | |
| }) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| // Display response | |
| document.getElementById('answer').innerHTML = `<p><strong>Answer:</strong> ${data.answer}</p>`; | |
| // Handle context display with error checking | |
| if (data.context && Array.isArray(data.context)) { | |
| const validContexts = data.context.filter(c => c != null && c !== ''); | |
| const contextHtml = validContexts.length > 0 | |
| ? validContexts.join('<br><br>') | |
| : 'No context available'; | |
| document.getElementById('context').innerHTML = `<div class="context">${contextHtml}</div>`; | |
| // Show the radio toggle only after we have a valid response with context | |
| document.querySelector('.toggle-radio').style.display = 'flex'; | |
| } else { | |
| document.getElementById('context').innerHTML = `<div class="context">No context available</div>`; | |
| } | |
| } catch (error) { | |
| console.error('Error:', error); | |
| alert('Error submitting query: ' + error.message); | |
| } finally { | |
| setLoading(false, 'query'); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |