code-review-env / env /trajectory_logger.py
ragavrida's picture
CodeReviewEnv v1.0 β€” OpenEnv-compliant submission
dbf5e96
Raw
History Blame Contribute Delete
3.74 kB
"""
Trajectory Logger β€” MBRL Dataset Hook
Each trajectory file is a valid training dataset for a semantic world model.
Format: JSONL where each line is one (s, a, r, s') transition.
To train a world model:
1. Load trajectories from trajectories/ directory
2. Encode states with an LLM encoder (e.g. sentence-transformers)
3. Train transition model f(s_t, a_t) -> (s_{t+1}, r_t)
4. Use model for planning without real env β€” Dyna-Q over language state space
This is the first step toward model-based planning over knowledge-work
environments. No existing MBRL benchmark provides this for semantic state spaces.
"""
import json
import os
from datetime import datetime, timezone
from typing import Dict, List, Optional
from env.models import Observation, Action, Reward
class TrajectoryLogger:
"""
Logs (state, action, reward, next_state) transitions in JSONL format.
Each episode produces one JSONL file, each line is one transition.
This format is directly consumable by dataset loaders for semantic
world model training β€” see world_model/scaffold.py.
Research motivation:
Standard MBRL benchmarks (MuJoCo, Atari) log transitions as
numerical vectors. SemanticTransitionDataset wraps these JSONL
files and provides encoding hooks for structured text states.
"""
def __init__(self, output_dir: str = "trajectories"):
self.output_dir = output_dir
self.transitions: List[Dict] = []
self.episode_id: Optional[str] = None
self.task: Optional[str] = None
os.makedirs(self.output_dir, exist_ok=True)
def start_episode(self, episode_id: str, task: str) -> None:
"""Begin a new episode, clearing any existing transition buffer."""
self.episode_id = episode_id
self.task = task
self.transitions = []
def log_transition(
self,
step: int,
state: Observation,
action: Action,
reward: Reward,
next_state: Observation,
done: bool,
) -> None:
"""
Log a single (s, a, r, s') transition.
Each transition is a complete snapshot suitable for world model
training: given (state, action), predict (next_state, reward).
"""
transition = {
"step": step,
"state": state.model_dump(),
"action": action.model_dump(),
"reward": reward.model_dump(),
"next_state": next_state.model_dump(),
"done": done,
"timestamp": datetime.now(timezone.utc).isoformat(),
"episode_id": self.episode_id,
"task": self.task,
}
self.transitions.append(transition)
def save(self) -> str:
"""
Save episode trajectory to JSONL file.
Returns the filepath of the saved trajectory.
Format: trajectories/{task}_{episode_id}.jsonl
"""
if not self.transitions:
return ""
filename = f"{self.task}_{self.episode_id}.jsonl"
filepath = os.path.join(self.output_dir, filename)
with open(filepath, "w") as f:
for transition in self.transitions:
f.write(json.dumps(transition, default=str) + "\n")
return filepath
def export(self) -> List[Dict]:
"""
Return full episode as list of dicts.
Clean JSONL-ready format for world model training dataset.
Each dict has keys: step, state, action, reward, next_state, done, timestamp.
"""
return list(self.transitions)
def reset(self) -> None:
"""Clear transition buffer for new episode."""
self.transitions = []
self.episode_id = None
self.task = None