feat: add Evennia training baseline and eval harness (#37)
This commit is contained in:
@@ -2,24 +2,52 @@ import json
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
DEFAULT_BASE_DIR = "~/.timmy/training-data/evennia"
|
||||
|
||||
def telemetry_dir(base_dir: str | Path = "~/.timmy/training-data/evennia") -> Path:
|
||||
|
||||
def telemetry_dir(base_dir: str | Path = DEFAULT_BASE_DIR) -> Path:
|
||||
return Path(base_dir).expanduser()
|
||||
|
||||
|
||||
def event_log_path(session_id: str, base_dir: str | Path = "~/.timmy/training-data/evennia") -> Path:
|
||||
def _session_day() -> str:
|
||||
return datetime.now(timezone.utc).strftime("%Y%m%d")
|
||||
|
||||
|
||||
def event_log_path(session_id: str, base_dir: str | Path = DEFAULT_BASE_DIR) -> Path:
|
||||
session_id = (session_id or "unbound").strip() or "unbound"
|
||||
day = datetime.now(timezone.utc).strftime("%Y%m%d")
|
||||
return telemetry_dir(base_dir) / day / f"{session_id}.jsonl"
|
||||
return telemetry_dir(base_dir) / _session_day() / f"{session_id}.jsonl"
|
||||
|
||||
|
||||
def append_event(session_id: str, event: dict, base_dir: str | Path = "~/.timmy/training-data/evennia") -> Path:
|
||||
def session_meta_path(session_id: str, base_dir: str | Path = DEFAULT_BASE_DIR) -> Path:
|
||||
session_id = (session_id or "unbound").strip() or "unbound"
|
||||
return telemetry_dir(base_dir) / _session_day() / f"{session_id}.meta.json"
|
||||
|
||||
|
||||
def write_session_metadata(session_id: str, metadata: dict, base_dir: str | Path = DEFAULT_BASE_DIR) -> Path:
|
||||
path = session_meta_path(session_id, base_dir)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
payload = {}
|
||||
if path.exists():
|
||||
try:
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
payload = {}
|
||||
payload.update(metadata or {})
|
||||
payload.setdefault("session_id", session_id)
|
||||
payload.setdefault("event_log_path", str(event_log_path(session_id, base_dir)))
|
||||
payload.setdefault("updated_at", datetime.now(timezone.utc).isoformat())
|
||||
path.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
|
||||
return path
|
||||
|
||||
|
||||
def append_event(session_id: str, event: dict, base_dir: str | Path = DEFAULT_BASE_DIR) -> Path:
|
||||
path = event_log_path(session_id, base_dir)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
payload = dict(event)
|
||||
payload.setdefault("timestamp", datetime.now(timezone.utc).isoformat())
|
||||
with path.open("a", encoding="utf-8") as f:
|
||||
f.write(json.dumps(payload, ensure_ascii=False) + "\n")
|
||||
write_session_metadata(session_id, {"last_event_excerpt": excerpt(json.dumps(payload, ensure_ascii=False), 400)}, base_dir)
|
||||
return path
|
||||
|
||||
|
||||
|
||||
28
evennia_tools/training.py
Normal file
28
evennia_tools/training.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from pathlib import Path
|
||||
|
||||
WORLD_BASICS_COMMANDS = (
|
||||
"look",
|
||||
"enter",
|
||||
"workshop",
|
||||
"look",
|
||||
"courtyard",
|
||||
"chapel",
|
||||
"look Book of the Soul",
|
||||
)
|
||||
|
||||
WORLD_BASICS_EXPECTATIONS = {
|
||||
"look": ("Gate",),
|
||||
"enter": ("Courtyard",),
|
||||
"workshop": ("Workshop", "Workbench"),
|
||||
"courtyard": ("Courtyard", "Map Table"),
|
||||
"chapel": ("Chapel", "Prayer Wall"),
|
||||
"look Book of the Soul": ("Book of the Soul", "doctrinal anchor"),
|
||||
}
|
||||
|
||||
|
||||
def example_trace_path(repo_root: str | Path) -> Path:
|
||||
return Path(repo_root) / "training-data" / "evennia" / "examples" / "world-basics-trace.example.jsonl"
|
||||
|
||||
|
||||
def example_eval_path(repo_root: str | Path) -> Path:
|
||||
return Path(repo_root) / "training-data" / "evennia" / "examples" / "world-basics-eval.example.json"
|
||||
Reference in New Issue
Block a user