import { useState } from 'react'; import { useAppContext } from '../utils/app.context'; import { CONFIG_DEFAULT, CONFIG_INFO } from '../Config'; import { isDev } from '../Config'; import StorageUtils from '../utils/storage'; import { isBoolean, isNumeric, isString } from '../utils/misc'; type SettKey = keyof typeof CONFIG_DEFAULT; const COMMON_SAMPLER_KEYS: SettKey[] = [ 'temperature', 'top_k', 'top_p', 'min_p', 'max_tokens', ]; const OTHER_SAMPLER_KEYS: SettKey[] = [ 'dynatemp_range', 'dynatemp_exponent', 'typical_p', 'xtc_probability', 'xtc_threshold', ]; const PENALTY_KEYS: SettKey[] = [ 'repeat_last_n', 'repeat_penalty', 'presence_penalty', 'frequency_penalty', 'dry_multiplier', 'dry_base', 'dry_allowed_length', 'dry_penalty_last_n', ]; export default function SettingDialog({ show, onClose, }: { show: boolean; onClose: () => void; }) { const { config, saveConfig } = useAppContext(); // clone the config object to prevent direct mutation const [localConfig, setLocalConfig] = useState( JSON.parse(JSON.stringify(config)) ); const resetConfig = () => { if (window.confirm('Are you sure to reset all settings?')) { setLocalConfig(CONFIG_DEFAULT); } }; const handleSave = () => { // 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(); }; const debugImportDemoConv = async () => { const res = await fetch('/demo-conversation.json'); const demoConv = await res.json(); StorageUtils.remove(demoConv.id); for (const msg of demoConv.messages) { StorageUtils.appendMsg(demoConv.id, msg); } 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 (

Settings

Settings below are saved in browser's localStorage