Files
opus-orchestrator-ai/opus_orchestrator/agents/fiction/voice.py
T
mrhavens dec5aae09a Wire up all agents with LLM calls
- Worldsmith, Character Lead, Voice, Editor agents now call LLM
- All nonfiction agents wired (Researcher, Analyst, Writer, FactChecker, Editor)
- Orchestrator fully wired with agent pipeline
- Add python-dotenv dependency
2026-03-12 18:42:15 +00:00

227 lines
6.5 KiB
Python

"""The Voice agent - Prose style and tone.
From Fiction Fortress Level 1-3:
- Role: Prose style and tone
- Responsibilities: Sentence-level writing, voice consistency
- Output: Prose samples, style guide
"""
from typing import Any
from opus_orchestrator.agents.base import AgentResponse, BaseAgent
VOICE_SYSTEM_PROMPT = """## Role: The Voice
You are The Voice — the owner of the prose itself, the sound, rhythm, and texture of the language. Your expertise lies in maintaining consistent style across thousands of words while adapting to scene-specific demands.
## Core Responsibilities
1. **Prose Style Control**
- Sentence rhythm variation (short/medium/long calibration)
- Vocabulary level management
- Figurative language deployment (metaphor, simile, symbolism density)
- Point of view intimacy maintenance
2. **Voice Consistency**
- Style guide creation and adherence
- Word bank maintenance
- Phrase pattern tracking
- Tone range specification (warm/cool, dark/light, etc.)
3. **Scene-Type Adaptation**
- Action scene pacing (sentence shortening)
- Emotional scene density (sentence complexity)
- Dialogue scene formatting
- Descriptive scene rhythm
- Exposition handling (invisible vs. visible)
4. **Point of View Management**
- Deep POV techniques
- Perspective consistency
- Head-hopping prevention
- Internal monologue integration
## Supporting Capabilities
- Dialogue attribution (said vs. action beats vs. no attribution)
- Punctuation style consistency
- Paragraph rhythm (white space management)
- Reader proximity calibration
## Voice Consistency Protocol
Maintain:
1. **Word bank** - Preferred vocabulary
2. **Phrase patterns** - Recurring constructions
3. **Rhythm map** - Sentence length distribution
4. **Tone guide** - Emotional range
## Quality Standards
- Voice must remain consistent across entire manuscript
- Scene type must inform prose style
- POV must be maintained without head-hopping
- Dialogue must sound distinct for each character
"""
class VoiceAgent(BaseAgent):
"""Agent responsible for prose style and voice consistency."""
def __init__(self, config=None):
super().__init__(
role="Voice",
description="Prose style and tone",
system_prompt=VOICE_SYSTEM_PROMPT,
config=config,
)
async def execute(self, input_data: Any, context: dict[str, Any]) -> AgentResponse:
"""Execute the Voice agent's task to create style guide and samples."""
genre = input_data.get("genre", "general")
tone = input_data.get("tone", "neutral")
target_audience = input_data.get("target_audience", "General readers")
user_prompt = f"""## Task
Create a voice/style guide and prose samples for:
- Genre: {genre}
- Tone: {tone}
- Target Audience: {target_audience}
## Guidelines
Follow the Voice agent methodology from your system prompt.
Include:
- Word bank (preferred vocabulary for this genre/tone)
- Phrase patterns (recurring constructions)
- Rhythm map (sentence length distribution)
- Tone guide (emotional range)
- 3 sample scenes:
1. Opening scene
2. Dialogue-heavy scene
3. Descriptive/pacific scene
Make the samples vivid and representative of the final prose style.
"""
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Voice", "genre": genre, "tone": tone},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Voice"},
)
async def write_chapter(
self,
chapter_spec: dict[str, Any],
style_guide: str,
context: dict[str, Any],
) -> AgentResponse:
"""Write a complete chapter following the style guide."""
user_prompt = f"""## Chapter Specification
- Chapter Number: {chapter_spec.get('chapter_number')}
- Title: {chapter_spec.get('title')}
- Summary: {chapter_spec.get('summary')}
- Word Count Target: {chapter_spec.get('word_count_target', 3000)}
- POV Character: {chapter_spec.get('pov_character', 'Narrator')}
- Key Events: {', '.join(chapter_spec.get('key_events', []))}
## Style Guide
{style_guide}
## Task
Write the complete chapter following the style guide and chapter specification.
Maintain consistent voice throughout. Make it vivid, engaging, and professional quality.
Start with the chapter title as a heading.
"""
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
word_count = len(result.split())
return AgentResponse(
success=True,
output={
"content": result,
"word_count": word_count,
"chapter_number": chapter_spec.get("chapter_number"),
},
metadata={"role": "Voice", "word_count": word_count},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Voice"},
)
async def polish_chapter(
self,
chapter_content: str,
style_guide: str,
context: dict[str, Any],
) -> AgentResponse:
"""Polish an existing chapter for voice consistency."""
user_prompt = f"""## Chapter to Polish
{chapter_content}
## Style Guide
{style_guide}
## Task
Polish this chapter for voice consistency. Ensure:
- Sentence rhythm varies appropriately
- Word choice matches the style guide
- Tone remains consistent
- POV is maintained without head-hopping
- Prose flows smoothly
- Show don't tell where possible
Return the polished chapter as your output.
"""
try:
result = await self.call_llm(
system_prompt=self.build_system_prompt(context),
user_prompt=user_prompt,
)
return AgentResponse(
success=True,
output=result,
metadata={"role": "Voice", "task": "polish"},
)
except Exception as e:
return AgentResponse(
success=False,
output=None,
error=str(e),
metadata={"role": "Voice"},
)