mirror of
				https://github.com/ggml-org/llama.cpp.git
				synced 2025-10-31 08:51:55 +00:00 
			
		
		
		
	server : (webui) fix numeric settings being saved as string (#11739)
* server : (webui) fix numeric settings being saved as string * add some more comments
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							| @@ -23,6 +23,7 @@ export default function MarkdownDisplay({ content }: { content: string }) { | |||||||
|         button: (props) => ( |         button: (props) => ( | ||||||
|           <CopyCodeButton {...props} origContent={preprocessedContent} /> |           <CopyCodeButton {...props} origContent={preprocessedContent} /> | ||||||
|         ), |         ), | ||||||
|  |         // note: do not use "pre", "p" or other basic html elements here, it will cause the node to re-render when the message is being generated (this should be a bug with react-markdown, not sure how to fix it) | ||||||
|       }} |       }} | ||||||
|     > |     > | ||||||
|       {preprocessedContent} |       {preprocessedContent} | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ import { useAppContext } from '../utils/app.context'; | |||||||
| import { CONFIG_DEFAULT, CONFIG_INFO } from '../Config'; | import { CONFIG_DEFAULT, CONFIG_INFO } from '../Config'; | ||||||
| import { isDev } from '../Config'; | import { isDev } from '../Config'; | ||||||
| import StorageUtils from '../utils/storage'; | import StorageUtils from '../utils/storage'; | ||||||
|  | import { isBoolean, isNumeric, isString } from '../utils/misc'; | ||||||
|  |  | ||||||
| type SettKey = keyof typeof CONFIG_DEFAULT; | type SettKey = keyof typeof CONFIG_DEFAULT; | ||||||
|  |  | ||||||
| @@ -52,7 +53,42 @@ export default function SettingDialog({ | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   const handleSave = () => { |   const handleSave = () => { | ||||||
|     saveConfig(localConfig); |     // copy the local config to prevent direct mutation | ||||||
|  |     const newConfig: typeof CONFIG_DEFAULT = JSON.parse( | ||||||
|  |       JSON.stringify(localConfig) | ||||||
|  |     ); | ||||||
|  |     // validate the config | ||||||
|  |     for (const key in newConfig) { | ||||||
|  |       const value = newConfig[key as SettKey]; | ||||||
|  |       const mustBeBoolean = isBoolean(CONFIG_DEFAULT[key as SettKey]); | ||||||
|  |       const mustBeString = isString(CONFIG_DEFAULT[key as SettKey]); | ||||||
|  |       const mustBeNumeric = isNumeric(CONFIG_DEFAULT[key as SettKey]); | ||||||
|  |       if (mustBeString) { | ||||||
|  |         if (!isString(value)) { | ||||||
|  |           alert(`Value for ${key} must be string`); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |       } else if (mustBeNumeric) { | ||||||
|  |         const trimedValue = value.toString().trim(); | ||||||
|  |         const numVal = Number(trimedValue); | ||||||
|  |         if (isNaN(numVal) || !isNumeric(numVal) || trimedValue.length === 0) { | ||||||
|  |           alert(`Value for ${key} must be numeric`); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |         // force conversion to number | ||||||
|  |         // @ts-expect-error this is safe | ||||||
|  |         newConfig[key] = numVal; | ||||||
|  |       } else if (mustBeBoolean) { | ||||||
|  |         if (!isBoolean(value)) { | ||||||
|  |           alert(`Value for ${key} must be boolean`); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         console.error(`Unknown default type for key ${key}`); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     if (isDev) console.log('Saving config', newConfig); | ||||||
|  |     saveConfig(newConfig); | ||||||
|     onClose(); |     onClose(); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| @@ -66,6 +102,11 @@ export default function SettingDialog({ | |||||||
|     onClose(); |     onClose(); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   const onChange = (key: SettKey) => (value: string | boolean) => { | ||||||
|  |     // note: we do not perform validation here, because we may get incomplete value as user is still typing it | ||||||
|  |     setLocalConfig({ ...localConfig, [key]: value }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <dialog className={`modal ${show ? 'modal-open' : ''}`}> |     <dialog className={`modal ${show ? 'modal-open' : ''}`}> | ||||||
|       <div className="modal-box"> |       <div className="modal-box"> | ||||||
| @@ -79,9 +120,7 @@ export default function SettingDialog({ | |||||||
|             configKey="apiKey" |             configKey="apiKey" | ||||||
|             configDefault={CONFIG_DEFAULT} |             configDefault={CONFIG_DEFAULT} | ||||||
|             value={localConfig.apiKey} |             value={localConfig.apiKey} | ||||||
|             onChange={(value) => |             onChange={onChange('apiKey')} | ||||||
|               setLocalConfig({ ...localConfig, apiKey: value }) |  | ||||||
|             } |  | ||||||
|           /> |           /> | ||||||
|  |  | ||||||
|           <label className="form-control mb-2"> |           <label className="form-control mb-2"> | ||||||
| @@ -92,12 +131,7 @@ export default function SettingDialog({ | |||||||
|               className="textarea textarea-bordered h-24" |               className="textarea textarea-bordered h-24" | ||||||
|               placeholder={`Default: ${CONFIG_DEFAULT.systemMessage}`} |               placeholder={`Default: ${CONFIG_DEFAULT.systemMessage}`} | ||||||
|               value={localConfig.systemMessage} |               value={localConfig.systemMessage} | ||||||
|               onChange={(e) => |               onChange={(e) => onChange('systemMessage')(e.target.value)} | ||||||
|                 setLocalConfig({ |  | ||||||
|                   ...localConfig, |  | ||||||
|                   systemMessage: e.target.value, |  | ||||||
|                 }) |  | ||||||
|               } |  | ||||||
|             /> |             /> | ||||||
|           </label> |           </label> | ||||||
|  |  | ||||||
| @@ -107,9 +141,7 @@ export default function SettingDialog({ | |||||||
|               configKey={key} |               configKey={key} | ||||||
|               configDefault={CONFIG_DEFAULT} |               configDefault={CONFIG_DEFAULT} | ||||||
|               value={localConfig[key]} |               value={localConfig[key]} | ||||||
|               onChange={(value) => |               onChange={onChange(key)} | ||||||
|                 setLocalConfig({ ...localConfig, [key]: value }) |  | ||||||
|               } |  | ||||||
|             /> |             /> | ||||||
|           ))} |           ))} | ||||||
|  |  | ||||||
| @@ -123,9 +155,7 @@ export default function SettingDialog({ | |||||||
|                 configKey="samplers" |                 configKey="samplers" | ||||||
|                 configDefault={CONFIG_DEFAULT} |                 configDefault={CONFIG_DEFAULT} | ||||||
|                 value={localConfig.samplers} |                 value={localConfig.samplers} | ||||||
|                 onChange={(value) => |                 onChange={onChange('samplers')} | ||||||
|                   setLocalConfig({ ...localConfig, samplers: value }) |  | ||||||
|                 } |  | ||||||
|               /> |               /> | ||||||
|               {OTHER_SAMPLER_KEYS.map((key) => ( |               {OTHER_SAMPLER_KEYS.map((key) => ( | ||||||
|                 <SettingsModalShortInput |                 <SettingsModalShortInput | ||||||
| @@ -133,9 +163,7 @@ export default function SettingDialog({ | |||||||
|                   configKey={key} |                   configKey={key} | ||||||
|                   configDefault={CONFIG_DEFAULT} |                   configDefault={CONFIG_DEFAULT} | ||||||
|                   value={localConfig[key]} |                   value={localConfig[key]} | ||||||
|                   onChange={(value) => |                   onChange={onChange(key)} | ||||||
|                     setLocalConfig({ ...localConfig, [key]: value }) |  | ||||||
|                   } |  | ||||||
|                 /> |                 /> | ||||||
|               ))} |               ))} | ||||||
|             </div> |             </div> | ||||||
| @@ -152,9 +180,7 @@ export default function SettingDialog({ | |||||||
|                   configKey={key} |                   configKey={key} | ||||||
|                   configDefault={CONFIG_DEFAULT} |                   configDefault={CONFIG_DEFAULT} | ||||||
|                   value={localConfig[key]} |                   value={localConfig[key]} | ||||||
|                   onChange={(value) => |                   onChange={onChange(key)} | ||||||
|                     setLocalConfig({ ...localConfig, [key]: value }) |  | ||||||
|                   } |  | ||||||
|                 /> |                 /> | ||||||
|               ))} |               ))} | ||||||
|             </div> |             </div> | ||||||
| @@ -171,10 +197,7 @@ export default function SettingDialog({ | |||||||
|                   className="checkbox" |                   className="checkbox" | ||||||
|                   checked={localConfig.showThoughtInProgress} |                   checked={localConfig.showThoughtInProgress} | ||||||
|                   onChange={(e) => |                   onChange={(e) => | ||||||
|                     setLocalConfig({ |                     onChange('showThoughtInProgress')(e.target.checked) | ||||||
|                       ...localConfig, |  | ||||||
|                       showThoughtInProgress: e.target.checked, |  | ||||||
|                     }) |  | ||||||
|                   } |                   } | ||||||
|                 /> |                 /> | ||||||
|                 <span className="ml-4"> |                 <span className="ml-4"> | ||||||
| @@ -187,10 +210,7 @@ export default function SettingDialog({ | |||||||
|                   className="checkbox" |                   className="checkbox" | ||||||
|                   checked={localConfig.excludeThoughtOnReq} |                   checked={localConfig.excludeThoughtOnReq} | ||||||
|                   onChange={(e) => |                   onChange={(e) => | ||||||
|                     setLocalConfig({ |                     onChange('excludeThoughtOnReq')(e.target.checked) | ||||||
|                       ...localConfig, |  | ||||||
|                       excludeThoughtOnReq: e.target.checked, |  | ||||||
|                     }) |  | ||||||
|                   } |                   } | ||||||
|                 /> |                 /> | ||||||
|                 <span className="ml-4"> |                 <span className="ml-4"> | ||||||
| @@ -220,10 +240,7 @@ export default function SettingDialog({ | |||||||
|                   className="checkbox" |                   className="checkbox" | ||||||
|                   checked={localConfig.showTokensPerSecond} |                   checked={localConfig.showTokensPerSecond} | ||||||
|                   onChange={(e) => |                   onChange={(e) => | ||||||
|                     setLocalConfig({ |                     onChange('showTokensPerSecond')(e.target.checked) | ||||||
|                       ...localConfig, |  | ||||||
|                       showTokensPerSecond: e.target.checked, |  | ||||||
|                     }) |  | ||||||
|                   } |                   } | ||||||
|                 /> |                 /> | ||||||
|                 <span className="ml-4">Show tokens per second</span> |                 <span className="ml-4">Show tokens per second</span> | ||||||
| @@ -245,9 +262,7 @@ export default function SettingDialog({ | |||||||
|                   className="textarea textarea-bordered h-24" |                   className="textarea textarea-bordered h-24" | ||||||
|                   placeholder='Example: { "mirostat": 1, "min_p": 0.1 }' |                   placeholder='Example: { "mirostat": 1, "min_p": 0.1 }' | ||||||
|                   value={localConfig.custom} |                   value={localConfig.custom} | ||||||
|                   onChange={(e) => |                   onChange={(e) => onChange('custom')(e.target.value)} | ||||||
|                     setLocalConfig({ ...localConfig, custom: e.target.value }) |  | ||||||
|                   } |  | ||||||
|                 /> |                 /> | ||||||
|               </label> |               </label> | ||||||
|             </div> |             </div> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Xuan-Son Nguyen
					Xuan-Son Nguyen