File size: 7,597 Bytes
513ea7b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
from __future__ import annotations

from dataclasses import dataclass
from typing import Literal

from .backends.image import STYLE_PROFILES, compose_flux_prompt

SceneCategory = Literal["animal", "human", "object", "environment"]


@dataclass(frozen=True)
class ForestScene:
    slug: str
    category: SceneCategory
    prompt: str


FOREST_SCENES = (
    ForestScene(
        "fox-threshold",
        "animal",
        "a gentle red fox pausing at the edge of a fern-lined path",
    ),
    ForestScene(
        "listening-owl",
        "animal",
        "a round barn owl listening from a low mossy branch",
    ),
    ForestScene(
        "steady-deer",
        "animal",
        "a young deer standing calmly between silver birch trees",
    ),
    ForestScene(
        "brave-snail",
        "animal",
        "a tiny snail crossing a dew-covered fern at dawn",
    ),
    ForestScene(
        "singing-wren",
        "animal",
        "a small wren singing beside loose woodland flowers",
    ),
    ForestScene(
        "river-otter",
        "animal",
        "a river otter holding one smooth stone beside quiet reeds",
    ),
    ForestScene(
        "thoughtful-badger",
        "animal",
        "a thoughtful badger beside a lantern-shaped mushroom",
    ),
    ForestScene(
        "patient-hare",
        "animal",
        "a patient brown hare resting beneath arching grasses",
    ),
    ForestScene(
        "moonlit-moth",
        "animal",
        "a luna moth hovering near moonlit foxgloves",
    ),
    ForestScene(
        "walking-turtle",
        "animal",
        "a small woodland turtle moving between clover and stones",
    ),
    ForestScene(
        "person-open-window",
        "human",
        "an adult seen from behind opening a window to pale morning light",
    ),
    ForestScene(
        "person-blank-notebook",
        "human",
        "an adult seated at a wooden desk with an open blank notebook",
    ),
    ForestScene(
        "person-forked-path",
        "human",
        "a small human figure viewed from behind at a gentle fork in a path",
    ),
    ForestScene(
        "person-train-platform",
        "human",
        "a quiet adult figure waiting on a misty train platform with one bag",
    ),
    ForestScene(
        "person-moving-box",
        "human",
        "an adult carrying one moving box toward a sunlit doorway",
    ),
    ForestScene(
        "person-footbridge",
        "human",
        "a side-view figure taking one step across a narrow wooden footbridge",
    ),
    ForestScene(
        "person-doorway",
        "human",
        "a calm adult silhouette standing in an open doorway between two rooms",
    ),
    ForestScene(
        "person-seedling",
        "human",
        "hands gently watering a small seedling on a windowsill",
    ),
    ForestScene(
        "person-rain-shelter",
        "human",
        "an adult seen from the side resting on a bench beneath a rain shelter",
    ),
    ForestScene(
        "person-dawn-hill",
        "human",
        "a distant human figure standing on a low hillside at dawn",
    ),
    ForestScene(
        "lantern-crossroads",
        "object",
        "a small glowing lantern placed where two woodland paths meet",
    ),
    ForestScene(
        "map-compass",
        "object",
        "an unfolded map and simple compass resting on a wooden table",
    ),
    ForestScene(
        "open-notebook",
        "object",
        "an open blank notebook beside a pencil and one pressed leaf",
    ),
    ForestScene(
        "stepping-stones",
        "object",
        "four smooth stepping stones crossing a narrow stream",
    ),
    ForestScene(
        "warm-cup",
        "object",
        "a warm ceramic cup sending a thin curl of steam into morning light",
    ),
    ForestScene(
        "woven-thread",
        "object",
        "loose green and gold threads gradually woven into one calm pattern",
    ),
    ForestScene(
        "key-and-door",
        "object",
        "a simple brass key resting beside a small unopened wooden door",
    ),
    ForestScene(
        "paper-boat",
        "object",
        "a single paper boat floating on still water beneath willow reflections",
    ),
    ForestScene(
        "balanced-stones",
        "object",
        "three imperfect river stones balanced beside soft grasses",
    ),
    ForestScene(
        "empty-chair-light",
        "object",
        "an empty wooden chair in a quiet patch of warm window light",
    ),
    ForestScene(
        "winding-path",
        "environment",
        "a winding path disappearing gently through tall ferns and morning mist",
    ),
    ForestScene(
        "river-crossing",
        "environment",
        "a shallow river crossing with stones visible beneath clear water",
    ),
    ForestScene(
        "room-at-dawn",
        "environment",
        "a quiet room at dawn with curtains moving beside an open window",
    ),
    ForestScene(
        "city-garden",
        "environment",
        "a small green garden between quiet city buildings after rain",
    ),
    ForestScene(
        "misty-platform",
        "environment",
        "an empty train platform fading softly into early morning mist",
    ),
    ForestScene(
        "clearing-after-rain",
        "environment",
        "a forest clearing just after rain with one bright opening in the clouds",
    ),
    ForestScene(
        "hillside-trail",
        "environment",
        "a gradual hillside trail curving toward a pale open horizon",
    ),
    ForestScene(
        "staircase-light",
        "environment",
        "a simple staircase with warm light falling across the next three steps",
    ),
    ForestScene(
        "canopy-opening",
        "environment",
        "a dark green canopy opening into a circle of soft sky",
    ),
    ForestScene(
        "shoreline-horizon",
        "environment",
        "a calm shoreline where fading clouds meet a wide quiet horizon",
    ),
)

# Compatibility alias for callers that used the v1 name.
FOREST_SUBJECTS = FOREST_SCENES

TRAINED_STYLE_IDS = (
    "watercolor",
    "paper_cut",
    "moonlit_gouache",
    "botanical_ink",
)


def build_style_records(
    *,
    samples_per_style: int = 40,
    base_seed: int = 9000,
) -> list[dict[str, str | int]]:
    if not 1 <= samples_per_style <= len(FOREST_SCENES):
        raise ValueError(f"samples_per_style must be between 1 and {len(FOREST_SCENES)}")

    records: list[dict[str, str | int]] = []
    for style_offset, style in enumerate(TRAINED_STYLE_IDS):
        profile = STYLE_PROFILES[style]
        for scene_index, scene in enumerate(FOREST_SCENES[:samples_per_style]):
            seed = base_seed + style_offset * 1000 + scene_index
            prompt = compose_flux_prompt(
                scene.prompt,
                style=style,  # type: ignore[arg-type]
                seed=seed,
            )
            records.append(
                {
                    "style": style,
                    "trigger": profile.trigger,
                    "category": scene.category,
                    "subject": scene.slug,
                    "seed": seed,
                    "prompt": prompt,
                    "text": (
                        f"{profile.trigger}, {scene.prompt}, "
                        f"{profile.label.lower()} storybook scene"
                    ),
                    "file_name": (
                        f"{scene_index:03d}-{scene.category}-{scene.slug}.png"
                    ),
                }
            )
    return records