diff --git a/examples/server/public/index.html b/examples/server/public/index.html index f768d316f..379f2ffd4 100644 --- a/examples/server/public/index.html +++ b/examples/server/public/index.html @@ -185,28 +185,38 @@ - - + - @@ -218,14 +228,17 @@ const BASE_URL = localStorage.getItem('base') // for debugging || (new URL('.', document.baseURI).href).toString(); // for production const CONFIG_DEFAULT = { + // Note: in order not to introduce breaking changes, please keep the same data type (number, string, etc) if you want to change the default value. Do not use null or undefined for default value. apiKey: '', systemMessage: 'You are a helpful assistant.', temperature: 0.8, top_k: 40, top_p: 0.95, + min_p: 0.95, max_tokens: -1, - custom: '', // custom json object + custom: '', // custom json-stringified object }; + const CONFIG_NUMERIC_KEYS = ['temperature', 'top_k', 'top_p', 'min_p', 'max_tokens']; const THEMES = ['light', 'dark', 'cupcake', 'bumblebee', 'emerald', 'corporate', 'synthwave', 'retro', 'cyberpunk', 'valentine', 'halloween', 'garden', 'forest', 'aqua', 'lofi', 'pastel', 'fantasy', 'wireframe', 'black', 'luxury', 'dracula', 'cmyk', 'autumn', 'business', 'acid', 'lemonade', 'night', 'coffee', 'winter', 'dim', 'nord', 'sunset']; // markdown support @@ -296,7 +309,12 @@ // manage config getConfig() { - return JSON.parse(localStorage.getItem('config') || 'null') || {...CONFIG_DEFAULT}; + const savedVal = JSON.parse(localStorage.getItem('config') || '{}'); + // to prevent breaking changes in the future, we always provide default value for missing keys + return { + ...CONFIG_DEFAULT, + ...savedVal, + }; }, setConfig(config) { localStorage.setItem('config', JSON.stringify(config)); @@ -319,7 +337,7 @@ setTimeout(() => msgListElem.scrollTo({ top: msgListElem.scrollHeight }), 1); }; - createApp({ + const mainApp = createApp({ components: { VueMarkdown, }, @@ -381,22 +399,6 @@ this.fetchMessages(); } }, - closeSaveAndConfigDialog() { - try { - if (this.config.custom.length) JSON.parse(this.config.custom); - } catch (error) { - alert('Invalid JSON for custom config. Please either fix it or leave it empty.'); - return; - } - for (const key of ['temperature', 'top_k', 'top_p', 'max_tokens']) { - if (isNaN(this.config[key])) { - alert('Invalid number for ' + key); - return; - } - } - this.showConfigDialog = false; - StorageUtils.setConfig(this.config); - }, async sendMessage() { if (!this.inputMsg) return; const currConvId = this.viewingConvId; @@ -507,6 +509,34 @@ this.generateMessage(currConvId); }, + // settings dialog methods + closeAndSaveConfigDialog() { + try { + if (this.config.custom.length) JSON.parse(this.config.custom); + } catch (error) { + alert('Invalid JSON for custom config. Please either fix it or leave it empty.'); + return; + } + for (const key of CONFIG_NUMERIC_KEYS) { + if (isNaN(this.config[key])) { + alert(`Invalid number for ${key} (expected an integer or a float)`); + return; + } + this.config[key] = parseFloat(this.config[key]); + } + this.showConfigDialog = false; + StorageUtils.setConfig(this.config); + }, + closeAndDiscardConfigDialog() { + this.showConfigDialog = false; + this.config = StorageUtils.getConfig(); + }, + resetConfigDialog() { + if (window.confirm('Are you sure to reset all settings?')) { + this.config = {...CONFIG_DEFAULT}; + } + }, + // sync state functions fetchConversation() { this.conversations = StorageUtils.getAllConversations(); @@ -515,7 +545,18 @@ this.messages = StorageUtils.getOneConversation(this.viewingConvId)?.messages ?? []; }, }, - }).mount('#app'); + }); + mainApp.config.errorHandler = alert; + try { + mainApp.mount('#app'); + } catch (err) { + console.error(err); + document.getElementById('app').innerHTML = `
+ Failed to start app. Please try clearing localStorage and try again.
+
+ +
`; + }