| """ | |
| frame_metadata.py — Pydantic schemas for LLM structured output. | |
| Used by Outlines to enforce valid JSON generation. | |
| Design note (schema compaction): | |
| The LLM never echoes word indices. Each Frame carries a `count` (how many | |
| of the remaining words belong to this line). Indices are reconstructed | |
| sequentially on our side, which makes contiguity, ordering and full coverage | |
| true *by construction* — the model cannot produce an invalid grouping, and | |
| the JSON it must emit is a fraction of the old `word_indices` list size. | |
| The LLM's job is just two simple per-line decisions: `count` (line split) | |
| and `frame_animation` (one mood-matching effect for the whole line). | |
| """ | |
| from enum import Enum | |
| from typing import List | |
| from pydantic import BaseModel, Field | |
| class FrameAnim(str, Enum): | |
| none = "none" | |
| zoom_in = "zoom_in" | |
| zoom_out = "zoom_out" | |
| pan_left = "pan_left" | |
| pan_right = "pan_right" | |
| flash = "flash" | |
| fade_to_black = "fade_to_black" | |
| class Frame(BaseModel): | |
| count: int = Field(description="How many of the remaining words (in order) belong to this line") | |
| frame_animation: FrameAnim = FrameAnim.none | |
| class SongFrames(BaseModel): | |
| frames: List[Frame] | |