hard007ik commited on
Commit
04b615f
·
1 Parent(s): 8464e70

complete almost

Browse files
Blog.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🏬 ShopManagerEng: Training LLMs to Run a Business
2
+
3
+ Welcome to **ShopManagerEng**, a Reinforcement Learning (RL) environment designed to test and train Large Language Models (LLMs) on complex, multi-step business operations.
4
+
5
+ While LLMs have become incredibly adept at chatting and writing code, evaluating their ability to make strategic, long-term decisions in a dynamic environment remains a challenge. ShopManagerEng tackles this by putting the AI in the shoes of a jewelry shop manager. Dont get into name 'Eng',just typos mistake of 'Env'.
6
+
7
+ This blog post breaks down how the environment works, its architecture, and how it can be used to train smarter, more strategic agents.
8
+
9
+ ---
10
+
11
+ ## 🎮 The Environment: A 3-Phase Business Simulation
12
+
13
+ ShopManagerEng is not a simple Q&A benchmark. It is a continuous simulation where the agent must manage inventory, respond to market fluctuations, and negotiate with customers. Every "episode" (a full game loop) consists of three distinct phases:
14
+
15
+ ### Phase 1: 📈 The Market (Supply)
16
+ The agent starts with a limited budget and must decide when to buy raw gold.
17
+ * **The Catch:** Gold prices fluctuate. The agent can observe price trends and decide to "wait" for a better price or "buy" immediately.
18
+ * **Real-World Noise:** The environment supports a "real" market mode that pulls live gold prices from Yahoo Finance, testing the agent against real-world economic volatility.
19
+
20
+ ### Phase 2: 🏭 The Warehouse (Production)
21
+ Once gold is acquired, the agent must decide what to craft: Rings, Necklaces, or Bracelets.
22
+ * **The Catch:** The agent must balance raw material costs, labor costs, and market demand. It receives a "demand forecast" (which includes noise) and must make production choices that maximize potential profit without running out of cash or gold.
23
+
24
+ ### Phase 3: 🤝 The Showroom (Sales)
25
+ The final phase tests the agent's negotiation skills.
26
+ * **The Catch:** Customers make initial offers. The agent can accept, reject, or counter-offer over a maximum of 5 rounds. Push too hard, and the customer walks away (resulting in zero profit). Settle too early, and the agent leaves money on the table.
27
+
28
+ The agent's final score is a cumulative reward based on how well it navigated all three phases.
29
+
30
+ ---
31
+
32
+ ## 🏗️ Architecture Under the Hood
33
+
34
+ ShopManagerEng is built on a robust Client-Server architecture, making it highly scalable for Reinforcement Learning tasks.
35
+
36
+ 1. **The Server (`/server/`):** The core simulation engine runs as a standalone web application (often deployed via Docker to a Hugging Face Space). It tracks the hidden "true" state of the world, handles state transitions, fetches real market data, and manages an SQLite database to log inventory and invoices.
37
+ 2. **The Client (`client.py` & `models.py`):** Provides a clean, typed Python interface. Agents use this client to send actions (e.g., `{"market_action": "buy", "gold_qty": 2.0}`) and receive structured observations in return.
38
+ 3. **The AI Player (`inference.py`):** A script demonstrating how to plug an LLM (like Llama 3) into the environment. It dynamically builds text prompts explaining the current state (e.g., *"Gold is $2000/oz and trending down. You have $1000. Buy or wait?"*) and parses the LLM's text output back into valid game actions.
39
+ 4. **The Training Suite (`/training/`):** The real power of this project lies in its RL training capabilities. Using algorithms like GRPO (Group Relative Policy Optimization), the framework can run massive batches of episodes, evaluate the agent using custom reward functions, and iteratively update the model's weights to forge a master negotiator and supply-chain manager.
40
+
41
+ ### 🛠️ Technical Stack & Data Flow
42
+
43
+ * **FastAPI & OpenEnv:** The server is powered by FastAPI, leveraging the `openenv` framework to standardize interactions. This ensures the environment can be easily hosted (e.g., on Hugging Face Spaces) and queried by agents remotely.
44
+ * **Pydantic Models:** All actions and observations are strongly typed using Pydantic (`models.py`). This guarantees that agents send properly formatted JSON payloads (like `target_price_usd` or `inventory_urgent` flags) and receive structured state data.
45
+ * **State Persistence:** A built-in SQLite store (`sqlite_store.py`) tracks the complex state across episodes, maintaining ledgers for cash, gold (in troy ounces and grams), and specific inventory items (rings, necklaces, bracelets).
46
+ * **yfinance Integration:** For the "real" market mode, the environment dynamically fetches live GC=F (Gold Futures) ticker data via `market_data.py`, injecting true market volatility into the simulation rather than relying purely on synthetic random walks.
47
+ * **GRPO Training:** The training pipeline (`train_jewelry_grpo.py`) utilizes Group Relative Policy Optimization, an advanced RL technique designed to stabilize training and improve sample efficiency when teaching LLMs complex, multi-step tasks. Custom reward functions (`rewards.py`) evaluate and guide the model's behavior.
48
+
49
+ ---
50
+
51
+ ## 🚀 Why This Matters
52
+
53
+ As we move towards autonomous AI agents, we need benchmarks that go beyond static knowledge retrieval. ShopManagerEng evaluates an agent's ability to:
54
+ * **Plan Long-Term:** A bad purchase in Phase 1 ruins the negotiation in Phase 3.
55
+ * **Handle Uncertainty:** Dealing with noisy demand forecasts and volatile live markets.
56
+ * **Negotiate:** Understanding margins and customer psychology.
57
+
58
+ Whether you are testing the out-of-the-box reasoning of a new foundational model or fine-tuning a specialized RL agent, ShopManagerEng provides a rich, complex sandbox to push AI capabilities forward.
README.md CHANGED
@@ -5,12 +5,15 @@ colorFrom: green
5
  colorTo: blue
6
  sdk: docker
7
  pinned: false
8
- app_port: 8000
9
  base_path: /web
10
  tags:
11
  - openenv
12
  ---
13
 
 
 
 
14
  # Jewelry Shop Manager — RL Environment
15
 
16
  A reinforcement learning environment simulating a **jewelry shop management** pipeline. An AI agent navigates three sequential phases — buying raw materials, selecting products to craft based on demand, and negotiating sales — to maximize profit.
 
5
  colorTo: blue
6
  sdk: docker
7
  pinned: false
8
+ app_port: 7860
9
  base_path: /web
10
  tags:
11
  - openenv
12
  ---
13
 
14
+ Link of the environment: https://huggingface.co/spaces/hard007ik/ShopManagerEng
15
+ Link of Blog.md: https://huggingface.co/spaces/hard007ik/ShopManagerEng/tree/main/Blog.md
16
+
17
  # Jewelry Shop Manager — RL Environment
18
 
19
  A reinforcement learning environment simulating a **jewelry shop management** pipeline. An AI agent navigates three sequential phases — buying raw materials, selecting products to craft based on demand, and negotiating sales — to maximize profit.
inference.py CHANGED
@@ -71,7 +71,8 @@ SYSTEM_PROMPT = textwrap.dedent(
71
  Respond: "ring", "necklace", or "bracelet".
72
 
73
  ## Phase 3: SHOWROOM (negotiate)
74
- The customer makes an offer; if you counter, they raise it ~5% per round,
 
75
  up to 5 rounds. After 5 rounds with no acceptance, the customer leaves
76
  (no phase-3 reward). Reject also gives 0 phase-3 reward.
77
  Respond: "I accept" or a counter like "How about $X?". NEVER explicitly reject.
@@ -344,8 +345,8 @@ async def main() -> None:
344
  # ── ENV SERVER URL ──────────────────────────────────────────────────────
345
  # LOCAL: start server with `uv run --project . server`, then use localhost
346
  # REMOTE: comment the localhost line and uncomment the HF Space line
347
- # base_url = "http://localhost:8000"
348
- base_url = "https://hard007ik-shopmanagereng.hf.space"
349
  # ───────────────────────────────────────────────────────────────────────
350
 
351
  # print(f"[CONFIG] base_url={base_url} model={MODEL_NAME}", flush=True)
 
71
  Respond: "ring", "necklace", or "bracelet".
72
 
73
  ## Phase 3: SHOWROOM (negotiate)
74
+ you makes an offer; if customer counter by telling less price from your offer, you can drop price about ~3-5% per round but make sure to not sell when loss is happening also bring max profit,
75
+ if customer says less price then your first told price then you have to say the price that lesser than the price you told before but more that the customer told price
76
  up to 5 rounds. After 5 rounds with no acceptance, the customer leaves
77
  (no phase-3 reward). Reject also gives 0 phase-3 reward.
78
  Respond: "I accept" or a counter like "How about $X?". NEVER explicitly reject.
 
345
  # ── ENV SERVER URL ──────────────────────────────────────────────────────
346
  # LOCAL: start server with `uv run --project . server`, then use localhost
347
  # REMOTE: comment the localhost line and uncomment the HF Space line
348
+ base_url = "http://localhost:8000"
349
+ # base_url = "https://hard007ik-shopmanagereng.hf.space"
350
  # ───────────────────────────────────────────────────────────────────────
351
 
352
  # print(f"[CONFIG] base_url={base_url} model={MODEL_NAME}", flush=True)
pyproject.toml CHANGED
@@ -21,6 +21,7 @@ dependencies = [
21
  "yfinance>=0.2.40",
22
  "python-dotenv>=1.0.0",
23
  "requests>=2.28.0",
 
24
  ]
25
 
26
  [project.optional-dependencies]
 
21
  "yfinance>=0.2.40",
22
  "python-dotenv>=1.0.0",
23
  "requests>=2.28.0",
24
+ "streamlit>=1.30.0",
25
  ]
26
 
27
  [project.optional-dependencies]
server/Dockerfile CHANGED
@@ -59,6 +59,11 @@ FROM ${BASE_IMAGE}
59
 
60
  WORKDIR /app
61
 
 
 
 
 
 
62
  # Copy the virtual environment from builder
63
  COPY --from=builder /app/env/.venv /app/.venv
64
 
@@ -71,10 +76,15 @@ ENV PATH="/app/.venv/bin:$PATH"
71
  # Set PYTHONPATH so imports work correctly
72
  ENV PYTHONPATH="/app/env:$PYTHONPATH"
73
 
 
 
 
74
  # Health check
75
  HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
76
  CMD curl -f http://localhost:8000/health || exit 1
77
 
78
- # Run the FastAPI server
79
- # The module path is constructed to work with the /app/env structure
80
- CMD ["sh", "-c", "cd /app/env && uvicorn server.app:app --host 0.0.0.0 --port 8000"]
 
 
 
59
 
60
  WORKDIR /app
61
 
62
+ # Install curl (for health checks in start.sh) and streamlit
63
+ RUN apt-get update && \
64
+ apt-get install -y --no-install-recommends curl && \
65
+ rm -rf /var/lib/apt/lists/*
66
+
67
  # Copy the virtual environment from builder
68
  COPY --from=builder /app/env/.venv /app/.venv
69
 
 
76
  # Set PYTHONPATH so imports work correctly
77
  ENV PYTHONPATH="/app/env:$PYTHONPATH"
78
 
79
+ # Install streamlit into the existing venv
80
+ RUN pip install --no-cache-dir streamlit
81
+
82
  # Health check
83
  HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
84
  CMD curl -f http://localhost:8000/health || exit 1
85
 
86
+ # Make startup script executable
87
+ RUN chmod +x /app/env/start.sh
88
+
89
+ # Run both API server (background) + Streamlit UI (foreground)
90
+ CMD ["/app/env/start.sh"]
start.sh ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Start the OpenEnv API server in the background (port 8000)
5
+ cd /app/env
6
+ uvicorn server.app:app --host 0.0.0.0 --port 8000 &
7
+ API_PID=$!
8
+
9
+ # Wait for the API to be ready
10
+ echo "[start] Waiting for API server on port 8000..."
11
+ for i in $(seq 1 30); do
12
+ if curl -sf http://localhost:8000/health > /dev/null 2>&1; then
13
+ echo "[start] API server ready."
14
+ break
15
+ fi
16
+ sleep 1
17
+ done
18
+
19
+ # Start Streamlit UI (port 7860 — HF Spaces default)
20
+ echo "[start] Launching Streamlit UI on port 7860..."
21
+ exec streamlit run ui.py \
22
+ --server.port 7860 \
23
+ --server.address 0.0.0.0 \
24
+ --server.headless true \
25
+ --browser.gatherUsageStats false \
26
+ --theme.primaryColor "#7c3aed" \
27
+ --theme.backgroundColor "#0f0c29" \
28
+ --theme.secondaryBackgroundColor "#302b63" \
29
+ --theme.textColor "#e2e8f0"
train_jewelry_grpo.py CHANGED
@@ -44,6 +44,7 @@ try:
44
  from ShopManagerEng.training.plotting import (
45
  build_metrics_callback,
46
  save_training_artifacts,
 
47
  )
48
  from ShopManagerEng.training.prompts import SYSTEM_PROMPT
49
  from ShopManagerEng.training.rewards import (
@@ -56,6 +57,7 @@ except ImportError: # script-style invocation from inside the folder
56
  from training.plotting import ( # type: ignore
57
  build_metrics_callback,
58
  save_training_artifacts,
 
59
  )
60
  from training.prompts import SYSTEM_PROMPT # type: ignore
61
  from training.rewards import ( # type: ignore
@@ -135,6 +137,12 @@ def main() -> None:
135
  help="Fraction of GPU mem reserved for vLLM. Lower if OOM.",
136
  )
137
  ap.add_argument("--push-to-hub", action="store_true")
 
 
 
 
 
 
138
  ap.add_argument(
139
  "--report-to",
140
  default=os.environ.get("TRAIN_REPORT_TO", "trackio"),
@@ -330,6 +338,24 @@ def main() -> None:
330
  trainer.save_model(args.output_dir)
331
  if args.push_to_hub:
332
  trainer.push_to_hub()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  print(f"[DONE] saved to {args.output_dir}")
334
 
335
 
 
44
  from ShopManagerEng.training.plotting import (
45
  build_metrics_callback,
46
  save_training_artifacts,
47
+ upload_training_artifacts_to_hub,
48
  )
49
  from ShopManagerEng.training.prompts import SYSTEM_PROMPT
50
  from ShopManagerEng.training.rewards import (
 
57
  from training.plotting import ( # type: ignore
58
  build_metrics_callback,
59
  save_training_artifacts,
60
+ upload_training_artifacts_to_hub,
61
  )
62
  from training.prompts import SYSTEM_PROMPT # type: ignore
63
  from training.rewards import ( # type: ignore
 
137
  help="Fraction of GPU mem reserved for vLLM. Lower if OOM.",
138
  )
139
  ap.add_argument("--push-to-hub", action="store_true")
140
+ ap.add_argument(
141
+ "--hub-repo-id",
142
+ default=None,
143
+ help="HF model repo (user/model-name) for weight push + training-artifact upload. "
144
+ "If omitted, artifact upload uses {whoami}/{basename of --output-dir}.",
145
+ )
146
  ap.add_argument(
147
  "--report-to",
148
  default=os.environ.get("TRAIN_REPORT_TO", "trackio"),
 
338
  trainer.save_model(args.output_dir)
339
  if args.push_to_hub:
340
  trainer.push_to_hub()
341
+ # Default Hub push only ships weights/tokenizer; upload plots + metrics explicitly.
342
+ try:
343
+ from huggingface_hub import whoami
344
+
345
+ user = whoami().get("name") or whoami().get("preferred_username", "user")
346
+ rid = (
347
+ args.hub_repo_id
348
+ or getattr(trainer.args, "hub_model_id", None)
349
+ or f"{user}/{Path(args.output_dir).name}"
350
+ )
351
+ uploaded = upload_training_artifacts_to_hub(args.output_dir, rid)
352
+ if uploaded:
353
+ print(
354
+ f"[HUB] training artifacts ({len(uploaded)} files) -> "
355
+ f"https://huggingface.co/{rid}/tree/main/training_artifacts"
356
+ )
357
+ except Exception as exc: # noqa: BLE001
358
+ print(f"[HUB] training artifact upload failed: {exc}")
359
  print(f"[DONE] saved to {args.output_dir}")
360
 
361
 
training/plotting.py CHANGED
@@ -278,3 +278,48 @@ def build_metrics_callback(output_dir: str | Path, snapshot_every: int = 5):
278
  return control
279
 
280
  return MetricsSaverCallback()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  return control
279
 
280
  return MetricsSaverCallback()
281
+
282
+
283
+ def upload_training_artifacts_to_hub(
284
+ output_dir: str | Path,
285
+ repo_id: str,
286
+ *,
287
+ path_in_repo: str = "training_artifacts",
288
+ ) -> list[str]:
289
+ """Upload small evidence files to the same model repo (PNGs, CSV, JSON).
290
+
291
+ ``GRPOTrainer.push_to_hub`` typically uploads weights/tokenizer only; this
292
+ adds ``metrics.csv``, ``loss_curve.png``, and related files under
293
+ ``path_in_repo/`` on the Hub so they survive ephemeral cloud jobs.
294
+ """
295
+ from huggingface_hub import HfApi, create_repo
296
+
297
+ out = Path(output_dir)
298
+ if not out.is_dir():
299
+ return []
300
+
301
+ create_repo(repo_id, repo_type="model", exist_ok=True)
302
+ api = HfApi()
303
+ names = (
304
+ "metrics.csv",
305
+ "metrics.json",
306
+ "loss_curve.png",
307
+ "reward_curve.png",
308
+ "reward_total_curve.png",
309
+ "training_summary.json",
310
+ )
311
+ prefix = path_in_repo.strip("/")
312
+ uploaded: list[str] = []
313
+ for name in names:
314
+ path = out / name
315
+ if not path.is_file():
316
+ continue
317
+ dest = f"{prefix}/{name}" if prefix else name
318
+ api.upload_file(
319
+ path_or_fileobj=str(path),
320
+ path_in_repo=dest,
321
+ repo_id=repo_id,
322
+ repo_type="model",
323
+ )
324
+ uploaded.append(dest)
325
+ return uploaded
training/rollout.py CHANGED
@@ -68,9 +68,17 @@ def rollout_once(
68
  """Play one full jewelry-shop episode and return per-episode signals.
69
 
70
  Returns the dict shape TRL's GRPO loop expects: ``prompt_ids``,
71
- ``completion_ids``, ``logprobs`` (concatenated across turns of the episode)
72
- plus reward signals consumed by reward functions (``total_reward``,
73
- ``market_reward``, ``warehouse_reward``, ``showroom_reward``).
 
 
 
 
 
 
 
 
74
  """
75
  # Late import: trl.experimental.openenv only exists for trl >= 0.17.
76
  from trl.experimental.openenv import generate_rollout_completions
@@ -79,9 +87,9 @@ def rollout_once(
79
  result = sync_env.reset(task_id=task_id)
80
  obs = result.observation
81
 
82
- prompt_ids: List[int] = []
83
- completion_ids: List[int] = []
84
- logprobs: List[float] = []
85
 
86
  history: List[str] = []
87
  last_reward = 0.0
@@ -99,9 +107,18 @@ def rollout_once(
99
  prompt_text = _apply_chat_template(tokenizer, messages, model_name=model_name)
100
 
101
  rollout_outputs = generate_rollout_completions(trainer, [prompt_text])[0]
102
- prompt_ids.extend(rollout_outputs["prompt_ids"])
103
- completion_ids.extend(rollout_outputs["completion_ids"])
104
- logprobs.extend(rollout_outputs["logprobs"])
 
 
 
 
 
 
 
 
 
105
 
106
  completion_text = rollout_outputs.get("text") or tokenizer.decode(
107
  rollout_outputs["completion_ids"], skip_special_tokens=True
@@ -125,10 +142,17 @@ def rollout_once(
125
  total_reward = float(getattr(obs, "cumulative_reward", sum(phase_rewards.values())))
126
  total_reward = max(0.0, min(total_reward, 1.0))
127
 
 
 
 
 
 
 
 
128
  return {
129
- "prompt_ids": prompt_ids,
130
- "completion_ids": completion_ids,
131
- "logprobs": logprobs,
132
  "total_reward": total_reward,
133
  "market_reward": float(phase_rewards["market"]),
134
  "warehouse_reward": float(phase_rewards["warehouse"]),
 
68
  """Play one full jewelry-shop episode and return per-episode signals.
69
 
70
  Returns the dict shape TRL's GRPO loop expects: ``prompt_ids``,
71
+ ``completion_ids``, ``logprobs`` for **a single** vLLM forward (the **last
72
+ environment turn** in the episode) plus reward signals for reward
73
+ functions.
74
+
75
+ We **do not** concatenate multiple turns into one list. In ``GRPOTrainer``,
76
+ each batch row is ``cat(prompt_ids, completion_ids)``; vLLM's per-token
77
+ ``logprobs`` must be for **that** exact sequence, or the importance-sampling
78
+ ratio (vLLM vs reference forward) collapses. Multi-turn play still runs in
79
+ the environment; the policy gradient is applied to the **last** action's
80
+ tokens, while ``total_reward`` remains the full episode return for GRPO
81
+ group advantages.
82
  """
83
  # Late import: trl.experimental.openenv only exists for trl >= 0.17.
84
  from trl.experimental.openenv import generate_rollout_completions
 
87
  result = sync_env.reset(task_id=task_id)
88
  obs = result.observation
89
 
90
+ # One (prompt_ids, completion_ids, logprobs) per vLLM call; last turn only
91
+ # is returned to TRL (see module docstring).
92
+ turn_traces: List[Dict[str, Any]] = []
93
 
94
  history: List[str] = []
95
  last_reward = 0.0
 
107
  prompt_text = _apply_chat_template(tokenizer, messages, model_name=model_name)
108
 
109
  rollout_outputs = generate_rollout_completions(trainer, [prompt_text])[0]
110
+ p_ids = rollout_outputs["prompt_ids"]
111
+ c_ids = rollout_outputs["completion_ids"]
112
+ lps = rollout_outputs["logprobs"]
113
+ p_list = p_ids.tolist() if hasattr(p_ids, "tolist") else list(p_ids)
114
+ c_list = c_ids.tolist() if hasattr(c_ids, "tolist") else list(c_ids)
115
+ turn_traces.append(
116
+ {
117
+ "prompt_ids": p_list,
118
+ "completion_ids": c_list,
119
+ "logprobs": [float(x) for x in lps],
120
+ }
121
+ )
122
 
123
  completion_text = rollout_outputs.get("text") or tokenizer.decode(
124
  rollout_outputs["completion_ids"], skip_special_tokens=True
 
142
  total_reward = float(getattr(obs, "cumulative_reward", sum(phase_rewards.values())))
143
  total_reward = max(0.0, min(total_reward, 1.0))
144
 
145
+ if not turn_traces:
146
+ raise ValueError(
147
+ "rollout_once produced no vLLM turns (max_turns too low or env ended "
148
+ "before the first action)."
149
+ )
150
+ last = turn_traces[-1]
151
+
152
  return {
153
+ "prompt_ids": last["prompt_ids"],
154
+ "completion_ids": last["completion_ids"],
155
+ "logprobs": last["logprobs"],
156
  "total_reward": total_reward,
157
  "market_reward": float(phase_rewards["market"]),
158
  "warehouse_reward": float(phase_rewards["warehouse"]),
training/training_artifacts_v1/loss_curve.png ADDED
training/training_artifacts_v1/metrics.csv ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ step,loss,grad_norm,learning_rate,num_tokens,completions/mean_length,completions/min_length,completions/max_length,completions/clipped_ratio,completions/mean_terminated_length,completions/min_terminated_length,completions/max_terminated_length,rewards/reward_total/mean,rewards/reward_total/std,rewards/reward_market/mean,rewards/reward_market/std,rewards/reward_warehouse/mean,rewards/reward_warehouse/std,rewards/reward_showroom/mean,rewards/reward_showroom/std,reward,reward_std,frac_reward_zero_std,sampling/sampling_logp_difference/mean,sampling/sampling_logp_difference/max,sampling/importance_sampling_ratio/min,sampling/importance_sampling_ratio/mean,sampling/importance_sampling_ratio/max,entropy,clip_ratio/low_mean,clip_ratio/low_min,clip_ratio/high_mean,clip_ratio/high_max,clip_ratio/region_mean,step_time,epoch,train_runtime,train_samples_per_second,train_steps_per_second,total_flos,train_loss
2
+ 1,-0.009,12.235088348388672,0.0,27758.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7793656587600708,0.12745577096939087,0.25,0.13440430164337158,0.42500001192092896,0.20160645246505737,0.10436563193798065,0.069697305560112,0.7793656587600708,0.12745577096939087,0.0,0.005470390431582928,0.22214925289154053,0.8007970452308655,0.9949374794960022,1.076386570930481,0.028439456821217846,0.0,0.0,0.0,0.0,0.0,19.228480510413647,0.05555555555555555,,,,,
3
+ 2,0.0723,60.551937103271484,5.000000000000001e-07,55324.0,3.25,3.0,7.0,0.0,3.25,3.0,7.0,0.719434380531311,0.1505809724330902,0.30000001192092896,0.17597654461860657,0.30000001192092896,0.17597654461860657,0.11943437159061432,0.07055392116308212,0.719434380531311,0.1505809724330902,0.0,0.01085888221859932,0.28092825412750244,0.8382877111434937,1.0260276794433594,1.324359655380249,0.036137547835437545,0.0,0.0,0.0,0.0,0.0,17.92062332853675,0.1111111111111111,,,,,
4
+ 3,0.1153,232.934814453125,1.0000000000000002e-06,83000.0,3.5,3.0,7.0,0.0,3.5,3.0,7.0,0.7885687351226807,0.1279384195804596,0.32500001788139343,0.18837162852287292,0.375,0.20160646736621857,0.08856874704360962,0.07010025531053543,0.7885687351226807,0.1279384344816208,0.0,0.0251829382032156,0.6850378513336182,0.5226751565933228,1.0358223915100098,1.9838452339172363,0.03248842835137111,0.0,0.0,0.0,0.0,0.0,17.184778176248074,0.16666666666666666,,,,,
5
+ 4,0.0243,13.620709419250488,1.5e-06,110708.0,3.125,3.0,7.0,0.0,3.125,3.0,7.0,0.7762374877929688,0.13016164302825928,0.32499998807907104,0.18837164342403412,0.3500000238418579,0.1967477649450302,0.10123749077320099,0.06825561076402664,0.7762374877929688,0.13016162812709808,0.0,0.007013080175966024,0.2646750509738922,0.7674550414085388,0.9837819337844849,1.0260045528411865,0.03743034108288157,0.0,0.0,0.0,0.0,0.0,17.90316915512085,0.2222222222222222,,,,,
6
+ 5,0.0004,2.0591225624084473,2.0000000000000003e-06,138452.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7784374952316284,0.12858590483665466,0.30000001192092896,0.17597654461860657,0.375,0.20160646736621857,0.10343749821186066,0.06380020827054977,0.7784374952316284,0.12858593463897705,0.0,0.001465568202547729,0.05673474818468094,0.9749767780303955,1.0017430782318115,1.058376669883728,0.008188390799773515,0.0,0.0,0.0,0.0,0.0,17.8210555203259,0.2777777777777778,,,,,
7
+ 6,0.0915,31.611696243286133,2.5e-06,166252.0,3.125,3.0,7.0,0.0,3.125,3.0,7.0,0.7915937900543213,0.12960509955883026,0.375,0.20160646736621857,0.32500001788139343,0.18837162852287292,0.09159374982118607,0.0639258474111557,0.7915937900543213,0.12960509955883026,0.0,0.008641102351248264,0.8236088752746582,0.9935171008110046,1.0399717092514038,2.278707504272461,0.007084679029730978,0.0,0.0,0.0,0.0,0.0,18.056264080107212,0.3333333333333333,,,,,
8
+ 7,-0.0,0.281630277633667,3e-06,193950.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7600874900817871,0.13816162943840027,0.32500001788139343,0.18837162852287292,0.32500001788139343,0.18837162852287292,0.11008749902248383,0.07028691470623016,0.7600874900817871,0.13816164433956146,0.0,3.554227441782132e-05,0.0027569520752876997,0.997247576713562,0.9999052286148071,1.0000724792480469,0.0005298306713825696,0.0,0.0,0.0,0.0,0.0,17.43799263238907,0.3888888888888889,,,,,
9
+ 8,0.0,0.00018881642608903348,3.5e-06,221677.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7622687816619873,0.1372590959072113,0.4000000059604645,0.20320022106170654,0.25,0.13440430164337158,0.11226874589920044,0.07360353320837021,0.7622687816619873,0.1372590959072113,0.0,2.545601773817907e-07,1.5496943888138048e-06,0.9999986886978149,1.000000238418579,1.0000016689300537,4.1391018498870835e-05,0.0,0.0,0.0,0.0,0.0,17.406394600868225,0.4444444444444444,,,,,
10
+ 9,0.0,0.00015632262511644512,4.000000000000001e-06,249549.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.775946855545044,0.137176051735878,0.375,0.20160646736621857,0.30000001192092896,0.17597654461860657,0.10094687342643738,0.058497413992881775,0.775946855545044,0.1371760368347168,0.0,2.918131087881193e-07,3.099441755693988e-06,0.9999978542327881,1.0,1.000001311302185,4.173239403826301e-05,0.0,0.0,0.0,0.0,0.0,18.514019537717104,0.5,,,,,
11
+ 10,0.0,9.833038348006085e-05,4.5e-06,277377.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7337374687194824,0.15055809915065765,0.2750000059604645,0.1586231142282486,0.3500000238418579,0.1967477649450302,0.10873749852180481,0.06778524816036224,0.7337374687194824,0.15055811405181885,0.0,2.719489771152439e-07,1.9073031580774114e-06,0.9999985694885254,0.9999998807907104,1.0000019073486328,4.224909940830912e-05,0.0,0.0,0.0,0.0,0.0,18.26371632888913,0.5555555555555556,,,,,
12
+ 11,-0.0,0.00015879125567153096,5e-06,305332.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7567968368530273,0.13728150725364685,0.375,0.20160646736621857,0.2750000059604645,0.1586231142282486,0.10679687559604645,0.07404065877199173,0.7567968368530273,0.13728150725364685,0.0,3.067227396513772e-07,2.6226434783893637e-06,0.9999973773956299,0.9999994039535522,1.0000019073486328,4.7876037001515215e-05,0.0,0.0,0.0,0.0,0.0,19.4472255371511,0.6111111111111112,,,,,
13
+ 12,-0.0,0.00039661259506829083,4.3750000000000005e-06,333165.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7081500291824341,0.1421954482793808,0.30000001192092896,0.17597654461860657,0.2750000059604645,0.1586231142282486,0.13315001130104065,0.07370516657829285,0.7081500291824341,0.142195463180542,0.0,4.768499479723687e-07,5.602954843197949e-06,0.9999943971633911,0.9999988675117493,1.0000016689300537,5.9777358274004655e-05,0.0,0.0,0.0,0.0,0.0,18.45015063509345,0.6666666666666666,,,,,
14
+ 13,0.0,0.0005282312049530447,3.7500000000000005e-06,361006.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7762781381607056,0.13823458552360535,0.32500001788139343,0.18837162852287292,0.3500000238418579,0.1967477649450302,0.10127812623977661,0.06158862262964249,0.7762781381607056,0.13823460042476654,0.0,6.830008487668238e-07,5.60290391149465e-06,0.9999943971633911,0.9999983310699463,1.0000022649765015,7.182803437899565e-05,0.0,0.0,0.0,0.0,0.0,17.955969959497452,0.7222222222222222,,,,,
15
+ 14,-0.0,0.000535853614564985,3.125e-06,388862.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7628874778747559,0.1295449286699295,0.30000001192092896,0.17597654461860657,0.3499999940395355,0.19674775004386902,0.11288750171661377,0.073255755007267,0.7628874778747559,0.1295449435710907,0.0,1.1113726259281975e-06,2.0979605324100703e-05,0.9999922513961792,1.0000004768371582,1.0000211000442505,9.972968496185786e-05,0.0,0.0,0.0,0.0,0.0,18.99697282537818,0.7777777777777778,,,,,
16
+ 15,0.0,0.005312301218509674,2.5e-06,416636.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7899656295776367,0.1296130269765854,0.3499999940395355,0.19674775004386902,0.3500000238418579,0.1967477649450302,0.08996562659740448,0.05463240668177605,0.7899656295776367,0.12961304187774658,0.0,4.004845322924666e-06,4.589592936099507e-05,0.9999337792396545,0.9999885559082031,1.0000029802322388,0.0001807671503684105,0.0,0.0,0.0,0.0,0.0,19.184648096561432,0.8333333333333334,,,,,
17
+ 16,-0.0,0.005995223298668861,1.8750000000000003e-06,444544.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.789996862411499,0.12048782408237457,0.375,0.20160646736621857,0.32039374113082886,0.18316024541854858,0.09460312128067017,0.062435995787382126,0.789996862411499,0.12048781663179398,0.0,4.866625204158481e-06,2.9087463190080598e-05,0.999959409236908,0.9999855160713196,1.0000004768371582,0.00019320984370096994,0.0,0.0,0.0,0.0,0.0,19.476148523390293,0.8888888888888888,,,,,
18
+ 17,0.0,0.011378168128430843,1.25e-06,472481.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.8168656826019287,0.09262391924858093,0.375,0.20160646736621857,0.3498094081878662,0.19690066576004028,0.09205625206232071,0.07046373933553696,0.8168656826019287,0.09262390434741974,0.0,5.950785180175444e-06,4.7328881919384e-05,0.9999284744262695,0.9999822974205017,1.000001072883606,0.00021975090658088448,0.0,0.0,0.0,0.0,0.0,19.344543006271124,0.9444444444444444,,,,,
19
+ 18,0.0,0.018683306872844696,6.25e-07,500266.0,3.0,3.0,3.0,0.0,3.0,3.0,3.0,0.7750625014305115,0.14084643125534058,0.3500000238418579,0.1967477649450302,0.32499998807907104,0.18837164342403412,0.10006250441074371,0.05640558898448944,0.7750625014305115,0.14084644615650177,0.0625,1.1303089195280336e-05,0.00027322862297296524,0.999584436416626,0.9999662637710571,0.9999997615814209,0.000320568448614722,0.0,0.0,0.0,0.0,0.0,17.66909484937787,1.0,,,,,
20
+ 18,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1.0,406.352,0.738,0.044,0.0,0.016376476217475202
training/training_artifacts_v1/metrics.json ADDED
@@ -0,0 +1,695 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "step": 1,
4
+ "loss": -0.009,
5
+ "grad_norm": 12.235088348388672,
6
+ "learning_rate": 0.0,
7
+ "num_tokens": 27758.0,
8
+ "completions/mean_length": 3.0,
9
+ "completions/min_length": 3.0,
10
+ "completions/max_length": 3.0,
11
+ "completions/clipped_ratio": 0.0,
12
+ "completions/mean_terminated_length": 3.0,
13
+ "completions/min_terminated_length": 3.0,
14
+ "completions/max_terminated_length": 3.0,
15
+ "rewards/reward_total/mean": 0.7793656587600708,
16
+ "rewards/reward_total/std": 0.12745577096939087,
17
+ "rewards/reward_market/mean": 0.25,
18
+ "rewards/reward_market/std": 0.13440430164337158,
19
+ "rewards/reward_warehouse/mean": 0.42500001192092896,
20
+ "rewards/reward_warehouse/std": 0.20160645246505737,
21
+ "rewards/reward_showroom/mean": 0.10436563193798065,
22
+ "rewards/reward_showroom/std": 0.069697305560112,
23
+ "reward": 0.7793656587600708,
24
+ "reward_std": 0.12745577096939087,
25
+ "frac_reward_zero_std": 0.0,
26
+ "sampling/sampling_logp_difference/mean": 0.005470390431582928,
27
+ "sampling/sampling_logp_difference/max": 0.22214925289154053,
28
+ "sampling/importance_sampling_ratio/min": 0.8007970452308655,
29
+ "sampling/importance_sampling_ratio/mean": 0.9949374794960022,
30
+ "sampling/importance_sampling_ratio/max": 1.076386570930481,
31
+ "entropy": 0.028439456821217846,
32
+ "clip_ratio/low_mean": 0.0,
33
+ "clip_ratio/low_min": 0.0,
34
+ "clip_ratio/high_mean": 0.0,
35
+ "clip_ratio/high_max": 0.0,
36
+ "clip_ratio/region_mean": 0.0,
37
+ "step_time": 19.228480510413647,
38
+ "epoch": 0.05555555555555555
39
+ },
40
+ {
41
+ "step": 2,
42
+ "loss": 0.0723,
43
+ "grad_norm": 60.551937103271484,
44
+ "learning_rate": 5.000000000000001e-07,
45
+ "num_tokens": 55324.0,
46
+ "completions/mean_length": 3.25,
47
+ "completions/min_length": 3.0,
48
+ "completions/max_length": 7.0,
49
+ "completions/clipped_ratio": 0.0,
50
+ "completions/mean_terminated_length": 3.25,
51
+ "completions/min_terminated_length": 3.0,
52
+ "completions/max_terminated_length": 7.0,
53
+ "rewards/reward_total/mean": 0.719434380531311,
54
+ "rewards/reward_total/std": 0.1505809724330902,
55
+ "rewards/reward_market/mean": 0.30000001192092896,
56
+ "rewards/reward_market/std": 0.17597654461860657,
57
+ "rewards/reward_warehouse/mean": 0.30000001192092896,
58
+ "rewards/reward_warehouse/std": 0.17597654461860657,
59
+ "rewards/reward_showroom/mean": 0.11943437159061432,
60
+ "rewards/reward_showroom/std": 0.07055392116308212,
61
+ "reward": 0.719434380531311,
62
+ "reward_std": 0.1505809724330902,
63
+ "frac_reward_zero_std": 0.0,
64
+ "sampling/sampling_logp_difference/mean": 0.01085888221859932,
65
+ "sampling/sampling_logp_difference/max": 0.28092825412750244,
66
+ "sampling/importance_sampling_ratio/min": 0.8382877111434937,
67
+ "sampling/importance_sampling_ratio/mean": 1.0260276794433594,
68
+ "sampling/importance_sampling_ratio/max": 1.324359655380249,
69
+ "entropy": 0.036137547835437545,
70
+ "clip_ratio/low_mean": 0.0,
71
+ "clip_ratio/low_min": 0.0,
72
+ "clip_ratio/high_mean": 0.0,
73
+ "clip_ratio/high_max": 0.0,
74
+ "clip_ratio/region_mean": 0.0,
75
+ "step_time": 17.92062332853675,
76
+ "epoch": 0.1111111111111111
77
+ },
78
+ {
79
+ "step": 3,
80
+ "loss": 0.1153,
81
+ "grad_norm": 232.934814453125,
82
+ "learning_rate": 1.0000000000000002e-06,
83
+ "num_tokens": 83000.0,
84
+ "completions/mean_length": 3.5,
85
+ "completions/min_length": 3.0,
86
+ "completions/max_length": 7.0,
87
+ "completions/clipped_ratio": 0.0,
88
+ "completions/mean_terminated_length": 3.5,
89
+ "completions/min_terminated_length": 3.0,
90
+ "completions/max_terminated_length": 7.0,
91
+ "rewards/reward_total/mean": 0.7885687351226807,
92
+ "rewards/reward_total/std": 0.1279384195804596,
93
+ "rewards/reward_market/mean": 0.32500001788139343,
94
+ "rewards/reward_market/std": 0.18837162852287292,
95
+ "rewards/reward_warehouse/mean": 0.375,
96
+ "rewards/reward_warehouse/std": 0.20160646736621857,
97
+ "rewards/reward_showroom/mean": 0.08856874704360962,
98
+ "rewards/reward_showroom/std": 0.07010025531053543,
99
+ "reward": 0.7885687351226807,
100
+ "reward_std": 0.1279384344816208,
101
+ "frac_reward_zero_std": 0.0,
102
+ "sampling/sampling_logp_difference/mean": 0.0251829382032156,
103
+ "sampling/sampling_logp_difference/max": 0.6850378513336182,
104
+ "sampling/importance_sampling_ratio/min": 0.5226751565933228,
105
+ "sampling/importance_sampling_ratio/mean": 1.0358223915100098,
106
+ "sampling/importance_sampling_ratio/max": 1.9838452339172363,
107
+ "entropy": 0.03248842835137111,
108
+ "clip_ratio/low_mean": 0.0,
109
+ "clip_ratio/low_min": 0.0,
110
+ "clip_ratio/high_mean": 0.0,
111
+ "clip_ratio/high_max": 0.0,
112
+ "clip_ratio/region_mean": 0.0,
113
+ "step_time": 17.184778176248074,
114
+ "epoch": 0.16666666666666666
115
+ },
116
+ {
117
+ "step": 4,
118
+ "loss": 0.0243,
119
+ "grad_norm": 13.620709419250488,
120
+ "learning_rate": 1.5e-06,
121
+ "num_tokens": 110708.0,
122
+ "completions/mean_length": 3.125,
123
+ "completions/min_length": 3.0,
124
+ "completions/max_length": 7.0,
125
+ "completions/clipped_ratio": 0.0,
126
+ "completions/mean_terminated_length": 3.125,
127
+ "completions/min_terminated_length": 3.0,
128
+ "completions/max_terminated_length": 7.0,
129
+ "rewards/reward_total/mean": 0.7762374877929688,
130
+ "rewards/reward_total/std": 0.13016164302825928,
131
+ "rewards/reward_market/mean": 0.32499998807907104,
132
+ "rewards/reward_market/std": 0.18837164342403412,
133
+ "rewards/reward_warehouse/mean": 0.3500000238418579,
134
+ "rewards/reward_warehouse/std": 0.1967477649450302,
135
+ "rewards/reward_showroom/mean": 0.10123749077320099,
136
+ "rewards/reward_showroom/std": 0.06825561076402664,
137
+ "reward": 0.7762374877929688,
138
+ "reward_std": 0.13016162812709808,
139
+ "frac_reward_zero_std": 0.0,
140
+ "sampling/sampling_logp_difference/mean": 0.007013080175966024,
141
+ "sampling/sampling_logp_difference/max": 0.2646750509738922,
142
+ "sampling/importance_sampling_ratio/min": 0.7674550414085388,
143
+ "sampling/importance_sampling_ratio/mean": 0.9837819337844849,
144
+ "sampling/importance_sampling_ratio/max": 1.0260045528411865,
145
+ "entropy": 0.03743034108288157,
146
+ "clip_ratio/low_mean": 0.0,
147
+ "clip_ratio/low_min": 0.0,
148
+ "clip_ratio/high_mean": 0.0,
149
+ "clip_ratio/high_max": 0.0,
150
+ "clip_ratio/region_mean": 0.0,
151
+ "step_time": 17.90316915512085,
152
+ "epoch": 0.2222222222222222
153
+ },
154
+ {
155
+ "step": 5,
156
+ "loss": 0.0004,
157
+ "grad_norm": 2.0591225624084473,
158
+ "learning_rate": 2.0000000000000003e-06,
159
+ "num_tokens": 138452.0,
160
+ "completions/mean_length": 3.0,
161
+ "completions/min_length": 3.0,
162
+ "completions/max_length": 3.0,
163
+ "completions/clipped_ratio": 0.0,
164
+ "completions/mean_terminated_length": 3.0,
165
+ "completions/min_terminated_length": 3.0,
166
+ "completions/max_terminated_length": 3.0,
167
+ "rewards/reward_total/mean": 0.7784374952316284,
168
+ "rewards/reward_total/std": 0.12858590483665466,
169
+ "rewards/reward_market/mean": 0.30000001192092896,
170
+ "rewards/reward_market/std": 0.17597654461860657,
171
+ "rewards/reward_warehouse/mean": 0.375,
172
+ "rewards/reward_warehouse/std": 0.20160646736621857,
173
+ "rewards/reward_showroom/mean": 0.10343749821186066,
174
+ "rewards/reward_showroom/std": 0.06380020827054977,
175
+ "reward": 0.7784374952316284,
176
+ "reward_std": 0.12858593463897705,
177
+ "frac_reward_zero_std": 0.0,
178
+ "sampling/sampling_logp_difference/mean": 0.001465568202547729,
179
+ "sampling/sampling_logp_difference/max": 0.05673474818468094,
180
+ "sampling/importance_sampling_ratio/min": 0.9749767780303955,
181
+ "sampling/importance_sampling_ratio/mean": 1.0017430782318115,
182
+ "sampling/importance_sampling_ratio/max": 1.058376669883728,
183
+ "entropy": 0.008188390799773515,
184
+ "clip_ratio/low_mean": 0.0,
185
+ "clip_ratio/low_min": 0.0,
186
+ "clip_ratio/high_mean": 0.0,
187
+ "clip_ratio/high_max": 0.0,
188
+ "clip_ratio/region_mean": 0.0,
189
+ "step_time": 17.8210555203259,
190
+ "epoch": 0.2777777777777778
191
+ },
192
+ {
193
+ "step": 6,
194
+ "loss": 0.0915,
195
+ "grad_norm": 31.611696243286133,
196
+ "learning_rate": 2.5e-06,
197
+ "num_tokens": 166252.0,
198
+ "completions/mean_length": 3.125,
199
+ "completions/min_length": 3.0,
200
+ "completions/max_length": 7.0,
201
+ "completions/clipped_ratio": 0.0,
202
+ "completions/mean_terminated_length": 3.125,
203
+ "completions/min_terminated_length": 3.0,
204
+ "completions/max_terminated_length": 7.0,
205
+ "rewards/reward_total/mean": 0.7915937900543213,
206
+ "rewards/reward_total/std": 0.12960509955883026,
207
+ "rewards/reward_market/mean": 0.375,
208
+ "rewards/reward_market/std": 0.20160646736621857,
209
+ "rewards/reward_warehouse/mean": 0.32500001788139343,
210
+ "rewards/reward_warehouse/std": 0.18837162852287292,
211
+ "rewards/reward_showroom/mean": 0.09159374982118607,
212
+ "rewards/reward_showroom/std": 0.0639258474111557,
213
+ "reward": 0.7915937900543213,
214
+ "reward_std": 0.12960509955883026,
215
+ "frac_reward_zero_std": 0.0,
216
+ "sampling/sampling_logp_difference/mean": 0.008641102351248264,
217
+ "sampling/sampling_logp_difference/max": 0.8236088752746582,
218
+ "sampling/importance_sampling_ratio/min": 0.9935171008110046,
219
+ "sampling/importance_sampling_ratio/mean": 1.0399717092514038,
220
+ "sampling/importance_sampling_ratio/max": 2.278707504272461,
221
+ "entropy": 0.007084679029730978,
222
+ "clip_ratio/low_mean": 0.0,
223
+ "clip_ratio/low_min": 0.0,
224
+ "clip_ratio/high_mean": 0.0,
225
+ "clip_ratio/high_max": 0.0,
226
+ "clip_ratio/region_mean": 0.0,
227
+ "step_time": 18.056264080107212,
228
+ "epoch": 0.3333333333333333
229
+ },
230
+ {
231
+ "step": 7,
232
+ "loss": -0.0,
233
+ "grad_norm": 0.281630277633667,
234
+ "learning_rate": 3e-06,
235
+ "num_tokens": 193950.0,
236
+ "completions/mean_length": 3.0,
237
+ "completions/min_length": 3.0,
238
+ "completions/max_length": 3.0,
239
+ "completions/clipped_ratio": 0.0,
240
+ "completions/mean_terminated_length": 3.0,
241
+ "completions/min_terminated_length": 3.0,
242
+ "completions/max_terminated_length": 3.0,
243
+ "rewards/reward_total/mean": 0.7600874900817871,
244
+ "rewards/reward_total/std": 0.13816162943840027,
245
+ "rewards/reward_market/mean": 0.32500001788139343,
246
+ "rewards/reward_market/std": 0.18837162852287292,
247
+ "rewards/reward_warehouse/mean": 0.32500001788139343,
248
+ "rewards/reward_warehouse/std": 0.18837162852287292,
249
+ "rewards/reward_showroom/mean": 0.11008749902248383,
250
+ "rewards/reward_showroom/std": 0.07028691470623016,
251
+ "reward": 0.7600874900817871,
252
+ "reward_std": 0.13816164433956146,
253
+ "frac_reward_zero_std": 0.0,
254
+ "sampling/sampling_logp_difference/mean": 3.554227441782132e-05,
255
+ "sampling/sampling_logp_difference/max": 0.0027569520752876997,
256
+ "sampling/importance_sampling_ratio/min": 0.997247576713562,
257
+ "sampling/importance_sampling_ratio/mean": 0.9999052286148071,
258
+ "sampling/importance_sampling_ratio/max": 1.0000724792480469,
259
+ "entropy": 0.0005298306713825696,
260
+ "clip_ratio/low_mean": 0.0,
261
+ "clip_ratio/low_min": 0.0,
262
+ "clip_ratio/high_mean": 0.0,
263
+ "clip_ratio/high_max": 0.0,
264
+ "clip_ratio/region_mean": 0.0,
265
+ "step_time": 17.43799263238907,
266
+ "epoch": 0.3888888888888889
267
+ },
268
+ {
269
+ "step": 8,
270
+ "loss": 0.0,
271
+ "grad_norm": 0.00018881642608903348,
272
+ "learning_rate": 3.5e-06,
273
+ "num_tokens": 221677.0,
274
+ "completions/mean_length": 3.0,
275
+ "completions/min_length": 3.0,
276
+ "completions/max_length": 3.0,
277
+ "completions/clipped_ratio": 0.0,
278
+ "completions/mean_terminated_length": 3.0,
279
+ "completions/min_terminated_length": 3.0,
280
+ "completions/max_terminated_length": 3.0,
281
+ "rewards/reward_total/mean": 0.7622687816619873,
282
+ "rewards/reward_total/std": 0.1372590959072113,
283
+ "rewards/reward_market/mean": 0.4000000059604645,
284
+ "rewards/reward_market/std": 0.20320022106170654,
285
+ "rewards/reward_warehouse/mean": 0.25,
286
+ "rewards/reward_warehouse/std": 0.13440430164337158,
287
+ "rewards/reward_showroom/mean": 0.11226874589920044,
288
+ "rewards/reward_showroom/std": 0.07360353320837021,
289
+ "reward": 0.7622687816619873,
290
+ "reward_std": 0.1372590959072113,
291
+ "frac_reward_zero_std": 0.0,
292
+ "sampling/sampling_logp_difference/mean": 2.545601773817907e-07,
293
+ "sampling/sampling_logp_difference/max": 1.5496943888138048e-06,
294
+ "sampling/importance_sampling_ratio/min": 0.9999986886978149,
295
+ "sampling/importance_sampling_ratio/mean": 1.000000238418579,
296
+ "sampling/importance_sampling_ratio/max": 1.0000016689300537,
297
+ "entropy": 4.1391018498870835e-05,
298
+ "clip_ratio/low_mean": 0.0,
299
+ "clip_ratio/low_min": 0.0,
300
+ "clip_ratio/high_mean": 0.0,
301
+ "clip_ratio/high_max": 0.0,
302
+ "clip_ratio/region_mean": 0.0,
303
+ "step_time": 17.406394600868225,
304
+ "epoch": 0.4444444444444444
305
+ },
306
+ {
307
+ "step": 9,
308
+ "loss": 0.0,
309
+ "grad_norm": 0.00015632262511644512,
310
+ "learning_rate": 4.000000000000001e-06,
311
+ "num_tokens": 249549.0,
312
+ "completions/mean_length": 3.0,
313
+ "completions/min_length": 3.0,
314
+ "completions/max_length": 3.0,
315
+ "completions/clipped_ratio": 0.0,
316
+ "completions/mean_terminated_length": 3.0,
317
+ "completions/min_terminated_length": 3.0,
318
+ "completions/max_terminated_length": 3.0,
319
+ "rewards/reward_total/mean": 0.775946855545044,
320
+ "rewards/reward_total/std": 0.137176051735878,
321
+ "rewards/reward_market/mean": 0.375,
322
+ "rewards/reward_market/std": 0.20160646736621857,
323
+ "rewards/reward_warehouse/mean": 0.30000001192092896,
324
+ "rewards/reward_warehouse/std": 0.17597654461860657,
325
+ "rewards/reward_showroom/mean": 0.10094687342643738,
326
+ "rewards/reward_showroom/std": 0.058497413992881775,
327
+ "reward": 0.775946855545044,
328
+ "reward_std": 0.1371760368347168,
329
+ "frac_reward_zero_std": 0.0,
330
+ "sampling/sampling_logp_difference/mean": 2.918131087881193e-07,
331
+ "sampling/sampling_logp_difference/max": 3.099441755693988e-06,
332
+ "sampling/importance_sampling_ratio/min": 0.9999978542327881,
333
+ "sampling/importance_sampling_ratio/mean": 1.0,
334
+ "sampling/importance_sampling_ratio/max": 1.000001311302185,
335
+ "entropy": 4.173239403826301e-05,
336
+ "clip_ratio/low_mean": 0.0,
337
+ "clip_ratio/low_min": 0.0,
338
+ "clip_ratio/high_mean": 0.0,
339
+ "clip_ratio/high_max": 0.0,
340
+ "clip_ratio/region_mean": 0.0,
341
+ "step_time": 18.514019537717104,
342
+ "epoch": 0.5
343
+ },
344
+ {
345
+ "step": 10,
346
+ "loss": 0.0,
347
+ "grad_norm": 9.833038348006085e-05,
348
+ "learning_rate": 4.5e-06,
349
+ "num_tokens": 277377.0,
350
+ "completions/mean_length": 3.0,
351
+ "completions/min_length": 3.0,
352
+ "completions/max_length": 3.0,
353
+ "completions/clipped_ratio": 0.0,
354
+ "completions/mean_terminated_length": 3.0,
355
+ "completions/min_terminated_length": 3.0,
356
+ "completions/max_terminated_length": 3.0,
357
+ "rewards/reward_total/mean": 0.7337374687194824,
358
+ "rewards/reward_total/std": 0.15055809915065765,
359
+ "rewards/reward_market/mean": 0.2750000059604645,
360
+ "rewards/reward_market/std": 0.1586231142282486,
361
+ "rewards/reward_warehouse/mean": 0.3500000238418579,
362
+ "rewards/reward_warehouse/std": 0.1967477649450302,
363
+ "rewards/reward_showroom/mean": 0.10873749852180481,
364
+ "rewards/reward_showroom/std": 0.06778524816036224,
365
+ "reward": 0.7337374687194824,
366
+ "reward_std": 0.15055811405181885,
367
+ "frac_reward_zero_std": 0.0,
368
+ "sampling/sampling_logp_difference/mean": 2.719489771152439e-07,
369
+ "sampling/sampling_logp_difference/max": 1.9073031580774114e-06,
370
+ "sampling/importance_sampling_ratio/min": 0.9999985694885254,
371
+ "sampling/importance_sampling_ratio/mean": 0.9999998807907104,
372
+ "sampling/importance_sampling_ratio/max": 1.0000019073486328,
373
+ "entropy": 4.224909940830912e-05,
374
+ "clip_ratio/low_mean": 0.0,
375
+ "clip_ratio/low_min": 0.0,
376
+ "clip_ratio/high_mean": 0.0,
377
+ "clip_ratio/high_max": 0.0,
378
+ "clip_ratio/region_mean": 0.0,
379
+ "step_time": 18.26371632888913,
380
+ "epoch": 0.5555555555555556
381
+ },
382
+ {
383
+ "step": 11,
384
+ "loss": -0.0,
385
+ "grad_norm": 0.00015879125567153096,
386
+ "learning_rate": 5e-06,
387
+ "num_tokens": 305332.0,
388
+ "completions/mean_length": 3.0,
389
+ "completions/min_length": 3.0,
390
+ "completions/max_length": 3.0,
391
+ "completions/clipped_ratio": 0.0,
392
+ "completions/mean_terminated_length": 3.0,
393
+ "completions/min_terminated_length": 3.0,
394
+ "completions/max_terminated_length": 3.0,
395
+ "rewards/reward_total/mean": 0.7567968368530273,
396
+ "rewards/reward_total/std": 0.13728150725364685,
397
+ "rewards/reward_market/mean": 0.375,
398
+ "rewards/reward_market/std": 0.20160646736621857,
399
+ "rewards/reward_warehouse/mean": 0.2750000059604645,
400
+ "rewards/reward_warehouse/std": 0.1586231142282486,
401
+ "rewards/reward_showroom/mean": 0.10679687559604645,
402
+ "rewards/reward_showroom/std": 0.07404065877199173,
403
+ "reward": 0.7567968368530273,
404
+ "reward_std": 0.13728150725364685,
405
+ "frac_reward_zero_std": 0.0,
406
+ "sampling/sampling_logp_difference/mean": 3.067227396513772e-07,
407
+ "sampling/sampling_logp_difference/max": 2.6226434783893637e-06,
408
+ "sampling/importance_sampling_ratio/min": 0.9999973773956299,
409
+ "sampling/importance_sampling_ratio/mean": 0.9999994039535522,
410
+ "sampling/importance_sampling_ratio/max": 1.0000019073486328,
411
+ "entropy": 4.7876037001515215e-05,
412
+ "clip_ratio/low_mean": 0.0,
413
+ "clip_ratio/low_min": 0.0,
414
+ "clip_ratio/high_mean": 0.0,
415
+ "clip_ratio/high_max": 0.0,
416
+ "clip_ratio/region_mean": 0.0,
417
+ "step_time": 19.4472255371511,
418
+ "epoch": 0.6111111111111112
419
+ },
420
+ {
421
+ "step": 12,
422
+ "loss": -0.0,
423
+ "grad_norm": 0.00039661259506829083,
424
+ "learning_rate": 4.3750000000000005e-06,
425
+ "num_tokens": 333165.0,
426
+ "completions/mean_length": 3.0,
427
+ "completions/min_length": 3.0,
428
+ "completions/max_length": 3.0,
429
+ "completions/clipped_ratio": 0.0,
430
+ "completions/mean_terminated_length": 3.0,
431
+ "completions/min_terminated_length": 3.0,
432
+ "completions/max_terminated_length": 3.0,
433
+ "rewards/reward_total/mean": 0.7081500291824341,
434
+ "rewards/reward_total/std": 0.1421954482793808,
435
+ "rewards/reward_market/mean": 0.30000001192092896,
436
+ "rewards/reward_market/std": 0.17597654461860657,
437
+ "rewards/reward_warehouse/mean": 0.2750000059604645,
438
+ "rewards/reward_warehouse/std": 0.1586231142282486,
439
+ "rewards/reward_showroom/mean": 0.13315001130104065,
440
+ "rewards/reward_showroom/std": 0.07370516657829285,
441
+ "reward": 0.7081500291824341,
442
+ "reward_std": 0.142195463180542,
443
+ "frac_reward_zero_std": 0.0,
444
+ "sampling/sampling_logp_difference/mean": 4.768499479723687e-07,
445
+ "sampling/sampling_logp_difference/max": 5.602954843197949e-06,
446
+ "sampling/importance_sampling_ratio/min": 0.9999943971633911,
447
+ "sampling/importance_sampling_ratio/mean": 0.9999988675117493,
448
+ "sampling/importance_sampling_ratio/max": 1.0000016689300537,
449
+ "entropy": 5.9777358274004655e-05,
450
+ "clip_ratio/low_mean": 0.0,
451
+ "clip_ratio/low_min": 0.0,
452
+ "clip_ratio/high_mean": 0.0,
453
+ "clip_ratio/high_max": 0.0,
454
+ "clip_ratio/region_mean": 0.0,
455
+ "step_time": 18.45015063509345,
456
+ "epoch": 0.6666666666666666
457
+ },
458
+ {
459
+ "step": 13,
460
+ "loss": 0.0,
461
+ "grad_norm": 0.0005282312049530447,
462
+ "learning_rate": 3.7500000000000005e-06,
463
+ "num_tokens": 361006.0,
464
+ "completions/mean_length": 3.0,
465
+ "completions/min_length": 3.0,
466
+ "completions/max_length": 3.0,
467
+ "completions/clipped_ratio": 0.0,
468
+ "completions/mean_terminated_length": 3.0,
469
+ "completions/min_terminated_length": 3.0,
470
+ "completions/max_terminated_length": 3.0,
471
+ "rewards/reward_total/mean": 0.7762781381607056,
472
+ "rewards/reward_total/std": 0.13823458552360535,
473
+ "rewards/reward_market/mean": 0.32500001788139343,
474
+ "rewards/reward_market/std": 0.18837162852287292,
475
+ "rewards/reward_warehouse/mean": 0.3500000238418579,
476
+ "rewards/reward_warehouse/std": 0.1967477649450302,
477
+ "rewards/reward_showroom/mean": 0.10127812623977661,
478
+ "rewards/reward_showroom/std": 0.06158862262964249,
479
+ "reward": 0.7762781381607056,
480
+ "reward_std": 0.13823460042476654,
481
+ "frac_reward_zero_std": 0.0,
482
+ "sampling/sampling_logp_difference/mean": 6.830008487668238e-07,
483
+ "sampling/sampling_logp_difference/max": 5.60290391149465e-06,
484
+ "sampling/importance_sampling_ratio/min": 0.9999943971633911,
485
+ "sampling/importance_sampling_ratio/mean": 0.9999983310699463,
486
+ "sampling/importance_sampling_ratio/max": 1.0000022649765015,
487
+ "entropy": 7.182803437899565e-05,
488
+ "clip_ratio/low_mean": 0.0,
489
+ "clip_ratio/low_min": 0.0,
490
+ "clip_ratio/high_mean": 0.0,
491
+ "clip_ratio/high_max": 0.0,
492
+ "clip_ratio/region_mean": 0.0,
493
+ "step_time": 17.955969959497452,
494
+ "epoch": 0.7222222222222222
495
+ },
496
+ {
497
+ "step": 14,
498
+ "loss": -0.0,
499
+ "grad_norm": 0.000535853614564985,
500
+ "learning_rate": 3.125e-06,
501
+ "num_tokens": 388862.0,
502
+ "completions/mean_length": 3.0,
503
+ "completions/min_length": 3.0,
504
+ "completions/max_length": 3.0,
505
+ "completions/clipped_ratio": 0.0,
506
+ "completions/mean_terminated_length": 3.0,
507
+ "completions/min_terminated_length": 3.0,
508
+ "completions/max_terminated_length": 3.0,
509
+ "rewards/reward_total/mean": 0.7628874778747559,
510
+ "rewards/reward_total/std": 0.1295449286699295,
511
+ "rewards/reward_market/mean": 0.30000001192092896,
512
+ "rewards/reward_market/std": 0.17597654461860657,
513
+ "rewards/reward_warehouse/mean": 0.3499999940395355,
514
+ "rewards/reward_warehouse/std": 0.19674775004386902,
515
+ "rewards/reward_showroom/mean": 0.11288750171661377,
516
+ "rewards/reward_showroom/std": 0.073255755007267,
517
+ "reward": 0.7628874778747559,
518
+ "reward_std": 0.1295449435710907,
519
+ "frac_reward_zero_std": 0.0,
520
+ "sampling/sampling_logp_difference/mean": 1.1113726259281975e-06,
521
+ "sampling/sampling_logp_difference/max": 2.0979605324100703e-05,
522
+ "sampling/importance_sampling_ratio/min": 0.9999922513961792,
523
+ "sampling/importance_sampling_ratio/mean": 1.0000004768371582,
524
+ "sampling/importance_sampling_ratio/max": 1.0000211000442505,
525
+ "entropy": 9.972968496185786e-05,
526
+ "clip_ratio/low_mean": 0.0,
527
+ "clip_ratio/low_min": 0.0,
528
+ "clip_ratio/high_mean": 0.0,
529
+ "clip_ratio/high_max": 0.0,
530
+ "clip_ratio/region_mean": 0.0,
531
+ "step_time": 18.99697282537818,
532
+ "epoch": 0.7777777777777778
533
+ },
534
+ {
535
+ "step": 15,
536
+ "loss": 0.0,
537
+ "grad_norm": 0.005312301218509674,
538
+ "learning_rate": 2.5e-06,
539
+ "num_tokens": 416636.0,
540
+ "completions/mean_length": 3.0,
541
+ "completions/min_length": 3.0,
542
+ "completions/max_length": 3.0,
543
+ "completions/clipped_ratio": 0.0,
544
+ "completions/mean_terminated_length": 3.0,
545
+ "completions/min_terminated_length": 3.0,
546
+ "completions/max_terminated_length": 3.0,
547
+ "rewards/reward_total/mean": 0.7899656295776367,
548
+ "rewards/reward_total/std": 0.1296130269765854,
549
+ "rewards/reward_market/mean": 0.3499999940395355,
550
+ "rewards/reward_market/std": 0.19674775004386902,
551
+ "rewards/reward_warehouse/mean": 0.3500000238418579,
552
+ "rewards/reward_warehouse/std": 0.1967477649450302,
553
+ "rewards/reward_showroom/mean": 0.08996562659740448,
554
+ "rewards/reward_showroom/std": 0.05463240668177605,
555
+ "reward": 0.7899656295776367,
556
+ "reward_std": 0.12961304187774658,
557
+ "frac_reward_zero_std": 0.0,
558
+ "sampling/sampling_logp_difference/mean": 4.004845322924666e-06,
559
+ "sampling/sampling_logp_difference/max": 4.589592936099507e-05,
560
+ "sampling/importance_sampling_ratio/min": 0.9999337792396545,
561
+ "sampling/importance_sampling_ratio/mean": 0.9999885559082031,
562
+ "sampling/importance_sampling_ratio/max": 1.0000029802322388,
563
+ "entropy": 0.0001807671503684105,
564
+ "clip_ratio/low_mean": 0.0,
565
+ "clip_ratio/low_min": 0.0,
566
+ "clip_ratio/high_mean": 0.0,
567
+ "clip_ratio/high_max": 0.0,
568
+ "clip_ratio/region_mean": 0.0,
569
+ "step_time": 19.184648096561432,
570
+ "epoch": 0.8333333333333334
571
+ },
572
+ {
573
+ "step": 16,
574
+ "loss": -0.0,
575
+ "grad_norm": 0.005995223298668861,
576
+ "learning_rate": 1.8750000000000003e-06,
577
+ "num_tokens": 444544.0,
578
+ "completions/mean_length": 3.0,
579
+ "completions/min_length": 3.0,
580
+ "completions/max_length": 3.0,
581
+ "completions/clipped_ratio": 0.0,
582
+ "completions/mean_terminated_length": 3.0,
583
+ "completions/min_terminated_length": 3.0,
584
+ "completions/max_terminated_length": 3.0,
585
+ "rewards/reward_total/mean": 0.789996862411499,
586
+ "rewards/reward_total/std": 0.12048782408237457,
587
+ "rewards/reward_market/mean": 0.375,
588
+ "rewards/reward_market/std": 0.20160646736621857,
589
+ "rewards/reward_warehouse/mean": 0.32039374113082886,
590
+ "rewards/reward_warehouse/std": 0.18316024541854858,
591
+ "rewards/reward_showroom/mean": 0.09460312128067017,
592
+ "rewards/reward_showroom/std": 0.062435995787382126,
593
+ "reward": 0.789996862411499,
594
+ "reward_std": 0.12048781663179398,
595
+ "frac_reward_zero_std": 0.0,
596
+ "sampling/sampling_logp_difference/mean": 4.866625204158481e-06,
597
+ "sampling/sampling_logp_difference/max": 2.9087463190080598e-05,
598
+ "sampling/importance_sampling_ratio/min": 0.999959409236908,
599
+ "sampling/importance_sampling_ratio/mean": 0.9999855160713196,
600
+ "sampling/importance_sampling_ratio/max": 1.0000004768371582,
601
+ "entropy": 0.00019320984370096994,
602
+ "clip_ratio/low_mean": 0.0,
603
+ "clip_ratio/low_min": 0.0,
604
+ "clip_ratio/high_mean": 0.0,
605
+ "clip_ratio/high_max": 0.0,
606
+ "clip_ratio/region_mean": 0.0,
607
+ "step_time": 19.476148523390293,
608
+ "epoch": 0.8888888888888888
609
+ },
610
+ {
611
+ "step": 17,
612
+ "loss": 0.0,
613
+ "grad_norm": 0.011378168128430843,
614
+ "learning_rate": 1.25e-06,
615
+ "num_tokens": 472481.0,
616
+ "completions/mean_length": 3.0,
617
+ "completions/min_length": 3.0,
618
+ "completions/max_length": 3.0,
619
+ "completions/clipped_ratio": 0.0,
620
+ "completions/mean_terminated_length": 3.0,
621
+ "completions/min_terminated_length": 3.0,
622
+ "completions/max_terminated_length": 3.0,
623
+ "rewards/reward_total/mean": 0.8168656826019287,
624
+ "rewards/reward_total/std": 0.09262391924858093,
625
+ "rewards/reward_market/mean": 0.375,
626
+ "rewards/reward_market/std": 0.20160646736621857,
627
+ "rewards/reward_warehouse/mean": 0.3498094081878662,
628
+ "rewards/reward_warehouse/std": 0.19690066576004028,
629
+ "rewards/reward_showroom/mean": 0.09205625206232071,
630
+ "rewards/reward_showroom/std": 0.07046373933553696,
631
+ "reward": 0.8168656826019287,
632
+ "reward_std": 0.09262390434741974,
633
+ "frac_reward_zero_std": 0.0,
634
+ "sampling/sampling_logp_difference/mean": 5.950785180175444e-06,
635
+ "sampling/sampling_logp_difference/max": 4.7328881919384e-05,
636
+ "sampling/importance_sampling_ratio/min": 0.9999284744262695,
637
+ "sampling/importance_sampling_ratio/mean": 0.9999822974205017,
638
+ "sampling/importance_sampling_ratio/max": 1.000001072883606,
639
+ "entropy": 0.00021975090658088448,
640
+ "clip_ratio/low_mean": 0.0,
641
+ "clip_ratio/low_min": 0.0,
642
+ "clip_ratio/high_mean": 0.0,
643
+ "clip_ratio/high_max": 0.0,
644
+ "clip_ratio/region_mean": 0.0,
645
+ "step_time": 19.344543006271124,
646
+ "epoch": 0.9444444444444444
647
+ },
648
+ {
649
+ "step": 18,
650
+ "loss": 0.0,
651
+ "grad_norm": 0.018683306872844696,
652
+ "learning_rate": 6.25e-07,
653
+ "num_tokens": 500266.0,
654
+ "completions/mean_length": 3.0,
655
+ "completions/min_length": 3.0,
656
+ "completions/max_length": 3.0,
657
+ "completions/clipped_ratio": 0.0,
658
+ "completions/mean_terminated_length": 3.0,
659
+ "completions/min_terminated_length": 3.0,
660
+ "completions/max_terminated_length": 3.0,
661
+ "rewards/reward_total/mean": 0.7750625014305115,
662
+ "rewards/reward_total/std": 0.14084643125534058,
663
+ "rewards/reward_market/mean": 0.3500000238418579,
664
+ "rewards/reward_market/std": 0.1967477649450302,
665
+ "rewards/reward_warehouse/mean": 0.32499998807907104,
666
+ "rewards/reward_warehouse/std": 0.18837164342403412,
667
+ "rewards/reward_showroom/mean": 0.10006250441074371,
668
+ "rewards/reward_showroom/std": 0.05640558898448944,
669
+ "reward": 0.7750625014305115,
670
+ "reward_std": 0.14084644615650177,
671
+ "frac_reward_zero_std": 0.0625,
672
+ "sampling/sampling_logp_difference/mean": 1.1303089195280336e-05,
673
+ "sampling/sampling_logp_difference/max": 0.00027322862297296524,
674
+ "sampling/importance_sampling_ratio/min": 0.999584436416626,
675
+ "sampling/importance_sampling_ratio/mean": 0.9999662637710571,
676
+ "sampling/importance_sampling_ratio/max": 0.9999997615814209,
677
+ "entropy": 0.000320568448614722,
678
+ "clip_ratio/low_mean": 0.0,
679
+ "clip_ratio/low_min": 0.0,
680
+ "clip_ratio/high_mean": 0.0,
681
+ "clip_ratio/high_max": 0.0,
682
+ "clip_ratio/region_mean": 0.0,
683
+ "step_time": 17.66909484937787,
684
+ "epoch": 1.0
685
+ },
686
+ {
687
+ "step": 18,
688
+ "train_runtime": 406.352,
689
+ "train_samples_per_second": 0.738,
690
+ "train_steps_per_second": 0.044,
691
+ "total_flos": 0.0,
692
+ "train_loss": 0.016376476217475202,
693
+ "epoch": 1.0
694
+ }
695
+ ]
training/training_artifacts_v1/reward_curve.png ADDED
training/training_artifacts_v1/reward_total_curve.png ADDED
training/training_artifacts_v1/training_summary.json ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "loss": {
3
+ "final": 0.0,
4
+ "max": 0.1153,
5
+ "min": -0.009,
6
+ "mean": 0.01637777777777778,
7
+ "n": 18
8
+ },
9
+ "reward_total": {
10
+ "final": 0.7750625014305115,
11
+ "max": 0.8168656826019287,
12
+ "min": 0.7081500291824341,
13
+ "mean": 0.7689822945329878,
14
+ "n": 18
15
+ },
16
+ "reward_market": {
17
+ "final": 0.0,
18
+ "max": 0.0,
19
+ "min": 0.0,
20
+ "mean": 0.0,
21
+ "n": 0
22
+ },
23
+ "reward_warehouse": {
24
+ "final": 0.0,
25
+ "max": 0.0,
26
+ "min": 0.0,
27
+ "mean": 0.0,
28
+ "n": 0
29
+ },
30
+ "reward_showroom": {
31
+ "final": 0.0,
32
+ "max": 0.0,
33
+ "min": 0.0,
34
+ "mean": 0.0,
35
+ "n": 0
36
+ },
37
+ "n_log_rows": 19,
38
+ "output_dir": "/workspace/shopmanager-grpo-qwen3",
39
+ "run_config": {
40
+ "model": "Qwen/Qwen3-1.7B",
41
+ "env_url": "https://hard007ik-shopmanagereng.hf.space",
42
+ "dataset_size": 300,
43
+ "num_generations": 2,
44
+ "per_device_batch": 1,
45
+ "grad_accum": 32,
46
+ "max_completion_length": 64,
47
+ "max_turns": 15,
48
+ "lr": 5e-06,
49
+ "warmup_steps": 10,
50
+ "max_steps": -1,
51
+ "epochs": 1,
52
+ "vllm_gpu_mem": 0.3,
53
+ "reward_weights": [
54
+ 1.0,
55
+ 0.0,
56
+ 0.0,
57
+ 0.0
58
+ ],
59
+ "precision": {
60
+ "bf16": true
61
+ }
62
+ }
63
+ }
ui.py ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Streamlit UI for ShopManagerEng — Interactive Jewelry Shop Demo.
3
+
4
+ An AI heuristic agent automatically plays through each episode.
5
+ Users press "New Episode" and watch the agent navigate all 3 phases.
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ import random
11
+ import time
12
+ from pathlib import Path
13
+
14
+ import streamlit as st
15
+
16
+ # ── Ensure imports resolve ──────────────────────────────────────────────────
17
+ ROOT = Path(__file__).resolve().parent
18
+ if str(ROOT) not in sys.path:
19
+ sys.path.insert(0, str(ROOT))
20
+
21
+ os.environ.setdefault("SHOPMANAGER_MARKET_MODE", "synthetic")
22
+
23
+ from server.ShopManagerEng_environment import JewelryShopEnvironment
24
+ from models import JewelryAction, PRODUCT_CATALOG
25
+
26
+
27
+ # ── Page config ─────────────────────────────────────────────────────────────
28
+ st.set_page_config(
29
+ page_title="ShopManagerEng — Jewelry Shop RL",
30
+ page_icon="💎",
31
+ layout="wide",
32
+ initial_sidebar_state="expanded",
33
+ )
34
+
35
+ # ── CSS: clean light-theme styling ──────────────────────────────────────────
36
+ st.markdown("""
37
+ <style>
38
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap');
39
+ html, body, [class*="st-"] { font-family: 'Inter', sans-serif; }
40
+
41
+ .hero-title {
42
+ font-size: 36px; font-weight: 800;
43
+ background: linear-gradient(135deg, #7c3aed, #3b82f6, #10b981);
44
+ -webkit-background-clip: text; -webkit-text-fill-color: transparent;
45
+ margin-bottom: 2px;
46
+ }
47
+ .hero-sub { font-size: 15px; color: #64748b; margin-bottom: 20px; }
48
+
49
+ .metric-card {
50
+ background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px;
51
+ padding: 14px 18px; text-align: center; min-height: 90px;
52
+ }
53
+ .metric-card .label { font-size: 12px; color: #64748b; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
54
+ .metric-card .value { font-size: 24px; font-weight: 800; color: #1e293b; margin-top: 4px; }
55
+
56
+ .phase-box {
57
+ background: #f1f5f9; border: 1px solid #cbd5e1; border-radius: 12px;
58
+ padding: 18px; margin-bottom: 12px;
59
+ }
60
+ .phase-box.active { border: 2px solid #7c3aed; background: #f5f3ff; }
61
+ .phase-box h4 { margin: 0 0 6px; color: #1e293b; }
62
+ .phase-box p { margin: 0; color: #475569; font-size: 14px; }
63
+
64
+ .env-msg {
65
+ background: #eff6ff; border-left: 4px solid #3b82f6;
66
+ border-radius: 0 10px 10px 0; padding: 12px 16px;
67
+ margin: 10px 0; font-size: 13px; color: #1e40af; line-height: 1.5;
68
+ word-wrap: break-word;
69
+ }
70
+
71
+ .step-row {
72
+ padding: 8px 12px; margin: 4px 0; border-radius: 8px;
73
+ font-size: 13px; color: #334155;
74
+ }
75
+ .step-row.market { background: #fef3c7; border-left: 3px solid #f59e0b; }
76
+ .step-row.warehouse { background: #dbeafe; border-left: 3px solid #3b82f6; }
77
+ .step-row.showroom { background: #d1fae5; border-left: 3px solid #10b981; }
78
+
79
+ .reward-big {
80
+ text-align: center; padding: 24px;
81
+ background: linear-gradient(135deg, #f5f3ff, #eff6ff);
82
+ border: 2px solid #7c3aed; border-radius: 16px;
83
+ }
84
+ .reward-big .score { font-size: 52px; font-weight: 800; color: #7c3aed; }
85
+ .reward-big .label { font-size: 14px; color: #64748b; }
86
+
87
+ .catalog-card {
88
+ background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px;
89
+ padding: 16px; text-align: center;
90
+ }
91
+ .catalog-card h4 { margin: 0 0 8px; color: #1e293b; }
92
+ .catalog-card p { margin: 2px 0; color: #475569; font-size: 13px; }
93
+
94
+ .demand-bar {
95
+ background: #e2e8f0; border-radius: 6px; height: 10px; overflow: hidden; margin-top: 4px;
96
+ }
97
+ .demand-fill { height: 100%; border-radius: 6px; }
98
+ </style>
99
+ """, unsafe_allow_html=True)
100
+
101
+
102
+ # ── Heuristic Agent ─────────────────────────────────────────────────────────
103
+ def heuristic_action(obs):
104
+ """Simple rule-based agent that plays through all 3 phases."""
105
+ if obs.phase == "market":
106
+ price = float(obs.gold_price or 300)
107
+ # Buy if we have enough cash for at least 1 oz
108
+ if obs.cash >= price + 10:
109
+ return JewelryAction(
110
+ market_action="buy",
111
+ gold_qty=1.0,
112
+ target_price_usd=obs.gold_price,
113
+ )
114
+ return JewelryAction(market_action="wait")
115
+
116
+ if obs.phase == "warehouse":
117
+ # Pick the highest-demand product we can afford
118
+ demand = obs.demand or {"ring": 0.5, "necklace": 0.3, "bracelet": 0.2}
119
+ for name in sorted(demand, key=lambda k: demand.get(k, 0), reverse=True):
120
+ spec = PRODUCT_CATALOG[name]
121
+ if obs.gold_oz + 1e-8 >= spec["gold_oz"] and obs.cash >= spec["labor"]:
122
+ return JewelryAction(product_choice=name)
123
+ return JewelryAction(product_choice="ring")
124
+
125
+ if obs.phase == "showroom":
126
+ # Accept if margin > 15% or after round 3
127
+ if (
128
+ obs.current_offer
129
+ and obs.cost_basis > 0
130
+ and float(obs.current_offer) / float(obs.cost_basis) >= 1.15
131
+ ) or (obs.negotiation_round and int(obs.negotiation_round) >= 3):
132
+ return JewelryAction(message="I accept")
133
+ offer = float(obs.current_offer or 0)
134
+ if offer:
135
+ return JewelryAction(message=f"How about ${offer * 1.08:.2f}?")
136
+ return JewelryAction(message="I need a better offer")
137
+
138
+ return JewelryAction()
139
+
140
+
141
+ # ── Session state ───────────────────────────────────────────────────────────
142
+ if "episode_steps" not in st.session_state:
143
+ st.session_state.episode_steps = None
144
+ st.session_state.final_reward = None
145
+ st.session_state.episode_count = 0
146
+
147
+
148
+ def run_episode(task_id):
149
+ """Run a full episode with the heuristic agent and return step logs."""
150
+ env = JewelryShopEnvironment()
151
+ seed = random.randint(0, 99999)
152
+ obs = env.reset(seed=seed, market_mode="synthetic", task_id=task_id)
153
+
154
+ steps = [{
155
+ "step": 0, "phase": obs.phase, "action": "reset",
156
+ "msg": obs.message, "reward": 0.0,
157
+ "cash": obs.cash, "gold_oz": obs.gold_oz,
158
+ "gold_price": obs.gold_price,
159
+ "cumulative": float(obs.cumulative_reward),
160
+ }]
161
+
162
+ for i in range(1, 20):
163
+ if obs.done:
164
+ break
165
+ action = heuristic_action(obs)
166
+
167
+ # Describe the action in human terms
168
+ if obs.phase == "market":
169
+ act_str = f"BUY {action.gold_qty} oz" if action.market_action == "buy" else "WAIT"
170
+ elif obs.phase == "warehouse":
171
+ act_str = f"CRAFT {action.product_choice}"
172
+ else:
173
+ act_str = action.message or "..."
174
+
175
+ obs = env.step(action)
176
+ steps.append({
177
+ "step": i, "phase": obs.phase, "action": act_str,
178
+ "msg": obs.message, "reward": float(obs.reward),
179
+ "cash": obs.cash, "gold_oz": obs.gold_oz,
180
+ "gold_price": getattr(obs, "gold_price", 0),
181
+ "product": getattr(obs, "product_for_sale", None),
182
+ "offer": float(obs.current_offer) if obs.current_offer else None,
183
+ "cost_basis": float(obs.cost_basis) if obs.cost_basis else None,
184
+ "cumulative": float(obs.cumulative_reward),
185
+ })
186
+
187
+ return steps, float(obs.cumulative_reward)
188
+
189
+
190
+ # ── Sidebar ─────────────────────────────────────────────────────────────────
191
+ with st.sidebar:
192
+ st.markdown("### 💎 ShopManagerEng")
193
+ st.markdown("---")
194
+
195
+ task = st.selectbox(
196
+ "🎯 Task Profile",
197
+ ["profit_negotiator", "market_timing", "demand_crafter"],
198
+ index=0,
199
+ )
200
+ weights = {
201
+ "profit_negotiator": "Showroom 60% · Market 20% · Warehouse 20%",
202
+ "market_timing": "Market 60% · Warehouse 20% · Showroom 20%",
203
+ "demand_crafter": "Warehouse 60% · Market 20% · Showroom 20%",
204
+ }
205
+ st.caption(f"**Weights:** {weights[task]}")
206
+
207
+ st.markdown("---")
208
+ if st.button("🚀 New Episode", use_container_width=True, type="primary"):
209
+ steps, reward = run_episode(task)
210
+ st.session_state.episode_steps = steps
211
+ st.session_state.final_reward = reward
212
+ st.session_state.episode_count += 1
213
+ st.rerun()
214
+
215
+ st.markdown("---")
216
+ st.markdown("#### How It Works")
217
+ st.markdown("""
218
+ An AI **heuristic agent** automatically plays
219
+ through all 3 phases of the jewelry shop:
220
+
221
+ 1. 📈 **Market** — Buy gold at the right price
222
+ 2. 🏭 **Warehouse** — Craft the most demanded product
223
+ 3. 🤝 **Showroom** — Negotiate the best sale price
224
+
225
+ Press **🚀 New Episode** to watch the agent play!
226
+ """)
227
+
228
+ if st.session_state.final_reward is not None:
229
+ st.markdown("---")
230
+ reward = st.session_state.final_reward
231
+ color = "#10b981" if reward >= 0.6 else "#f59e0b" if reward >= 0.4 else "#ef4444"
232
+ st.markdown(f"**Final Score:** :{'green' if reward >= 0.6 else 'orange' if reward >= 0.4 else 'red'}[{reward:.4f}]")
233
+ st.metric("Episodes Played", st.session_state.episode_count)
234
+
235
+
236
+ # ── Main area ───────────────────────────────────────────────────────────────
237
+ st.markdown('<p class="hero-title">💎 Jewelry Shop Manager</p>', unsafe_allow_html=True)
238
+ st.markdown('<p class="hero-sub">An RL environment for training LLMs on multi-step business decisions</p>', unsafe_allow_html=True)
239
+
240
+
241
+ # ── No episode yet — show welcome ──────────────────────────────────────────
242
+ if st.session_state.episode_steps is None:
243
+ st.info("👋 **Welcome!** Press **🚀 New Episode** in the sidebar to watch the AI agent play through the jewelry shop simulation.")
244
+
245
+ st.markdown("### 📦 Product Catalog")
246
+ cols = st.columns(3)
247
+ items = [("💍 Ring", "ring"), ("📿 Necklace", "necklace"), ("⌚ Bracelet", "bracelet")]
248
+ for i, (icon_name, key) in enumerate(items):
249
+ spec = PRODUCT_CATALOG[key]
250
+ with cols[i]:
251
+ st.markdown(f"""
252
+ <div class="catalog-card">
253
+ <h4>{icon_name}</h4>
254
+ <p>🪙 Gold: {spec['gold_oz']} oz</p>
255
+ <p>🔧 Labor: ${spec['labor']:.0f}</p>
256
+ <p>📊 Base demand: {spec['base_demand']:.0%}</p>
257
+ </div>
258
+ """, unsafe_allow_html=True)
259
+
260
+ st.markdown("### 🧠 Three Business Phases")
261
+ c1, c2, c3 = st.columns(3)
262
+ with c1:
263
+ st.markdown("""
264
+ <div class="phase-box">
265
+ <h4>📈 Phase 1: Market</h4>
266
+ <p>Buy raw gold at the best price. Prices fluctuate — time your purchase wisely!</p>
267
+ </div>
268
+ """, unsafe_allow_html=True)
269
+ with c2:
270
+ st.markdown("""
271
+ <div class="phase-box">
272
+ <h4>🏭 Phase 2: Warehouse</h4>
273
+ <p>Craft a product (ring, necklace, bracelet) that matches market demand.</p>
274
+ </div>
275
+ """, unsafe_allow_html=True)
276
+ with c3:
277
+ st.markdown("""
278
+ <div class="phase-box">
279
+ <h4>🤝 Phase 3: Showroom</h4>
280
+ <p>Negotiate with a customer over 5 rounds to maximize your selling price.</p>
281
+ </div>
282
+ """, unsafe_allow_html=True)
283
+
284
+
285
+ # ── Episode results ─────────────────────────────────────────────────────────
286
+ else:
287
+ steps = st.session_state.episode_steps
288
+ reward = st.session_state.final_reward
289
+
290
+ # ── Score banner ────────────────────────────────────────────────────────
291
+ if reward >= 0.8:
292
+ grade, grade_emoji = "Excellent", "🏆"
293
+ elif reward >= 0.6:
294
+ grade, grade_emoji = "Good", "👍"
295
+ elif reward >= 0.4:
296
+ grade, grade_emoji = "Fair", "😐"
297
+ else:
298
+ grade, grade_emoji = "Poor", "😬"
299
+
300
+ st.markdown(f"""
301
+ <div class="reward-big">
302
+ <div class="label">{grade_emoji} Episode #{st.session_state.episode_count} — {grade}</div>
303
+ <div class="score">{reward:.4f}</div>
304
+ <div class="label">cumulative reward (out of 1.0)</div>
305
+ </div>
306
+ """, unsafe_allow_html=True)
307
+
308
+ st.markdown("")
309
+
310
+ # ── Summary metrics ─────────────────────────────────────────────────────
311
+ last = steps[-1]
312
+ m1, m2, m3, m4 = st.columns(4)
313
+ with m1:
314
+ st.markdown(f"""<div class="metric-card"><div class="label">Steps</div><div class="value">{len(steps)-1}</div></div>""", unsafe_allow_html=True)
315
+ with m2:
316
+ st.markdown(f"""<div class="metric-card"><div class="label">Final Cash</div><div class="value">${last['cash']:,.0f}</div></div>""", unsafe_allow_html=True)
317
+ with m3:
318
+ gold_price = steps[0].get("gold_price", 0)
319
+ st.markdown(f"""<div class="metric-card"><div class="label">Gold Price</div><div class="value">${gold_price:,.0f}/oz</div></div>""", unsafe_allow_html=True)
320
+ with m4:
321
+ product = None
322
+ for s in steps:
323
+ if s.get("product"):
324
+ product = s["product"]
325
+ st.markdown(f"""<div class="metric-card"><div class="label">Product</div><div class="value">{(product or 'N/A').title()}</div></div>""", unsafe_allow_html=True)
326
+
327
+ st.markdown("---")
328
+
329
+ # ── Step-by-step log ────────────────────────────────────────────────────
330
+ st.markdown("### 📋 Agent Decision Log")
331
+
332
+ for s in steps:
333
+ phase = s.get("phase", "market")
334
+ icon = {"market": "📈", "warehouse": "🏭", "showroom": "🤝"}.get(phase, "⬜")
335
+ step_num = s["step"]
336
+ action = s.get("action", "")
337
+ rw = s.get("reward", 0)
338
+ cum = s.get("cumulative", 0)
339
+
340
+ rw_badge = f" · reward: `{rw:.4f}`" if rw else ""
341
+ cum_str = f" · cumulative: `{cum:.4f}`" if cum else ""
342
+
343
+ # Use pure markdown — no raw HTML divs
344
+ st.markdown(f"**Step {step_num}** {icon} **{action}**{rw_badge}{cum_str}")
345
+
346
+ # Show environment message
347
+ if s.get("msg"):
348
+ st.caption(s["msg"])
349
+
350
+ st.divider()
351
+
352
+ # ── Reward progression chart ────────────────────────────────────────────
353
+ st.markdown("---")
354
+ st.markdown("### 📊 Cumulative Reward Over Steps")
355
+ chart_data = [s["cumulative"] for s in steps]
356
+ st.line_chart(chart_data, use_container_width=True, height=200)
357
+
358
+ st.info("Press **🚀 New Episode** in the sidebar to run another episode with a different seed!")