opencode-skills-antigravity 1.0.39 → 1.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/bundled-skills/.antigravity-install-manifest.json +10 -1
  2. package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
  3. package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
  4. package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
  5. package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-29-refresh.csv +34 -0
  6. package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-29-refresh.md +2 -0
  7. package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
  8. package/bundled-skills/docs/sources/sources.md +2 -2
  9. package/bundled-skills/docs/users/bundles.md +1 -1
  10. package/bundled-skills/docs/users/claude-code-skills.md +1 -1
  11. package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
  12. package/bundled-skills/docs/users/getting-started.md +1 -1
  13. package/bundled-skills/docs/users/kiro-integration.md +1 -1
  14. package/bundled-skills/docs/users/usage.md +4 -4
  15. package/bundled-skills/docs/users/visual-guide.md +4 -4
  16. package/bundled-skills/hugging-face-cli/SKILL.md +192 -195
  17. package/bundled-skills/hugging-face-community-evals/SKILL.md +213 -0
  18. package/bundled-skills/hugging-face-community-evals/examples/.env.example +3 -0
  19. package/bundled-skills/hugging-face-community-evals/examples/USAGE_EXAMPLES.md +101 -0
  20. package/bundled-skills/hugging-face-community-evals/scripts/inspect_eval_uv.py +104 -0
  21. package/bundled-skills/hugging-face-community-evals/scripts/inspect_vllm_uv.py +306 -0
  22. package/bundled-skills/hugging-face-community-evals/scripts/lighteval_vllm_uv.py +297 -0
  23. package/bundled-skills/hugging-face-dataset-viewer/SKILL.md +120 -120
  24. package/bundled-skills/hugging-face-gradio/SKILL.md +304 -0
  25. package/bundled-skills/hugging-face-gradio/examples.md +613 -0
  26. package/bundled-skills/hugging-face-jobs/SKILL.md +25 -18
  27. package/bundled-skills/hugging-face-jobs/index.html +216 -0
  28. package/bundled-skills/hugging-face-jobs/references/hardware_guide.md +336 -0
  29. package/bundled-skills/hugging-face-jobs/references/hub_saving.md +352 -0
  30. package/bundled-skills/hugging-face-jobs/references/token_usage.md +570 -0
  31. package/bundled-skills/hugging-face-jobs/references/troubleshooting.md +475 -0
  32. package/bundled-skills/hugging-face-jobs/scripts/cot-self-instruct.py +718 -0
  33. package/bundled-skills/hugging-face-jobs/scripts/finepdfs-stats.py +546 -0
  34. package/bundled-skills/hugging-face-jobs/scripts/generate-responses.py +587 -0
  35. package/bundled-skills/hugging-face-model-trainer/SKILL.md +11 -12
  36. package/bundled-skills/hugging-face-model-trainer/references/gguf_conversion.md +296 -0
  37. package/bundled-skills/hugging-face-model-trainer/references/hardware_guide.md +283 -0
  38. package/bundled-skills/hugging-face-model-trainer/references/hub_saving.md +364 -0
  39. package/bundled-skills/hugging-face-model-trainer/references/local_training_macos.md +231 -0
  40. package/bundled-skills/hugging-face-model-trainer/references/reliability_principles.md +371 -0
  41. package/bundled-skills/hugging-face-model-trainer/references/trackio_guide.md +189 -0
  42. package/bundled-skills/hugging-face-model-trainer/references/training_methods.md +150 -0
  43. package/bundled-skills/hugging-face-model-trainer/references/training_patterns.md +203 -0
  44. package/bundled-skills/hugging-face-model-trainer/references/troubleshooting.md +282 -0
  45. package/bundled-skills/hugging-face-model-trainer/references/unsloth.md +313 -0
  46. package/bundled-skills/hugging-face-model-trainer/scripts/convert_to_gguf.py +424 -0
  47. package/bundled-skills/hugging-face-model-trainer/scripts/dataset_inspector.py +417 -0
  48. package/bundled-skills/hugging-face-model-trainer/scripts/estimate_cost.py +150 -0
  49. package/bundled-skills/hugging-face-model-trainer/scripts/train_dpo_example.py +106 -0
  50. package/bundled-skills/hugging-face-model-trainer/scripts/train_grpo_example.py +89 -0
  51. package/bundled-skills/hugging-face-model-trainer/scripts/train_sft_example.py +122 -0
  52. package/bundled-skills/hugging-face-model-trainer/scripts/unsloth_sft_example.py +512 -0
  53. package/bundled-skills/hugging-face-paper-publisher/SKILL.md +11 -4
  54. package/bundled-skills/hugging-face-paper-publisher/examples/example_usage.md +326 -0
  55. package/bundled-skills/hugging-face-paper-publisher/references/quick_reference.md +216 -0
  56. package/bundled-skills/hugging-face-paper-publisher/scripts/paper_manager.py +606 -0
  57. package/bundled-skills/hugging-face-paper-publisher/templates/arxiv.md +299 -0
  58. package/bundled-skills/hugging-face-paper-publisher/templates/ml-report.md +358 -0
  59. package/bundled-skills/hugging-face-paper-publisher/templates/modern.md +319 -0
  60. package/bundled-skills/hugging-face-paper-publisher/templates/standard.md +201 -0
  61. package/bundled-skills/hugging-face-papers/SKILL.md +241 -0
  62. package/bundled-skills/hugging-face-trackio/.claude-plugin/plugin.json +19 -0
  63. package/bundled-skills/hugging-face-trackio/SKILL.md +117 -0
  64. package/bundled-skills/hugging-face-trackio/references/alerts.md +196 -0
  65. package/bundled-skills/hugging-face-trackio/references/logging_metrics.md +206 -0
  66. package/bundled-skills/hugging-face-trackio/references/retrieving_metrics.md +251 -0
  67. package/bundled-skills/hugging-face-vision-trainer/SKILL.md +595 -0
  68. package/bundled-skills/hugging-face-vision-trainer/references/finetune_sam2_trainer.md +254 -0
  69. package/bundled-skills/hugging-face-vision-trainer/references/hub_saving.md +618 -0
  70. package/bundled-skills/hugging-face-vision-trainer/references/image_classification_training_notebook.md +279 -0
  71. package/bundled-skills/hugging-face-vision-trainer/references/object_detection_training_notebook.md +700 -0
  72. package/bundled-skills/hugging-face-vision-trainer/references/reliability_principles.md +310 -0
  73. package/bundled-skills/hugging-face-vision-trainer/references/timm_trainer.md +91 -0
  74. package/bundled-skills/hugging-face-vision-trainer/scripts/dataset_inspector.py +814 -0
  75. package/bundled-skills/hugging-face-vision-trainer/scripts/estimate_cost.py +217 -0
  76. package/bundled-skills/hugging-face-vision-trainer/scripts/image_classification_training.py +383 -0
  77. package/bundled-skills/hugging-face-vision-trainer/scripts/object_detection_training.py +710 -0
  78. package/bundled-skills/hugging-face-vision-trainer/scripts/sam_segmentation_training.py +382 -0
  79. package/bundled-skills/jq/SKILL.md +273 -0
  80. package/bundled-skills/odoo-edi-connector/SKILL.md +32 -10
  81. package/bundled-skills/odoo-woocommerce-bridge/SKILL.md +9 -5
  82. package/bundled-skills/tmux/SKILL.md +370 -0
  83. package/bundled-skills/transformers-js/SKILL.md +639 -0
  84. package/bundled-skills/transformers-js/references/CACHE.md +339 -0
  85. package/bundled-skills/transformers-js/references/CONFIGURATION.md +390 -0
  86. package/bundled-skills/transformers-js/references/EXAMPLES.md +605 -0
  87. package/bundled-skills/transformers-js/references/MODEL_ARCHITECTURES.md +167 -0
  88. package/bundled-skills/transformers-js/references/PIPELINE_OPTIONS.md +545 -0
  89. package/bundled-skills/transformers-js/references/TEXT_GENERATION.md +315 -0
  90. package/bundled-skills/viboscope/SKILL.md +64 -0
  91. package/package.json +1 -1
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env python3
2
+ # /// script
3
+ # requires-python = ">=3.10"
4
+ # dependencies = []
5
+ # ///
6
+ """
7
+ Estimate training time and cost for vision model training jobs on Hugging Face Jobs.
8
+
9
+ Usage:
10
+ uv run estimate_cost.py --model ustc-community/dfine-small-coco --dataset cppe-5 --hardware t4-small
11
+ uv run estimate_cost.py --model PekingU/rtdetr_v2_r50vd --dataset-size 5000 --hardware t4-small --epochs 30
12
+ uv run estimate_cost.py --model google/vit-base-patch16-224-in21k --dataset ethz/food101 --hardware t4-small --epochs 3
13
+ """
14
+
15
+ import argparse
16
+
17
+ HARDWARE_COSTS = {
18
+ "t4-small": 0.40,
19
+ "t4-medium": 0.60,
20
+ "l4x1": 0.80,
21
+ "l4x4": 3.80,
22
+ "a10g-small": 1.00,
23
+ "a10g-large": 1.50,
24
+ "a10g-largex2": 3.00,
25
+ "a10g-largex4": 5.00,
26
+ "l40sx1": 1.80,
27
+ "l40sx4": 8.30,
28
+ "a100-large": 2.50,
29
+ "a100x4": 10.00,
30
+ }
31
+
32
+ # Vision model sizes in millions of parameters
33
+ MODEL_PARAMS_M = {
34
+ # Object detection
35
+ "dfine-small": 10.4,
36
+ "dfine-large": 31.4,
37
+ "dfine-xlarge": 63.5,
38
+ "rtdetr_v2_r18vd": 20.2,
39
+ "rtdetr_v2_r50vd": 43.0,
40
+ "rtdetr_v2_r101vd": 76.0,
41
+ "detr-resnet-50": 41.3,
42
+ "detr-resnet-101": 60.2,
43
+ "yolos-small": 30.7,
44
+ "yolos-tiny": 6.5,
45
+ # Image classification
46
+ "mobilenetv3_small": 2.5,
47
+ "mobilevit_s": 5.6,
48
+ "resnet50": 25.6,
49
+ "vit_base_patch16": 86.6,
50
+ # SAM / SAM2 segmentation
51
+ "sam-vit-base": 93.7,
52
+ "sam-vit-large": 312.3,
53
+ "sam-vit-huge": 641.1,
54
+ "sam2.1-hiera-tiny": 38.9,
55
+ "sam2.1-hiera-small": 46.0,
56
+ "sam2.1-hiera-base-plus": 80.8,
57
+ "sam2.1-hiera-large": 224.4,
58
+ }
59
+
60
+ KNOWN_DATASETS = {
61
+ # Object detection
62
+ "cppe-5": 1000,
63
+ "merve/license-plate": 6180,
64
+ # Image classification
65
+ "ethz/food101": 75750,
66
+ # SAM segmentation
67
+ "merve/MicroMat-mini": 240,
68
+ }
69
+
70
+
71
+ def extract_model_params(model_name: str) -> float:
72
+ """Extract model size in millions of parameters from the model name."""
73
+ name_lower = model_name.lower()
74
+ for key, params in MODEL_PARAMS_M.items():
75
+ if key.lower() in name_lower:
76
+ return params
77
+ return 30.0 # reasonable default for vision models
78
+
79
+
80
+ def estimate_training_time(model_params_m: float, dataset_size: int, epochs: int,
81
+ image_size: int, batch_size: int, hardware: str) -> float:
82
+ """Estimate training time in hours for vision model training."""
83
+ # Steps per epoch
84
+ steps_per_epoch = dataset_size / batch_size
85
+ # empirical calibration values
86
+ base_secs_per_step = 0.8
87
+ model_factor = (model_params_m / 30.0) ** 0.6
88
+ image_factor = (image_size / 640.0) ** 2
89
+
90
+
91
+ batch_factor = (batch_size / 8.0) ** 0.7
92
+
93
+ secs_per_step = base_secs_per_step * model_factor * image_factor * batch_factor
94
+
95
+ hardware_multipliers = {
96
+ "t4-small": 2.0,
97
+ "t4-medium": 2.0,
98
+ "l4x1": 1.2,
99
+ "l4x4": 0.5,
100
+ "a10g-small": 1.0,
101
+ "a10g-large": 1.0,
102
+ "a10g-largex2": 0.6,
103
+ "a10g-largex4": 0.4,
104
+ "l40sx1": 0.7,
105
+ "l40sx4": 0.25,
106
+ "a100-large": 0.5,
107
+ "a100x4": 0.2,
108
+ }
109
+
110
+ multiplier = hardware_multipliers.get(hardware, 1.0)
111
+ total_steps = steps_per_epoch * epochs
112
+ total_secs = total_steps * secs_per_step * multiplier
113
+
114
+ # Add overhead: model loading (~2 min), eval per epoch (~10% of training), Hub push (~3 min)
115
+ eval_overhead = total_secs * 0.10
116
+ fixed_overhead = 5 * 60 # 5 minutes
117
+ total_secs += eval_overhead + fixed_overhead
118
+
119
+ return total_secs / 3600
120
+
121
+
122
+ def parse_args():
123
+ parser = argparse.ArgumentParser(description="Estimate training cost for vision model training jobs")
124
+ parser.add_argument("--model", required=True,
125
+ help="Model name (e.g., 'ustc-community/dfine-small-coco' or 'detr-resnet-50')")
126
+ parser.add_argument("--dataset", default=None, help="Dataset name (for known size lookup)")
127
+ parser.add_argument("--hardware", required=True, choices=HARDWARE_COSTS.keys(), help="Hardware flavor")
128
+ parser.add_argument("--dataset-size", type=int, default=None,
129
+ help="Number of training images (overrides dataset lookup)")
130
+ parser.add_argument("--epochs", type=int, default=30, help="Number of training epochs (default: 30)")
131
+ parser.add_argument("--image-size", type=int, default=640, help="Image square size in pixels (default: 640)")
132
+ parser.add_argument("--batch-size", type=int, default=8, help="Per-device batch size (default: 8)")
133
+ return parser.parse_args()
134
+
135
+
136
+ def main():
137
+ args = parse_args()
138
+
139
+ model_params = extract_model_params(args.model)
140
+ print(f"Model: {args.model} (~{model_params:.1f}M parameters)")
141
+
142
+ if args.dataset_size:
143
+ dataset_size = args.dataset_size
144
+ elif args.dataset and args.dataset in KNOWN_DATASETS:
145
+ dataset_size = KNOWN_DATASETS[args.dataset]
146
+ elif args.dataset:
147
+ print(f"Unknown dataset '{args.dataset}', defaulting to 1000 images.")
148
+ print(f"Use --dataset-size to specify the exact count.")
149
+ dataset_size = 1000
150
+ else:
151
+ dataset_size = 1000
152
+
153
+ print(f"Dataset: {args.dataset or 'custom'} (~{dataset_size} images)")
154
+ print(f"Epochs: {args.epochs}")
155
+ print(f"Image size: {args.image_size}px")
156
+ print(f"Batch size: {args.batch_size}")
157
+ print(f"Hardware: {args.hardware} (${HARDWARE_COSTS[args.hardware]:.2f}/hr)")
158
+ print()
159
+
160
+ estimated_hours = estimate_training_time(
161
+ model_params, dataset_size, args.epochs, args.image_size, args.batch_size, args.hardware
162
+ )
163
+ estimated_cost = estimated_hours * HARDWARE_COSTS[args.hardware]
164
+ recommended_timeout = estimated_hours * 1.3 # 30% buffer
165
+
166
+ print(f"Estimated training time: {estimated_hours:.1f} hours")
167
+ print(f"Estimated cost: ${estimated_cost:.2f}")
168
+ print(f"Recommended timeout: {recommended_timeout:.1f}h (with 30% buffer)")
169
+ print()
170
+
171
+ if estimated_hours > 6:
172
+ print("Warning: Long training time. Consider:")
173
+ print(" - Reducing epochs or image size")
174
+ print(" - Using --max_train_samples for a test run first")
175
+ print(" - Upgrading hardware")
176
+ print()
177
+
178
+ if model_params > 50 and args.hardware in ("t4-small", "t4-medium"):
179
+ print("Warning: Large model on T4. If you hit OOM:")
180
+ print(" - Reduce batch size (try 4, then 2)")
181
+ print(" - Reduce image size (try 480)")
182
+ print(" - Upgrade to l4x1 or a10g-small")
183
+ print()
184
+
185
+ timeout_str = f"{recommended_timeout:.0f}h"
186
+ timeout_secs = int(recommended_timeout * 3600)
187
+ print(f"Example job configuration (MCP tool):")
188
+ print(f"""
189
+ hf_jobs("uv", {{
190
+ "script": "scripts/object_detection_training.py",
191
+ "script_args": [
192
+ "--model_name_or_path", "{args.model}",
193
+ "--dataset_name", "{args.dataset or 'your-dataset'}",
194
+ "--image_square_size", "{args.image_size}",
195
+ "--num_train_epochs", "{args.epochs}",
196
+ "--per_device_train_batch_size", "{args.batch_size}",
197
+ "--push_to_hub", "--do_train", "--do_eval"
198
+ ],
199
+ "flavor": "{args.hardware}",
200
+ "timeout": "{timeout_str}",
201
+ "secrets": {{"HF_TOKEN": "$HF_TOKEN"}}
202
+ }})
203
+ """)
204
+ print(f"Example job configuration (Python API):")
205
+ print(f"""
206
+ api.run_uv_job(
207
+ script="scripts/object_detection_training.py",
208
+ script_args=[...],
209
+ flavor="{args.hardware}",
210
+ timeout={timeout_secs},
211
+ secrets={{"HF_TOKEN": get_token()}},
212
+ )
213
+ """)
214
+
215
+
216
+ if __name__ == "__main__":
217
+ main()
@@ -0,0 +1,383 @@
1
+ # /// script
2
+ # dependencies = [
3
+ # "transformers>=5.2.0",
4
+ # "accelerate>=1.1.0",
5
+ # "timm",
6
+ # "datasets>=4.0",
7
+ # "evaluate",
8
+ # "scikit-learn",
9
+ # "torchvision",
10
+ # "trackio",
11
+ # "huggingface_hub",
12
+ # ]
13
+ # ///
14
+
15
+ """Fine-tuning any Transformers or timm model supported by AutoModelForImageClassification using the Trainer API."""
16
+
17
+ import logging
18
+ import os
19
+ import sys
20
+ from dataclasses import dataclass, field
21
+ from functools import partial
22
+ from typing import Any
23
+
24
+ import evaluate
25
+ import numpy as np
26
+ import torch
27
+ from datasets import load_dataset
28
+ from torchvision.transforms import (
29
+ CenterCrop,
30
+ Compose,
31
+ Normalize,
32
+ RandomHorizontalFlip,
33
+ RandomResizedCrop,
34
+ Resize,
35
+ ToTensor,
36
+ )
37
+
38
+ import trackio
39
+
40
+ import transformers
41
+ from transformers import (
42
+ AutoConfig,
43
+ AutoImageProcessor,
44
+ AutoModelForImageClassification,
45
+ DefaultDataCollator,
46
+ HfArgumentParser,
47
+ Trainer,
48
+ TrainingArguments,
49
+ )
50
+ from transformers.trainer import EvalPrediction
51
+ from transformers.utils import check_min_version
52
+ from transformers.utils.versions import require_version
53
+
54
+
55
+ logger = logging.getLogger(__name__)
56
+
57
+ check_min_version("4.57.0.dev0")
58
+ require_version("datasets>=2.0.0")
59
+
60
+
61
+ @dataclass
62
+ class DataTrainingArguments:
63
+ dataset_name: str = field(
64
+ default="ethz/food101",
65
+ metadata={"help": "Name of a dataset from the Hub."},
66
+ )
67
+ dataset_config_name: str | None = field(
68
+ default=None,
69
+ metadata={"help": "The configuration name of the dataset to use (via the datasets library)."},
70
+ )
71
+ train_val_split: float | None = field(
72
+ default=0.15,
73
+ metadata={"help": "Fraction to split off of train for validation (used only when no validation split exists)."},
74
+ )
75
+ max_train_samples: int | None = field(
76
+ default=None,
77
+ metadata={"help": "Truncate training set to this many samples (for debugging / quick tests)."},
78
+ )
79
+ max_eval_samples: int | None = field(
80
+ default=None,
81
+ metadata={"help": "Truncate evaluation set to this many samples."},
82
+ )
83
+ image_column_name: str = field(
84
+ default="image",
85
+ metadata={"help": "The column name for images in the dataset."},
86
+ )
87
+ label_column_name: str = field(
88
+ default="label",
89
+ metadata={"help": "The column name for labels in the dataset."},
90
+ )
91
+
92
+
93
+ @dataclass
94
+ class ModelArguments:
95
+ model_name_or_path: str = field(
96
+ default="timm/mobilenetv3_small_100.lamb_in1k",
97
+ metadata={"help": "Path to pretrained model or model identifier from huggingface.co/models."},
98
+ )
99
+ config_name: str | None = field(
100
+ default=None,
101
+ metadata={"help": "Pretrained config name or path if not the same as model_name."},
102
+ )
103
+ cache_dir: str | None = field(
104
+ default=None,
105
+ metadata={"help": "Where to store pretrained models downloaded from the Hub."},
106
+ )
107
+ model_revision: str = field(
108
+ default="main",
109
+ metadata={"help": "The specific model version to use (branch, tag, or commit id)."},
110
+ )
111
+ image_processor_name: str | None = field(
112
+ default=None,
113
+ metadata={"help": "Name or path of image processor config."},
114
+ )
115
+ ignore_mismatched_sizes: bool = field(
116
+ default=True,
117
+ metadata={"help": "Allow loading weights when num_labels differs from pretrained checkpoint."},
118
+ )
119
+ token: str | None = field(
120
+ default=None,
121
+ metadata={"help": "Auth token for private models / datasets."},
122
+ )
123
+ trust_remote_code: bool = field(
124
+ default=False,
125
+ metadata={"help": "Whether to trust remote code from Hub repos."},
126
+ )
127
+
128
+
129
+ def build_transforms(image_processor, is_training: bool):
130
+ """Build torchvision transforms from the image processor's config."""
131
+ if hasattr(image_processor, "size"):
132
+ size = image_processor.size
133
+ if "shortest_edge" in size:
134
+ img_size = size["shortest_edge"]
135
+ elif "height" in size and "width" in size:
136
+ img_size = (size["height"], size["width"])
137
+ else:
138
+ img_size = 224
139
+ else:
140
+ img_size = 224
141
+
142
+ if hasattr(image_processor, "image_mean") and image_processor.image_mean:
143
+ normalize = Normalize(mean=image_processor.image_mean, std=image_processor.image_std)
144
+ else:
145
+ normalize = Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
146
+
147
+ if is_training:
148
+ return Compose([
149
+ RandomResizedCrop(img_size),
150
+ RandomHorizontalFlip(),
151
+ ToTensor(),
152
+ normalize,
153
+ ])
154
+ else:
155
+ if isinstance(img_size, int):
156
+ resize_size = int(img_size / 0.875) # standard 87.5% center crop ratio
157
+ else:
158
+ resize_size = tuple(int(s / 0.875) for s in img_size)
159
+ return Compose([
160
+ Resize(resize_size),
161
+ CenterCrop(img_size),
162
+ ToTensor(),
163
+ normalize,
164
+ ])
165
+
166
+
167
+ def main():
168
+ parser = HfArgumentParser((ModelArguments, DataTrainingArguments, TrainingArguments))
169
+ if len(sys.argv) == 2 and sys.argv[1].endswith(".json"):
170
+ model_args, data_args, training_args = parser.parse_json_file(json_file=os.path.abspath(sys.argv[1]))
171
+ else:
172
+ model_args, data_args, training_args = parser.parse_args_into_dataclasses()
173
+
174
+ # --- Hub authentication ---
175
+ from huggingface_hub import login
176
+ hf_token = os.environ.get("HF_TOKEN") or os.environ.get("hfjob")
177
+ if hf_token:
178
+ login(token=hf_token)
179
+ training_args.hub_token = hf_token
180
+ logger.info("Logged in to Hugging Face Hub")
181
+ elif training_args.push_to_hub:
182
+ logger.warning("HF_TOKEN not found in environment. Hub push will likely fail.")
183
+
184
+ # --- Trackio ---
185
+ trackio.init(project=training_args.output_dir, name=training_args.run_name)
186
+
187
+ # --- Logging ---
188
+ logging.basicConfig(
189
+ format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
190
+ datefmt="%m/%d/%Y %H:%M:%S",
191
+ handlers=[logging.StreamHandler(sys.stdout)],
192
+ )
193
+ if training_args.should_log:
194
+ transformers.utils.logging.set_verbosity_info()
195
+
196
+ log_level = training_args.get_process_log_level()
197
+ logger.setLevel(log_level)
198
+ transformers.utils.logging.set_verbosity(log_level)
199
+ transformers.utils.logging.enable_default_handler()
200
+ transformers.utils.logging.enable_explicit_format()
201
+
202
+ logger.warning(
203
+ f"Process rank: {training_args.local_process_index}, device: {training_args.device}, "
204
+ f"n_gpu: {training_args.n_gpu}, distributed training: "
205
+ f"{training_args.parallel_mode.value == 'distributed'}, 16-bits training: {training_args.fp16}"
206
+ )
207
+ logger.info(f"Training/evaluation parameters {training_args}")
208
+
209
+ # --- Load dataset ---
210
+ dataset = load_dataset(
211
+ data_args.dataset_name,
212
+ data_args.dataset_config_name,
213
+ cache_dir=model_args.cache_dir,
214
+ trust_remote_code=model_args.trust_remote_code,
215
+ )
216
+
217
+ # --- Resolve label column ---
218
+ label_col = data_args.label_column_name
219
+ if label_col not in dataset["train"].column_names:
220
+ candidates = [c for c in dataset["train"].column_names if c in ("label", "labels", "class", "fine_label")]
221
+ if candidates:
222
+ label_col = candidates[0]
223
+ logger.info(f"Label column '{data_args.label_column_name}' not found, using '{label_col}'")
224
+ else:
225
+ raise ValueError(
226
+ f"Label column '{data_args.label_column_name}' not found. "
227
+ f"Available columns: {dataset['train'].column_names}"
228
+ )
229
+
230
+ # --- Discover labels ---
231
+ label_feature = dataset["train"].features[label_col]
232
+ if hasattr(label_feature, "names"):
233
+ label_names = label_feature.names
234
+ else:
235
+ unique_labels = sorted(set(dataset["train"][label_col]))
236
+ if all(isinstance(l, str) for l in unique_labels):
237
+ label_names = unique_labels
238
+ else:
239
+ label_names = [str(l) for l in unique_labels]
240
+
241
+ num_labels = len(label_names)
242
+ id2label = dict(enumerate(label_names))
243
+ label2id = {v: k for k, v in id2label.items()}
244
+ logger.info(f"Number of classes: {num_labels}")
245
+
246
+ # --- Remap string labels to int if needed ---
247
+ sample_label = dataset["train"][0][label_col]
248
+ if isinstance(sample_label, str):
249
+ logger.info("Remapping string labels to integer IDs")
250
+ for split_name in list(dataset.keys()):
251
+ dataset[split_name] = dataset[split_name].map(
252
+ lambda ex: {label_col: label2id[ex[label_col]]},
253
+ )
254
+
255
+ # --- Shuffle + Train/val split ---
256
+ dataset["train"] = dataset["train"].shuffle(seed=training_args.seed)
257
+
258
+ data_args.train_val_split = None if "validation" in dataset else data_args.train_val_split
259
+ if isinstance(data_args.train_val_split, float) and data_args.train_val_split > 0.0:
260
+ split = dataset["train"].train_test_split(data_args.train_val_split, seed=training_args.seed)
261
+ dataset["train"] = split["train"]
262
+ dataset["validation"] = split["test"]
263
+
264
+ # --- Truncate ---
265
+ if data_args.max_train_samples is not None:
266
+ max_train = min(data_args.max_train_samples, len(dataset["train"]))
267
+ dataset["train"] = dataset["train"].select(range(max_train))
268
+ logger.info(f"Truncated training set to {max_train} samples")
269
+ if data_args.max_eval_samples is not None and "validation" in dataset:
270
+ max_eval = min(data_args.max_eval_samples, len(dataset["validation"]))
271
+ dataset["validation"] = dataset["validation"].select(range(max_eval))
272
+ logger.info(f"Truncated validation set to {max_eval} samples")
273
+
274
+ # --- Load model & image processor ---
275
+ common_pretrained_args = {
276
+ "cache_dir": model_args.cache_dir,
277
+ "revision": model_args.model_revision,
278
+ "token": model_args.token,
279
+ "trust_remote_code": model_args.trust_remote_code,
280
+ }
281
+
282
+ config = AutoConfig.from_pretrained(
283
+ model_args.config_name or model_args.model_name_or_path,
284
+ num_labels=num_labels,
285
+ label2id=label2id,
286
+ id2label=id2label,
287
+ **common_pretrained_args,
288
+ )
289
+
290
+ model = AutoModelForImageClassification.from_pretrained(
291
+ model_args.model_name_or_path,
292
+ config=config,
293
+ ignore_mismatched_sizes=model_args.ignore_mismatched_sizes,
294
+ **common_pretrained_args,
295
+ )
296
+
297
+ image_processor = AutoImageProcessor.from_pretrained(
298
+ model_args.image_processor_name or model_args.model_name_or_path,
299
+ **common_pretrained_args,
300
+ )
301
+
302
+ # --- Build transforms ---
303
+ train_transforms = build_transforms(image_processor, is_training=True)
304
+ val_transforms = build_transforms(image_processor, is_training=False)
305
+
306
+ image_col = data_args.image_column_name
307
+
308
+ def preprocess_train(examples):
309
+ return {
310
+ "pixel_values": [train_transforms(img.convert("RGB")) for img in examples[image_col]],
311
+ "labels": examples[label_col],
312
+ }
313
+
314
+ def preprocess_val(examples):
315
+ return {
316
+ "pixel_values": [val_transforms(img.convert("RGB")) for img in examples[image_col]],
317
+ "labels": examples[label_col],
318
+ }
319
+
320
+ dataset["train"].set_transform(preprocess_train)
321
+ if "validation" in dataset:
322
+ dataset["validation"].set_transform(preprocess_val)
323
+ if "test" in dataset:
324
+ dataset["test"].set_transform(preprocess_val)
325
+
326
+ # --- Metrics ---
327
+ accuracy_metric = evaluate.load("accuracy")
328
+
329
+ def compute_metrics(eval_pred: EvalPrediction):
330
+ predictions = np.argmax(eval_pred.predictions, axis=1)
331
+ return accuracy_metric.compute(predictions=predictions, references=eval_pred.label_ids)
332
+
333
+ # --- Trainer ---
334
+ eval_dataset = None
335
+ if training_args.do_eval:
336
+ if "validation" in dataset:
337
+ eval_dataset = dataset["validation"]
338
+ elif "test" in dataset:
339
+ eval_dataset = dataset["test"]
340
+
341
+ trainer = Trainer(
342
+ model=model,
343
+ args=training_args,
344
+ train_dataset=dataset["train"] if training_args.do_train else None,
345
+ eval_dataset=eval_dataset,
346
+ processing_class=image_processor,
347
+ data_collator=DefaultDataCollator(),
348
+ compute_metrics=compute_metrics,
349
+ )
350
+
351
+ # --- Train ---
352
+ if training_args.do_train:
353
+ train_result = trainer.train(resume_from_checkpoint=training_args.resume_from_checkpoint)
354
+ trainer.save_model()
355
+ trainer.log_metrics("train", train_result.metrics)
356
+ trainer.save_metrics("train", train_result.metrics)
357
+ trainer.save_state()
358
+
359
+ # --- Evaluate ---
360
+ if training_args.do_eval:
361
+ test_dataset = dataset.get("test", dataset.get("validation"))
362
+ test_prefix = "test" if "test" in dataset else "eval"
363
+ if test_dataset is not None:
364
+ metrics = trainer.evaluate(eval_dataset=test_dataset, metric_key_prefix=test_prefix)
365
+ trainer.log_metrics(test_prefix, metrics)
366
+ trainer.save_metrics(test_prefix, metrics)
367
+
368
+ trackio.finish()
369
+
370
+ # --- Push to Hub ---
371
+ kwargs = {
372
+ "finetuned_from": model_args.model_name_or_path,
373
+ "dataset": data_args.dataset_name,
374
+ "tags": ["image-classification", "vision"],
375
+ }
376
+ if training_args.push_to_hub:
377
+ trainer.push_to_hub(**kwargs)
378
+ else:
379
+ trainer.create_model_card(**kwargs)
380
+
381
+
382
+ if __name__ == "__main__":
383
+ main()