| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>File Chat</title> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.min.js"></script> |
| <script src="https://unpkg.com/tesseract.js@v2.1.0/dist/tesseract.min.js"></script> |
| <script src="https://unpkg.com/mammoth@1.4.21/mammoth.browser.min.js"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"> |
| <style> |
| body { |
| font-family: Arial, sans-serif; |
| margin: 0; |
| padding: 0; |
| background-color: #f5f5f5; |
| } |
| .container { |
| max-width: 800px; |
| margin: 0 auto; |
| padding: 20px; |
| } |
| h1 { |
| text-align: center; |
| color: #333; |
| } |
| .file-upload { |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| margin-bottom: 20px; |
| } |
| .file-upload input[type="file"] { |
| display: none; |
| } |
| .file-upload label { |
| padding: 10px 20px; |
| background-color: #4CAF50; |
| color: white; |
| cursor: pointer; |
| border-radius: 4px; |
| } |
| .file-upload label:hover { |
| background-color: #45a049; |
| } |
| .text-block { |
| margin-bottom: 20px; |
| padding: 10px; |
| background-color: white; |
| border-radius: 4px; |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| } |
| .file-name { |
| font-weight: bold; |
| margin-bottom: 5px; |
| color: #333; |
| } |
| .loading { |
| margin-top: 10px; |
| font-style: italic; |
| color: #888; |
| } |
| .no-valid-text { |
| color: red; |
| font-weight: bold; |
| } |
| .remove-file { |
| margin-left: 10px; |
| color: red; |
| cursor: pointer; |
| } |
| .chat-container { |
| margin-top: 20px; |
| background-color: white; |
| border-radius: 4px; |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| } |
| .chat-header { |
| padding: 10px; |
| background-color: #4CAF50; |
| color: white; |
| border-top-left-radius: 4px; |
| border-top-right-radius: 4px; |
| } |
| .chat-history { |
| height: 300px; |
| overflow-y: scroll; |
| padding: 10px; |
| } |
| .user-message { |
| background-color: #e1f3fb; |
| padding: 10px; |
| margin-bottom: 10px; |
| border-radius: 4px; |
| } |
| .assistant-message { |
| background-color: #f0f0f0; |
| padding: 10px; |
| margin-bottom: 10px; |
| border-radius: 4px; |
| } |
| .chat-input { |
| display: flex; |
| align-items: center; |
| padding: 10px; |
| } |
| .chat-input input[type="text"] { |
| flex: 1; |
| padding: 8px; |
| border: 1px solid #ccc; |
| border-radius: 4px; |
| } |
| .chat-input button { |
| margin-left: 10px; |
| padding: 8px 16px; |
| background-color: #4CAF50; |
| color: white; |
| border: none; |
| border-radius: 4px; |
| cursor: pointer; |
| } |
| .chat-input button:hover { |
| background-color: #45a049; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <h1>OpenCall.ai File Chat</h1> <div class="file-upload"> |
| <input type="file" id="fileUpload" accept=".txt,.doc,.docx,.pdf,.html,.htm,.jpg,.jpeg,.png" multiple> |
| <label for="fileUpload"><i class="fas fa-file-upload"></i> Choose Files</label> |
| </div> |
| <div id="textContent"></div> |
|
|
| <div class="chat-container" style="display: none;"> |
| <div class="chat-header"> |
| <h2>Chat with AI</h2> |
| </div> |
| <div class="chat-history" id="chatHistory"></div> |
| <div class="chat-input"> |
| <input type="text" id="userInput" placeholder="Enter your query"> |
| <button id="sendButton"><i class="fas fa-paper-plane"></i> Send</button> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| const fileUpload = document.getElementById('fileUpload'); |
| const textContent = document.getElementById('textContent'); |
| const chatContainer = document.querySelector('.chat-container'); |
| const chatHistory = document.getElementById('chatHistory'); |
| const userInput = document.getElementById('userInput'); |
| const sendButton = document.getElementById('sendButton'); |
| |
| let extractedContent = ''; |
| let chatMessages = []; |
| |
| fileUpload.addEventListener('change', handleFileUpload); |
| sendButton.addEventListener('click', sendQuery); |
| |
| function handleFileUpload(event) { |
| const files = event.target.files; |
| |
| for (let i = 0; i < files.length; i++) { |
| const file = files[i]; |
| const fileReader = new FileReader(); |
| |
| const textBlock = document.createElement('div'); |
| textBlock.className = 'text-block'; |
| textBlock.innerHTML = ` |
| <div> |
| <span class="file-name">${file.name}</span> |
| <span class="remove-file" data-index="${textContent.children.length}"><i class="fas fa-times"></i></span> |
| </div> |
| <div class="text-content"></div> |
| <div class="loading">Loading...</div> |
| `; |
| textContent.appendChild(textBlock); |
| |
| fileReader.onload = function() { |
| const content = fileReader.result; |
| |
| if (file.type === 'application/pdf') { |
| extractTextFromPDF(content, textBlock); |
| } else if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { |
| extractTextFromDocx(content, textBlock); |
| } else if (file.type.startsWith('image/')) { |
| extractTextFromImage(content, textBlock); |
| } else { |
| const extractedText = extractText(content); |
| displayText(extractedText, textBlock); |
| } |
| }; |
| |
| if (file.type === 'application/pdf') { |
| fileReader.readAsArrayBuffer(file); |
| } else if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { |
| fileReader.readAsArrayBuffer(file); |
| } else if (file.type.startsWith('image/')) { |
| fileReader.readAsDataURL(file); |
| } else { |
| fileReader.readAsText(file); |
| } |
| } |
| |
| chatContainer.style.display = 'block'; |
| } |
| |
| function extractTextFromPDF(content, textBlock) { |
| pdfjsLib.getDocument({ data: content }).promise.then(function(pdf) { |
| const numPages = pdf.numPages; |
| let extractedText = ''; |
| |
| const extractPageText = function(pageNum) { |
| pdf.getPage(pageNum).then(function(page) { |
| page.getTextContent().then(function(textContent) { |
| extractedText += textContent.items.map(item => item.str).join(' '); |
| |
| if (pageNum < numPages) { |
| extractPageText(pageNum + 1); |
| } else { |
| displayText(extractedText, textBlock); |
| } |
| }); |
| }); |
| }; |
| |
| extractPageText(1); |
| }).catch(function(error) { |
| console.error('Error extracting text from PDF:', error); |
| displayText('Error extracting text from PDF. Please try again.', textBlock); |
| }); |
| } |
| |
| function extractTextFromDocx(content, textBlock) { |
| mammoth.extractRawText({ arrayBuffer: content }) |
| .then(function(result) { |
| const extractedText = result.value; |
| displayText(extractedText, textBlock); |
| }) |
| .catch(function(error) { |
| console.error('Error extracting text from DOCX:', error); |
| displayText('Error extracting text from DOCX. Please try again.', textBlock); |
| }); |
| } |
| |
| function extractTextFromImage(content, textBlock) { |
| Tesseract.recognize(content) |
| .then(function(result) { |
| const extractedText = result.data.text; |
| displayText(extractedText, textBlock); |
| }) |
| .catch(function(error) { |
| console.error('Error extracting text from image:', error); |
| displayText('Error extracting text from image. Please try again.', textBlock); |
| }); |
| } |
| |
| function extractText(content) { |
| const lines = content.split('\n'); |
| const extractedLines = lines.filter(line => line.trim() !== ''); |
| return extractedLines.join('\n'); |
| } |
| |
| function displayText(text, textBlock) { |
| const textContent = textBlock.querySelector('.text-content'); |
| const loadingIndicator = textBlock.querySelector('.loading'); |
| textContent.textContent = text; |
| loadingIndicator.style.display = 'none'; |
| |
| const paragraphs = text.split('\n\n'); |
| const validParagraphs = paragraphs.filter(isValidText); |
| |
| if (validParagraphs.length === 0) { |
| textBlock.classList.add('no-valid-text'); |
| textContent.textContent = 'No valid text found in the file.'; |
| } else { |
| extractedContent += `${textBlock.querySelector('.file-name').textContent}\n${validParagraphs.join('\n\n')}\n\n`; |
| } |
| } |
| |
| function isValidText(text) { |
| const letterRegex = /[a-zA-Z]/g; |
| const nonLetterRegex = /[^a-zA-Z]/g; |
| |
| const letterCount = (text.match(letterRegex) || []).length; |
| const nonLetterCount = (text.match(nonLetterRegex) || []).length; |
| |
| return letterCount > nonLetterCount; |
| } |
| |
| function sendQuery() { |
| const query = userInput.value.trim(); |
| if (query === '') return; |
| |
| const userMessage = document.createElement('div'); |
| userMessage.className = 'user-message'; |
| userMessage.textContent = 'User: ' + query; |
| chatHistory.appendChild(userMessage); |
| |
| chatMessages.push({ role: 'user', content: query }); |
| |
| const requestData = { |
| model: "gradientai/Llama-3-8B-Instruct-Gradient-1048k", |
| messages: [ |
| { |
| role: "system", |
| content: extractedContent |
| }, |
| ...chatMessages, |
| { |
| role: "user", |
| content: "'Based on the above context, please answer the following query: " + query |
| } |
| ], |
| max_tokens: 400, |
| top_p: 0.9, |
| temperature: 0.8 |
| }; |
| |
| fetch('https://azure5.ngrok.app/v1/chat/completions', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json' |
| }, |
| body: JSON.stringify(requestData) |
| }) |
| .then(response => response.json()) |
| .then(data => { |
| const assistantMessage = document.createElement('div'); |
| assistantMessage.className = 'assistant-message'; |
| assistantMessage.textContent = 'Assistant: ' + data.choices[0].message.content; |
| chatHistory.appendChild(assistantMessage); |
| chatHistory.scrollTop = chatHistory.scrollHeight; |
| |
| chatMessages.push({ role: 'assistant', content: data.choices[0].message.content }); |
| }) |
| .catch(error => { |
| console.error('Error:', error); |
| const errorMessage = document.createElement('div'); |
| errorMessage.className = 'assistant-message'; |
| errorMessage.textContent = 'Error: Failed to get response from the model.'; |
| chatHistory.appendChild(errorMessage); |
| }); |
| |
| userInput.value = ''; |
| } |
| |
| textContent.addEventListener('click', function(event) { |
| if (event.target.classList.contains('remove-file')) { |
| const index = event.target.dataset.index; |
| textContent.removeChild(textContent.children[index]); |
| } |
| }); |
| </script> |
| </body> |
| </html> |