docs(decisions): amend D-138 with Spike 2 findings
Spike 2 amendments: stdio IPC (not HTTP, Gemma 2 T&C compliance), tell differentiation results (3/5 at 2B capacity), double-prompt technique, ContentType::Factual for LLM bypass, all negative injectors moved from universal RULES to per-culture voice_persona. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -412,17 +412,18 @@ How narrative, NPCs, and world content are created: content tiers, NPC generatio
|
||||
- **Decision:** NPC observable behaviors and dialogue are processed through an LLM re-voicing pipeline that translates culture-neutral semantic base text into character-voiced output. The pipeline is a background runtime enhancement, not a live generation system. Tell behaviors are base-text passthrough — always. Active tell state influences the re-voicing prompt for surrounding content (tells are read-only inputs to the LLM, never LLM outputs). The game is complete and functional without the pipeline; it is an enhancement that elevates voice quality for players with sufficient hardware.
|
||||
- **Architecture:**
|
||||
- **Model:** Gemma 2 2B IT Q4_K_M (~1.6GB), bundled as `server/models/gemma2.gguf`. No fallback model. *(Amended 2026-03-07: Phi-3 dropped entirely after Spike 1 — Gemma 2B produces superior culturally-differentiated output at the same quantization. Original GGUF: `gemma-2-2b-it-Q4_K_M.gguf` from Hugging Face bartowski/gemma-2-2b-it-GGUF.)*
|
||||
- **Runtime:** `llama-cpp-rs` with GGUF format. Separate inference thread pool at below-normal priority.
|
||||
- **Runtime:** `llama-cpp-rs` with GGUF format. Separate inference thread pool at below-normal priority. *(Amended 2026-03-07, Spike 2: IPC is stdin/stdout JSONL pipes, not HTTP. Each worker owns a piped `sr-voice` child process — no network ports. This satisfies Gemma 2 Terms & Conditions: model is only reachable through the game server's queue, never exposed as a service.)*
|
||||
- **Content tiers:** Baked (hub zones, build-time, human-reviewed) → Pre-voiced (background queue, priority-ordered) → Base text fallback (always present).
|
||||
- **Tell treatment:** Passthrough always. Tell state flows into re-voicing prompts as universal tone injectors. Cultural flavor is conditional and additive — humans are humans first; micro-expressions and body language must remain universally recognizable. Per-culture tell-tone tables are optional enrichment, not a launch requirement.
|
||||
- **Tell treatment:** Passthrough always. Tell state flows into re-voicing prompts as universal tone injectors. Cultural flavor is conditional and additive — humans are humans first; micro-expressions and body language must remain universally recognizable. Per-culture tell-tone tables are optional enrichment, not a launch requirement. *(Amended 2026-03-07, Spike 2: Tell differentiation at 2B — 3/5 tells produce distinguishable output (Nervous, Guarded, Angry). Friendly and RoutineDeviation are inert at 2B capacity — model cannot reliably differentiate them from neutral. Deferred to post-ship or larger model. Angry tell requires length-aware injectors: short/medium content gets standard compression, long content (≥16 words) gets an explicit "keep full claim intact" instruction to prevent destructive information loss.)*
|
||||
- **Determinism:** Cache-as-determinism. LLM generates once per seed; result cached. Cache lookup is deterministic.
|
||||
- **Caching:** Content-length-gated variants. Short lines (≤7 words): neutral only. Medium lines: 3 variants (neutral, high-affect, guarded). Long lines: up to 6 variants. Key: `(npc_stable_id, line_id, tell_state, culture_id)`. *(Amended 2026-03-07: Spike 1 confirmed 2B model cannot produce distinguishable tell-state variants on short lines — 5/5 states produced near-identical output for "Inspection's next week." Length-gated caching reduces wasted compute/storage.)*
|
||||
- **Hardware:** "AI-Enhanced Dialogue" toggle. Layered detection: RAM check → TPT benchmark → recommendation. No hard minimum spec floor. Player can always override.
|
||||
- **Distribution:** Model bundled in game install (~1.5GB).
|
||||
- **Protected categories (never re-voiced):** Tell behaviors, secret-tier dialogue (D-028 Layer 3), anchor lines (D-092), relationship-specific lines naming third parties.
|
||||
- **Composition engine:** Occasional prompt injections (e.g. oath vocabulary, faith expressions) are controlled by the prompt generator at a configurable frequency (e.g. 1-in-4), not by the model. The model never decides injection frequency — it either receives the clause or doesn't. This is a systemic pattern applicable to any culture marker that should appear occasionally. *(Added 2026-03-07: Spike 1 proved 2B models treat vocabulary lists as required markers. Composition-engine gating eliminates both over-use and under-use.)*
|
||||
- **Negative injectors:** NI-2 (no military ranks), NI-3 (technology vocabulary), NI-4 (no banter/wit) are universal. NI-1 (religious language) and NI-5 (Earth references) are culture-gated — cultures with religious or Earth-descended heritage use appropriate expressions. Earth is not lost; cultural heritage from colonization history is intentional and expected. *(Amended 2026-03-07: Jeroen's decision — "a planet colonized by a company from Dublin would show clear traces of Ireland." NI-1/NI-5 moved from universal bans to culture-specific constraints.)*
|
||||
- **Validation:** Two-spike strategy. Spike 1: Rust `sr-voice` CLI + manual prompt testing (Jeroen/Mellanie/Paula). Spike 2: full pipeline integration.
|
||||
- **Composition engine:** Occasional prompt injections (e.g. oath vocabulary, faith expressions) are controlled by the prompt generator at a configurable frequency (e.g. 1-in-4), not by the model. The model never decides injection frequency — it either receives the clause or doesn't. This is a systemic pattern applicable to any culture marker that should appear occasionally. *(Added 2026-03-07: Spike 1 proved 2B models treat vocabulary lists as required markers. Composition-engine gating eliminates both over-use and under-use.)* *(Amended 2026-03-07, Spike 2: Prompt architecture uses a double-prompt technique — critical constraints are repeated in a REMEMBER block immediately before the OUTPUT: stop token to anchor them in the 2B model's attention window. Epistemic markers ("I heard", "apparently", "I think") are preserved via example-based integration, not keyword lists — keyword lists caused the model to emit comma-separated marker dumps. Injections use imperative framing: once fired by the composition engine, the model executes without discretion.)*
|
||||
- **Content classification:** Base text should be classified by content type. `Dialogue` and `Behavior` pass through the LLM. A new `Factual` content type is recommended for lines bearing specific numbers, causal chains, or denial statements — these bypass the LLM entirely and serve base text, because 2B models cannot reliably preserve quantitative precision (e.g., "14 crates in bay seven" became "fourteen crates are missing"). *(Added 2026-03-07, Spike 2: Paula endorsed ContentType::Factual over template-based approaches.)*
|
||||
- **Negative injectors:** All negative injectors (NI-1 through NI-5) belong in per-culture voice personas, not in universal RULES. The universal RULES const contains only format constraints (one line, complete sentences, no invention). Worldbuilding constraints — military ranks, technology vocabulary, humor register, religious language, Earth references — vary by system/planet/location/culture and are authored per-culture in `voice_persona`. *(Amended 2026-03-07, Spike 2: Jeroen directed removal of all worldbuilding from universal RULES. "Military ranks do exist in some parts of the settings." "Why all these assumptions." NI-2/NI-3/NI-4 removed from universal scope; all NIs are now culture-specific.)*
|
||||
- **Validation:** Two-spike strategy. Spike 1: Rust `sr-voice` CLI + manual prompt testing (Jeroen/Mellanie/Paula). Spike 2: full pipeline integration (queue → worker pool → sr-voice child → cache → disk). *(Amended 2026-03-07, Spike 2: Both spikes complete. 39 edge-case test prompts across 8 categories (length, tells, epistemic markers, injections, behaviors, named entities, causal chains, denials). Three rounds of iterative prompt refinement with Paula, Mellanie, and Gestalt reviewing output. Pipeline tested end-to-end with real Gemma 2B at ~16 t/s CPU.)*
|
||||
- **Rationale:** D-122 (all NPCs generated) and D-128 (culture implicit in starting location) require NPC voice to scale across zones and cultures without O(R×Z×C) hand-authoring. The re-voicing model is the only architecture that scales while preserving content quality. Base-text fallback ensures the game is complete without the pipeline.
|
||||
- **Source:** LLM Voice Pipeline Workshop (2026-03-07)
|
||||
- **Raised by:** Team Leader (Jeroen), with Gestalt, Tyre, Paula, Mellanie, Ozzie, Miri, Troblum
|
||||
@@ -434,4 +435,4 @@ How narrative, NPCs, and world content are created: content tiers, NPC generatio
|
||||
|
||||
---
|
||||
|
||||
*38 decisions. Last updated: 2026-03-07 (D-138 added and amended with Spike 1 findings; D-123 amended; D-124 superseded — LLM Voice Pipeline Workshop)*
|
||||
*38 decisions. Last updated: 2026-03-07 (D-138 amended with Spike 2 findings: stdio IPC, tell differentiation results, double-prompt technique, ContentType::Factual, negative injectors moved to per-culture; D-123 amended; D-124 superseded — LLM Voice Pipeline Workshop)*
|
||||
|
||||
Reference in New Issue
Block a user