Skip to content

Commit cee1cb5

Browse files
authored
Merge pull request #135 from BitMind-AI/dev
Release experimental taxonomy, scoring, and download updates
2 parents 52b3b99 + acf5f5f commit cee1cb5

50 files changed

Lines changed: 3364 additions & 2277 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,11 @@ For model submission requirements, see the
2323
To learn how to submit your model to **Bittensor Subnet 34** — including the entrance exam, full benchmark, and scoring pipeline — see the
2424
👉 **[Discriminative Mining Guide](https://github.com/BitMind-AI/bitmind-subnet/blob/main/docs/Discriminative-Mining.md)**
2525

26-
> **Note**: ONNX format is no longer accepted for competition. See [ONNX.md](./docs/ONNX.md) for legacy reference.
27-
2826
---
2927

3028
## Installation
3129

32-
To run benchmarks, install the `gpu` extra (on macOS/Windows this
33-
automatically substitutes CPU onnxruntime via platform markers):
30+
To run benchmarks, install the `gpu` extra:
3431

3532
```bash
3633
cd gasbench
@@ -39,7 +36,7 @@ pip install -e '.[gpu]'
3936

4037
The base install is intentionally minimal — just the dataset registry
4138
(`gasbench.dataset.config` and the bundled YAML configs) with no
42-
torch/onnxruntime. Use it when you only need dataset definitions
39+
PyTorch. Use it when you only need dataset definitions
4340
(e.g. bitmind-subnet's validator cache):
4441

4542
```bash
@@ -116,8 +113,6 @@ results = asyncio.run(evaluate_model())
116113
For full submission requirements, see:
117114
👉 **[Safetensors Model Specification](./docs/Safetensors.md)** (required for competition)
118115

119-
> **Note**: ONNX format is no longer accepted. See [ONNX.md](./docs/ONNX.md) for legacy reference.
120-
121116
---
122117

123118
## Metrics

‎docs/ONNX.md‎

Lines changed: 0 additions & 164 deletions
This file was deleted.

‎docs/Safetensors.md‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
This document defines the requirements for **safetensors** format models used with GASBench on Subnet 34.
44

5-
> **Note:** ONNX format is no longer accepted for competition submissions. All new models must use safetensors format.
6-
75
---
86

97
## 1. Required Files
@@ -355,5 +353,3 @@ gascli d push --audio-model my_model.zip
355353
4. **Mismatched resize dimensions**: Ensure `preprocessing.resize` in config matches your model's expected input size.
356354

357355
5. **Mismatched frame count**: Ensure `preprocessing.num_frames` matches the temporal dimension your model expects. If `frame_rate` is set, frames are sampled at that fps from frame 0; otherwise the first `num_frames` consecutive frames are used.
358-
359-
5. **ONNX format**: ONNX is no longer accepted. Convert your model to safetensors format.

‎pyproject.toml‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "gasbench"
7-
version = "0.8.3"
7+
version = "0.9.0"
88
description = "GASBench - ML model benchmark evaluation package"
99
readme = "README.md"
1010
requires-python = ">=3.10"
@@ -22,9 +22,6 @@ gpu = [
2222
"numpy==2.4.2",
2323
"pillow==12.1.1",
2424
"opencv-python-headless==4.13.0.92",
25-
"onnxruntime-gpu==1.24.2; platform_system == 'Linux'",
26-
"onnxruntime>=1.22.0; platform_system == 'Darwin'",
27-
"onnxruntime>=1.22.0; platform_system == 'Windows'",
2825
"decord==0.6.0; platform_system != 'Darwin'",
2926
"scikit-learn==1.8.0",
3027
"torch==2.8.0",
@@ -91,5 +88,6 @@ follow_imports = "silent"
9188

9289
[tool.pytest.ini_options]
9390
testpaths = ["tests"]
91+
addopts = "-m 'not slow'"
9492
markers = ["slow: marks tests as slow (network I/O)"]
9593
filterwarnings = ["ignore::DeprecationWarning:pkg_resources.*"]

‎src/gasbench/__init__.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from gasbench import run_benchmark
1010
1111
results = await run_benchmark(
12-
model_path="path/to/model.onnx",
12+
model_path="path/to/model_directory",
1313
modality="image",
1414
mode="debug"
1515
)
@@ -35,7 +35,7 @@
3535

3636
# Benchmark exports resolve lazily (PEP 562) so that the base install —
3737
# which carries only the dataset registry and pyyaml — can import
38-
# gasbench.dataset.config without pulling in torch/onnxruntime. The full
38+
# gasbench.dataset.config without pulling in torch. The full
3939
# benchmark stack requires the `gpu` extra: pip install gasbench[gpu]
4040
_LAZY_EXPORTS = {
4141
"run_image_benchmark": ("gasbench.benchmarks.image_bench", "run_image_benchmark"),

‎src/gasbench/benchmark.py‎

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,15 @@ async def run_benchmark(
3636
holdouts_only: bool = False,
3737
content_category: Optional[str] = None,
3838
score_composition: Optional[Dict[str, float]] = None,
39+
multiclass_scoring: bool = False,
3940
n_aug_per_dataset: int = 0,
4041
aug_weight: float = 0.2,
4142
aug_cache_dir: Optional[str] = None,
4243
aug_cache_readonly: bool = False,
4344
) -> Dict:
4445
"""
4546
Args:
46-
model_path: Path to ONNX model file
47+
model_path: Path to a custom PyTorch model directory
4748
modality: Type of modality to test ("image" or "video")
4849
mode: Benchmark mode - "debug", "small", or "full" (default: "full")
4950
gasstation_only: If True, only use gasstation datasets
@@ -125,6 +126,7 @@ async def run_benchmark(
125126
holdouts_only,
126127
content_category,
127128
score_composition,
129+
multiclass_scoring,
128130
n_aug_per_dataset=n_aug_per_dataset,
129131
aug_weight=aug_weight,
130132
aug_cache_dir=aug_cache_dir,
@@ -162,7 +164,7 @@ async def run_benchmark(
162164
async def load_model_for_benchmark(
163165
model_path: str, modality: str, benchmark_results: Dict
164166
):
165-
"""Load and validate ONNX model for benchmarking."""
167+
"""Load and validate a model for benchmarking."""
166168

167169
if not os.path.exists(model_path):
168170
benchmark_results["errors"].append(f"Model file not found: {model_path}")
@@ -199,7 +201,7 @@ async def load_model_for_benchmark(
199201

200202
except Exception as e:
201203
logger.error(f"Failed to load model for inference: {e}")
202-
benchmark_results["errors"].append(f"ONNX runtime error: {str(e)}")
204+
benchmark_results["errors"].append(f"Model loading error: {str(e)}")
203205
benchmark_results["benchmark_completed"] = False
204206
return None, None
205207

@@ -225,14 +227,15 @@ async def execute_benchmark(
225227
holdouts_only: bool = False,
226228
content_category: Optional[str] = None,
227229
score_composition: Optional[Dict[str, float]] = None,
230+
multiclass_scoring: bool = False,
228231
n_aug_per_dataset: int = 0,
229232
aug_weight: float = 0.2,
230233
aug_cache_dir: Optional[str] = None,
231234
aug_cache_readonly: bool = False,
232235
) -> float:
233236
"""Execute the actual benchmark evaluation."""
234237

235-
logger.info(f"Running {modality} benchmark (mode={mode}, gasstation_only={gasstation_only}, download_latest_gasstation_data={download_latest_gasstation_data}, skip_missing={skip_missing}, holdout_weight={holdout_weight}, holdouts_only={holdouts_only}, content_category={content_category}, score_composition={score_composition})")
238+
logger.info(f"Running {modality} benchmark (mode={mode}, gasstation_only={gasstation_only}, download_latest_gasstation_data={download_latest_gasstation_data}, skip_missing={skip_missing}, holdout_weight={holdout_weight}, holdouts_only={holdouts_only}, content_category={content_category}, score_composition={score_composition}, multiclass_scoring={multiclass_scoring})")
236239
if dataset_filters:
237240
logger.info(f"Dataset filters: {dataset_filters}")
238241
if modality == "image":
@@ -256,6 +259,7 @@ async def execute_benchmark(
256259
holdouts_only=holdouts_only,
257260
content_category=content_category,
258261
score_composition=score_composition,
262+
multiclass_scoring=multiclass_scoring,
259263
n_aug_per_dataset=n_aug_per_dataset,
260264
aug_weight=aug_weight,
261265
aug_cache_dir=aug_cache_dir,
@@ -283,6 +287,7 @@ async def execute_benchmark(
283287
holdouts_only=holdouts_only,
284288
content_category=content_category,
285289
score_composition=score_composition,
290+
multiclass_scoring=multiclass_scoring,
286291
n_aug_per_dataset=n_aug_per_dataset,
287292
aug_weight=aug_weight,
288293
aug_cache_dir=aug_cache_dir,
@@ -310,6 +315,7 @@ async def execute_benchmark(
310315
holdouts_only=holdouts_only,
311316
content_category=content_category,
312317
score_composition=score_composition,
318+
multiclass_scoring=multiclass_scoring,
313319
)
314320
benchmark_score = benchmark_results.get("audio_results", {}).get("benchmark_score", 0.0)
315321
else:
@@ -506,6 +512,18 @@ def save_results_to_json(
506512
"aug_binary_mcc": results.get("aug_binary_mcc"),
507513
"aug_binary_ce": results.get("aug_binary_ce"),
508514
"aug_binary_brier": results.get("aug_binary_brier"),
515+
# Multiclass metrics are recorded on every run regardless of
516+
# which scheme sn34_score was derived from, so a round can be
517+
# compared under either. Keys must stay in sync with the dict
518+
# built in recording.compute_metrics_from_df.
519+
"num_classes": results.get("num_classes"),
520+
"multiclass_scoring": results.get("multiclass_scoring"),
521+
"gorodkin_mcc": results.get("gorodkin_mcc"),
522+
"multiclass_brier": results.get("multiclass_brier"),
523+
"binary_sn34_score": results.get("binary_sn34_score"),
524+
"multiclass_sn34_score": results.get("multiclass_sn34_score"),
525+
# int keys become strings through JSON; that is fine for a report.
526+
"per_class_recall": results.get("per_class_recall"),
509527
}
510528

511529
per_dataset = results.get("per_dataset_results", {})

‎src/gasbench/benchmarks/audio_bench.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ async def run_audio_benchmark(
8181
holdouts_only: bool = False,
8282
content_category: Optional[str] = None,
8383
score_composition: dict = None,
84+
multiclass_scoring: bool = False,
8485
) -> pd.DataFrame:
8586
"""Test model on benchmark audio datasets for AI-generated content detection.
8687
@@ -117,6 +118,7 @@ async def run_audio_benchmark(
117118
holdouts_only=holdouts_only,
118119
content_category=content_category,
119120
score_composition=score_composition,
121+
multiclass_scoring=multiclass_scoring,
120122
)
121123

122124
plan = build_plan(logger, run_config, input_specs)

0 commit comments

Comments
 (0)