Skip to content

Commit 2727c0b

Browse files
abidlabscursoragentgradio-pr-bot
authored
Add markdown reports across Trackio (#437)
Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
1 parent 4ac7d38 commit 2727c0b

14 files changed

Lines changed: 494 additions & 21 deletions

File tree

.changeset/ready-rats-kneel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"trackio": minor
3+
---
4+
5+
feat:Add markdown reports across Trackio

docs/source/cli_commands.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,26 @@ Output in JSON format:
6060
trackio list system-metrics --project "my-project" --run "my-run" --json
6161
```
6262

63+
### List Reports
64+
65+
List markdown reports in a project (across all runs):
66+
67+
```sh
68+
trackio list reports --project "my-project"
69+
```
70+
71+
List markdown reports for a specific run:
72+
73+
```sh
74+
trackio list reports --project "my-project" --run "my-run"
75+
```
76+
77+
Output in JSON format:
78+
79+
```sh
80+
trackio list reports --project "my-project" --run "my-run" --json
81+
```
82+
6383
## Get Commands
6484

6585
### Get Project Summary
@@ -140,6 +160,20 @@ Output in JSON format:
140160
trackio get system-metric --project "my-project" --run "my-run" --metric "gpu_utilization" --json
141161
```
142162

163+
### Get Report Content
164+
165+
Print markdown report entries for a specific report name in a run:
166+
167+
```sh
168+
trackio get report --project "my-project" --run "my-run" --report "training_report"
169+
```
170+
171+
Output in JSON format:
172+
173+
```sh
174+
trackio get report --project "my-project" --run "my-run" --report "training_report" --json
175+
```
176+
143177
## Output Formats
144178

145179
All commands support two output formats:
@@ -154,6 +188,7 @@ The CLI commands include comprehensive validation and error handling:
154188
- If a project doesn't exist, an error message is displayed
155189
- If a run doesn't exist in a project, an error message is displayed
156190
- If a metric doesn't exist in a run, an error message is displayed
191+
- If a report doesn't exist in a run, an error message is displayed
157192

158193
All errors are written to stderr and the command exits with a non-zero exit code.
159194

@@ -182,6 +217,12 @@ trackio get metric --project "my-project" --run "my-run" --metric "loss"
182217

183218
# 7. Get system metrics (if available)
184219
trackio list system-metrics --project "my-project" --run "my-run"
220+
221+
# 8. List reports in a run
222+
trackio list reports --project "my-project" --run "my-run"
223+
224+
# 9. Print report markdown in terminal
225+
trackio get report --project "my-project" --run "my-run" --report "training_report"
185226
```
186227

187228
## Use Cases

docs/source/track.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,30 @@ trackio.log(
9191
style="border:0;">
9292
</iframe>
9393

94+
### Logging reports (Markdown)
95+
96+
You can log markdown reports using the [`Markdown`] class. Reports are shown in the **Reports** page in the dashboard, where the newest report appears first.
97+
98+
```python
99+
trackio.log(
100+
{
101+
"training_report": trackio.Markdown(
102+
"""# Training Report
103+
104+
Final validation accuracy: **0.92**
105+
106+
- Best epoch: 18
107+
- Early stopping: enabled
108+
"""
109+
)
110+
}
111+
)
112+
```
113+
114+
You can log reports multiple times during a run (for example, one report per checkpoint), and Trackio will keep the full history across steps.
115+
116+
For a complete runnable script, see `examples/training-with-report.py`.
117+
94118
### Logging images
95119

96120
You can log images using the [`Image`] class.

examples/training-with-report.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import random
2+
import time
3+
4+
import trackio
5+
6+
PROJECT_ID = random.randint(100000, 999999)
7+
PROJECT_NAME = f"report-demo-{PROJECT_ID}"
8+
9+
trackio.init(
10+
project=PROJECT_NAME,
11+
name="run-with-report",
12+
config={"epochs": 12, "learning_rate": 0.001},
13+
)
14+
15+
loss_values = []
16+
accuracy_values = []
17+
18+
for step in range(12):
19+
loss = round(1.2 / (step + 1) + random.uniform(-0.03, 0.03), 4)
20+
accuracy = round(min(0.98, 0.5 + step * 0.04 + random.uniform(-0.02, 0.02)), 4)
21+
loss_values.append(loss)
22+
accuracy_values.append(accuracy)
23+
24+
trackio.log(
25+
{
26+
"train/loss": loss,
27+
"train/accuracy": accuracy,
28+
},
29+
step=step,
30+
)
31+
time.sleep(0.1)
32+
33+
best_accuracy = max(accuracy_values)
34+
final_loss = loss_values[-1]
35+
final_accuracy = accuracy_values[-1]
36+
37+
report_md = f"""# Training Report
38+
39+
Training completed for `{PROJECT_NAME}`.
40+
41+
## Final Metrics
42+
43+
- Final loss: `{final_loss}`
44+
- Final accuracy: `{final_accuracy}`
45+
- Best accuracy: `{best_accuracy}`
46+
"""
47+
48+
trackio.log({"training_report": trackio.Markdown(report_md)})
49+
trackio.finish()
50+
51+
print(f"Run complete. Open with: trackio show --project {PROJECT_NAME}")

tests/unit/test_run.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import pytest
66

7-
from trackio import Run, init
7+
from trackio import Markdown, Run, init
88
from trackio.sqlite_storage import SQLiteStorage
99

1010

@@ -28,6 +28,23 @@ def test_run_log_writes_to_sqlite_locally(temp_dir):
2828
assert config is not None
2929

3030

31+
def test_markdown_logging(temp_dir):
32+
run = Run(url=None, project="proj", client=None, name="run-report", space_id=None)
33+
run.log({"loss": 0.1, "summary": Markdown("# Training summary")})
34+
run.finish()
35+
36+
logs = SQLiteStorage.get_logs("proj", "run-report")
37+
38+
markdown_entries = [
39+
entry
40+
for entry in logs
41+
if isinstance(entry.get("summary"), dict)
42+
and entry["summary"].get("_type") == Markdown.TYPE
43+
]
44+
assert len(markdown_entries) == 1
45+
assert markdown_entries[0]["summary"]["_value"] == "# Training summary"
46+
47+
3148
def test_run_log_calls_client_for_spaces(temp_dir):
3249
client = DummyClient()
3350
run = Run(

trackio/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from trackio.gpu import gpu_available, log_gpu
2323
from trackio.histogram import Histogram
2424
from trackio.imports import import_csv, import_tf_events
25+
from trackio.markdown import Markdown
2526
from trackio.media import (
2627
TrackioAudio,
2728
TrackioImage,
@@ -64,6 +65,7 @@
6465
"Audio",
6566
"Table",
6667
"Histogram",
68+
"Markdown",
6769
"Api",
6870
]
6971

@@ -165,7 +167,6 @@ def init(
165167
gpu_log_interval (`float`, *optional*, defaults to `10.0`):
166168
The interval in seconds between automatic GPU metric logs.
167169
Only used when `auto_log_gpu=True`.
168-
169170
Returns:
170171
`Run`: A [`Run`] object that can be used to log metrics and finish the run.
171172
"""

0 commit comments

Comments
 (0)