Enhance no longer fails the studio job when the rewrite refuses or comes back empty; host prompt copies keep the official steps plus the adult appendix after a node re-clone. Co-authored-by: Cursor <cursoragent@cursor.com>
44 lines
2.1 KiB
JavaScript
44 lines
2.1 KiB
JavaScript
/** Qwen PE refusal / empty-rewrite detection — fail open to promptRaw. */
|
||
|
||
const REFUSAL_RE =
|
||
/i cannot|i can't|i['’]m not able|i am not able|cannot assist|can't assist|won['’]t create|will not create|against my|not appropriate|\bsafety\b|content policy|抱歉|无法|不能协助|不符合/i
|
||
|
||
const STOP = new Set([
|
||
'the', 'and', 'for', 'are', 'was', 'were', 'been', 'being', 'this', 'that', 'with', 'from',
|
||
'into', 'your', 'have', 'will', 'would', 'could', 'should', 'about', 'there', 'their', 'them',
|
||
'then', 'than', 'when', 'what', 'which', 'while', 'where', 'make', 'made', 'like', 'just',
|
||
'only', 'also', 'over', 'under', 'after', 'before', 'between', 'through', 'image', 'photo',
|
||
'picture', 'please', 'create', 'generate', 'show', 'want', 'need', 'scene', 'style', 'prompt',
|
||
'edit', 'change', 'keep', 'using', 'into', 'onto', 'her', 'him', 'his', 'she', 'they', 'them',
|
||
])
|
||
|
||
/** Concrete tokens from the user brief (latin words ≥3 or CJK runs). */
|
||
export function concreteTokens(text) {
|
||
const raw = String(text || '').toLowerCase().match(/[a-z][a-z0-9-]{2,}|[\u4e00-\u9fff]{2,}/g) || []
|
||
return [...new Set(raw)].filter(w => !STOP.has(w))
|
||
}
|
||
|
||
function isGutted(userPrompt, rewritten) {
|
||
const user = String(userPrompt || '').trim()
|
||
const out = String(rewritten || '').trim()
|
||
if (!user || !out) return !out
|
||
if (out.length >= user.length) return false
|
||
const nouns = concreteTokens(user)
|
||
if (!nouns.length) return false
|
||
const lower = out.toLowerCase()
|
||
return !nouns.some(n => lower.includes(n))
|
||
}
|
||
|
||
/**
|
||
* @returns {{ refused: boolean, reason: string }}
|
||
*/
|
||
export function qwen21PeRefusal(userPrompt, { positive_prompt, thinking, parse_ok } = {}) {
|
||
const positive = String(positive_prompt || '').trim()
|
||
const think = String(thinking || '').trim()
|
||
if (!parse_ok && !positive) return { refused: true, reason: 'empty rewrite (parse_ok false)' }
|
||
if (!positive) return { refused: true, reason: 'empty rewrite' }
|
||
if (REFUSAL_RE.test(positive) || REFUSAL_RE.test(think)) return { refused: true, reason: 'model refused' }
|
||
if (isGutted(userPrompt, positive)) return { refused: true, reason: 'gutted rewrite' }
|
||
return { refused: false, reason: '' }
|
||
}
|