mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-07 02:58:21 +00:00
fix(images): stop auto-assigning prompt to negative prompt nodes, expose seed and extra_params via API
- Don't auto-assign node_ids for ambiguous text/prompt/positive keys in workflow auto-detection so admins control which CLIPTextEncode nodes receive the prompt vs negative prompt - Restore editable key input fields for workflow nodes - Add seed field to CreateImageForm and pass it through to ComfyUI payload - Add extra_params dict to allow API callers to set arbitrary workflow parameters (e.g. cfg, sampler_name, scheduler, denoise)
This commit is contained in:
parent
283520d128
commit
c3eaed3c5f
3 changed files with 55 additions and 10 deletions
|
|
@ -455,6 +455,8 @@ class CreateImageForm(BaseModel):
|
|||
n: int = 1
|
||||
steps: int | None = None
|
||||
negative_prompt: str | None = None
|
||||
seed: int | None = None
|
||||
extra_params: dict | None = None
|
||||
|
||||
|
||||
GenerateImageForm = CreateImageForm # Alias for backward compatibility
|
||||
|
|
@ -749,6 +751,12 @@ async def image_generations(
|
|||
if form_data.negative_prompt is not None:
|
||||
data['negative_prompt'] = form_data.negative_prompt
|
||||
|
||||
if form_data.seed is not None:
|
||||
data['seed'] = form_data.seed
|
||||
|
||||
if form_data.extra_params:
|
||||
data['extra_params'] = form_data.extra_params
|
||||
|
||||
form_data = ComfyUICreateImageForm(
|
||||
**{
|
||||
'workflow': ComfyUIWorkflow(
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ class ComfyUICreateImageForm(BaseModel):
|
|||
|
||||
steps: Optional[int] = None
|
||||
seed: Optional[int] = None
|
||||
extra_params: Optional[dict] = None
|
||||
|
||||
|
||||
def _apply_workflow_nodes(workflow, nodes, model, payload):
|
||||
|
|
@ -240,6 +241,9 @@ def _apply_workflow_nodes(workflow, nodes, model, payload):
|
|||
elif node.value is not None:
|
||||
# Custom static override
|
||||
workflow[node_id]['inputs'][node_key] = node.value
|
||||
elif hasattr(payload, 'extra_params') and payload.extra_params and node_key in payload.extra_params:
|
||||
# API-provided dynamic override
|
||||
workflow[node_id]['inputs'][node_key] = payload.extra_params[node_key]
|
||||
|
||||
# --- Generic static value passthrough --------------------------------
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -104,10 +104,17 @@
|
|||
);
|
||||
|
||||
if (!nodeGroups.has(entryKey)) {
|
||||
// Keys that map to payload.prompt in _apply_workflow_nodes are ambiguous
|
||||
// when multiple nodes share the same key (e.g. positive vs negative
|
||||
// CLIPTextEncode both have key 'text'). Leave node_ids empty for
|
||||
// these so the admin explicitly picks which nodes receive the prompt.
|
||||
const ambiguousKeys = new Set(['text', 'prompt', 'positive']);
|
||||
const autoAssign = !ambiguousKeys.has(inputKey);
|
||||
|
||||
nodeGroups.set(entryKey, {
|
||||
type: semanticType,
|
||||
key: inputKey,
|
||||
node_ids: [nodeId],
|
||||
node_ids: autoAssign ? [nodeId] : [],
|
||||
class_type: node.class_type
|
||||
});
|
||||
}
|
||||
|
|
@ -255,10 +262,14 @@
|
|||
const semanticType = `${node.class_type}::${inputKey}`;
|
||||
|
||||
if (!nodeGroups.has(entryKey)) {
|
||||
// Same ambiguous-key logic as parseAndPopulateWorkflowNodes
|
||||
const ambiguousKeys = new Set(['text', 'prompt', 'positive']);
|
||||
const autoAssign = !ambiguousKeys.has(inputKey);
|
||||
|
||||
nodeGroups.set(entryKey, {
|
||||
type: semanticType,
|
||||
key: inputKey,
|
||||
node_ids: [nodeId],
|
||||
node_ids: autoAssign ? [nodeId] : [],
|
||||
class_type: node.class_type
|
||||
});
|
||||
}
|
||||
|
|
@ -810,16 +821,27 @@
|
|||
<div class="flex w-full flex-col">
|
||||
<div class="shrink-0">
|
||||
<div
|
||||
class="line-clamp-1 text-gray-400 dark:text-gray-500"
|
||||
class="capitalize line-clamp-1 w-20 text-gray-400 dark:text-gray-500"
|
||||
title={node.type}
|
||||
>
|
||||
<span class="font-medium">{node.class_type}</span><span
|
||||
class="opacity-60">::{node.key}</span
|
||||
>
|
||||
{node.class_type}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-0.5 flex items-center">
|
||||
<div class="">
|
||||
<Tooltip content={$i18n.t('Input Key (e.g. text, unet_name, steps)')}>
|
||||
<input
|
||||
class="{inputClass} w-24"
|
||||
placeholder={$i18n.t('Key')}
|
||||
bind:value={node.key}
|
||||
required
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div class="px-2 text-gray-400 dark:text-gray-500">:</div>
|
||||
|
||||
<div class="w-full">
|
||||
<Tooltip
|
||||
content={$i18n.t('Comma separated Node Ids (e.g. 1 or 1,2)')}
|
||||
|
|
@ -1113,16 +1135,27 @@
|
|||
<div class="flex w-full flex-col">
|
||||
<div class="shrink-0">
|
||||
<div
|
||||
class="line-clamp-1 text-gray-400 dark:text-gray-500"
|
||||
class="capitalize line-clamp-1 w-20 text-gray-400 dark:text-gray-500"
|
||||
title={node.type}
|
||||
>
|
||||
<span class="font-medium">{node.class_type}</span><span
|
||||
class="opacity-60">::{node.key}</span
|
||||
>
|
||||
{node.class_type}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-0.5 flex items-center">
|
||||
<div class="">
|
||||
<Tooltip content={$i18n.t('Input Key (e.g. text, unet_name, steps)')}>
|
||||
<input
|
||||
class="{inputClass} w-24"
|
||||
placeholder={$i18n.t('Key')}
|
||||
bind:value={node.key}
|
||||
required
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div class="px-2 text-gray-400 dark:text-gray-500">:</div>
|
||||
|
||||
<div class="w-full">
|
||||
<Tooltip
|
||||
content={$i18n.t('Comma separated Node Ids (e.g. 1 or 1,2)')}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue