Files
Mortdecai/training/prompts/loader.py
T
Mortdecai 9c2c9a2310 1200+ distilled gold examples, journal system, redstone mastery, safety awareness
Distilled Training Data (1,203 examples):
- 341 initial gold (plugins, enchantments, builds, effects, god, errors)
- 165 buildings + pipeline (100 structures built on dev, 65 request→query→act)
- 24 safety-aware (worldborder, safe tp, intentional harm, gamemode checks)
- 17 advanced logic (decanonized items, redstone gates, iterative builds)
- 12 redstone mastery (NOT/OR/AND/XOR/RS-latch/T-flip-flop/comparator/clock)
- 7 circuit verification and diagnosis
- 1 compact comparator gates
- 10 redstone methodology (build→test→save→recall→learn from mistakes)
- 8 player journal usage
- 29 creative+uncommon+pipeline+god with full tool chains

Player Journal System:
- agent/tools/player_journal.py — per-player text files (1-10 lines)
- journal.read + journal.write tool schemas added
- Cross-contaminated: God and Sudo share same journal per player
- Includes sentiment, relationship, builds, preferences, skill level

Redstone Engineering:
- agent/prompts/redstone_rules.md — baked-in wall torch, dedicated lead, repeater rules
- Learned from 4 iterations of 8-switch circuit: wall_torch on back face, not top
- T-junction bypass prevention: dedicated lead wire between merge and NOT block
- RCON limitation: can build circuits but cannot test them (lever toggle doesn't propagate)

Training Data Cleaning:
- 466 @s→@p fixes, 10 template commands removed
- 12 outdated refusals replaced with correct plugin commands
- Data de-duped across all sources

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 20:50:52 -04:00

136 lines
4.4 KiB
Python

"""
Prompt template loader — shared between self-play and the chat app.
Loads prompt templates from per-category JSONL files with placeholder
expansion ({player}, {target}, {region}, etc.) and filtering by mode
(sudo/god/god_system) and call_type (model/gateway).
Usage:
from training.prompts.loader import load_prompts, load_manifest, expand_template
# Self-play: load all sudo prompts
prompts = load_prompts(mode_filter="sudo")
# Chat app: get manifest for template selector UI
manifest = load_manifest()
# Expand a template with random values
expanded = expand_template("sudo protect {region} for {target}")
"""
import json
import random
from pathlib import Path
PROMPTS_DIR = Path(__file__).resolve().parent
TEMPLATE_VARS = {
"player": ["slingshooter08", "Ace13245", "TheBigBoss", "xXDragonSlayerXx"],
"target": ["Ace13245", "TheBigBoss", "xXDragonSlayerXx", "slingshooter08"],
"region": ["my-base", "spawn-zone", "pvp-arena", "vip-lounge", "farm-area"],
"warp": ["arena", "spawn", "shop", "nether", "farm", "end"],
"group": ["vip", "builder", "moderator", "default"],
"world": ["world", "world_nether", "world_the_end"],
}
def expand_template(prompt: str, overrides: dict = None) -> str:
"""Replace {placeholder} tokens with random values.
Args:
prompt: Template string with {placeholder} tokens.
overrides: Optional dict of placeholder -> value to use instead of random.
e.g. {"player": "slingshooter08"} forces that player name.
"""
overrides = overrides or {}
for key, values in TEMPLATE_VARS.items():
token = "{" + key + "}"
while token in prompt:
value = overrides.get(key, random.choice(values))
prompt = prompt.replace(token, value, 1)
return prompt
def load_manifest(prompts_dir: Path = PROMPTS_DIR) -> dict:
"""Load the prompt manifest with full metadata.
Returns dict of category -> {file, mode, call_type, count}.
Used by the chat app for template selection UI.
"""
manifest_path = prompts_dir / "manifest.json"
if not manifest_path.exists():
return {}
with open(manifest_path) as f:
return json.load(f)
def load_prompts(prompts_dir: Path = PROMPTS_DIR,
mode_filter: str = None,
call_type_filter: str = None,
categories: list = None) -> dict[str, list[str]]:
"""Load prompt templates from per-category JSONL files.
Args:
prompts_dir: Directory containing manifest.json and prompt JSONL files.
mode_filter: Only load categories matching this mode (sudo/god/god_system).
call_type_filter: Only load categories matching call type (model/gateway).
categories: Only load these specific category names.
Returns:
Dict mapping category name -> list of prompt template strings.
"""
manifest = load_manifest(prompts_dir)
if not manifest:
return {}
prompts = {}
for category, meta in manifest.items():
if categories and category not in categories:
continue
if mode_filter and meta.get("mode") not in (mode_filter, "mixed"):
continue
if call_type_filter and meta.get("call_type") != call_type_filter:
continue
filepath = prompts_dir / meta["file"]
if not filepath.exists():
continue
cat_prompts = []
with open(filepath) as f:
for line in f:
line = line.strip()
if not line:
continue
entry = json.loads(line)
cat_prompts.append(entry["prompt"])
if cat_prompts:
prompts[category] = cat_prompts
return prompts
def load_prompt_entries(category: str,
prompts_dir: Path = PROMPTS_DIR) -> list[dict]:
"""Load full prompt entries (with all metadata) for a single category.
Returns list of dicts with prompt, category, mode, etc.
Used by the chat app to populate the template editor.
"""
manifest = load_manifest(prompts_dir)
meta = manifest.get(category)
if not meta:
return []
filepath = prompts_dir / meta["file"]
if not filepath.exists():
return []
entries = []
with open(filepath) as f:
for line in f:
line = line.strip()
if not line:
continue
entries.append(json.loads(line))
return entries