mirror of
https://github.com/mudler/LocalAI.git
synced 2025-05-31 16:05:00 +00:00
feat(ui): remove api key handling and small ui adjustments (#4948)
* chore(ui): drop set api key button Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * chore(ui): shore in-progress installs in model view Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(ui): improve text to image view Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
parent
06eb7e9fa7
commit
de81b42b49
9 changed files with 25 additions and 282 deletions
|
@ -42,12 +42,6 @@ function toggleLoader(show) {
|
|||
}
|
||||
}
|
||||
|
||||
function submitKey(event) {
|
||||
event.preventDefault();
|
||||
localStorage.setItem("key", document.getElementById("apiKey").value);
|
||||
document.getElementById("apiKey").blur();
|
||||
}
|
||||
|
||||
function submitSystemPrompt(event) {
|
||||
event.preventDefault();
|
||||
localStorage.setItem("system_prompt", document.getElementById("systemPrompt").value);
|
||||
|
@ -62,10 +56,9 @@ function submitPrompt(event) {
|
|||
const input = document.getElementById("input").value;
|
||||
Alpine.store("chat").add("user", input, image);
|
||||
document.getElementById("input").value = "";
|
||||
const key = localStorage.getItem("key");
|
||||
const systemPrompt = localStorage.getItem("system_prompt");
|
||||
Alpine.nextTick(() => { document.getElementById('messages').scrollIntoView(false); });
|
||||
promptGPT(systemPrompt, key, input);
|
||||
promptGPT(systemPrompt, input);
|
||||
}
|
||||
|
||||
function readInputImage() {
|
||||
|
@ -82,7 +75,7 @@ function readInputImage() {
|
|||
}
|
||||
|
||||
|
||||
async function promptGPT(systemPrompt, key, input) {
|
||||
async function promptGPT(systemPrompt, input) {
|
||||
const model = document.getElementById("chat-model").value;
|
||||
// Set class "loader" to the element with "loader" id
|
||||
//document.getElementById("loader").classList.add("loader");
|
||||
|
@ -160,7 +153,6 @@ function readInputImage() {
|
|||
const response = await fetch("v1/chat/completions", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${key}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
@ -266,20 +258,12 @@ function readInputImage() {
|
|||
document.getElementById("input").focus();
|
||||
}
|
||||
|
||||
document.getElementById("key").addEventListener("submit", submitKey);
|
||||
document.getElementById("system_prompt").addEventListener("submit", submitSystemPrompt);
|
||||
|
||||
document.getElementById("prompt").addEventListener("submit", submitPrompt);
|
||||
document.getElementById("input").focus();
|
||||
document.getElementById("input_image").addEventListener("change", readInputImage);
|
||||
|
||||
storeKey = localStorage.getItem("key");
|
||||
if (storeKey) {
|
||||
document.getElementById("apiKey").value = storeKey;
|
||||
} else {
|
||||
document.getElementById("apiKey").value = null;
|
||||
}
|
||||
|
||||
storesystemPrompt = localStorage.getItem("system_prompt");
|
||||
if (storesystemPrompt) {
|
||||
document.getElementById("systemPrompt").value = storesystemPrompt;
|
||||
|
|
|
@ -1,48 +1,11 @@
|
|||
/*
|
||||
|
||||
https://github.com/david-haerer/chatapi
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 David Härer
|
||||
Copyright (c) 2024 Ettore Di Giacinto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
function submitKey(event) {
|
||||
event.preventDefault();
|
||||
localStorage.setItem("key", document.getElementById("apiKey").value);
|
||||
document.getElementById("apiKey").blur();
|
||||
}
|
||||
|
||||
|
||||
function genImage(event) {
|
||||
event.preventDefault();
|
||||
const input = document.getElementById("input").value;
|
||||
const key = localStorage.getItem("key");
|
||||
|
||||
promptDallE(key, input);
|
||||
|
||||
promptDallE(input);
|
||||
}
|
||||
|
||||
async function promptDallE(key, input) {
|
||||
async function promptDallE(input) {
|
||||
document.getElementById("loader").style.display = "block";
|
||||
document.getElementById("input").value = "";
|
||||
document.getElementById("input").disabled = true;
|
||||
|
@ -51,7 +14,6 @@ async function promptDallE(key, input) {
|
|||
const response = await fetch("v1/images/generations", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${key}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
@ -84,13 +46,6 @@ async function promptDallE(key, input) {
|
|||
document.getElementById("input").focus();
|
||||
}
|
||||
|
||||
document.getElementById("key").addEventListener("submit", submitKey);
|
||||
document.getElementById("input").focus();
|
||||
document.getElementById("genimage").addEventListener("submit", genImage);
|
||||
document.getElementById("loader").style.display = "none";
|
||||
|
||||
const storeKey = localStorage.getItem("key");
|
||||
if (storeKey) {
|
||||
document.getElementById("apiKey").value = storeKey;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,6 @@ let isRecording = false;
|
|||
let conversationHistory = [];
|
||||
let resetTimer;
|
||||
|
||||
function getApiKey() {
|
||||
return document.getElementById('apiKey').value;
|
||||
}
|
||||
|
||||
function getModel() {
|
||||
return document.getElementById('modelSelect').value;
|
||||
}
|
||||
|
@ -99,34 +95,13 @@ function stopRecording() {
|
|||
};
|
||||
}
|
||||
|
||||
function submitKey(event) {
|
||||
event.preventDefault();
|
||||
localStorage.setItem("key", document.getElementById("apiKey").value);
|
||||
document.getElementById("apiKey").blur();
|
||||
}
|
||||
|
||||
document.getElementById("key").addEventListener("submit", submitKey);
|
||||
|
||||
|
||||
storeKey = localStorage.getItem("key");
|
||||
if (storeKey) {
|
||||
document.getElementById("apiKey").value = storeKey;
|
||||
} else {
|
||||
document.getElementById("apiKey").value = null;
|
||||
}
|
||||
|
||||
|
||||
async function sendAudioToWhisper(audioBlob) {
|
||||
const formData = new FormData();
|
||||
formData.append('file', audioBlob);
|
||||
formData.append('model', getWhisperModel());
|
||||
API_KEY = localStorage.getItem("key");
|
||||
|
||||
const response = await fetch('v1/audio/transcriptions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
|
@ -137,14 +112,9 @@ async function sendAudioToWhisper(audioBlob) {
|
|||
|
||||
async function sendTextToChatGPT(text) {
|
||||
conversationHistory.push({ role: "user", content: text });
|
||||
API_KEY = localStorage.getItem("key");
|
||||
|
||||
const response = await fetch('v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: getModel(),
|
||||
messages: conversationHistory
|
||||
|
@ -161,13 +131,10 @@ async function sendTextToChatGPT(text) {
|
|||
}
|
||||
|
||||
async function getTextToSpeechAudio(text) {
|
||||
API_KEY = localStorage.getItem("key");
|
||||
|
||||
const response = await fetch('v1/audio/speech', {
|
||||
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
|
|
@ -1,52 +1,18 @@
|
|||
// Initialize Alpine store for API key management
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.store('chat', {
|
||||
get key() {
|
||||
return localStorage.getItem('key') || '';
|
||||
},
|
||||
set key(value) {
|
||||
localStorage.setItem('key', value);
|
||||
}
|
||||
});
|
||||
Alpine.store('chat', { });
|
||||
});
|
||||
|
||||
function submitKey(event) {
|
||||
event.preventDefault();
|
||||
const keyValue = document.getElementById("apiKey").value;
|
||||
localStorage.setItem("key", keyValue);
|
||||
|
||||
// Show brief visual confirmation
|
||||
const button = event.submitter;
|
||||
const originalIcon = button.innerHTML;
|
||||
button.innerHTML = '<i class="fa-solid fa-check text-green-400"></i>';
|
||||
button.classList.add('bg-green-600');
|
||||
button.classList.remove('bg-blue-600', 'hover:bg-blue-700');
|
||||
|
||||
setTimeout(() => {
|
||||
button.innerHTML = originalIcon;
|
||||
button.classList.remove('bg-green-600');
|
||||
button.classList.add('bg-blue-600', 'hover:bg-blue-700');
|
||||
}, 1000);
|
||||
|
||||
document.getElementById("apiKey").blur();
|
||||
}
|
||||
|
||||
function genAudio(event) {
|
||||
event.preventDefault();
|
||||
const input = document.getElementById("input").value;
|
||||
const key = localStorage.getItem("key");
|
||||
|
||||
if (!input.trim()) {
|
||||
showNotification('error', 'Please enter text to convert to speech');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
showNotification('warning', 'API key is not set. Please set your API key first.');
|
||||
return;
|
||||
}
|
||||
|
||||
tts(key, input);
|
||||
tts(input);
|
||||
}
|
||||
|
||||
function showNotification(type, message) {
|
||||
|
@ -109,7 +75,7 @@ function showNotification(type, message) {
|
|||
}, 5000);
|
||||
}
|
||||
|
||||
async function tts(key, input) {
|
||||
async function tts(input) {
|
||||
// Show loader and prepare UI
|
||||
const loader = document.getElementById("loader");
|
||||
const inputField = document.getElementById("input");
|
||||
|
@ -126,7 +92,6 @@ async function tts(key, input) {
|
|||
const response = await fetch("tts", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${key}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
@ -224,17 +189,10 @@ async function tts(key, input) {
|
|||
|
||||
// Set up event listeners when DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.getElementById("key").addEventListener("submit", submitKey);
|
||||
document.getElementById("input").focus();
|
||||
document.getElementById("tts").addEventListener("submit", genAudio);
|
||||
document.getElementById("loader").style.display = "none";
|
||||
|
||||
// Initialize stored API key if available
|
||||
const storeKey = localStorage.getItem("key");
|
||||
if (storeKey) {
|
||||
document.getElementById("apiKey").value = storeKey;
|
||||
}
|
||||
|
||||
|
||||
// Add basic keyboard shortcuts
|
||||
document.addEventListener('keydown', (e) => {
|
||||
// Submit on Ctrl+Enter
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue