Commit graph

8 commits

Author SHA1 Message Date
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
81b2e90326 Fix podcasts defaulting to English: set language=de on default episode profiles
The three bundled episode profiles (business_analysis, solo_expert,
tech_discussion) shipped with language=null, which podcast_creator treats as
"unspecified" and defaults to English for outline/transcript generation
regardless of source language. Set language="de" on all three.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 00:37:09 +02:00
778f820e27 Document the num_ctx=8192 default that caused empty chat answers
esperanto's OllamaLanguageModel silently caps num_ctx at 8192 unless the
credential sets it explicitly, no matter what OLLAMA_CONTEXT_LENGTH or the
model's real context window is. Any chat context beyond that got truncated,
and because qwen3.5:27b is a thinking model, the truncated prompt usually
produced an empty final answer (swallowed by clean_thinking_content) rather
than a visible error - looked like "chat gives no answer" in the UI. Set
num_ctx=98304 on the Ollama chat credential: the largest value that still
keeps the whole model on GPU 1 (131072 spills onto CPU, 5-6x slower).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 23:28:12 +02:00
631ed26558 Document the embedding-timeout root cause and switch to nomic-embed-text
qwen3-embedding (repurposed 8B LLM, ~13GB loaded) didn't fit on GPU 1
alongside the resident 17GB chat model, so Ollama silently ran it 44-56%
on CPU. A single embed call took 39-54s, so any real document's chunk
batches blew past esperanto's 60s embedding timeout and got stuck retrying
forever - looked like "adding the source failed" but extraction was fine.
Also note: credential num_ctx doesn't work for embeddings (esperanto sends
it at the wrong JSON level, Ollama ignores it) - a small dedicated
embedding model is the real fix, not context-window tuning.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 23:00:34 +02:00
ef700613fe Document the two new CC0-licensed Piper-synthesized reference voices
male_thorsten/female_kerstin come from Piper's openly-licensed German voice
models, not scraped real-person audio, to avoid cloning someone's voice
without consent. Speaker profiles now use distinct voices per speaker instead
of everyone defaulting to the owner's own cloned voice.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 22:45:03 +02:00
0d8af23598 Add voice cloning to the TTS wrapper, default to the owner's own voice sample
tts_server.py now resolves `voice` against services/voices/*.wav (gitignored,
personal recordings) and clones via chatterbox's audio_prompt_path, falling
back to "default" (symlinked to ~/chatterbox-tts-cli/my_voice_deutsch_60s.wav)
for unknown names, or to the old built-in-voice-by-language-code behavior if
`voice` is a recognized language. All podcast speaker profiles now point at
voice_id "default" until distinct per-speaker reference clips are added.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 22:38:03 +02:00
fb1fbcfabe Add local TTS/STT wrapper servers (chatterbox, faster-whisper) as openai_compatible providers
Wraps the locally installed chatterbox-tts and faster-whisper packages in thin
FastAPI servers implementing OpenAI's audio API shape, since neither Ollama nor
OpenRouter support speech. Pinned to GPU 2 to avoid contending with Ollama's
resident models on GPU 1. Requires UFW rules for 8901/8902 (same pattern as
the existing 11434 rule) since UFW defaults to deny-incoming.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 21:41:44 +02:00
114dfacba8 Add CLAUDE.md documenting the deployment architecture and AI provider setup
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 21:08:55 +02:00