Commit graph

2 commits

Author SHA1 Message Date
a10874c574 Pin the transcript JSON keys so a stray "sender" cannot kill the podcast
The retried podcast failed with "Failed to parse ValidatedTranscript ... 2
validation errors ... missing": qwen3.5:27b had emitted "sender" instead of
"speaker" in 2 of 14 dialogue entries. Pydantic rejects the object, langchain
raises OUTPUT_PARSING_FAILURE and the entire job dies — after the outline and most
of the transcript were already done.

The template showed the schema as a JSON example but never forbade other key names,
so the model was free to drift. transcript.jinja now states the constraint
explicitly, right where the schema is defined.

This does not make the model deterministic — a parse failure still occurred once on
the next run, but podcast_creator's own retry absorbed it and the episode completed:
15:16 min of audio, 53 clips. Before the change the same failure was fatal.

Also, since this is the run that proved the non-root switch end to end: the final
MP3 is owned by dschlueter, and prune_podcast_data.py cleaned up the leftovers of
the two dead runs (5.5 MB) with a plain host-side rmtree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 15:56:02 +02:00
054f867a8a Fix podcasts generating in English + failing with invalid JSON
Two root causes, both fixed in the bind-mounted podcast prompt templates
(prompts/podcast/*.jinja):

1. Language: the episode profile's `language` field IS passed to both
   podcast_creator templates as {{ language }}, but the stock templates never
   reference it — so podcasts came out English (driven only by the English
   stock briefings/speakers), then read aloud by the German-locked Chatterbox
   TTS = "English with a German accent". Added a CRITICAL LANGUAGE REQUIREMENT
   block keyed on {{ language }} to both templates; now `language: "de"`
   actually forces German. Verified end-to-end: a full run produced a 44-line
   all-German transcript + audio.

2. Invalid json output failures: qwen3.5:27b is a thinking model; on long
   segments the <think> block ate the response-token budget and truncated the
   JSON. Prepended /no_think to both templates (~3x faster, valid JSON).

Templates are bind-mounted read-only via docker-compose (directory mount, so
edits survive a container restart without inode-staleness). Bundled briefings
and speaker backstories were also translated to German to reduce drift.

Known limitation documented: feeding an entire book (~70k tokens) as podcast
content makes each of the 6 LLM calls take ~3.5 min and is unreliable; use a
shorter source or summary. Confirmed working with concise content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 02:30:05 +02:00