The .tgx Artifact Idea: Making Graph Experiments Easier to Inspect
Graph experiments generate a lot of context: what graph was used, what its
structure looked like, what hardware ran the experiment, what configuration
was used, what metrics resulted. This context is often scattered across
disparate files, command-line outputs, and wandb dashboards — or not saved at
all. TGraphX provides several write functions that, when used together, create
a self-contained experiment artifact directory that is easy to audit after
the fact.
Note: .tgx is used here as a conceptual shorthand for the artifact
directory pattern, not a confirmed file format standard in TGraphX.
The Core Write Functions
TGraphX exports five write functions for experiment context:
| Function | What it writes |
|---|---|
write_graph_stats |
Node count, edge count, feature shapes |
write_run_metadata |
Run timestamp, epoch count, final metrics |
write_experiment_config |
Hyperparameters, model type, dataset info |
write_hardware_report |
GPU name, memory, CPU count, platform |
write_sampling_metadata |
Sampling strategy and parameters (if applicable) |
Together, these cover the five categories of information that make an
experiment reproducible and auditable.
Using Runner and ExperimentConfig
The experiments module provides Runner, ExperimentConfig, GridRunner,
EarlyStopping, and ModelCheckpoint. Runner is the high-level orchestrator
that ties together the write functions with the training loop:
from tgraphx.experiments import (
Runner, ExperimentConfig, EarlyStopping, ModelCheckpoint
)
from tgraphx import CSVLogger
config = ExperimentConfig(
model=model,
optimizer=optimizer,
criterion=criterion,
epochs=100,
experiment_name="patch_graph_v1",
)
callbacks = [
EarlyStopping(patience=15, monitor="val_loss"),
ModelCheckpoint(path="./artifacts/best_model.pt", monitor="val_loss"),
]
logger = CSVLogger(log_dir="./artifacts", experiment_name="patch_graph_v1")
runner = Runner(config, callbacks=callbacks, logger=logger)
runner.fit(train_loader, val_loader)
Building the Artifact Directory Pattern
Use the write functions alongside Runner to create a complete artifact
directory:
from pathlib import Path
from tgraphx import (
write_graph_stats,
write_run_metadata,
write_experiment_config,
write_hardware_report,
)
from tgraphx.performance import env_report
from tgraphx.reproducibility import set_seed
# Setup
set_seed(42, deterministic=True)
artifact_dir = Path("./artifacts/run_001")
artifact_dir.mkdir(parents=True, exist_ok=True)
# 1. Hardware context (written before training)
write_hardware_report(path=artifact_dir / "hardware.json")
# 2. Environment context
env_info = env_report(include_hardware=True)
write_experiment_config(
{
**env_info,
"seed": 42,
"model_type": "TensorGraphSAGELayer x2",
"hidden_dim": 128,
"lr": 0.001,
"epochs": 100,
"dataset": "my_patch_graph_dataset",
},
path=artifact_dir / "config.json"
)
# 3. Graph statistics (written after graph construction)
write_graph_stats(g, path=artifact_dir / "graph_stats.json")
# 4. Run training (runner writes its own logs)
runner.fit(train_loader, val_loader)
# 5. Run metadata (written after training)
write_run_metadata(
{
"final_train_loss": final_train_loss,
"final_val_loss": final_val_loss,
"best_epoch": runner.best_epoch,
"early_stopped": runner.early_stopped,
},
path=artifact_dir / "run_metadata.json"
)
Resulting Artifact Directory
artifacts/run_001/
├── hardware.json ← GPU, CPU, memory info
├── config.json ← hyperparameters, env, seed
├── graph_stats.json ← N nodes, E edges, feature shapes
├── run_metadata.json ← final metrics, training outcome
└── metrics.csv ← per-epoch training/val metrics (CSVLogger)
This directory is self-contained. To understand what an experiment did, you
read these five files — no external service required, no dashboard login.
Why This Pattern Matters
For debugging: When a result is unexpectedly poor, graph_stats.json
immediately tells you if the graph was misconfigured (wrong node count, wrong
feature shapes). config.json tells you if the seed or hyperparameters were
different from what you thought.
For sharing: A collaborator can reproduce your result by reading
config.json, constructing the same graph, and using the same seed. They do
not need access to your wandb account.
For publication: Reviewers increasingly expect experiment configurations
to be attached to submissions. An artifact directory produced by this pattern
is a concrete deliverable.
For future you: Running an experiment in January and revisiting it in
October is much easier when the context is written to files rather than
reconstructed from memory.
GridRunner for Hyperparameter Sweeps
GridRunner extends Runner for grid searches:
from tgraphx.experiments import GridRunner, ExperimentConfig
base_config = ExperimentConfig(
model_class=MyGNN,
criterion=criterion,
epochs=50,
)
grid = {
"lr": [0.001, 0.01, 0.1],
"hidden_dim": [64, 128, 256],
}
grid_runner = GridRunner(base_config, grid=grid, log_dir="./artifacts/grid")
grid_runner.run(train_loader, val_loader)
Each configuration in the grid gets its own artifact directory, allowing
post-hoc comparison.
Logging Backends
TGraphX exports three loggers that work with Runner:
from tgraphx import CSVLogger, TensorBoardLogger, MLflowLogger
# No external dependencies
csv_logger = CSVLogger(log_dir="./artifacts", experiment_name="exp_v1")
# Requires tensorboard package
tb_logger = TensorBoardLogger(log_dir="./artifacts/tb")
# Requires mlflow package
mlflow_logger = MLflowLogger(tracking_uri="./mlruns")
CSVLogger is the most portable: the output is a plain .csv file readable
with any spreadsheet tool or pandas. TensorBoardLogger and MLflowLogger
require their respective packages but provide richer visualization.
What the Pattern Does Not Provide
The artifact directory pattern does not:
- Automatically save model weights (use ModelCheckpoint for that)
- Save raw data or graphs (those are typically too large)
- Provide diff-tracking between runs (no git-like history)
- Upload to cloud storage (local files only)
For large-scale experiment tracking with team collaboration, the artifact
directories can be uploaded to S3 or equivalent storage, or used as input
to MLflow's artifact store. TGraphX does not handle this upload step.
The Inspectability Principle
The value of writing experiment context to files is inspectability: a third
party with only the artifact directory and the TGraphX codebase should be
able to understand what happened in the experiment. Not reproduce it on
identical hardware — that requires more context — but understand it: what
graph, what model, what config, what results.
Inspectability is a weaker but more achievable goal than full reproducibility.
It is also more honest: claiming full reproducibility for a complex GNN
experiment often requires controlling for hardware, random number generator
state, library versions, and CUDA behavior in ways that are difficult to
guarantee. Claiming inspectability — "these files describe what we did" —
is a more defensible standard.