The GEO_* environment variables and /geo/… paths are exactly the names the platform actually provides.

Directories

/geo
dataset/GEO_DATA_DIR — original dataset files, read-only. All in place before training starts
manifest.jsonfile list · kinds · metadata
images/one subdirectory per kind (image)
annotations/(annotation)
timeseries/(timeseries)
tabular/(tabular)
pointclouds/(pointcloud)
work/GEO_WORK_DIR — writable workspace. Disappears when the run ends
experiment.jsonGEO_CONFIG — snapshot of the experiment settings (advanced)
PathEnvironment variableContents
/geo/datasetGEO_DATA_DIROriginal dataset files (read-only). Several runs reuse the same cache, so do not write here
/geo/workGEO_WORK_DIRCheckpoints · converted labels · intermediate outputs. Disappears with the pod
/geo/experiment.jsonGEO_CONFIGFull snapshot of the settings. Read it only when the environment variables are not enough

manifest.json

It sits directly under GEO_DATA_DIR. path is relative to GEO_DATA_DIR, so join the two as is to open a file.

{
  "dataset": { "id": "ds-…", "name": "…" },
  "files": [
    { "path": "images/site_008.jpg", "kind": "image",
      "meta": { "width": 640, "height": 480, "format": "JPEG",
                "label_files": [{ "filename": "site_008.json", "format": "labelme" }] } },
    { "path": "annotations/site_008.json", "kind": "annotation",
      "meta": { "format": "labelme", "annotation_count": 2, "match_rate": 1.0 } },
    { "path": "tabular/features.csv", "kind": "tabular",
      "meta": { "row_count": 300, "columns": [{ "name": "label", "dtype": "object" }] } }
  ]
}
  • kind is one of image · annotation · timeseries · tabular · pointcloud, and matches the subdirectory the file is placed in. Only files that passed validation are placed.
  • The directory also holds a hidden file the platform uses for its cache check (.stamp). Read the file list from manifest.json instead of scanning the directory.
  • The folder structure inside a zip is flattened on upload. If names collide, -2 is appended to the later one. Do not rely on structure such as per-class subfolders.
  • meta holds values filled in by the platform validators (image size and paired label files, annotation format, row count and columns of a table, and so on). The example is shortened and may omit keys.
  • Labels arrive in a different shape for each kind. Image data gets annotation files (COCO JSON · LabelMe JSON · VOC XML), tabular gets a column inside the CSV, and point clouds get an integer property inside the PLY file.
  • timeseries and tabular use the same .csv/.parquet files. The modality chosen when the dataset was created tells them apart. The meta of tabular has no time_column key at all.
  • The trainer does the train/val split. The platform does not split the files; it only writes the ratio and seed into split in experiment.json.

Environment variables

VariableContents
GEO_DATA_DIRDataset directory — /geo/dataset
GEO_WORK_DIRWorkspace — /geo/work
GEO_CONFIGExperiment settings file — /geo/experiment.json
GEO_PARAM_EXPERIMENT_IDTraining run ID (experiment_id in experiment.json)
GEO_PARAM_EXPERIMENT_NAMEExperiment name (= MLflow experiment name)
GEO_PARAM_TASKTask (for example object_detection)
GEO_PARAM_FRAMEWORKFramework chosen in wizard step 2 (for example yolo)
GEO_PARAM_MODELModel variant (for example yolo26n)
GEO_PARAM_DATASET_IDDataset ID
GEO_PARAM_DEVICE0 or cpu. Inside the pod, GPUs are always numbered from 0
GEO_HP_<name>Hyperparameters chosen in the wizard (for example GEO_HP_EPOCHS=50, GEO_HP_LR=0.001)
GEO_RUNTIME_IMAGEAddress of the image that runs this training. It may be pinned to a digest
CUDA_VISIBLE_DEVICES0 when one or more GPUs are assigned, empty otherwise. Even with several slots, only GPU 0 is visible
MLFLOW_TRACKING_URIThe platform's MLflow address
MLFLOW_TRACKING_TOKENA token issued for each run and revoked when it ends. The MLflow client reads it by itself. Not set on deployments with MLflow authentication turned off
MLFLOW_EXPERIMENT_NAMEName of the experiment the platform created in advance — use this value as is
MLFLOW_RUN_IDThe run the platform created in advance. mlflow.start_run() attaches to this run
  • GEO_HP_* naming rule: hyperparameter keys must match ^[a-z][a-z0-9_]*$, and the environment variable name is that key converted to upper case as is (lr → GEO_HP_LR). Nested structures and lists cannot be expressed as environment variables, so they appear only in experiment.json.
  • All values are strings. Convert them to the type of the default value when you read them (see the hyperparameter() function in the example). Booleans arrive as lower-case true/false. In Python bool("false") is true, so compare the string directly.
  • Only keys present in the step 7 YAML of the wizard arrive. At submission the keys are checked against the allow list of the chosen framework, so a key the catalog does not have cannot be sent. If the YAML is submitted empty, no GEO_HP_* arrives at all, so keep a default in the image for every value.
  • What is not passed in: object storage addresses and keys. The platform fetches the data in advance, so no storage credentials reach the training container.
  • The platform does not set PYTHONUNBUFFERED. To see logs in real time, add ENV PYTHONUNBUFFERED=1 to your Dockerfile.

Resource limits

ItemDefaultWhen exceeded
MemoryTraining container limit of 64Gi (server setting GEO_MLOPS_TRAINING_RUNTIME_MEMORY_LIMIT). /dev/shm counts toward itThe pod ends with exit code 137 and the training fails
/dev/shm2Gi (server setting GEO_MLOPS_TRAINING_RUNTIME_SHM_SIZE)With many DataLoader workers or large batches it can run short. Ask the operator to raise it
GPUThe number of slots chosen in wizard step 10. 0 means CPUFor a GPU-only framework, 0 is rejected at submission

experiment.json (advanced)

All the main values also come as environment variables, so most images do not read this file. Read it only when you need the classes list, the split ratio or nested hyperparameters. The file contains no credentials, so it is safe to write it to the log.

{
  "experiment_id": "7abfb12e3a8d…",
  "name": "mnist-external-smoke-3",
  "tenant": "DEMO",
  "created_at": "2026-09-21T06:59:47Z",

  "task": "object_detection",
  "framework": "yolo",
  "model": "yolo26n",
  "classes": ["head", "helmet"],

  "split": { "method": "random", "train_percent": 80, "seed": 0 },
  "hyperparameters": { "epochs": 2 },

  "device": "cpu",
  "gpu": 0,

  "evaluation": { "benchmark": true, "speed_test": false },
  "export": { "onnx": false, "tensorrt": false },
  "serving": { "runtime": "cpu" },
  "register": { "enabled": false, "model_name": "" },
  "pretrained": { "source": "catalog" },

  "dataset": { "id": "ds-…", "name": "…", "file_count": 16,
               "path": "/geo/dataset", "manifest": "/geo/dataset/manifest.json",
               "pointcloud_labels": null },
  "paths": { "data_dir": "/geo/dataset", "work_dir": "/geo/work" },
  "mlflow": { "experiment_name": "mnist-external-smoke-3", "run_id": "…" }
}
GroupMeaning
experiment_id · name · tenant · created_atWhich run this is. name = MLflow experiment name
task · framework · model · classesWhat is being trained. classes contains only the classes chosen for this experiment
splitSplit instructions. The trainer does the split itself
hyperparametersThe parsed object with the same values as GEO_HP_*
device · gpuCompute resources
evaluation · export · servingRequests for after training. If you do not support them, ignore them
registerWhether to register, and the model name. The platform does the registration itself
pretrainedWhere the starting weights come from — Pretrained weights
dataset · paths · mlflowLocations and the run, for reference. dataset.pointcloud_labels tells which PLY property is the class and which is the instance ID (null without point clouds)

Written for the platform as of 2026-10-02.

© MLOps Central Platform