From 897addca54f23fe08fc33fd10e469dcdf7b72dc0 Mon Sep 17 00:00:00 2001 From: whoisdomi Date: Sun, 26 Jul 2026 10:47:11 -0500 Subject: [PATCH] Model_compiler.py: Local Only If local flag is used onnx file is compiled into one pkl file and put into data/models. File name will be local-MODELID. Model manager will allow it and know its local --- scripts/model_compiler.py | 54 +++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/scripts/model_compiler.py b/scripts/model_compiler.py index 5a1c92f20..d3f4bd3e6 100644 --- a/scripts/model_compiler.py +++ b/scripts/model_compiler.py @@ -5,6 +5,7 @@ import hashlib import json import os import pickle +import shutil import subprocess import sys from pathlib import Path @@ -19,6 +20,7 @@ COMPILE_SCRIPT = REPO_ROOT / "tinygrad_repo/examples/openpilot/compile3.py" DRIVING_COMPILE_SCRIPT = REPO_ROOT / "selfdrive/modeld/compile_modeld.py" DM_WARP_COMPILE_SCRIPT = REPO_ROOT / "selfdrive/modeld/compile_dm_warp.py" MODEL_VERSIONS_CACHE = Path("/data/models/.model_versions.json") +MODELS_PATH = MODEL_VERSIONS_CACHE.parent # runtime dir modeld loads from: /data/models DM_MODEL_KEY = "dm" DM_MODEL_NAME = "dmonitoring_model" @@ -84,6 +86,11 @@ def parse_args() -> argparse.Namespace: help="Compile the driving artifact for the USB AMD GPU.") parser.add_argument("--split-artifact", type=Path, help="Split an existing oversized PKL without compiling.") parser.add_argument("--chunk-size-mib", type=int, default=95, help="Multipart size in MiB; must be below 100.") + parser.add_argument("--no-split", action="store_true", + help="Keep a single .pkl even if >100 MiB (for local installs, which need one " + "file). Auto-enabled for local- model IDs.") + parser.add_argument("--no-install", action="store_true", + help="Do not auto-copy a local- model into /data/models after compiling.") parser.add_argument( "--image-history-pipeline", choices=("policy", "warp"), @@ -302,6 +309,20 @@ def multipart_output_paths(artifact: Path, output_dir: Path | None = None) -> li ] +def install_local_artifact(artifact: Path) -> None: + """Copy a freshly compiled local- model into the runtime dir modeld loads from. + + Local models must be a single is_file() in /data/models to appear in the picker. + No-ops off-device (when /data/models is absent) so dev-box runs don't error. + """ + if not MODELS_PATH.is_dir(): + print(f" skipped auto-install: {MODELS_PATH} not present (not on device?)") + return + dest = MODELS_PATH / artifact.name + shutil.copy2(artifact, dest) + print(f" installed -> {dest} (reboot + one online boot to see it in the picker)") + + def split_oversized_artifact( artifact: Path, output_dir: Path | None = None, @@ -507,17 +528,34 @@ def main() -> int: if not version and input_format == "supercombo": version = "v15" version_label = version or "unspecified behavior" - print(f"Compiling {model_key} ({input_format}, {version_label}) from {args.input_dir} -> {args.output_dir}") + will_install = model_key.startswith("local-") and not args.no_install + target = f"{args.output_dir}" + (f" -> {MODELS_PATH} (auto-install)" if will_install else "") + print(f"Compiling {model_key} ({input_format}, {version_label}) from {args.input_dir} -> {target}") output = compile_driving(model_key, files, input_format, version, args.output_dir, args.image_history_pipeline, args.external_gpu) print(f" saved {output.name}") - multipart_outputs = split_oversized_artifact(output) - if multipart_outputs: - print(" artifact exceeds 100 MiB; created repository-safe multipart files:") - for multipart_output in multipart_outputs: - print(f" {multipart_output.name} ({multipart_output.stat().st_size} bytes)") - output.unlink() - print(f" removed oversized source artifact {output.name}") + # Local models install as a single is_file() and never go to GitHub, so the >100 MiB + # repo split is pointless for them (you'd only have to reassemble it). Keep one .pkl. + keep_single = args.no_split or model_key.startswith("local-") + if keep_single: + is_local = model_key.startswith("local-") + if output.stat().st_size > REPOSITORY_FILE_LIMIT: + size_mb = output.stat().st_size / 1e6 + if is_local: + print(f" local model: kept as one {size_mb:.1f} MB file (repo split not needed)") + else: + print(f" --no-split: kept one {size_mb:.1f} MB file; over 100 MB, so split it " + "before committing to a repo (re-run without --no-split, or --split-artifact)") + if is_local and not args.no_install: + install_local_artifact(output) + else: + multipart_outputs = split_oversized_artifact(output) + if multipart_outputs: + print(" artifact exceeds 100 MiB; created repository-safe multipart files:") + for multipart_output in multipart_outputs: + print(f" {multipart_output.name} ({multipart_output.stat().st_size} bytes)") + output.unlink() + print(f" removed oversized source artifact {output.name}") print("Done.") return 0