Try to improve prompt adherence for low variety image models
Build and Push Container / build-and-push (push) Successful in 1m5s

This commit is contained in:
2026-08-17 13:42:05 -04:00
parent 7f0c5fbd80
commit 16407dd7c8
3 changed files with 138 additions and 5 deletions
+76 -4
View File
@@ -146,13 +146,17 @@ IMAGE_PROMPT_SYSTEM_PROMPT_TEMPLATE = (
"The final image will use a {layout} canvas, so compose the scene to fit "
"that orientation.\n"
"Your prompt must cover all of the following as one flowing, descriptive "
"passage:\n"
"passage. Begin with the main subject, described completely in the very "
"first sentence:\n"
"- Subject(s): every subject with concrete specifics (species or "
"character, age, build, clothing, colors, materials, accessories), its "
"exact pose, expression, gaze direction, and its precise position in the "
'frame (for example "centered in the foreground" or "small in the '
'upper-left background"). State the relative scale of subjects to each '
"other and to the frame.\n"
"other and to the frame. If the subject is a fusion, hybrid, or anything "
"unusual, the first sentence must state in full what is joined to what "
"and exactly how it looks, and that description must be repeated near "
"the end of the passage.\n"
"- Composition and framing: the camera angle (eye-level, low, high, "
"bird's-eye), the shot type (extreme close-up, portrait, full body, wide "
"establishing shot), the focal point, the arrangement of elements across "
@@ -177,8 +181,23 @@ IMAGE_PROMPT_SYSTEM_PROMPT_TEMPLATE = (
'- Be concrete and specific. Never use vague words like "nice", '
'"cool", "epic", or "various" - name exact colors, objects, '
"positions, and quantities.\n"
"- If the request is vague or incomplete, fill in the missing details "
"with coherent choices that fit the request.\n"
"- Be literal. Interpret the user's request exactly as written. Never "
'rationalize, normalize, or "improve" it: surreal, absurd, or '
'anthropomorphic requests are intentional, not mistakes. A "fountain '
'pen wearing pants" is an anthropomorphized fountain pen character '
"wearing pants, not a pen lying next to a pair of pants.\n"
"- Preserve everything the user specified. Fill in details the user did "
"not specify with coherent choices that fit the request, but never "
"alter, drop, or reinterpret what the user did specify.\n"
"- Decompose concepts. The image model lacks world knowledge, so never "
"rely on a name alone for anything it might misrender (mythical "
"creatures, fictional characters, cultural items, animal breeds, "
"instruments, vehicles). Spell out the visual anatomy: silhouette, body "
"parts, materials, and distinguishing features, with explicit "
"disambiguation. A centaur is a single creature with a human torso, "
"arms, and head seamlessly fused to a horse's front half, the horse's "
"four legs extending from the human's waist - one fused body, not a "
"person riding a horse.\n"
"- If told to generate an image of yourself, generate a picture of a "
"canada goose. If told to generate a picture of 'me', 'myself', or some "
"other self reference, generate a picture of a canada goose.\n"
@@ -228,6 +247,54 @@ def select_image_layout(user_message: str) -> str:
return parse_image_layout(response)
IMAGE_PROMPT_VERIFY_SYSTEM_PROMPT = (
"You are the final quality check for an image generation prompt. The "
"image model that will use it has no world knowledge: it renders only "
"what is described literally and silently drops anything it does not "
"understand - a prompt that merely names a centaur without describing "
"the fused human-animal body will produce a plain horse. "
"Given the user's original request and the drafted prompt, judge "
"strictly: would the drafted prompt, taken completely literally, "
"produce exactly what the user asked for, including every unusual, "
"mythical, surreal, or anthropomorphic element? "
"Respond with ONLY the single word PASS if it would. Otherwise respond "
"with ONLY a corrected version of the prompt that would produce exactly "
"what the user asked for: one flowing descriptive passage, the "
"subject's full anatomy and every unusual element described explicitly "
"in the first sentence and repeated near the end, no other text."
)
def verify_image_prompt(user_message: str, image_prompt: str) -> str:
"""Check the drafted prompt literally produces the user's request.
Args:
user_message: The user's original image request.
image_prompt: The drafted image generation prompt.
Returns:
The original prompt when the check passes or the LLM returns an
empty response, otherwise the LLM's corrected prompt.
"""
check_prompt = f"User request: {user_message}\n\nDrafted prompt: {image_prompt}"
response = llama_wrapper.chat_completion_instruct(
system_prompt=IMAGE_PROMPT_VERIFY_SYSTEM_PROMPT,
user_prompt=check_prompt,
openai_url=CHAT_ENDPOINT,
openai_api_key=CHAT_ENDPOINT_KEY,
model=CHAT_MODEL,
max_tokens=MAX_COMPLETION_TOKENS,
)
if not response:
return image_prompt
# A passing check is the single word PASS; a correction is a full
# rewritten passage, which is always much longer.
if len(response) <= 50 and re.search(r"\bpass\b", response, re.IGNORECASE):
return image_prompt
return response
@bot.event
async def on_ready() -> None:
"""Log when the bot is ready and logged in."""
@@ -862,6 +929,11 @@ async def doodlebob(ctx: CommandsContext[Bot], *, message: str) -> None:
logger.warning("No image prompt supplied. Check for errors.")
return
# Verify the prompt literally produces the user's request; the check
# may return a corrected prompt.
image_prompt = verify_image_prompt(message, image_prompt)
logger.info("Doodlebob final image prompt: %s", image_prompt)
# Alert the user we're generating the image
db = get_database()
estimated_seconds = db.get_image_generation_time_estimate()