Voice-Assistant / index.html
Ivan000's picture
Create index.html
7937e65 verified
<html><head><base href="https://voice-gemma-ai.example.com/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Voice Assistant with Advanced Generation Capabilities</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
background-color: #1a1a1a;
color: #ffffff;
}
.assistant-container {
flex: 1;
width: 90%;
max-width: 800px;
margin: 20px auto;
background-color: #2a2a2a;
border-radius: 20px;
box-shadow: 0 0 20px rgba(0,0,0,0.3);
overflow: hidden;
display: flex;
flex-direction: column;
}
.assistant-header {
background-color: #3a3a3a;
color: #4a90e2;
padding: 20px;
text-align: center;
font-size: 28px;
font-weight: bold;
}
.visualization-area {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
background-color: #222222;
position: relative;
overflow: hidden;
height: 300px;
}
.animation-container {
width: 200px;
height: 200px;
position: relative;
}
.circle {
position: absolute;
border-radius: 50%;
transition: all 0.5s ease;
}
.idle .circle {
width: 20px;
height: 20px;
background-color: #4a90e2;
opacity: 0.7;
}
.idle .circle:nth-child(1) { top: 40%; left: 20%; animation: pulse 2s infinite; }
.idle .circle:nth-child(2) { top: 60%; left: 40%; animation: pulse 2s infinite 0.3s; }
.idle .circle:nth-child(3) { top: 40%; left: 60%; animation: pulse 2s infinite 0.6s; }
.idle .circle:nth-child(4) { top: 60%; left: 80%; animation: pulse 2s infinite 0.9s; }
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.listening .circle {
width: 30px;
height: 30px;
background-color: #4a90e2;
}
.listening .circle:nth-child(1) { top: 50%; left: 10%; animation: wave 1s infinite; }
.listening .circle:nth-child(2) { top: 50%; left: 30%; animation: wave 1s infinite 0.2s; }
.listening .circle:nth-child(3) { top: 50%; left: 50%; animation: wave 1s infinite 0.4s; }
.listening .circle:nth-child(4) { top: 50%; left: 70%; animation: wave 1s infinite 0.6s; }
@keyframes wave {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
.generating .circle, .loading .circle {
width: 40px;
height: 40px;
background-color: #4a90e2;
}
.generating .circle:nth-child(1), .loading .circle:nth-child(1) { top: 50%; left: 20%; animation: rotate 2s infinite linear; }
.generating .circle:nth-child(2), .loading .circle:nth-child(2) { top: 30%; left: 50%; animation: rotate 2s infinite linear 0.5s; }
.generating .circle:nth-child(3), .loading .circle:nth-child(3) { top: 70%; left: 50%; animation: rotate 2s infinite linear 1s; }
.generating .circle:nth-child(4), .loading .circle:nth-child(4) { top: 50%; left: 80%; animation: rotate 2s infinite linear 1.5s; }
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.speaking .circle {
width: 50px;
height: 50px;
background-color: #4a90e2;
}
.speaking .circle:nth-child(1) { top: 40%; left: 20%; animation: bounce 0.5s infinite alternate; }
.speaking .circle:nth-child(2) { top: 60%; left: 40%; animation: bounce 0.5s infinite alternate 0.1s; }
.speaking .circle:nth-child(3) { top: 40%; left: 60%; animation: bounce 0.5s infinite alternate 0.2s; }
.speaking .circle:nth-child(4) { top: 60%; left: 80%; animation: bounce 0.5s infinite alternate 0.3s; }
@keyframes bounce {
0% { transform: translateY(0); }
100% { transform: translateY(-20px); }
}
.controls {
display: flex;
justify-content: center;
padding: 20px;
background-color: #2a2a2a;
}
.control-button {
background-color: #4a90e2;
color: white;
border: none;
padding: 15px 30px;
margin: 0 10px;
border-radius: 50px;
cursor: pointer;
font-size: 18px;
transition: all 0.3s ease;
}
.control-button:hover {
background-color: #3a7bc8;
transform: scale(1.05);
}
.control-button:active {
transform: scale(0.95);
}
.control-button:disabled {
background-color: #999;
cursor: not-allowed;
}
.settings-button {
position: absolute;
top: 20px;
right: 20px;
background-color: transparent;
color: #4a90e2;
border: none;
font-size: 24px;
cursor: pointer;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.6);
}
.modal-content {
background-color: #2a2a2a;
margin: 15% auto;
padding: 20px;
border: 1px solid #3a3a3a;
width: 80%;
max-width: 500px;
border-radius: 10px;
color: #ffffff;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #4a90e2;
text-decoration: none;
cursor: pointer;
}
#api-key, #language-select, #model-select, #tts-select, #system-prompt {
width: 100%;
padding: 10px;
margin: 10px 0;
border-radius: 5px;
border: 1px solid #3a3a3a;
background-color: #222222;
color: #ffffff;
}
#api-key {
-webkit-text-security: disc;
text-security: disc;
}
#save-settings, #reset-default {
background-color: #4a90e2;
color: white;
border: none;
padding: 10px 20px;
margin: 10px 5px 0 0;
border-radius: 5px;
cursor: pointer;
}
.chat-history {
background-color: #2a2a2a;
padding: 20px;
border-radius: 0 0 20px 20px;
max-height: 400px;
overflow-y: auto;
}
.chat-entry {
margin-bottom: 15px;
padding: 10px;
border-radius: 10px;
background-color: #3a3a3a;
}
.user-message {
color: #4a90e2;
font-weight: bold;
}
.ai-response {
color: #ffffff;
}
.status-message {
color: #ffa500;
font-style: italic;
}
#language-display, #model-display, #tts-display {
text-align: center;
padding: 5px;
font-size: 16px;
color: #4a90e2;
}
.generated-image {
max-width: 100%;
height: auto;
margin-top: 10px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
}
.music-player {
background-color: #3a3a3a;
border-radius: 10px;
padding: 15px;
margin-top: 15px;
}
.music-player audio {
width: 100%;
margin-top: 10px;
}
.music-controls {
display: flex;
justify-content: space-between;
margin-top: 10px;
}
.music-control-button {
background-color: #4a90e2;
color: white;
border: none;
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
}
.timer-container {
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px;
}
.timer {
width: 60px;
height: 60px;
border-radius: 50%;
background: conic-gradient(#4a90e2 0deg, #2a2a2a 0deg);
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: bold;
color: #ffffff;
}
#chat-log-checkbox, #auto-translate-checkbox {
margin-right: 5px;
}
#model-select option[disabled] {
font-weight: bold;
color: #4a90e2;
background-color: #3a3a3a;
}
</style>
</head>
<body>
<div class="assistant-container">
<div class="assistant-header">
AI Voice Assistant with Advanced Generation Capabilities
</div>
<div id="language-display">Current Language: Not set</div>
<div id="model-display">Current Model: Not set</div>
<div id="tts-display">Current TTS: Not set</div>
<div class="visualization-area">
<div class="animation-container idle">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
</div>
<div class="timer-container">
<div class="timer" id="cooldown-timer">20</div>
</div>
<div class="controls">
<button id="start-button" class="control-button">Start Listening</button>
<button id="stop-button" class="control-button" style="display: none;">Stop Listening</button>
</div>
<div class="chat-history" id="chat-history"></div>
</div>
<button class="settings-button" id="settings-button">⚙️</button>
<div id="settings-modal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Settings</h2>
<label for="api-key">API Key:</label>
<input type="password" id="api-key" placeholder="Enter your Hugging Face API key">
<label for="language-select">Language:</label>
<select id="language-select">
<option value="en-US">English 🇺🇸</option>
<option value="ru-RU">Russian 🇷🇺</option>
</select>
<label for="model-select">Model:</label>
<select id="model-select">
<option disabled>Text Generation Models</option>
<option value="google/gemma-2b-it">Gemma 2B IT 🤖</option>
<option value="mistralai/Mixtral-8x7B-Instruct-v0.1">Mixtral 8x7B 🌪️</option>
<option value="HuggingFaceTB/SmolLM-1.7B-Instruct">SmolLM 1.7B 🐣</option>
<option value="mistralai/Mistral-Nemo-Instruct-2407">Mistral Nemo 🗣️</option>
<option value="01-ai/Yi-1.5-34B-Chat">Yi 1.5 34B 🧠</option>
<option value="NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO">Nous Hermes 2 Mixtral 🦉</option>
<option value="stabilityai/stablelm-2-zephyr-1_6b">StableLM Zephyr 1.6B 🌟</option>
<option value="microsoft/Phi-3-mini-4k-instruct">Phi-3 Mini 4K 🧠</option>
<option value="microsoft/DialoGPT-medium">DialoGPT Medium 💬</option>
<option value="google/gemma-1.1-7b-it">Gemma 1.1 7B IT 🧠</option>
<option value="google/gemma-2-27b-it">Gemma 2 27B IT 🧠</option>
<option value="meta-llama/Meta-Llama-3-8B-Instruct">Meta-Llama 3 8B Instruct 🦙</option>
<option value="codellama/CodeLlama-34b-Instruct-hf">CodeLlama 34B Instruct 💻</option>
<option disabled>Image Generation Models</option>
<option value="CompVis/stable-diffusion-v1-4">Stable Diffusion 🎨</option>
<option value="dreamlike-art/dreamlike-photoreal-2.0">Dreamlike Photoreal 📷</option>
<option value="openskyml/soviet-diffusion-xl">Soviet Diffusion XL 🎨</option>
<option value="black-forest-labs/FLUX.1-dev">FLUX.1 Dev 🖼️</option>
<option value="dataautogpt3/OpenDalleV1.1">OpenDalle V1.1 🎭</option>
<option value="black-forest-labs/FLUX.1-schnell">FLUX.1 Schnell 🌠</option>
<option disabled>Music Generation Models</option>
<option value="facebook/musicgen-small">MusicGen 🎵</option>
</select>
<label for="tts-select">Text-to-Speech:</label>
<select id="tts-select">
<option value="standard">Standard 🔊</option>
<option value="espnet/kan-bayashi_ljspeech_vits">kan-bayashi 🎙️</option>
<option value="facebook/mms-tts-eng">mms-tts-eng 🗣️</option>
<option value="wasmdashai/vits-eng-us-ljs">VITS ENG US LJS 🎤</option>
</select>
<label for="system-prompt">System Prompt (optional):</label>
<textarea id="system-prompt" placeholder="Enter optional system prompt"></textarea>
<div>
<label for="auto-translate-checkbox">
<input type="checkbox" id="auto-translate-checkbox"> Enable Auto-Translation (for image and music generation)
</label>
</div>
<div>
<label for="chat-log-checkbox">
<input type="checkbox" id="chat-log-checkbox"> Enable Chat Logging
</label>
</div>
<button id="save-settings">Save</button>
<button id="reset-default">Reset to Default</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
const startButton = document.getElementById('start-button');
const stopButton = document.getElementById('stop-button');
const settingsButton = document.getElementById('settings-button');
const settingsModal = document.getElementById('settings-modal');
const closeButton = document.getElementsByClassName('close')[0];
const apiKeyInput = document.getElementById('api-key');
const languageSelect = document.getElementById('language-select');
const modelSelect = document.getElementById('model-select');
const ttsSelect = document.getElementById('tts-select');
const systemPromptInput = document.getElementById('system-prompt');
const saveSettingsButton = document.getElementById('save-settings');
const resetDefaultButton = document.getElementById('reset-default');
const animationContainer = document.querySelector('.animation-container');
const chatHistory = document.getElementById('chat-history');
const languageDisplay = document.getElementById('language-display');
const modelDisplay = document.getElementById('model-display');
const ttsDisplay = document.getElementById('tts-display');
const cooldownTimer = document.getElementById('cooldown-timer');
const defaultApiKey = '';
const defaultLanguage = 'en-US';
const defaultModel = 'meta-llama/Meta-Llama-3-8B-Instruct';
const defaultTts = 'standard';
let apiKey = localStorage.getItem('huggingface_api_key') || defaultApiKey;
let selectedLanguage = localStorage.getItem('selected_language') || defaultLanguage;
let selectedModel = localStorage.getItem('selected_model') || defaultModel;
let selectedTts = localStorage.getItem('selected_tts') || defaultTts;
let systemPrompt = localStorage.getItem('system_prompt') || '';
let chatLoggingEnabled = localStorage.getItem('chat_logging_enabled') === 'true';
let autoTranslateEnabled = localStorage.getItem('auto_translate_enabled') === 'true';
const translationModel = 'Helsinki-NLP/opus-mt-ru-en';
async function translateText(text) {
try {
const response = await axios.post(`https://api-inference.huggingface.co/models/${translationModel}`, {
inputs: text
}, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
return response.data[0].translation_text;
} catch (error) {
console.error('Translation error:', error);
return text; // Return original text if translation fails
}
}
let recognition;
let isListening = false;
let cooldownActive = false;
let cooldownSeconds = 20;
function setAnimationState(state) {
animationContainer.className = `animation-container ${state}`;
}
function addChatEntry(userMessage, aiResponse, isStatus = false, imageUrl = null, audioUrl = null) {
if (!chatLoggingEnabled) {
chatHistory.innerHTML = ''; // Clear all previous entries
}
const chatEntry = document.createElement('div');
chatEntry.className = 'chat-entry';
let content = `
<div class="user-message">You: ${userMessage}</div>
<div class="${isStatus ? 'status-message' : 'ai-response'}">AI: ${aiResponse}</div>
`;
if (imageUrl) {
content += `<img src="${imageUrl}" alt="Generated Image" class="generated-image">`;
}
if (audioUrl) {
content += `
<div class="music-player">
<audio controls>
<source src="${audioUrl}" type="audio/wav">
Your browser does not support the audio element.
</audio>
<div class="music-controls">
<button class="music-control-button" onclick="document.querySelector('audio').play()">Play</button>
<button class="music-control-button" onclick="document.querySelector('audio').pause()">Pause</button>
<button class="music-control-button" onclick="document.querySelector('audio').currentTime = 0">Restart</button>
</div>
</div>
`;
}
chatEntry.innerHTML = content;
chatHistory.insertBefore(chatEntry, chatHistory.firstChild);
}
function initializeSpeechRecognition() {
if ('webkitSpeechRecognition' in window) {
recognition = new webkitSpeechRecognition();
recognition.continuous = false;
recognition.interimResults = false;
recognition.lang = selectedLanguage;
recognition.onstart = function() {
isListening = true;
startButton.style.display = 'none';
stopButton.style.display = 'inline-block';
setAnimationState('listening');
};
recognition.onend = function() {
isListening = false;
startButton.style.display = 'inline-block';
stopButton.style.display = 'none';
setAnimationState('idle');
startCooldown();
};
recognition.onresult = async function(event) {
const transcript = event.results[0][0].transcript;
console.log('You said: ' + transcript);
setAnimationState('generating');
addChatEntry(transcript, "Processing your request...", true);
let processedText = transcript;
const isImageOrMusicModel = selectedModel.includes('stable-diffusion') ||
selectedModel.includes('dreamlike-photoreal') ||
selectedModel.includes('soviet-diffusion') ||
selectedModel.includes('FLUX') ||
selectedModel.includes('OpenDalle') ||
selectedModel.includes('musicgen');
if (autoTranslateEnabled && selectedLanguage === 'ru-RU' && isImageOrMusicModel) {
processedText = await translateText(transcript);
console.log('Translated text:', processedText);
}
try {
if (isImageOrMusicModel) {
if (selectedModel.includes('musicgen')) {
const audioUrl = await generateMusic(processedText);
addChatEntry(transcript, "Here's the generated music:", false, null, audioUrl);
} else {
const imageUrl = await generateImage(processedText);
addChatEntry(transcript, "Here's the generated image:", false, imageUrl);
}
} else {
const response = await makeApiRequest(processedText);
handleApiResponse(transcript, response);
}
} catch (error) {
console.error('Error:', error);
handleApiError(transcript, error);
}
};
} else {
console.log('Web Speech API is not supported in this browser.');
startButton.disabled = true;
startButton.textContent = 'Speech Recognition Not Supported';
}
}
async function makeApiRequest(transcript) {
let userMessage = transcript;
if (systemPrompt) {
userMessage = `${systemPrompt}\n\n${transcript}`;
}
return axios.post(`https://api-inference.huggingface.co/models/${selectedModel}/v1/chat/completions`, {
model: selectedModel,
messages: [{"role": "user", "content": userMessage}],
max_tokens: 500,
stream: false
}, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
}
async function generateImage(prompt) {
const response = await axios.post(`https://api-inference.huggingface.co/models/${selectedModel}`, {
inputs: prompt
}, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
responseType: 'arraybuffer'
});
const blob = new Blob([response.data], { type: 'image/jpeg' });
return URL.createObjectURL(blob);
}
async function generateMusic(prompt) {
const response = await axios.post('https://api-inference.huggingface.co/models/facebook/musicgen-small', {
inputs: prompt
}, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
responseType: 'arraybuffer'
});
const blob = new Blob([response.data], { type: 'audio/wav' });
return URL.createObjectURL(blob);
}
function handleApiResponse(transcript, response) {
if (response.status === 503 && response.data.error.includes("is currently loading")) {
setAnimationState('loading');
addChatEntry(transcript, "Model is loading. Please wait...", true);
setTimeout(() => checkModelStatus(transcript), 5000);
} else {
let aiResponse;
if (response.data.choices && response.data.choices[0].message) {
aiResponse = response.data.choices[0].message.content;
} else if (response.data.generated_text) {
aiResponse = response.data.generated_text;
} else {
aiResponse = "Sorry, I couldn't generate a response.";
}
console.log('AI response:', aiResponse);
addChatEntry(transcript, aiResponse);
setAnimationState('speaking');
speakResponse(aiResponse);
}
}
function handleApiError(transcript, error) {
let errorMessage = 'An error occurred while processing your request.';
if (error.response) {
errorMessage = `Server Error: ${error.response.status} - ${error.response.data.error || error.response.statusText}`;
} else if (error.request) {
errorMessage = 'No response received from the server. Please check your internet connection.';
} else {
errorMessage = `Error: ${error.message}`;
}
addChatEntry(transcript, errorMessage, true);
setAnimationState('idle');
}
async function checkModelStatus(transcript) {
try {
const response = await makeApiRequest(transcript);
handleApiResponse(transcript, response);
} catch (error) {
if (error.response && error.response.status === 503) {
addChatEntry(transcript, "Model is still loading. Checking again...", true);
setTimeout(() => checkModelStatus(transcript), 5000);
} else {
handleApiError(transcript, error);
}
}
}
async function speakResponse(text) {
if (selectedTts === 'standard') {
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = selectedLanguage;
utterance.onend = function() {
setAnimationState('idle');
};
speechSynthesis.speak(utterance);
} else {
try {
const response = await axios.post(`https://api-inference.huggingface.co/models/${selectedTts}`, {
inputs: text
}, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
responseType: 'arraybuffer'
});
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const audioBuffer = await audioContext.decodeAudioData(response.data);
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioContext.destination);
source.onended = function() {
setAnimationState('idle');
};
source.start();
} catch (error) {
console.error('Error with AI TTS:', error);
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = selectedLanguage;
utterance.onend = function() {
setAnimationState('idle');
};
speechSynthesis.speak(utterance);
}
}
}
function startCooldown() {
cooldownActive = true;
startButton.disabled = true;
cooldownSeconds = 20;
updateCooldownTimer();
const cooldownInterval = setInterval(() => {
cooldownSeconds--;
updateCooldownTimer();
if (cooldownSeconds <= 0) {
clearInterval(cooldownInterval);
cooldownActive = false;
startButton.disabled = false;
cooldownTimer.style.background = 'conic-gradient(#4a90e2 360deg, #2a2a2a 360deg)';
cooldownTimer.textContent = '20';
}
}, 1000);
}
function updateCooldownTimer() {
const progress = (20 - cooldownSeconds) / 20 * 360;
cooldownTimer.style.background = `conic-gradient(#4a90e2 ${progress}deg, #2a2a2a ${progress}deg)`;
cooldownTimer.textContent = cooldownSeconds;
}
startButton.addEventListener('click', function() {
if (!cooldownActive && recognition) {
recognition.start();
}
});
stopButton.addEventListener('click', function() {
if (recognition) {
recognition.stop();
}
});
settingsButton.onclick = function() {
settingsModal.style.display = "block";
apiKeyInput.value = apiKey;
languageSelect.value = selectedLanguage;
setInitialModelValue();
ttsSelect.value = selectedTts;
systemPromptInput.value = systemPrompt;
document.getElementById('auto-translate-checkbox').checked = autoTranslateEnabled;
document.getElementById('chat-log-checkbox').checked = chatLoggingEnabled;
}
closeButton.onclick = function() {
settingsModal.style.display = "none";
}
window.onclick = function(event) {
if (event.target == settingsModal) {
settingsModal.style.display = "none";
}
}
saveSettingsButton.onclick = function() {
apiKey = apiKeyInput.value.trim();
selectedLanguage = languageSelect.value;
selectedModel = modelSelect.value;
selectedTts = ttsSelect.value;
systemPrompt = systemPromptInput.value.trim();
autoTranslateEnabled = document.getElementById('auto-translate-checkbox').checked;
chatLoggingEnabled = document.getElementById('chat-log-checkbox').checked;
localStorage.setItem('huggingface_api_key', apiKey);
localStorage.setItem('selected_language', selectedLanguage);
localStorage.setItem('selected_model', selectedModel);
localStorage.setItem('selected_tts', selectedTts);
localStorage.setItem('system_prompt', systemPrompt);
localStorage.setItem('auto_translate_enabled', autoTranslateEnabled);
localStorage.setItem('chat_logging_enabled', chatLoggingEnabled);
settingsModal.style.display = "none";
updateLanguageDisplay();
updateModelDisplay();
updateTtsDisplay();
initializeSpeechRecognition();
addChatEntry("Update Settings", "Settings updated successfully!");
if (!chatLoggingEnabled) {
clearChatHistoryExceptLast();
}
}
function clearChatHistoryExceptLast() {
const chatEntries = chatHistory.getElementsByClassName('chat-entry');
if (chatEntries.length > 1) {
for (let i = chatEntries.length - 1; i > 0; i--) {
chatHistory.removeChild(chatEntries[i]);
}
}
}
resetDefaultButton.onclick = function() {
apiKey = defaultApiKey;
selectedLanguage = defaultLanguage;
selectedModel = defaultModel;
selectedTts = defaultTts;
systemPrompt = '';
autoTranslateEnabled = false;
chatLoggingEnabled = true;
apiKeyInput.value = apiKey;
languageSelect.value = selectedLanguage;
modelSelect.value = selectedModel;
ttsSelect.value = selectedTts;
systemPromptInput.value = systemPrompt;
document.getElementById('auto-translate-checkbox').checked = autoTranslateEnabled;
document.getElementById('chat-log-checkbox').checked = chatLoggingEnabled;
localStorage.setItem('huggingface_api_key', apiKey);
localStorage.setItem('selected_language', selectedLanguage);
localStorage.setItem('selected_model', selectedModel);
localStorage.setItem('selected_tts', selectedTts);
localStorage.setItem('system_prompt', systemPrompt);
localStorage.setItem('auto_translate_enabled', autoTranslateEnabled);
localStorage.setItem('chat_logging_enabled', chatLoggingEnabled);
updateLanguageDisplay();
updateModelDisplay();
updateTtsDisplay();
initializeSpeechRecognition();
addChatEntry("Reset Settings", "Settings reset to default.");
}
function updateLanguageDisplay() {
const languageName = languageSelect.options[languageSelect.selectedIndex].text;
languageDisplay.textContent = `Current Language: ${languageName}`;
}
function updateModelDisplay() {
const modelName = modelSelect.options[modelSelect.selectedIndex].text;
modelDisplay.textContent = `Current Model: ${modelName}`;
}
function updateTtsDisplay() {
const ttsName = ttsSelect.options[ttsSelect.selectedIndex].text;
ttsDisplay.textContent = `Current TTS: ${ttsName}`;
}
function setInitialModelValue() {
const storedModel = localStorage.getItem('selected_model');
if (storedModel) {
const option = modelSelect.querySelector(`option[value="${storedModel}"]`);
if (option && !option.disabled) {
modelSelect.value = storedModel;
} else {
modelSelect.value = modelSelect.querySelector('option:not([disabled])').value;
}
} else {
modelSelect.value = modelSelect.querySelector('option:not([disabled])').value;
}
}
apiKeyInput.value = apiKey;
languageSelect.value = selectedLanguage;
setInitialModelValue();
ttsSelect.value = selectedTts;
systemPromptInput.value = systemPrompt;
updateLanguageDisplay();
updateModelDisplay();
updateTtsDisplay();
document.getElementById('auto-translate-checkbox').checked = autoTranslateEnabled;
document.getElementById('chat-log-checkbox').checked = chatLoggingEnabled;
setAnimationState('idle');
initializeSpeechRecognition();
</script>
</body></html>