smart_image_gen v0.7.3: edit_image inherits style from prior tool call
User reported edit_image picking 'juggernaut' (photoreal) for an edit
on a furry image — the LLM didn't carry context, and the tool's
fallback _route_style only sees the edit instruction text, which for
neutral edits ('bigger', 'glowing eyes') has no furry keywords.
Fix in two places:
1. Tool: _inherited_style scans __messages__ in reverse for prior
generate_image / edit_image tool calls and returns the style arg
they used. edit_image now resolves: explicit style → inherited →
keyword fallback. Deterministic, no LLM cooperation needed for
follow-up edits on previously-generated images.
2. System prompt: explicit three-step style resolution for
edit_image. Generated by you → omit style and auto-inherit.
Uploaded by user → INSPECT visually and pick a matching style
(the LLM is the only thing with vision; the tool can't see
pixels). Then keep that style for subsequent edits.
Both paths matter — the tool fix handles the common case
deterministically, the prompt fix handles the upload case where
there's nothing to inherit from.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
title: Smart Image Generator & Editor (ComfyUI)
|
||||
author: ai-stack
|
||||
version: 0.7.2
|
||||
version: 0.7.3
|
||||
description: Generate or edit images via ComfyUI with automatic SDXL
|
||||
checkpoint routing. Two methods — generate_image (txt2img) and
|
||||
edit_image (img2img on the user's most recently attached image). The
|
||||
@@ -20,6 +20,7 @@ import asyncio
|
||||
import base64
|
||||
import inspect
|
||||
import io
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
import uuid
|
||||
@@ -222,6 +223,42 @@ def _route_style(prompt: str) -> str:
|
||||
return DEFAULT_STYLE
|
||||
|
||||
|
||||
def _inherited_style(messages: Optional[list]) -> Optional[str]:
|
||||
"""
|
||||
Return the `style` arg from the most recent generate_image /
|
||||
edit_image tool call in the conversation. Used so edit_image can
|
||||
auto-inherit the style of the image being edited when the LLM
|
||||
didn't pass one explicitly — without this, an edit on a furry
|
||||
image with a neutral edit prompt ("make the eyes glow") falls
|
||||
through to the keyword router and picks a wrong style.
|
||||
"""
|
||||
if not messages:
|
||||
return None
|
||||
for msg in reversed(messages):
|
||||
if not isinstance(msg, dict):
|
||||
continue
|
||||
for tc in (msg.get("tool_calls") or []):
|
||||
if not isinstance(tc, dict):
|
||||
continue
|
||||
fn = tc.get("function") or {}
|
||||
if fn.get("name") not in ("generate_image", "edit_image"):
|
||||
continue
|
||||
raw_args = fn.get("arguments")
|
||||
if isinstance(raw_args, str):
|
||||
try:
|
||||
args = json.loads(raw_args)
|
||||
except (TypeError, ValueError):
|
||||
args = {}
|
||||
elif isinstance(raw_args, dict):
|
||||
args = raw_args
|
||||
else:
|
||||
args = {}
|
||||
style = args.get("style")
|
||||
if isinstance(style, str) and style in STYLES:
|
||||
return style
|
||||
return None
|
||||
|
||||
|
||||
def _seed_value(seed: int) -> int:
|
||||
return seed if seed > 0 else int(time.time() * 1000) % (2**31)
|
||||
|
||||
@@ -799,9 +836,18 @@ class Tools:
|
||||
|
||||
Pick `style` for the DESIRED OUTPUT, not the input image.
|
||||
|
||||
Style resolution order: explicit `style` arg → inherited from the
|
||||
most recent prior generate_image / edit_image call in this
|
||||
conversation → keyword detection on `prompt`. Omit `style` to
|
||||
let the tool inherit from the previous call automatically — it
|
||||
usually picks the right thing for follow-up edits on an image
|
||||
the LLM just generated.
|
||||
|
||||
:param prompt: What the changed area should look like.
|
||||
Tool auto-prepends quality tags — don't include those.
|
||||
:param style: One of the StyleName values. Omit to auto-detect.
|
||||
:param style: One of the StyleName values. Omit to auto-inherit
|
||||
from the previous tool call (recommended for edits on
|
||||
images you generated earlier in this chat).
|
||||
:param mask_text: Noun phrase describing the region to edit. Set
|
||||
for LOCAL changes; omit for GLOBAL.
|
||||
:param denoise: 0.0 = no change, 1.0 = ignore source. Defaults to
|
||||
@@ -810,7 +856,12 @@ class Tools:
|
||||
:param seed: 0 to randomize, otherwise specific.
|
||||
:return: Markdown image of the result, or an error if no image is attached.
|
||||
"""
|
||||
chosen = style or _route_style(prompt)
|
||||
# Resolve style with explicit > inherited-from-prior-call > keyword.
|
||||
# Inheritance covers the common case where the LLM is editing an
|
||||
# image it already generated and forgets to set style — without it,
|
||||
# neutral edit prompts ("bigger", "glowing eyes") fall through to
|
||||
# the keyword router and get the wrong checkpoint.
|
||||
chosen = style or _inherited_style(__messages__) or _route_style(prompt)
|
||||
settings = STYLES.get(chosen)
|
||||
if not settings:
|
||||
return f"Unknown style '{chosen}'. Available: {', '.join(STYLES.keys())}"
|
||||
|
||||
Reference in New Issue
Block a user