Skip to content

Commit c11f0d1

Browse files
committed
Add mock mode support - demo runs without Tinker API key
1 parent 2af394c commit c11f0d1

File tree

3 files changed

+113
-11
lines changed

3 files changed

+113
-11
lines changed

logger.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
"""
2+
Structured logging utilities for the training loop.
3+
"""
4+
5+
import json
6+
import logging
7+
import sys from datetime import datetime
8+
from pathlib import Path
9+
from typing import Any, Dict, Optional
10+
11+
12+
class StructuredLogger:
13+
"""JSON-structured logger for training metrics and events."""
14+
15+
def __init__(self, run_dir: Optional[Path] = None, log_level: int = logging.INFO):
16+
"""
17+
Initialize structured logger.
18+
19+
Args:
20+
run_dir: Directory to write metrics.jsonl. If None, logs to stdout only.
21+
log_level: Logging level (default INFO).
22+
"""
23+
self.run_dir = run_dir
24+
self.run_id = datetime.now().strftime("%Y%m%d_%H%M%S")
25+
26+
if run_dir:
27+
run_dir.mkdir(parents=True, exist_ok=True)
28+
self.metrics_file = run_dir / "metrics.jsonl"
29+
else:
30+
self.metrics_file = None
31+
32+
self.logger = logging.getLogger("tinker_eval_loop")
33+
self.logger.setLevel(log_level)
34+
35+
handler = logging.StreamHandler(sys.stdout)
36+
handler.setLevel(log_level)
37+
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
38+
handler.setFormatter(formatter)
39+
self.logger.addHandler(handler)
40+
41+
def log_event(self, event_type: str, data: Dict[str, Any], level: str = "INFO"):
42+
"""
43+
Log a structured event.
44+
45+
Args:
46+
event_type: Type of event (e.g., "training_start", "eval_complete").
47+
data: Event data dictionary.
48+
level: Log level (INFO, WARNING, ERROR).
49+
"""
50+
log_entry = {
51+
"timestamp": datetime.now().isoformat(),
52+
"run_id": self.run_id,
53+
"event": event_type,
54+
**data
55+
}
56+
57+
if self.metrics_file:
58+
with open(self.metrics_file, "a") as f:
59+
f.write(json.dumps(log_entry) + "\n")
60+
61+
log_fn = getattr(self.logger, level.lower(), self.logger.info)
62+
log_fn(f"[{event_type}] {json.dumps(data, indent=None)}")
63+
64+
def log_training_step(self, round_num: int, step: int, lr: float, loss: Optional[float] = None):
65+
"""Log a training step."""
66+
self.log_event("training_step", {
67+
"round": round_num,
68+
"step": step,
69+
"learning_rate": lr,
70+
"loss": loss,
71+
})
72+
73+
def log_evaluation(self, round_num: int, score: float, threshold: float, passed: bool, metrics: Optional[Dict] = None):
74+
"""Log an evaluation result."""
75+
self.log_event("evaluation", {
76+
"round": round_num,
77+
"score": score,
78+
"threshold": threshold,
79+
"passed": passed,
80+
"metrics": metrics or {},
81+
})
82+
83+
def log_checkpoint(self, round_num: int, checkpoint_uri: str):
84+
"""Log a checkpoint save."""
85+
self.log_event("checkpoint", {
86+
"round": round_num,
87+
"checkpoint_uri": checkpoint_uri,
88+
})
89+
90+
def log_config(self, config: Dict[str, Any]):
91+
"""Log the run configuration."""
92+
self.log_event("config", config)

run_demo.sh

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@ echo "╚═══════════════════════
77
echo ""
88

99
if [ -z "$TINKER_API_KEY" ]; then
10-
echo "❌ Error: TINKER_API_KEY environment variable not set"
10+
echo "⚠️ No TINKER_API_KEY found - running in MOCK MODE"
1111
echo ""
12-
echo "Please set your Tinker API key:"
12+
echo "Mock mode simulates Tinker training locally (no GPU, no cloud calls)."
13+
echo "To use real Tinker infrastructure, set:"
1314
echo " export TINKER_API_KEY=sk-your-key-here"
1415
echo ""
15-
exit 1
16+
export TINKER_MOCK=1
17+
else
18+
echo "✓ Tinker API key found - using real Tinker infrastructure"
19+
echo ""
1620
fi
1721

18-
echo "✓ Tinker API key found"
19-
echo ""
20-
2122
if [ ! -d ".venv" ]; then
2223
echo "📦 Creating virtual environment..."
2324
python3 -m venv .venv

trainer_with_eval.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,20 @@
2828

2929
import numpy as np
3030

31-
try:
32-
import tinker
33-
from tinker import types
34-
except ImportError:
35-
tinker = None
31+
USE_MOCK = os.getenv("TINKER_MOCK", "0") == "1"
32+
33+
if USE_MOCK:
34+
print("[MOCK MODE] Using offline mock Tinker client")
35+
from mock_tinker import create_mock_tinker_module
36+
tinker = create_mock_tinker_module()
37+
types = tinker.types
38+
else:
39+
try:
40+
import tinker
41+
from tinker import types
42+
except ImportError:
43+
tinker = None
44+
types = None
3645

3746
try:
3847
from inspect_ai import Task, task

0 commit comments

Comments
 (0)