Store the Edit TextEncode prompt on library stills, not a Start still caption.
Edit + Enhance always leads with the keep/<image1> stanza and typed change; PE describe dumps are dropped, and Typed stays promptRaw. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,33 +1,60 @@
|
||||
/** Qwen Edit / PE-I2I prompt helpers. Start still = <image1>; Hero is never a slot. */
|
||||
|
||||
export const QWEN21_EDIT_KEEP =
|
||||
'Keep the identity, face, body, and pose of the person in <image1>.'
|
||||
'Keep the identity, face, body, pose, and likeness of the person in <image1>.\nDo not invent a different person.'
|
||||
|
||||
export const QWEN21_EDIT_KEEP_CHANGE =
|
||||
`${QWEN21_EDIT_KEEP} Apply only this change:`
|
||||
`${QWEN21_EDIT_KEEP}\nApply only this change:`
|
||||
|
||||
/** User omitted <image1> — prepend the keep-identity instruction once. */
|
||||
const EDIT_VERB =
|
||||
/\b(?:change|replace|put|swap|keep|remove|add|edit|make|turn|convert|transform|modify|update|set|apply|wear|place|swap|switch)\b/i
|
||||
|
||||
const DESCRIBE_LEAD =
|
||||
/^(?:the image is\b|this is a photograph of\b|a vertical photorealistic\b|a photorealistic\b|this (?:image|photo|picture) (?:shows|depicts|features)\b|the (?:photo|picture) (?:shows|depicts|features)\b)/i
|
||||
|
||||
/** Fixed identity stanza + the user's raw edit instruction. Always includes <image1>. */
|
||||
export function buildQwen21EditKeepStanza(rawInstruction) {
|
||||
const raw = String(rawInstruction || '').trim()
|
||||
if (!raw) return QWEN21_EDIT_KEEP.trim()
|
||||
return `${QWEN21_EDIT_KEEP_CHANGE} ${raw}`.trim()
|
||||
}
|
||||
|
||||
/** Enhance off / refusal: ensure the sample prompt is the keep stanza, never PE-only. */
|
||||
export function ensureQwen21EditPrompt(prompt) {
|
||||
const text = String(prompt || '').trim()
|
||||
if (!text) return text
|
||||
if (/<image1>/i.test(text)) return text
|
||||
return `${QWEN21_EDIT_KEEP_CHANGE} ${text}`.trim()
|
||||
if (/Keep the identity, face, body, pose, and likeness of the person in <image1>/i.test(text)) return text
|
||||
return buildQwen21EditKeepStanza(text)
|
||||
}
|
||||
|
||||
/**
|
||||
* After PE-I2I: official PE told N=1 not to use tags, so rewrites often say
|
||||
* "the photo" / "the image" with zero <image1>. Qwen Edit only binds Start still
|
||||
* when the text contains the tag — force it onto every Edit rewrite.
|
||||
*/
|
||||
export function stitchQwen21PeEditPrompt(rewritten) {
|
||||
let text = String(rewritten || '').trim()
|
||||
if (!text) return text
|
||||
// Prefer the tag over natural substitutes (do not invent <image2>).
|
||||
text = text
|
||||
/** PE rewrite looks like a T2I observer caption, not an edit directive. */
|
||||
export function isQwen21PeEditDescribe(rewritten) {
|
||||
const text = String(rewritten || '').trim()
|
||||
if (!text) return true
|
||||
if (DESCRIBE_LEAD.test(text)) return true
|
||||
if (!EDIT_VERB.test(text)) return true
|
||||
return false
|
||||
}
|
||||
|
||||
function retagNaturalImageRefs(text) {
|
||||
return String(text || '')
|
||||
.replace(/\bthe woman in the (?:input )?(?:photo|picture|image)\b/gi, 'the person in <image1>')
|
||||
.replace(/\bthe (?:person|man|subject) in the (?:input )?(?:photo|picture|image)\b/gi, 'the person in <image1>')
|
||||
.replace(/\bin the (?:input )?(?:photo|picture|image)\b/gi, 'in <image1>')
|
||||
.replace(/\bthe (?:input )?(?:photo|picture|image)\b/gi, '<image1>')
|
||||
if (/<image1>/i.test(text)) return text
|
||||
return `${QWEN21_EDIT_KEEP} ${text}`.trim()
|
||||
}
|
||||
|
||||
/**
|
||||
* After PE-I2I: never let the PE chunk be the entire prompt.
|
||||
* Always lead with the keep/<image1> stanza + raw instruction; append PE only when it is an edit directive.
|
||||
*/
|
||||
export function stitchQwen21PeEditPrompt(rawInstruction, rewritten) {
|
||||
const stanza = buildQwen21EditKeepStanza(rawInstruction)
|
||||
let pe = retagNaturalImageRefs(String(rewritten || '').trim()).trim()
|
||||
if (!pe) return { prompt: stanza, skippedAsDescribe: false }
|
||||
if (isQwen21PeEditDescribe(pe)) {
|
||||
return { prompt: stanza, skippedAsDescribe: true }
|
||||
}
|
||||
// No <image1> in the PE chunk is fine — stanza already has the tag; keep PE as extra detail.
|
||||
return { prompt: `${stanza}\n\n${pe}`.trim(), skippedAsDescribe: false }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user