Merge branch 'feature/caller-redesign' into main
Brings in the Phase 5B caller-generation rewrite: - Slim two-stage pipeline: Sonnet 4.6 batch identity pregen at session start, Haiku 4.5 live dialog per turn. Deletes CallerBackground dataclass, shape/style/voice-matching, per-model routing, preflight UI. - New caller_gen.py (slim prompt builder) and regulars_v2.py (Obsidian lore loader for named recurring callers). - Reworked caller buttons and info panel around the slim background: identity, situation, signature, secret want. Removes shape badges, energy dots, emotion info-badges. - Inworld TTS: emotional_register -> (temperature, speed_adjust) mapping via _emotional_register_to_params(). applyTextNormalization ON. - Silas identity/voice leak fix, avatar gender, pre-warm batch gen. - Archives old regulars to data/regulars.archived.json, adds 10 sample caller transcripts under docs/samples/. Post-merge fixes applied during resolution: - intern.py: kept main's richer new_show() (NEW SHOW history marker, trim, _save()) and _track_suggestion(); removed the branch's duplicate minimal new_show() stub. - tts.py: added 5 voice speed overrides (Graham, Malcolm, Victoria, Loretta, Marlene) that main had tuned locally. Evelyn deliberately NOT added to VOICE_PROFILES — she is in BLACKLISTED_VOICES for unnatural prosody. - Main's cost dashboard polish, LLM per-model params, and Devon show context memory from commits c087c03..61b3cba carried through cleanly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,13 +42,14 @@ Required in `.env`:
|
||||
- `generate_with_tools()` in llm.py supports OpenRouter function calling for the intern feature
|
||||
|
||||
## Caller Generation System
|
||||
- **CallerBackground dataclass**: Structured output from LLM background generation (JSON mode). Fields: name, age, gender, job, location, reason_for_calling, pool_name, communication_style, energy_level, emotional_state, signature_detail, situation_summary, natural_description, seeds, verbal_fluency, calling_from.
|
||||
- **Voice-personality matching**: `_match_voices_to_styles()` runs after background generation. 68 voice profiles in `VOICE_PROFILES` (tts.py), 18 style-to-voice mappings in `STYLE_VOICE_PREFERENCES` (main.py). Soft matching — scores voices against style preferences.
|
||||
- **Adaptive call shapes**: `SHAPE_STYLE_AFFINITIES` maps communication styles to shape weight multipliers. Consecutive shape repeats are dampened.
|
||||
- **Inter-caller awareness**: Thematic matching in `get_show_history()` scores previous callers by keyword/category overlap. Adaptive reaction frequency (60%/35%/15%). Show energy tracking via `_get_show_energy()`.
|
||||
- **Caller memory**: Returning callers store structured backgrounds, key moments, arc status, and relationships with other regulars. `RegularCallerService` has `add_relationship()` and expanded `update_after_call()`.
|
||||
- **Show pacing**: `_sort_caller_queue()` sorts presentation order by energy alternation, topic variety, shape variety.
|
||||
- **Call quality signals**: `_assess_call_quality()` captures exchange count, response length, host engagement, shape target hit, natural ending.
|
||||
- **Two-stage pipeline**: (1) batch identity pregen via Sonnet 4.6 at session start, (2) live dialog via Haiku 4.5 per turn. Cost ~$1/show.
|
||||
- **Slim caller dict**: Populated once at `Session._pregenerate_backgrounds()` via `caller_gen.generate_batch()`. Keys: `name`, `age`, `voice`, `location`, `identity`, `situation`, `reason_calling`, `opening_line`, `secret_want`, `specific_details`, `emotional_register`. Stored in `session.caller_backgrounds[caller_key]`.
|
||||
- **Dialog model**: Always Haiku 4.5 via the `caller_dialog` category in `config.category_models`. No per-caller model routing — deleted in Phase 5B.
|
||||
- **Prompt builder**: `get_caller_prompt(caller)` in main.py builds the slim system prompt from the dict; see `tests/test_caller_prompt.py` for the contract.
|
||||
- **Regulars**: `backend/services/regulars_v2.py` loads lore from Obsidian markdown files for named recurring callers (e.g. Silas). The batch prompt optionally includes 2-3 active regulars per session.
|
||||
- **Inter-caller awareness**: `get_show_history()` scores previous callers by keyword overlap with the current caller's `situation`/`reason_calling`. Reaction frequency scales with match strength (60%/35%/15%).
|
||||
- **Caller memory**: Returning callers auto-promote from first-timers at ~5% probability after 8+ exchanges. `RegularCallerService` tracks summaries, relationships, arc state.
|
||||
- **Call quality signals**: `_assess_call_quality()` captures exchange count, response length, host engagement, caller depth, natural ending.
|
||||
|
||||
## Devon (Intern Character)
|
||||
- **Service**: `backend/services/intern.py` — persistent show character, not a caller
|
||||
@@ -62,8 +63,8 @@ Required in `.env`:
|
||||
## Frontend Control Panel
|
||||
- **Keyboard shortcuts**: 1-0 (callers), H (hangup), W (wrap up), M (music toggle), D (ask Devon), Escape (close modals)
|
||||
- **Wrap It Up**: Amber button that signals callers to wind down gracefully. Reduces response budget, injects wrap-up signals, forces goodbye after 2 exchanges.
|
||||
- **Caller info panel**: Shows call shape, energy level, emotional state, signature detail, situation summary during active calls
|
||||
- **Caller buttons**: Energy dots (colored by level) and shape badges on each button
|
||||
- **Caller info panel**: Shows identity, situation, signature detail, secret want during active calls
|
||||
- **Caller buttons**: Populated from the slim caller background dicts
|
||||
- **Pinned SFX**: Cheer/Applause/Boo always visible, rest collapsible
|
||||
- **Visual polish**: Thinking pulse, call glow, compact media row, smoother transitions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user