feat: Implement ai_blueprint_v2.md — Exp 5, 6 & 7 (persona validation, mid-gen consistency, two-pass drafting)
Exp 6 — Iterative Persona Validation (story/style_persona.py + cli/engine.py): - Added validate_persona(): generates ~200-word sample in persona voice, scores 1–10 via lightweight voice-quality prompt; accepts if ≥ 7/10 - cli/engine.py retries create_initial_persona() up to 3× until validation passes - Expected: -20% Phase 3 voice-drift rewrites Exp 5 — Mid-gen Consistency Snapshots (cli/engine.py): - analyze_consistency() called every 10 chapters inside the writing loop - Issues logged as ⚠️ warnings; non-blocking; score and summary emitted - Expected: -30% post-generation continuity error rate Exp 7 — Two-Pass Drafting (story/writer.py): - After Flash rough draft, Pro model (model_logic) polishes prose against a strict checklist: filter words, deep POV, active voice, AI-isms, chapter hook - max_attempts reduced 3 → 2 since polished prose needs fewer rewrite cycles - Expected: +0.3 HQS with no increase in per-chapter cost Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -50,9 +50,16 @@ def process_book(bp, folder, context="", resume=False, interactive=False):
|
||||
bp = planner.enrich(bp, folder, context)
|
||||
with open(bp_path, "w") as f: json.dump(bp, f, indent=2)
|
||||
|
||||
# Ensure Persona Exists (Auto-create if missing)
|
||||
# Ensure Persona Exists (Auto-create + Exp 6: Validate before accepting)
|
||||
if 'author_details' not in bp['book_metadata'] or not bp['book_metadata']['author_details']:
|
||||
bp['book_metadata']['author_details'] = style_persona.create_initial_persona(bp, folder)
|
||||
max_persona_attempts = 3
|
||||
for persona_attempt in range(1, max_persona_attempts + 1):
|
||||
candidate_persona = style_persona.create_initial_persona(bp, folder)
|
||||
is_valid, p_score = style_persona.validate_persona(bp, candidate_persona, folder)
|
||||
if is_valid or persona_attempt == max_persona_attempts:
|
||||
bp['book_metadata']['author_details'] = candidate_persona
|
||||
break
|
||||
utils.log("SYSTEM", f" -> Persona attempt {persona_attempt}/{max_persona_attempts} scored {p_score}/10. Regenerating...")
|
||||
with open(bp_path, "w") as f: json.dump(bp, f, indent=2)
|
||||
except Exception as _e:
|
||||
utils.log("ERROR", f"Blueprint phase failed: {type(_e).__name__}: {_e}")
|
||||
@@ -268,6 +275,21 @@ def process_book(bp, folder, context="", resume=False, interactive=False):
|
||||
# Update Structured Story State (Item 9: Thread Tracking)
|
||||
current_story_state = story_state.update_story_state(txt, ch['chapter_number'], current_story_state, folder)
|
||||
|
||||
# Exp 5: Mid-gen Consistency Snapshot (every 10 chapters)
|
||||
if len(ms) > 0 and len(ms) % 10 == 0:
|
||||
utils.log("EDITOR", f"--- Mid-gen consistency check after chapter {ch['chapter_number']} ({len(ms)} written) ---")
|
||||
try:
|
||||
consistency = story_editor.analyze_consistency(bp, ms, folder)
|
||||
issues = consistency.get('issues', [])
|
||||
if issues:
|
||||
for issue in issues:
|
||||
utils.log("EDITOR", f" ⚠️ {issue}")
|
||||
c_score = consistency.get('score', 'N/A')
|
||||
c_summary = consistency.get('summary', '')
|
||||
utils.log("EDITOR", f" Consistency score: {c_score}/10 — {c_summary}")
|
||||
except Exception as _ce:
|
||||
utils.log("EDITOR", f" Mid-gen consistency check failed (non-blocking): {_ce}")
|
||||
|
||||
# Dynamic Pacing Check (every other chapter)
|
||||
remaining = chapters[i+1:]
|
||||
if remaining and len(remaining) >= 2 and i % 2 == 1:
|
||||
|
||||
Reference in New Issue
Block a user