Skip to main content

Narrative rendering

This is the only part of the system that can send data outside your network, so it is worth understanding precisely.

What is local and what is not

The analysis pipeline has three stages.

Scoring runs against the lexicon and feature model in the image. Local.

Simulation is a seedable Monte Carlo run producing percentile vectors for Low, Medium, and High trajectories. Local, and reproducible — the numbers come from a real distribution rather than a model's guess at one.

Rendering converts those already-computed vectors into natural-language text in the subject's voice. One LLM call per turn, plus one scenario-extraction call the first time a behaviour scenario is set.

Only the third stage calls out.

Turning it off

Leave OPENAI_API_KEY out of the application secret.

The engine then returns the same structured, deterministic output through a templated renderer. You get the trust, cooperation, and defensiveness figures and the recommended next step; you do not get prose. The output carries a note saying rendering is unavailable.

Nothing else changes. Scoring, simulation, storage, and reporting are unaffected, and no request leaves your network.

Turning it on

Add OPENAI_API_KEY to the application secret.

app:
config:
OPENAI_RESPONSES_MODEL: "gpt-4o-mini"

The call goes to OpenAI under your API key, on your account, under your own agreement with them. Presponsieve is not in that path and never sees the request. Your data processing agreement for it is with OpenAI, not with us.

What is sent is the prompt built from the latent vectors and the subject model. Review it before enabling this in a regulated environment.

Chat

The chat feature requires the key unconditionally. Without it, chat endpoints return 503 with a message naming OPENAI_API_KEY. That is the intended behaviour, not a fault.

Choosing the model

OPENAI_RESPONSES_MODEL defaults to gpt-4o-mini. The rendering task is constrained — the vectors are already computed, the model is phrasing them — so a larger model buys less here than it would for open-ended generation.

Audio transcription

Separate egress path, off by default.

app:
config:
TRANSCRIPTION_BACKEND: "gcp"
SPEECH_LOCATION: "global"
SPEECH_LANGUAGE_CODES: "en-US"
SPEECH_MAX_SPEAKERS: "6"

gcp enables Google Cloud Speech-to-Text with speaker diarization, which is what lets a recording be filtered to one person the way an uploaded transcript can. It reads staged audio from your own bucket using the pod's Workload Identity, so no extra credentials are needed, but the Speech-to-Text API must be enabled and the service account needs roles/speech.client.

Left disabled, the audio endpoint declines politely and points users at text upload.

Simulation samples

SIMULATION_SAMPLES defaults to 1000. Higher gives tighter percentiles at the cost of CPU per analysis. This is local computation and has nothing to do with the LLM call.