From fa1fdc1b37a1863c53d73a834445030fcedd5a89 Mon Sep 17 00:00:00 2001
From: Oikko <100654554+MRIOikko@users.noreply.github.com>
Date: Sun, 27 Oct 2024 16:10:57 -0400
Subject: [PATCH] Audio speech and hearing version
---
LLM.css | 102 ++++++++++++++++++++++++++++---
LLM.html | 4 ++
LLM.js | 182 +++++++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 254 insertions(+), 34 deletions(-)
diff --git a/LLM.css b/LLM.css
index c3c8eab..80b7e62 100644
--- a/LLM.css
+++ b/LLM.css
@@ -1,16 +1,13 @@
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
-
*{
font-family: 'Arial', sans-serif;
}
-
body{
margin: 0;
padding: 0;
background-image: linear-gradient(to right, rgb(51, 84, 177), rgb(17, 204, 101));
/*rgb(230, 20, 136)*/
}
-
.header{
display: flex;
font: sans-serif;
@@ -20,13 +17,11 @@ body{
border-bottom: 3px solid #ebe4e4;
height: 45px;
}
-
.header h1{
color: white;
font-size: 22px;
font-weight: 800;
}
-
.container{
max-width: 920px;
height: 100vh;
@@ -36,15 +31,17 @@ body{
margin: 0 auto;
}
+
+
+
+
.info{
-
color: rgb(255, 255, 255);
display: flex;
align-items: center;
justify-content: center;
flex: 20;
}
-
.info a{
color: #fff;
text-decoration: none;
@@ -52,11 +49,14 @@ body{
font-weight: bold;
transition: all 0.3s ease;
}
-
.info a:hover{
color: #1f263f;
}
+
+
+
+
.input-container{
background-image: linear-gradient( #434764, rgb(57, 59, 95));
border-radius: 15px;
@@ -68,6 +68,10 @@ body{
bottom: 0;
}
+
+
+
+
#user-input{
background-color: #182036;
color: #ffffff;
@@ -85,6 +89,11 @@ body{
font-weight: 400;
}
+
+
+
+
+
#send-button{
display: flex;
align-items: center;
@@ -95,7 +104,7 @@ body{
background-color: #4c77af;
color: #fff;
cursor: pointer;
- margin-left: 15px;
+ margin-left: 5px;
transition: all 0.3s ease;
}
@@ -103,6 +112,66 @@ body{
background-color: #293b6e;
}
+
+
+@keyframes pulse{
+ 0%{
+ transform: scale(1);
+ }
+ 50% {
+ transform: scale(1.1);
+ }
+ 100% {
+ transform: scale(1);
+ }
+
+}
+
+
+.voice-button{
+ color: rgb(255, 255, 255);
+ background-color: #4c77af;
+ cursor: pointer;
+ border-radius: 50%;
+ padding:10px 11px;
+ margin-left: 5px;
+ border: none;
+}
+.voice-button:hover{
+ color: white;
+ background-color:#293b6e ;
+}
+.voice-button.listening{
+ background-color: #46e66e;
+ animation: pulse 1.5s infinite;
+}
+
+
+
+
+
+
+.mute-button{
+ color: white;
+ background-color: #4c77af;
+ cursor: pointer;
+ border-radius: 50%;
+ padding:10px 11px;
+ margin-left: 5px;
+ border: none;
+}
+.mute-button:hover{
+ color: white;
+ background-color: #293b6e;
+}
+.mute-button.muted{
+ background-color: #182036;
+}
+
+
+
+
+
.chat-container{
flex: 1;
}
@@ -151,4 +220,19 @@ body{
#chat-log #bot-icon i{
background-color: #00b7ff;
padding: 10px 8px 11px;
+}
+
+
+
+::-webkit-scrollbar {
+ background: rgb(17, 204, 101);
+ width: 10px;
+}
+::-webkit-scrollbar-thumb{
+ background: #4c77af;
+ border-radius: 10px;
+
+}
+::-webkit-scrollbar-thumb.hover{
+ background: #293b6e;
}
\ No newline at end of file
diff --git a/LLM.html b/LLM.html
index 6df5301..0916435 100644
--- a/LLM.html
+++ b/LLM.html
@@ -31,9 +31,13 @@
Hi Oikko! Send me a message to get started!
+
+
+
+
diff --git a/LLM.js b/LLM.js
index d41f151..bcb818f 100644
--- a/LLM.js
+++ b/LLM.js
@@ -4,6 +4,34 @@ const chatLog = document.getElementById('chat-log'),
buttonIcon = document.getElementById('button-icon'),
info = document.querySelector('.info');
+
+const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
+const recognition = new SpeechRecognition();
+recognition.continuous = false;
+recognition.lang = 'en-US';
+
+
+const synth = window.speechSynthesis;
+let isMuted = false;
+
+
+const voiceButton = document.createElement('button');
+voiceButton.innerHTML = '';
+voiceButton.className = 'voice-button';
+sendButton.parentNode.insertBefore(voiceButton, sendButton);
+
+
+const muteButton = document.createElement('button');
+muteButton.innerHTML = '';
+muteButton.className = 'mute-button';
+sendButton.parentNode.insertBefore(muteButton, sendButton);
+
+
+let isListening = false;
+
+
+voiceButton.addEventListener('click', toggleVoiceInput);
+muteButton.addEventListener('click', toggleMute);
sendButton.addEventListener('click', sendMessage);
userInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
@@ -11,52 +39,157 @@ userInput.addEventListener('keydown', (event) => {
}
});
-function sendMessage() {
+
+function toggleMute() {
+ isMuted = !isMuted;
+ if (isMuted) {
+ muteButton.innerHTML = '';
+ muteButton.setAttribute('title', 'Unmute AI voice');
+ synth.cancel();
+ } else {
+ muteButton.innerHTML = '';
+ muteButton.setAttribute('title', 'Mute AI voice');
+ }
+ muteButton.classList.toggle('muted');
+}
+
+
+function toggleVoiceInput() {
+ if (!isListening) {
+ recognition.start();
+ voiceButton.innerHTML = '';
+ voiceButton.classList.add('listening');
+ isListening = true;
+ } else {
+ recognition.stop();
+ voiceButton.innerHTML = '';
+ voiceButton.classList.remove('listening');
+ isListening = false;
+ }
+}
+
+
+recognition.onresult = (event) => {
+ const transcript = event.results[0][0].transcript;
+ userInput.value = transcript;
+ sendMessage();
+};
+
+
+recognition.onend = () => {
+ voiceButton.innerHTML = '';
+ voiceButton.classList.remove('listening');
+ isListening = false;
+};
+
+
+function splitIntoSentences(text) {
+ return text.match(/[^.!?]+[.!?]+/g) || [text];
+}
+
+
+function speakMessage(message) {
+ if (isMuted) return;
+
+
+ synth.cancel();
+
+
+ const sentences = splitIntoSentences(message);
+ let currentSentence = 0;
+
+
+ function speakNextSentence() {
+ if (currentSentence < sentences.length && !isMuted) {
+ const utterance = new SpeechSynthesisUtterance(sentences[currentSentence]);
+ utterance.lang = 'en-GB';
+ utterance.rate = 1.01;
+ utterance.pitch = 1.4;
+
+
+
+ utterance.onend = () => {
+ currentSentence++;
+ speakNextSentence();
+ };
+
+
+
+ utterance.onerror = (event) => {
+ console.error('Speech error:', event);
+ currentSentence = sentences.length;
+ };
+
+
+ synth.speak(utterance);
+ }
+ }
+
+
+ speakNextSentence();
+}
+
+
+async function sendMessage() {
const message = userInput.value.trim();
if (message === '') {
return;
}
+
+
appendMessage('user', message);
userInput.value = '';
- const options = {
- method: 'POST',
- headers: {
- 'x-rapidapi-key': '96fe58a1edmsh64abdfc6c6d56dap19fd5djsnd234de8c1a26',
- 'x-rapidapi-host': 'chat-gpt26.p.rapidapi.com',
- 'Content-Type': 'application/json',
- },
- body: `{"messages":[{"role":"user","content":"${message}"}]}`
- };
- fetch('https://chat-gpt26.p.rapidapi.com/', options).then((response) => response.json()).then((response) => {
- appendMessage('bot', response.choices[0].message.content);
+ try {
+ const options = {
+ method: 'POST',
+ headers: {
+ 'x-rapidapi-key': '96fe58a1edmsh64abdfc6c6d56dap19fd5djsnd234de8c1a26',
+ 'x-rapidapi-host': 'cheapest-gpt-4-turbo-gpt-4-vision-chatgpt-openai-ai-api.p.rapidapi.com',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ messages: [{ role: 'user', content: message }],
+ model: 'gpt-4o'
+ })
+ };
+
+
+ const response = await fetch('https://cheapest-gpt-4-turbo-gpt-4-vision-chatgpt-openai-ai-api.p.rapidapi.com/v1/chat/completions', options);
+ const data = await response.json();
+
+ const botResponse = data.choices[0].message.content;
+ appendMessage('bot', botResponse);
+
+ speakMessage(botResponse);
+
buttonIcon.classList.add('fa-solid', 'fa-bolt');
buttonIcon.classList.remove('fas', 'fa-spinner', 'fa-pulse');
- }).catch((err) => {
- if (err.name === 'TypeError') {
- appendMessage('bot', 'ERROR : Check Your Skibidi API Key! ');
- buttonIcon.classList.add('fa-solid', 'fa-bolt');
- buttonIcon.classList.remove('fas', 'fa-spinner', 'fa-pulse');
- }
- });
+ } catch (err) {
+ console.error('Error:', err);
+ appendMessage('bot', 'Sorry, there was an error processing your request.');
+ buttonIcon.classList.add('fa-solid', 'fa-bolt');
+ buttonIcon.classList.remove('fas', 'fa-spinner', 'fa-pulse');
+ }
}
+
function appendMessage(sender, message) {
info.style.display = "none";
buttonIcon.classList.remove('fa-solid', 'fa-bolt');
buttonIcon.classList.add('fas', 'fa-spinner', 'fa-pulse');
-
+
const messageElement = document.createElement('div');
const iconElement = document.createElement('div');
const chatElement = document.createElement('div');
const icon = document.createElement('i');
-
+
chatElement.classList.add("chat-box");
iconElement.classList.add("icon");
messageElement.classList.add(sender);
messageElement.innerText = message;
-
+
if (sender === 'user') {
icon.classList.add('fa-solid', 'fa-ghost');
iconElement.setAttribute('id', 'user-icon');
@@ -64,11 +197,10 @@ function appendMessage(sender, message) {
icon.classList.add('fa-solid', 'fa-circle-notch');
iconElement.setAttribute('id', 'bot-icon');
}
-
+
iconElement.appendChild(icon);
chatElement.appendChild(iconElement);
chatElement.appendChild(messageElement);
chatLog.appendChild(chatElement);
- chatLog.scrollTo = chatLog.scrollHeight;
-
+ chatLog.scrollTop = chatLog.scrollHeight;
}
\ No newline at end of file