feat: custom advanced params

This commit is contained in:
Timothy Jaeryang Baek 2025-05-29 03:33:11 +04:00
parent bb4115fa0e
commit 9220afe7b3
5 changed files with 103 additions and 56 deletions

View File

@ -658,6 +658,12 @@ async def chat_completion_files_handler(
def apply_params_to_form_data(form_data, model):
params = form_data.pop("params", {})
custom_params = params.pop("custom_params", {})
if custom_params:
# If custom_params are provided, merge them into params
params = deep_update(params, custom_params)
if model.get("ollama"):
form_data["options"] = params

View File

@ -1,5 +1,6 @@
from open_webui.utils.task import prompt_template, prompt_variables_template
from open_webui.utils.misc import (
deep_update,
add_or_update_system_message,
)
@ -59,6 +60,11 @@ def apply_model_params_to_body(
# inplace function: form_data is modified
def apply_model_params_to_body_openai(params: dict, form_data: dict) -> dict:
custom_params = params.pop("custom_params", {})
if custom_params:
# If there are custom parameters, we need to apply them first
params = deep_update(params, custom_params)
mappings = {
"temperature": float,
"top_p": float,
@ -76,6 +82,11 @@ def apply_model_params_to_body_openai(params: dict, form_data: dict) -> dict:
def apply_model_params_to_body_ollama(params: dict, form_data: dict) -> dict:
custom_params = params.pop("custom_params", {})
if custom_params:
# If there are custom parameters, we need to apply them first
params = deep_update(params, custom_params)
# Convert OpenAI parameter names to Ollama parameter names if needed.
name_differences = {
"max_tokens": "num_predict",

View File

@ -86,7 +86,7 @@
<Collapsible title={$i18n.t('Advanced Params')} open={true} buttonClassName="w-full">
<div class="text-sm mt-1.5" slot="content">
<div>
<AdvancedParams admin={$user?.role === 'admin'} bind:params />
<AdvancedParams admin={$user?.role === 'admin'} custom={true} bind:params />
</div>
</div>
</Collapsible>

View File

@ -1,15 +1,17 @@
<script lang="ts">
import Switch from '$lib/components/common/Switch.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import { getContext, createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
import Plus from '$lib/components/icons/Plus.svelte';
import { getContext } from 'svelte';
const i18n = getContext('i18n');
export let admin = false;
export let onChange: (params: any) => void = () => {};
export let params = {
export let admin = false;
export let custom = false;
const defaultParams = {
// Advanced
stream_response: null, // Set stream responses for this model individually
function_calling: null,
@ -18,31 +20,30 @@
temperature: null,
reasoning_effort: null,
logit_bias: null,
frequency_penalty: null,
repeat_last_n: null,
mirostat: null,
mirostat_eta: null,
mirostat_tau: null,
max_tokens: null,
top_k: null,
top_p: null,
min_p: null,
frequency_penalty: null,
presence_penalty: null,
mirostat: null,
mirostat_eta: null,
mirostat_tau: null,
repeat_last_n: null,
tfs_z: null,
num_ctx: null,
num_batch: null,
num_keep: null,
max_tokens: null,
repeat_penalty: null,
use_mmap: null,
use_mlock: null,
num_keep: null,
num_ctx: null,
num_batch: null,
num_thread: null,
num_gpu: null,
template: null
num_gpu: null
};
let customFieldName = '';
let customFieldValue = '';
export let params = defaultParams;
$: if (params) {
dispatch('change', params);
onChange(params);
}
</script>
@ -145,7 +146,7 @@
<div class="flex mt-0.5 space-x-2">
<div class=" flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-hidden"
class="text-sm w-full bg-transparent outline-hidden outline-none"
type="number"
placeholder={$i18n.t('Enter Seed')}
bind:value={params.seed}
@ -190,7 +191,7 @@
<div class="flex mt-0.5 space-x-2">
<div class=" flex-1">
<input
class="w-full rounded-lg py-2 px-1 text-sm dark:text-gray-300 dark:bg-gray-850 outline-hidden"
class="text-sm w-full bg-transparent outline-hidden outline-none"
type="text"
placeholder={$i18n.t('Enter stop sequence')}
bind:value={params.stop}
@ -288,7 +289,7 @@
<div class="flex mt-0.5 space-x-2">
<div class=" flex-1">
<input
class="w-full rounded-lg py-2 px-1 text-sm dark:text-gray-300 dark:bg-gray-850 outline-hidden"
class="text-sm w-full bg-transparent outline-hidden outline-none"
type="text"
placeholder={$i18n.t('Enter reasoning effort')}
bind:value={params.reasoning_effort}
@ -331,7 +332,7 @@
<div class="flex mt-0.5 space-x-2">
<div class=" flex-1">
<input
class="w-full rounded-lg pl-2 py-2 px-1 text-sm dark:text-gray-300 dark:bg-gray-850 outline-hidden"
class="text-sm w-full bg-transparent outline-hidden outline-none"
type="text"
placeholder={$i18n.t(
'Enter comma-separated "token:bias_value" pairs (example: 5432:100, 413:-100)'
@ -1367,37 +1368,71 @@
{/if}
</div>
<!-- <div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Template')}</div>
{#if custom && admin}
<div class="flex flex-col justify-center">
{#each Object.keys(params?.custom_params ?? {}) as key}
<div class=" py-0.5 w-full justify-between mb-1">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">
<input
type="text"
class=" text-xs w-full bg-transparent outline-none"
placeholder={$i18n.t('Custom Parameter Name')}
value={key}
on:change={(e) => {
const newKey = e.target.value.trim();
if (newKey && newKey !== key) {
params.custom_params[newKey] = params.custom_params[key];
delete params.custom_params[key];
params = {
...params,
custom_params: { ...params.custom_params }
};
}
}}
/>
</div>
<button
class="p-1 px-3 text-xs flex rounded-sm transition shrink-0 outline-hidden"
type="button"
on:click={() => {
delete params.custom_params[key];
params = {
...params,
custom_params: { ...params.custom_params }
};
}}
>
{$i18n.t('Remove')}
</button>
</div>
<div class="flex mt-0.5 space-x-2">
<div class=" flex-1">
<input
bind:value={params.custom_params[key]}
type="text"
class="text-sm w-full bg-transparent outline-hidden outline-none"
placeholder={$i18n.t('Custom Parameter Value')}
/>
</div>
</div>
</div>
{/each}
<button
class="p-1 px-3 text-xs flex rounded-sm transition shrink-0 outline-hidden"
class=" flex gap-2 items-center w-full text-center justify-center mb-5"
type="button"
on:click={() => {
params.template = (params?.template ?? null) === null ? '' : null;
params.custom_params = (params?.custom_params ?? {}) || {};
params.custom_params['custom_param_name'] = 'custom_param_value';
}}
>
{#if (params?.template ?? null) === null}
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
{/if}
<div>
<Plus />
</div>
<div>{$i18n.t('Add Custom Parameter')}</div>
</button>
</div>
{#if (params?.template ?? null) !== null}
<div class="flex mt-0.5 space-x-2">
<div class=" flex-1">
<textarea
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-hidden rounded-lg -mb-1"
placeholder={$i18n.t('Write your model template content here')}
rows="4"
bind:value={params.template}
/>
</div>
</div>
{/if}
</div> -->
{/if}
{/if}
</div>

View File

@ -119,6 +119,7 @@
toast.error('Model Name is required.');
}
info.params = { ...info.params, ...params };
info.access_control = accessControl;
info.meta.capabilities = capabilities;
@ -588,13 +589,7 @@
{#if showAdvanced}
<div class="my-2">
<AdvancedParams
admin={true}
bind:params
on:change={(e) => {
info.params = { ...info.params, ...params };
}}
/>
<AdvancedParams admin={true} custom={true} bind:params />
</div>
{/if}
</div>