|
|
|
|
| """Pre-flight validation for LitGPT checkpoints.
|
|
|
| Usage:
|
| litgpt validate --checkpoint_dir checkpoints/meta-llama/...
|
| """
|
|
|
| import sys
|
| from pathlib import Path
|
|
|
| import torch
|
| import yaml
|
|
|
| from litgpt.config import Config
|
| from litgpt.utils import (
|
| check_valid_checkpoint_dir,
|
| estimate_model_memory,
|
| validate_checkpoint,
|
| )
|
|
|
|
|
| def validate_setup(
|
| checkpoint_dir: Path,
|
| model_filename: str = "lit_model.pth",
|
| dtype: str = "float32",
|
| training: bool = False,
|
| ) -> None:
|
| """Run pre-flight validation on a checkpoint directory.
|
|
|
| This checks everything without actually running training or generation:
|
| 1. Checkpoint directory structure (required files exist)
|
| 2. Model config loading
|
| 3. Tokenizer loading
|
| 4. Checkpoint key/shape validation against the model
|
| 5. Memory estimation
|
|
|
| Args:
|
| checkpoint_dir: Path to the checkpoint directory.
|
| model_filename: Name of the checkpoint file (default: ``lit_model.pth``).
|
| dtype: Data type for memory estimation (``float32``, ``float16``, ``bfloat16``).
|
| training: If ``True``, estimate memory for training (includes optimizer states).
|
| """
|
| checkpoint_dir = Path(checkpoint_dir)
|
| print(f"{'=' * 60}")
|
| print("LitGPT Pre-flight Validation")
|
| print(f"Checkpoint: {checkpoint_dir}")
|
| print(f"{'=' * 60}\n")
|
|
|
| all_passed = True
|
|
|
|
|
| print("[1/5] Checking checkpoint directory structure...")
|
| try:
|
| check_valid_checkpoint_dir(
|
| checkpoint_dir,
|
| model_filename=model_filename,
|
| )
|
| print(" β All required files found.\n")
|
| except (FileNotFoundError, SystemExit) as e:
|
| print(f" β Directory validation failed: {e}\n", file=sys.stderr)
|
| all_passed = False
|
|
|
|
|
| print("[2/5] Loading model config...")
|
| config = None
|
| config_path = checkpoint_dir / "model_config.yaml"
|
| try:
|
| if config_path.is_file():
|
| with open(config_path, encoding="utf-8") as f:
|
| config_dict = yaml.safe_load(f)
|
| config = Config(**config_dict)
|
| print(f" β Config loaded: {config.name or 'unnamed'}")
|
| print(
|
| f" n_layer={config.n_layer}, n_embd={config.n_embd}, "
|
| f"n_head={config.n_head}, vocab_size={config.vocab_size}\n"
|
| )
|
| else:
|
| print(f" β Config file not found: {config_path}\n", file=sys.stderr)
|
| all_passed = False
|
| except Exception as e:
|
| print(f" β Failed to load config: {e}\n", file=sys.stderr)
|
| all_passed = False
|
|
|
|
|
| print("[3/5] Checking tokenizer...")
|
| try:
|
| from litgpt.tokenizer import Tokenizer
|
|
|
| tokenizer = Tokenizer(checkpoint_dir)
|
|
|
| test_text = "Hello"
|
| tokens = tokenizer.encode(test_text)
|
| decoded = tokenizer.decode(tokens)
|
| print(f" β Tokenizer loaded (backend={tokenizer.backend})")
|
| print(f' Round-trip test: "{test_text}" β {tokens.tolist()} β "{decoded}"\n')
|
| except Exception as e:
|
| print(f" β Tokenizer failed: {e}\n", file=sys.stderr)
|
| all_passed = False
|
|
|
|
|
| print("[4/5] Validating checkpoint against model...")
|
| checkpoint_path = checkpoint_dir / model_filename
|
| if config is not None and checkpoint_path.is_file():
|
| try:
|
| from litgpt import GPT
|
|
|
| with torch.device("meta"):
|
| model = GPT(config)
|
| result = validate_checkpoint(checkpoint_path, model, verbose=False)
|
| if result.is_valid:
|
| print(" β Checkpoint keys and shapes match the model.\n")
|
| else:
|
| all_passed = False
|
| print(f" β {result.summary()}\n", file=sys.stderr)
|
| except Exception as e:
|
| print(f" β Checkpoint validation error: {e}\n", file=sys.stderr)
|
| all_passed = False
|
| elif not checkpoint_path.is_file():
|
| print(f" β Skipped (checkpoint file not found: {checkpoint_path})\n")
|
| else:
|
| print(" β Skipped (config not loaded)\n")
|
|
|
|
|
| print("[5/5] Estimating memory requirements...")
|
| if config is not None:
|
| mem = estimate_model_memory(config, dtype=dtype, training=training)
|
| print(f" Estimated parameters: {mem['param_count']:,}")
|
| print(f" Parameter memory: {mem['param_memory_gb']:.2f} GB ({dtype})")
|
| mode_str = "training (params + grads + optimizer)" if training else "inference (params only)"
|
| print(f" Estimated total ({mode_str}): {mem['estimated_total_gb']:.2f} GB")
|
| if mem["available_gpu_memory_gb"] is not None:
|
| print(f" Available GPU memory: {mem['available_gpu_memory_gb']:.2f} GB")
|
| if mem["fits_in_memory"]:
|
| print(" β Model should fit in GPU memory.\n")
|
| else:
|
| print(" β WARNING: Model may NOT fit in GPU memory!\n", file=sys.stderr)
|
| all_passed = False
|
| else:
|
| print(" β No GPU detected, skipping memory fit check.\n")
|
| else:
|
| print(" β Skipped (config not loaded)\n")
|
|
|
|
|
| print(f"{'=' * 60}")
|
| if all_passed:
|
| print("β All validation checks passed!")
|
| else:
|
| print("β Some validation checks failed. See details above.", file=sys.stderr)
|
| print(f"{'=' * 60}")
|
|
|
| if not all_passed:
|
| raise SystemExit(1)
|
|
|