Praneshrajan15's picture
Deploy DataForge playground API
13fe504 verified
Raw
History Blame Contribute Delete
32.5 kB
"""Manifest-driven policy for DataForge Hugging Face model-family releases."""
from __future__ import annotations
import hashlib
import json
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import Any, Protocol, cast
import yaml
FAMILY_MANIFEST_SCHEMA_VERSION = "dataforge_model_family_manifest_v1"
FAMILY_REPORT_SCHEMA_VERSION = "dataforge_model_family_report_v2"
DEFAULT_HF_OWNER = "Praneshrajan15"
DEFAULT_DATASET_REPO = "Praneshrajan15/dataforge-sft-trajectories"
MODEL_FAMILY_SIZES = ("0.5B", "1.5B", "3B", "7B")
MODEL_FAMILY_STAGES = ("SFT", "GRPO", "GiGPO")
PASSING_QUALITY_STATUSES = frozenset({"quality_improved_verified", "quality_verified"})
PUBLIC_ARTIFACT_STATUSES = frozenset({"public", "public_verified"})
_STAGE_PREDECESSOR = {"SFT": None, "GRPO": "SFT", "GiGPO": "GRPO"}
_SIZE_CONFIG_SLUGS = {"0.5B": "05b", "1.5B": "15b", "3B": "3b", "7B": "7b"}
_SIZE_PATH_SLUGS = {"0.5B": "0.5b", "1.5B": "1.5b", "3B": "3b", "7B": "7b"}
class ModelFamilyError(RuntimeError):
"""Raised when the model-family manifest or evidence is internally unsafe."""
class BaseModelInfo(Protocol):
"""Minimal Hugging Face model-info shape used for license resolution."""
@property
def sha(self) -> str | None:
"""Return the Hub commit SHA."""
...
class BaseModelApi(Protocol):
"""Subset of HfApi used by the family policy module."""
def model_info(self, repo_id: str, *, token: str | None = None) -> BaseModelInfo:
"""Return model metadata from the Hub."""
@dataclass(frozen=True, slots=True)
class HubLicense:
"""Normalized license metadata from a Hugging Face model card."""
license: str
license_name: str | None
license_link: str | None
source_sha: str | None = None
@dataclass(frozen=True, slots=True)
class ModelFamilyEntry:
"""One expected DataForge model-family row."""
size: str
stage: str
base_model: str
upstream_license: str
hub_license: str
license_name: str | None
license_link: str | None
repo_id: str
predecessor_repo: str | None
compute_backend: str
training_backend: str
config_path: str
verifier: str
eval_gate: dict[str, Any]
artifact_status: str
quality_status: str
limitations: tuple[str, ...]
@property
def slug(self) -> str:
"""Return the repository slug without the owner namespace."""
return self.repo_id.rsplit("/", 1)[-1]
@property
def size_config_slug(self) -> str:
"""Return the compact file-name slug for this size."""
return _SIZE_CONFIG_SLUGS[self.size]
@property
def size_path_slug(self) -> str:
"""Return the lowercase path slug for this size."""
return _SIZE_PATH_SLUGS[self.size]
@property
def is_public_quality_verified(self) -> bool:
"""Return whether this row may satisfy the full-family quality gate."""
return (
self.artifact_status in PUBLIC_ARTIFACT_STATUSES
and self.quality_status in PASSING_QUALITY_STATUSES
)
def model_card_metadata(self, dataset_repo: str) -> dict[str, Any]:
"""Return required Hugging Face model-card front-matter for this row."""
metadata: dict[str, Any] = {
"license": self.hub_license,
"base_model": self.base_model,
"library_name": "transformers",
"datasets": [dataset_repo],
"metrics": ["f1"],
"tags": ["dataforge", "data-quality", self.stage.lower(), self.size.lower()],
}
if self.license_name:
metadata["license_name"] = self.license_name
if self.license_link:
metadata["license_link"] = self.license_link
metadata["model-index"] = [
{
"name": self.slug,
"results": [
{
"task": {
"type": "text-generation",
"name": "DataForge repair planning",
},
"dataset": {"name": "DataForge SFT trajectories", "type": dataset_repo},
"metrics": [
{
"type": "macro_f1",
"name": "Held-out macro F1",
"value": None,
}
],
}
],
}
]
return metadata
@dataclass(frozen=True, slots=True)
class ModelFamilyManifest:
"""Loaded model-family manifest."""
schema_version: str
hf_owner: str
dataset_repo: str
entries: tuple[ModelFamilyEntry, ...]
source_path: Path | None = None
@property
def manifest_hash(self) -> str:
"""Return a stable hash over the manifest entries."""
payload = {
"schema_version": self.schema_version,
"hf_owner": self.hf_owner,
"dataset_repo": self.dataset_repo,
"entries": [asdict(entry) for entry in self.entries],
}
encoded = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
return hashlib.sha256(encoded).hexdigest()
def repo_ids(self) -> tuple[str, ...]:
"""Return expected repo ids in manifest order."""
return tuple(entry.repo_id for entry in self.entries)
def entry_for(self, *, size: str, stage: str) -> ModelFamilyEntry:
"""Return the manifest row for a size and stage."""
for entry in self.entries:
if entry.size == size and entry.stage == stage:
return entry
raise ModelFamilyError(f"Missing model-family row for {size}-{stage}.")
def entry_for_repo(self, repo_id: str) -> ModelFamilyEntry | None:
"""Return the manifest row for a repo id, if present."""
for entry in self.entries:
if entry.repo_id == repo_id:
return entry
return None
def dependency_errors(self) -> list[str]:
"""Return quality-status dependency violations across the family."""
by_repo = {entry.repo_id: entry for entry in self.entries}
errors: list[str] = []
for entry in self.entries:
if entry.stage == "SFT":
continue
if not entry.predecessor_repo:
errors.append(f"{entry.repo_id}: predecessor_repo is required for {entry.stage}.")
continue
predecessor = by_repo.get(entry.predecessor_repo)
if predecessor is None:
errors.append(f"{entry.repo_id}: predecessor {entry.predecessor_repo} is absent.")
continue
if entry.is_public_quality_verified and not predecessor.is_public_quality_verified:
errors.append(
f"{entry.repo_id}: cannot be quality-verified before "
f"{predecessor.repo_id} is quality-verified."
)
return errors
def project_root() -> Path:
"""Return the repository root."""
return Path(__file__).resolve().parents[2]
def default_manifest_path() -> Path:
"""Return the default model-family manifest path."""
return project_root() / "training" / "configs" / "model_family.yaml"
def repo_id_for(owner: str, size: str, stage: str) -> str:
"""Return the canonical DataForge Hugging Face repo id."""
_validate_size_stage(size=size, stage=stage)
return f"{owner}/DataForge-{size}-{stage}"
def previous_stage(stage: str) -> str | None:
"""Return the required predecessor stage for a training stage."""
if stage not in MODEL_FAMILY_STAGES:
raise ModelFamilyError(f"Unknown model-family stage: {stage}")
return _STAGE_PREDECESSOR[stage]
def expected_license_for_repo(
repo_id: str,
*,
manifest: ModelFamilyManifest | None = None,
) -> str:
"""Return the expected downstream license name for a repo."""
manifest = manifest or load_model_family_manifest()
entry = manifest.entry_for_repo(repo_id)
return entry.upstream_license if entry is not None else "apache-2.0"
def expected_predecessor_for_repo(
repo_id: str,
*,
manifest: ModelFamilyManifest | None = None,
) -> str | None:
"""Return the expected predecessor repo for a repo."""
manifest = manifest or load_model_family_manifest()
entry = manifest.entry_for_repo(repo_id)
return entry.predecessor_repo if entry is not None else None
def license_matches(actual: Any, expected: str, *, license_name: Any = None) -> bool:
"""Return whether Hub or metric license metadata satisfies the manifest policy."""
actual_text = str(actual or "").strip().lower()
expected_text = expected.strip().lower()
license_name_text = str(license_name or "").strip().lower()
return actual_text == expected_text or license_name_text == expected_text
def hub_license_from_card_data(card_data: Any, *, source_sha: str | None = None) -> HubLicense:
"""Normalize license fields from Hugging Face cardData."""
card = card_data if isinstance(card_data, dict) else {}
return HubLicense(
license=str(card.get("license", "")).strip(),
license_name=_optional_str(card.get("license_name")),
license_link=_optional_str(card.get("license_link")),
source_sha=source_sha,
)
def resolve_base_license(
base_model: str,
*,
api: BaseModelApi | None = None,
token: str | None = None,
) -> HubLicense:
"""Resolve current license metadata for a base model from the Hub."""
if api is None:
from huggingface_hub import HfApi
api = cast(BaseModelApi, HfApi())
info = api.model_info(base_model, token=token)
return hub_license_from_card_data(getattr(info, "cardData", {}), source_sha=info.sha)
def load_model_family_manifest(path: Path | None = None) -> ModelFamilyManifest:
"""Load and validate the model-family manifest."""
manifest_path = path or default_manifest_path()
raw = yaml.safe_load(manifest_path.read_text(encoding="utf-8"))
payload = _mapping(raw, name=str(manifest_path))
schema_version = _required_str(payload, "schema_version")
if schema_version != FAMILY_MANIFEST_SCHEMA_VERSION:
raise ModelFamilyError(
f"model-family manifest schema_version must be {FAMILY_MANIFEST_SCHEMA_VERSION}."
)
hf_owner = _required_str(payload, "hf_owner")
dataset_repo = _required_str(payload, "dataset_repo")
sizes = _size_metadata(payload.get("sizes"))
stage_gates = _stage_gates(payload.get("stage_gates"))
rows = _required_list(payload, "models")
entries: list[ModelFamilyEntry] = []
seen: set[tuple[str, str]] = set()
for row in rows:
row_mapping = _mapping(row, name="models[]")
size = _required_str(row_mapping, "size")
stage = _required_str(row_mapping, "stage")
_validate_size_stage(size=size, stage=stage)
if (size, stage) in seen:
raise ModelFamilyError(f"Duplicate model-family row: {size}-{stage}.")
seen.add((size, stage))
size_info = sizes[size]
repo_id = _optional_str(row_mapping.get("repo_id")) or repo_id_for(hf_owner, size, stage)
predecessor = _optional_str(row_mapping.get("predecessor_repo"))
predecessor_stage = previous_stage(stage)
if predecessor is None and predecessor_stage is not None:
predecessor = repo_id_for(hf_owner, size, predecessor_stage)
gate = dict(stage_gates[stage])
gate.update(_optional_mapping(row_mapping.get("eval_gate"), name="eval_gate"))
entries.append(
ModelFamilyEntry(
size=size,
stage=stage,
base_model=size_info["base_model"],
upstream_license=size_info["upstream_license"],
hub_license=size_info["hub_license"],
license_name=_optional_str(size_info.get("license_name")),
license_link=_optional_str(size_info.get("license_link")),
repo_id=repo_id,
predecessor_repo=predecessor,
compute_backend=_required_str(row_mapping, "compute_backend"),
training_backend=_required_str(row_mapping, "training_backend"),
config_path=_required_str(row_mapping, "config_path"),
verifier=_required_str(row_mapping, "verifier"),
eval_gate=gate,
artifact_status=_required_str(row_mapping, "artifact_status"),
quality_status=_required_str(row_mapping, "quality_status"),
limitations=tuple(_string_list(row_mapping.get("limitations"))),
)
)
expected = {(size, stage) for size in MODEL_FAMILY_SIZES for stage in MODEL_FAMILY_STAGES}
missing = sorted(f"{size}-{stage}" for size, stage in expected - seen)
if missing:
raise ModelFamilyError("model-family manifest missing rows: " + ", ".join(missing))
manifest = ModelFamilyManifest(
schema_version=schema_version,
hf_owner=hf_owner,
dataset_repo=dataset_repo,
entries=tuple(entries),
source_path=manifest_path,
)
dependency_errors = manifest.dependency_errors()
if dependency_errors:
raise ModelFamilyError("; ".join(dependency_errors))
return manifest
def render_stage_config(
entry: ModelFamilyEntry, *, dataset_repo: str = DEFAULT_DATASET_REPO
) -> dict[str, Any]:
"""Render a training config dictionary for one manifest row."""
if entry.stage == "SFT":
return _render_sft_config(entry, dataset_repo=dataset_repo)
if entry.stage == "GRPO":
return _render_grpo_config(entry, dataset_repo=dataset_repo)
if entry.stage == "GiGPO":
return _render_gigpo_config(entry, dataset_repo=dataset_repo)
raise ModelFamilyError(f"Unknown model-family stage: {entry.stage}")
def build_hub_upload_manifest(
entry: ModelFamilyEntry,
*,
dataset_repo: str,
dataset_sha: str,
source_git_commit: str,
model_sha: str = "",
training_run_url: str = "",
eval_report_path: str = "",
verification_report_path: str = "",
eval_metrics: dict[str, Any] | None = None,
) -> dict[str, Any]:
"""Return a v2 evidence row skeleton derived from a verified model artifact."""
return {
"size": entry.size,
"stage": entry.stage,
"repo_id": entry.repo_id,
"artifact_status": entry.artifact_status,
"quality_status": entry.quality_status,
"verifier_passed": entry.quality_status in PASSING_QUALITY_STATUSES,
"upstream_license": entry.upstream_license,
"hub_license": entry.hub_license,
"license_name": entry.license_name,
"base_model": entry.base_model,
"predecessor_repo": entry.predecessor_repo,
"dataset_repo": dataset_repo,
"training_backend": entry.training_backend,
"training_run_url": training_run_url,
"source_git_commit": source_git_commit,
"dataset_sha": dataset_sha,
"model_sha": model_sha,
"model_card_url": f"https://huggingface.co/{entry.repo_id}",
"eval_report_path": eval_report_path,
"verification_report_path": verification_report_path,
"eval_metrics": eval_metrics or {},
"limitations": list(entry.limitations),
}
def _render_common_environment(entry: ModelFamilyEntry) -> dict[str, Any]:
packages = [
"trl==1.4.0",
"transformers==5.7.0",
"accelerate==1.13.0",
"peft==0.19.1",
"bitsandbytes==0.49.2",
"datasets==4.8.5",
"huggingface_hub==1.13.0",
"pyyaml==6.0.3",
"pandas==2.3.3",
]
if entry.stage in {"GRPO", "GiGPO"}:
packages.append("tensorboard==2.20.0")
if _uses_hf_jobs(entry):
packages.append("trackio")
return {
"resolved_on": "2026-06-04",
"runtime_target": entry.compute_backend,
"pip_packages": packages,
}
def _render_sft_config(entry: ModelFamilyEntry, *, dataset_repo: str) -> dict[str, Any]:
return {
"schema_version": f"sft_{entry.size_config_slug}_v4",
"environment": _render_common_environment(entry),
"repos": {
"dataset_repo_template": "{hf_user}/dataforge-sft-trajectories",
"source_dataset_repo": dataset_repo,
"model_repo_template": f"{{hf_user}}/{entry.slug}",
"trajectory_filename": "expert_v4.jsonl",
"split_manifest_filename": "split_manifest_v4.json",
"config_filename": Path(entry.config_path).name,
"model_card_template_filename": "MODEL_CARD_TEMPLATE.md",
},
"release": {
"require_hf_token": True,
"upload_eval_diagnostics": True,
"max_failure_samples": 25,
"push_only_if_gate_passes": True,
"promoted_status": "quality_improved_verified",
},
"model": {
"base_model": entry.base_model,
"model_license": entry.upstream_license,
"hub_license": entry.hub_license,
"license_name": entry.license_name,
"trust_remote_code": True,
"torch_dtype": "float16",
"target_model_repo": entry.repo_id,
"quantization": {
"load_in_4bit": True,
"bnb_4bit_quant_type": "nf4",
"bnb_4bit_use_double_quant": True,
"bnb_4bit_compute_dtype": "float16",
},
},
"lora": _lora_defaults(entry),
"training": {
"output_dir": f"/kaggle/working/dataforge-{entry.size_path_slug}-sft-v4",
"adapter_dir": f"/kaggle/working/dataforge-{entry.size_path_slug}-sft-v4-adapter",
"merged_dir": f"/kaggle/working/{entry.slug}-v4-merged",
"num_train_epochs": 2,
"per_device_train_batch_size": 1,
"gradient_accumulation_steps": 16 if entry.size in {"0.5B", "1.5B"} else 32,
"learning_rate": 0.00002,
"lr_scheduler_type": "cosine",
"warmup_ratio": 0.03,
"weight_decay": 0.0,
"max_length": 1024,
"packing": False,
"logging_steps": 10,
"save_steps": 100,
"save_total_limit": 3,
"fp16": True,
"bf16": False,
"gradient_checkpointing": True,
"report_to": "trackio" if _uses_hf_jobs(entry) else "none",
},
"evaluation": _evaluation_defaults(entry),
"model_card": entry.model_card_metadata(dataset_repo),
}
def _render_grpo_config(entry: ModelFamilyEntry, *, dataset_repo: str) -> dict[str, Any]:
return {
"schema_version": f"grpo_{entry.size_config_slug}_v1",
"environment": _render_common_environment(entry),
"repos": {
"dataset_repo_template": "{hf_user}/dataforge-sft-trajectories",
"source_dataset_repo": dataset_repo,
"sft_model_repo": entry.predecessor_repo,
"grpo_model_repo_template": f"{{hf_user}}/{entry.slug}",
"config_filename": Path(entry.config_path).name,
"reward_module": "training/rewards/dataforge_reward.py",
},
"model": {
"base_model": entry.base_model,
"sft_checkpoint": entry.predecessor_repo,
"sft_checkpoint_required": True,
"target_model_repo": entry.repo_id,
"model_license": entry.upstream_license,
"hub_license": entry.hub_license,
"license_name": entry.license_name,
"trust_remote_code": True,
"torch_dtype": "float16",
},
"lora": _lora_defaults(entry),
"quantization": _quantization_defaults(entry),
"training": {
"output_dir": f"/kaggle/working/dataforge-{entry.size_path_slug}-grpo",
"adapter_dir": f"/kaggle/working/dataforge-{entry.size_path_slug}-grpo-adapter",
"merged_dir": f"/kaggle/working/{entry.slug}-merged",
"max_steps": 500,
"num_generations": 4,
"max_completion_length": 256,
"prompt_token_budget": 1280,
"per_device_train_batch_size": 1,
"gradient_accumulation_steps": 16,
"beta": 0.04,
"learning_rate": 0.00001,
"num_iterations": 1,
"save_steps": 50,
"logging_steps": 5,
"report_to": "trackio" if _uses_hf_jobs(entry) else "tensorboard",
"save_total_limit": 4,
"lr_scheduler_type": "cosine",
"warmup_ratio": 0.03,
"weight_decay": 0.0,
"fp16": True,
"bf16": False,
"gradient_checkpointing": True,
"use_cache": False,
},
"reward": {
"function": "training.rewards.dataforge_reward:dataforge_reward",
"prompt_contract_version": "repair_contract_v2",
"local_stateless": True,
"endpoint_healthcheck_only": True,
"parse_failure_reward": 0.0,
},
"readiness": {
"trajectory_filename": "expert_v4.jsonl",
"split_manifest_filename": "split_manifest_v4.json",
"prompt_contract_version": "repair_contract_v2",
"required_datasets": ["hospital", "flights", "beers"],
"auxiliary_datasets": ["hospital_synthetic_deterministic_v1"],
"min_records": 128,
"min_records_per_dataset": 16,
"min_repair_records": 32,
"min_repair_signal_domains": 2,
"min_dirty_records": 0,
"min_dirty_records_per_dataset": 0,
"min_clean_records": 32,
"min_reward_std": 0.05,
"min_per_dataset_reward_std": 0.01,
"max_failure_samples": 25,
"block_on_heldout_leakage": True,
"require_source_provenance": True,
},
"training_sequence": _grpo_training_sequence_defaults(),
"release": _release_defaults(entry),
"evaluation": _grpo_evaluation_defaults(),
"model_card": entry.model_card_metadata(dataset_repo),
}
def _render_gigpo_config(entry: ModelFamilyEntry, *, dataset_repo: str) -> dict[str, Any]:
return {
"schema_version": f"gigpo_{entry.size_config_slug}_v1",
"environment": _render_common_environment(entry),
"repos": {
"dataset_repo_template": "{hf_user}/dataforge-sft-trajectories",
"source_dataset_repo": dataset_repo,
"grpo_model_repo": entry.predecessor_repo,
"gigpo_model_repo_template": f"{{hf_user}}/{entry.slug}",
"config_filename": Path(entry.config_path).name,
"advantage_module": "training/gigpo_advantage.py",
},
"model": {
"base_model": entry.base_model,
"grpo_checkpoint": entry.predecessor_repo,
"grpo_checkpoint_required": True,
"target_model_repo": entry.repo_id,
"model_license": entry.upstream_license,
"hub_license": entry.hub_license,
"license_name": entry.license_name,
"trust_remote_code": True,
"torch_dtype": "float16",
},
"lora": _lora_defaults(entry),
"quantization": _quantization_defaults(entry),
"training": {
"output_dir": f"/kaggle/working/dataforge-{entry.size_path_slug}-gigpo",
"adapter_dir": f"/kaggle/working/dataforge-{entry.size_path_slug}-gigpo-adapter",
"merged_dir": f"/kaggle/working/{entry.slug}-merged",
"max_steps": 500,
"num_rollouts_per_anchor": 4,
"max_completion_length": 256,
"prompt_token_budget": 1024,
"per_device_train_batch_size": 1,
"gradient_accumulation_steps": 16,
"macro_episode_advantage": True,
"micro_step_advantage": True,
"anchor_state_grouping": "canonical_observation_hash",
"learning_rate": 0.000005,
"save_steps": 50,
"logging_steps": 5,
"report_to": "trackio",
"fp16": True,
"bf16": False,
"gradient_checkpointing": True,
"use_cache": False,
},
"reward": {
"function": "training.rewards.dataforge_reward:dataforge_reward",
"local_stateless": True,
"canonical_observation_hashes": True,
},
"release": _release_defaults(entry),
"model_card": entry.model_card_metadata(dataset_repo),
}
def _lora_defaults(entry: ModelFamilyEntry) -> dict[str, Any]:
rank = 16 if entry.size == "0.5B" else 8
if entry.size == "7B":
rank = 4
return {
"enabled": True,
"r": rank,
"alpha": 16,
"dropout": 0.05,
"bias": "none",
"task_type": "CAUSAL_LM",
"target_modules": ["q_proj", "k_proj", "v_proj", "o_proj"],
}
def _uses_hf_jobs(entry: ModelFamilyEntry) -> bool:
return entry.training_backend == "hf_jobs" or entry.compute_backend == "hf_jobs_gpu"
def _quantization_defaults(entry: ModelFamilyEntry) -> dict[str, Any]:
if entry.size == "0.5B":
return {"load_in_4bit": _uses_hf_jobs(entry)}
return {
"load_in_4bit": True,
"bnb_4bit_quant_type": "nf4",
"bnb_4bit_use_double_quant": True,
"bnb_4bit_compute_dtype": "float16",
}
def _evaluation_defaults(entry: ModelFamilyEntry) -> dict[str, Any]:
return {
"heldout_tasks": 100,
"benchmark_name": "DataForge-Bench-light-verified",
"benchmark_seeds": [0, 1, 2],
"parse_success_min": entry.eval_gate["parse_success_min"],
"schema_case_error_max": entry.eval_gate["schema_case_error_max"],
"min_absolute_f1_gain": entry.eval_gate["min_absolute_f1_gain"],
"require_eval_diagnostics": True,
"remote_only": True,
}
def _grpo_evaluation_defaults() -> dict[str, Any]:
return {
"heldout_tasks": 100,
"seeds_start": 10000,
"chunk_width": 4,
"max_new_tokens": 1024,
"source": "pinned_dataforge_registry",
"datasets": ["hospital", "flights", "beers"],
}
def _grpo_training_sequence_defaults() -> dict[str, Any]:
return {
"stages": [
{
"name": "smoke",
"max_steps": 50,
"allow_upload": False,
"purpose": "Validate imports, dataset contract, reward variance, memory, and logging.",
},
{
"name": "candidate",
"max_steps": 500,
"allow_upload_after_gate": True,
"purpose": "First publish-eligible candidate if strict held-out gate passes.",
},
{
"name": "extended_candidate",
"max_steps": 1000,
"run_if": "500_step_improves_trend_but_misses_gate",
"allow_upload_after_gate": True,
"purpose": "Only run when the 500-step candidate trends upward but misses +0.03 F1.",
},
],
"selection_order": [
"highest_strict_macro_f1",
"lowest_schema_case_errors",
"lowest_gpu_hours",
],
}
def _release_defaults(entry: ModelFamilyEntry) -> dict[str, Any]:
return {
"benchmark_name": "DataForge-Bench-light-verified",
"benchmark_seeds": [0, 1, 2],
"min_absolute_f1_gain": entry.eval_gate["min_absolute_f1_gain"],
"require_parse_success_rate": entry.eval_gate["parse_success_min"],
"require_schema_case_error_count": entry.eval_gate["schema_case_error_max"],
"require_eval_diagnostics": True,
"push_only_if_gate_passes": True,
"compute_cost_unit": "gpu_hours",
"training_backend": entry.training_backend,
}
def _validate_size_stage(*, size: str, stage: str) -> None:
if size not in MODEL_FAMILY_SIZES:
raise ModelFamilyError(f"Unknown model-family size: {size}")
if stage not in MODEL_FAMILY_STAGES:
raise ModelFamilyError(f"Unknown model-family stage: {stage}")
def _mapping(value: object, *, name: str) -> dict[str, Any]:
if not isinstance(value, dict):
raise ModelFamilyError(f"{name} must be a mapping.")
return cast(dict[str, Any], value)
def _optional_mapping(value: object, *, name: str) -> dict[str, Any]:
if value is None:
return {}
return _mapping(value, name=name)
def _required_list(payload: dict[str, Any], key: str) -> list[Any]:
value = payload.get(key)
if not isinstance(value, list):
raise ModelFamilyError(f"{key} must be a list.")
return value
def _required_str(payload: dict[str, Any], key: str) -> str:
value = payload.get(key)
if not isinstance(value, str) or not value.strip():
raise ModelFamilyError(f"{key} is required.")
return value.strip()
def _optional_str(value: object) -> str | None:
if value is None:
return None
if not isinstance(value, str):
return None
stripped = value.strip()
return stripped or None
def _string_list(value: object) -> list[str]:
if value is None:
return []
if not isinstance(value, list) or not all(isinstance(item, str) for item in value):
raise ModelFamilyError("limitations must be a list of strings.")
return [item.strip() for item in value if item.strip()]
def _size_metadata(value: object) -> dict[str, dict[str, Any]]:
sizes = _required_sequence_mappings(value, name="sizes")
by_size: dict[str, dict[str, Any]] = {}
for item in sizes:
size = _required_str(item, "size")
if size not in MODEL_FAMILY_SIZES:
raise ModelFamilyError(f"Unknown size metadata row: {size}")
by_size[size] = {
"base_model": _required_str(item, "base_model"),
"upstream_license": _required_str(item, "upstream_license"),
"hub_license": _required_str(item, "hub_license"),
"license_name": _optional_str(item.get("license_name")),
"license_link": _optional_str(item.get("license_link")),
}
missing = sorted(set(MODEL_FAMILY_SIZES) - set(by_size))
if missing:
raise ModelFamilyError("sizes metadata missing: " + ", ".join(missing))
return by_size
def _stage_gates(value: object) -> dict[str, dict[str, Any]]:
gates = _required_sequence_mappings(value, name="stage_gates")
by_stage: dict[str, dict[str, Any]] = {}
for item in gates:
stage = _required_str(item, "stage")
if stage not in MODEL_FAMILY_STAGES:
raise ModelFamilyError(f"Unknown stage gate row: {stage}")
by_stage[stage] = {
"metric": _required_str(item, "metric"),
"predecessor_metric": _optional_str(item.get("predecessor_metric")),
"min_absolute_f1_gain": float(item.get("min_absolute_f1_gain", 0.0)),
"parse_success_min": float(item.get("parse_success_min", 0.99)),
"schema_case_error_max": int(item.get("schema_case_error_max", 0)),
}
missing = sorted(set(MODEL_FAMILY_STAGES) - set(by_stage))
if missing:
raise ModelFamilyError("stage_gates missing: " + ", ".join(missing))
return by_stage
def _required_sequence_mappings(value: object, *, name: str) -> list[dict[str, Any]]:
if not isinstance(value, list):
raise ModelFamilyError(f"{name} must be a list.")
return [_mapping(item, name=f"{name}[]") for item in value]