arcana / scripts /phase0_mapping.py
JG1310's picture
Arcana v1: themed concept-tarot generator + progressive reader (3 demo decks)
b04d6d2 verified
Raw
History Blame Contribute Delete
2.63 kB
"""Phase 0 (SPEC §12) — prove mapping quality before any art or UI.
Runs Agent 1 (the Deck Designer) against the open ≤32B model for several varied
themes and prints each deck as a readable archetype→concept table plus the full
JSON. Inspect by hand: do the mappings read as clever-but-right across all
themes? If not, fix the prompt/few-shots before building anything else.
Usage:
set -a; source ~/tokens; set +a
python -m scripts.phase0_mapping # default 5 themes
python -m scripts.phase0_mapping "free jazz" "tax law"
"""
from __future__ import annotations
import json
import os
import sys
import time
from arcana.archetypes import MAJOR_ARCANA
from arcana.designer import DeckError, design_deck
from arcana.llm import get_llm
DEFAULT_THEMES = [
"thermodynamics", # serious / scientific
"Lord of the Rings", # fandom
"the French Revolution", # history
"breakfast foods", # silly
"professional wrestling", # pop-culture wildcard
]
OUT_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"phase0_out")
def print_table(deck: dict) -> None:
print(f"\n style: {deck['style_suffix']}")
for a in MAJOR_ARCANA:
c = deck["cards"][a.number]
print(f" {a.roman:<5} {a.name:<18}{c['concept']}")
print(f" ↳ {c['justification']}")
def main(themes: list[str]) -> int:
os.makedirs(OUT_DIR, exist_ok=True)
llm = get_llm()
print(f"Model: {getattr(llm, 'model', '?')} via {getattr(llm, 'base_url', '?')}")
failures = 0
for theme in themes:
print("\n" + "=" * 72)
print(f"THEME: {theme}")
print("=" * 72)
t0 = time.time()
try:
deck = design_deck(theme, llm=llm)
except DeckError as e:
failures += 1
print(f" ✗ FAILED: {e} ({time.time() - t0:.1f}s)")
continue
dt = time.time() - t0
print_table(deck)
slug = "".join(ch if ch.isalnum() else "_" for ch in theme.lower())[:40]
path = os.path.join(OUT_DIR, f"{slug}.json")
with open(path, "w") as f:
json.dump(deck, f, indent=2, ensure_ascii=False)
print(f"\n ✓ 22 cards in {dt:.1f}s → {path}")
print("\n" + "=" * 72)
print(f"DONE — {len(themes) - failures}/{len(themes)} decks generated.")
print("Inspect the tables above: do the mappings feel clever-but-right?")
return 1 if failures else 0
if __name__ == "__main__":
args = sys.argv[1:] or DEFAULT_THEMES
raise SystemExit(main(args))