/
/
/
Ansible role that deployes services on my runner machine
1# ==============================================================================
2# POST-SESSION PROCESSING - diarization, chronicle, state
3# ==============================================================================
4
5# Only used to download gated pyannote weights once. Inference is entirely
6# local; nothing about a session ever leaves the network.
7HF_TOKEN={{ vault_runner.huggingface_token }}
8HF_HOME=/models
9
10# LiteLLM fronts Ollama with an OpenAI-compatible API.
11# Which chronicler writes the chapter.
12#
13# local ~66 calls against the local model: summaries, claims, the thread
14# map, a multi-pass weave. Needs no network and no third party.
15# remote ONE call over the whole transcript. Needs a model whose context
16# can hold a session -- measured, a 4-hour transcript is ~61,000
17# tokens, which qwen3:14b on a 12 GB card cannot fit at any setting.
18#
19# Measured across eight real sessions (E23-E28, C2E46/47): the remote path cut
20# dice and table leakage from 83 references to 12, and ran in ~5 minutes
21# against ~2 hours.
22DND_CHRONICLE_BACKEND={{ dnd_chronicle_backend }}
23
24# The SHARED client, always local. Every entry point reads these -- dnd-spine,
25# dnd-refine, dnd-enrol and the local chapter chain -- so they must stay
26# pointed at litellm whatever the chronicler is.
27#
28# This used to be branched on the backend, which meant selecting the remote
29# chronicler silently sent the spine and the refine step to a hosted provider
30# too. Measured: dnd-spine ran 37 minutes with ZERO CPU and an idle GPU,
31# making its windowed calls over HTTPS to api.deepseek.com. Nothing errored --
32# it just became slow, silent and billable.
33DND_LLM_BASE_URL=http://{{ ansible_default_ipv4.address }}:{{ llm_stack_litellm_port }}/v1
34DND_LLM_API_KEY={{ vault_runner.lite_llm_master_key }}
35DND_LLM_MODEL={{ dnd_chronicle_model }}
36
37{% if dnd_chronicle_backend == 'remote' %}
38# The remote chronicler's OWN endpoint, read only by `remote.build()`. The key
39# is a vault secret and reaches the container only through this file, which is
40# 0640 and owned by the media user.
41DND_REMOTE_BASE_URL={{ dnd_remote_base_url }}
42DND_REMOTE_API_KEY={{ vault_runner.deepseek_api_key | default('') }}
43DND_REMOTE_MODEL={{ dnd_remote_model }}
44
45# Guard against a runaway transcript, not a model limit: probed against
46# deepseek-v4-pro, prompts of 604,880 tokens were accepted without error.
47# NOTE a 162,308-token prompt returned an EMPTY reply -- long inputs are
48# accepted and then answered poorly, so past ~100k tokens is unproven.
49DND_TRANSCRIPT_BUDGET={{ dnd_transcript_budget }}
50{% endif %}
51
52DND_CAMPAIGN_DIR=/media/dnd/campaign
53DND_TRANSCRIPT_DIR=/media/dnd/transcripts
54DND_RECORDING_DIR=/media/dnd/recordings
55
56# cuda when the driver matches torch's build, cpu otherwise. CPU still runs
57# faster than realtime, so it is a genuine fallback rather than a failure.
58DND_DIARIZE_DEVICE={{ dnd_diarize_device }}
59