@@ -27,13 +27,17 @@ const DEFAULT_FLAGZ = {
2727 "frequency_penalty" : 0 ,
2828 "presence_penalty" : 0 ,
2929 "temperature" : 0.8 ,
30+ "top_p" : 0.95 ,
3031 "seed" : null
3132} ;
3233
3334const chatMessages = document . getElementById ( "chat-messages" ) ;
3435const chatInput = document . getElementById ( "chat-input" ) ;
3536const sendButton = document . getElementById ( "send-button" ) ;
3637const stopButton = document . getElementById ( "stop-button" ) ;
38+ const settingsButton = document . getElementById ( "settings-button" ) ;
39+ const settingsModal = document . getElementById ( "settings-modal" ) ;
40+ const closeSettings = document . getElementById ( "close-settings" ) ;
3741
3842let abortController = null ;
3943let disableAutoScroll = false ;
@@ -168,6 +172,7 @@ async function sendMessage() {
168172 // update chat history
169173 chatHistory . push ( { role : "user" , content : message } ) ;
170174
175+ const settings = loadSettings ( ) ;
171176 try {
172177 const response = await fetch ( API_ENDPOINT , {
173178 method : "POST" ,
@@ -178,7 +183,10 @@ async function sendMessage() {
178183 body : JSON . stringify ( {
179184 model : "gpt-3.5-turbo" ,
180185 messages : chatHistory ,
181- temperature : 0.0 ,
186+ temperature : settings . temperature ,
187+ top_p : settings . top_p ,
188+ presence_penalty : settings . presence_penalty ,
189+ frequency_penalty : settings . frequency_penalty ,
182190 stream : true
183191 } ) ,
184192 signal : abortController . signal
@@ -361,9 +369,93 @@ function startChat(history) {
361369 scrollToBottom ( ) ;
362370}
363371
372+ function loadSettings ( ) {
373+ const stored = localStorage . getItem ( 'v1.modelSettings' ) ;
374+ if ( stored ) {
375+ return JSON . parse ( stored ) ;
376+ }
377+ return {
378+ temperature : flagz . temperature ,
379+ top_p : flagz . top_p ,
380+ presence_penalty : flagz . presence_penalty ,
381+ frequency_penalty : flagz . frequency_penalty ,
382+ } ;
383+ }
384+
385+ function saveSettings ( settings ) {
386+ localStorage . setItem ( 'v1.modelSettings' , JSON . stringify ( settings ) ) ;
387+ }
388+
389+ function formatDoubleWithPlus ( x ) {
390+ return ( x >= 0 ? "+" : "" ) + x . toFixed ( 2 ) ;
391+ }
392+
393+ function updateSettingsDisplay ( settings ) {
394+ document . getElementById ( "temp-value" ) . textContent = settings . temperature ? settings . temperature . toFixed ( 2 ) : "0.00 (deterministic)" ;
395+ document . getElementById ( "top-p-value" ) . textContent = settings . top_p . toFixed ( 2 ) ;
396+ document . getElementById ( "presence-value" ) . textContent = formatDoubleWithPlus ( settings . presence_penalty ) ;
397+ document . getElementById ( "frequency-value" ) . textContent = formatDoubleWithPlus ( settings . frequency_penalty ) ;
398+ document . getElementById ( "temperature" ) . value = settings . temperature ;
399+ document . getElementById ( "top-p" ) . value = settings . top_p ;
400+ document . getElementById ( "presence-penalty" ) . value = settings . presence_penalty ;
401+ document . getElementById ( "frequency-penalty" ) . value = settings . frequency_penalty ;
402+
403+ // Handle top-p disabling - using a more reliable selector
404+ const topPSettingItem = document . querySelector ( '.setting-item:has(#top-p)' ) ;
405+ if ( settings . temperature === 0 ) {
406+ topPSettingItem . classList . add ( 'disabled' ) ;
407+ } else {
408+ topPSettingItem . classList . remove ( 'disabled' ) ;
409+ }
410+
411+ // Update top-p description with percentage
412+ const topPDescription = topPSettingItem . querySelector ( '.setting-description' ) ;
413+ if ( settings . top_p >= 1 ) {
414+ topPDescription . textContent = "Disabled. All tokens will be considered by the sampler." ;
415+ } else if ( settings . top_p > .5 ) {
416+ const percentage = Math . round ( ( 1 - settings . top_p ) * 100 ) ;
417+ topPDescription . textContent = `The bottom ${ percentage } % tokens will be ignored by the sampler.` ;
418+ } else {
419+ const percentage = Math . round ( settings . top_p * 100 ) ;
420+ topPDescription . textContent = `Only the top ${ percentage } % tokens will be considered by the sampler.` ;
421+ }
422+ }
423+
424+ function setupSettings ( ) {
425+ settingsButton . addEventListener ( "click" , ( ) => {
426+ settingsModal . style . display = "flex" ;
427+ updateSettingsDisplay ( loadSettings ( ) ) ;
428+ } ) ;
429+ closeSettings . addEventListener ( "click" , ( ) => {
430+ settingsModal . style . display = "none" ;
431+ } ) ;
432+ [ "temperature" , "top-p" , "presence-penalty" , "frequency-penalty" ] . forEach ( id => {
433+ const element = document . getElementById ( id ) ;
434+ element . addEventListener ( "input" , ( e ) => {
435+ const settings = loadSettings ( ) ;
436+ const value = parseFloat ( e . target . value ) ;
437+ const key = id . replace ( / - / g, '_' ) ;
438+ settings [ key ] = value ;
439+ saveSettings ( settings ) ;
440+ updateSettingsDisplay ( settings ) ;
441+ } ) ;
442+ } ) ;
443+ settingsModal . addEventListener ( "mousedown" , ( e ) => {
444+ if ( e . target === settingsModal ) {
445+ settingsModal . style . display = "none" ;
446+ }
447+ } ) ;
448+ document . addEventListener ( "keydown" , ( e ) => {
449+ if ( e . key === "Escape" ) {
450+ settingsModal . style . display = "none" ;
451+ }
452+ } ) ;
453+ }
454+
364455async function chatbot ( ) {
365456 flagz = await fetchFlagz ( ) ;
366457 updateModelInfo ( ) ;
458+ setupSettings ( ) ;
367459 startChat ( [ { role : "system" , content : getSystemPrompt ( ) } ] ) ;
368460 sendButton . addEventListener ( "click" , sendMessage ) ;
369461 stopButton . addEventListener ( "click" , stopMessage ) ;
0 commit comments