diff --git a/examples/ai-hub/README.md b/examples/ai-hub/README.md index dce4bd1..e0d865f 100644 --- a/examples/ai-hub/README.md +++ b/examples/ai-hub/README.md @@ -13,18 +13,10 @@ This example takes the ONNX model produced by the SageMaker training example and Run the training example first and wait for it to complete: ```bash -bash examples/training/run_training.sh --config config.yaml --wait +examples/training/run_training.sh --wait ``` -If the dataset is already uploaded to S3, use: - -```bash -bash examples/training/run_training.sh --config config.yaml --skip-upload --wait -``` - -The training artifact must contain a static-shape `model.onnx`. The training example exports an input named `input` with shape `1x3x160x160`. - -Your `config.yaml` must include AI Hub settings: +The `config.yaml` file must include AI Hub settings: ```yaml aihub: @@ -36,16 +28,20 @@ aihub: output_dir: build/qai-hub ``` -You also need local Qualcomm AI Hub SDK authentication configured. +Finally, the user needs to authenticate with Qualcomm AI Hub using: + +```bash +qai-hub configure --api_token +``` ## Prepare Inputs AI Hub does not consume the raw JPG training images directly. It needs NumPy tensors that match the ONNX model input shape and preprocessing. -Generate calibration and validation inputs: +To generate calibration and validation inputs: ```bash -uv run python examples/ai-hub/prepare_inputs.py +python examples/ai-hub/prepare_inputs.py ``` This writes: @@ -61,58 +57,23 @@ The script applies the same image preprocessing used by the training example: - convert to channel-first `1x3x160x160` - normalize with ImageNet mean and standard deviation -Useful options: +## Upload Model to Qualcomm Workbench + +The model can be uploaded to Qualcomm Workbench using: ```bash -uv run python examples/ai-hub/prepare_inputs.py \ - --dataset-dir examples/training/data/flower_photos_sagemaker \ - --calibration-dir examples/training/data/aihub_calibration \ - --input-file examples/training/data/inputs.npz \ - --samples 16 +qc-cli ai-hub upload examples/training/data/aihub_calibration examples/training/data/inputs.npz ``` -## Run AI Hub +The first argument is the calibration path for the model and the second argument is the input file, both of which were created by the `prepare_inputs.py` script. For more details, add `--help` after the `upload` command. -After training completes and inputs are prepared: +The `upload` command runs the following commands in order: +1. `qc-cli ai-hub quantize` +2. `qc-cli ai-hub compile` +3. `qc-cli ai-hub validate` +4. `qc-cli ai-hub profile` +Finally the user can download the model from AI Workbench using the command ```bash -bash examples/ai-hub/run_ai_hub.sh --config config.yaml +qc-cli ai-hub download ``` - -By default, the script uses the last SageMaker training job recorded in `.qc-cli.json`. It downloads that job's `model.tar.gz`, extracts `model.onnx`, runs the AI Hub workflow, and downloads the compiled artifact. - -To use a specific training job: - -```bash -bash examples/ai-hub/run_ai_hub.sh \ - --config config.yaml \ - --from-job qc-cli-YYYYMMDD-HHMMSS -``` - -To resume from a later Workbench step: - -```bash -bash examples/ai-hub/run_ai_hub.sh \ - --config config.yaml \ - --from-step validate -``` - -To skip downloading the compiled artifact: - -```bash -bash examples/ai-hub/run_ai_hub.sh \ - --config config.yaml \ - --skip-download -``` - -## Troubleshooting - -If AI Hub reports dynamic input shapes, rerun training with the current training source. AI Hub quantization requires the exported ONNX model to use static input shapes. - -If `run_ai_hub.sh` reports missing calibration or input files, run: - -```bash -uv run python examples/ai-hub/prepare_inputs.py -``` - -If validation fails with a missing input name, make sure `config.yaml` and the generated `.npz` both use `input` as the input name. diff --git a/examples/ai-hub/prepare_inputs.py b/examples/ai-hub/prepare_inputs.py old mode 100755 new mode 100644 diff --git a/examples/ai-hub/run_ai_hub.sh b/examples/ai-hub/run_ai_hub.sh deleted file mode 100755 index 07fcb49..0000000 --- a/examples/ai-hub/run_ai_hub.sh +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -CONFIG_PATH="config.yaml" -CALIBRATION_PATH="examples/training/data/aihub_calibration" -INPUT_FILE="examples/training/data/inputs.npz" -FROM_STEP="quantize" -FROM_JOB="" -MODEL_S3_URI="" -ONNX_PATH="" -INPUT_NAME="" -DOWNLOAD=true -OUTPUT_PATH="" - -usage() { - cat <&2 - usage >&2 - exit 1 - ;; - esac -done - -if [[ ! -f "${CONFIG_PATH}" ]]; then - echo "Config not found: ${CONFIG_PATH}" >&2 - exit 1 -fi - -case "${FROM_STEP}" in - quantize|compile|validate|profile) - ;; - *) - echo "--from-step must be one of: quantize, compile, validate, profile" >&2 - exit 1 - ;; -esac - -if [[ ! -e "${CALIBRATION_PATH}" ]]; then - echo "Calibration path not found: ${CALIBRATION_PATH}" >&2 - echo "Pass --calibration with a .npz file or directory of .npy samples." >&2 - exit 1 -fi - -if [[ ! -f "${INPUT_FILE}" ]]; then - echo "Input file not found: ${INPUT_FILE}" >&2 - echo "Pass --input-file with a validation .npz or .npy file." >&2 - exit 1 -fi - -run() { - echo "+ $*" - "$@" -} - -UPLOAD_ARGS=( - "${CALIBRATION_PATH}" - "${INPUT_FILE}" - --from-step "${FROM_STEP}" - --config "${CONFIG_PATH}" -) - -if [[ -n "${FROM_JOB}" ]]; then - UPLOAD_ARGS+=(--from-job "${FROM_JOB}") -fi - -if [[ -n "${MODEL_S3_URI}" ]]; then - UPLOAD_ARGS+=(--model-s3-uri "${MODEL_S3_URI}") -fi - -if [[ -n "${ONNX_PATH}" ]]; then - UPLOAD_ARGS+=(--onnx-path "${ONNX_PATH}") -fi - -if [[ -n "${INPUT_NAME}" ]]; then - UPLOAD_ARGS+=(--input-name "${INPUT_NAME}") -fi - -run uv run qc-cli ai-hub upload "${UPLOAD_ARGS[@]}" - -if [[ "${DOWNLOAD}" == false ]]; then - exit 0 -fi - -DOWNLOAD_ARGS=(--config "${CONFIG_PATH}") -if [[ -n "${OUTPUT_PATH}" ]]; then - DOWNLOAD_ARGS+=(--output "${OUTPUT_PATH}") -fi - -run uv run qc-cli ai-hub download "${DOWNLOAD_ARGS[@]}"