Nodes/ComfyUI-OldTimeRadio/ LPL Script Writer (v2.0)
ComfyUI Node

LPL Script Writer (v2.0)

A ComfyUI node in OldTimeRadio with 34 inputs and 5 outputs.

By jbrick2070·Created 5 months ago·Updated about 4 hours ago· 7
LPL Script Writer (v2.0)
    • script_text
    • script_json
    • news_used
    • estimated_minutes
    • technical_model
    episode_title
    num_characters2
    creative_writing_modelmistralai/Mistral-Nemo-Instruct-2407
    technical_modelmistralai/Mistral-Nemo-Instruct-2407
    custom_premise
    include_act_breakstrue
    act_count3
    creativitybalanced
    perfect_run_spacesaverfalse
    min_p0.05
    repetition_penalty1.03
    max_new_tokens_cap200
    lemmy_cameoroll (~11% chance)
    use_exchangefalse
    enable_production_stage3_validatorsfalse
    news_briefs_requiredtrue
    openrouter_slot_a_model(enable OpenRouter)
    openrouter_slot_b_model(enable OpenRouter)
    comfy_slot_a_model(enable Comfy Credits)
    comfy_slot_b_model(enable Comfy Credits)
    refine_target_gradeOff
    story_scaffoldauto
    source_bankscifi_news_pro
    visual_stylesci_fi_radio
    google_api_slot_a_model(select Google API model)
    google_api_slot_b_model(select Google API model)
    source_ref
    llm_devicecuda
    llm_attn_implsdpa
    llm_quant_policybnb_nf4
    llm_vram_ceiling_gb14.5
    gguf_n_ctx4096
    gguf_quantQ8_0
    gate_in
    CategoryOldTimeRadio

    Inputs (34)

    NameTypeDefaultDescription
    episode_titleSTRINGOptional episode title override. Stamped at ledger.meta.episode_title so SignalLostVideo picks it up directly without title-chain fallback. Leave blank to let the outline supply a title.
    num_charactersINT21–10REQUESTED number of speaking characters (plus ANNOUNCER bookends). 1 = monologue/diary mode. This is a request, not a cap: a story that genuinely needs another voice may use one. The real ceiling is the voice stock, because two characters never share a voice.
    creative_writing_modeloptCOMBOmistralai/Mistral-Nemo-Instruct-2407LLM for the creative/narrative passes (outline, cast, dialogue composer, polish, style picker invention). Mistral-Nemo is the C7 byte-identical audio baseline. Suffix tags like [LOCAL HF], [LOCAL GGUF], and [NOT DOWNLOADED] are stripped before HF lookup. To use a remote OpenRouter model, set OPENROUTER_API_KEY and pick OpenRouter A/B (see docs/openrouter-setup.md).
    technical_modeloptCOMBOmistralai/Mistral-Nemo-Instruct-2407LLM for the technical/structured passes (JSON validators, GBNF grammar output, reviewer verdicts, cast contract checks, format normalization, news interpreter). Default matches creative_writing_model so the single-model audio baseline holds; pick a smaller model here when you want Slot 1 != Slot 2 routing for VRAM headroom. To use a remote OpenRouter model, set OPENROUTER_API_KEY and pick OpenRouter A/B (see docs/openrouter-setup.md).
    custom_premiseoptSTRINGEmpty (default) -> RSS fetcher pulls a fresh real-world science headline as the episode seed. Non-empty -> uses your text verbatim as the seed and skips RSS entirely. Use cases for the override: - test a specific story idea - reproduce a previous run with controlled inputs - work offline / skip RSS when the network is slow.
    include_act_breaksoptBOOLEANtrueWhen ON (default), the outline LLM is told to plan music_inter beats between acts so the episode breathes between scenes. When OFF, the outline LLM is told the episode is one continuous flow with no music_inter beats. Outline schema (Beat.speaker_role) supports music_inter either way; this widget just tells the LLM whether to use it. Wired into the outline prompt via the `Target episode shape` line 2026-05-10.
    act_countoptCOMBO3Number of acts, 1-6. This is the only knob that shapes episode length, and your pick is always honoured. More acts means a story with more turns in it -- each act gets its own beat skeleton and its own pass. The episode ends up as long as the story needs; length is reported afterwards, never requested up front. 1 -> a single scene 2 -> setup, resolution 3 -> setup, complication, resolution 8 -> the full arc, through crisis and climax
    creativityoptCOMBObalancedCreativity dial — overrides raw temperature + top_p with curated presets: safe & tight -> temp 0.60, top_p 0.90 balanced -> temp 0.85, top_p 0.95 wild & rough -> temp 0.92, top_p 0.98 maximum chaos -> temp 0.95, top_p 0.99 (BUG-014: temp > 1.0 caused format collapse, so 'maximum chaos' caps at 0.95.)
    perfect_run_spacesaveroptBOOLEANfalseDEPRECATED 2026-08-08 -- NO-OP sentinel. Widget preserved to keep positional layout stable (BUG-LOCAL-097). Formerly triggered OTR_RTXUpscale's per-episode intermediate cleanup, which was retired with the RTX-VSR node (queue item 8; nodes/rtx_upscale.py removed). Setting this True has no effect.
    min_poptFLOAT0.050–0.5min_p sampling threshold (HuggingFace transformers). 0.05 (default) cuts the long tail of low-probability tokens that produce the occasional off-key word in an otherwise good line on 7B-14B small local LLMs (Mistral-Nemo, Gemma-2, Qwen2.5). Tier 2 fix #17 (2026-05-11) flipped this from 0.0 — preserving an unvalidated baseline is not preservation. 0.0 = disabled. Aggressive: 0.10. Pairs with the existing creativity top_p — when both are active the tail cut is the union.
    repetition_penaltyoptFLOAT1.031–1.2Repetition penalty for HuggingFace transformers generate. 1.03 (default) is gentle and helps small local LLMs avoid looping on character names / high-frequency tokens in short outputs. Tier 2 fix #17 (2026-05-11) flipped this from 1.0 — preserving an unvalidated baseline is not preservation. 1.0 = disabled. Values above 1.08 commonly damage short generations on the 7B-14B class.
    max_new_tokens_capoptINT20040–400Per-line max_new_tokens ceiling on the composer hot-path. Default 200 preserves current behavior. The Attempt-1 uses this cap directly; attempt-2 retry uses the full cap. It is a per-CALL decode budget, not a length target -- it was scaled from target_words until 2026-08-14, which made it a token ceiling derived from a word request.
    lemmy_cameooptCOMBOroll (~11% chance)LEMMY easter-egg cameo -- the genial Cockney communications officer who occasionally joins the cast. roll (~11% chance) -- default; LEMMY may appear at random. The roll uses OS entropy and is NOT tied to the seed (BUG-LOCAL-260), so a fixed seed no longer pins him on or off. always include -- force LEMMY into the cast this run. never include -- keep LEMMY out this run. 'always' / 'never' consume one of the num_characters slots, exactly as a natural roll does.
    use_exchangeoptBOOLEANfalseBuild 4 grouped-exchange dialogue. OFF (default) keeps the per-beat composer; PD1 byte-identity holds. ON groups 2-3 consecutive voiced beats and renders each as one exchange (compose_exchange) with the Build 3 contracts + Build 2 Tier-A check; one block per slot, one repair-by-group, then legacy fallback. ANNOUNCER/MUSIC + trailing singletons keep their pass. Any failure falls back to legacy per beat -- audio is never blocked. Validate VRAM <= 14.5 GB + zero slot drift on a live N=3 run.
    enable_production_stage3_validatorsoptBOOLEANfalseOFF (default) preserves PD1 byte-identity on the legacy path -- no validators run. ON wires Stage 3 validators (speaker-leak, banned-phrase, length, pronoun, on-beat) into the production compose_line for every character dialogue beat. TELEMETRY ONLY: findings are stamped on meta.lines[].validation_findings and NOTHING is regenerated, rerolled or rejected -- an audit may never fail a story for length, language, style or quality. Costs no extra LLM call at any severity. Flip ON for production smokes; OFF for the byte-identity regression run.
    news_briefs_requiredoptBOOLEANtrueON (default): typed non-quality source-interpreter failures stay fail-loud. OFF: the legacy branch may degrade to raw news_seed. Rejected/malformed LLM briefs do not reach this switch: they rotate through fresh technical/creative repair passes and end at a validated bank-specific source floor.
    openrouter_slot_a_modeloptCOMBO(enable OpenRouter)OpenRouter model slug bound to the 'openrouter:slot-a' handle (the creative slot). Passive: only used when creative_writing_model is set to 'openrouter:slot-a'. Choices are the curated '~family-latest' aliases (which resolve upstream, so they never go stale) plus your favourites from the cached catalog; run the refresh script or set OTR_OPENROUTER_FULL_CATALOG=1 to browse every cached slug. Shows '(enable OpenRouter)' until OPENROUTER_API_KEY is set. A saved slug is preserved even if absent from a stale cache. See docs/openrouter-setup.md.
    openrouter_slot_b_modeloptCOMBO(enable OpenRouter)OpenRouter model slug bound to the 'openrouter:slot-b' handle (the technical slot). Passive: only used when technical_model is set to 'openrouter:slot-b'. Choices are the curated '~family-latest' aliases plus your favourites from the cached catalog; shows '(enable OpenRouter)' until remote is enabled. OTR_OPENROUTER_SLOT_B_REQUIRE_JSON=1 limits the CACHED CATALOG rows to structured-output models; the curated aliases are policy, not catalog discovery, so they are still offered -- check the family before binding one here. See docs/openrouter-setup.md.
    comfy_slot_a_modeloptCOMBO(enable Comfy Credits)Comfy Credits model slug bound to the 'comfy:slot-a' handle (the creative slot). Passive: only used when creative_writing_model is set to 'comfy:slot-a'. Choices are the pinned ComfyUI partner-node catalog; shows '(enable Comfy Credits)' until OTR_ENABLE_COMFY_CREDITS=1 and a Comfy account with credits is logged in. Credit-billed. See docs/comfy-credits-setup.md.
    comfy_slot_b_modeloptCOMBO(enable Comfy Credits)Comfy Credits model slug bound to the 'comfy:slot-b' handle (the technical slot). Passive: only used when technical_model is set to 'comfy:slot-b'. Choices are the pinned ComfyUI partner-node catalog; shows '(enable Comfy Credits)' until the lane is enabled. Credit-billed. See docs/comfy-credits-setup.md.
    refine_target_gradeoptCOMBOOffIterative story-REVISION loop (v1): keep REWRITING the story (revising the existing draft) until it reaches this grade, then ship -- or stop at a hard cap of 5 passes. Off = disabled (single pass, the default, byte-identical). B (~75) is a reachable target for a local model; A (~90) may never be hit (it then ships the last revision). Local-only. The env vars OTR_STORY_REFINE_BAR / OTR_STORY_REFINE_PASSES override this widget for headless runs.
    story_scaffoldoptCOMBOautoHow much the radio-drama SCAFFOLD shapes the story. off = a story drawn straight from the news seed (the base prompt only -- no style catalog, no climax-shape grammar, no grounding gate; the writer's own take). on = the news story shaped by ONE of the ~100 radio-drama styles (varied climax + ending + the premise-grounding body gate). auto (default) = follow the OTR_ENABLE_STYLE_GRAMMAR env / its default (ON). on/off override that env for THIS run.
    source_bankoptCOMBOscifi_news_proStory-path SOURCE BANK (multi-modal story schema). Selects which registered story pack supplies the pack-routed creative prompts and which lane the episode runs. scifi_news_pro = the local default sci-fi bank, an LLM-first multipass lane using the configured model slots. Each lane is an INDEPENDENT bank (own pack + bank metadata). The only non-runnable row is '+ Add Your Own' (custom_source_bank) -- picking it FAILS LOUD before any story work (no fallback), with its guide_ref naming the real path: author a bundle under user_packs/source_banks/, run 'otr_check bank <path> --activate', restart, and your bank joins this list as its own entry (contract: docs/EXTENDING_OTR.md). A bank's own default_story_model picks its story pack -- there is no separate pack widget. ROLL: pick 'roll (any eligible bank)' to let the run choose for you, uniformly, from every runnable bank whose lane can build the requested shape. This is INDEPENDENT of the visual_style roll -- rolling one does not roll the other. The choice is recorded in the ledger at meta.bank_roll (selected id, seed, and the exact pool it drew from); set OTR_BANK_SEED to replay a past roll. A pinned source_ref cannot be combined with the roll -- a pinned source belongs to one bank.
    visual_styleoptCOMBOsci_fi_radioVISUAL STYLE (multi-modal story schema). Rewrites ONLY the downstream still/video prompt style language (tails); story content is untouched. sci_fi_radio = the production look (default, byte-identical). anime / cartoon / paper_origami / archival_documentary / recur_frac / shakespeare_stage_realism / storybook_engraving / video_art are live immediately. Unknown id fails LOUD before any story work. ROLL: pick 'roll (any style)' to let the run choose the look for you, uniformly, from every registered style (they are all fully live, so there is nothing to exclude). This is a SEPARATE randomizer from the source_bank roll -- either, both, or neither. The choice is recorded at meta.style_roll; set OTR_VISUAL_STYLE_SEED to replay a past roll (that is its own seed -- OTR_STYLE_SEED is the narrative arc-shape seed and is unrelated).
    google_api_slot_a_modeloptCOMBO(select Google API model)Google Gemini API model bound to 'google_api:slot-a' (creative slot). Env-only auth: OTR_GOOGLE_API_KEY, GEMINI_API_KEY, or GOOGLE_API_KEY. Passive until the main model dropdown selects google_api:slot-a. No local fallback.
    google_api_slot_b_modeloptCOMBO(select Google API model)Google Gemini API model bound to 'google_api:slot-b' (technical slot). Use a structured-output capable text model for JSON passes. Env-only auth, no local fallback.
    source_refoptSTRINGOptional source reference for source-bank lanes (for example a public-domain URL/id/title). Blank uses the bank's default source selection. This is not a fallback; unsupported nonblank references must fail loud in the consuming bank.
    llm_deviceoptCOMBOcudaEXPLICIT LLM device (platform profile value). No auto-detect; an unavailable device fails loud at load.
    llm_attn_imploptCOMBOsdpaAttention implementation for the transformers lane (the FA2 auto-probe is gone). sdpa = the proven baseline.
    llm_quant_policyoptCOMBObnb_nf4Quantization for the transformers lane. bnb lanes are OFF on ROCm/MPS/CPU tiers (missing bitsandbytes fails loud).
    llm_vram_ceiling_gboptFLOAT14.50–96Pre-download VRAM-fit ceiling (GB). 0 DISABLES the gate (cpu tier only).
    gguf_n_ctxoptINT4096512–32768GGUF lane context window. NO silent downgrade: a window that does not fit free VRAM fails loud.
    gguf_quantoptCOMBOQ8_0GGUF artifact quant (filename + expected size come from the artifact table).
    gate_inoptSTRINGOrdering/validation signal (wire OTR_WorkflowValidator.validation_report).

    Outputs (5)

    NameTypeDescription
    script_textSTRING
    script_jsonSTRING
    news_usedSTRING
    estimated_minutesINT
    technical_modelSTRING