16 KiB
Anime Story Bible – Design & Implementation (Story Writer SSOT)
This document is the single source of truth for the Anime Story Bible in Story Writer: what it is, where it lives in the codebase, how it is generated, and how it is used across outline, story text, images, and motion/animation.
1. Core Concepts
-
Anime Story Bible: Structured description of characters, world, and visual style for anime-style stories. It is designed to be:
- Stable across the whole story (single bible per story)
- Machine-readable (Pydantic/TypeScript models)
- Reusable for text, image, and video prompts
-
Design Goals
- Maintain character consistency across scenes and media
- Maintain world rules (tech/magic, constraints) throughout the narrative
- Maintain a coherent anime visual style across images and motion clips
- Allow future reuse for other story templates and media pipelines
2. Data Model (Backend & Frontend)
2.1 Backend Models
File: story_models.py
Key classes:
AnimeCharacterAnimeWorldAnimeVisualStyleAnimeStoryBible
They are defined as:
-
AnimeCharacterid: stable snake_case identifiernameage_rangerole(protagonist, antagonist, mentor, etc.)look(key visual details)outfit_palettepersonality_tags: List[str]
-
AnimeWorldsetting(locations and general world description)era(near-future, alt 1990s, etc.)tech_or_magic_levelcore_rules: List[str](constraints and consistent rules)
-
AnimeVisualStylestyle_preset(anime_manga, cinematic_anime, cozy_slice_of_life, etc.)camera_stylecolor_moodlightingline_styleextra_tags: List[str]
-
AnimeStoryBiblestory_id?: strmain_cast: List[AnimeCharacter]world: AnimeWorldvisual_style: AnimeVisualStyle
The bible is attached to:
StorySetupOption.anime_bible: Optional[AnimeStoryBible]StoryOutlineResponse.anime_bible: Optional[AnimeStoryBible]
Additionally, for downstream usage:
StoryGenerationRequest.anime_bible: Optional[Dict[str, Any]]StoryContinueRequest.anime_bible: Optional[Dict[str, Any]]
This allows story-start and continuation to receive a JSON-serializable bible blob without strict coupling to the AnimeStoryBible class.
2.2 Frontend Models
File: storyWriterApi.ts
Types mirror the backend:
AnimeCharacterAnimeWorldAnimeVisualStyleAnimeStoryBible
The bible flows through:
StoryOutlineResponse.anime_bible?: AnimeStoryBibleStoryGenerationRequest.anime_bible?: AnimeStoryBible | nullStoryStartRequestandStoryContinueRequest(viaStoryGenerationRequest)
State layer:
File: useStoryWriterState.ts
StoryWriterState.animeBible: any | nullsetAnimeBiblesetter- Persisted and restored via
localStorage:- Saved under
animeBiblekey in the serialized state - Ensures the bible survives refreshes
- Saved under
3. Bible Lifecycle & Generation
3.1 Generation Source
The Anime Story Bible is generated in the story setup / outline pipeline on the backend:
- The story setup step produces a single
StorySetupOptionenriched withanime_biblewhen the selected template is anime-focused. - The outline generation step (
StoryOutlineResponse) carriesanime_bibleso the UI can display it and store it in Story Writer state.
SSOT:
- Models: story_models.py
- Outline response:
StoryOutlineResponse.anime_bible
3.2 Frontend Storage and Access
The frontend receives anime_bible from StoryOutlineResponse and:
- Stores it in
StoryWriterState.animeBible - Persists it in
localStoragewith the rest of the story writer state - Exposes it to:
- Director chip / bible viewer UI
- Story generation (start/continue)
- Scene animation (via
story_context)
Key locations:
- State hook: useStoryWriterState.ts
- Outline phase UI: StoryOutline.tsx
4. Integration Points (Current Implementation)
This section documents how the Anime Story Bible is currently used across the Story Writer pipelines.
4.1 Story Text Generation (Start & Continue)
4.1.1 Requests
Frontend:
-
StoryGenerationRequest(base)- Now includes
anime_bible?: AnimeStoryBible | null
- Now includes
-
getRequest()inuseStoryWriterStateaddsanime_bibleautomatically:
Story start:
StoryWriting.handleGenerateStart:- Builds
request = state.getRequest() - Calls
storyWriterApi.generateStoryStart(premise, outline, request) - StoryWriting.tsx
- Builds
Story continue:
StoryWriting.handleContinue:request = state.getRequest()- Builds
continueRequest = { ...request, premise, outline, story_text } - Calls
storyWriterApi.continueStory(continueRequest) - StoryWriting.tsx
Backend:
StoryGenerationRequest/StoryContinueRequestincludeanime_bible: Optional[Dict[str, Any]]
4.1.2 Routing Layer
File: api/story_writer/routes/story_content.py
-
generate_story_start:story_start = story_service.generate_story_start( premise=request.premise, outline=outline_data, persona=request.persona, story_setting=request.story_setting, character_input=request.character_input, plot_elements=request.plot_elements, writing_style=request.writing_style, story_tone=request.story_tone, narrative_pov=request.narrative_pov, audience_age_group=request.audience_age_group, content_rating=request.content_rating, ending_preference=request.ending_preference, story_length=story_length, anime_bible=getattr(request, "anime_bible", None), user_id=user_id, ) -
continue_story:continuation = story_service.continue_story( premise=request.premise, outline=outline_data, story_text=request.story_text, persona=request.persona, story_setting=request.story_setting, character_input=request.character_input, plot_elements=request.plot_elements, writing_style=request.writing_style, story_tone=request.story_tone, narrative_pov=request.narrative_pov, audience_age_group=request.audience_age_group, content_rating=request.content_rating, ending_preference=request.ending_preference, anime_bible=getattr(request, "anime_bible", None), story_length=story_length, user_id=user_id, )
4.1.3 Service Layer Prompts
File: story_content.py
-
StoryContentMixin.generate_story_start(...)now acceptsanime_bible: Optional[Dict[str, Any]]and injects a serialized bible block right after the persona prompt:anime_bible_context = "" if anime_bible: try: serialized_bible = json.dumps(anime_bible, ensure_ascii=False, indent=2) except Exception: serialized_bible = str(anime_bible) anime_bible_context = f""" You also have a structured ANIME STORY BIBLE that defines the main cast, world rules, and visual style. Use it as a hard constraint for character consistency, worldbuilding, and visual storytelling: {serialized_bible} """The context is included for both short-story and longer-story prompts. This ensures:
- Character, world, and style constraints are explicitly visible to the LLM
- The same bible is applied consistently for start and continuation
-
StoryContentMixin.continue_story(...)similarly acceptsanime_bibleand injects the sameanime_bible_contextinto the continuation prompt, directly afterpersona_prompt.
This means every text generation step (start and continue) is conditioned on the bible when present.
4.2 Scene Animation (Image-to-Video)
The current bible-aware integration is focused on motion prompts for Kling image-to-video.
4.2.1 Frontend: story_context payload
File: StoryOutline.tsx
createStoryContextPayload includes anime_bible:
const createStoryContextPayload = () => ({
persona: state.persona,
story_setting: state.storySetting,
characters: state.characters,
plot_elements: state.plotElements,
writing_style: state.writingStyle,
story_tone: state.storyTone,
narrative_pov: state.narrativePOV,
audience_age_group: state.audienceAgeGroup,
content_rating: state.contentRating,
story_length: state.storyLength,
premise: state.premise,
outline: state.outline,
story_content: state.storyContent,
anime_bible: state.animeBible,
});
This payload is passed to:
storyWriterApi.animateScene(...)storyWriterApi.animateSceneVoiceover(...)
4.2.2 Backend: Kling animation service
File: kling_animation.py
-
animate_scene_image(...)is unchanged in signature but passesstory_contexttogenerate_animation_prompt(...). -
_build_fallback_prompt(scene_data, story_context):- Reads
anime_bible = story_context.get("anime_bible") - Extracts:
- Visual style details (
style_preset,camera_style,color_mood,lighting,line_style,extra_tags) - World
setting main_castnames
- Visual style details (
- Appends a concise style text to the deterministic fallback prompt to preserve:
- Visual style
- World flavor
- Character design consistency (names only)
- Reads
-
generate_animation_prompt(scene_data, story_context, user_id):- Builds an
ANIME STORY BIBLE VISUAL GUIDANCEblock whenanime_bibleis present, e.g.:- Visual style preset and camera style
- Color mood, lighting, line style
- Extra style tags
- Main cast names to keep visually consistent
- World/setting context
- Inserts this block between
Settingand the “Focus on” bullet list in the LLM prompt. - Both structured JSON responses and fallback text generation flows see this block.
- Builds an
Result:
- Motion prompts for Kling image-to-video are constrained by the bible, making animations conform to:
- The same anime visual style
- The same character set
- The same world tone
4.3 Images (Current State)
Image generation currently uses:
StoryScene.image_promptgenerated during outline generation- Image provider settings (width, height, model)
The anime bible is not yet used in a second-pass image prompt rewriter. However:
- The bible is already aligned with the same outline and template that produced
image_prompt. - The bible is threaded into Story Writer’s state and can be used later to refine image prompts or add style constraints.
Planned enhancement (not yet implemented):
- Add a lightweight prompt refinement step that:
- Takes
scene.image_prompt+AnimeStoryBible.visual_style - Emits a style-constrained
final_image_prompt - Passes that to the image generation service
- Takes
This document should be updated when that enhancement is implemented.
5. Adapting the Bible to Other Story Types
Although the Anime Story Bible is currently wired for anime-focused stories, the architecture is intentionally reusable.
5.1 Reuse Strategy
-
Data model:
AnimeStoryBibleis anime-specific, but the concept of a structured “story bible” (cast + world + style) is general.- Future story types can introduce sibling models (e.g.,
NovelStoryBible,ComicStoryBible) reusing similar patterns.
-
Transport layer:
- Requests use a flexible
anime_bible: Optional[Dict[str, Any]]at the story-generation level. - This can be generalized to a
story_biblefield if we want cross-template reuse.
- Requests use a flexible
-
Prompt patterns:
- Both text and motion pipelines use the same pattern:
- Serialize the bible
- Inject a dedicated paragraph or bullet block
- Explicitly instruct the model to treat it as a hard constraint
- This pattern is template-agnostic and can be reused for other story modes.
- Both text and motion pipelines use the same pattern:
5.2 Extension Guidelines
When adapting the bible pattern to other story types:
-
Define the bible model
- Add a dedicated Pydantic model under
story_models.py. - Mirror it with a TypeScript interface in
storyWriterApi.ts.
- Add a dedicated Pydantic model under
-
Attach it to responses
- Extend the relevant response models (setup, outline, etc.) with an optional bible field.
- Ensure the generating service populates it when the template supports it.
-
Thread through state
- Add a field to
StoryWriterState. - Persist it in
localStorage. - Provide setter(s) and ensure it is included in
getRequest()when relevant.
- Add a field to
-
Inject into prompts
- Text: add a serialized bible context block after the persona prompt for:
- Story start
- Story continuation
- Media: add a structured guidance block to:
- Image prompt generation (if using AI to build prompts)
- Motion/animation prompts
- Text: add a serialized bible context block after the persona prompt for:
-
Document the flow
- Update this document (or a sibling doc) with:
- Model definitions
- Where the bible is generated
- Where and how it is injected into prompts
- Update this document (or a sibling doc) with:
6. Summary of Recent Changes (Bible Wiring)
This section summarizes the concrete changes made for the initial Anime Story Bible integration:
-
Backend models
- Added
anime_bibletoStoryGenerationRequestandStoryContinueRequestasOptional[Dict[str, Any]]. - Confirmed
AnimeStoryBibleand related classes in story_models.py.
- Added
-
Frontend models & state
- Added
anime_bible?: AnimeStoryBible | nulltoStoryGenerationRequest. useStoryWriterState.getRequest()now includesanime_bible: state.animeBible || null.createStoryContextPayloadfor outline/animation includesanime_bible: state.animeBible.
- Added
-
Story text prompts
generate_story_startandcontinue_storyacceptanime_bibleand inject a serialized “ANIME STORY BIBLE” context block directly afterpersona_prompt.- Routing layer passes
request.anime_biblethrough from API to service.
-
Motion prompts (Kling image-to-video)
story_context.anime_bibleis used in:_build_fallback_promptto append style/world/cast hints to deterministic prompts.generate_animation_promptto add an explicitANIME STORY BIBLE VISUAL GUIDANCEblock for the LLM.
-
Not yet implemented
- Second-pass enrichment of per-scene
image_promptusing the bible. - Generalization beyond anime templates (would require broader “story bible” abstraction).
- Second-pass enrichment of per-scene
This document should be kept up to date whenever the Anime Story Bible is:
- Extended to new story templates
- Used for additional media types (e.g., storyboard export, trailers)
- Modified in structure or prompt integration