mirror of
https://github.com/open-webui/open-webui.git
synced 2026-11-15 09:31:21 +00:00
refac
This commit is contained in:
parent
2840f0e07b
commit
f0cc1bb86e
4 changed files with 88 additions and 36 deletions
|
|
@ -2081,10 +2081,15 @@ ENABLE_AUTOMATIONS = os.getenv('ENABLE_AUTOMATIONS', 'True').lower() == 'true'
|
|||
|
||||
ENABLE_SUBAGENTS = os.getenv('ENABLE_SUBAGENTS', 'False').lower() == 'true'
|
||||
SUBAGENTS_BACKGROUND_ENABLED = os.getenv('SUBAGENTS_BACKGROUND_ENABLED', 'False').lower() == 'true'
|
||||
SUBAGENTS_MAX_CONCURRENT = int(os.getenv('SUBAGENTS_MAX_CONCURRENT', '20'))
|
||||
SUBAGENTS_MAX_ASYNC = int(os.getenv('SUBAGENTS_MAX_ASYNC', '20'))
|
||||
SUBAGENTS_MAX_ITERATIONS = int(os.getenv('SUBAGENTS_MAX_ITERATIONS', '30'))
|
||||
SUBAGENTS_MAX_OUTPUT = int(os.getenv('SUBAGENTS_MAX_OUTPUT', '30000'))
|
||||
# Leave empty for unlimited.
|
||||
SUBAGENTS_MAX_CONCURRENT = os.getenv('SUBAGENTS_MAX_CONCURRENT', '')
|
||||
SUBAGENTS_MAX_CONCURRENT = int(SUBAGENTS_MAX_CONCURRENT) if SUBAGENTS_MAX_CONCURRENT else None
|
||||
SUBAGENTS_MAX_ASYNC = os.getenv('SUBAGENTS_MAX_ASYNC', '')
|
||||
SUBAGENTS_MAX_ASYNC = int(SUBAGENTS_MAX_ASYNC) if SUBAGENTS_MAX_ASYNC else None
|
||||
SUBAGENTS_MAX_ITERATIONS = os.getenv('SUBAGENTS_MAX_ITERATIONS', '')
|
||||
SUBAGENTS_MAX_ITERATIONS = int(SUBAGENTS_MAX_ITERATIONS) if SUBAGENTS_MAX_ITERATIONS else None
|
||||
SUBAGENTS_MAX_OUTPUT = os.getenv('SUBAGENTS_MAX_OUTPUT', '')
|
||||
SUBAGENTS_MAX_OUTPUT = int(SUBAGENTS_MAX_OUTPUT) if SUBAGENTS_MAX_OUTPUT else None
|
||||
SUBAGENTS_SYSTEM_PROMPT = os.getenv('SUBAGENTS_SYSTEM_PROMPT', '')
|
||||
|
||||
AUTOMATION_MAX_COUNT = os.getenv('AUTOMATION_MAX_COUNT', '')
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ from open_webui.utils.tools import (
|
|||
set_terminal_servers,
|
||||
set_tool_servers,
|
||||
)
|
||||
from pydantic import BaseModel, ConfigDict, StrictBool
|
||||
from pydantic import BaseModel, ConfigDict, Field, StrictBool, field_validator
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
|
@ -799,12 +799,28 @@ async def set_models_config(request: Request, form_data: ModelsConfigForm, user=
|
|||
class SubagentsConfigForm(BaseModel):
|
||||
ENABLE_SUBAGENTS: bool
|
||||
SUBAGENTS_BACKGROUND_ENABLED: bool
|
||||
SUBAGENTS_MAX_CONCURRENT: int
|
||||
SUBAGENTS_MAX_ASYNC: int
|
||||
SUBAGENTS_MAX_ITERATIONS: int
|
||||
SUBAGENTS_MAX_OUTPUT: int
|
||||
SUBAGENTS_MAX_CONCURRENT: int | None = Field(default=None, gt=0)
|
||||
SUBAGENTS_MAX_ASYNC: int | None = Field(default=None, gt=0)
|
||||
SUBAGENTS_MAX_ITERATIONS: int | None = Field(default=None, gt=0)
|
||||
SUBAGENTS_MAX_OUTPUT: int | None = Field(default=None, gt=0)
|
||||
SUBAGENTS_SYSTEM_PROMPT: str
|
||||
|
||||
@field_validator(
|
||||
'SUBAGENTS_MAX_CONCURRENT',
|
||||
'SUBAGENTS_MAX_ASYNC',
|
||||
'SUBAGENTS_MAX_ITERATIONS',
|
||||
'SUBAGENTS_MAX_OUTPUT',
|
||||
mode='before',
|
||||
)
|
||||
@classmethod
|
||||
def normalize_limit(cls, value):
|
||||
return None if value == '' else value
|
||||
|
||||
@field_validator('SUBAGENTS_MAX_CONCURRENT', 'SUBAGENTS_MAX_ASYNC', mode='before')
|
||||
@classmethod
|
||||
def normalize_legacy_unlimited(cls, value):
|
||||
return None if value == -1 else value
|
||||
|
||||
|
||||
@router.get('/subagents', response_model=SubagentsConfigForm)
|
||||
async def get_subagents_config(user=Depends(get_admin_user)):
|
||||
|
|
|
|||
|
|
@ -322,13 +322,21 @@ async def delegate(
|
|||
'subagents.max_output',
|
||||
'subagents.system_prompt',
|
||||
)
|
||||
max_concurrent = int(config.get('subagents.max_concurrent') or 20)
|
||||
max_async = int(config.get('subagents.max_async') or 20)
|
||||
max_iterations = int(config.get('subagents.max_iterations') or 30)
|
||||
max_output = int(config.get('subagents.max_output') or 30_000)
|
||||
if max_concurrent != -1:
|
||||
max_concurrent = config.get('subagents.max_concurrent')
|
||||
max_concurrent = int(max_concurrent) if max_concurrent else None
|
||||
max_async = config.get('subagents.max_async')
|
||||
max_async = int(max_async) if max_async else None
|
||||
max_iterations = config.get('subagents.max_iterations')
|
||||
max_iterations = int(max_iterations) if max_iterations else None
|
||||
max_output = config.get('subagents.max_output')
|
||||
max_output = int(max_output) if max_output else None
|
||||
if max_concurrent == -1:
|
||||
max_concurrent = None
|
||||
elif max_concurrent is not None:
|
||||
max_concurrent = max(1, max_concurrent)
|
||||
if max_async != -1:
|
||||
if max_async == -1:
|
||||
max_async = None
|
||||
elif max_async is not None:
|
||||
max_async = max(1, max_async)
|
||||
|
||||
if background and not config.get('subagents.background_enabled'):
|
||||
|
|
@ -406,13 +414,13 @@ async def delegate(
|
|||
foreground_semaphore = None
|
||||
if background:
|
||||
async with _background_lock:
|
||||
if max_async != -1 and len(_background_active) >= max_async:
|
||||
if max_async is not None and len(_background_active) >= max_async:
|
||||
return (
|
||||
f'Error: Async subagent capacity reached ({max_async} running). '
|
||||
'Wait for one to finish or increase subagents.max_async.'
|
||||
)
|
||||
_background_active.add(delegation_id)
|
||||
elif max_concurrent != -1:
|
||||
elif max_concurrent is not None:
|
||||
if _foreground_semaphore is None:
|
||||
_foreground_semaphore = asyncio.Semaphore(max_concurrent)
|
||||
foreground_semaphore = _foreground_semaphore
|
||||
|
|
@ -551,7 +559,7 @@ async def delegate(
|
|||
for part in item.get('content') or []
|
||||
if part.get('type') == 'output_text'
|
||||
)
|
||||
if len(summary) > max_output:
|
||||
if max_output is not None and len(summary) > max_output:
|
||||
summary = f'{summary[:max_output]}\n\n[output truncated]'
|
||||
error = message.get('error')
|
||||
if isinstance(error, dict):
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
let saving = false;
|
||||
let enabled = false;
|
||||
let backgroundEnabled = false;
|
||||
let maxConcurrent = 20;
|
||||
let maxAsync = 20;
|
||||
let maxIterations = 30;
|
||||
let maxOutput = 30000;
|
||||
let maxConcurrent: number | null = null;
|
||||
let maxAsync: number | null = null;
|
||||
let maxIterations: number | null = null;
|
||||
let maxOutput: number | null = null;
|
||||
let systemPrompt = '';
|
||||
|
||||
onMount(async () => {
|
||||
|
|
@ -26,10 +26,10 @@
|
|||
const config = await getSubagentsConfig(localStorage.token);
|
||||
enabled = config?.ENABLE_SUBAGENTS ?? false;
|
||||
backgroundEnabled = config?.SUBAGENTS_BACKGROUND_ENABLED ?? false;
|
||||
maxConcurrent = Number(config?.SUBAGENTS_MAX_CONCURRENT) || 20;
|
||||
maxAsync = Number(config?.SUBAGENTS_MAX_ASYNC) || 20;
|
||||
maxIterations = Number(config?.SUBAGENTS_MAX_ITERATIONS) || 30;
|
||||
maxOutput = Number(config?.SUBAGENTS_MAX_OUTPUT) || 30000;
|
||||
maxConcurrent = config?.SUBAGENTS_MAX_CONCURRENT ?? null;
|
||||
maxAsync = config?.SUBAGENTS_MAX_ASYNC ?? null;
|
||||
maxIterations = config?.SUBAGENTS_MAX_ITERATIONS ?? null;
|
||||
maxOutput = config?.SUBAGENTS_MAX_OUTPUT ?? null;
|
||||
systemPrompt = config?.SUBAGENTS_SYSTEM_PROMPT ?? '';
|
||||
} catch (error) {
|
||||
toast.error(`${error}`);
|
||||
|
|
@ -44,10 +44,10 @@
|
|||
await setSubagentsConfig(localStorage.token, {
|
||||
ENABLE_SUBAGENTS: enabled,
|
||||
SUBAGENTS_BACKGROUND_ENABLED: backgroundEnabled,
|
||||
SUBAGENTS_MAX_CONCURRENT: maxConcurrent,
|
||||
SUBAGENTS_MAX_ASYNC: maxAsync,
|
||||
SUBAGENTS_MAX_ITERATIONS: maxIterations,
|
||||
SUBAGENTS_MAX_OUTPUT: maxOutput,
|
||||
SUBAGENTS_MAX_CONCURRENT: maxConcurrent ?? null,
|
||||
SUBAGENTS_MAX_ASYNC: maxAsync ?? null,
|
||||
SUBAGENTS_MAX_ITERATIONS: maxIterations ?? null,
|
||||
SUBAGENTS_MAX_OUTPUT: maxOutput ?? null,
|
||||
SUBAGENTS_SYSTEM_PROMPT: systemPrompt
|
||||
});
|
||||
await appConfig.set(await getBackendConfig());
|
||||
|
|
@ -92,13 +92,21 @@
|
|||
id="sa-concurrent"
|
||||
type="number"
|
||||
bind:value={maxConcurrent}
|
||||
min="-1"
|
||||
min="1"
|
||||
step="1"
|
||||
aria-describedby="sa-concurrent-help"
|
||||
class="h-7 w-16 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
/>
|
||||
<span class="text-[0.6875rem] text-gray-400 dark:text-gray-600">
|
||||
{$i18n.t('simultaneous sub-agents')}
|
||||
</span>
|
||||
</div>
|
||||
<p
|
||||
id="sa-concurrent-help"
|
||||
class="mt-1 text-[0.6875rem] text-gray-400 dark:text-gray-600"
|
||||
>
|
||||
{$i18n.t('Leave empty for unlimited')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -123,13 +131,18 @@
|
|||
id="sa-async"
|
||||
type="number"
|
||||
bind:value={maxAsync}
|
||||
min="-1"
|
||||
min="1"
|
||||
step="1"
|
||||
aria-describedby="sa-async-help"
|
||||
class="h-7 w-16 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
/>
|
||||
<span class="text-[0.6875rem] text-gray-400 dark:text-gray-600">
|
||||
{$i18n.t('background sub-agents')}
|
||||
</span>
|
||||
</div>
|
||||
<p id="sa-async-help" class="mt-1 text-[0.6875rem] text-gray-400 dark:text-gray-600">
|
||||
{$i18n.t('Leave empty for unlimited')}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
|
@ -143,13 +156,20 @@
|
|||
type="number"
|
||||
bind:value={maxIterations}
|
||||
min="1"
|
||||
max="100"
|
||||
step="1"
|
||||
aria-describedby="sa-iterations-help"
|
||||
class="h-7 w-16 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
/>
|
||||
<span class="text-[0.6875rem] text-gray-400 dark:text-gray-600">
|
||||
{$i18n.t('tool loops per sub-agent')}
|
||||
</span>
|
||||
</div>
|
||||
<p
|
||||
id="sa-iterations-help"
|
||||
class="mt-1 text-[0.6875rem] text-gray-400 dark:text-gray-600"
|
||||
>
|
||||
{$i18n.t('Leave empty for unlimited')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -161,13 +181,16 @@
|
|||
id="sa-output"
|
||||
type="number"
|
||||
bind:value={maxOutput}
|
||||
min="1000"
|
||||
max="100000"
|
||||
step="1000"
|
||||
min="1"
|
||||
step="1"
|
||||
aria-describedby="sa-output-help"
|
||||
class="h-7 w-20 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
|
||||
/>
|
||||
<span class="text-[0.6875rem] text-gray-400 dark:text-gray-600">chars</span>
|
||||
</div>
|
||||
<p id="sa-output-help" class="mt-1 text-[0.6875rem] text-gray-400 dark:text-gray-600">
|
||||
{$i18n.t('Leave empty for unlimited')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue