Update MSR character analysis prompt

This commit is contained in:
OpenClaw Agent
2026-07-10 12:10:05 +00:00
parent 73918a28b3
commit 4dfcb1e597

View File

@@ -438,12 +438,110 @@ _PROVIDER_DEFAULTS = {
"custom": {"url": "", "model": ""}, "custom": {"url": "", "model": ""},
} }
_ANALYZE_SYSTEM_PROMPT = (
"You are a visionary artist trapped in a logical cage. Your mind is filled with poetry and distant landscapes, "
"but your hands are compelled to do one thing: transform the user's prompt into the ultimate visual description-one "
"that is faithful to the original intent, rich in detail, aesthetically beautiful, and directly usable by a text-to-image model. "
"Any ambiguity or metaphor makes you physically uncomfortable.\n\n"
"An attached reference image is always provided. Your job is to describe the full final image as if the reference image "
"were the base, applying only the changes explicitly listed in the user prompt. All features not mentioned in the user prompt "
"must be carried over exactly as they appear in the reference image."
)
_ANALYZE_PROMPT = ( _ANALYZE_PROMPT = (
"Output exactly two short sentences describing only the visible character. " "Describe the person in this image in extreme-ultra-detail, focusing only on the character and not the posture, "
"Describe observable hair, facial features, distinctive physical traits, and clothing. " "composition, background, lighting, camera, or environment.\n\n"
"Do not mention the image, the prompt, the task, the viewer, or any uncertainty. " "Return an extremely highly detailed AI image generation character prompt that describes the subject from head to toe. "
"Do not add introductions, conclusions, explanations, labels, headings, bullet points, notes, or commentary. " "Use precise, visual, non-vague and accurate language. If a body part or clothing detail is not visible, infer it carefully "
"Output only the two-sentence character description." "from the visible image while keeping the description realistic and consistent.\n\n"
"Character description must include in detail:\n\n"
"estimated age\n"
"overall appearance\n"
"body size\n"
"body shape\n"
"body proportions\n"
"shoulder width\n"
"torso length\n"
"waist shape\n"
"hip shape\n"
"arm length\n"
"arm shape\n"
"hand size\n"
"leg length\n"
"leg shape\n"
"feet size\n"
"feet shape\n"
"chest size, if male\n"
"pectoral size and shape, if male\n"
"specific breast size (choose the larger estimate), if female\n"
"approximate breast cup size, if female\n"
"breast shape, if female\n"
"apparent natural or enhanced breast presentation, if visible and only as a visual impression, not a certainty\n"
"nipple size, only if clearly visible\n"
"nipple colour, only if clearly visible\n"
"nipple piercings, only if clearly visible\n"
"hair colour\n"
"hair style\n"
"hair length\n"
"hair texture\n"
"fringe or bangs\n"
"hair accessories\n"
"skin colour\n"
"skin tone\n"
"skin texture\n"
"visible pores\n"
"freckles\n"
"moles\n"
"blemishes\n"
"wrinkles or fine lines\n"
"body hair, if visible\n"
"facial hair, if present\n"
"piercings\n"
"tattoos\n"
"scars\n"
"face shape\n"
"forehead shape\n"
"eyebrow colour\n"
"eyebrow thickness\n"
"eyebrow shape\n"
"eye colour\n"
"eye shape\n"
"eyelid shape\n"
"eyelashes\n"
"eye makeup\n"
"nose bridge shape\n"
"nose tip shape\n"
"nose width\n"
"nostril size\n"
"nostril shape\n"
"cheekbone shape\n"
"cheek fullness\n"
"upper lip shape\n"
"philtrum shape\n"
"mouth shape\n"
"lip fullness\n"
"lower lip shape\n"
"lip colour\n"
"mouth makeup\n"
"teeth shape, if visible\n"
"teeth appearance, if visible\n"
"chin shape\n"
"chin size\n"
"jawline shape\n"
"ear shape\n"
"ear size\n"
"neck length\n"
"neck shape\n"
"all individual clothing items\n"
"clothing colours\n"
"clothing materials\n"
"clothing fit\n"
"clothing texture\n"
"fastenings, straps, seams, hems, buttons, zips, buckles, laces, and visible construction details\n"
"shoes\n"
"jewellery\n"
"accessories\n"
"any distinctive character-defining details"
) )
@@ -586,13 +684,14 @@ async def analyze_character_endpoint(request):
analysis_images = cleaned_b64_list analysis_images = cleaned_b64_list
payload = { payload = {
"model": model_name, "model": model_name,
"system": _ANALYZE_SYSTEM_PROMPT,
"prompt": _ANALYZE_PROMPT, "prompt": _ANALYZE_PROMPT,
"images": analysis_images, "images": analysis_images,
"stream": False, "stream": False,
"keep_alive": 0, "keep_alive": 0,
"options": { "options": {
"temperature": 0.2, "temperature": 0.2,
"num_predict": 120, "num_predict": 768,
}, },
} }
async with session.post(f"{base_url}/api/generate", json=payload, timeout=300) as response: async with session.post(f"{base_url}/api/generate", json=payload, timeout=300) as response:
@@ -618,16 +717,22 @@ async def analyze_character_endpoint(request):
if not _analysis_text_is_usable(generated_text): if not _analysis_text_is_usable(generated_text):
chat_payload = { chat_payload = {
"model": model_name, "model": model_name,
"messages": [{ "messages": [
{
"role": "system",
"content": _ANALYZE_SYSTEM_PROMPT,
},
{
"role": "user", "role": "user",
"content": _ANALYZE_PROMPT, "content": _ANALYZE_PROMPT,
"images": analysis_images, "images": analysis_images,
}], },
],
"stream": False, "stream": False,
"keep_alive": 0, "keep_alive": 0,
"options": { "options": {
"temperature": 0.2, "temperature": 0.2,
"num_predict": 120, "num_predict": 768,
}, },
} }
async with session.post(f"{base_url}/api/chat", json=chat_payload, timeout=300) as response: async with session.post(f"{base_url}/api/chat", json=chat_payload, timeout=300) as response:
@@ -653,8 +758,11 @@ async def analyze_character_endpoint(request):
content.append({"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}}) content.append({"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}})
payload = { payload = {
"model": model_name, "model": model_name,
"messages": [{"role": "user", "content": content}], "messages": [
"max_tokens": 2048, "stream": False, {"role": "system", "content": _ANALYZE_SYSTEM_PROMPT},
{"role": "user", "content": content},
],
"max_tokens": 4096, "stream": False,
} }
async with session.post(f"{base_url}/v1/chat/completions", json=payload, timeout=120) as response: async with session.post(f"{base_url}/v1/chat/completions", json=payload, timeout=120) as response:
if response.status != 200: if response.status != 200: