the-apprentice / scripts /mock_prompts.py
AndrewRqy
Trace-sharing infra: traces/sample is committable, add curation script + README badge claim
fd94fc8
Raw
History Blame Contribute Delete
7.08 kB
"""Print the exact prompts the LLM would see for several sample inputs.
No network call — this just builds the system + user messages and dumps
them to stdout. Useful for reading what the model actually sees with a
given oracle / theme / language combo.
Usage:
cd oracles_app
../.venv/bin/python scripts/mock_prompts.py
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
_HERE = Path(__file__).resolve().parent
_APP_ROOT = _HERE.parent
if str(_APP_ROOT) not in sys.path:
sys.path.insert(0, str(_APP_ROOT))
from oracles.state import GameState, Oracle, Obstacle, NARRATION_LENGTHS
from oracles.themes import get_theme
from oracles.resolution import (
_load_resolution_prompt,
_apply_theme,
_wrap_with_language_force,
_safe_oracle_for_template,
)
def build_resolution_prompt(
obstacle_setup: str,
oracle_text: str,
hero_name: str,
village_name: str,
language: str,
theme_key: str,
narration_length: str = "medium",
) -> tuple[str, str]:
"""Return (system, user) — exactly what would be sent to the LLM.
This mirrors ``resolve_trial`` up to the ``client.complete_json``
call, then bails out and returns the prompt.
"""
_, n_min, n_max, _max_tokens = NARRATION_LENGTHS.get(
narration_length, NARRATION_LENGTHS["medium"]
)
template = _load_resolution_prompt()
safe_oracle = _safe_oracle_for_template(oracle_text)
th = get_theme(theme_key)
system = _apply_theme(template, th)
system = (
system
.replace("{hero_name}", hero_name)
.replace("{village_name}", village_name)
.replace("{obstacle_setup}", obstacle_setup)
.replace("{oracle_text}", safe_oracle)
.replace("{language}", language)
.replace("{narration_min}", str(n_min))
.replace("{narration_max}", str(n_max))
)
system = _wrap_with_language_force(system, language)
user = "Pick one of modes A/B/C and write the resolution now."
return system, user
# ---------------------------------------------------------------------------
# Sample scenarios — pretend the player has just inscribed these oracles
# and the apprentice has reached trial 1.
# ---------------------------------------------------------------------------
SCENARIOS = [
{
"label": "Fantasy / English — single noun",
"obstacle_setup": (
"A grey sphinx with the body of a lion and the cracked face of an "
"old woman blocks the mountain pass. She offers a single riddle in "
"a voice like wind through dry reeds — and warns that all who "
"answer wrong have already been eaten."
),
"oracle_text": "phone",
"hero_name": "Tobin",
"village_name": "the Hollow",
"language": "English",
"theme_key": "fantasy",
"narration_length": "medium",
},
{
"label": "Fantasy / English — gibberish",
"obstacle_setup": (
"A grey sphinx with the body of a lion and the cracked face of an "
"old woman blocks the mountain pass. She offers a single riddle."
),
"oracle_text": "qwerty",
"hero_name": "Tobin",
"village_name": "the Hollow",
"language": "English",
"theme_key": "fantasy",
"narration_length": "medium",
},
{
"label": "Space-Cowboy / English — emoji",
"obstacle_setup": (
"The mayor's hired gun stands in the dust street outside the "
"saloon, hand near his holster. He calls the apprentice's name. "
"The town watches from shaded porches; no one moves."
),
"oracle_text": "🍕",
"hero_name": "Cal",
"village_name": "Dry Creek",
"language": "English",
"theme_key": "space_cowboy",
"narration_length": "short",
},
{
"label": "Mistgate / Simplified Chinese — short Chinese phrase",
"obstacle_setup": (
"雾门前立着一道无形的屏障。守门人沉默不语,"
"只用一根食指点向地面的符印——错答者即化为雾。"
),
"oracle_text": "蓝色",
"hero_name": "小明",
"village_name": "凡人村",
"language": "Simplified Chinese (use 简体中文 throughout; do not write in English)",
"theme_key": "mistgate",
"narration_length": "medium",
},
{
"label": "Fantasy / English — silly compound",
"obstacle_setup": (
"Three hornets the size of small cats hum a foot above the path. "
"Their wings rattle like a held breath. There is nowhere to flank."
),
"oracle_text": "wooden spoon",
"hero_name": "Tobin",
"village_name": "the Hollow",
"language": "English",
"theme_key": "fantasy",
"narration_length": "long",
},
]
def _hr(char: str = "─", width: int = 78) -> str:
return char * width
def main() -> int:
print(_hr("═"))
print("THE APPRENTICE — mock prompt inspection")
print(_hr("═"))
print()
print(
"For each scenario below, the system + user messages are exactly\n"
"what the LLM client sends. No network call is made; the LoRA's\n"
"response would slot in after the user message."
)
print()
for i, sc in enumerate(SCENARIOS, 1):
print(_hr("═"))
print(f" SCENARIO {i}: {sc['label']}")
print(_hr("═"))
print()
print(f" Theme: {sc['theme_key']}")
print(f" Hero / village: {sc['hero_name']!r} / {sc['village_name']!r}")
print(f" Language: {sc['language']}")
print(f" Narration length: {sc['narration_length']}")
print(f" Oracle inscribed: {sc['oracle_text']!r}")
print()
print(" OBSTACLE SETUP:")
print(f" > {sc['obstacle_setup']}")
print()
system, user = build_resolution_prompt(
obstacle_setup=sc["obstacle_setup"],
oracle_text=sc["oracle_text"],
hero_name=sc["hero_name"],
village_name=sc["village_name"],
language=sc["language"],
theme_key=sc["theme_key"],
narration_length=sc["narration_length"],
)
print(_hr("─"))
print(" SYSTEM PROMPT (sent as role=system)")
print(_hr("─"))
print(system)
print()
print(_hr("─"))
print(" USER PROMPT (sent as role=user)")
print(_hr("─"))
print(user)
print()
print(f" ↳ Expected response shape: JSON")
print(f" {{\"narration\": str (~{NARRATION_LENGTHS[sc['narration_length']][1]}-"
f"{NARRATION_LENGTHS[sc['narration_length']][2]} words / chars), "
f"\"tactic\": str (~1 line)}}")
print()
print(_hr("═"))
print(f" {len(SCENARIOS)} scenarios printed.")
print(_hr("═"))
return 0
if __name__ == "__main__":
sys.exit(main())