AdmiralTaco's picture
Thousand Token Wood: emergent small-model economy for Build Small Hackathon
c26b033
Raw
History Blame Contribute Delete
2.97 kB
"""Run the wood on the real small model via the deployed Modal endpoint.
Doubles as the 3B reliability gate: it reports how often the model emits a
parseable JSON object and at least one valid offer. If 3B holds up, we keep
Tiny Titan eligibility; if not, fall back to 7B (set TTW_MODEL and redeploy).
Run (after `python -m modal deploy serve.py`):
python scripts/run_llm.py
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from ttw.actions import parse_actions
from ttw.agents import make_llm_policy
from ttw.events import EventDeck
from ttw.llm import ModalLLM
from ttw.market import gini
from ttw.sim import step
from ttw.world import seed_world
def main(turns: int = 15) -> None:
world = seed_world()
client = ModalLLM()
policy = make_llm_policy(client, temperature=0.7)
deck = EventDeck(seed=7)
parsed_ok = 0
json_ok = 0
total = 0
for _ in range(turns):
# Fate draws a Wood Legend (a reskinned market mania) every 5 turns.
if world.turn in (4, 9, 13):
legend = deck.draw(world)
print(f"\n*** WOOD LEGEND: {legend.title} ***")
print(f" {legend.flavor} (inspired by: {legend.inspired_by})")
events = step(world, policy)
raw = policy.state["raw"]
# Reliability accounting for this turn.
for name, text in raw.items():
total += 1
offers, _ = parse_actions(name, text)
from ttw.actions import _extract_json
if _extract_json(text) is not None:
json_ok += 1
if offers:
parsed_ok += 1
trades = [e for e in events if e["type"] == "trade"]
gossip = [e for e in events if e["type"] == "gossip"]
prices = " ".join(f"{g}={p:.0f}" for g, p in world.last_price.items())
nets = [c.net_worth(world.last_price) for c in world.alive()]
print(f"\n=== turn {world.turn} | {len(trades)} trades | gini {gini(nets):.2f} | {prices}")
for t in trades:
print(f" {t['buyer']} bought {t['qty']} {t['good']} from {t['seller']} @ {t['price']}")
for g in gossip:
print(f" [rumor] {g['creature']}: {g['message']}")
# One sample reasoning trace, to eyeball quality.
sample_name = next(iter(policy.state["raw"]))
print(f"\n--- sample reasoning trace ({sample_name}, last turn) ---")
print(policy.state["raw"][sample_name].strip()[:500])
print("\n=== RELIABILITY ===")
print(f"valid JSON object: {json_ok}/{total} ({100*json_ok/total:.0f}%)")
print(f"yielded >=1 valid offer: {parsed_ok}/{total} ({100*parsed_ok/total:.0f}%)")
print("\nFinal standings:")
for c in sorted(world.alive(), key=lambda x: -x.net_worth(world.last_price)):
print(f" {c.name:<9} pebbles={c.pebbles:>4} wellbeing={c.wellbeing} net={c.net_worth(world.last_price):.0f}")
if __name__ == "__main__":
main()