--- name: quark-onnx-autosearch-pro description: > L3 recipe that runs `quark.onnx.AutoSearchPro` end-to-end on a user `.onnx` model: intake → preset selection (or custom search space) → calibration / eval data reader → standalone autosearch script generation → confirmed execution → best_params reporting. Wraps the Optuna-driven hyperparameter search exposed in `quark/onnx/quantization/auto_search/auto_search_pro.py`. Use when the user wants to "auto search", "tune quantization", "find best quant config", "sweep AdaRound/AdaQuant", "two-stage search", or pick `ADVANCED_SEARCH` / `XINT8_SEARCH` / `A8W8_SEARCH` / `A16W8_SEARCH` for an ONNX model. Not for single-shot PTQ (use `quark-onnx-ptq`). Not for safetensors models (use `quark-torch-ptq`). layer: l3-recipes backend: onnx primary_artifact: run_manifest.yaml source_knowledge: - quark/onnx/quantization/auto_search/auto_search_pro.py - quark/onnx/quantization/auto_search/qconfig_mapping.py - quark/onnx/quantization/auto_search/config_generator.py - quark/onnx/quantization/auto_search/utils.py - examples/onnx/auto_search/auto_search_pro_model.py - docs/source/onnx/user_guide_auto_search_pro.rst - tutorials/onnx/auto_search/onnx_auto_search_tutorial.ipynb - tutorials/onnx/ryzen_ai/auto_search_for_ryzen_ai/auto_search_yolov8/onnx_ryzen_ai_auto_search_yolov8_tutorial.ipynb --- # quark-onnx-autosearch-pro ## Purpose Drive Quark ONNX `AutoSearchPro` (Optuna-driven) on a `.onnx` model to discover the best quantization configuration — activation / weight specs, calibration method, CLE, AdaRound / AdaQuant hyperparameters — without hand-tuning. The recipe orchestrates intake, preset (or custom) search-space selection, reader construction, generation of a standalone autosearch script in the user's workspace, confirmed execution, and reporting of `best_params.json` plus Optuna study artifacts. Unlike single-shot PTQ this produces many candidate models, so preset and trial budget are explicit and the search is bounded. ## Inputs - Input `.onnx` model (with optional sibling `.onnx_data`). - Calibration data: folder of representative samples or a Python `CalibrationDataReader` class. Optional separate evaluation reader. - User goal: preset choice (`ADVANCED_SEARCH` / `XINT8_SEARCH` / `A8W8_SEARCH` / `A16W8_SEARCH` / custom dict), deployment target, search budget (`n_trials`, `n_jobs`, `two_stage_search`), and metric (built-in or custom callable). - `session_context.json` (`constraints.backend = "onnx"`), `env_context.json`, `workspace_context.json`, plus `onnx_install_result.json` and `quark_install_result.json`. **Optuna** must be importable (`pip install optuna`). ## Outputs: run_manifest.yaml Records the generated autosearch script path, the exact `python3` invocation, the preset name (or custom search-space hash), trial budget, Optuna study DB path, and the final `best_params.json` location. Side artifacts written by `AutoSearchPro` into `output_dir`: `auto_search.log`, `best_params.json`, `auto_search.db` (resumable Optuna study), `quantized_model_.onnx` per trial, and `opt_history.html` / `param_importance.html` when `plot_results=True`. Built in Step 4. Schema: [`run_manifest.schema.json`](../../../shared/contracts/run_manifest.schema.json) ## Interaction Flow 1. **Intake** — `quark-onnx-model-intake` → `model_analysis.json` 2. **Preset / search space** — pick preset or build custom → `quant_plan.json` (with `search_space` block + `n_trials`) 3. **Reader + evaluator** — confirm `CalibrationDataReader` and evaluator mode 4. **Manifest** — generate standalone autosearch script in user workspace + `run_manifest.yaml`; stop for user approval 5. **Execute** — run the confirmed script, report `best_params.json` ## CRITICAL RULES 1. **NEVER call `AutoSearchPro(...).run()` directly from this skill.** Generate a standalone script the user reviews first. Searches can take hours and write many `.onnx` files — user must opt in. 2. **NEVER skip preset confirmation.** Presets default to `optim_device = "cuda:0"`; surface device gaps before execution. 3. **NEVER silently fall back to CPU** when CUDA/ROCm was requested. Hand off to `quark-onnx-install` / `quark-onnx-debug`. 4. **NEVER write into the Quark repo.** Generated scripts go to the user's workspace, *not* under `examples/onnx/auto_search/` or `tutorials/onnx/auto_search/`. The shipped `examples/onnx/auto_search/auto_search_pro_model.py` is a template to read, not patch. 5. **Pre-check optuna.** `AutoSearchPro` imports it lazily; verify it imports in the user's env before writing the script. 6. **Bound the budget.** Refuse `n_trials > 200` without explicit user opt-in — one `.onnx` per trial. 7. **Validate custom search spaces** with `quark.onnx.quantization.auto_search.utils.validate_search_space`. If `n_trials > discrete_space_size` without continuous fields, AutoSearchPro auto-clamps — surface it instead of letting it happen quietly. See [`presets-reference.md`](presets-reference.md) for the preset table, deployment recommendations, custom-search-space rules, device gating snippet, evaluator modes, and sampler list. ## Required Artifact Flow ```text Step 1 (Intake) ──► model_analysis.json Step 2 (Preset/space) ──► quant_plan.json (search_space + n_trials) Step 3 (Reader) ──► (informs script body) Step 4 (Manifest) ──► run_manifest.yaml + user_workspace/_autosearch.py Step 5 (Execute) ──► best_params.json + auto_search.db + quantized_model_*.onnx ``` --- ## Step 1: Model Intake Hand off to `quark-onnx-model-intake`. Stop if QDQ nodes already exist — AutoSearchPro requires an unquantized float `.onnx`. Add one recipe-specific line to the summary: *"Search will produce ~N quantized .onnx files in `output_dir` — ensure ≥ N × free."* ### >>> CHECKPOINT 1: Confirm model analysis --- ## Step 2: Preset / Custom Search-Space Selection Pick a built-in preset or accept a user-supplied `search_space` dict. See [`presets-reference.md`](presets-reference.md) for the full preset table and deployment-target recommendations. For custom search spaces, run `validate_search_space(...)` in your head against the spec rules in the reference. Compute `discrete_space_size` and warn if `n_trials` would be clamped. ### Decision table to show the user | Decision | Default | Notes | |----------|---------|-------| | `search_space` source | preset name | `XINT8_SEARCH` for NPU CNN, `ADVANCED_SEARCH` for accuracy, etc. | | `search_algo` | `TPE` | also: `Random`, `CmaEs`, `GPS`, `NSGAII`, `QMC`, `Grid` | | `n_trials` | `20` | preset default; ~4 calib configs + 20 FastFT with `two_stage_search` | | `n_jobs` | `1` | parallel processes only when GPU memory allows | | `two_stage_search` | `True` | grid over calib first, then TPE over FastFinetune | | `search_metric` | `L2` | or `L1` / `cos` / `psnr` / `ssim`, or set `search_evaluator` | | `direction` | `minimize` | matches L2 distance | | `output_dir` | `./autosearch_output/` | holds trial `.onnx`, study DB, log | | `temp_dir` | `./autosearch_temp/` | float-model dumps for built-in evaluator | | `study_storage_db` | `auto_search.db` | resumable Optuna study | | `load_study_if_exists` | `True` | resume from interrupted runs | | `plot_results` | `False` | `True` → `opt_history.html` + `param_importance.html` | | device override | `cuda:0 → cpu` if no GPU | see device-gating snippet in reference | ### >>> CHECKPOINT 2: User confirms preset, `n_trials`, devices, metric --- ## Step 3: Calibration + Evaluation Reader Reader patterns mirror `quark-onnx-ptq-workflow` Step 3 (vision: `ImageDataReader`; LLM: tokenizer-driven). AutoSearchPro wraps the reader with `CachedDataReader` — one pass over data is enough. For evaluator mode (built-in metric vs. custom `search_evaluator(onnx_path) -> float`) and `direction` semantics, see [`presets-reference.md`](presets-reference.md). Pass a distinct `eval_data_reader` to score on a different slice; omit it to reuse calibration (AutoSearchPro warns). ### >>> CHECKPOINT 3: Confirm reader + evaluator mode --- ## Step 4: Manifest Generation Translate the confirmed plan into a runnable script in the user's workspace and a `run_manifest.yaml`. Do not write into the Quark repo. ### Actions 1. **Script path.** Choose `./_autosearch.py` in the user's working directory. Never under `examples/` or `tutorials/`. 2. **Pre-check optuna.** If `import optuna` fails in the user env, surface `pip install optuna` before writing the script. 3. **Build the script body.** Pieces: ```python # user_workspace/_autosearch.py from quark.onnx import AutoSearchPro from quark.onnx.quantization.auto_search import get_auto_search_config # from onnxruntime.quantization.calibrate import CalibrationDataReader # ... ImageDataReader / tokenizer-driven reader from Step 3 ... cfg = get_auto_search_config("XINT8_SEARCH") cfg["model_input"] = "./models/yolov8n.onnx" cfg["calib_data_reader"] = ImageDataReader("./calib_data", cfg["model_input"]) cfg["eval_data_reader"] = None cfg["output_dir"] = "./autosearch_output" cfg["temp_dir"] = "./autosearch_temp" cfg["n_trials"] = 20 cfg["n_jobs"] = 1 cfg["search_algo"] = "TPE" cfg["two_stage_search"] = True cfg["search_metric"] = "L2" cfg["direction"] = "minimize" cfg["study_storage_db"] = "auto_search.db" cfg["load_study_if_exists"] = True cfg["plot_results"] = True # Apply device override here if env has no CUDA/ROCm — see presets-reference.md if __name__ == "__main__": best = AutoSearchPro(cfg).run() print("Best params:", best) ``` If the user picked a custom search space, replace `cfg["search_space"]` instead of (or in addition to) using a preset. 4. **Write the script to disk** at the chosen path. Print the full body back to the user — never just say "generated a script". 5. **Build the command:** ```bash python3 ./yolov8n_autosearch.py 2>&1 | tee ./autosearch_output/run.stdout.log ``` 6. **Expected output layout:** ```text ./_autosearch.py (generated here) ./run_manifest.yaml (this recipe's manifest) ./autosearch_temp/ (float-model dumps; cleaned at end) ./autosearch_output/ ├── auto_search.log ├── auto_search.db (resumable Optuna study) ├── best_params.json (final answer) ├── quantized_model_*.onnx (one per trial) └── opt_history.html / param_importance.html (if plot_results=True) ``` 7. **Estimate cost.** From `model_analysis.json`: disk ≈ model_size × `n_trials`; flag if > 100 GB. Estimate per-trial wall-clock from CPU-vs-GPU + FastFinetune iter range so the user knows whether to walk away. ### >>> CHECKPOINT 4: Show script body, command, cost estimate; ask "shall I run this?" If the user declines or wants changes, return to Step 2 (preset/budget) or Step 3 (reader/evaluator) — never patch the script in place. --- ## Step 5: Execute AutoSearch Runs ONLY after explicit Step 4 confirmation. ### Actions 1. `mkdir -p ./autosearch_output ./autosearch_temp` 2. Run the script and stream the log. AutoSearchPro logs per-trial: ```text [Trial 7] Params: {'activation': 'Int8Spec', 'algorithms': 'adaround', ...} L2 distance is: 0.00012 ``` 3. After completion, verify: ```bash ls -lh ./autosearch_output/best_params.json ./autosearch_output/auto_search.db ``` 4. Read `best_params.json` and report a summary: trials run / budget, best trial index, best metric value, the resolved params dict, the winning `quantized_model_*.onnx` path, the study DB path (resumable), and the plot HTMLs if generated. 5. **Follow-ups:** hand off the winning `.onnx` to `quark-onnx-result-validator`; prune unwanted trial `.onnx` files if disk is tight; offer a continuation run with a tighter `search_space` around the winning region. ### Common failures and routing - `ModuleNotFoundError: optuna` → `pip install optuna`, restart. - `CUDAExecutionProvider not available` or custom-op library load failure (`BFPQuantizeDequantize`, `MXQuantizeDequantize`, `Extended*`) → `quark-onnx-install` / `quark-onnx-debug`; never silently swap to CPU. - OOM during AdaRound/AdaQuant → narrow `num_iterations` range, lower `data_size`, drop `batch_size`, or set `optim_device = ["cpu"]`. - Resumed run loaded an incompatible study → delete `auto_search.db` or pick a new `study_name`. - "n_trials clamped to discrete_space_size" → expected when search space has no continuous fields and is exhausted; informational. ## Recovery - If any upstream artifact is missing, stop and name the producer skill. - If the model is already QDQ-quantized, stop — AutoSearchPro requires unquantized input. - If the user wants to change preset / budget mid-run, return to Step 2 — do not patch the generated script. - If `optuna` cannot be installed, surface a clear blocker; there is no fallback search backend. - If the user pastes a Torch traceback or HuggingFace path, hand off to `quark-torch-router` and stop. ## See also - [`presets-reference.md`](presets-reference.md) — presets, custom-space rules, device gating, evaluator modes, samplers. - `quark-onnx-ptq` — single-shot PTQ alternative. - `quark-onnx-result-validator`, `quark-onnx-debug`, `quark-onnx-install`.