Use when optimizing prompts for AI video storyboard pipelines, implementing dodge layers for content filters, adding continuity locks for retry consistency, creating custom PromptSkill modules, or debugging prompt-related quality issues in multi-pass LangGraph pipelines. Triggers include "dodge layer", "filter bypass", "continuity lock", "prompt modular", "storyboard pipeline", "PromptSkill", "分镜提示词".
Prompt engineering toolkit for 4-pass AI video storyboard pipelines (LangGraph). Covers modular rule composition, filter bypass, and retry consistency.
Pipeline (LangGraph StateGraph)
├── Pass 1: Scene ← core + style + dodge
├── Pass 2: Character ← core + physics + dodge
├── Pass 3: Shot ← core + dialogue + physics + dodge + continuity*
├── Pass 4: Verify ← core + dialogue + dodge
└── Retry (score<10) ← prepareRetry → continuity activates
Post-process: sanitizer.ts applies regex replacement + dodge layer injection on final output (covers desc, act, motive in seq).
Each shot in seq contains:
| Field | Type | Source |
|---|---|---|
id | string | Pass 3 (shot generation) |
desc | string | 5-part: 景别|动作|台词|心理→外化|运镜 |
act | string? | 演出动作(纯动作,不含特效) |
fx | string|null? | 特效:风/烟/光/粒子 |
motive | string? | 动机:这个动作外化了什么心理 |
act/fx/motive are optional fields populated by the 4-Pass Pipeline's aggregate layer. The single-pass LangChain path only produces {id, desc}.
interface PromptSkill {
id: string
rules: string | ((state: PipelineStateSlice) => string)
appliesTo: PassType[] // 'scene' | 'character' | 'shot' | 'verify'
priority: number // lower = earlier in prompt
}
| id | type | appliesTo | priority | content |
|---|---|---|---|---|
| core | static | all | 0 | lighting, color, lens, snapshot, micro-expression, Z-axis, duration |
| dialogue | static | shot, verify | 10 | character name + dialogue verbatim extraction |
| physics | static | character, shot | 10 | physical desc, motion vectors, quantification |
| style | static | scene | 10 | color palette, light source, shadow depth |
| dodge | static | all | 20 | D1-D8 artistic obfuscation rules |
| continuity | dynamic | shot | 30 | retry reference frame lock (activates only when retryFeedback exists) |
import { BUILTIN_SKILLS, type PromptSkill } from './prompt-skills'
const horrorSkill: PromptSkill = {
id: 'horror',
rules: `Horror Rules:
- Shadow depth > 85%, single cold light source
- Sound: low-freq drone 30-50Hz + sudden silence gaps
- fg must have occluder (door frame/fingers/bars) for voyeuristic framing`,
appliesTo: ['scene', 'shot'],
priority: 15
}
const service = new StoryboardPipelineService(config, [...BUILTIN_SKILLS, horrorSkill])
Two independent layers — both required:
Layer 1 (Prompt-level): D1-D8 rules in system prompt guide LLM to generate safe text. See references/dodge-patterns.md.
Layer 2 (Post-process): sanitizer.ts runs regex replacement + dodge modifier injection on final output.
CRITICAL CONSTRAINTS:
injectDodgeLayer appends to desc with | separator — never insert mid-stringActivates ONLY during retry (when state.retryFeedback is non-empty).
previousShots stores { id, desc } only — NOT full ShotData.
| Data | Est. tokens | Note |
|---|---|---|
9 shots {id, desc} | ~800 | 5-part desc avg 80 tokens |
| Character anchors | ~200 | [name] anchor format |
| Lock template | ~100 | Fixed text |
| Total | ~1100 | ~13% of 8192 max |
Do NOT expand PreviousShot to full ShotData — token budget would jump to ~3000+ and crowd out generation context. The desc field contains the 5-part shot specification which is sufficient for continuity reference.
prepareRetry saves shots.map(s => ({id, desc})) as previousShotsbuildContinuityLock(state) generates lock rules with character anchors + reference framesSee references/continuity-lock.md for implementation details.
| Mistake | Why it's wrong | Correct approach |
|---|---|---|
| Expanding PreviousShot to full ShotData | Token budget ~3000+ crowds generation context | Keep {id, desc} only (~1100 tokens) |
Adding lockedShotIds to PipelineState | Over-engineering; retryFeedback already identifies broken shots | Let continuity lock rule handle it |
| Making dodge skill dynamic (function) | Unnecessary complexity; static D1-D8 + sanitizer is sufficient | Keep dodge static, add new skills for special cases |
| Platform-specific replacement rules | No validated evidence of differing filter behavior | Use universal rules until proven insufficient |
| Putting code-level shot enforcement in generateShots | Corrupts LangGraph node purity; side effects in node functions | Keep nodes pure, enforcement belongs in post-process |