Add multiple story frameworks
- Snowflake Method (already had) - Three-Act Structure - Save the Cat (Blake Snyder) - Hero's Journey (Joseph Campbell) - Story Circle (Dan Harmon) - The 7-Point Plot (The Pantone) - Fichtean Curve Pass framework='hero-journey' or 'save-the-cat' etc. to use.
This commit is contained in:
@@ -0,0 +1,278 @@
|
|||||||
|
"""Story frameworks for Opus Orchestrator.
|
||||||
|
|
||||||
|
Implements multiple narrative structure frameworks:
|
||||||
|
- Snowflake Method
|
||||||
|
- Three-Act Structure
|
||||||
|
- Save the Cat (Blake Snyder)
|
||||||
|
- Hero's Journey (Joseph Campbell)
|
||||||
|
- Story Circle (Dan Harmon)
|
||||||
|
- The 7-Point Plot (The Pantone)
|
||||||
|
- Fichtean Curve
|
||||||
|
"""
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class StoryFramework(str, Enum):
|
||||||
|
"""Available story frameworks."""
|
||||||
|
|
||||||
|
SNOWFLAKE = "snowflake"
|
||||||
|
THREE_ACT = "three-act"
|
||||||
|
SAVE_THE_CAT = "save-the-cat"
|
||||||
|
HERO_JOURNEY = "hero-journey"
|
||||||
|
STORY_CIRCLE = "story-circle"
|
||||||
|
SEVEN_POINT = "seven-point"
|
||||||
|
FICHTEAN = "fichtean"
|
||||||
|
|
||||||
|
|
||||||
|
# Framework descriptions and prompts
|
||||||
|
|
||||||
|
FRAMEWORKS = {
|
||||||
|
StoryFramework.SNOWFLAKE: {
|
||||||
|
"name": "Snowflake Method",
|
||||||
|
"description": "Fractal expansion from sentence to paragraph to full novel",
|
||||||
|
"stages": [
|
||||||
|
"One sentence summary",
|
||||||
|
"One paragraph outline",
|
||||||
|
"Character sheets",
|
||||||
|
"Four-page outline",
|
||||||
|
"Detailed character charts",
|
||||||
|
"Scene list",
|
||||||
|
"Scene descriptions",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
StoryFramework.THREE_ACT: {
|
||||||
|
"name": "Three-Act Structure",
|
||||||
|
"description": "Classic setup, confrontation, resolution structure",
|
||||||
|
"stages": [
|
||||||
|
"Act I: Setup - Introduce protagonist, status quo, inciting incident",
|
||||||
|
"Act I: Break into Two - Commit to journey",
|
||||||
|
"Act II, Part 1: Fun and Games - Promise of premise",
|
||||||
|
"Act II, Part 1: Midpoint - Stakes raise",
|
||||||
|
"Act II, Part 2: Bad Guys Close In - External pressure",
|
||||||
|
"Act II, Part 2: All Is Lost - Lowest point",
|
||||||
|
"Act III: Finale - Climax and resolution",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
StoryFramework.SAVE_THE_CAT: {
|
||||||
|
"name": "Save the Cat",
|
||||||
|
"description": "Blake Snyder's 15-beat screenwriting structure",
|
||||||
|
"beats": [
|
||||||
|
("Opening Image", "Visual hook that sets the tone"),
|
||||||
|
("Theme Stated", "Someone states the theme"),
|
||||||
|
("Setup", "Normal world, introduce key players"),
|
||||||
|
("Catalyst", "Life-changing event"),
|
||||||
|
("Debate", "Protagonist resists the call"),
|
||||||
|
("Break Into Two", "Commit to the journey"),
|
||||||
|
("B Story", "Subplot begins"),
|
||||||
|
("Fun and Games", "Promise of the premise"),
|
||||||
|
("Midpoint", "Stakes are raised"),
|
||||||
|
("Bad Guys Close In", "External pressure increases"),
|
||||||
|
("All Is Lost", "Darkest moment"),
|
||||||
|
("Dark Night of the Soul", "Emotional nadir"),
|
||||||
|
("Break Into Three", "Solution found"),
|
||||||
|
("Finale", "Final confrontation"),
|
||||||
|
("Final Image", "Changed world"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
StoryFramework.HERO_JOURNEY: {
|
||||||
|
"name": "Hero's Journey",
|
||||||
|
"description": "Joseph Campbell's monomyth - 12 stages",
|
||||||
|
"beats": [
|
||||||
|
("Ordinary World", "Hero's normal life before the adventure"),
|
||||||
|
("Call to Adventure", "Challenge or quest presented"),
|
||||||
|
("Refusal of the Call", "Hero hesitates or declines"),
|
||||||
|
("Meeting the Mentor", "Guide appears with wisdom/tools"),
|
||||||
|
("Crossing the Threshold", "Hero commits, enters special world"),
|
||||||
|
("Tests, Allies, Enemies", "Hero faces challenges, makes friends/foes"),
|
||||||
|
("Approach to Inmost Cave", "Hero prepares for major challenge"),
|
||||||
|
("Ordeal", "Hero faces greatest challenge, death/rebirth"),
|
||||||
|
("Reward", "Hero gains prize/knowledge"),
|
||||||
|
("The Road Back", "Hero begins return journey"),
|
||||||
|
("Resurrection", "Final test, hero transformed"),
|
||||||
|
("Return with Elixir", "Hero returns, transformed"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
StoryFramework.STORY_CIRCLE: {
|
||||||
|
"name": "Story Circle",
|
||||||
|
"description": "Dan Harmon's 8-step circular structure",
|
||||||
|
"beats": [
|
||||||
|
("You", "Character in their comfort zone"),
|
||||||
|
("Need", "Character feels something is missing"),
|
||||||
|
("Go", "Character enters unfamiliar situation"),
|
||||||
|
("Adapt", "Character adjusts to new world"),
|
||||||
|
("Get", "Character gains what they sought"),
|
||||||
|
("Return", "Character returns home"),
|
||||||
|
("Change", "Character is transformed"),
|
||||||
|
("Result", "Character's life is different"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
StoryFramework.SEVEN_POINT: {
|
||||||
|
"name": "The 7-Point Plot",
|
||||||
|
"description": "The Pantone method - 7 key plot points",
|
||||||
|
"beats": [
|
||||||
|
("Hook", "Opening that grabs attention"),
|
||||||
|
("Plot Turn 1", "First major change, inciting incident"),
|
||||||
|
("Pinch Point 1", "Pressure from antagonist"),
|
||||||
|
("Midpoint", "Character commits to action"),
|
||||||
|
("Pinch Point 2", "Increased pressure, stakes raise"),
|
||||||
|
("Plot Turn 2", "Major reversal, everything changes"),
|
||||||
|
("Resolution", "Final confrontation, new equilibrium"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
StoryFramework.FICHTEAN: {
|
||||||
|
"name": "Fichtean Curve",
|
||||||
|
"description": "Progressive rising action - series of crises",
|
||||||
|
"beats": [
|
||||||
|
("Inciting Incident", "Chain of events begins"),
|
||||||
|
("Rising Action 1", "First crisis"),
|
||||||
|
("Rising Action 2", "Second crisis"),
|
||||||
|
("Rising Action 3", "Third crisis"),
|
||||||
|
("Climax", "Maximum tension"),
|
||||||
|
("Falling Action", "Aftermath"),
|
||||||
|
("Resolution", "New status quo"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_framework_prompt(framework: StoryFramework) -> str:
|
||||||
|
"""Get the system prompt for a framework."""
|
||||||
|
|
||||||
|
if framework == StoryFramework.SAVE_THE_CAT:
|
||||||
|
return """You are an expert in Save the Cat story structure (Blake Snyder).
|
||||||
|
|
||||||
|
The 15 beats of Save the Cat:
|
||||||
|
1. Opening Image - Visual hook, tone setter
|
||||||
|
2. Theme Stated - Someone states the theme
|
||||||
|
3. Setup - Normal world, introduce characters
|
||||||
|
4. Catalyst - Life-changing event
|
||||||
|
5. Debate - Protagonist resists the call
|
||||||
|
6. Break Into Two - Commit to journey
|
||||||
|
7. B Story - Subplot begins
|
||||||
|
8. Fun and Games - Promise of the premise
|
||||||
|
9. Midpoint - Stakes raise
|
||||||
|
10. Bad Guys Close In - External pressure
|
||||||
|
11. All Is Lost - Darkest moment
|
||||||
|
12. Dark Night of the Soul - Emotional nadirs
|
||||||
|
13. Break Into Three - Solution found
|
||||||
|
14. Finale - Final confrontation
|
||||||
|
15. Final Image - Changed world
|
||||||
|
|
||||||
|
Use these beats to structure compelling narratives."""
|
||||||
|
|
||||||
|
elif framework == StoryFramework.HERO_JOURNEY:
|
||||||
|
return """You are an expert in the Hero's Journey (Joseph Campbell's monomyth).
|
||||||
|
|
||||||
|
The 12 stages:
|
||||||
|
1. Ordinary World - Hero's normal life
|
||||||
|
2. Call to Adventure - Challenge presented
|
||||||
|
3. Refusal of the Call - Hero hesitates
|
||||||
|
4. Meeting the Mentor - Guide appears
|
||||||
|
5. Crossing the Threshold - Enter special world
|
||||||
|
6. Tests, Allies, Enemies - Face challenges
|
||||||
|
7. Approach to Inmost Cave - Prepare for major challenge
|
||||||
|
8. Ordeal - Greatest challenge, death/rebirth
|
||||||
|
9. Reward - Gain prize/knowledge
|
||||||
|
10. The Road Back - Begin return
|
||||||
|
11. Resurrection - Final test, transformation
|
||||||
|
12. Return with Elixir - Return transformed
|
||||||
|
|
||||||
|
Use these stages to structure mythic narratives."""
|
||||||
|
|
||||||
|
elif framework == StoryFramework.STORY_CIRCLE:
|
||||||
|
return """You are an expert in Dan Harmon's Story Circle.
|
||||||
|
|
||||||
|
The 8 steps:
|
||||||
|
1. You - Character in comfort zone
|
||||||
|
2. Need - Something missing
|
||||||
|
3. Go - Enter unfamiliar situation
|
||||||
|
4. Adapt - Adjust to new world
|
||||||
|
5. Get - Gain what sought
|
||||||
|
6. Return - Return home
|
||||||
|
7. Change - Transformed
|
||||||
|
8. Result - Life different
|
||||||
|
|
||||||
|
Use this circular structure for balanced narratives."""
|
||||||
|
|
||||||
|
elif framework == StoryFramework.SEVEN_POINT:
|
||||||
|
return """You are an expert in The 7-Point Plot (The Pantone).
|
||||||
|
|
||||||
|
The 7 plot points:
|
||||||
|
1. Hook - Opening grab
|
||||||
|
2. Plot Turn 1 - First major change
|
||||||
|
3. Pinch Point 1 - Antagonist pressure
|
||||||
|
4. Midpoint - Commit to action
|
||||||
|
5. Pinch Point 2 - Stakes raise
|
||||||
|
6. Plot Turn 2 - Major reversal
|
||||||
|
7. Resolution - New equilibrium
|
||||||
|
|
||||||
|
Use this for tight, event-driven plots."""
|
||||||
|
|
||||||
|
elif framework == StoryFramework.FICHTEAN:
|
||||||
|
return """You are an expert in the Fichtean Curve.
|
||||||
|
|
||||||
|
Progressive crisis structure:
|
||||||
|
1. Inciting Incident - Chain of events begins
|
||||||
|
2. Rising Action 1 - First crisis
|
||||||
|
3. Rising Action 2 - Second crisis (bigger)
|
||||||
|
4. Rising Action 3 - Third crisis (biggest)
|
||||||
|
5. Climax - Maximum tension
|
||||||
|
6. Falling Action - Aftermath
|
||||||
|
7. Resolution - New status quo
|
||||||
|
|
||||||
|
Use this for action-driven, tension-building narratives."""
|
||||||
|
|
||||||
|
elif framework == StoryFramework.THREE_ACT:
|
||||||
|
return """You are an expert in Three-Act Structure.
|
||||||
|
|
||||||
|
Classic narrative structure:
|
||||||
|
ACT I - SETUP
|
||||||
|
- Opening Image
|
||||||
|
- Theme Stated
|
||||||
|
- Setup (normal world)
|
||||||
|
- Catalyst (inciting incident)
|
||||||
|
- Debate (protagonist resists)
|
||||||
|
- Break Into Two (commit to journey)
|
||||||
|
|
||||||
|
ACT II - CONFRONTATION
|
||||||
|
- B Story (subplot begins)
|
||||||
|
- Fun and Games (promise of premise)
|
||||||
|
- Midpoint (stakes raise)
|
||||||
|
- Bad Guys Close In (external pressure)
|
||||||
|
- All Is Lost (lowest point)
|
||||||
|
- Dark Night of the Soul (internal reckoning)
|
||||||
|
- Break Into Three (solution found)
|
||||||
|
|
||||||
|
ACT III - RESOLUTION
|
||||||
|
- Finale (climax)
|
||||||
|
- Final Image (changed world)
|
||||||
|
|
||||||
|
Use this traditional structure for any genre."""
|
||||||
|
|
||||||
|
else:
|
||||||
|
return "You are an expert story architect."
|
||||||
|
|
||||||
|
|
||||||
|
def get_framework_for_genre(genre: str) -> list[StoryFramework]:
|
||||||
|
"""Suggest frameworks based on genre."""
|
||||||
|
|
||||||
|
suggestions = {
|
||||||
|
"fantasy": [StoryFramework.HERO_JOURNEY, StoryFramework.SNOWFLAKE],
|
||||||
|
"science-fiction": [StoryFramework.SNOWFLAKE, StoryFramework.SAVE_THE_CAT],
|
||||||
|
"thriller": [StoryFramework.SAVE_THE_CAT, StoryFramework.SEVEN_POINT, StoryFramework.FICHTEAN],
|
||||||
|
"horror": [StoryFramework.HERO_JOURNEY, StoryFramework.FICHTEAN],
|
||||||
|
"romance": [StoryFramework.STORY_CIRCLE, StoryFramework.SAVE_THE_CAT],
|
||||||
|
"mystery": [StoryFramework.SEVEN_POINT, StoryFramework.THREE_ACT],
|
||||||
|
"literary": [StoryFramework.SNOWFLAKE, StoryFramework.HERO_JOURNEY],
|
||||||
|
"adventure": [StoryFramework.HERO_JOURNEY, StoryFramework.FICHTEAN],
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestions.get(genre.lower(), [StoryFramework.THREE_ACT, StoryFramework.SNOWFLAKE])
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
"""Main Opus Orchestrator - Snowflake Method Implementation.
|
"""Main Opus Orchestrator - Snowflake Method Implementation with Multiple Frameworks.
|
||||||
|
|
||||||
Full pipeline following the Snowflake Method for book writing:
|
Full pipeline supporting multiple story frameworks:
|
||||||
1. One sentence (concept)
|
- Snowflake Method (fractal expansion)
|
||||||
2. One paragraph (outline)
|
- Three-Act Structure
|
||||||
3. Character sheets
|
- Save the Cat (Blake Snyder)
|
||||||
4. Four-page outline
|
- Hero's Journey (Joseph Campbell)
|
||||||
5. Detailed character charts
|
- Story Circle (Dan Harmon)
|
||||||
6. Scene list
|
- The 7-Point Plot (The Pantone)
|
||||||
7. Scene descriptions
|
- Fichtean Curve
|
||||||
8. First draft
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -35,6 +34,12 @@ from opus_orchestrator.agents.nonfiction import (
|
|||||||
ResearcherAgent,
|
ResearcherAgent,
|
||||||
)
|
)
|
||||||
from opus_orchestrator.config import OpusConfig, get_config
|
from opus_orchestrator.config import OpusConfig, get_config
|
||||||
|
from opus_orchestrator.frameworks import (
|
||||||
|
StoryFramework,
|
||||||
|
FRAMEWORKS,
|
||||||
|
get_framework_for_genre,
|
||||||
|
get_framework_prompt,
|
||||||
|
)
|
||||||
from opus_orchestrator.schemas import (
|
from opus_orchestrator.schemas import (
|
||||||
BookBlueprint,
|
BookBlueprint,
|
||||||
BookIntent,
|
BookIntent,
|
||||||
@@ -50,7 +55,7 @@ from opus_orchestrator.state import OpusState
|
|||||||
|
|
||||||
|
|
||||||
class OpusOrchestrator:
|
class OpusOrchestrator:
|
||||||
"""Main orchestrator implementing the Snowflake Method."""
|
"""Main orchestrator implementing multiple story frameworks."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -61,9 +66,23 @@ class OpusOrchestrator:
|
|||||||
intended_outcome: str = "complete novel",
|
intended_outcome: str = "complete novel",
|
||||||
tone: Optional[str] = None,
|
tone: Optional[str] = None,
|
||||||
target_word_count: int = 80000,
|
target_word_count: int = 80000,
|
||||||
|
framework: str = "snowflake",
|
||||||
config: Optional[OpusConfig] = None,
|
config: Optional[OpusConfig] = None,
|
||||||
):
|
):
|
||||||
"""Initialize the Opus Orchestrator with Snowflake Method."""
|
"""Initialize the Opus Orchestrator with selectable framework.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
repo_url: GitHub URL for content
|
||||||
|
book_type: "fiction" or "nonfiction"
|
||||||
|
genre: Genre (for framework suggestions)
|
||||||
|
target_audience: Who is this for
|
||||||
|
intended_outcome: What to produce
|
||||||
|
tone: Desired tone
|
||||||
|
target_word_count: Target length
|
||||||
|
framework: Story framework to use (snowflake, three-act, save-the-cat,
|
||||||
|
hero-journey, story-circle, seven-point, fichtean)
|
||||||
|
config: Optional config override
|
||||||
|
"""
|
||||||
self.config = config or get_config()
|
self.config = config or get_config()
|
||||||
|
|
||||||
if not self.config.agent.api_key:
|
if not self.config.agent.api_key:
|
||||||
@@ -72,6 +91,19 @@ class OpusOrchestrator:
|
|||||||
self.book_type = BookType(book_type.lower())
|
self.book_type = BookType(book_type.lower())
|
||||||
self.repo_url = repo_url
|
self.repo_url = repo_url
|
||||||
|
|
||||||
|
# Handle framework
|
||||||
|
if isinstance(framework, str):
|
||||||
|
try:
|
||||||
|
self.framework = StoryFramework(framework.lower())
|
||||||
|
except ValueError:
|
||||||
|
# Default to snowflake if invalid
|
||||||
|
self.framework = StoryFramework.SNOWFLAKE
|
||||||
|
else:
|
||||||
|
self.framework = framework
|
||||||
|
|
||||||
|
# Get framework info
|
||||||
|
self.framework_info = FRAMEWORKS.get(self.framework, FRAMEWORKS[StoryFramework.SNOWFLAKE])
|
||||||
|
|
||||||
self.intent = BookIntent(
|
self.intent = BookIntent(
|
||||||
book_type=self.book_type,
|
book_type=self.book_type,
|
||||||
genre=genre,
|
genre=genre,
|
||||||
@@ -171,23 +203,19 @@ Write ONE compelling sentence that captures the entire story.
|
|||||||
return self.one_sentence
|
return self.one_sentence
|
||||||
|
|
||||||
async def snowflake_stage_2(self) -> str:
|
async def snowflake_stage_2(self) -> str:
|
||||||
"""Stage 2: One paragraph summary.
|
"""Stage 2: One paragraph outline (framework-dependent).
|
||||||
|
|
||||||
Expand the one sentence to a paragraph with setup, 3 acts, and resolution.
|
Expand the one sentence to a paragraph with setup, 3 acts, and resolution.
|
||||||
|
Uses the selected story framework.
|
||||||
"""
|
"""
|
||||||
print("❄️ SNOWFLAKE STAGE 2: One paragraph outline...")
|
print(f"❄️ SNOWFLAKE STAGE 2: One paragraph outline ({self.framework_info['name']})...")
|
||||||
|
|
||||||
|
# Get framework-specific prompt
|
||||||
|
framework_system_prompt = get_framework_prompt(self.framework)
|
||||||
|
|
||||||
user_prompt = f"""Expand this one-sentence summary into a full one-paragraph story outline.
|
user_prompt = f"""Expand this one-sentence summary into a full one-paragraph story outline.
|
||||||
|
|
||||||
Include:
|
Use the {self.framework_info['name']} framework: {self.framework_info.get('description', '')}
|
||||||
- Opening image (the "before" state)
|
|
||||||
- Setup (normal world, who the protagonist is)
|
|
||||||
- Catalyst (what changes everything)
|
|
||||||
- Rising action (attempts to solve the problem)
|
|
||||||
- Midpoint (major twist or revelation)
|
|
||||||
- Complications (things get worse)
|
|
||||||
- Crisis (lowest point)
|
|
||||||
- Resolution (how it ends)
|
|
||||||
|
|
||||||
## One sentence:
|
## One sentence:
|
||||||
{self.one_sentence}
|
{self.one_sentence}
|
||||||
@@ -196,7 +224,7 @@ Include:
|
|||||||
Write one detailed paragraph (4-8 sentences) that tells the complete story arc.
|
Write one detailed paragraph (4-8 sentences) that tells the complete story arc.
|
||||||
"""
|
"""
|
||||||
response = await self.agents["architect"].call_llm(
|
response = await self.agents["architect"].call_llm(
|
||||||
system_prompt="You are an expert story architect. Create detailed, act-structured outlines.",
|
system_prompt=framework_system_prompt,
|
||||||
user_prompt=user_prompt,
|
user_prompt=user_prompt,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -316,27 +344,31 @@ Write comprehensive, detailed character charts.
|
|||||||
return self.character_charts
|
return self.character_charts
|
||||||
|
|
||||||
async def snowflake_stage_6(self) -> str:
|
async def snowflake_stage_6(self) -> str:
|
||||||
"""Stage 6: Scene list.
|
"""Stage 6: Scene list (framework-dependent).
|
||||||
|
|
||||||
Create a list of all scenes needed (like index cards).
|
Create a list of all scenes using the selected framework.
|
||||||
"""
|
"""
|
||||||
print("❄️ SNOWFLAKE STAGE 6: Scene list...")
|
print(f"❄️ SNOWFLAKE STAGE 6: Scene list ({self.framework_info['name']})...")
|
||||||
|
|
||||||
|
# Get framework-specific prompt
|
||||||
|
framework_system_prompt = get_framework_prompt(self.framework)
|
||||||
|
|
||||||
words_per_scene = 1500 # Average scene length
|
words_per_scene = 1500 # Average scene length
|
||||||
num_scenes = max(10, self.intent.target_word_count // words_per_scene)
|
num_scenes = max(10, self.intent.target_word_count // words_per_scene)
|
||||||
|
|
||||||
user_prompt = f"""Create a complete SCENE LIST for this story.
|
# Get framework beats if available
|
||||||
|
framework_beats = ""
|
||||||
|
if "beats" in self.framework_info:
|
||||||
|
framework_beats = f"\n\n## Framework Beats:\n"
|
||||||
|
for beat_name, beat_desc in self.framework_info["beats"]:
|
||||||
|
framework_beats += f"- {beat_name}: {beat_desc}\n"
|
||||||
|
|
||||||
For each scene, provide:
|
user_prompt = f"""Create a complete SCENE LIST for this story using the {self.framework_info['name']}.
|
||||||
- Scene number
|
|
||||||
- POV character
|
|
||||||
- Setting/location
|
|
||||||
- What happens (one line)
|
|
||||||
- Purpose (advances plot? reveals character? builds world?)
|
|
||||||
- Chapter placement
|
|
||||||
|
|
||||||
Target: approximately {num_scenes} scenes for a {self.intent.target_word_count:,} word novel.
|
Target: approximately {num_scenes} scenes for a {self.intent.target_word_count:,} word novel.
|
||||||
|
|
||||||
|
{framework_beats}
|
||||||
|
|
||||||
## Four-page outline:
|
## Four-page outline:
|
||||||
{self.four_page_outline}
|
{self.four_page_outline}
|
||||||
|
|
||||||
@@ -347,7 +379,7 @@ Target: approximately {num_scenes} scenes for a {self.intent.target_word_count:,
|
|||||||
Create a comprehensive scene list with all scenes needed.
|
Create a comprehensive scene list with all scenes needed.
|
||||||
"""
|
"""
|
||||||
response = await self.agents["architect"].call_llm(
|
response = await self.agents["architect"].call_llm(
|
||||||
system_prompt="You are an expert story architect. Create detailed scene lists.",
|
system_prompt=framework_system_prompt,
|
||||||
user_prompt=user_prompt,
|
user_prompt=user_prompt,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -545,7 +577,7 @@ Make it vivid, engaging, and true to the characters.
|
|||||||
themes=[],
|
themes=[],
|
||||||
tone=self.intent.tone or "neutral",
|
tone=self.intent.tone or "neutral",
|
||||||
chapters=[
|
chapters=[
|
||||||
BookBlueprint.model_construct(
|
ChapterBlueprint(
|
||||||
chapter_number=i,
|
chapter_number=i,
|
||||||
title=f"Chapter {i}",
|
title=f"Chapter {i}",
|
||||||
summary=f"Chapter {i}",
|
summary=f"Chapter {i}",
|
||||||
@@ -595,18 +627,21 @@ Make it vivid, engaging, and true to the characters.
|
|||||||
# =========================================================================
|
# =========================================================================
|
||||||
|
|
||||||
async def run(self) -> Manuscript:
|
async def run(self) -> Manuscript:
|
||||||
"""Run the full Snowflake Method pipeline."""
|
"""Run the full pipeline with selected framework."""
|
||||||
|
framework_name = self.framework_info.get("name", "Unknown")
|
||||||
|
|
||||||
print(f"\n{'='*60}")
|
print(f"\n{'='*60}")
|
||||||
print("❄️ OPUS ORCHESTRATOR - SNOWFLAKE METHOD")
|
print(f"❄️ OPUS ORCHESTRATOR - {framework_name.upper()}")
|
||||||
print(f"{'='*60}\n")
|
print(f"{'='*60}")
|
||||||
|
print(f"Framework: {self.framework_info.get('description', '')}\n")
|
||||||
|
|
||||||
await self.ingest()
|
await self.ingest()
|
||||||
|
|
||||||
# Pre-writing stages (Snowflake 1-7)
|
# Pre-writing stages
|
||||||
await self.snowflake_stage_1() # One sentence
|
await self.snowflake_stage_1() # One sentence
|
||||||
await self.snowflake_stage_2() # One paragraph
|
await self.snowflake_stage_2() # One paragraph/outline with framework
|
||||||
await self.snowflake_stage_3() # Character sheets
|
await self.snowflake_stage_3() # Character sheets
|
||||||
await self.snowflake_stage_4() # Four-page outline
|
await self.snowflake_stage_4() # Expanded outline
|
||||||
await self.snowflake_stage_5() # Detailed character charts
|
await self.snowflake_stage_5() # Detailed character charts
|
||||||
await self.snowflake_stage_6() # Scene list
|
await self.snowflake_stage_6() # Scene list
|
||||||
await self.snowflake_stage_7() # Scene descriptions
|
await self.snowflake_stage_7() # Scene descriptions
|
||||||
@@ -621,11 +656,12 @@ Make it vivid, engaging, and true to the characters.
|
|||||||
manuscript = await self.compile_manuscript()
|
manuscript = await self.compile_manuscript()
|
||||||
|
|
||||||
print(f"\n{'='*60}")
|
print(f"\n{'='*60}")
|
||||||
print("✅ SNOWFLAKE COMPLETE!")
|
print("✅ COMPLETE!")
|
||||||
print(f"{'='*60}")
|
print(f"{'='*60}")
|
||||||
print(f"📖 Title: {manuscript.title}")
|
print(f"📖 Title: {manuscript.title}")
|
||||||
print(f"📄 Words: {manuscript.total_word_count:,}")
|
print(f"📄 Words: {manuscript.total_word_count:,}")
|
||||||
print(f"📑 Chapters: {len(manuscript.chapters)}")
|
print(f"📑 Chapters: {len(manuscript.chapters)}")
|
||||||
|
print(f"🎯 Framework: {framework_name}")
|
||||||
|
|
||||||
return manuscript
|
return manuscript
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user