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>
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user