Spaces:
Running
Running
File size: 8,733 Bytes
be9aa9f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
#!/usr/bin/env python3
"""
Generate unified model card from template
Handles template variables and conditional sections for quantized models
"""
import os
import re
import argparse
import logging
from pathlib import Path
from typing import Dict, Any, Optional
from datetime import datetime
logger = logging.getLogger(__name__)
class ModelCardGenerator:
"""Generate unified model cards from templates"""
def __init__(self, template_path: str = "templates/model_card.md"):
self.template_path = Path(template_path)
if not self.template_path.exists():
raise FileNotFoundError(f"Template not found: {self.template_path}")
def load_template(self) -> str:
"""Load the model card template"""
with open(self.template_path, 'r', encoding='utf-8') as f:
return f.read()
def process_conditionals(self, content: str, variables: Dict[str, Any]) -> str:
"""Process conditional sections in the template"""
# Handle {{#if variable}}...{{/if}} blocks
pattern = r'\{\{#if\s+(\w+)\}\}(.*?)\{\{/if\}\}'
def replace_conditional(match):
variable_name = match.group(1)
conditional_content = match.group(2)
# Check if variable exists and is truthy
if variable_name in variables and variables[variable_name]:
return conditional_content
else:
return ""
return re.sub(pattern, replace_conditional, content, flags=re.DOTALL)
def replace_variables(self, content: str, variables: Dict[str, Any]) -> str:
"""Replace template variables with actual values"""
for key, value in variables.items():
placeholder = f"{{{{{key}}}}}"
content = content.replace(placeholder, str(value))
return content
def generate_model_card(self, variables: Dict[str, Any]) -> str:
"""Generate the complete model card"""
# Load template
content = self.load_template()
# Process conditionals first
content = self.process_conditionals(content, variables)
# Replace variables
content = self.replace_variables(content, variables)
return content
def save_model_card(self, content: str, output_path: str) -> bool:
"""Save the generated model card"""
try:
output_file = Path(output_path)
output_file.parent.mkdir(parents=True, exist_ok=True)
with open(output_file, 'w', encoding='utf-8') as f:
f.write(content)
logger.info(f"β
Model card saved to: {output_file}")
return True
except Exception as e:
logger.error(f"β Failed to save model card: {e}")
return False
def create_default_variables() -> Dict[str, Any]:
"""Create default variables for the model card"""
return {
"model_name": "SmolLM3 Fine-tuned Model",
"model_description": "A fine-tuned version of SmolLM3-3B for improved text generation and conversation capabilities.",
"repo_name": "your-username/model-name",
"base_model": "HuggingFaceTB/SmolLM3-3B",
"dataset_name": "OpenHermes-FR",
"training_config_type": "Custom Configuration",
"trainer_type": "SFTTrainer",
"batch_size": "8",
"gradient_accumulation_steps": "16",
"learning_rate": "5e-6",
"max_epochs": "3",
"max_seq_length": "2048",
"hardware_info": "GPU (H100/A100)",
"experiment_name": "smollm3-experiment",
"trackio_url": "https://trackio.space/experiment",
"dataset_repo": "tonic/trackio-experiments",
"dataset_size": "~80K samples",
"dataset_format": "Chat format",
"author_name": "Your Name",
"model_name_slug": "smollm3-fine-tuned",
"quantized_models": False,
"dataset_sample_size": None,
"training_loss": "N/A",
"validation_loss": "N/A",
"perplexity": "N/A"
}
def parse_args():
"""Parse command line arguments"""
parser = argparse.ArgumentParser(description="Generate unified model card")
parser.add_argument("--template", default="templates/model_card.md",
help="Path to model card template")
parser.add_argument("--output", default="README.md",
help="Output path for generated model card")
parser.add_argument("--repo-name", required=True,
help="Hugging Face repository name")
parser.add_argument("--model-name", help="Model name")
parser.add_argument("--experiment-name", help="Experiment name")
parser.add_argument("--dataset-name", help="Dataset name")
parser.add_argument("--training-config", help="Training configuration type")
parser.add_argument("--trainer-type", help="Trainer type")
parser.add_argument("--batch-size", help="Batch size")
parser.add_argument("--learning-rate", help="Learning rate")
parser.add_argument("--max-epochs", help="Maximum epochs")
parser.add_argument("--max-seq-length", help="Maximum sequence length")
parser.add_argument("--hardware-info", help="Hardware information")
parser.add_argument("--trackio-url", help="Trackio URL")
parser.add_argument("--dataset-repo", help="Dataset repository")
parser.add_argument("--author-name", help="Author name")
parser.add_argument("--quantized-models", action="store_true",
help="Include quantized models")
parser.add_argument("--dataset-sample-size", help="Dataset sample size")
parser.add_argument("--training-loss", help="Training loss value")
parser.add_argument("--validation-loss", help="Validation loss value")
parser.add_argument("--perplexity", help="Perplexity value")
return parser.parse_args()
def main():
"""Main function"""
args = parse_args()
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
try:
# Create generator
generator = ModelCardGenerator(args.template)
# Create variables dictionary
variables = create_default_variables()
# Override with command line arguments
if args.repo_name:
variables["repo_name"] = args.repo_name
if args.model_name:
variables["model_name"] = args.model_name
if args.experiment_name:
variables["experiment_name"] = args.experiment_name
if args.dataset_name:
variables["dataset_name"] = args.dataset_name
if args.training_config:
variables["training_config_type"] = args.training_config
if args.trainer_type:
variables["trainer_type"] = args.trainer_type
if args.batch_size:
variables["batch_size"] = args.batch_size
if args.learning_rate:
variables["learning_rate"] = args.learning_rate
if args.max_epochs:
variables["max_epochs"] = args.max_epochs
if args.max_seq_length:
variables["max_seq_length"] = args.max_seq_length
if args.hardware_info:
variables["hardware_info"] = args.hardware_info
if args.trackio_url:
variables["trackio_url"] = args.trackio_url
if args.dataset_repo:
variables["dataset_repo"] = args.dataset_repo
if args.author_name:
variables["author_name"] = args.author_name
if args.quantized_models:
variables["quantized_models"] = True
if args.dataset_sample_size:
variables["dataset_sample_size"] = args.dataset_sample_size
if args.training_loss:
variables["training_loss"] = args.training_loss
if args.validation_loss:
variables["validation_loss"] = args.validation_loss
if args.perplexity:
variables["perplexity"] = args.perplexity
# Generate model card
print("π Generating model card...")
content = generator.generate_model_card(variables)
# Save model card
if generator.save_model_card(content, args.output):
print("β
Model card generated successfully!")
print(f"π Output: {args.output}")
else:
print("β Failed to generate model card")
return 1
return 0
except Exception as e:
logger.error(f"β Error generating model card: {e}")
return 1
if __name__ == "__main__":
exit(main()) |