-
Notifications
You must be signed in to change notification settings - Fork 274
Expand file tree
/
Copy pathgen_characters.py
More file actions
148 lines (124 loc) · 5.47 KB
/
Copy pathgen_characters.py
File metadata and controls
148 lines (124 loc) · 5.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python3
"""
One-shot characters.md generator for foundation phase.
Reads seed.txt + voice.md + world.md + CRAFT.md, calls writer model.
"""
import os
import sys
from pathlib import Path
from dotenv import load_dotenv
BASE_DIR = Path(__file__).parent
load_dotenv(BASE_DIR / ".env")
WRITER_MODEL = os.environ.get("AUTONOVEL_WRITER_MODEL", "claude-sonnet-4-6")
API_KEY = os.environ.get("ANTHROPIC_API_KEY", "")
API_BASE = os.environ.get("AUTONOVEL_API_BASE_URL", "https://api.anthropic.com")
def call_writer(prompt, max_tokens=16000):
import httpx
headers = {
"x-api-key": API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
}
payload = {
"model": WRITER_MODEL,
"max_tokens": max_tokens,
"temperature": 0.7,
"system": (
"You are a character designer for literary fiction with deep knowledge of "
"wound/want/need/lie frameworks, Sanderson's three sliders, and dialogue "
"distinctiveness. You create characters who feel like real people with "
"contradictions, secrets, and speech patterns you can hear. "
"You never use AI slop words. You write in clean, direct prose."
),
"messages": [{"role": "user", "content": prompt}],
}
resp = httpx.post(f"{API_BASE}/v1/messages", headers=headers, json=payload, timeout=300)
resp.raise_for_status()
return resp.json()["content"][0]["text"]
seed = (BASE_DIR / "seed.txt").read_text()
world = (BASE_DIR / "world.md").read_text()
# Voice Part 2 only
voice = (BASE_DIR / "voice.md").read_text()
voice_lines = voice.split('\n')
part2_start = next(i for i, l in enumerate(voice_lines) if 'Part 2' in l)
voice_part2 = '\n'.join(voice_lines[part2_start:])
prompt = f"""Build a complete character registry for this fantasy novel. This is CHARACTERS.MD --
the definitive reference for WHO exists in this story, what drives them, how they speak,
and what secrets they carry.
SEED CONCEPT:
{seed}
WORLD BIBLE (the world these characters inhabit):
{world}
VOICE IDENTITY (the novel's tone):
{voice_part2}
CHARACTER CRAFT REQUIREMENTS (from CRAFT.md):
### The Three Sliders (Sanderson)
Every character has three independent dials (0-10):
PROACTIVITY -- Do they drive the plot or react to it?
LIKABILITY -- Does the reader empathize with them?
COMPETENCE -- Are they good at what they do?
Rule: compelling = HIGH on at least TWO, or HIGH on one with clear growth.
### Wound / Want / Need / Lie Framework
A causal chain:
GHOST (backstory event) -> WOUND (ongoing damage) -> LIE (false belief to cope)
-> WANT (external goal driven by Lie) -> NEED (internal truth, opposes Lie)
Rules: Want and Need must be IN TENSION. Lie statable in one sentence.
Truth is its direct opposite.
### Dialogue Distinctiveness (8 dimensions)
1. Vocabulary level 2. Sentence length 3. Contractions/formality
4. Verbal tics 5. Question vs statement ratio 6. Interruption patterns
7. Metaphor domain 8. Directness vs indirectness
Test: Remove dialogue tags. Can you tell who's speaking?
BUILD THE REGISTRY WITH AT LEAST THESE CHARACTERS:
1. **Cass Bellwright** (protagonist, POV character)
- Full wound/want/need/lie chain
- Three sliders with justification
- Arc type (positive/negative/flat)
- Detailed speech pattern (8 dimensions)
- Physical habits and tells
- At least 2 secrets
- Key relationships mapped
2. **Eddan Bellwright** (father)
- Same depth as Cass
- His relationship to the sealed journals, the shaking hands
- What he knows and what he's hiding
3. **Perin Bellwright** (brother)
- Even though he's absent for much of the story, he needs full depth
- What actually happened with the Corda contract
- His presence through absence
4. **Maret Corda** (antagonist)
- Not a villain -- someone whose interests conflicts with Cass's
- Her own wound/want/need/lie (she should be understandable)
5. **Rector Suvaine** (Academy Chancellor)
- The institutional antagonist -- the system personified
- She believes she's protecting Cantamura
6. **Torvald Hess** (Compact leader)
- The outsider perspective on the system
- What he represents thematically
7. **At least 1-2 additional characters** that the story needs
- A peer/friend for Cass at the Academy?
- Someone at the House of Corda who knows Perin?
- A Court Singer with divided loyalties?
FOR EACH CHARACTER INCLUDE:
- Name, age, role
- Ghost/Wound/Want/Need/Lie chain (for major characters)
- Three sliders (proactivity/likability/competence) with numbers and justification
- Arc type and arc trajectory
- Speech pattern (all 8 dimensions, with example lines)
- Physical appearance (specific, not generic)
- Physical habits and unconscious tells
- Secrets (what the reader doesn't learn immediately)
- Key relationships (mapped to other characters)
- Thematic role (what question does this character embody?)
IMPORTANT:
- Characters must INTERCONNECT. Their wants should conflict with each other.
- Every secret should be something that would CHANGE the story if revealed.
- Speech patterns must be distinct enough to pass the no-tags test.
- Give Cass habits that come from his gift (the pain, the constant listening).
- The father's shaking hands should connect to something specific.
- Maret Corda should be as fully realized as Cass -- a worthy antagonist.
- Target ~3000-4000 words. Dense character work, not padding.
"""
print("Calling writer model...", file=sys.stderr)
result = call_writer(prompt)
print(result)