| let token = ""; |
| let recognition; |
| let previousModel = ""; |
|
|
|
|
| |
|
|
| async function register() |
| { |
| const username = document.getElementById("regUser").value; |
| const password = document.getElementById("regPass").value; |
|
|
| const response = await fetch("/register", |
| { |
| method: "POST", |
| headers: |
| { |
| "Content-Type":"application/json" |
| }, |
| body: JSON.stringify( |
| { |
| username:username, |
| password:password |
| }) |
| }); |
|
|
| const data = await response.json(); |
|
|
| if(response.ok) |
| { |
| alert("Successfully Registered"); |
| } |
| else |
| { |
| alert(data.detail || "Registration failed"); |
| } |
| } |
|
|
|
|
| |
|
|
| async function login() |
| { |
|
|
| const username = document.getElementById("loginUser").value; |
| const password = document.getElementById("loginPass").value; |
|
|
| const formData = new URLSearchParams(); |
| formData.append("username",username); |
| formData.append("password",password); |
| formData.append("grant_type", "password"); |
|
|
| const response = await fetch("/login", |
| { |
| method:"POST", |
| headers: |
| { |
| "Content-Type":"application/x-www-form-urlencoded" |
| }, |
| body:formData |
| }); |
|
|
| const data = await response.json(); |
|
|
| if(response.ok) |
| { |
|
|
| token = data.access_token; |
| localStorage.setItem("token", token); |
|
|
| alert("Login Successful"); |
|
|
| document.getElementById("authSection").style.display="none"; |
| document.getElementById("mainApp").style.display="block"; |
|
|
| loadModels(); |
|
|
| } |
| else |
| { |
| alert("Login Failed"); |
| } |
|
|
| } |
|
|
|
|
| |
| async function loadModels() |
| { |
|
|
| const select = document.getElementById("modelSelect"); |
| |
| const modelInfo = document.getElementById("modelInfo"); |
| if (modelInfo) { |
| modelInfo.innerText = |
| "🤖 If you click Refresh Models button, Default LLM model will be selected."; |
| modelInfo.style.color = "blue"; |
| } |
|
|
| const response = await fetch("/v1/models"); |
|
|
| const data = await response.json(); |
|
|
| select.innerHTML=""; |
|
|
| data.data.forEach(model => |
| { |
|
|
| let option = document.createElement("option"); |
|
|
| option.value = model.id; |
|
|
| option.text = model.id; |
|
|
| select.appendChild(option); |
|
|
| }); |
|
|
| |
| if (select.options.length > 0) { |
| select.selectedIndex = 0; |
| previousModel = select.value; |
| } |
|
|
| |
| select.onchange = function () { |
| const modelInfo = document.getElementById("modelInfo"); |
|
|
| if (!modelInfo) return; |
|
|
| const message = |
| "You switched to model " + select.value + |
| ". This model will be used for all new questions."; |
|
|
| modelInfo.innerText = |
| "🤖 You switched to: " + select.value + |
| ". This model will be used for ALL new questions."; |
|
|
| modelInfo.style.color = "green"; |
|
|
| |
| speak(message); |
| }; |
|
|
| } |
|
|
|
|
| |
|
|
| async function uploadFile() |
| { |
|
|
| const file = document.getElementById("fileInput").files[0]; |
|
|
| const formData = new FormData(); |
|
|
| formData.append("file",file); |
|
|
| const response = await fetch("/upload", |
| { |
| method:"POST", |
| headers: |
| { |
| Authorization:"Bearer "+token |
| }, |
| body:formData |
| }); |
|
|
| const data = await response.json(); |
|
|
| alert(data.message); |
| } |
|
|
|
|
|
|
| |
|
|
| async function sendQuestion() |
| { |
|
|
| const inputBox = document.getElementById("questionInput"); |
|
|
| const question = inputBox.value; |
|
|
| if(!question.trim()) return; |
|
|
| addUserMessage(question); |
|
|
| inputBox.value = ""; |
|
|
| const model = document.getElementById("modelSelect").value; |
|
|
| const inline = document.getElementById("refInline").checked; |
| const list = document.getElementById("refList").checked; |
|
|
| let refStyle = "both"; |
| if (inline && !list) refStyle = "inline"; |
| else if (!inline && list) refStyle = "list"; |
| else if (!inline && !list) refStyle = "none"; |
|
|
| const response = await fetch("/v1/chat/completions", |
| { |
| method:"POST", |
| headers: |
| { |
| "Content-Type":"application/json", |
| "Authorization":"Bearer " + token |
| }, |
| body:JSON.stringify( |
| { |
| model:model, |
| reference_style: refStyle, |
| messages:[ |
| {role:"user",content:question} |
| ] |
| }) |
| }); |
|
|
|
|
| const data = await response.json(); |
|
|
| const answer = data.choices[0].message.content; |
| |
| let displayAnswer = answer |
| .replace(/\[\d+\]/g, "") |
| .replace(/Note: Citation marker.*$/s, ""); |
|
|
| addBotMessage(displayAnswer); |
| let cleanAnswer = answer |
| .replace(/<[^>]*>/g, "") |
| .replace(/\([^)]*\.pdf[^)]*\)/gi, "") |
| .replace(/\[\d+\]/g, "") |
| .replace(/Note: Citation marker.*$/s, "") |
| .replace(/\s+/g, " ") |
| .trim(); |
|
|
| cleanAnswer = cleanAnswer.split("References:")[0]; |
|
|
| speak(cleanAnswer); |
| } |
|
|
| document.addEventListener("DOMContentLoaded", function() { |
|
|
| document.getElementById("questionInput").addEventListener("keydown", function(event) { |
| if (event.key === "Enter") { |
| event.preventDefault(); |
| sendQuestion(); |
| } |
| }); |
|
|
| }); |
|
|
|
|
| |
|
|
| function addUserMessage(text) |
| { |
|
|
| const chat = document.getElementById("chatWindow"); |
|
|
| const div = document.createElement("div"); |
|
|
| div.className="userMessage"; |
|
|
| div.innerText=text; |
|
|
| chat.appendChild(div); |
|
|
| } |
|
|
|
|
| function addBotMessage(text) |
| { |
|
|
| const chat = document.getElementById("chatWindow"); |
|
|
| const div = document.createElement("div"); |
|
|
| div.className="botMessage"; |
|
|
| div.innerHTML = text; |
|
|
| chat.appendChild(div); |
|
|
| } |
|
|
|
|
| |
|
|
| function startVoice() |
| { |
|
|
| recognition = new webkitSpeechRecognition(); |
|
|
| recognition.lang="en-US"; |
|
|
| recognition.onresult=function(event) |
| { |
| document.getElementById("questionInput").value = event.results[0][0].transcript; |
| }; |
|
|
| recognition.start(); |
|
|
| } |
|
|
| function stopVoice() |
| { |
|
|
| if(recognition) |
| { |
| recognition.stop(); |
| } |
|
|
| speechSynthesis.cancel(); |
| } |
|
|
|
|
| |
|
|
| function speak(text) |
| { |
|
|
| |
| speechSynthesis.cancel(); |
|
|
| const speech = new SpeechSynthesisUtterance(text); |
|
|
| speech.lang="en-US"; |
|
|
| speechSynthesis.speak(speech); |
|
|
| } |
|
|
| function readChat() |
| { |
|
|
| const messages = document.getElementsByClassName("botMessage"); |
|
|
| if(messages.length === 0) return; |
|
|
| const lastMessage = messages[messages.length - 1]; |
|
|
| const chatText = lastMessage.innerText; |
|
|
| |
| let cleanText = chatText |
| .replace(/\([^)]*\.pdf[^)]*\)/gi, "") |
| .replace(/\[\d+\]/g, ""); |
|
|
| |
| cleanText = cleanText.split("References:")[0]; |
|
|
| speak(cleanText); |
|
|
| } |
|
|
| function saveChatAsPDF() |
| { |
| const chatWindow = document.getElementById("chatWindow"); |
|
|
| const originalContent = chatWindow.innerHTML; |
|
|
| const printWindow = window.open('', '', 'width=800,height=600'); |
|
|
| printWindow.document.write(` |
| <html> |
| <head> |
| <title>Chat Export</title> |
| <style> |
| body { font-family: Arial; padding: 20px; } |
| .userMessage { color: blue; margin: 5px 0; } |
| .botMessage { color: black; margin: 5px 0; } |
| </style> |
| </head> |
| <body> |
| <h2>Chat History</h2> |
| ${originalContent} |
| </body> |
| </html> |
| `); |
|
|
| printWindow.document.close(); |
| printWindow.print(); |
| } |
|
|