Compare commits
2 Commits
2618b30d40
...
717257dd75
| Author | SHA1 | Date | |
|---|---|---|---|
| 717257dd75 | |||
| 75255b37d0 |
40
README.md
40
README.md
@@ -1,4 +1,4 @@
|
|||||||
# qai-cli
|
# qc-cli
|
||||||
|
|
||||||
A CLI for the Qualcomm model MLOps pipeline — browse and download models from Qualcomm AI Hub, fine-tune them on custom datasets using SageMaker, validate inference, and prepare artifacts for Qualcomm hardware deployment.
|
A CLI for the Qualcomm model MLOps pipeline — browse and download models from Qualcomm AI Hub, fine-tune them on custom datasets using SageMaker, validate inference, and prepare artifacts for Qualcomm hardware deployment.
|
||||||
|
|
||||||
@@ -6,40 +6,40 @@ A CLI for the Qualcomm model MLOps pipeline — browse and download models from
|
|||||||
|
|
||||||
- Python 3.13+
|
- Python 3.13+
|
||||||
- [uv](https://docs.astral.sh/uv/getting-started/installation/)
|
- [uv](https://docs.astral.sh/uv/getting-started/installation/)
|
||||||
- AWS account with credentials configured (`aws configure`) when using `qai-cli infra`
|
- AWS account with credentials configured (`aws configure`) when using `qc-cli infra`
|
||||||
- AWS CDK CLI (`npm install -g aws-cdk`) when using `qai-cli infra setup` or `qai-cli infra destroy`
|
- AWS CDK CLI (`npm install -g aws-cdk`) when using `qc-cli infra setup` or `qc-cli infra destroy`
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone <repo>
|
git clone <repo>
|
||||||
cd qai-cli
|
cd qc-cli
|
||||||
uv sync
|
uv sync
|
||||||
```
|
```
|
||||||
|
|
||||||
Run commands with `uv run qai-cli <command>` or activate the venv first:
|
Run commands with `uv run qc-cli <command>` or activate the venv first:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
qai-cli --help
|
qc-cli --help
|
||||||
```
|
```
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Create config.yaml in the current directory
|
# 1. Create config.yaml in the current directory
|
||||||
qai-cli init
|
qc-cli init
|
||||||
|
|
||||||
# 2. Edit config.yaml — at minimum set s3.bucket and sagemaker.role_name
|
# 2. Edit config.yaml — at minimum set s3.bucket and sagemaker.role_name
|
||||||
|
|
||||||
# 3. Provision AWS infrastructure (S3 bucket + SageMaker IAM role).
|
# 3. Provision AWS infrastructure (S3 bucket + SageMaker IAM role).
|
||||||
# This is the step that requires the AWS CDK CLI.
|
# This is the step that requires the AWS CDK CLI.
|
||||||
qai-cli infra setup
|
qc-cli infra setup
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
`qai-cli init` writes a `config.yaml` in the current directory. The fields you must fill in before using the tool:
|
`qc-cli init` writes a `config.yaml` in the current directory. The fields you must fill in before using the tool:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
aws:
|
aws:
|
||||||
@@ -50,7 +50,7 @@ s3:
|
|||||||
bucket: your-unique-bucket-name
|
bucket: your-unique-bucket-name
|
||||||
|
|
||||||
sagemaker:
|
sagemaker:
|
||||||
role_name: qai-cli-sagemaker-role
|
role_name: qc-cli-sagemaker-role
|
||||||
```
|
```
|
||||||
|
|
||||||
To provision an MLflow tracking server, set:
|
To provision an MLflow tracking server, set:
|
||||||
@@ -74,21 +74,21 @@ mlflow:
|
|||||||
### `init`
|
### `init`
|
||||||
|
|
||||||
```
|
```
|
||||||
qai-cli init Write config.yaml
|
qc-cli init Write config.yaml
|
||||||
qai-cli init --output <path> Write config to a custom path
|
qc-cli init --output <path> Write config to a custom path
|
||||||
qai-cli init --force Overwrite an existing config file
|
qc-cli init --force Overwrite an existing config file
|
||||||
```
|
```
|
||||||
|
|
||||||
### `infra`
|
### `infra`
|
||||||
|
|
||||||
```
|
```
|
||||||
qai-cli infra setup Deploy the CDK stack
|
qc-cli infra setup Deploy the CDK stack
|
||||||
qai-cli infra setup --no-bootstrap Deploy without running CDK bootstrap
|
qc-cli infra setup --no-bootstrap Deploy without running CDK bootstrap
|
||||||
qai-cli infra setup --cloudformation-execution-policy <arn> Set CDK bootstrap execution policy ARN
|
qc-cli infra setup --cloudformation-execution-policy <arn> Set CDK bootstrap execution policy ARN
|
||||||
qai-cli infra status Show CDK stack/resource status
|
qc-cli infra status Show CDK stack/resource status
|
||||||
qai-cli infra destroy Destroy stack, retaining S3 data
|
qc-cli infra destroy Destroy stack, retaining S3 data
|
||||||
qai-cli infra destroy --yes Destroy stack without confirmation
|
qc-cli infra destroy --yes Destroy stack without confirmation
|
||||||
qai-cli infra destroy --delete-bucket-data Destroy stack and delete S3 data
|
qc-cli infra destroy --delete-bucket-data Destroy stack and delete S3 data
|
||||||
```
|
```
|
||||||
|
|
||||||
## AWS permissions required
|
## AWS permissions required
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ requires = ["hatchling"]
|
|||||||
build-backend = "hatchling.build"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "qai-cli"
|
name = "qc-cli"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "CLI for SageMaker ONNX training and Qualcomm AI Hub optimization"
|
description = "CLI for SageMaker ONNX training and Qualcomm AI Hub optimization"
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
@@ -17,7 +17,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
qai-cli = "src.main:app"
|
qc-cli = "src.main:app"
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
[tool.hatch.build.targets.wheel]
|
||||||
packages = ["src"]
|
packages = ["src"]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ def load_config(path: str = "config.yaml") -> Config:
|
|||||||
config_path = Path(path)
|
config_path = Path(path)
|
||||||
if not config_path.exists():
|
if not config_path.exists():
|
||||||
raise FileNotFoundError(
|
raise FileNotFoundError(
|
||||||
f"Config file not found: {config_path}. Run 'qai-cli init' to create one."
|
f"Config file not found: {config_path}. Run 'qc-cli init' to create one."
|
||||||
)
|
)
|
||||||
with open(config_path) as f:
|
with open(config_path) as f:
|
||||||
data = yaml.safe_load(f)
|
data = yaml.safe_load(f)
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Literal
|
from typing import Literal
|
||||||
|
|
||||||
from mypy_boto3_s3.literals import BucketLocationConstraintType
|
from mypy_boto3_s3.literals import BucketLocationConstraintType
|
||||||
from mypy_boto3_sagemaker.literals import TrainingInstanceTypeType
|
|
||||||
from pydantic import BaseModel, Field, model_validator
|
from pydantic import BaseModel, Field, model_validator
|
||||||
|
|
||||||
|
|
||||||
@@ -24,23 +23,13 @@ class AwsConfig(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class S3Config(BaseModel):
|
class S3Config(BaseModel):
|
||||||
bucket: str = "my-onnx-bucket"
|
bucket: str = "my-qc-mlops-bucket"
|
||||||
data_prefix: str = "data/"
|
data_prefix: str = "data/"
|
||||||
model_prefix: str = "models/"
|
model_prefix: str = "models/"
|
||||||
|
|
||||||
|
|
||||||
class TrainingConfig(BaseModel):
|
|
||||||
instance_type: TrainingInstanceTypeType = "ml.m5.xlarge"
|
|
||||||
instance_count: int = 1
|
|
||||||
image_uri: str = ""
|
|
||||||
entry_point: str | None = None
|
|
||||||
source_dir: str | None = None
|
|
||||||
hyperparameters: dict[str, Any] = Field(default_factory=dict)
|
|
||||||
|
|
||||||
|
|
||||||
class SageMakerConfig(BaseModel):
|
class SageMakerConfig(BaseModel):
|
||||||
role_name: str = "qai-cli-sagemaker-role"
|
role_name: str = "qc-cli-sagemaker-role"
|
||||||
training: TrainingConfig = Field(default_factory=TrainingConfig)
|
|
||||||
|
|
||||||
|
|
||||||
class MlflowConfig(BaseModel):
|
class MlflowConfig(BaseModel):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import json
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
INFRA_STATE_FILE = ".qai-cli-infra.json"
|
INFRA_STATE_FILE = ".qc-cli-infra.json"
|
||||||
|
|
||||||
|
|
||||||
def state_path(config_dir: str) -> Path:
|
def state_path(config_dir: str) -> Path:
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from src.commands import infra
|
|||||||
from src.config import Config
|
from src.config import Config
|
||||||
|
|
||||||
app = typer.Typer(
|
app = typer.Typer(
|
||||||
help="qai-cli: End-to-end model managment for Qualcomm AI Hub.",
|
help="qc-cli: End-to-end model managment for Qualcomm AI Hub.",
|
||||||
no_args_is_help=True,
|
no_args_is_help=True,
|
||||||
)
|
)
|
||||||
app.add_typer(infra.app, name="infra")
|
app.add_typer(infra.app, name="infra")
|
||||||
@@ -33,7 +33,4 @@ def init(
|
|||||||
yaml.safe_dump(config.model_dump(mode="json"), f, sort_keys=False)
|
yaml.safe_dump(config.model_dump(mode="json"), f, sort_keys=False)
|
||||||
|
|
||||||
console.print(f"[green]✓[/green] Config written to [bold]{dest}[/bold]")
|
console.print(f"[green]✓[/green] Config written to [bold]{dest}[/bold]")
|
||||||
console.print(
|
console.print("Edit it (especially [cyan]s3.bucket[/cyan]) before running other commands.")
|
||||||
"Edit it (especially [cyan]s3.bucket[/cyan] and [cyan]sagemaker.training.image_uri[/cyan]) "
|
|
||||||
"before running other commands."
|
|
||||||
)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user