v2.5.3 — Fix duplicate portrait + anti-repetition tags
- portraitAdded guard prevents duplicate image in chat - Negative prompt: multiple views, split screen, repetition, duplicate - Removed cowboy shot (caused repetition) - Clean gender tags: 1girl, solo (no trailing comma) - Steps 35, CFG 6.5 for better NoobAI-XL quality - Image max-width 400px in chat
This commit is contained in:
+11
-11
@@ -120,18 +120,18 @@ def build_prompt_from_appearance(character: dict, context: str = "") -> str:
|
|||||||
# Gender — Danbooru tags for anime, natural language for others
|
# Gender — Danbooru tags for anime, natural language for others
|
||||||
if use_danbooru:
|
if use_danbooru:
|
||||||
if gender == "female":
|
if gender == "female":
|
||||||
gender_tag = "1girl, woman, "
|
gender_tag = "1girl, solo"
|
||||||
elif gender == "male":
|
elif gender == "male":
|
||||||
gender_tag = "1boy, man, "
|
gender_tag = "1boy, solo"
|
||||||
else:
|
else:
|
||||||
gender_tag = "person, "
|
gender_tag = "solo"
|
||||||
else:
|
else:
|
||||||
if gender == "female":
|
if gender == "female":
|
||||||
gender_tag = "young woman, "
|
gender_tag = "young woman"
|
||||||
elif gender == "male":
|
elif gender == "male":
|
||||||
gender_tag = "young man, "
|
gender_tag = "young man"
|
||||||
else:
|
else:
|
||||||
gender_tag = "person, "
|
gender_tag = "person"
|
||||||
|
|
||||||
# Translation map: German appearance values → English tags for the model
|
# Translation map: German appearance values → English tags for the model
|
||||||
translate_map = {
|
translate_map = {
|
||||||
@@ -183,7 +183,7 @@ def build_prompt_from_appearance(character: dict, context: str = "") -> str:
|
|||||||
|
|
||||||
# Build prompt — use established Danbooru tags for NoobAI-XL
|
# Build prompt — use established Danbooru tags for NoobAI-XL
|
||||||
parts = [
|
parts = [
|
||||||
f"cowboy shot, {style_prefix}{gender_tag.strip()}",
|
f"{style_prefix}{gender_tag}",
|
||||||
f"{age} years old",
|
f"{age} years old",
|
||||||
]
|
]
|
||||||
if build:
|
if build:
|
||||||
@@ -216,8 +216,8 @@ def build_portrait_workflow(prompt: str, negative: str = "", width: int = 1024,
|
|||||||
"class_type": "KSampler",
|
"class_type": "KSampler",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"seed": int(time.time()) % (2**32),
|
"seed": int(time.time()) % (2**32),
|
||||||
"steps": 30,
|
"steps": 35,
|
||||||
"cfg": 7.0,
|
"cfg": 6.5,
|
||||||
"sampler_name": "dpmpp_2m",
|
"sampler_name": "dpmpp_2m",
|
||||||
"scheduler": "karras",
|
"scheduler": "karras",
|
||||||
"denoise": 1.0,
|
"denoise": 1.0,
|
||||||
@@ -245,7 +245,7 @@ def build_portrait_workflow(prompt: str, negative: str = "", width: int = 1024,
|
|||||||
"7": {
|
"7": {
|
||||||
"class_type": "CLIPTextEncode",
|
"class_type": "CLIPTextEncode",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"text": f"lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, blurry, deformed, ugly, {negative}",
|
"text": f"realistic, 3d, render, photorealistic, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, blurry, deformed, ugly, multiple views, split screen, repetition, duplicate, {negative}",
|
||||||
"clip": ["4", 1]
|
"clip": ["4", 1]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -322,7 +322,7 @@ def build_i2i_workflow(prompt: str, negative: str, reference_image_path: str, wi
|
|||||||
"7": {
|
"7": {
|
||||||
"class_type": "CLIPTextEncode",
|
"class_type": "CLIPTextEncode",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"text": f"lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, blurry, deformed, ugly, {negative}",
|
"text": f"realistic, 3d, render, photorealistic, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, blurry, deformed, ugly, multiple views, split screen, repetition, duplicate, {negative}",
|
||||||
"clip": ["4", 1]
|
"clip": ["4", 1]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 971 KiB After Width: | Height: | Size: 1.1 MiB |
+5
-3
@@ -321,12 +321,14 @@
|
|||||||
|
|
||||||
if (data.job_id) {
|
if (data.job_id) {
|
||||||
const jobId = data.job_id;
|
const jobId = data.job_id;
|
||||||
|
let portraitAdded = false; // Guard against duplicate insertion
|
||||||
const pollInterval = setInterval(async () => {
|
const pollInterval = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
const statusResp = await fetch(`/api/portrait/status/${jobId}`);
|
const statusResp = await fetch(`/api/portrait/status/${jobId}`);
|
||||||
const statusData = await statusResp.json();
|
const statusData = await statusResp.json();
|
||||||
|
|
||||||
if (statusData.status === 'done' && statusData.image) {
|
if (statusData.status === 'done' && statusData.image && !portraitAdded) {
|
||||||
|
portraitAdded = true; // Prevent duplicate
|
||||||
clearInterval(pollInterval);
|
clearInterval(pollInterval);
|
||||||
const imgUrl = `${statusData.image}?t=${Date.now()}`;
|
const imgUrl = `${statusData.image}?t=${Date.now()}`;
|
||||||
|
|
||||||
@@ -334,13 +336,13 @@
|
|||||||
const avatarEl = document.querySelector('.avatar');
|
const avatarEl = document.querySelector('.avatar');
|
||||||
avatarEl.innerHTML = `<img src="${imgUrl}" style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">`;
|
avatarEl.innerHTML = `<img src="${imgUrl}" style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">`;
|
||||||
|
|
||||||
// Also show the portrait in the chat as a message
|
// Show portrait in chat as a message (only once!)
|
||||||
const portraitMsg = document.createElement('div');
|
const portraitMsg = document.createElement('div');
|
||||||
portraitMsg.className = 'msg msg-bot';
|
portraitMsg.className = 'msg msg-bot';
|
||||||
portraitMsg.style.padding = '0';
|
portraitMsg.style.padding = '0';
|
||||||
portraitMsg.style.overflow = 'hidden';
|
portraitMsg.style.overflow = 'hidden';
|
||||||
portraitMsg.innerHTML = `
|
portraitMsg.innerHTML = `
|
||||||
<img src="${imgUrl}" style="width: 100%; max-width: 300px; border-radius: 16px 16px 16px 4px; display: block;">
|
<img src="${imgUrl}" style="width: 100%; max-width: 400px; border-radius: 16px 16px 16px 4px; display: block;">
|
||||||
<div style="padding: 8px 12px; font-size: 0.8rem; color: var(--muted);">🖼️ Neues Portrait generiert</div>
|
<div style="padding: 8px 12px; font-size: 0.8rem; color: var(--muted);">🖼️ Neues Portrait generiert</div>
|
||||||
`;
|
`;
|
||||||
chat.appendChild(portraitMsg);
|
chat.appendChild(portraitMsg);
|
||||||
|
|||||||
Reference in New Issue
Block a user