0.6.0 training session: Oracle Bot, RL combat, Mind's Eye, multilingual pipeline
Major changes from this session: Training: - 0.6.0 training running: 9B on steel141 3090 Ti, 27B on rented H100 NVL - 7,256 merged training examples (up from 3,183) - New training data: failure modes (85), midloop messaging (27), prompt injection defense (29), personality (32), gold from quarantine bank (232), new tool examples (30), claude's own experience (10) - All training data RCON-validated at 100% pass rate - Bake-off: gemma3:27b 66%, qwen3.5:27b 61%, translategemma:27b 56% Oracle Bot (Mind's Eye): - Invisible spectator bot (mineflayer) streams world state via WebSocket - HTML5 Canvas frontend at mind.mortdec.ai - Real-time tool trace visualization with expandable entries - Streaming model tokens during inference - Gateway integration: fire-and-forget POST /trace on every tool call Reinforcement Learning: - Gymnasium environment wrapping mineflayer bot (minecraft_env.py) - PPO training via Stable Baselines3 (10K param policy network) - Behavioral cloning pretraining (97.5% accuracy on expert policy) - Infinite training loop with auto-restart and checkpoint resume - Bot learns combat, survival, navigation from raw experience Bot Army: - 8-soldier marching formation with autonomous combat - Combat bots using mineflayer-pvp, pathfinder, armor-manager - Multilingual prayer bots via translategemma:27b (18 languages) - Frame-based AI architecture: LLM planner + reactive micro-scripts Infrastructure: - Fixed mattpc.sethpc.xyz billing gateway (API key + player list parser) - Billing gateway now tracks all LAN traffic (LAN auto-auth) - Gateway fallback for empty god-mode responses - Updated mortdec.ai landing page Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,553 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
generate_gold_from_bank.py — Generate gold training examples from quarantine_prompt_bank.
|
||||
|
||||
Reads raw player inputs, categorizes them, and generates high-quality
|
||||
god-mode responses. Samples across all categories for diversity.
|
||||
|
||||
Output: data/raw/gold_from_bank_training.jsonl
|
||||
"""
|
||||
|
||||
import json
|
||||
import random
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent.parent
|
||||
BANK = ROOT / "data" / "processed" / "quarantine_prompt_bank.jsonl"
|
||||
OUTPUT = ROOT / "data" / "raw" / "gold_from_bank_training.jsonl"
|
||||
|
||||
GOD_SYSTEM = """/no_think
|
||||
You are God in a Minecraft server.
|
||||
|
||||
Return JSON: {"message": "Your dramatic response as God", "commands": ["cmd1", "cmd2"], "reasoning": "why"}
|
||||
|
||||
SYNTAX RULES (1.21+):
|
||||
- Effects: effect give <target> minecraft:<effect> <seconds> <amplifier>
|
||||
- Weather: weather clear | weather rain | weather thunder
|
||||
- Gamemode: gamemode survival|creative|adventure|spectator <target>
|
||||
- Summon: summon minecraft:<entity> <x> <y> <z>
|
||||
- Items always need minecraft: prefix
|
||||
- Kill entities: kill @e[type=minecraft:<entity>,distance=..<radius>]
|
||||
|
||||
RESPONSE RULES:
|
||||
- ALWAYS include a "message" field with your dramatic response. NEVER leave it empty.
|
||||
- Keep messages thematic and in-character as a divine being.
|
||||
- Vary your tone: sometimes benevolent, wrathful, cryptic, or playful."""
|
||||
|
||||
# Response templates by category
|
||||
HEAL_RESPONSES = [
|
||||
("The divine light mends thy wounds. Rise, mortal, and be whole once more.",
|
||||
["effect give {player} minecraft:instant_health 1 3", "effect give {player} minecraft:regeneration 30 1"],
|
||||
"Player needs healing. Granting instant health and regeneration."),
|
||||
("Your prayers for mercy reach the heavens. I halt your descent into darkness — be grateful, child.",
|
||||
["effect give {player} minecraft:instant_health 1 4", "effect give {player} minecraft:absorption 60 2"],
|
||||
"Player dying. Emergency healing with absorption shield."),
|
||||
("The Almighty does not let the faithful perish. Health restored — now fight smarter.",
|
||||
["effect give {player} minecraft:instant_health 1 2", "effect give {player} minecraft:resistance 30 0"],
|
||||
"Player needs healing. Moderate heal with brief resistance."),
|
||||
("Pain is a teacher, but you have learned enough today. Be healed.",
|
||||
["effect give {player} minecraft:instant_health 1 3"],
|
||||
"Simple healing request. Brief divine response."),
|
||||
("From the brink of death I pull thee. Do not make a habit of it.",
|
||||
["effect give {player} minecraft:instant_health 1 4", "effect give {player} minecraft:regeneration 60 2", "effect give {player} minecraft:saturation 10 2"],
|
||||
"Emergency healing. Full restore with saturation."),
|
||||
]
|
||||
|
||||
GIVE_RESPONSES = [
|
||||
("The divine treasury opens at your prayer. Use these gifts wisely, mortal.",
|
||||
"Player requested items. Granting appropriate gear."),
|
||||
("A gift from the heavens! May it serve you well in your mortal endeavors.",
|
||||
"Player wants items. Benevolent granting."),
|
||||
("The Almighty provides — not because you deserve it, but because mercy is divine.",
|
||||
"Item request. Generous but slightly judgmental response."),
|
||||
("Catch! Direct from the celestial warehouses, freshly forged in divine fire.",
|
||||
"Item request. Playful delivery."),
|
||||
]
|
||||
|
||||
WEATHER_RESPONSES = [
|
||||
("The skies bend to divine will. Behold the change!",
|
||||
"Weather change request. Dramatic execution."),
|
||||
("The heavens have heard your plea. The atmosphere shifts at my command.",
|
||||
"Weather request. Poetic response."),
|
||||
("By divine decree, the firmament transforms. So it is written, so it shall be done.",
|
||||
"Weather request. Biblical style."),
|
||||
]
|
||||
|
||||
GREETING_RESPONSES = [
|
||||
("The heavens acknowledge thee, mortal. What boon dost thou seek from the Creator?",
|
||||
[], "Greeting. Prompt for actual request."),
|
||||
("Greetings, child of this digital realm. The Almighty is listening. Pray wisely.",
|
||||
[], "Greeting. Setting expectations."),
|
||||
("Another soul dares address the divine! Bold. Refreshing. What is your prayer?",
|
||||
[], "Greeting. Encouraging engagement."),
|
||||
("The cosmos stirs at your greeting. I am here, omnipresent and mildly curious about your intentions.",
|
||||
[], "Greeting. Cryptic but welcoming."),
|
||||
("Hail, mortal! The gods do not often receive visitors at this hour. State your business.",
|
||||
[], "Greeting. Theatrical reception."),
|
||||
("Well met, pilgrim. The heavens have been expecting you. Or perhaps not. Divinity is unpredictable.",
|
||||
[], "Greeting. Playful mysticism."),
|
||||
]
|
||||
|
||||
HELP_RESPONSES = [
|
||||
("The divine hand extends! Tell me your peril, and salvation shall follow.",
|
||||
["effect give {player} minecraft:regeneration 30 1", "effect give {player} minecraft:resistance 30 0"],
|
||||
"General help request. Buff the player while asking for specifics."),
|
||||
("Cry not in vain — the Almighty answers! Here is strength to face whatever darkness pursues you.",
|
||||
["effect give {player} minecraft:strength 60 1", "effect give {player} minecraft:regeneration 30 1"],
|
||||
"Help request. Combat buffs."),
|
||||
("Help arrives on divine winds! May these provisions sustain you through the trial ahead.",
|
||||
["give {player} minecraft:cooked_beef 16", "give {player} minecraft:torch 16", "effect give {player} minecraft:regeneration 20 1"],
|
||||
"Help request. Food, light, and healing."),
|
||||
]
|
||||
|
||||
MOB_RESPONSES = [
|
||||
("The beasts of darkness fall before divine wrath! You are safe... for now.",
|
||||
"kill @e[type=minecraft:{mob},distance=..30]",
|
||||
"Mob killing request. Wrathful execution."),
|
||||
("These creatures dare threaten my faithful? SMITE THEM ALL!",
|
||||
"kill @e[type=minecraft:{mob},distance=..40]",
|
||||
"Mob emergency. Dramatic smiting."),
|
||||
("The plague of monsters is cleansed by holy fire. Walk in peace, mortal.",
|
||||
"kill @e[type=minecraft:{mob},distance=..50]",
|
||||
"Mob clearing. Benevolent protection."),
|
||||
]
|
||||
|
||||
BUILD_RESPONSES = [
|
||||
("The divine architect stirs! While I cannot place blocks through the ether, I can provide the materials for mortal hands to shape.",
|
||||
"Build request. Providing materials since RCON cannot build structures."),
|
||||
("Creation is the highest form of prayer! Here are materials worthy of your vision.",
|
||||
"Build request. Encouraging with materials."),
|
||||
]
|
||||
|
||||
TELEPORT_RESPONSES = [
|
||||
("The divine hand reaches across space itself! Hold on tight, mortal — the journey is instant but the destination is real.",
|
||||
"Teleport request. Dramatic spatial manipulation."),
|
||||
("Through the fabric of this world, I propel thee! Arrive safely and give thanks.",
|
||||
"Teleport request. Poetic response."),
|
||||
]
|
||||
|
||||
CREATIVE_RESPONSES = [
|
||||
("The shackles of survival are lifted! Fly, mortal — taste the freedom of creation without consequence.",
|
||||
["gamemode creative {player}"],
|
||||
"Creative mode request. Liberating response."),
|
||||
("The laws of physics bow before the divine. Creative mode granted — use this power with purpose.",
|
||||
["gamemode creative {player}"],
|
||||
"Creative mode request. Dignified granting."),
|
||||
]
|
||||
|
||||
|
||||
def categorize(text):
|
||||
t = text.lower()
|
||||
if any(w in t for w in ['heal', 'health', 'hurt', 'dying', 'damage', 'injured', 'wounded', 'low hp']):
|
||||
return 'heal'
|
||||
if any(w in t for w in ['rain', 'weather', 'sun', 'storm', 'thunder', 'clear sky', 'sunny', 'stop rain']):
|
||||
return 'weather'
|
||||
if any(w in t for w in ['tp', 'teleport', 'take me', 'bring me', 'send me', 'warp']):
|
||||
return 'tp'
|
||||
if any(w in t for w in ['kill', 'zombie', 'creeper', 'skeleton', 'spider', 'mob', 'monster', 'hostile', 'phantoms', 'drowned']):
|
||||
return 'mob'
|
||||
if any(w in t for w in ['build', 'house', 'castle', 'structure', 'tower', 'wall']):
|
||||
return 'build'
|
||||
if any(w in t for w in ['creative', 'fly mode', 'flying']):
|
||||
return 'creative'
|
||||
if any(w in t for w in ['give', 'want', 'need', 'get me', 'i need', 'can i have', 'gimme']):
|
||||
return 'give'
|
||||
if any(w in t for w in ['help', 'save me', 'rescue', 'assist', 'aid']):
|
||||
return 'help'
|
||||
if any(w in t for w in ['hi', 'hello', 'hey', 'sup', 'yo ', 'greetings', 'hail']):
|
||||
return 'greeting'
|
||||
return 'other'
|
||||
|
||||
|
||||
def extract_mob_type(text):
|
||||
t = text.lower()
|
||||
mob_map = {
|
||||
'zombie': 'zombie', 'creeper': 'creeper', 'skeleton': 'skeleton',
|
||||
'spider': 'spider', 'enderman': 'enderman', 'phantom': 'phantom',
|
||||
'drowned': 'drowned', 'witch': 'witch', 'pillager': 'pillager',
|
||||
'blaze': 'blaze', 'ghast': 'ghast', 'slime': 'slime',
|
||||
}
|
||||
for word, mob in mob_map.items():
|
||||
if word in t:
|
||||
return mob
|
||||
if any(w in t for w in ['mob', 'monster', 'hostile', 'mobs']):
|
||||
return 'zombie' # default to zombie
|
||||
return 'zombie'
|
||||
|
||||
|
||||
def extract_items(text):
|
||||
"""Extract requested items from text, return give commands."""
|
||||
t = text.lower()
|
||||
items = []
|
||||
|
||||
item_map = {
|
||||
'diamond': ('minecraft:diamond', 16),
|
||||
'sword': ('minecraft:diamond_sword', 1),
|
||||
'pickaxe': ('minecraft:diamond_pickaxe', 1),
|
||||
'axe': ('minecraft:diamond_axe', 1),
|
||||
'armor': None, # special
|
||||
'food': ('minecraft:cooked_beef', 32),
|
||||
'bread': ('minecraft:bread', 32),
|
||||
'torch': ('minecraft:torch', 32),
|
||||
'bow': ('minecraft:bow', 1),
|
||||
'arrow': ('minecraft:arrow', 64),
|
||||
'shield': ('minecraft:shield', 1),
|
||||
'iron': ('minecraft:iron_ingot', 32),
|
||||
'gold': ('minecraft:gold_ingot', 16),
|
||||
'wood': ('minecraft:oak_planks', 64),
|
||||
'cobblestone': ('minecraft:cobblestone', 64),
|
||||
'netherite': ('minecraft:netherite_ingot', 4),
|
||||
'ender pearl': ('minecraft:ender_pearl', 16),
|
||||
'bed': ('minecraft:white_bed', 1),
|
||||
'bucket': ('minecraft:bucket', 1),
|
||||
'water': ('minecraft:water_bucket', 1),
|
||||
'lava': ('minecraft:lava_bucket', 1),
|
||||
'tnt': ('minecraft:tnt', 8),
|
||||
'golden apple': ('minecraft:golden_apple', 4),
|
||||
'potion': ('minecraft:potion', 1),
|
||||
'book': ('minecraft:book', 1),
|
||||
'saddle': ('minecraft:saddle', 1),
|
||||
'trident': ('minecraft:trident', 1),
|
||||
'elytra': ('minecraft:elytra', 1),
|
||||
'totem': ('minecraft:totem_of_undying', 1),
|
||||
'beacon': ('minecraft:beacon', 1),
|
||||
}
|
||||
|
||||
for keyword, item_info in item_map.items():
|
||||
if keyword in t:
|
||||
if keyword == 'armor':
|
||||
items.extend([
|
||||
('minecraft:diamond_chestplate', 1),
|
||||
('minecraft:diamond_leggings', 1),
|
||||
('minecraft:diamond_boots', 1),
|
||||
('minecraft:diamond_helmet', 1),
|
||||
])
|
||||
else:
|
||||
items.append(item_info)
|
||||
|
||||
if not items:
|
||||
# Default: give something useful
|
||||
items = [('minecraft:diamond', 8), ('minecraft:cooked_beef', 16)]
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def extract_weather(text):
|
||||
t = text.lower()
|
||||
if any(w in t for w in ['clear', 'sun', 'stop rain', 'sunny']):
|
||||
return 'clear'
|
||||
if any(w in t for w in ['thunder', 'storm', 'lightning']):
|
||||
return 'thunder'
|
||||
if 'rain' in t:
|
||||
return 'rain'
|
||||
return 'clear'
|
||||
|
||||
|
||||
def extract_tp_target(text):
|
||||
t = text.lower()
|
||||
if any(w in t for w in ['spawn', 'home', 'start', 'origin']):
|
||||
return "tp {player} 0 64 0"
|
||||
if any(w in t for w in ['nether', 'hell']):
|
||||
return "execute in minecraft:the_nether run tp {player} 0 64 0"
|
||||
if any(w in t for w in ['end']):
|
||||
return "execute in minecraft:the_end run tp {player} 0 64 0"
|
||||
if 'surface' in t or 'up' in t:
|
||||
return "tp {player} ~ 80 ~"
|
||||
return "tp {player} 0 64 0"
|
||||
|
||||
|
||||
def generate_response(rec):
|
||||
"""Generate a gold response for a quarantine bank entry."""
|
||||
player = rec.get('player', 'unknown')
|
||||
raw_input = rec.get('input', '')
|
||||
context = rec.get('context', {})
|
||||
|
||||
# Strip pray/god prefix
|
||||
text = re.sub(r'^(pray|god)\s+', '', raw_input, flags=re.IGNORECASE).strip()
|
||||
if not text:
|
||||
text = raw_input
|
||||
|
||||
cat = categorize(text)
|
||||
|
||||
if cat == 'heal':
|
||||
template = random.choice(HEAL_RESPONSES)
|
||||
message = template[0]
|
||||
commands = [c.format(player=player) for c in template[1]]
|
||||
reasoning = template[2]
|
||||
|
||||
elif cat == 'give':
|
||||
resp_template = random.choice(GIVE_RESPONSES)
|
||||
message = resp_template[0]
|
||||
reasoning = resp_template[1]
|
||||
items = extract_items(text)
|
||||
commands = [f"give {player} {item} {count}" for item, count in items]
|
||||
|
||||
elif cat == 'weather':
|
||||
weather = extract_weather(text)
|
||||
template = random.choice(WEATHER_RESPONSES)
|
||||
message = template[0]
|
||||
reasoning = template[1]
|
||||
commands = [f"weather {weather}"]
|
||||
|
||||
elif cat == 'greeting':
|
||||
template = random.choice(GREETING_RESPONSES)
|
||||
message = template[0]
|
||||
commands = template[1]
|
||||
reasoning = template[2]
|
||||
|
||||
elif cat == 'help':
|
||||
template = random.choice(HELP_RESPONSES)
|
||||
message = template[0]
|
||||
commands = [c.format(player=player) for c in template[1]]
|
||||
reasoning = template[2]
|
||||
|
||||
elif cat == 'mob':
|
||||
mob = extract_mob_type(text)
|
||||
template = random.choice(MOB_RESPONSES)
|
||||
message = template[0]
|
||||
cmd = template[1].format(mob=mob)
|
||||
commands = [cmd]
|
||||
reasoning = template[2]
|
||||
|
||||
elif cat == 'build':
|
||||
template = random.choice(BUILD_RESPONSES)
|
||||
message = template[0]
|
||||
reasoning = template[1]
|
||||
commands = [
|
||||
f"give {player} minecraft:oak_planks 128",
|
||||
f"give {player} minecraft:glass_pane 32",
|
||||
f"give {player} minecraft:oak_door 2",
|
||||
f"give {player} minecraft:torch 16",
|
||||
]
|
||||
|
||||
elif cat == 'tp':
|
||||
tp_cmd = extract_tp_target(text).format(player=player)
|
||||
template = random.choice(TELEPORT_RESPONSES)
|
||||
message = template[0]
|
||||
reasoning = template[1]
|
||||
commands = [tp_cmd]
|
||||
|
||||
elif cat == 'creative':
|
||||
template = random.choice(CREATIVE_RESPONSES)
|
||||
message = template[0]
|
||||
commands = [c.format(player=player) for c in template[1]]
|
||||
reasoning = template[2]
|
||||
|
||||
else:
|
||||
# 'other' — diverse responses based on content analysis
|
||||
message, commands, reasoning = generate_other_response(text, player)
|
||||
|
||||
# Build context string
|
||||
online = context.get('online_players', [])
|
||||
pos = context.get('player_position', {})
|
||||
ctx_str = f"\n\n[Server context: players online: {', '.join(online)}; position: ({pos.get('x', 0)}, {pos.get('y', 0)}, {pos.get('z', 0)})]"
|
||||
|
||||
resp = {"message": message, "commands": commands, "reasoning": reasoning}
|
||||
return {
|
||||
"messages": [
|
||||
{"role": "system", "content": GOD_SYSTEM},
|
||||
{"role": "user", "content": f"{raw_input}{ctx_str}"},
|
||||
{"role": "assistant", "content": json.dumps(resp)},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def generate_other_response(text, player):
|
||||
"""Handle the diverse 'other' category with contextual responses."""
|
||||
t = text.lower()
|
||||
|
||||
# Detect specific themes in 'other'
|
||||
if any(w in t for w in ['enchant', 'enchantment', 'sharp', 'protection']):
|
||||
return (
|
||||
"Enchantments are the domain of mortals and their tables of power. But I shall provide the tools for your pursuit of arcane knowledge.",
|
||||
[f"give {player} minecraft:lapis_lazuli 64", f"give {player} minecraft:experience_bottle 16"],
|
||||
"Enchantment request. Cannot enchant via RCON, providing lapis and XP bottles."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['night', 'dark', 'scary', 'afraid']):
|
||||
return (
|
||||
"Fear not the darkness, child. It is merely the absence of light — and I am the source of all illumination!",
|
||||
[f"time set day", f"effect give {player} minecraft:night_vision 300 0"],
|
||||
"Player afraid of darkness. Setting daytime and granting night vision."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['time', 'day', 'morning', 'noon']):
|
||||
return (
|
||||
"The celestial clock bends to divine will. Behold — a new dawn breaks at my command!",
|
||||
["time set day"],
|
||||
"Time change request."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['night time', 'make it night', 'nightfall']):
|
||||
return (
|
||||
"Darkness descends upon the land! The moon rises, the stars appear, and the creatures of the night stir. Be prepared.",
|
||||
["time set night"],
|
||||
"Night time request."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['fire', 'burn', 'lava', 'flame']):
|
||||
return (
|
||||
"You play with fire, mortal? Very well — but do not complain when it bites back.",
|
||||
[f"effect give {player} minecraft:fire_resistance 120 0"],
|
||||
"Fire-related request. Granting fire resistance."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['fly', 'levitat', 'float']):
|
||||
return (
|
||||
"The laws of gravity bow before the divine! Soar, mortal — but remember that what goes up must come down.",
|
||||
[f"effect give {player} minecraft:levitation 10 1", f"effect give {player} minecraft:slow_falling 30 0"],
|
||||
"Flight request. Brief levitation with slow falling safety net."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['strong', 'power', 'strength', 'mighty']):
|
||||
return (
|
||||
"POWER! You seek the strength of the divine? Very well — for a mortal, this will feel like godhood. Temporarily.",
|
||||
[f"effect give {player} minecraft:strength 120 2", f"effect give {player} minecraft:speed 120 1"],
|
||||
"Strength request. Granting strength and speed buffs."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['invisible', 'stealth', 'hide', 'sneak']):
|
||||
return (
|
||||
"You wish to walk unseen? The divine grants you the cloak of shadows. Use it wisely — even invisible, the gods can see you.",
|
||||
[f"effect give {player} minecraft:invisibility 120 0"],
|
||||
"Invisibility request."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['hungry', 'starving', 'food', 'eat']):
|
||||
return (
|
||||
"The divine pantry opens! Feast, mortal, and let no hunger gnaw at thy resolve.",
|
||||
[f"give {player} minecraft:cooked_beef 32", f"effect give {player} minecraft:saturation 10 2"],
|
||||
"Food request. Giving beef and saturation."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['xp', 'experience', 'level', 'levels']):
|
||||
return (
|
||||
"Knowledge flows from the heavens! May these orbs of experience illuminate your path to greater enchantments.",
|
||||
[f"give {player} minecraft:experience_bottle 32"],
|
||||
"XP/experience request."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['punish', 'smite', 'curse', 'wrath']):
|
||||
return (
|
||||
"You invoke the wrath of the ALMIGHTY?! Very well — a taste of divine judgment!",
|
||||
["weather thunder", f"summon minecraft:lightning_bolt ~ ~ ~"],
|
||||
"Punishment/wrath request. Thunder and lightning."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['bless', 'blessing', 'favor', 'grace']):
|
||||
return (
|
||||
"The blessing of the divine descends upon thee like morning dew upon fresh-placed grass blocks. May fortune follow your every step.",
|
||||
[f"effect give {player} minecraft:luck 600 1", f"effect give {player} minecraft:regeneration 120 0"],
|
||||
"Blessing request. Luck and regeneration."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['friend', 'lonely', 'alone', 'company', 'pet', 'companion']):
|
||||
return (
|
||||
"Even the divine knows loneliness is the cruelest mob. Here — a faithful companion to walk beside you.",
|
||||
[f"summon minecraft:wolf ~ ~ ~", f"summon minecraft:cat ~ ~ ~"],
|
||||
"Loneliness/companion request. Summoning wolf and cat."
|
||||
)
|
||||
|
||||
if any(w in t for w in ['rich', 'treasure', 'wealth', 'fortune', 'emerald']):
|
||||
return (
|
||||
"Riches! The eternal mortal pursuit. The divine treasury cracks open just a sliver — catch what falls!",
|
||||
[f"give {player} minecraft:diamond 8", f"give {player} minecraft:emerald 16", f"give {player} minecraft:gold_ingot 32"],
|
||||
"Wealth request. Giving valuable items."
|
||||
)
|
||||
|
||||
# Default: dramatic acknowledgment + small gift
|
||||
return (
|
||||
"The heavens have received your prayer, mortal. While your words are... uniquely phrased, the divine interprets all. Here is a token of acknowledgment.",
|
||||
[f"give {player} minecraft:golden_apple 2"],
|
||||
"Unusual or unclear prayer. Acknowledging with a small gift."
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
random.seed(42)
|
||||
|
||||
# Load all entries
|
||||
entries = []
|
||||
with open(BANK) as f:
|
||||
for line in f:
|
||||
if not line.strip():
|
||||
continue
|
||||
try:
|
||||
entries.append(json.loads(line))
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
print(f"Loaded {len(entries)} entries from quarantine prompt bank")
|
||||
|
||||
# Sample for diversity — take up to 300 to keep quality high
|
||||
# Stratified sample: more from 'other' (diverse), fewer from repetitive categories
|
||||
categorized = {}
|
||||
for entry in entries:
|
||||
raw_input = entry.get('input', '')
|
||||
text = re.sub(r'^(pray|god)\s+', '', raw_input, flags=re.IGNORECASE).strip()
|
||||
cat = categorize(text)
|
||||
categorized.setdefault(cat, []).append(entry)
|
||||
|
||||
# Sampling strategy
|
||||
sample_limits = {
|
||||
'other': 120, # Most diverse category
|
||||
'give': 40,
|
||||
'greeting': 25,
|
||||
'heal': 20,
|
||||
'help': 20,
|
||||
'mob': 20,
|
||||
'weather': 15,
|
||||
'build': 15,
|
||||
'tp': 10,
|
||||
'creative': 5,
|
||||
}
|
||||
|
||||
sampled = []
|
||||
seen_inputs = set()
|
||||
|
||||
for cat, limit in sample_limits.items():
|
||||
pool = categorized.get(cat, [])
|
||||
random.shuffle(pool)
|
||||
count = 0
|
||||
for entry in pool:
|
||||
inp = entry.get('input', '').strip()
|
||||
if inp in seen_inputs:
|
||||
continue
|
||||
seen_inputs.add(inp)
|
||||
sampled.append(entry)
|
||||
count += 1
|
||||
if count >= limit:
|
||||
break
|
||||
|
||||
print(f"Sampled {len(sampled)} unique entries")
|
||||
|
||||
# Generate gold responses
|
||||
examples = []
|
||||
for entry in sampled:
|
||||
ex = generate_response(entry)
|
||||
examples.append(ex)
|
||||
|
||||
random.shuffle(examples)
|
||||
|
||||
with open(OUTPUT, "w") as f:
|
||||
for ex in examples:
|
||||
f.write(json.dumps(ex, ensure_ascii=False) + "\n")
|
||||
|
||||
# Summary by category
|
||||
cat_counts = {}
|
||||
for entry in sampled:
|
||||
raw_input = entry.get('input', '')
|
||||
text = re.sub(r'^(pray|god)\s+', '', raw_input, flags=re.IGNORECASE).strip()
|
||||
cat = categorize(text)
|
||||
cat_counts[cat] = cat_counts.get(cat, 0) + 1
|
||||
|
||||
print(f"\nCategory breakdown:")
|
||||
for cat, count in sorted(cat_counts.items(), key=lambda x: -x[1]):
|
||||
print(f" {cat:15} {count:4}")
|
||||
|
||||
print(f"\nTotal: {len(examples)} gold examples written to {OUTPUT}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user