Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c77cf92
chore: init
vividf Oct 8, 2025
117dead
chore: add deployment framework intro
vividf Oct 8, 2025
41a3e9a
feat(deployment):prototype deployment framework (#137)
vividf Dec 24, 2025
d80db0a
feat(deployment): restructure deployment framework (#160)
vividf Dec 25, 2025
a1edc32
chore: add missing pipeline directory and docstring
vividf Dec 25, 2025
a362b27
feat(deployment): refactor config and clean code (#180)
vividf Feb 12, 2026
d99296c
chore: refactor base config
vividf Mar 5, 2026
e23c210
chore: clean up code: device spec, remove unused fucntion .etc
vividf Mar 10, 2026
dd46052
chore: refactor export compenent
vividf Mar 10, 2026
2b28f60
chore: fix more Device spec
vividf Mar 10, 2026
85f0d64
chore: enable only trt evaluation
vividf Mar 25, 2026
e7439a6
chore: fix verification
vividf Mar 25, 2026
ca6f730
chore: fix main
vividf Mar 25, 2026
d150f5e
chore: fix base evaluator
vividf Mar 26, 2026
23df89b
chore: clean up base
vividf Mar 27, 2026
36d7568
chore: add base logger
vividf Mar 27, 2026
5bd5b76
chore: update docs
vividf Mar 27, 2026
0eed1f1
chore: add more readme
vividf Mar 27, 2026
d706ff7
chore: base add -> None for __init__
vividf Apr 9, 2026
9dfb6a1
chore: remove task profile
vividf Apr 9, 2026
a75d739
chore: fix matrix report base
vividf Apr 10, 2026
efa71d1
chore: clean metrics
vividf Apr 10, 2026
0c7c57c
chore: update project registry base
vividf Apr 10, 2026
ddc5106
feat(deployment): centerpoint deployment integration (#181)
vividf Apr 14, 2026
d0b491d
chore: improve docs
vividf Apr 16, 2026
5080b40
chore: clean up docs
vividf Apr 16, 2026
a46f933
chore: clean up code
vividf Apr 16, 2026
b7b6954
chore: fix verification
vividf Apr 20, 2026
f873e85
chore: fix verification 2
vividf Apr 20, 2026
9329b11
chore: clean up __init__.py
vividf Apr 20, 2026
1d4c27f
chor: clean code
vividf Apr 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions deployment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# AWML Deployment Framework

The `deployment/` package is the shared path from trained PyTorch checkpoints to ONNX and TensorRT artifacts, with verification and evaluation built into the same run. Shared runtime code lives in the framework packages, while task-specific logic lives under `deployment/projects/<name>/`.

## Core workflow

```text
Load checkpoint -> Export -> Verify -> Evaluate
```

## Quick start

```bash
python -m deployment.cli.main <project_name> <deploy_cfg.py> <model_cfg.py> [--log-level INFO]

# Example (CenterPoint)
python -m deployment.cli.main centerpoint \
deployment/projects/centerpoint/config/deploy_config.py \
<model_cfg.py> \
--rot-y-axis-reference
```

## What to read

| If you want to... | Start here |
| --- | --- |
| Run deployment today | [docs/runbook.md](docs/runbook.md) |
| Edit or author deploy config | [docs/configuration.md](docs/configuration.md) |
| Understand the framework structure | [docs/architecture.md](docs/architecture.md) |
| Troubleshoot or tune runs | [docs/operations.md](docs/operations.md) |
| Add a new project bundle | [docs/contributing.md](docs/contributing.md) |
| Run the current shipped project | [projects/centerpoint/README.md](projects/centerpoint/README.md) |

## Current status

- Current first-class project: [CenterPoint](projects/centerpoint/README.md)
- Shared framework responsibilities: CLI, typed config, exporters, runtime orchestration, verification, evaluation, and pipeline creation

## Repository layout

```text
deployment/
├── cli/ # Unified CLI
├── configs/ # Typed deploy config schema
├── core/ # Shared types, evaluators, verification mixins
├── exporters/ # ONNX / TensorRT exporters and export pipeline bases
├── pipelines/ # Inference pipelines and global factory
├── runtime/ # BaseDeploymentRunner, orchestrators, ArtifactManager
└── projects/ # Per-task bundles
```

## License

See `LICENSE` at the repository root.
7 changes: 7 additions & 0 deletions deployment/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Autoware ML Deployment Framework.

Task-agnostic export, verification, and evaluation across backends (ONNX, TensorRT).
Import from concrete submodules (for example ``deployment.configs.base``, ``deployment.runtime.runner``).
"""

__version__ = "1.0.0"
1 change: 1 addition & 0 deletions deployment/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Deployment CLI package."""
85 changes: 85 additions & 0 deletions deployment/cli/args.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"""
CLI helpers: argument parsing and logging setup.

Config schema does not depend on argparse/logging; this module is the single place for CLI concerns.
"""

from __future__ import annotations

import argparse
import logging
import os
from typing import Optional

_LOG_FORMAT = "%(levelname)s:%(name)s:%(message)s"


def setup_logging(level: str = "INFO") -> logging.Logger:
"""
Setup logging configuration.

Args:
level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)

Returns:
Configured logger instance
"""
logging.basicConfig(level=getattr(logging, level), format=_LOG_FORMAT)
return logging.getLogger("deployment")


def add_deployment_file_logging(log_file_path: str) -> None:
"""
Append a UTF-8 file handler to the root logger so all log records are also written to disk.

Idempotent for the same absolute path. Creates parent directories when needed.

Args:
log_file_path: Absolute or resolved path to the log file.
"""
path = os.path.abspath(os.path.expanduser(log_file_path))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use pathlib instead

parent = os.path.dirname(path)
if parent:
os.makedirs(parent, exist_ok=True)

root = logging.getLogger()
for h in root.handlers:
if isinstance(h, logging.FileHandler):
if os.path.abspath(getattr(h, "baseFilename", "")) == path:
return

fh = logging.FileHandler(path, mode="a", encoding="utf-8")
fh.setFormatter(logging.Formatter(_LOG_FORMAT))
fh.setLevel(root.level)
root.addHandler(fh)


def parse_base_args(
parser: Optional[argparse.ArgumentParser] = None,
) -> argparse.ArgumentParser:
"""
Create argument parser with common deployment arguments.

Args:
parser: Optional existing ArgumentParser to add arguments to

Returns:
ArgumentParser with deployment arguments
"""
if parser is None:
parser = argparse.ArgumentParser(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why parser can be None?

description="Deploy model to ONNX/TensorRT",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)

parser.add_argument("deploy_cfg", help="Deploy config path")
parser.add_argument("model_cfg", help="Model config path")
# Optional overrides
parser.add_argument(
"--log-level",
default="INFO",
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
help="Logging level",
)

return parser
101 changes: 101 additions & 0 deletions deployment/cli/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""
Single deployment entrypoint.

Usage:
python -m deployment.cli.main <project> <deploy_cfg.py> <model_cfg.py> [project-specific args]
"""

from __future__ import annotations

import argparse
import importlib
import pkgutil
import sys
import traceback
from typing import List

import deployment.projects as projects_pkg
from deployment.cli.args import parse_base_args
from deployment.projects.registry import project_registry


def _discover_project_packages() -> List[str]:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sequence instead of List

"""Discover project package names under deployment.projects (without importing them)."""

names: List[str] = []
for mod in pkgutil.iter_modules(projects_pkg.__path__):
if not mod.ispkg:
continue
if mod.name.startswith("_"):
continue
names.append(mod.name)
return sorted(names)


def _import_and_register_project(project_name: str) -> None:
"""Import project package, which should register itself into project_registry."""
importlib.import_module(f"deployment.projects.{project_name}")


def build_parser() -> argparse.ArgumentParser:
"""Build the deployment CLI parser.

This discovers `deployment.projects.<name>` bundles, imports them to trigger
registration into ``deployment.projects.registry.project_registry``, then creates a
subcommand per registered project.
"""
parser = argparse.ArgumentParser(
description="AWML Deployment CLI",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)

subparsers = parser.add_subparsers(dest="project", required=True)

# Discover projects and import them so they can contribute args.
failed_projects: List[str] = []
for project_name in _discover_project_packages():
try:
_import_and_register_project(project_name)
except Exception as e:
tb = traceback.format_exc()
failed_projects.append(f"- {project_name}: {e}\n{tb}")
continue

try:
adapter = project_registry.get(project_name)
except KeyError:
continue

sub = subparsers.add_parser(project_name, help=f"{project_name} deployment")
parse_base_args(sub) # adds deploy_cfg, model_cfg, --log-level
adapter.add_args(sub)
sub.set_defaults(_adapter_name=project_name)

if not project_registry.list_projects():
details = "\n".join(failed_projects) if failed_projects else "(no project packages discovered)"
raise RuntimeError(
"No deployment projects were registered. This usually means project imports failed.\n" f"{details}"
)

return parser


def main(argv: List[str] | None = None) -> int:
"""CLI entrypoint.

Args:
argv: Optional argv list (without program name). If None, uses `sys.argv[1:]`.

Returns:
Process exit code (0 for success).
"""
argv = sys.argv[1:] if argv is None else argv
parser = build_parser()
args = parser.parse_args(argv)

adapter = project_registry.get(args._adapter_name)
return adapter.run(args)


if __name__ == "__main__":
raise SystemExit(main())
4 changes: 4 additions & 0 deletions deployment/configs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""Deployment configuration package (enums, schema, base container).

Import from concrete modules, e.g. ``deployment.configs.base``, ``deployment.configs.schema``, ``deployment.configs.enums``.
"""
Loading