writers_room 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.envrc +1 -0
- data/CHANGELOG.md +186 -0
- data/COMMITS.md +196 -0
- data/LICENSE +21 -0
- data/README.md +572 -0
- data/Rakefile +12 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/bin/wr +9 -0
- data/docs/configuration.md +361 -0
- data/docs/project_structure.md +226 -0
- data/docs/quick_reference.md +200 -0
- data/docs/quick_start.md +264 -0
- data/lib/writers_room/actor.rb +324 -0
- data/lib/writers_room/cli/actor.rb +57 -0
- data/lib/writers_room/cli/config.rb +29 -0
- data/lib/writers_room/cli/direct.rb +91 -0
- data/lib/writers_room/cli/init.rb +51 -0
- data/lib/writers_room/cli/version.rb +14 -0
- data/lib/writers_room/cli.rb +73 -0
- data/lib/writers_room/config.rb +98 -0
- data/lib/writers_room/director.rb +262 -0
- data/lib/writers_room/version.rb +5 -0
- data/lib/writers_room.rb +15 -0
- metadata +97 -0
data/README.md
ADDED
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
# Writer's Room - AI-Powered Multi-Character Dialog System
|
|
2
|
+
|
|
3
|
+
An experimental Ruby-based system for generating multi-character dialog using independent AI agents. Each character is an autonomous actor process that uses LLMs to generate dialog while maintaining consistent personality and voice.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Writer's Room is designed to experiment with AI-driven theatrical dialog. It features:
|
|
8
|
+
|
|
9
|
+
- **6 Distinct Characters**: Marcus, Jamie, Tyler, Alex, Benny, and Zoe from a comedic teen play
|
|
10
|
+
- **8 Detailed Scenes**: Complete scene breakdowns with objectives, beats, and relationship progressions
|
|
11
|
+
- **Independent Actor Processes**: Each character runs as a separate Ruby process
|
|
12
|
+
- **Redis-Based Communication**: Actors communicate via SmartMessage over Redis pub/sub
|
|
13
|
+
- **LLM-Powered Dialog**: Uses RubyLLM with Ollama (gpt-oss model) by default
|
|
14
|
+
- **Director Orchestration**: Manages multiple actors and produces transcripts
|
|
15
|
+
- **Flexible Configuration**: Easy switching between Ollama, OpenAI, Anthropic, or other providers
|
|
16
|
+
|
|
17
|
+
## Project Structure
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
writers_room/
|
|
21
|
+
├── actor.rb # Actor class (executable)
|
|
22
|
+
├── director.rb # Director orchestration script (executable)
|
|
23
|
+
├── run_scene_example.sh # Quick start launcher (executable)
|
|
24
|
+
├── messages/ # SmartMessage subclasses
|
|
25
|
+
│ ├── dialog_message.rb
|
|
26
|
+
│ ├── scene_control_message.rb
|
|
27
|
+
│ ├── stage_direction_message.rb
|
|
28
|
+
│ └── meta_message.rb
|
|
29
|
+
├── projects/ # Project-based organization
|
|
30
|
+
│ └── teen_play/ # Teen comedy play project
|
|
31
|
+
│ ├── project.yml # Project metadata (title, tagline, description)
|
|
32
|
+
│ ├── characters/ # Character YAML definitions
|
|
33
|
+
│ │ ├── marcus.yml
|
|
34
|
+
│ │ ├── jamie.yml
|
|
35
|
+
│ │ ├── tyler.yml
|
|
36
|
+
│ │ ├── alex.yml
|
|
37
|
+
│ │ ├── benny.yml
|
|
38
|
+
│ │ └── zoe.yml
|
|
39
|
+
│ └── scenes/ # Scene YAML definitions
|
|
40
|
+
│ ├── scene_01_gym_wars.yml
|
|
41
|
+
│ ├── scene_02_statistical_anomaly.yml
|
|
42
|
+
│ ├── scene_04_equipment_room.yml
|
|
43
|
+
│ └── scene_08_data_dump.yml
|
|
44
|
+
└── logs/ # Actor process logs (created automatically)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Note**: The project structure allows multiple independent projects. Character directories are auto-detected from scene file paths.
|
|
48
|
+
|
|
49
|
+
## Requirements
|
|
50
|
+
|
|
51
|
+
### System Requirements
|
|
52
|
+
- Ruby 3.0+
|
|
53
|
+
- Redis server running locally or accessible
|
|
54
|
+
- MacStudio M2max (or similar)
|
|
55
|
+
|
|
56
|
+
### Ruby Gems
|
|
57
|
+
```bash
|
|
58
|
+
gem install debug_me
|
|
59
|
+
gem install ruby_llm
|
|
60
|
+
gem install smart_message
|
|
61
|
+
gem install redis
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Setup
|
|
65
|
+
|
|
66
|
+
### 1. Start Redis Server
|
|
67
|
+
|
|
68
|
+
Ensure Redis is running:
|
|
69
|
+
```bash
|
|
70
|
+
redis-server
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or if using Homebrew:
|
|
74
|
+
```bash
|
|
75
|
+
brew services start redis
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. Configure LLM Provider
|
|
79
|
+
|
|
80
|
+
**Default Configuration: Ollama with gpt-oss model**
|
|
81
|
+
|
|
82
|
+
The system is pre-configured to use Ollama with the `gpt-oss` model. Ensure Ollama is running:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Start Ollama
|
|
86
|
+
ollama serve
|
|
87
|
+
|
|
88
|
+
# Pull the gpt-oss model if you haven't already
|
|
89
|
+
ollama pull gpt-oss
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Using Different Providers (Optional)**
|
|
93
|
+
|
|
94
|
+
You can override the default Ollama configuration with environment variables:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Use a different Ollama model
|
|
98
|
+
export RUBY_LLM_MODEL="llama2"
|
|
99
|
+
|
|
100
|
+
# Use Ollama on a different host
|
|
101
|
+
export OLLAMA_URL="http://192.168.1.100:11434"
|
|
102
|
+
|
|
103
|
+
# Switch to OpenAI
|
|
104
|
+
export RUBY_LLM_PROVIDER="openai"
|
|
105
|
+
export OPENAI_API_KEY="your-key-here"
|
|
106
|
+
|
|
107
|
+
# Switch to Anthropic
|
|
108
|
+
export RUBY_LLM_PROVIDER="anthropic"
|
|
109
|
+
export ANTHROPIC_API_KEY="your-key-here"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3. Verify Setup
|
|
113
|
+
|
|
114
|
+
Test that Redis is accessible:
|
|
115
|
+
```bash
|
|
116
|
+
redis-cli ping
|
|
117
|
+
# Should return: PONG
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Test that Ollama is accessible:
|
|
121
|
+
```bash
|
|
122
|
+
curl http://localhost:11434
|
|
123
|
+
# Should return Ollama version info
|
|
124
|
+
|
|
125
|
+
ollama list | grep gpt-oss
|
|
126
|
+
# Should show the gpt-oss model
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 4. Configuration Reference
|
|
130
|
+
|
|
131
|
+
For detailed configuration options, see **[CONFIGURATION.md](CONFIGURATION.md)**
|
|
132
|
+
|
|
133
|
+
Quick reference:
|
|
134
|
+
- Default provider: Ollama with gpt-oss model
|
|
135
|
+
- Switch models: `export RUBY_LLM_MODEL="llama2"`
|
|
136
|
+
- Switch providers: `export RUBY_LLM_PROVIDER="openai"`
|
|
137
|
+
- Debug mode: `export DEBUG_ME=1`
|
|
138
|
+
|
|
139
|
+
## Usage
|
|
140
|
+
|
|
141
|
+
### Running a Scene
|
|
142
|
+
|
|
143
|
+
The simplest way to run a scene is using the director:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
./director.rb -s projects/teen_play/scenes/scene_01_gym_wars.yml
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
This will:
|
|
150
|
+
1. Load the scene configuration
|
|
151
|
+
2. Auto-detect the character directory (`projects/teen_play/characters/`)
|
|
152
|
+
3. Start actor processes for all characters in the scene
|
|
153
|
+
4. Monitor and display their dialog in real-time
|
|
154
|
+
5. Save a transcript when complete
|
|
155
|
+
|
|
156
|
+
### Director Options
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
./director.rb [options]
|
|
160
|
+
|
|
161
|
+
Options:
|
|
162
|
+
-s, --scene FILE Scene YAML file (required)
|
|
163
|
+
-c, --characters DIR Character directory (auto-detected if not specified)
|
|
164
|
+
-o, --output FILE Transcript output file
|
|
165
|
+
-l, --max-lines N Maximum lines before ending (default: 50)
|
|
166
|
+
-h, --help Show help
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Examples
|
|
170
|
+
|
|
171
|
+
**Run Scene 1 with default settings:**
|
|
172
|
+
```bash
|
|
173
|
+
./director.rb -s projects/teen_play/scenes/scene_01_gym_wars.yml
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Run Scene 2 with custom transcript name:**
|
|
177
|
+
```bash
|
|
178
|
+
./director.rb -s projects/teen_play/scenes/scene_02_statistical_anomaly.yml -o scene2_take1.txt
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Run Scene 4 with more lines:**
|
|
182
|
+
```bash
|
|
183
|
+
./director.rb -s projects/teen_play/scenes/scene_04_equipment_room.yml -l 100
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Running Individual Actors
|
|
187
|
+
|
|
188
|
+
You can also run actors manually for testing:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
./actor.rb -c projects/teen_play/characters/marcus.yml -s projects/teen_play/scenes/scene_01_gym_wars.yml
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
In a separate terminal, run another actor:
|
|
195
|
+
```bash
|
|
196
|
+
./actor.rb -c projects/teen_play/characters/jamie.yml -s projects/teen_play/scenes/scene_01_gym_wars.yml
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
They will automatically begin conversing via Redis.
|
|
200
|
+
|
|
201
|
+
## Character Definitions
|
|
202
|
+
|
|
203
|
+
Each character is defined in a YAML file with the following structure:
|
|
204
|
+
|
|
205
|
+
```yaml
|
|
206
|
+
name: Marcus
|
|
207
|
+
age: 16
|
|
208
|
+
personality: |
|
|
209
|
+
Description of character traits and behaviors...
|
|
210
|
+
|
|
211
|
+
voice_pattern: |
|
|
212
|
+
How the character speaks, example phrases...
|
|
213
|
+
|
|
214
|
+
sport: Basketball team statistician
|
|
215
|
+
|
|
216
|
+
relationships:
|
|
217
|
+
Jamie: "Current relationship status..."
|
|
218
|
+
Tyler: "Current relationship status..."
|
|
219
|
+
# ... other characters
|
|
220
|
+
|
|
221
|
+
current_arc: |
|
|
222
|
+
Where the character is in their development...
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
See `projects/teen_play/characters/` directory for complete examples.
|
|
226
|
+
|
|
227
|
+
## Scene Definitions
|
|
228
|
+
|
|
229
|
+
Scenes are defined in YAML with detailed structure:
|
|
230
|
+
|
|
231
|
+
```yaml
|
|
232
|
+
scene_number: 1
|
|
233
|
+
scene_name: "The Gym Wars"
|
|
234
|
+
week: 1
|
|
235
|
+
location: "School gymnasium"
|
|
236
|
+
|
|
237
|
+
context: |
|
|
238
|
+
Detailed scene setup and situation...
|
|
239
|
+
|
|
240
|
+
characters:
|
|
241
|
+
- Marcus
|
|
242
|
+
- Jamie
|
|
243
|
+
- Tyler
|
|
244
|
+
- Alex
|
|
245
|
+
- Benny
|
|
246
|
+
- Zoe
|
|
247
|
+
|
|
248
|
+
scene_objectives:
|
|
249
|
+
Marcus: |
|
|
250
|
+
What Marcus wants to achieve in this scene...
|
|
251
|
+
Jamie: |
|
|
252
|
+
What Jamie wants to achieve in this scene...
|
|
253
|
+
# ... objectives for all characters
|
|
254
|
+
|
|
255
|
+
beat_structure:
|
|
256
|
+
- beat: "The Standoff"
|
|
257
|
+
duration: "2 minutes"
|
|
258
|
+
description: "What happens in this beat..."
|
|
259
|
+
|
|
260
|
+
- beat: "The Negotiators"
|
|
261
|
+
duration: "3 minutes"
|
|
262
|
+
description: "What happens in this beat..."
|
|
263
|
+
|
|
264
|
+
relationship_status:
|
|
265
|
+
Marcus_Jamie: "Strangers → Intrigued"
|
|
266
|
+
Tyler_Alex: "Rivals → Respectful competitors"
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
See `projects/teen_play/scenes/` directory for complete examples.
|
|
270
|
+
|
|
271
|
+
## How It Works
|
|
272
|
+
|
|
273
|
+
### Architecture
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
┌─────────────────────────────────────────────────────────┐
|
|
277
|
+
│ DIRECTOR │
|
|
278
|
+
│ - Spawns actor processes │
|
|
279
|
+
│ - Monitors dialog via Redis │
|
|
280
|
+
│ - Saves transcripts │
|
|
281
|
+
└─────────────────┬───────────────────────────────────────┘
|
|
282
|
+
│
|
|
283
|
+
┌────────┴────────┐
|
|
284
|
+
│ │
|
|
285
|
+
Redis Pub/Sub Redis Pub/Sub
|
|
286
|
+
│ │
|
|
287
|
+
┌────┴────┐ ┌────┴────┐
|
|
288
|
+
│ Actor │ │ Actor │
|
|
289
|
+
│ Process │←─────→│ Process │
|
|
290
|
+
│ (Marcus)│ │ (Jamie) │
|
|
291
|
+
└─────────┘ └─────────┘
|
|
292
|
+
│ │
|
|
293
|
+
RubyLLM RubyLLM
|
|
294
|
+
│ │
|
|
295
|
+
LLM Provider LLM Provider
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Message Flow
|
|
299
|
+
|
|
300
|
+
1. **Director** sends `SceneControlMessage` to start scene
|
|
301
|
+
2. **Actors** subscribe to `writers_room:dialog` channel
|
|
302
|
+
3. **Actor** generates dialog using character info + scene context + conversation history
|
|
303
|
+
4. **Actor** publishes `DialogMessage` to Redis
|
|
304
|
+
5. **Other Actors** receive message, decide whether to respond
|
|
305
|
+
6. **Actor** generates response if appropriate
|
|
306
|
+
7. **Director** monitors all messages and records transcript
|
|
307
|
+
|
|
308
|
+
### Dialog Generation
|
|
309
|
+
|
|
310
|
+
Each actor uses a two-part prompt system:
|
|
311
|
+
|
|
312
|
+
**System Prompt:**
|
|
313
|
+
- Character profile (personality, voice pattern, age, sport)
|
|
314
|
+
- Current character arc
|
|
315
|
+
- Relationship statuses
|
|
316
|
+
- Scene context and objectives
|
|
317
|
+
- Instructions for staying in character
|
|
318
|
+
|
|
319
|
+
**User Prompt:**
|
|
320
|
+
- Recent conversation history (last 10 exchanges)
|
|
321
|
+
- Additional context (if responding to specific dialog)
|
|
322
|
+
- Prompt: "What does [Character] say?"
|
|
323
|
+
|
|
324
|
+
The LLM generates a response, which is cleaned and published as dialog.
|
|
325
|
+
|
|
326
|
+
### Response Decision Logic
|
|
327
|
+
|
|
328
|
+
Actors decide whether to respond based on:
|
|
329
|
+
1. **Direct address**: Name mentioned in dialog
|
|
330
|
+
2. **Conversation flow**: Not spoken recently, appropriate turn
|
|
331
|
+
3. **Random interjection**: 10% chance to interject
|
|
332
|
+
4. **Character-specific logic**: Can be customized per character
|
|
333
|
+
|
|
334
|
+
## SmartMessage Integration
|
|
335
|
+
|
|
336
|
+
The system uses SmartMessage subclasses for type-safe Redis communication:
|
|
337
|
+
|
|
338
|
+
### DialogMessage
|
|
339
|
+
```ruby
|
|
340
|
+
DialogMessage.new(
|
|
341
|
+
from: "Marcus",
|
|
342
|
+
content: "There's a 73% chance this will work!",
|
|
343
|
+
scene: 1,
|
|
344
|
+
timestamp: Time.now.to_i,
|
|
345
|
+
emotion: "excited", # optional
|
|
346
|
+
addressing: "Jamie" # optional
|
|
347
|
+
)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### SceneControlMessage
|
|
351
|
+
```ruby
|
|
352
|
+
SceneControlMessage.start_scene(1)
|
|
353
|
+
SceneControlMessage.stop_scene(1)
|
|
354
|
+
SceneControlMessage.end_scene(1)
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### StageDirectionMessage
|
|
358
|
+
```ruby
|
|
359
|
+
StageDirectionMessage.new(
|
|
360
|
+
character: "Marcus",
|
|
361
|
+
action: "pulls out tablet nervously",
|
|
362
|
+
scene: 1,
|
|
363
|
+
timestamp: Time.now.to_i
|
|
364
|
+
)
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Output
|
|
368
|
+
|
|
369
|
+
### Transcript Format
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
SCENE 1: The Gym Wars
|
|
373
|
+
Location: Riverside High gymnasium
|
|
374
|
+
Week: 1
|
|
375
|
+
|
|
376
|
+
------------------------------------------------------------
|
|
377
|
+
|
|
378
|
+
Tyler: We're here until 6:30.
|
|
379
|
+
Alex: So are we. Guess we're roommates.
|
|
380
|
+
Marcus: According to the scheduling system, there's been an error...
|
|
381
|
+
Jamie: Let me see that code. Oh, I see the bug!
|
|
382
|
+
Benny: Can we just settle this with rock-paper-scissors?
|
|
383
|
+
Zoe: As Shakespeare once said... actually, this is more West Side Story!
|
|
384
|
+
|
|
385
|
+
[continues...]
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Statistics Output
|
|
389
|
+
|
|
390
|
+
```
|
|
391
|
+
============================================================
|
|
392
|
+
SCENE STATISTICS
|
|
393
|
+
============================================================
|
|
394
|
+
Total lines: 47
|
|
395
|
+
|
|
396
|
+
Lines by character:
|
|
397
|
+
Marcus: 12
|
|
398
|
+
Jamie: 11
|
|
399
|
+
Tyler: 9
|
|
400
|
+
Alex: 8
|
|
401
|
+
Benny: 4
|
|
402
|
+
Zoe: 3
|
|
403
|
+
============================================================
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Debugging
|
|
407
|
+
|
|
408
|
+
### Enable Debug Output
|
|
409
|
+
|
|
410
|
+
The system uses the `debug_me` gem. To see debug output:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
DEBUG_ME=1 ./director.rb -s projects/teen_play/scenes/scene_01_gym_wars.yml
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Actor Logs
|
|
417
|
+
|
|
418
|
+
Individual actor logs are saved in the `logs/` directory:
|
|
419
|
+
- `logs/marcus_[timestamp].log` - Standard output
|
|
420
|
+
- `logs/marcus_[timestamp]_err.log` - Error output
|
|
421
|
+
|
|
422
|
+
### Monitor Redis
|
|
423
|
+
|
|
424
|
+
Watch Redis traffic in real-time:
|
|
425
|
+
```bash
|
|
426
|
+
redis-cli monitor
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Or subscribe to the dialog channel:
|
|
430
|
+
```bash
|
|
431
|
+
redis-cli
|
|
432
|
+
> SUBSCRIBE writers_room:dialog
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Customization
|
|
436
|
+
|
|
437
|
+
### Adding New Characters
|
|
438
|
+
|
|
439
|
+
1. Create a new YAML file in `projects/teen_play/characters/` (or your own project):
|
|
440
|
+
```yaml
|
|
441
|
+
name: NewCharacter
|
|
442
|
+
age: 16
|
|
443
|
+
personality: |
|
|
444
|
+
Character description...
|
|
445
|
+
voice_pattern: |
|
|
446
|
+
How they speak...
|
|
447
|
+
# ... etc
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
2. Add to scene's character list
|
|
451
|
+
3. Run the scene
|
|
452
|
+
|
|
453
|
+
### Adding New Scenes
|
|
454
|
+
|
|
455
|
+
1. Create scene YAML in `projects/teen_play/scenes/` (or your own project):
|
|
456
|
+
```yaml
|
|
457
|
+
scene_number: 9
|
|
458
|
+
scene_name: "New Scene"
|
|
459
|
+
characters:
|
|
460
|
+
- Character1
|
|
461
|
+
- Character2
|
|
462
|
+
scene_objectives:
|
|
463
|
+
Character1: |
|
|
464
|
+
Objective...
|
|
465
|
+
# ... etc
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
2. Run with director:
|
|
469
|
+
```bash
|
|
470
|
+
./director.rb -s projects/teen_play/scenes/scene_09_new_scene.yml
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
The director will auto-detect the character directory from the scene path.
|
|
474
|
+
|
|
475
|
+
### Customizing LLM Behavior
|
|
476
|
+
|
|
477
|
+
Edit the prompt building methods in `actor.rb`:
|
|
478
|
+
- `build_system_prompt` - Character definition and instructions
|
|
479
|
+
- `build_user_prompt` - Conversation context
|
|
480
|
+
|
|
481
|
+
### Adjusting Response Logic
|
|
482
|
+
|
|
483
|
+
Modify `should_respond?` method in `actor.rb` to change when actors speak.
|
|
484
|
+
|
|
485
|
+
## The Play: Character Arcs
|
|
486
|
+
|
|
487
|
+
The complete play spans 8 scenes over 16 weeks:
|
|
488
|
+
|
|
489
|
+
### Three Couples
|
|
490
|
+
|
|
491
|
+
**Marcus & Jamie** - "The Analysts"
|
|
492
|
+
- Arc: From "love is logical" → "love is beyond logic"
|
|
493
|
+
- Connection: Intellectual equals who make each other braver
|
|
494
|
+
|
|
495
|
+
**Tyler & Alex** - "The Captains"
|
|
496
|
+
- Arc: From rivals → teammates in life
|
|
497
|
+
- Connection: Competitive but supportive, bring out vulnerability
|
|
498
|
+
|
|
499
|
+
**Benny & Zoe** - "The Performers"
|
|
500
|
+
- Arc: From hiding behind personas → authentic selves
|
|
501
|
+
- Connection: See through each other's acts, permission to be real
|
|
502
|
+
|
|
503
|
+
### Timeline
|
|
504
|
+
|
|
505
|
+
- **Week 1** (Scene 1): Everyone meets
|
|
506
|
+
- **Week 2** (Scene 2): Marcus/Jamie bond over algorithm
|
|
507
|
+
- **Week 4** (Scene 3): Tyler/Alex forced to work together
|
|
508
|
+
- **Week 6** (Scene 4): Benny/Zoe breakthrough in equipment room
|
|
509
|
+
- **Week 8** (Scene 5): Group chat catastrophe, all feelings revealed
|
|
510
|
+
- **Week 10** (Scene 6): Track meet, relationships solidify
|
|
511
|
+
- **Week 14** (Scene 7): Championship games, Tyler/Alex first kiss
|
|
512
|
+
- **Week 16** (Scene 8): Algorithm revealed wrong, love wins
|
|
513
|
+
|
|
514
|
+
See the detailed planning documents for complete scene breakdowns, character maps, and relationship timelines.
|
|
515
|
+
|
|
516
|
+
## Troubleshooting
|
|
517
|
+
|
|
518
|
+
### Redis Connection Issues
|
|
519
|
+
```bash
|
|
520
|
+
# Check Redis is running
|
|
521
|
+
redis-cli ping
|
|
522
|
+
|
|
523
|
+
# Check Redis logs
|
|
524
|
+
tail -f /usr/local/var/log/redis.log
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Actor Process Issues
|
|
528
|
+
```bash
|
|
529
|
+
# Check running actor processes
|
|
530
|
+
ps aux | grep actor.rb
|
|
531
|
+
|
|
532
|
+
# Kill hung processes
|
|
533
|
+
pkill -f actor.rb
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### LLM API Issues
|
|
537
|
+
- Verify API keys are set correctly
|
|
538
|
+
- Check rate limits on your LLM provider
|
|
539
|
+
- Review actor logs in `logs/` directory
|
|
540
|
+
|
|
541
|
+
## Performance Tips
|
|
542
|
+
|
|
543
|
+
1. **Limit dialog exchanges** with `-l` flag to prevent runaway conversations
|
|
544
|
+
2. **Use faster models** for experimentation (e.g., GPT-3.5, Claude Haiku)
|
|
545
|
+
3. **Run fewer actors** initially to test scene dynamics
|
|
546
|
+
4. **Monitor Redis memory** with `redis-cli info memory`
|
|
547
|
+
|
|
548
|
+
## Future Enhancements
|
|
549
|
+
|
|
550
|
+
Potential areas for expansion:
|
|
551
|
+
|
|
552
|
+
- [ ] Stage direction generation
|
|
553
|
+
- [ ] Emotion detection and tracking
|
|
554
|
+
- [ ] Dynamic scene beat progression
|
|
555
|
+
- [ ] Multi-scene continuity
|
|
556
|
+
- [ ] Voice synthesis integration
|
|
557
|
+
- [ ] Visual character representation
|
|
558
|
+
- [ ] Real-time web interface
|
|
559
|
+
- [ ] Character memory/learning across scenes
|
|
560
|
+
- [ ] Playwright format export
|
|
561
|
+
|
|
562
|
+
## License
|
|
563
|
+
|
|
564
|
+
Experimental project for educational purposes.
|
|
565
|
+
|
|
566
|
+
## Credits
|
|
567
|
+
|
|
568
|
+
Created for exploring multi-agent AI dialog generation using Ruby, RubyLLM, and SmartMessage.
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
**Happy Writing!** 🎭
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
require "writers_room"
|
|
6
|
+
|
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
+
|
|
10
|
+
require "irb"
|
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED