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): def apply_params_to_form_data(form_data, model):
params = form_data.pop("params", {}) 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"): if model.get("ollama"):
form_data["options"] = params 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.task import prompt_template, prompt_variables_template
from open_webui.utils.misc import ( from open_webui.utils.misc import (
deep_update,
add_or_update_system_message, add_or_update_system_message,
) )
@ -59,6 +60,11 @@ def apply_model_params_to_body(
# inplace function: form_data is modified # inplace function: form_data is modified
def apply_model_params_to_body_openai(params: dict, form_data: dict) -> dict: 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 = { mappings = {
"temperature": float, "temperature": float,
"top_p": 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: 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. # Convert OpenAI parameter names to Ollama parameter names if needed.
name_differences = { name_differences = {
"max_tokens": "num_predict", "max_tokens": "num_predict",

View File

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

View File

@ -1,15 +1,17 @@
<script lang="ts"> <script lang="ts">
import Switch from '$lib/components/common/Switch.svelte'; import Switch from '$lib/components/common/Switch.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte';
import { getContext, createEventDispatcher } from 'svelte'; import Plus from '$lib/components/icons/Plus.svelte';
import { getContext } from 'svelte';
const dispatch = createEventDispatcher();
const i18n = getContext('i18n'); 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 // Advanced
stream_response: null, // Set stream responses for this model individually stream_response: null, // Set stream responses for this model individually
function_calling: null, function_calling: null,
@ -18,31 +20,30 @@
temperature: null, temperature: null,
reasoning_effort: null, reasoning_effort: null,
logit_bias: null, logit_bias: null,
frequency_penalty: null, max_tokens: null,
repeat_last_n: null,
mirostat: null,
mirostat_eta: null,
mirostat_tau: null,
top_k: null, top_k: null,
top_p: null, top_p: null,
min_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, tfs_z: null,
num_ctx: null, repeat_penalty: null,
num_batch: null,
num_keep: null,
max_tokens: null,
use_mmap: null, use_mmap: null,
use_mlock: null, use_mlock: null,
num_keep: null,
num_ctx: null,
num_batch: null,
num_thread: null, num_thread: null,
num_gpu: null, num_gpu: null
template: null
}; };
let customFieldName = ''; export let params = defaultParams;
let customFieldValue = '';
$: if (params) { $: if (params) {
dispatch('change', params); onChange(params);
} }
</script> </script>
@ -145,7 +146,7 @@
<div class="flex mt-0.5 space-x-2"> <div class="flex mt-0.5 space-x-2">
<div class=" flex-1"> <div class=" flex-1">
<input <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" type="number"
placeholder={$i18n.t('Enter Seed')} placeholder={$i18n.t('Enter Seed')}
bind:value={params.seed} bind:value={params.seed}
@ -190,7 +191,7 @@
<div class="flex mt-0.5 space-x-2"> <div class="flex mt-0.5 space-x-2">
<div class=" flex-1"> <div class=" flex-1">
<input <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" type="text"
placeholder={$i18n.t('Enter stop sequence')} placeholder={$i18n.t('Enter stop sequence')}
bind:value={params.stop} bind:value={params.stop}
@ -288,7 +289,7 @@
<div class="flex mt-0.5 space-x-2"> <div class="flex mt-0.5 space-x-2">
<div class=" flex-1"> <div class=" flex-1">
<input <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" type="text"
placeholder={$i18n.t('Enter reasoning effort')} placeholder={$i18n.t('Enter reasoning effort')}
bind:value={params.reasoning_effort} bind:value={params.reasoning_effort}
@ -331,7 +332,7 @@
<div class="flex mt-0.5 space-x-2"> <div class="flex mt-0.5 space-x-2">
<div class=" flex-1"> <div class=" flex-1">
<input <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" type="text"
placeholder={$i18n.t( placeholder={$i18n.t(
'Enter comma-separated "token:bias_value" pairs (example: 5432:100, 413:-100)' 'Enter comma-separated "token:bias_value" pairs (example: 5432:100, 413:-100)'
@ -1367,37 +1368,71 @@
{/if} {/if}
</div> </div>
<!-- <div class=" py-0.5 w-full justify-between"> {#if custom && admin}
<div class="flex w-full justify-between"> <div class="flex flex-col justify-center">
<div class=" self-center text-xs font-medium">{$i18n.t('Template')}</div> {#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 <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" type="button"
on:click={() => { 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} <div>
<span class="ml-2 self-center">{$i18n.t('Default')}</span> <Plus />
{:else} </div>
<span class="ml-2 self-center">{$i18n.t('Custom')}</span> <div>{$i18n.t('Add Custom Parameter')}</div>
{/if}
</button> </button>
</div> </div>
{/if}
{#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> </div>

View File

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