Share a Weights & Biases report
W&B reports are the right internal artifact and the wrong external one. The link asks for a login, the login asks for a seat in your team, and the person you wanted to show the chart to is a client, a reviewer, or an advisor who will never have one.
Export the run history
import plotly.graph_objects as go
import wandb
api = wandb.Api()
fig = go.Figure()
for run_id in ("abc123", "def456"):
run = api.run(f"my-team/my-project/{run_id}")
hist = run.history(keys=["_step", "val/loss"], pandas=True).dropna()
fig.add_trace(go.Scatter(x=hist["_step"], y=hist["val/loss"],
mode="lines", name=run.name))
fig.update_layout(title="val/loss — baseline vs new schedule",
xaxis_title="step", yaxis_title="val/loss")
fig.write_html("wandb.html", include_plotlyjs="inline")
include_plotlyjs="inline" keeps the file
self-contained — a chart that fetches its own
library from a CDN is a chart that renders blank on a locked-down network.
Publish it:
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html wandb.html \
--arg title "Schedule comparison — $(date +%F)" '{title: $title, html: $html}')"
What the published copy adds
- Anchored threads — the question about the step-8k divergence sits on the chart. See commenting on HTML.
- Revisions — one report id per experiment family; each publish is kept.
- Access per report — private, team-only, or domain-gated, decided per report rather than per workspace. See the sharing model.
Limits
- Entry HTML: 5 MB. Inlined plotly.js is roughly 3 MB; downsample long
histories with
samples=onhistory(). - Assets: 25 MB per file, 250 MB and 500 files per report.
- 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.