[GM Workbench] Extract LLM core from audio_service into llm_service #134
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation / Context
audio_service.pycurrently contains transcription and the entire structured-LLM stack: provider adapters (generate_structured_textatwebapp/backend/app/services/audio_service.py:1158-1221plus the four_structured_*backends), a dozen module-level system-prompt constants (:41-228), and domain functions for lore, names, storyline, and Q&A. The file is "audio" in name only.This is issue 1 of 3 foundational items behind the GM Workbench vision: turning GM Planning from one generator (names) into ~12 campaign-grounded generation tools (descriptions, backstories, loot, rumors, encounter seeds, improv NPCs, prep sheets, etc. — see the full catalog in
docs/.internal/gm-planning-expansion-2026-07-15.md§3). Before piling ~12 more prompts and provider-routing call sites intoaudio_service.py, split the reusable transport layer out. Every new Workbench tool sits ongenerate_structured_text; it needs a clean home.Approach
Purely mechanical move, no behavior change:
webapp/backend/app/services/llm_service.py— movegenerate_structured_text(audio_service.py:1158-1221), the four_structured_*provider-adapter backends (Anthropic/OpenAI/Ollama/llama.cpp-OpenAI-compatible), andextract_json_object(tolerant JSON parsing). Pure transport: provider routing by URL,system_prompt,json_mode,max_tokens=Nonesupport for local reasoning models, configurable timeout.audio_service.pyowning transcription + summarisation of audio sessions, plus its existing prompt constants and domain functions (lore extraction, names, storyline, Q&A) for now — those get progressively pulled intogeneration_service.pyin issue 2 as tools are registered, not all at once here.audio_service.py(from .llm_service import generate_structured_text, extract_json_object) so the ~10 existing call sites keep working without edits in this PR:reminder_tasks.py:1985/1997/2227/2494,lore_service.py:746, and others found via grep forgenerate_structured_text/extract_json_object.Dependencies
None — this is the first foundational item. Issue 2 (generalized workbench endpoint + tool registry) builds directly on
llm_service.pyexisting as a stable import target.Out of scope
audio_service.py— that happens incrementally as tools are registered ingeneration_service.py(issue 2) and later tool issues, not in this mechanical split.llm_service— leave the shims in place indefinitely unless a later cleanup pass wants to do that separately.Acceptance criteria
llm_service.pyexists and ownsgenerate_structured_text, all four provider adapters, andextract_json_object.audio_service.py.Picking this up as the first foundational item of the v3.10.0 GM Workbench pillar, on
feat/134-llm-service-extraction→ PR onto the integration branchfeat/v3.10-gm-workbench(per-issue PRs onto the integration branch, then one reviewed merge tomain, same workflow as v3.9.0).Purely mechanical: move the LLM transport layer (
generate_structured_text, the four_structured_*provider adapters,extract_json_object) out ofaudio_service.pyinto a newllm_service.py, with re-export shims inaudio_service.pyso all existing call sites keep working unchanged. No behaviour change; verified by the existing suite passing unmodified. (Note: the issue's line numbers predate v3.9.0 —audio_service.pygrew a lot with the stat-block work — so current locations will be found by grep.)Done and verified — merged into the integration branch via PR #216.
Verification (Docker, py3.12): 659 backend tests pass, unmodified (no behaviour change; the LLM-mocking suites — convert_stats, highlights, statblock_schema_targeting, system_aware_prompts, session_title_suggestions — all still resolve
generate_structured_textthrough the re-export shim).ruff check+ruff format --checkclean (0.4.4).Delivered: new
services/llm_service.pyowns the LLM transport (generate_structured_text, the four_structured_*provider adapters,extract_json_object, and_LLM_TIMEOUT/_is_ollama_url/_LORE_PROPOSAL_SYSTEM_PROMPT);audio_servicere-exports them so every call site is unchanged; no circular import (audio_service.generate_structured_text is llm_service.generate_structured_text). Domain functions stay inaudio_service.Closing; ships to
mainwith the v3.10.0 release. Next: #136 (generalized workbench endpoint + tool registry) and #138 (GenerationResult scratchpad), which build directly on this.