|
<!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/[email protected]/dist/tesseract.min.js"></script> |
|
<script src="https://unpkg.com/[email protected]/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> |