Merge 543f1bfc9f into 9e2e2198b0
This commit is contained in:
commit
900a76be93
Binary file not shown.
|
|
@ -5,9 +5,12 @@
|
|||
import Label from '$lib/components/ui/label/label.svelte';
|
||||
import * as Select from '$lib/components/ui/select';
|
||||
import { Textarea } from '$lib/components/ui/textarea';
|
||||
import { SETTING_CONFIG_DEFAULT, SETTING_CONFIG_INFO, SETTINGS_KEYS } from '$lib/constants';
|
||||
import { SETTING_CONFIG_INFO, SETTINGS_KEYS } from '$lib/constants';
|
||||
import { SettingsFieldType } from '$lib/enums/settings';
|
||||
import { settingsStore } from '$lib/stores/settings.svelte';
|
||||
import { serverStore } from '$lib/stores/server.svelte';
|
||||
import { modelsStore, selectedModelName } from '$lib/stores/models.svelte';
|
||||
import { normalizeFloatingPoint } from '$lib/utils/precision';
|
||||
import { ChatSettingsParameterSourceIndicator } from '$lib/components/app';
|
||||
import type { Component } from 'svelte';
|
||||
|
||||
|
|
@ -20,35 +23,36 @@
|
|||
|
||||
let { fields, localConfig, onConfigChange, onThemeChange }: Props = $props();
|
||||
|
||||
// Helper function to get parameter source info for syncable parameters
|
||||
function getParameterSourceInfo(key: string) {
|
||||
if (!settingsStore.canSyncParameter(key)) {
|
||||
return null;
|
||||
// server sampling defaults for placeholders
|
||||
let sp = $derived.by(() => {
|
||||
if (serverStore.isRouterMode) {
|
||||
const m = selectedModelName();
|
||||
if (m) {
|
||||
const p = modelsStore.getModelProps(m);
|
||||
return (p?.default_generation_settings?.params ?? {}) as Record<string, unknown>;
|
||||
}
|
||||
}
|
||||
|
||||
return settingsStore.getParameterInfo(key);
|
||||
}
|
||||
return (serverStore.defaultParams ?? {}) as Record<string, unknown>;
|
||||
});
|
||||
</script>
|
||||
|
||||
{#each fields as field (field.key)}
|
||||
<div class="space-y-2">
|
||||
{#if field.type === SettingsFieldType.INPUT}
|
||||
{@const paramInfo = getParameterSourceInfo(field.key)}
|
||||
{@const currentValue = String(localConfig[field.key] ?? '')}
|
||||
{@const propsDefault = paramInfo?.serverDefault}
|
||||
{@const serverDefault = sp[field.key]}
|
||||
{@const isCustomRealTime = (() => {
|
||||
if (!paramInfo || propsDefault === undefined) return false;
|
||||
if (serverDefault == null) return false;
|
||||
if (currentValue === '') return false;
|
||||
|
||||
// Apply same rounding logic for real-time comparison
|
||||
const inputValue = currentValue;
|
||||
const numericInput = parseFloat(inputValue);
|
||||
const numericInput = parseFloat(currentValue);
|
||||
const normalizedInput = !isNaN(numericInput)
|
||||
? Math.round(numericInput * 1000000) / 1000000
|
||||
: inputValue;
|
||||
: currentValue;
|
||||
const normalizedDefault =
|
||||
typeof propsDefault === 'number'
|
||||
? Math.round(propsDefault * 1000000) / 1000000
|
||||
: propsDefault;
|
||||
typeof serverDefault === 'number'
|
||||
? Math.round(serverDefault * 1000000) / 1000000
|
||||
: serverDefault;
|
||||
|
||||
return normalizedInput !== normalizedDefault;
|
||||
})()}
|
||||
|
|
@ -74,7 +78,9 @@
|
|||
// Update local config immediately for real-time badge feedback
|
||||
onConfigChange(field.key, e.currentTarget.value);
|
||||
}}
|
||||
placeholder={`Default: ${SETTING_CONFIG_DEFAULT[field.key] ?? 'none'}`}
|
||||
placeholder={sp[field.key] != null
|
||||
? `Default: ${normalizeFloatingPoint(sp[field.key])}`
|
||||
: ''}
|
||||
class="w-full {isCustomRealTime ? 'pr-8' : ''}"
|
||||
/>
|
||||
{#if isCustomRealTime}
|
||||
|
|
@ -82,9 +88,7 @@
|
|||
type="button"
|
||||
onclick={() => {
|
||||
settingsStore.resetParameterToServerDefault(field.key);
|
||||
// Trigger UI update by calling onConfigChange with the default value
|
||||
const defaultValue = propsDefault ?? SETTING_CONFIG_DEFAULT[field.key];
|
||||
onConfigChange(field.key, String(defaultValue));
|
||||
onConfigChange(field.key, '');
|
||||
}}
|
||||
class="absolute top-1/2 right-2 inline-flex h-5 w-5 -translate-y-1/2 items-center justify-center rounded transition-colors hover:bg-muted"
|
||||
aria-label="Reset to default"
|
||||
|
|
@ -112,7 +116,7 @@
|
|||
id={field.key}
|
||||
value={String(localConfig[field.key] ?? '')}
|
||||
onchange={(e) => onConfigChange(field.key, e.currentTarget.value)}
|
||||
placeholder={`Default: ${SETTING_CONFIG_DEFAULT[field.key] ?? 'none'}`}
|
||||
placeholder=""
|
||||
class="min-h-[10rem] w-full md:max-w-2xl"
|
||||
/>
|
||||
|
||||
|
|
@ -140,14 +144,12 @@
|
|||
(opt: { value: string; label: string; icon?: Component }) =>
|
||||
opt.value === localConfig[field.key]
|
||||
)}
|
||||
{@const paramInfo = getParameterSourceInfo(field.key)}
|
||||
{@const currentValue = localConfig[field.key]}
|
||||
{@const propsDefault = paramInfo?.serverDefault}
|
||||
{@const serverDefault = sp[field.key]}
|
||||
{@const isCustomRealTime = (() => {
|
||||
if (!paramInfo || propsDefault === undefined) return false;
|
||||
|
||||
// For select fields, do direct comparison (no rounding needed)
|
||||
return currentValue !== propsDefault;
|
||||
if (serverDefault == null) return false;
|
||||
if (currentValue === '' || currentValue === undefined) return false;
|
||||
return currentValue !== serverDefault;
|
||||
})()}
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
|
|
@ -190,9 +192,7 @@
|
|||
type="button"
|
||||
onclick={() => {
|
||||
settingsStore.resetParameterToServerDefault(field.key);
|
||||
// Trigger UI update by calling onConfigChange with the default value
|
||||
const defaultValue = propsDefault ?? SETTING_CONFIG_DEFAULT[field.key];
|
||||
onConfigChange(field.key, String(defaultValue));
|
||||
onConfigChange(field.key, '');
|
||||
}}
|
||||
class="absolute top-1/2 right-8 inline-flex h-5 w-5 -translate-y-1/2 items-center justify-center rounded transition-colors hover:bg-muted"
|
||||
aria-label="Reset to default"
|
||||
|
|
|
|||
|
|
@ -30,27 +30,30 @@ export const SETTING_CONFIG_DEFAULT: Record<string, string | number | boolean> =
|
|||
agenticMaxToolPreviewLines: 25,
|
||||
showToolCallInProgress: false,
|
||||
alwaysShowAgenticTurns: false,
|
||||
// make sure these default values are in sync with `common.h`
|
||||
samplers: 'top_k;typ_p;top_p;min_p;temperature',
|
||||
// sampling params: empty means "use server default"
|
||||
// the server / preset is the source of truth
|
||||
// empty values are shown as placeholders from /props in the UI
|
||||
// and are NOT sent in API requests, letting the server decide
|
||||
samplers: '',
|
||||
backend_sampling: false,
|
||||
temperature: 0.8,
|
||||
dynatemp_range: 0.0,
|
||||
dynatemp_exponent: 1.0,
|
||||
top_k: 40,
|
||||
top_p: 0.95,
|
||||
min_p: 0.05,
|
||||
xtc_probability: 0.0,
|
||||
xtc_threshold: 0.1,
|
||||
typ_p: 1.0,
|
||||
repeat_last_n: 64,
|
||||
repeat_penalty: 1.0,
|
||||
presence_penalty: 0.0,
|
||||
frequency_penalty: 0.0,
|
||||
dry_multiplier: 0.0,
|
||||
dry_base: 1.75,
|
||||
dry_allowed_length: 2,
|
||||
dry_penalty_last_n: -1,
|
||||
max_tokens: -1,
|
||||
temperature: '',
|
||||
dynatemp_range: '',
|
||||
dynatemp_exponent: '',
|
||||
top_k: '',
|
||||
top_p: '',
|
||||
min_p: '',
|
||||
xtc_probability: '',
|
||||
xtc_threshold: '',
|
||||
typ_p: '',
|
||||
repeat_last_n: '',
|
||||
repeat_penalty: '',
|
||||
presence_penalty: '',
|
||||
frequency_penalty: '',
|
||||
dry_multiplier: '',
|
||||
dry_base: '',
|
||||
dry_allowed_length: '',
|
||||
dry_penalty_last_n: '',
|
||||
max_tokens: '',
|
||||
custom: '', // custom json-stringified object
|
||||
// experimental features
|
||||
pyInterpreterEnabled: false,
|
||||
|
|
|
|||
|
|
@ -289,16 +289,10 @@ class SettingsStore {
|
|||
const serverDefaults = this.getServerDefaults();
|
||||
|
||||
if (serverDefaults[key] !== undefined) {
|
||||
const value = normalizeFloatingPoint(serverDefaults[key]);
|
||||
|
||||
this.config[key as keyof SettingsConfigType] =
|
||||
value as SettingsConfigType[keyof SettingsConfigType];
|
||||
} else {
|
||||
if (key in SETTING_CONFIG_DEFAULT) {
|
||||
const defaultValue = getConfigValue(SETTING_CONFIG_DEFAULT, key);
|
||||
|
||||
setConfigValue(this.config, key, defaultValue);
|
||||
}
|
||||
// sampling param known by server: clear it, let server decide
|
||||
setConfigValue(this.config, key, '');
|
||||
} else if (key in SETTING_CONFIG_DEFAULT) {
|
||||
setConfigValue(this.config, key, getConfigValue(SETTING_CONFIG_DEFAULT, key));
|
||||
}
|
||||
|
||||
this.userOverrides.delete(key);
|
||||
|
|
@ -319,12 +313,7 @@ class SettingsStore {
|
|||
*/
|
||||
syncWithServerDefaults(): void {
|
||||
const propsDefaults = this.getServerDefaults();
|
||||
|
||||
if (Object.keys(propsDefaults).length === 0) {
|
||||
console.warn('No server defaults available for initialization');
|
||||
|
||||
return;
|
||||
}
|
||||
if (Object.keys(propsDefaults).length === 0) return;
|
||||
|
||||
for (const [key, propsValue] of Object.entries(propsDefaults)) {
|
||||
const currentValue = getConfigValue(this.config, key);
|
||||
|
|
@ -332,17 +321,14 @@ class SettingsStore {
|
|||
const normalizedCurrent = normalizeFloatingPoint(currentValue);
|
||||
const normalizedDefault = normalizeFloatingPoint(propsValue);
|
||||
|
||||
// if user value matches server, it's not a real override
|
||||
if (normalizedCurrent === normalizedDefault) {
|
||||
this.userOverrides.delete(key);
|
||||
setConfigValue(this.config, key, propsValue);
|
||||
} else if (!this.userOverrides.has(key)) {
|
||||
setConfigValue(this.config, key, propsValue);
|
||||
}
|
||||
}
|
||||
|
||||
this.saveConfig();
|
||||
console.log('Settings initialized with props defaults:', propsDefaults);
|
||||
console.log('Current user overrides after sync:', Array.from(this.userOverrides));
|
||||
console.log('User overrides after sync:', Array.from(this.userOverrides));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -352,19 +338,11 @@ class SettingsStore {
|
|||
*/
|
||||
forceSyncWithServerDefaults(): void {
|
||||
const propsDefaults = this.getServerDefaults();
|
||||
const syncableKeys = ParameterSyncService.getSyncableParameterKeys();
|
||||
|
||||
for (const key of syncableKeys) {
|
||||
for (const key of ParameterSyncService.getSyncableParameterKeys()) {
|
||||
if (propsDefaults[key] !== undefined) {
|
||||
const normalizedValue = normalizeFloatingPoint(propsDefaults[key]);
|
||||
|
||||
setConfigValue(this.config, key, normalizedValue);
|
||||
} else {
|
||||
if (key in SETTING_CONFIG_DEFAULT) {
|
||||
const defaultValue = getConfigValue(SETTING_CONFIG_DEFAULT, key);
|
||||
|
||||
setConfigValue(this.config, key, defaultValue);
|
||||
}
|
||||
setConfigValue(this.config, key, '');
|
||||
} else if (key in SETTING_CONFIG_DEFAULT) {
|
||||
setConfigValue(this.config, key, getConfigValue(SETTING_CONFIG_DEFAULT, key));
|
||||
}
|
||||
|
||||
this.userOverrides.delete(key);
|
||||
|
|
|
|||
Loading…
Reference in New Issue