migrate my eary work

This commit is contained in:
Yazan Agha-Schrader 2024-05-27 08:33:36 +02:00
parent 0a30b6e082
commit 902862a505

View file

@ -352,28 +352,30 @@
} }
return html` return html`
<form onsubmit=${submit}> <form onsubmit=${submit}>
<div> <div class="chat-input-container">
<textarea <textarea
className=${generating.value ? "loading" : null} id="chat-input" placeholder="Say Something ..."
oninput=${(e) => message.value = e.target.value} class="${generating.value ? 'loading' : null}"
onkeypress=${enterSubmits} oninput=${(e) => message.value = e.target.value}
placeholder="Say something..." onkeypress=${enterSubmits}
rows=2 rows="2"
type="text" type="text"
value="${message}" value="${message}"
/> ></textarea>
</div> </div>
<div class="right"> <div class="right">
<button type="submit" disabled=${generating.value}>Send</button> <button class="button-back" onclick=${reset}>Back</button>
<button onclick=${uploadImage}>Upload Image</button> <button onclick=${uploadImage}>Upload Image</button>
<button onclick=${stop} disabled=${!generating.value}>Stop</button> <button onclick=${stop} disabled=${!generating.value}>Stop</button>
<button onclick=${reset}>Reset</button> <button type="submit" disabled=${generating.value}>Submit</button>
</div> </div>
</form> </form>
` `
} }
// completion view still needs some ux improvements
function CompletionControls() { function CompletionControls() {
const submit = (e) => { const submit = (e) => {
stop(e); stop(e);
@ -436,6 +438,93 @@
</div>`; </div>`;
}; };
///////////////////////////////////////////
///////////// UI Improvements /////////////
//
// toggle chat/completion
const handleToggleChange = (e) => {
const isChecked = e.target.checked;
session.value = { ...session.value, type: isChecked ? 'completion' : 'chat' };
// todo require further actions to update the user interface
// for example, calling a function that re-renders the form or updates the state
// that controls the display of the form. Currently after reset chat toggle does not return
}
//
// Insert the chosen prompt format
function updatePromptFormat(e) {
const promptFormat = e.target.value;
if (promptFormats.hasOwnProperty(promptFormat)) {
session.value = {
...session.value,
...promptFormats[promptFormat]
};
} else {
// llama.cpp's default setting
session.value = {
...session.value,
template: "{{prompt}}\n\n{{history}}\n{{char}}:",
historyTemplate: "{{name}}: {{message}}",
char: "Assistant",
user: "User"
};
}
console.log('Updated session value:', session.value); //
}
//
// Update the prompt format from the dropdown
function updatePromptFormatFromDropdown(element) {
const promptFormat = element.getAttribute('data-value');
console.log('Selected prompt format:', promptFormat); // debugging
updatePromptFormat({ target: { value: promptFormat } });
}
//
// adds the event listeners once the element is available
function addEventListenersWhenAvailable() {
var themeSelector = document.getElementById('theme-selector');
if (themeSelector) {
themeSelector.addEventListener('change', function(event) {
// event handler...
});
// placeholder further listeners wip
} else {
// if the element is not available yet, wait for the next frame
requestAnimationFrame(addEventListenersWhenAvailable);
}
}
//
// begin with the check
requestAnimationFrame(addEventListenersWhenAvailable);
//
// handle the dropdown selection
function handleDropdownSelection(e, promptFormat) {
// avoid the default behavior of the link
e.preventDefault();
// create a new event object with the value from the data-value attribute
const customEvent = {
target: {
value: promptFormat
}
};
//
// call the updatePromptFormat function with the new event object
updatePromptFormat(customEvent);
}
//
// Update the system prompt
function updateSystemPrompt(e) {
const SystemPrompt = e.target.value;
if (systemPrompts.hasOwnProperty(SystemPrompt)) {
session.value = {
...session.value,
prompt: systemPrompts[SystemPrompt].systemPrompt
};
}
}
///////////// UI Improvements /////////////
///////////////////////////////////////////
const ConfigForm = (props) => { const ConfigForm = (props) => {
const updateSession = (el) => session.value = { ...session.value, [el.target.name]: el.target.value } const updateSession = (el) => session.value = { ...session.value, [el.target.name]: el.target.value }
const updateParams = (el) => params.value = { ...params.value, [el.target.name]: el.target.value } const updateParams = (el) => params.value = { ...params.value, [el.target.name]: el.target.value }
@ -470,7 +559,7 @@
<div> <div>
<label for="${name}">${label}</label> <label for="${name}">${label}</label>
<input type="range" id="${name}" min="${min}" max="${max}" step="${step}" name="${name}" value="${value}" oninput=${updateParamsFloat} /> <input type="range" id="${name}" min="${min}" max="${max}" step="${step}" name="${name}" value="${value}" oninput=${updateParamsFloat} />
<span>${value}</span> <span id="${name}-value">${value}</span>
</div> </div>
` `
}; };
@ -479,8 +568,8 @@
return html` return html`
<div> <div>
<label for="${name}">${label}</label> <label for="${name}">${label}</label>
<input type="range" id="${name}" min="${min}" max="${max}" name="${name}" value="${value}" oninput=${updateParamsInt} /> <input type="range" id="${name}" min="${min}" max="${max}" step="${step}" name="${name}" value="${value}" oninput=${updateParamsInt} />
<span>${value}</span> <span id="${name}-value">${value}</span>
</div> </div>
` `
}; };
@ -502,12 +591,14 @@
const UserTemplateResetButton = () => { const UserTemplateResetButton = () => {
if (selectedUserTemplate.value.name == 'default') { if (selectedUserTemplate.value.name == 'default') {
return html` return html`
<button disabled>Using default template</button> <button class="reset-button" id="id_reset" onclick="${userTemplateReset}">Reset</button>
` `
} }
return html` return html`
<button onclick=${userTemplateReset}>Reset all to default</button> <div class="button-container">
<button class="reset-button" title="Caution: This resets the entire form." onclick="${userTemplateReset}">Reset</button>
</div>
` `
}; };
@ -519,56 +610,155 @@
const GrammarControl = () => ( const GrammarControl = () => (
html` html`
<div> <div>
<label for="template">Grammar</label> <label for="template"></label>
<textarea id="grammar" name="grammar" placeholder="Use gbnf or JSON Schema+convert" value="${params.value.grammar}" rows=4 oninput=${updateParams}/> <textarea id="grammar" name="grammar" placeholder="Use GBNF or JSON-Scheme + Converter" value="${params.value.grammar}" rows=4 oninput=${updateParams}/>
<input type="text" name="prop-order" placeholder="order: prop1,prop2,prop3" oninput=${updateGrammarJsonSchemaPropOrder} /> <div class="grammar-columns">
<button type="button" onclick=${convertJSONSchemaGrammar}>Convert JSON Schema</button> <div class="json-schema-controls">
<input type="text" name="prop-order" placeholder="Order: prop1,prop2,prop3" oninput=${updateGrammarJsonSchemaPropOrder} />
<button type="button" class="button-grammar" onclick=${convertJSONSchemaGrammar}>Convert JSON-Scheme</button>
</div>
</div>
</div> </div>
` `
); );
const PromptControlFieldSet = () => ( const PromptControlFieldSet = () => (
html` html`
<fieldset> <fieldset>
<div> <div class="input-container">
<label htmlFor="prompt">Prompt</label> <label for="prompt" class="input-label">System</label>
<textarea type="text" name="prompt" value="${session.value.prompt}" oninput=${updateSession}/> <textarea
</div> id="prompt"
</fieldset> class="persistent-input"
name="prompt"
value="${session.value.prompt}"
oninput=${updateSession}
></textarea>
</div>
</fieldset>
` `
); );
// todo update the form: reduce the amount, uset he new templates, integrate and adapt to the templates from https://github.com/ggerganov/llama.cpp/wiki/Templates-supported-by-llama_chat_apply_template
const ChatConfigForm = () => ( const ChatConfigForm = () => (
html` html`
${PromptControlFieldSet()} <fieldset class="dropdowns">
<fieldset class="two">
<div> <div>
<label for="user">User name</label> <select id="promptFormat" name="promptFormat" onchange=${updatePromptFormat}>
<option value="default">Prompt Style</option>
<option value=""></option>
<optgroup label="Common Prompt-Styles">
<option value="alpaca">Alpaca</option>
<option value="chatml">ChatML</option>
<option value="llama2">Llama 2</option>
<option value="vicuna">Vicuna</option>
<option value=""></option>
</optgroup>
<optgroup label="More Prompt-Styles">
<option value="airoboros180">Airoboros L2</option>
<option value="bakllava">BakLLaVA-1</option>
<option value="codeCherryPop">Code Cherry Pop</option>
<option value="deepseekCoder">Deepseek Coder</option>
<option value="dolphinMistral">Dolphin Mistral</option>
<option value="evolvedSeeker">evolvedSeeker 1.3B</option>
<option value="goliath120b">Goliath 120B</option>
<option value="jordan">Jordan</option>
<option value="llava">LLaVA</option>
<option value="leoHessianai">Leo Hessianai</option>
<option value="leoMistral">Leo Mistral</option>
<option value="marx">Marx</option>
<option value="med42">Med42</option>
<option value="metaMath">MetaMath</option>
<option value="mistralInstruct">Mistral Instruct</option>
<option value="mistralOpenOrca">Mistral 7B OpenOrca</option>
<option value="mythomax">MythoMax</option>
<option value="neuralchat">Neural Chat</option>
<option value="nousCapybara">Nous Capybara</option>
<option value="nousHermes">Nous Hermes</option>
<option value="openChat">OpenChat</option>
<option value="openhermes2Mistral">OpenHermes 2.5-Mistral</option>
<option value="orcamini">Orca Mini v3</option>
<option value="sauerkrautLM">SauerkrautLM</option>
<option value="samantha">Samantha</option>
<option value="samanthaMistral">Samantha Mistral</option>
<option value="scarlett">Scarlett</option>
<option value="starlingLM">Starling-7B</option>
<option value="starlingLM">Starling-7B Coding</option>
<option value="sydney">Sydney</option>
<option value="synthia">Synthia</option>
<option value="tess">Tess</option>
<option value="yi34b">Yi-34B</option>
<option value="zephyr">Zephyr</option>
<option value=""></option>
</optgroup>
</select>
<select id="SystemPrompt" name="SystemPrompt" onchange=${updateSystemPrompt}>
<option value="default">System Prompt</option>
<option value="empty">None</option>
<option value="airoboros">Airoboros</option>
<option value="alpaca">Alpaca</option>
<option value="atlas">Atlas</option>
<option value="cot">Chain of Tought</option>
<option value="deduce">Critical Thinking</option>
<option value="deepseekcoder">Deepseek Coder</option>
<option value="jordan">Jordan</option>
<option value="leomistral">Leo Mistral</option>
<option value="med42">Med42</option>
<option value="migeltot">Migel's Tree of Thought</option>
<option value="mistralopenorca">Mistral OpenOrca</option>
<option value="orcamini">Orca Mini</option>
<option value="samantha">Samantha</option>
<option value="sauerkraut">Sauerkraut</option>
<option value="scarlett">Scarlett</option>
<option value="synthia">Synthia</option>
</select>
<!--<select id="systemLanguage" name="systemLanguage">-->
<!--<option value="default">English</option>-->
<!--<option value="DE">German</option>-->
<!--<option value="placeholderLanguage">Placeholder</option>-->
<!--</select>-->
</div>
</fieldset>
${PromptControlFieldSet()}
<fieldset class="names">
<div>
<label for="user" id="id_user-name">User Name</label>
<input type="text" name="user" value="${session.value.user}" oninput=${updateSession} /> <input type="text" name="user" value="${session.value.user}" oninput=${updateSession} />
</div> </div>
<div> <div>
<label for="bot">Bot name</label> <label for="bot" id="id_bot-name">AI Name</label>
<input type="text" name="char" value="${session.value.char}" oninput=${updateSession} /> <input type="text" name="char" value="${session.value.char}" oninput=${updateSession} />
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<div> <details open>
<label for="template">Prompt template</label> <summary><span class="summary-title" id="id_prompt-style">Prompt Style</span></summary>
<textarea id="template" name="template" value="${session.value.template}" rows=4 oninput=${updateSession}/> <div class="two-columns">
</div> <div>
<div class="input-container">
<label for="template" class="input-label-sec" id_prompt-template>Prompt Template</label>
<textarea id="template" class="persistent-input-sec" name="template" value="${session.value.template}" rows=6 oninput=${updateSession}/>
</div>
</div>
<div>
<div class="input-container">
<label for="template" class="input-label-sec" id="id_history-template">Chat History</label>
<textarea id="template" class="persistent-input-sec" name="historyTemplate" value="${session.value.historyTemplate}" rows=1 oninput=${updateSession}/>
</div>
</div>
</div>
</details>
<details>
<summary><span class="summary-title" id="id_grammar-title" id_grammar-title>Grammar</span></summary>
${GrammarControl()}
</details>
<div> </fieldset>
<label for="template">Chat history template</label> `
<textarea id="template" name="historyTemplate" value="${session.value.historyTemplate}" rows=1 oninput=${updateSession}/>
</div>
${GrammarControl()}
</fieldset>
`
); );
// todo add possibility to concatenate special, well known
const CompletionConfigForm = () => ( const CompletionConfigForm = () => (
html` html`
${PromptControlFieldSet()} ${PromptControlFieldSet()}
@ -579,47 +769,49 @@
return html` return html`
<form> <form>
<fieldset class="two"> <fieldset class="two">
<input type="checkbox" id="toggle" class="toggleCheckbox" onchange=${handleToggleChange} />
<label for="toggle" class="toggleContainer">
<div id="id_toggle-label-chat">Chat</div>
<div id="id_toggle-label-complete">Complete</div>
</label>
<${UserTemplateResetButton}/> <${UserTemplateResetButton}/>
<div>
<label class="slim"><input type="radio" name="type" value="chat" checked=${session.value.type === "chat"} oninput=${updateSession} /> Chat</label>
<label class="slim"><input type="radio" name="type" value="completion" checked=${session.value.type === "completion"} oninput=${updateSession} /> Completion</label>
</div>
</fieldset> </fieldset>
${session.value.type === 'chat' ? ChatConfigForm() : CompletionConfigForm()} ${session.value.type === 'chat' ? ChatConfigForm() : CompletionConfigForm()}
<fieldset class="two"> <fieldset class="two">
${IntField({ label: "Predictions", max: 2048, min: -1, name: "n_predict", value: params.value.n_predict })} ${IntField({ label: "Prediction", max: 2048, min: -1, step: 16, name: "n_predict", value: params.value.n_predict, })}
${FloatField({ label: "Temperature", max: 2.0, min: 0.0, name: "temperature", step: 0.01, value: params.value.temperature })}
${FloatField({ label: "Penalize repeat sequence", max: 2.0, min: 0.0, name: "repeat_penalty", step: 0.01, value: params.value.repeat_penalty })}
${IntField({ label: "Consider N tokens for penalize", max: 2048, min: 0, name: "repeat_last_n", value: params.value.repeat_last_n })}
${BoolField({ label: "Penalize repetition of newlines", name: "penalize_nl", value: params.value.penalize_nl })}
${IntField({ label: "Top-K sampling", max: 100, min: -1, name: "top_k", value: params.value.top_k })}
${FloatField({ label: "Top-P sampling", max: 1.0, min: 0.0, name: "top_p", step: 0.01, value: params.value.top_p })}
${FloatField({ label: "Min-P sampling", max: 1.0, min: 0.0, name: "min_p", step: 0.01, value: params.value.min_p })} ${FloatField({ label: "Min-P sampling", max: 1.0, min: 0.0, name: "min_p", step: 0.01, value: params.value.min_p })}
${FloatField({ label: "Repetition Penalty", max: 2.0, min: 0.0, name: "repeat_penalty", step: 0.01, value: params.value.repeat_penalty })}
${FloatField({ label: "Temperature", max: 2.0, min: 0.0, name: "temperature", step: 0.01, value: params.value.temperature })}
</fieldset> </fieldset>
<details> <details>
<summary>More options</summary> <summary><span class="summary-title">Further Options</span></summary>
<fieldset class="two"> <fieldset class="two">
${IntField({ label: "Top-K", max: 100, min: 0, step: 1, name: "top_k", value: params.value.top_k })}
${IntField({ label: "Penalize Last N", max: 2048, min: 0, step: 16, name: "repeat_last_n", value: params.value.repeat_last_n })}
${FloatField({ label: "Top-P", max: 1.0, min: 0.0, name: "top_p", step: 0.01, value: params.value.top_p })}
${FloatField({ label: "Presence Penalty", max: 1.0, min: 0.0, name: "presence_penalty", step: 0.01, value: params.value.presence_penalty })}
${FloatField({ label: "TFS-Z", max: 1.0, min: 0.0, name: "tfs_z", step: 0.01, value: params.value.tfs_z })} ${FloatField({ label: "TFS-Z", max: 1.0, min: 0.0, name: "tfs_z", step: 0.01, value: params.value.tfs_z })}
${FloatField({ label: "Typical P", max: 1.0, min: 0.0, name: "typical_p", step: 0.01, value: params.value.typical_p })} ${FloatField({ label: "Frequency Penalty", max: 1.0, min: 0.0, name: "frequency_penalty", step: 0.01, value: params.value.frequency_penalty })}
${FloatField({ label: "Presence penalty", max: 1.0, min: 0.0, name: "presence_penalty", step: 0.01, value: params.value.presence_penalty })} ${FloatField({ label: "Typical-P", max: 1.0, min: 0.0, name: "typical_p", step: 0.01, value: params.value.typical_p })}
${FloatField({ label: "Frequency penalty", max: 1.0, min: 0.0, name: "frequency_penalty", step: 0.01, value: params.value.frequency_penalty })} ${BoolField({ label: "Penalize repetition of newlines", name: "penalize_nl", value: params.value.penalize_nl })}
</fieldset> </fieldset>
<hr />
<hr style="height: 1px; background-color: #ececf1; border: none;" />
<fieldset class="three"> <fieldset class="three">
<div> <div>
<label><input type="radio" name="mirostat" value="0" checked=${params.value.mirostat == 0} oninput=${updateParamsInt} /> no Mirostat</label> <label><input type="radio" name="mirostat" value="0" checked=${params.value.mirostat == 0} oninput=${updateParamsInt} /> Mirostat off</label>
<label><input type="radio" name="mirostat" value="1" checked=${params.value.mirostat == 1} oninput=${updateParamsInt} /> Mirostat v1</label> <label><input type="radio" name="mirostat" value="1" checked=${params.value.mirostat == 1} oninput=${updateParamsInt} /> Mirostat v1</label>
<label><input type="radio" name="mirostat" value="2" checked=${params.value.mirostat == 2} oninput=${updateParamsInt} /> Mirostat v2</label> <label><input type="radio" name="mirostat" value="2" checked=${params.value.mirostat == 2} oninput=${updateParamsInt} /> Mirostat v2</label>
</div> </div>
${FloatField({ label: "Mirostat tau", max: 10.0, min: 0.0, name: "mirostat_tau", step: 0.01, value: params.value.mirostat_tau })} ${FloatField({ label: "Entropy tau", max: 10.0, min: 0.0, name: "mirostat_tau", step: 0.01, value: params.value.mirostat_tau })}
${FloatField({ label: "Mirostat eta", max: 1.0, min: 0.0, name: "mirostat_eta", step: 0.01, value: params.value.mirostat_eta })} ${FloatField({ label: "Learning-rate eta", max: 1.0, min: 0.0, name: "mirostat_eta", step: 0.01, value: params.value.mirostat_eta })}
${IntField({ label: "Show Probabilities", max: 10, min: 0, step: 1, name: "n_probs", value: params.value.n_probs })}
</fieldset> </fieldset>
<fieldset>
${IntField({ label: "Show Probabilities", max: 10, min: 0, name: "n_probs", value: params.value.n_probs })}
</fieldset>
<fieldset>
${IntField({ label: "Min Probabilities from each Sampler", max: 10, min: 0, name: "min_keep", value: params.value.min_keep })} ${IntField({ label: "Min Probabilities from each Sampler", max: 10, min: 0, name: "min_keep", value: params.value.min_keep })}
</fieldset> </fieldset>
<fieldset> <fieldset>
@ -705,13 +897,23 @@
return html`<span dangerouslySetInnerHTML=${{ __html: md }} />`; return html`<span dangerouslySetInnerHTML=${{ __html: md }} />`;
}; };
// const ModelGenerationInfo = (params) => {
// if (!llamaStats.value) {
// return html`<span/>`
// }
// return html`
// <span>
// ${llamaStats.value.tokens_predicted} predicted, ${llamaStats.value.tokens_cached} cached, ${llamaStats.value.timings.predicted_per_token_ms.toFixed()}ms per token, ${llamaStats.value.timings.predicted_per_second.toFixed(2)} tokens per second
// </span>
// `
// }
const ModelGenerationInfo = (params) => { const ModelGenerationInfo = (params) => {
if (!llamaStats.value) { if (!llamaStats.value) {
return html`<span/>` return html`<span/>`
} }
return html` return html`
<span> <span>
${llamaStats.value.tokens_predicted} predicted, ${llamaStats.value.tokens_cached} cached, ${llamaStats.value.timings.predicted_per_token_ms.toFixed()}ms per token, ${llamaStats.value.timings.predicted_per_second.toFixed(2)} tokens per second ${llamaStats.value.tokens_predicted} predicted, ${llamaStats.value.predicted_per_second.toFixed(2)} tokens per second
</span> </span>
` `
} }
@ -748,7 +950,7 @@
}, []); }, []);
return html` return html`
<span style=${props.style} ref=${buttonRef} onClick=${togglePopover}>${props.children}</span> <span style=${props.style} ref=${buttonRef} onClick=${togglePopover} contenteditable="true">${props.children}</span>
${isOpen.value && html` ${isOpen.value && html`
<${Portal} into="#portal"> <${Portal} into="#portal">
<div <div
@ -836,7 +1038,18 @@
return html` return html`
<div class="mode-${session.value.type}"> <div class="mode-${session.value.type}">
<header> <header>
<h1>llama.cpp</h1> <h2>llama.cpp</h2>
<div class="dropdown">
<button class="dropbtn"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" stroke-width="2"/></svg></button>
<div class="dropdown-content" id="theme-selector">
<a href="#" data-theme="default">Ketivah</a>
<a href="#" data-theme="mangotango">Mango Tango</a>
<a href="#" data-theme="playground">Playground</a>
<a href="#" data-theme="polarnight">Polar Night</a>
<a href="#" data-theme="snowstorm">Snow Storm</a>
<a href="#" data-theme="beeninorder">Been In Order</a>
</div>
</div>
</header> </header>
<main id="content"> <main id="content">
@ -846,15 +1059,90 @@
<section id="write"> <section id="write">
<${session.value.type === 'chat' ? MessageInput : CompletionControls} /> <${session.value.type === 'chat' ? MessageInput : CompletionControls} />
</section> </section>
<footer> <footer>
<p><${ModelGenerationInfo} /></p> <p><${ModelGenerationInfo} /></p>
<p>Powered by <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a> and <a href="https://ggml.ai">ggml.ai</a>.</p> <p>Powered By <a href="https://github.com/ggerganov/llama.cpp#readme" target="_blank">llama.cpp</a> and <a href="https://ggml.ai/" target="_blank">ggml.ai</a></p>
</footer> </footer>
</div> </div>
`; `;
} }
///////////// UI Improvements /////////////
//
document.addEventListener('DOMContentLoaded', function() {
var themeSelector = document.getElementById('theme-selector');
var themeLinks = themeSelector.querySelectorAll('a[data-theme]');
//
themeLinks.forEach(function(link) {
link.addEventListener('click', function(event) {
event.preventDefault(); // avoid default behaviour
var selectedTheme = event.target.getAttribute('data-theme');
changeTheme(selectedTheme);
});
});
//
function changeTheme(theme) {
document.body.classList.remove('theme-default', 'theme-mangotango', 'theme-playground', 'theme-polarnight', 'theme-snowstorm', 'theme-beeninorder');
if (theme !== 'default') {
document.body.classList.add('theme-' + theme);
}
localStorage.setItem('selected-theme', theme);
}
//
// set the selected theme when loading the page
var savedTheme = localStorage.getItem('selected-theme');
if (savedTheme && savedTheme !== 'default') {
document.body.classList.add('theme-' + savedTheme);
// update the dropdown if it still exists
var dropdown = document.getElementById('theme-selector-dropdown');
if (dropdown) {
dropdown.value = savedTheme;
}
}
});
//
// snapping of the slider to indicate 'disabled'
document.addEventListener('DOMContentLoaded', (event) => {
// define an object that contains snap values and ranges for each slider
const snapSettings = {
temperature: { snapValue: 1.0, snapRangeMultiplier: 6 },
min_p: { snapValue: 0.05, snapRangeMultiplier: 2 },
top_p: { snapValue: 1.0, snapRangeMultiplier: 4 },
tfs_z: { snapValue: 1.0, snapRangeMultiplier: 4 },
typical_p: { snapValue: 1.0, snapRangeMultiplier: 4 },
repeat_penalty: { snapValue: 1.0, snapRangeMultiplier: 4 },
presence_penalty: { snapValue: 0.0, snapRangeMultiplier: 4 },
frequency_penalty: { snapValue: 0.0, snapRangeMultiplier: 4 },
};
// add an event listener for each slider
Object.keys(snapSettings).forEach(sliderName => {
const slider = document.querySelector(`input[name="${sliderName}"]`);
const settings = snapSettings[sliderName];
slider.addEventListener('input', (e) => {
let value = parseFloat(e.target.value);
const step = parseFloat(e.target.step);
const snapRange = step * settings.snapRangeMultiplier;
const valueDisplay = document.getElementById(`${e.target.name}-value`);
if (value >= settings.snapValue - snapRange && value <= settings.snapValue + snapRange) {
value = settings.snapValue; // set value to the snap value
e.target.value = value; // update the slider value
}
// update the displayed value
if (valueDisplay) {
valueDisplay.textContent = value.toFixed(2); // display value with two decimal places
}
});
});
});
//
///////////// UI Improvements /////////////
render(h(App), document.querySelector('#container')); render(h(App), document.querySelector('#container'));
</script> </script>
</head> </head>