mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-19 13:33:59 +08:00
* Add job to fetch and upload model artifacts
Introduced a new `get_model` job to retrieve and upload model artifacts as part of the workflow. Updated the `build_model` job to download and clean up model files before building, ensuring an isolated and streamlined process. These changes improve modularity and artifact handling in the CI pipeline.
* Refine model file handling in build workflow
Restrict deletion and download commands to ".onnx" files to prevent unintended removal or overwriting of non-ONNX files. This ensures a more targeted and safer workflow for handling model artifacts.
* Update model artifact handling in build workflow
Changed artifact upload path to include only .onnx files and commented out the deletion of existing models. Also added a dependency for the build stage to ensure proper execution sequence.
* Update build workflow to refine model artifact handling
Removed unused code for deleting models and fixed the artifact path. Added a reference file logging custom name and upstream branch for better traceability. These changes streamline the workflow and improve clarity.
* Set dynamic run-name for sunnypilot build workflow
Added a customizable `run-name` field in the sunnypilot build model workflow. This allows more informative and dynamic naming based on input parameters such as `custom_name` or `upstream_branch`. Improves clarity and traceability in workflow runs.
* Add customization options and metadata generation to build
Introduce new inputs for file name prefix and 20Hz model specification in the workflow. Enable renaming of model files, generation of file hashes, and creation of a `metadata.json` file containing build details. This improves flexibility and enhances artifact information management.
* remove EOF
* No need for this hack anymore
* Add support for compiling ONNX models to Tinygrad format
* Add model directory environment variable and metadata generation script
* Fix quoting in model generator script command
* Refactor conditional flag for 20Hz input in build model script
* meh
* Add powersave management to build model workflow
* Add environment variable setup to build model workflow
* make it path call it a day
* kill me
* kill me x2
* mmm
* mmm
* Generate metadata.pkl
* Generate metadata.pkl
* ignore failure on getting model metadata
* Cleanup the existing onnxs
* Fix rm command syntax in build model script
* Cleaning a little
* Add optional file name parameter to generate_metadata function
* update
* stg
* linter
* more formatting
* Update sunnypilot model build workflow: improve custom naming, handle 20Hz default, and add commit date as output.
* Update commit date format in workflow script
Changed the commit date format in sunnypilot-build-model.yaml to a more human-readable format ('Month DD, YYYY'). This improves readability and consistency in the workflow outputs.
* Fix output naming in sunnypilot-build-model workflow
Corrected the output name from 'model_date' to 'commit_date' to match its usage. This ensures consistency and prevents potential errors in the workflow.
Add debug echo for model date in GitHub workflow
This change adds a debug echo statement to display the model date in the sunnypilot-build-model workflow. It helps verify the correct commit date is being set during the workflow process.
* Update BUILD_DIR path in sunnypilot workflow
Replaced hardcoded BUILD_DIR with a dynamic path using `github.workspace`. This enhances flexibility and ensures compatibility with different environments or runners.
* Revert "Update BUILD_DIR path in sunnypilot workflow"
This reverts commit 376971b616.
* Refactor model metadata generation to use short names
Replaced `file_name` with generated `short_name` for metadata and file naming. Introduced `create_short_name` function to simplify short name creation from custom names. Updated scripts and workflow to reflect the new parameter and improve metadata handling.
* `Use timezone-aware UTC timestamp for build_time`
Updated the code to use `datetime.now(timezone.utc)` instead of `datetime.utcnow()`. This ensures that the generated timestamps are timezone-aware, improving consistency and correctness in the output.
* Refactor short name generation logic in model metadata
Enhanced the `create_short_name` function to better handle name conversion by incorporating new rules for handling parentheses, alphanumeric words, and version pairs. Updated related variable names in metadata functions for improved clarity and consistency.
* Fix syntax error in assigning 'models' key in metadata
Corrected a typo where 'models' was missing quotes, causing it to be interpreted as a variable instead of a string key. This ensures proper metadata dictionary structure.
Update model metadata structure and JSON generation
Revised metadata to include detailed download URIs and a type field for artifacts. Enhanced the JSON generator with new fields like environment, runner, and overrides for better configurability. These changes aim to improve metadata clarity and compatibility with downstream processes.
* Refactor variable name from "escaped_name" to "short_name"
Renamed "escaped_name" to "short_name" across function parameters and internal logic for clarity and consistency. This improves readability and better aligns with its use case in the metadata generation process. No functional changes were introduced.
* Refactor variable names and improve type annotations.
Updated parameter names to align with Python naming conventions, enhancing readability and consistency. Added type annotations for function parameters to improve code clarity and maintainability.
* Refactor type annotations and clarify comments.
Updated type annotations to use "Str" for consistency with custom typing conventions. Improved clarity of a comment describing the normal case logic in the shortening function.
* Fix dict formatting in model_generator.py
Moved the "overrides" key for better alignment and consistency in the dictionary format. This improves readability without changing functionality.
Refactor model short name generation logic
Simplify and clarify the `create_short_name` function by improving readability and condensing comments. Adjust casing and truncation logic for single-word cases and handle versioned names more intuitively.
* Ensure custom file names are converted to lowercase.
When renaming files using a custom short name, enforce lowercase conversion to maintain consistency and prevent potential issues with case-sensitive file systems. This change applies to both the tinygrad and metadata file names.
* Use UTC alias for timezone in datetime imports
Replaced `timezone.utc` with `UTC` from the `datetime` module for clarity and consistency. This simplifies the representation of time zones and aligns with Python's updated best practices.
---------
Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
132 lines
4.7 KiB
Python
Executable File
132 lines
4.7 KiB
Python
Executable File
import os
|
|
import sys
|
|
import hashlib
|
|
import json
|
|
import re
|
|
from pathlib import Path
|
|
from datetime import datetime, UTC
|
|
|
|
|
|
def create_short_name(full_name):
|
|
# Remove parentheses and extract alphanumeric words
|
|
clean_name = re.sub(r'\([^)]*\)', '', full_name)
|
|
words = [re.sub(r'[^a-zA-Z0-9]', '', word) for word in clean_name.split() if re.sub(r'[^a-zA-Z0-9]', '', word)]
|
|
|
|
if len(words) == 1:
|
|
# If there's only one word, return it as is, lowercased, truncated to 8 characters
|
|
truncated = words[0][:8]
|
|
return truncated.lower() if truncated.isupper() else truncated
|
|
|
|
# Handle special case: Name + Version (e.g., "Word A1" -> "WordA1")
|
|
if len(words) == 2 and re.match(r'^[A-Za-z]\d+$', words[1]):
|
|
first_word = words[0].lower() if words[0].isupper() else words[0]
|
|
return (first_word + words[1])[:8]
|
|
|
|
# Normal case: first letter and trailing numbers from each word
|
|
result = ''.join(word if word.isdigit() else word[0] + (re.search(r'\d+$', word) or [''])[0] for word in words)
|
|
return result[:8]
|
|
|
|
|
|
def generate_metadata(model_path: Path, output_dir: Path, short_name: str):
|
|
model_path = model_path
|
|
output_path = output_dir
|
|
base = model_path.stem
|
|
|
|
# Define output files for tinygrad and metadata
|
|
tinygrad_file = output_path / f"{base}_tinygrad.pkl"
|
|
metadata_file = output_path / f"{base}_metadata.pkl"
|
|
|
|
if not tinygrad_file.exists() or not metadata_file.exists():
|
|
print(f"Error: Missing files for model {base} ({tinygrad_file} or {metadata_file})", file=sys.stderr)
|
|
return
|
|
|
|
# Calculate the sha256 hashes
|
|
with open(tinygrad_file, 'rb') as f:
|
|
tinygrad_hash = hashlib.sha256(f.read()).hexdigest()
|
|
|
|
with open(metadata_file, 'rb') as f:
|
|
metadata_hash = hashlib.sha256(f.read()).hexdigest()
|
|
|
|
# Rename the files if a custom file name is provided
|
|
if short_name:
|
|
tinygrad_file = tinygrad_file.rename(output_path / f"{base}_{short_name.lower()}_tinygrad.pkl")
|
|
metadata_file = metadata_file.rename(output_path / f"{base}_{short_name.lower()}_metadata.pkl")
|
|
|
|
# Build the metadata structure
|
|
model_metadata = {
|
|
"type": base.split("_")[-1] if "dmonitoring" not in base else "dmonitoring",
|
|
"artifact": {
|
|
"file_name": tinygrad_file.name,
|
|
"download_uri": {
|
|
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/<FILLME>",
|
|
"sha256": tinygrad_hash
|
|
}
|
|
},
|
|
"metadata": {
|
|
"file_name": metadata_file.name,
|
|
"download_uri": {
|
|
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/<FILLME>",
|
|
"sha256": metadata_hash
|
|
}
|
|
}
|
|
}
|
|
|
|
# Return model metadata
|
|
return model_metadata
|
|
|
|
|
|
def create_metadata_json(models: list, output_dir: Path, custom_name=None, short_name=None, is_20hz=False, upstream_branch="unknown"):
|
|
metadata_json = {
|
|
"short_name": short_name,
|
|
"display_name": custom_name or upstream_branch,
|
|
"is_20hz": is_20hz,
|
|
"ref": upstream_branch,
|
|
"environment": "development",
|
|
"runner": "tinygrad",
|
|
"build_time": datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
"models": models,
|
|
"overrides": {},
|
|
"index": -1,
|
|
"minimum_selector_version": "-1",
|
|
"generation": "-1",
|
|
}
|
|
|
|
# Write metadata to output_dir
|
|
with open(output_dir / "metadata.json", "w") as f:
|
|
json.dump(metadata_json, f, indent=2)
|
|
|
|
print(f"Generated metadata.json with {len(models)} models.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import argparse
|
|
import glob
|
|
|
|
parser = argparse.ArgumentParser(description="Generate metadata for model files")
|
|
parser.add_argument("--model-dir", default="./models", help="Directory containing ONNX model files")
|
|
parser.add_argument("--output-dir", default="./output", help="Output directory for metadata")
|
|
parser.add_argument("--custom-name", help="Custom display name for the model")
|
|
parser.add_argument("--is-20hz", action="store_true", help="Whether this is a 20Hz model")
|
|
parser.add_argument("--upstream-branch", default="unknown", help="Upstream branch name")
|
|
args = parser.parse_args()
|
|
|
|
# Find all ONNX files in the given directory
|
|
model_paths = glob.glob(os.path.join(args.model_dir, "*.onnx"))
|
|
if not model_paths:
|
|
print(f"No ONNX files found in {args.model_dir}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
_output_dir = Path(args.output_dir)
|
|
_output_dir.mkdir(exist_ok=True, parents=True)
|
|
_models = []
|
|
|
|
for _model_path in model_paths:
|
|
_model_metadata = generate_metadata(Path(_model_path), _output_dir, create_short_name(args.custom_name))
|
|
if _model_metadata:
|
|
_models.append(_model_metadata)
|
|
|
|
if _models:
|
|
create_metadata_json(_models, _output_dir, args.custom_name, create_short_name(args.custom_name), args.is_20hz, args.upstream_branch)
|
|
else:
|
|
print("No models processed.", file=sys.stderr)
|