Skip to content

lasagnastack.stages.reel_pipeline.enhance

lasagnastack.stages.reel_pipeline.enhance

EnhanceStage

EnhanceStage(client: LLMClient | None = None)

Bases: Stage

Stage 5: assign visual styling and animations to the approved cut list.

Initialise with an optional LLM client.

Parameters:

Name Type Description Default
client LLMClient | None

LLM client to use. Defaults to GeminiClient.

None
Source code in src/lasagnastack/stages/reel_pipeline/enhance.py
def __init__(self, client: LLMClient | None = None) -> None:
    """Initialise with an optional LLM client.

    Args:
        client: LLM client to use. Defaults to GeminiClient.
    """
    self._client = client

completion_message

completion_message(state: PipelineState) -> str

Return the post-stage confirmation message.

Parameters:

Name Type Description Default
state PipelineState

Current pipeline state.

required

Returns:

Type Description
str

Human-readable completion string.

Source code in src/lasagnastack/stages/reel_pipeline/enhance.py
def completion_message(self, state: PipelineState) -> str:
    """Return the post-stage confirmation message.

    Args:
        state: Current pipeline state.

    Returns:
        Human-readable completion string.
    """
    assert isinstance(state, ReelPipelineState)
    rs = state.reel_style_sheet
    assert rs is not None
    styled = sum(1 for cs in rs.cut_styles if cs.caption_effect is not None)
    return (
        f"Stage 5 complete — {len(rs.cut_styles)} cuts styled, "
        f"{styled} caption effect(s) assigned. Continue to Stage 6 (render)?"
    )

run

Run the enhance stage.

Parameters:

Name Type Description Default
state PipelineState

Current pipeline state. state.cut_list must be set.

required

Returns:

Type Description
PipelineState

Updated pipeline state with reel_style_sheet set.

Source code in src/lasagnastack/stages/reel_pipeline/enhance.py
def run(self, state: PipelineState) -> PipelineState:
    """Run the enhance stage.

    Args:
        state: Current pipeline state. ``state.cut_list`` must be set.

    Returns:
        Updated pipeline state with ``reel_style_sheet`` set.
    """
    assert isinstance(state, ReelPipelineState)
    assert state.cut_list is not None
    reel_style_sheet = run(
        state.cut_list,
        state.brief_path,
        state.output_dir,
        self._client,
        state.skill_path,
    )
    return dataclasses.replace(state, reel_style_sheet=reel_style_sheet)

run

run(
    cut_list: CutList,
    brief_path: Path,
    output_dir: Path,
    client: LLMClient | None = None,
    skill_path: Path | None = None,
) -> ReelStyleSheet

Generate visual styling for the approved cut list.

Sends the cut list and brief to the LLM and returns a ReelStyleSheet describing per-cut transition types and caption effects (colour, animation, etc.). Writes reel_style.json to output_dir.

Parameters:

Name Type Description Default
cut_list CutList

Approved cut list from Stage 4.

required
brief_path Path

Path to the freeform .txt creator brief.

required
output_dir Path

Pipeline root; reel_style.json written here.

required
client LLMClient | None

LLM client to use. Defaults to GeminiClient.

None
skill_path Path | None

Optional path to a Markdown skill file injected into the prompt before the creator brief.

None

Returns:

Type Description
ReelStyleSheet

A ReelStyleSheet ready for the render stage.

Source code in src/lasagnastack/stages/reel_pipeline/enhance.py
def run(
    cut_list: CutList,
    brief_path: Path,
    output_dir: Path,
    client: LLMClient | None = None,
    skill_path: Path | None = None,
) -> ReelStyleSheet:
    """Generate visual styling for the approved cut list.

    Sends the cut list and brief to the LLM and returns a ReelStyleSheet describing
    per-cut transition types and caption effects (colour, animation, etc.).
    Writes reel_style.json to output_dir.

    Args:
        cut_list: Approved cut list from Stage 4.
        brief_path: Path to the freeform .txt creator brief.
        output_dir: Pipeline root; reel_style.json written here.
        client: LLM client to use. Defaults to GeminiClient.
        skill_path: Optional path to a Markdown skill file injected into the
            prompt before the creator brief.

    Returns:
        A ReelStyleSheet ready for the render stage.
    """
    if client is None:
        client = GeminiClient()

    prompt = _build_prompt(cut_list, brief_path, skill_path)
    captioned = sum(1 for cut in cut_list.cuts if cut.caption)
    log.info("enhance_start", cuts=len(cut_list.cuts), captioned=captioned)

    reel_style_sheet: ReelStyleSheet = client.generate(
        prompt, ReelStyleSheet, temperature=0.5
    )

    io.write_json(reel_style_sheet, io.reel_style_path(output_dir))
    log.info("enhance_done", cut_styles=len(reel_style_sheet.cut_styles))
    return reel_style_sheet