feat: Implement ai_blueprint.md action plan — architectural review & optimisations
Steps 1–7 of the ai_blueprint.md action plan executed: DOCUMENTATION (Steps 1–3, 6–7): - docs/current_state_analysis.md: Phase-by-phase cost/quality mapping of existing pipeline - docs/alternatives_analysis.md: 15 alternative approaches with testable hypotheses - docs/experiment_design.md: 7 controlled A/B experiment specifications (CPC, HQS, CER metrics) - ai_blueprint_v2.md: New recommended architecture with cost projections and experiment roadmap CODE IMPROVEMENTS (Step 4 — Experiments 1–4 implemented): - story/writer.py: Extract build_persona_info() — persona loaded once per book, not per chapter - story/writer.py: Adaptive scoring thresholds — SCORE_PASSING scales 6.5→7.5 by chapter position - story/writer.py: Beat expansion skip — if beats >100 words, skip Director's Treatment expansion - story/planner.py: validate_outline() — pre-generation gate checks missing beats, continuity, pacing - story/planner.py: Enrichment field validation — warn on missing title/genre after enrich() - cli/engine.py: Wire persona cache, outline validation gate, chapter_position threading Expected savings: ~285K tokens per 30-chapter novel (~7% cost reduction) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ from ai import models as ai_models
|
||||
from ai import setup as ai_setup
|
||||
from story import planner, writer as story_writer, editor as story_editor
|
||||
from story import style_persona, bible_tracker, state as story_state
|
||||
from story.writer import build_persona_info
|
||||
from marketing import assets as marketing_assets
|
||||
from export import exporter
|
||||
|
||||
@@ -99,6 +100,13 @@ def process_book(bp, folder, context="", resume=False, interactive=False):
|
||||
raise
|
||||
utils.log("TIMING", f"Chapter Planning: {time.time() - t_step:.1f}s")
|
||||
|
||||
# 4b. Outline Validation Gate (Alt 2-B: pre-generation quality check)
|
||||
if chapters and not resume:
|
||||
try:
|
||||
planner.validate_outline(events, chapters, bp, folder)
|
||||
except Exception as _e:
|
||||
utils.log("ARCHITECT", f"Outline validation skipped: {_e}")
|
||||
|
||||
# 5. Writing Loop
|
||||
ms_path = os.path.join(folder, "manuscript.json")
|
||||
loaded_ms = utils.load_json(ms_path) if (resume and os.path.exists(ms_path)) else []
|
||||
@@ -147,6 +155,10 @@ def process_book(bp, folder, context="", resume=False, interactive=False):
|
||||
session_chapters = 0
|
||||
session_time = 0
|
||||
|
||||
# Pre-load persona once for the entire writing phase (Alt 3-D: persona cache)
|
||||
# Rebuilt after each refine_persona() call to pick up bio updates.
|
||||
cached_persona = build_persona_info(bp)
|
||||
|
||||
i = len(ms)
|
||||
while i < len(chapters):
|
||||
ch_start = time.time()
|
||||
@@ -178,7 +190,8 @@ def process_book(bp, folder, context="", resume=False, interactive=False):
|
||||
else:
|
||||
summary_ctx = summary[-8000:] if len(summary) > 8000 else summary
|
||||
next_hint = chapters[i+1]['title'] if i + 1 < len(chapters) else ""
|
||||
txt = story_writer.write_chapter(ch, bp, folder, summary_ctx, tracking, prev_content, next_chapter_hint=next_hint)
|
||||
chap_pos = i / max(len(chapters) - 1, 1) if len(chapters) > 1 else 0.5
|
||||
txt = story_writer.write_chapter(ch, bp, folder, summary_ctx, tracking, prev_content, next_chapter_hint=next_hint, prebuilt_persona=cached_persona, chapter_position=chap_pos)
|
||||
except Exception as e:
|
||||
utils.log("SYSTEM", f"Chapter generation failed: {e}")
|
||||
if interactive:
|
||||
@@ -199,6 +212,7 @@ def process_book(bp, folder, context="", resume=False, interactive=False):
|
||||
if (i == 0 or i % 5 == 0) and txt:
|
||||
bp['book_metadata']['author_details'] = style_persona.refine_persona(bp, txt, folder)
|
||||
with open(bp_path, "w") as f: json.dump(bp, f, indent=2)
|
||||
cached_persona = build_persona_info(bp) # Rebuild cache with updated bio
|
||||
|
||||
# Look ahead for context
|
||||
next_info = ""
|
||||
|
||||
Reference in New Issue
Block a user