@pixerate/editor 0.223.6 → 0.223.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tools/skill-evals.d.cts +21 -1
- package/dist/tools/skill-evals.d.ts +21 -1
- package/package.json +1 -1
- package/skills/README.md +5 -2
- package/skills/pixerate-effect-authoring/SKILL.md +7 -0
- package/skills/pixerate-effect-look-development/SKILL.md +96 -0
- package/skills/pixerate-effect-look-development/evals/fade-in.json +55 -0
- package/skills/pixerate-effect-look-development/evals/seamless-loop.json +66 -0
- package/skills/pixerate-effect-look-development/evals/subtle-preset.json +49 -0
- package/skills/pixerate-generation/SKILL.md +7 -0
- package/skills/pixerate-generation-budgeted-batch/SKILL.md +99 -0
- package/skills/pixerate-generation-budgeted-batch/evals/drafts-within-budget.json +101 -0
- package/skills/pixerate-generation-budgeted-batch/evals/right-model-for-format.json +124 -0
- package/skills/pixerate-generation-budgeted-batch/evals/vary-earlier.json +101 -0
|
@@ -20,7 +20,7 @@ export interface SkillEvalCheck extends SkillEvalToolCall {
|
|
|
20
20
|
}
|
|
21
21
|
export interface SkillEval {
|
|
22
22
|
prompt: string;
|
|
23
|
-
fixture: SpreadsheetEvalFixture | ImageEvalFixture | VectorEvalFixture | PaintEvalFixture | VideoEvalFixture | ChartEvalFixture | DiagramEvalFixture | RichTextEvalFixture | AnimationEvalFixture;
|
|
23
|
+
fixture: SpreadsheetEvalFixture | ImageEvalFixture | VectorEvalFixture | PaintEvalFixture | VideoEvalFixture | ChartEvalFixture | DiagramEvalFixture | RichTextEvalFixture | AnimationEvalFixture | GenerationEvalFixture | EffectEvalFixture;
|
|
24
24
|
checks: SkillEvalCheck[];
|
|
25
25
|
solution: SkillEvalToolCall[];
|
|
26
26
|
}
|
|
@@ -87,6 +87,26 @@ export interface AnimationEvalFixture {
|
|
|
87
87
|
/** Tool calls that build the starting scene (`set_animation_artwork_svg`, `insert_shots`), run in order. */
|
|
88
88
|
setup?: SkillEvalToolCall[];
|
|
89
89
|
}
|
|
90
|
+
export interface GenerationEvalFixture {
|
|
91
|
+
editor: 'generation';
|
|
92
|
+
/** The host's model catalogue (`ModelCapabilities` records). */
|
|
93
|
+
models: Array<Record<string, unknown>>;
|
|
94
|
+
/** Price in USD per output, by `quality` (`default` for requests without one); adds `estimate_generation`. */
|
|
95
|
+
prices?: Record<string, number>;
|
|
96
|
+
/** Earlier generations in the history: a model id and the request it ran. */
|
|
97
|
+
history?: Array<{
|
|
98
|
+
id: string;
|
|
99
|
+
model: string;
|
|
100
|
+
request: Record<string, unknown>;
|
|
101
|
+
}>;
|
|
102
|
+
}
|
|
103
|
+
export interface EffectEvalFixture {
|
|
104
|
+
editor: 'effect';
|
|
105
|
+
/** The fake effect provider's effect to author (e.g. `fake.invert`). */
|
|
106
|
+
effectId: string;
|
|
107
|
+
/** Tool calls that prepare the session, run in order. */
|
|
108
|
+
setup?: SkillEvalToolCall[];
|
|
109
|
+
}
|
|
90
110
|
/** One eval file of a skill. */
|
|
91
111
|
export interface SkillEvalFile {
|
|
92
112
|
skill: string;
|
|
@@ -20,7 +20,7 @@ export interface SkillEvalCheck extends SkillEvalToolCall {
|
|
|
20
20
|
}
|
|
21
21
|
export interface SkillEval {
|
|
22
22
|
prompt: string;
|
|
23
|
-
fixture: SpreadsheetEvalFixture | ImageEvalFixture | VectorEvalFixture | PaintEvalFixture | VideoEvalFixture | ChartEvalFixture | DiagramEvalFixture | RichTextEvalFixture | AnimationEvalFixture;
|
|
23
|
+
fixture: SpreadsheetEvalFixture | ImageEvalFixture | VectorEvalFixture | PaintEvalFixture | VideoEvalFixture | ChartEvalFixture | DiagramEvalFixture | RichTextEvalFixture | AnimationEvalFixture | GenerationEvalFixture | EffectEvalFixture;
|
|
24
24
|
checks: SkillEvalCheck[];
|
|
25
25
|
solution: SkillEvalToolCall[];
|
|
26
26
|
}
|
|
@@ -87,6 +87,26 @@ export interface AnimationEvalFixture {
|
|
|
87
87
|
/** Tool calls that build the starting scene (`set_animation_artwork_svg`, `insert_shots`), run in order. */
|
|
88
88
|
setup?: SkillEvalToolCall[];
|
|
89
89
|
}
|
|
90
|
+
export interface GenerationEvalFixture {
|
|
91
|
+
editor: 'generation';
|
|
92
|
+
/** The host's model catalogue (`ModelCapabilities` records). */
|
|
93
|
+
models: Array<Record<string, unknown>>;
|
|
94
|
+
/** Price in USD per output, by `quality` (`default` for requests without one); adds `estimate_generation`. */
|
|
95
|
+
prices?: Record<string, number>;
|
|
96
|
+
/** Earlier generations in the history: a model id and the request it ran. */
|
|
97
|
+
history?: Array<{
|
|
98
|
+
id: string;
|
|
99
|
+
model: string;
|
|
100
|
+
request: Record<string, unknown>;
|
|
101
|
+
}>;
|
|
102
|
+
}
|
|
103
|
+
export interface EffectEvalFixture {
|
|
104
|
+
editor: 'effect';
|
|
105
|
+
/** The fake effect provider's effect to author (e.g. `fake.invert`). */
|
|
106
|
+
effectId: string;
|
|
107
|
+
/** Tool calls that prepare the session, run in order. */
|
|
108
|
+
setup?: SkillEvalToolCall[];
|
|
109
|
+
}
|
|
90
110
|
/** One eval file of a skill. */
|
|
91
111
|
export interface SkillEvalFile {
|
|
92
112
|
skill: string;
|
package/package.json
CHANGED
package/skills/README.md
CHANGED
|
@@ -63,6 +63,8 @@ request like "clean up this export" finds it.
|
|
|
63
63
|
| [`pixerate-rich-text-revise`](pixerate-rich-text-revise/SKILL.md) | Rich text (`pixerate-rich-text`) | Proofreading, renaming terms with exceptions and tightening, as minimal targeted edits. |
|
|
64
64
|
| [`pixerate-animation-motion-graphics`](pixerate-animation-motion-graphics/SKILL.md) | Animation (`pixerate-animation-editor`) | One idea per shot, staggered entrances, natural easing, holds to read, fitting a length, checks and export. |
|
|
65
65
|
| [`pixerate-animation-logo-reveal`](pixerate-animation-logo-reveal/SKILL.md) | Animation (`pixerate-animation-editor`) | A short reveal built from the logo's parts, landing on the beat and ending on the held, finished logo. |
|
|
66
|
+
| [`pixerate-generation-budgeted-batch`](pixerate-generation-budgeted-batch/SKILL.md) | Generation (`pixerate-generation`) | The right model for the format, plan and estimate before spending, drafts cheap and finals once, safe retries, variations from the history. |
|
|
67
|
+
| [`pixerate-effect-look-development`](pixerate-effect-look-development/SKILL.md) | Effects (`pixerate-effect-authoring`) | Tune a look in a few moves, save it as a preset, animate with eased keyframes, seamless loops. |
|
|
66
68
|
| [`pixerate-talking-head-edit`](pixerate-talking-head-edit/SKILL.md) | Video (`pixerate-video-editor`) | Talking-head cleanup by transcript: fillers, long pauses and stutters found in one pass and cut as one plan reviewed before it applies. Owns the dialogue tools. |
|
|
67
69
|
| [`pixerate-bgm-alignment`](pixerate-bgm-alignment/SKILL.md) | Video (`pixerate-video-editor`) | Background music: beats and cuts on the beat, ducking under speech, loudness in LUFS. Owns the music tools. |
|
|
68
70
|
|
|
@@ -129,8 +131,9 @@ same change.
|
|
|
129
131
|
"vector", "width", "height", "setup" }` with commands that draw the starting art,
|
|
130
132
|
`{ "editor": "paint", "width", "height", "setup" }` `{ "editor": "video", "setup" }` or `{ "editor":
|
|
131
133
|
"chart", "setup" }` `{ "editor": "diagram", "setup" }` with tool calls,
|
|
132
|
-
`{ "editor": "rich-text", "html" }`,
|
|
133
|
-
`{ "editor": "animation", "setup" }`
|
|
134
|
+
`{ "editor": "rich-text", "html" }`,
|
|
135
|
+
`{ "editor": "animation", "setup" }`, `{ "editor": "generation", "models", "prices", "history" }`
|
|
136
|
+
(a fake host that records each generation) or `{ "editor": "effect", "effectId", "setup" }`), `checks` (a read-only
|
|
134
137
|
tool, or `run_command` with a read-only command such as `vector.list`, its `args`, what its result must match in `expect`, and `why`) and a `solution` (the
|
|
135
138
|
tool calls an expert would make). The test proves each eval: some check fails on the fixture,
|
|
136
139
|
and all pass after the solution. A model harness runs the same file with the model in place
|
|
@@ -17,6 +17,13 @@ preview frames.
|
|
|
17
17
|
|
|
18
18
|
For general error reporting and undo conventions, see `pixerate-agent-tools`.
|
|
19
19
|
|
|
20
|
+
## Workflow skills
|
|
21
|
+
|
|
22
|
+
For these jobs, load the workflow skill too: it has the method, the checks between steps and
|
|
23
|
+
the pitfalls, and uses the tools below.
|
|
24
|
+
|
|
25
|
+
- `pixerate-effect-look-development`: tune a look, save presets, eased keyframes, seamless loops.
|
|
26
|
+
|
|
20
27
|
## Working method
|
|
21
28
|
|
|
22
29
|
1. **Inspect first.** Run `effect_authoring_describe` to inspect the effect name, kind, source
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixerate-effect-look-development
|
|
3
|
+
description: The look development workflow for Pixerate effects - reading an effect's controls, finding the look with a few deliberate value changes, saving looks as named presets, animating controls with keyframes and easing, setting duration and looping for seamless cycles, previewing at key moments, and editing shader source only when controls cannot get there. Use when asked to design, tune, tweak or animate an effect, shader, filter or procedural look, make a preset or variant of a look, make an effect fade in or out, pulse or loop, or when effect_authoring_describe, effect_authoring_set_values, effect_authoring_set_keyframe or effect_authoring_save_preset are available. Load with pixerate-effect-authoring, which lists every tool.
|
|
4
|
+
metadata:
|
|
5
|
+
kind: workflow
|
|
6
|
+
reference: pixerate-effect-authoring
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Developing a look
|
|
10
|
+
|
|
11
|
+
An effect is a set of controls over a shader or procedure. A look is a set of values for those
|
|
12
|
+
controls, kept as a named preset; an animated look adds keyframed tracks over a duration. Find
|
|
13
|
+
the look with a few deliberate moves (start from a preset, change one control at a time, look),
|
|
14
|
+
save it, and animate only what should change over time.
|
|
15
|
+
|
|
16
|
+
This skill is the method. `pixerate-effect-authoring` has the full tool reference.
|
|
17
|
+
|
|
18
|
+
## Goal and quality bar
|
|
19
|
+
|
|
20
|
+
- Every value is within its control's range (`effect_authoring_describe` lists `min`, `max`,
|
|
21
|
+
`default`).
|
|
22
|
+
- The look is saved as a preset with a clear name, so it can be applied again.
|
|
23
|
+
- Animation uses as few keyframes as the motion needs, with easing (`ease-out` to arrive,
|
|
24
|
+
`ease-in-out` for a pulse); duration fits the use.
|
|
25
|
+
- A loop is seamless: `loop` on, and the animated values match at the start and the end.
|
|
26
|
+
- `issues` is empty and `previewError` is null.
|
|
27
|
+
|
|
28
|
+
## Inputs to confirm
|
|
29
|
+
|
|
30
|
+
- **The look** in words (subtle, strong, warm, glitchy) or a reference.
|
|
31
|
+
- **Static or animated**, and the duration and looping for animation.
|
|
32
|
+
- **Whether to keep** the result as a preset, and its name.
|
|
33
|
+
|
|
34
|
+
## Working method
|
|
35
|
+
|
|
36
|
+
1. **Read.** `effect_authoring_describe`: controls with ranges and defaults, current values,
|
|
37
|
+
presets, tracks, duration, loop, issues.
|
|
38
|
+
**Check:** you know which control does what.
|
|
39
|
+
2. **Start close.** `effect_authoring_apply_preset` when a preset is near the look;
|
|
40
|
+
`effect_authoring_reset_values` to start clean.
|
|
41
|
+
3. **Tune.** `effect_authoring_set_values` with only the controls you change, a few at a time;
|
|
42
|
+
`effect_authoring_view` to look.
|
|
43
|
+
**Check:** `values` in `effect_authoring_describe` are what you set; no `issues`.
|
|
44
|
+
4. **Save.** `effect_authoring_save_preset` with a descriptive `name` ("Subtle", "Warm glow").
|
|
45
|
+
**Check:** the name is in `presets`.
|
|
46
|
+
5. **Animate.** `effect_authoring_set_timing` for `duration` and `loop`; then
|
|
47
|
+
`effect_authoring_set_keyframe` per control at the times that matter, with `easing` into the
|
|
48
|
+
next keyframe. For a loop, the last keyframe's value equals the first's.
|
|
49
|
+
**Check:** `tracks` list the control with the keyframe count you meant.
|
|
50
|
+
6. **Preview** with `effect_authoring_seek` to key times and `effect_authoring_view`.
|
|
51
|
+
7. **Source last.** `effect_authoring_get_source` / `effect_authoring_set_source` only when no
|
|
52
|
+
control can produce the look; read the returned issues and fix them.
|
|
53
|
+
|
|
54
|
+
## Decision table
|
|
55
|
+
|
|
56
|
+
| Want | Approach |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| A softer or stronger version of a look | Scale the main control (strength, amount); save as a preset |
|
|
59
|
+
| A starting point | `effect_authoring_apply_preset` |
|
|
60
|
+
| Back to defaults | `effect_authoring_reset_values` |
|
|
61
|
+
| Fade in | Keyframes from the neutral value to the look, `ease-out` |
|
|
62
|
+
| Pulse or breathe | Three keyframes (rest, peak, rest), `ease-in-out`, loop on |
|
|
63
|
+
| A one-off change at a moment | Two keyframes around the moment |
|
|
64
|
+
| Remove animation from a control | `effect_authoring_clear_track` |
|
|
65
|
+
| Something no control does | Edit the source |
|
|
66
|
+
|
|
67
|
+
## Recipes
|
|
68
|
+
|
|
69
|
+
**Quarter-strength preset.** `effect_authoring_set_values` `{ values: { amount: 0.25 } }` →
|
|
70
|
+
`effect_authoring_save_preset` `{ name: "Subtle" }`.
|
|
71
|
+
|
|
72
|
+
**Fade in over 1.5 s in a 2 s effect.** `effect_authoring_set_timing` `{ duration: 2000 }` →
|
|
73
|
+
`effect_authoring_set_keyframe` `{ control: "amount", time: 0, value: 0 }` → `{ control:
|
|
74
|
+
"amount", time: 1500, value: 1, easing: "ease-out" }`.
|
|
75
|
+
|
|
76
|
+
**Seamless 3 s pulse.** `effect_authoring_set_timing` `{ duration: 3000, loop: true }` → keyframes
|
|
77
|
+
at 0 (0), 1500 (1, `ease-in-out`) and 3000 (0, `ease-in-out`).
|
|
78
|
+
|
|
79
|
+
## Pitfalls
|
|
80
|
+
|
|
81
|
+
- **Values out of range** are clamped or refused; read the control's `min` and `max`.
|
|
82
|
+
- **Many keyframes** where three would do make motion lumpy and hard to edit.
|
|
83
|
+
- **Linear easing** on organic motion looks mechanical.
|
|
84
|
+
- **Loops that jump**: the end value must equal the start value.
|
|
85
|
+
- **Overwriting a preset** by saving under an existing name; choose a new name unless replacing
|
|
86
|
+
is intended.
|
|
87
|
+
- **Editing source first**: controls are safer and keep presets working.
|
|
88
|
+
|
|
89
|
+
## Tools used
|
|
90
|
+
|
|
91
|
+
- `effect_authoring_describe`, `effect_authoring_view`, `effect_authoring_seek`: read, look and preview
|
|
92
|
+
- `effect_authoring_set_values`, `effect_authoring_reset_values`, `effect_authoring_apply_preset`: find the look
|
|
93
|
+
- `effect_authoring_save_preset`: keep the look
|
|
94
|
+
- `effect_authoring_set_timing`, `effect_authoring_set_keyframe`, `effect_authoring_remove_keyframe`, `effect_authoring_clear_track`: animate
|
|
95
|
+
- `effect_authoring_get_source`, `effect_authoring_set_source`: edit the shader when needed
|
|
96
|
+
- `effect_authoring_undo`, `effect_authoring_redo`: take back a step
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "Animate the effect fading in: no effect at the start, full strength by 1.5 seconds, in a 2-second effect.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "effect",
|
|
5
|
+
"effectId": "fake.invert"
|
|
6
|
+
},
|
|
7
|
+
"checks": [
|
|
8
|
+
{
|
|
9
|
+
"why": "a 2-second effect",
|
|
10
|
+
"tool": "effect_authoring_describe",
|
|
11
|
+
"expect": {
|
|
12
|
+
"duration": 2000
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"why": "the amount is keyframed (at least a start and an end)",
|
|
17
|
+
"tool": "effect_authoring_describe",
|
|
18
|
+
"expect": {
|
|
19
|
+
"tracks": {
|
|
20
|
+
"$some": {
|
|
21
|
+
"control": "amount",
|
|
22
|
+
"keyframes": {
|
|
23
|
+
"$min": 2
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"solution": [
|
|
31
|
+
{
|
|
32
|
+
"tool": "effect_authoring_set_timing",
|
|
33
|
+
"args": {
|
|
34
|
+
"duration": 2000
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"tool": "effect_authoring_set_keyframe",
|
|
39
|
+
"args": {
|
|
40
|
+
"control": "amount",
|
|
41
|
+
"time": 0,
|
|
42
|
+
"value": 0
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"tool": "effect_authoring_set_keyframe",
|
|
47
|
+
"args": {
|
|
48
|
+
"control": "amount",
|
|
49
|
+
"time": 1500,
|
|
50
|
+
"value": 1,
|
|
51
|
+
"easing": "ease-out"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "Make this a seamless 3-second loop that pulses: the amount goes from 0 up to 1 and back to 0 by the end.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "effect",
|
|
5
|
+
"effectId": "fake.invert"
|
|
6
|
+
},
|
|
7
|
+
"checks": [
|
|
8
|
+
{
|
|
9
|
+
"why": "3 seconds, looping",
|
|
10
|
+
"tool": "effect_authoring_describe",
|
|
11
|
+
"expect": {
|
|
12
|
+
"duration": 3000,
|
|
13
|
+
"loop": true
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"why": "keyframes at the start, the peak and the end",
|
|
18
|
+
"tool": "effect_authoring_describe",
|
|
19
|
+
"expect": {
|
|
20
|
+
"tracks": {
|
|
21
|
+
"$some": {
|
|
22
|
+
"control": "amount",
|
|
23
|
+
"keyframes": {
|
|
24
|
+
"$min": 3
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"solution": [
|
|
32
|
+
{
|
|
33
|
+
"tool": "effect_authoring_set_timing",
|
|
34
|
+
"args": {
|
|
35
|
+
"duration": 3000,
|
|
36
|
+
"loop": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"tool": "effect_authoring_set_keyframe",
|
|
41
|
+
"args": {
|
|
42
|
+
"control": "amount",
|
|
43
|
+
"time": 0,
|
|
44
|
+
"value": 0
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"tool": "effect_authoring_set_keyframe",
|
|
49
|
+
"args": {
|
|
50
|
+
"control": "amount",
|
|
51
|
+
"time": 1500,
|
|
52
|
+
"value": 1,
|
|
53
|
+
"easing": "ease-in-out"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"tool": "effect_authoring_set_keyframe",
|
|
58
|
+
"args": {
|
|
59
|
+
"control": "amount",
|
|
60
|
+
"time": 3000,
|
|
61
|
+
"value": 0,
|
|
62
|
+
"easing": "ease-in-out"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "Make a subtle version of this invert look, at about a quarter strength, and save it as a preset called 'Subtle'.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "effect",
|
|
5
|
+
"effectId": "fake.invert"
|
|
6
|
+
},
|
|
7
|
+
"checks": [
|
|
8
|
+
{
|
|
9
|
+
"why": "about a quarter strength",
|
|
10
|
+
"tool": "effect_authoring_describe",
|
|
11
|
+
"expect": {
|
|
12
|
+
"values": {
|
|
13
|
+
"amount": {
|
|
14
|
+
"$min": 0.15,
|
|
15
|
+
"$max": 0.35
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"why": "saved as a preset named Subtle",
|
|
22
|
+
"tool": "effect_authoring_describe",
|
|
23
|
+
"expect": {
|
|
24
|
+
"presets": {
|
|
25
|
+
"$some": "Subtle"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"solution": [
|
|
31
|
+
{
|
|
32
|
+
"tool": "effect_authoring_describe"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"tool": "effect_authoring_set_values",
|
|
36
|
+
"args": {
|
|
37
|
+
"values": {
|
|
38
|
+
"amount": 0.25
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"tool": "effect_authoring_save_preset",
|
|
44
|
+
"args": {
|
|
45
|
+
"name": "Subtle"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -20,6 +20,13 @@ See `pixerate-agent-tools` for errors and namespacing.
|
|
|
20
20
|
`background_ref`, `mask`, `image_ref`, `video_ref`, `audio_ref`, plus any role a model
|
|
21
21
|
declares; each model lists the roles it accepts and their min/max counts.
|
|
22
22
|
|
|
23
|
+
## Workflow skills
|
|
24
|
+
|
|
25
|
+
For these jobs, load the workflow skill too: it has the method, the checks between steps and
|
|
26
|
+
the pitfalls, and uses the tools below.
|
|
27
|
+
|
|
28
|
+
- `pixerate-generation-budgeted-batch`: the right model, plan and estimate first, drafts cheap, finals once, variations.
|
|
29
|
+
|
|
23
30
|
## Working method
|
|
24
31
|
|
|
25
32
|
1. **Discover.** `list_models` (filter with `media`) and read each candidate's `requestSchema`:
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixerate-generation-budgeted-batch
|
|
3
|
+
description: The budgeted generation workflow with Pixerate's AI generation tools - choosing a model that supports the format, planning and estimating before spending, getting approval for cost, drafting cheap and finishing expensive, generating once with an idempotency key, retrying safely, reviewing results, and redoing or varying an earlier generation from the history. Use when asked to generate, render or create images, video, audio or text with AI, make several options or variations, work within a budget or quota, redo or vary an earlier result, or batch generations, or when plan_generation, estimate_generation, generate or vary_generation are available. Load with pixerate-generation, which lists every tool.
|
|
4
|
+
metadata:
|
|
5
|
+
kind: workflow
|
|
6
|
+
reference: pixerate-generation
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Generating within a budget
|
|
10
|
+
|
|
11
|
+
Generation costs money and cannot be undone, so every spend is planned: a model that supports
|
|
12
|
+
what the deliverable needs, a request the planner accepts without silent changes, an estimate
|
|
13
|
+
the user has agreed to, then one `generate` with an idempotency key. Explore at low cost, and
|
|
14
|
+
spend on quality only for the result that will be used.
|
|
15
|
+
|
|
16
|
+
This skill is the method. `pixerate-generation` has the full tool reference and request fields.
|
|
17
|
+
|
|
18
|
+
## Goal and quality bar
|
|
19
|
+
|
|
20
|
+
- The model supports the deliverable as asked (aspect ratio, resolution, duration, references):
|
|
21
|
+
`plan_generation` shows no `adjustments` that change what the user wanted.
|
|
22
|
+
- The cost is known before spending (`estimate_generation`) and within the user's budget or
|
|
23
|
+
approved; a batch, a high count, long video or the top quality tier is always confirmed.
|
|
24
|
+
- Exactly the generations intended: one `generate` per intended result, each with its own
|
|
25
|
+
`idempotencyKey`; a retry reuses the key.
|
|
26
|
+
- Drafts are cheap (low `quality`, small `resolution`, several in one request with `count`);
|
|
27
|
+
finals are at the quality the use needs.
|
|
28
|
+
- Redos and variations start from the history (`vary_generation`, `recreate_generation`) so
|
|
29
|
+
prompt, seed and settings carry over.
|
|
30
|
+
|
|
31
|
+
## Inputs to confirm
|
|
32
|
+
|
|
33
|
+
- **The deliverable:** where it will be used (banner 16:9, story 9:16, thumbnail 1:1), how many
|
|
34
|
+
results, the medium.
|
|
35
|
+
- **Budget** or quota, and whether drafts or finals are wanted.
|
|
36
|
+
- **References** (style, character, start frame) and how strictly they must be followed.
|
|
37
|
+
|
|
38
|
+
## Working method
|
|
39
|
+
|
|
40
|
+
1. **Discover.** `list_models` (with `media`), and read each candidate's `requestSchema`.
|
|
41
|
+
**Check:** at least one model supports the format and references; pick it by schema, never
|
|
42
|
+
by name.
|
|
43
|
+
2. **Plan.** `plan_generation` with the request; read every `adjustments` and `errors` entry.
|
|
44
|
+
Use `strategy: "error"` (or `upgrade`) when exact settings matter.
|
|
45
|
+
**Check:** `ok: true` and no adjustment that changes the deliverable; otherwise another model.
|
|
46
|
+
3. **Estimate.** `estimate_generation` with the same arguments; compare alternatives (fewer
|
|
47
|
+
outputs, lower quality, smaller size) against the budget.
|
|
48
|
+
**Check:** the cost fits the budget, or the user has approved it.
|
|
49
|
+
4. **Generate once.** `generate` with the same `model`, `request`, `strategy` and a fresh,
|
|
50
|
+
descriptive `idempotencyKey`. On a timeout or transport error, call again with the identical
|
|
51
|
+
arguments and the same key.
|
|
52
|
+
**Check:** `list_generations` shows one new record per intended result.
|
|
53
|
+
5. **Review** the results with the user; keep the chosen one's id.
|
|
54
|
+
6. **Finish or vary.** For the final or a variation, `vary_generation` (or `recreate_generation`)
|
|
55
|
+
from the chosen record with only the changed `settings`; read `drift`; then estimate and
|
|
56
|
+
generate as above.
|
|
57
|
+
|
|
58
|
+
## Decision table
|
|
59
|
+
|
|
60
|
+
| Situation | Approach |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| A format only some models support | `list_models`, choose by `requestSchema`, plan with `strategy: "error"` |
|
|
63
|
+
| Several options to choose from | One request with `count`, low `quality` |
|
|
64
|
+
| Tight budget | Estimate alternatives; drafts low, one final high |
|
|
65
|
+
| A result to redo exactly | `recreate_generation`, then `generate` |
|
|
66
|
+
| The same result in another format or size | `vary_generation` with `settings` |
|
|
67
|
+
| A timeout or network error | Retry with identical arguments and the same key |
|
|
68
|
+
| A planner adjustment that changes the brief | Another model, or ask the user |
|
|
69
|
+
|
|
70
|
+
## Recipes
|
|
71
|
+
|
|
72
|
+
**One 16:9 banner.** `list_models` → `plan_generation` `{ model, request: { prompt,
|
|
73
|
+
aspectRatio: "16:9", count: 1 } }` → `estimate_generation` → `generate` with `strategy:
|
|
74
|
+
"error"` and `idempotencyKey: "banner-lighthouse-1"`.
|
|
75
|
+
|
|
76
|
+
**Four drafts under $1.** `estimate_generation` at `quality: "high"` and `"low"` with `count: 4`
|
|
77
|
+
→ pick the one within budget → one `generate`.
|
|
78
|
+
|
|
79
|
+
**The last image, wider.** `list_generations` → `vary_generation` `{ id, settings: {
|
|
80
|
+
aspectRatio: "16:9" } }` → `generate` with the returned `model` and `request`.
|
|
81
|
+
|
|
82
|
+
## Pitfalls
|
|
83
|
+
|
|
84
|
+
- **Generating to find out what a model supports.** Plan and estimate are free; generate is not.
|
|
85
|
+
- **Silent adjustments** with `nearest`: a different aspect ratio or a dropped reference; read
|
|
86
|
+
`adjustments` before spending.
|
|
87
|
+
- **A new key on retry** pays twice; reuse the key for the same generation.
|
|
88
|
+
- **Separate calls for options** that one request with `count` would make more cheaply.
|
|
89
|
+
- **Finals at draft quality**, or drafts at final quality; match quality to the stage.
|
|
90
|
+
- **Rewriting a prompt by hand** to redo a result loses seed and settings; vary from the history.
|
|
91
|
+
|
|
92
|
+
## Tools used
|
|
93
|
+
|
|
94
|
+
- `list_models`: models and their request schemas
|
|
95
|
+
- `plan_generation`: check a request and read adjustments
|
|
96
|
+
- `estimate_generation`: cost and time before spending
|
|
97
|
+
- `generate`: the one paid call, with an idempotency key
|
|
98
|
+
- `list_generations`, `get_generation`: the history and a record's details
|
|
99
|
+
- `vary_generation`, `recreate_generation`: redo or vary an earlier result
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "We need four draft options for a poster of a red fox in snow, in one request, and we can spend at most $1. Final quality can come later.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "generation",
|
|
5
|
+
"models": [
|
|
6
|
+
{
|
|
7
|
+
"id": "wide-2",
|
|
8
|
+
"name": "Wide Two",
|
|
9
|
+
"media": "image",
|
|
10
|
+
"aspectRatios": {
|
|
11
|
+
"options": [
|
|
12
|
+
"1:1",
|
|
13
|
+
"16:9",
|
|
14
|
+
"9:16"
|
|
15
|
+
],
|
|
16
|
+
"default": "1:1"
|
|
17
|
+
},
|
|
18
|
+
"quality": {
|
|
19
|
+
"options": [
|
|
20
|
+
"low",
|
|
21
|
+
"high"
|
|
22
|
+
],
|
|
23
|
+
"default": "high"
|
|
24
|
+
},
|
|
25
|
+
"count": {
|
|
26
|
+
"min": 1,
|
|
27
|
+
"max": 4
|
|
28
|
+
},
|
|
29
|
+
"seed": {
|
|
30
|
+
"min": 0,
|
|
31
|
+
"max": 99999
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"prices": {
|
|
36
|
+
"low": 0.05,
|
|
37
|
+
"high": 0.4
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"checks": [
|
|
41
|
+
{
|
|
42
|
+
"why": "one request",
|
|
43
|
+
"tool": "list_generations",
|
|
44
|
+
"expect": {
|
|
45
|
+
"total": 1
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"why": "four drafts at low quality: 4 \u00d7 $0.05, within the $1 budget (high would be $1.60)",
|
|
50
|
+
"tool": "get_generation",
|
|
51
|
+
"args": {
|
|
52
|
+
"id": {
|
|
53
|
+
"$read": "list_generations",
|
|
54
|
+
"path": "records.0.id"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"expect": {
|
|
58
|
+
"$expr": "(() => { const s = JSON.stringify(v); return /\"count\":4/.test(s) && /\"quality\":\"low\"/.test(s); })()"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
"solution": [
|
|
63
|
+
{
|
|
64
|
+
"tool": "estimate_generation",
|
|
65
|
+
"args": {
|
|
66
|
+
"model": "wide-2",
|
|
67
|
+
"request": {
|
|
68
|
+
"prompt": "A red fox in snow, poster composition",
|
|
69
|
+
"count": 4,
|
|
70
|
+
"quality": "high",
|
|
71
|
+
"aspectRatio": "9:16"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"tool": "estimate_generation",
|
|
77
|
+
"args": {
|
|
78
|
+
"model": "wide-2",
|
|
79
|
+
"request": {
|
|
80
|
+
"prompt": "A red fox in snow, poster composition",
|
|
81
|
+
"count": 4,
|
|
82
|
+
"quality": "low",
|
|
83
|
+
"aspectRatio": "9:16"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"tool": "generate",
|
|
89
|
+
"args": {
|
|
90
|
+
"model": "wide-2",
|
|
91
|
+
"request": {
|
|
92
|
+
"prompt": "A red fox in snow, poster composition",
|
|
93
|
+
"count": 4,
|
|
94
|
+
"quality": "low",
|
|
95
|
+
"aspectRatio": "9:16"
|
|
96
|
+
},
|
|
97
|
+
"idempotencyKey": "fox-poster-drafts-1"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "Generate one 16:9 banner image of a lighthouse at dusk for the website header.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "generation",
|
|
5
|
+
"models": [
|
|
6
|
+
{
|
|
7
|
+
"id": "square-1",
|
|
8
|
+
"name": "Square One",
|
|
9
|
+
"media": "image",
|
|
10
|
+
"aspectRatios": {
|
|
11
|
+
"options": [
|
|
12
|
+
"1:1"
|
|
13
|
+
],
|
|
14
|
+
"default": "1:1"
|
|
15
|
+
},
|
|
16
|
+
"quality": {
|
|
17
|
+
"options": [
|
|
18
|
+
"low",
|
|
19
|
+
"high"
|
|
20
|
+
],
|
|
21
|
+
"default": "high"
|
|
22
|
+
},
|
|
23
|
+
"count": {
|
|
24
|
+
"min": 1,
|
|
25
|
+
"max": 4
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "wide-2",
|
|
30
|
+
"name": "Wide Two",
|
|
31
|
+
"media": "image",
|
|
32
|
+
"aspectRatios": {
|
|
33
|
+
"options": [
|
|
34
|
+
"1:1",
|
|
35
|
+
"16:9",
|
|
36
|
+
"9:16"
|
|
37
|
+
],
|
|
38
|
+
"default": "1:1"
|
|
39
|
+
},
|
|
40
|
+
"quality": {
|
|
41
|
+
"options": [
|
|
42
|
+
"low",
|
|
43
|
+
"high"
|
|
44
|
+
],
|
|
45
|
+
"default": "high"
|
|
46
|
+
},
|
|
47
|
+
"count": {
|
|
48
|
+
"min": 1,
|
|
49
|
+
"max": 4
|
|
50
|
+
},
|
|
51
|
+
"seed": {
|
|
52
|
+
"min": 0,
|
|
53
|
+
"max": 99999
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"prices": {
|
|
58
|
+
"low": 0.05,
|
|
59
|
+
"high": 0.25
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"checks": [
|
|
63
|
+
{
|
|
64
|
+
"why": "exactly one generation",
|
|
65
|
+
"tool": "list_generations",
|
|
66
|
+
"expect": {
|
|
67
|
+
"total": 1
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"why": "on a model that supports 16:9, at 16:9",
|
|
72
|
+
"tool": "get_generation",
|
|
73
|
+
"args": {
|
|
74
|
+
"id": {
|
|
75
|
+
"$read": "list_generations",
|
|
76
|
+
"path": "records.0.id"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"expect": {
|
|
80
|
+
"$expr": "JSON.stringify(v).includes('\"aspectRatio\":\"16:9\"') && JSON.stringify(v).includes('wide-2')"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"solution": [
|
|
85
|
+
{
|
|
86
|
+
"tool": "list_models"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"tool": "plan_generation",
|
|
90
|
+
"args": {
|
|
91
|
+
"model": "wide-2",
|
|
92
|
+
"request": {
|
|
93
|
+
"prompt": "A lighthouse at dusk, wide banner composition, warm sky",
|
|
94
|
+
"aspectRatio": "16:9",
|
|
95
|
+
"count": 1
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"tool": "estimate_generation",
|
|
101
|
+
"args": {
|
|
102
|
+
"model": "wide-2",
|
|
103
|
+
"request": {
|
|
104
|
+
"prompt": "A lighthouse at dusk, wide banner composition, warm sky",
|
|
105
|
+
"aspectRatio": "16:9",
|
|
106
|
+
"count": 1
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"tool": "generate",
|
|
112
|
+
"args": {
|
|
113
|
+
"model": "wide-2",
|
|
114
|
+
"request": {
|
|
115
|
+
"prompt": "A lighthouse at dusk, wide banner composition, warm sky",
|
|
116
|
+
"aspectRatio": "16:9",
|
|
117
|
+
"count": 1
|
|
118
|
+
},
|
|
119
|
+
"strategy": "error",
|
|
120
|
+
"idempotencyKey": "banner-lighthouse-1"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "Make that last fox image again, the same picture but wide (16:9) for a slide.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "generation",
|
|
5
|
+
"models": [
|
|
6
|
+
{
|
|
7
|
+
"id": "wide-2",
|
|
8
|
+
"name": "Wide Two",
|
|
9
|
+
"media": "image",
|
|
10
|
+
"aspectRatios": {
|
|
11
|
+
"options": [
|
|
12
|
+
"1:1",
|
|
13
|
+
"16:9",
|
|
14
|
+
"9:16"
|
|
15
|
+
],
|
|
16
|
+
"default": "1:1"
|
|
17
|
+
},
|
|
18
|
+
"quality": {
|
|
19
|
+
"options": [
|
|
20
|
+
"low",
|
|
21
|
+
"high"
|
|
22
|
+
],
|
|
23
|
+
"default": "high"
|
|
24
|
+
},
|
|
25
|
+
"count": {
|
|
26
|
+
"min": 1,
|
|
27
|
+
"max": 4
|
|
28
|
+
},
|
|
29
|
+
"seed": {
|
|
30
|
+
"min": 0,
|
|
31
|
+
"max": 99999
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"prices": {
|
|
36
|
+
"low": 0.05,
|
|
37
|
+
"high": 0.25
|
|
38
|
+
},
|
|
39
|
+
"history": [
|
|
40
|
+
{
|
|
41
|
+
"id": "fox-1",
|
|
42
|
+
"model": "wide-2",
|
|
43
|
+
"request": {
|
|
44
|
+
"prompt": "A red fox in snow",
|
|
45
|
+
"aspectRatio": "1:1",
|
|
46
|
+
"seed": 4242,
|
|
47
|
+
"quality": "high"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"checks": [
|
|
53
|
+
{
|
|
54
|
+
"why": "one new generation",
|
|
55
|
+
"tool": "list_generations",
|
|
56
|
+
"expect": {
|
|
57
|
+
"total": 2
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"why": "the same prompt and seed, now 16:9",
|
|
62
|
+
"tool": "get_generation",
|
|
63
|
+
"args": {
|
|
64
|
+
"id": {
|
|
65
|
+
"$read": "list_generations",
|
|
66
|
+
"path": "records.0.id"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"expect": {
|
|
70
|
+
"$expr": "(() => { const s = JSON.stringify(v); return s.includes('A red fox in snow') && /\"seed\":4242/.test(s) && s.includes('\"aspectRatio\":\"16:9\"'); })()"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"solution": [
|
|
75
|
+
{
|
|
76
|
+
"tool": "list_generations"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"tool": "vary_generation",
|
|
80
|
+
"args": {
|
|
81
|
+
"id": "fox-1",
|
|
82
|
+
"settings": {
|
|
83
|
+
"aspectRatio": "16:9"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"tool": "generate",
|
|
89
|
+
"args": {
|
|
90
|
+
"model": "wide-2",
|
|
91
|
+
"request": {
|
|
92
|
+
"prompt": "A red fox in snow",
|
|
93
|
+
"aspectRatio": "16:9",
|
|
94
|
+
"seed": 4242,
|
|
95
|
+
"quality": "high"
|
|
96
|
+
},
|
|
97
|
+
"idempotencyKey": "fox-wide-1"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|