Found in a Gemini Flash exam (recorded in tool-exam.md): - A later step's mask preview (only the character redrawn) was taken for a base; picked, the rest enlarged the mask. A base is the decoded picture itself. - Flash tries run_workflow with no arguments: on a blueprint just built that drew three bases of nothing and spent the three to pick from. A run that draws from an empty latent with every positive prompt empty is refused once. - A Tile refused for not fitting: when the user named the model, the AI is told to ask before changing it. - A decision's rejected option given as a sentence stays one option. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
67 lines
3.8 KiB
JavaScript
67 lines
3.8 KiB
JavaScript
/**
|
|
* Before a run: is a prompt in a language the canvas's drawing model cannot read (api/prompt_language.py)?
|
|
* The model files come from the loaders' model boxes (ui_node_model_picker.js), the prompts from what the run
|
|
* sends: the canvas's positive prompt boxes (prompt_boxes.js), or a job sheet's rows. Asked by the AI's
|
|
* run_workflow (mcp_bridge.js) and job sheet (job_sheet_run.js), and the job sheet's Start (ui_job_sheet.js).
|
|
* What was asked about once is let through the next time (`heard`, kept apart for the AI and the user: the AI's
|
|
* refusal is no warning the user saw), so either can insist.
|
|
* And is there a prompt at all: an AI trying a tool out calls run_workflow with nothing, and on a picture
|
|
* Anomalous just built, its prompt box still empty, that drew pictures of nothing (the bases of a plan too).
|
|
* Such a run is refused once as well.
|
|
*/
|
|
|
|
import { promptBoxes, promptMissing } from './prompt_boxes.js';
|
|
import { modelComboWidgets } from './ui_node_model_picker.js';
|
|
|
|
const off = node => node.mode === 2 || node.mode === 4;
|
|
const heard = new Set();
|
|
|
|
function* nodesOf(graph) {
|
|
for (const node of graph?._nodes || []) {
|
|
yield node;
|
|
if (node.subgraph) yield* nodesOf(node.subgraph);
|
|
}
|
|
}
|
|
|
|
/** The text in `graph`'s positive prompt boxes. */
|
|
export const canvasPrompts = graph => [...nodesOf(graph)].filter(node => !off(node))
|
|
.flatMap(node => promptBoxes(node).filter(box => box.role === 'positive').map(box => String(box.widget?.value ?? '')));
|
|
|
|
/** {family, model} when a prompt of `texts` (default: the canvas's) is in a language `graph`'s model cannot read; else null. */
|
|
export async function languageProblem(graph, texts = canvasPrompts(graph)) {
|
|
const models = [...nodesOf(graph)].filter(node => !off(node)).flatMap(node => modelComboWidgets(node).map(widget => widget.value))
|
|
.filter(value => typeof value === 'string' && value && value !== 'None');
|
|
if (!models.length || !texts.some(Boolean)) return null;
|
|
try {
|
|
const response = await fetch('/anomalous/prompt_language', { method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ models: [...new Set(models)], texts }) });
|
|
const found = await response.json();
|
|
return found?.family ? found : null;
|
|
} catch {
|
|
return null; // the check only helps: a run is never stopped by it failing
|
|
}
|
|
}
|
|
|
|
/** Whether `graph` would draw from an empty latent with every positive prompt box (`texts`) empty, the first time the AI tries it on that canvas. */
|
|
export function noPrompt(graph, texts) {
|
|
return promptMissing([...nodesOf(graph)].filter(node => !off(node)), texts)
|
|
&& Boolean(firstTime({ model: `no prompt ${graph?.id ?? ''}` }, texts, 'ai'));
|
|
}
|
|
|
|
export const NO_PROMPT_WORDS = 'Nothing was run: the positive prompt is empty, so the pictures would follow nothing. Give it with the run: '
|
|
+ 'run_workflow(prompt=…, negative=…). If the user wants a run with no prompt, call again unchanged.';
|
|
|
|
/** The problem the first time `who` ('ai' or 'user') meets it; null when they met it before with the same model and prompts. */
|
|
export function firstTime(problem, texts, who) {
|
|
if (!problem) return null;
|
|
const key = `${who}\n${problem.model}\n${texts.join('\n')}`;
|
|
if (heard.has(key)) return null;
|
|
heard.add(key);
|
|
return problem;
|
|
}
|
|
|
|
/** What the AI is told: nothing ran, why, and how to go on. */
|
|
export const aiWords = problem => `Nothing was run: the canvas's model ${problem.model} (${problem.family}) reads English words and tags only, `
|
|
+ 'and the prompt is Chinese, Japanese or Korean, so the picture would not follow it and shows whatever the model leans to. '
|
|
+ 'Write the prompt in English for it (keep what the user asked for), then run again. If the user wants it run as written, call again unchanged.';
|