# 컴파일 설정

[첫 컴파일](first_compile.md)에서는 모델에서 MXQ까지의 최단 경로를 보여 주었습니다. 이 장에서는 컴파일 설정으로 해당 경로를 제어하는 방법을 설명합니다.

qb Compiler에 설정을 전달하는 방법은 세 가지입니다.

- **설정 프리셋** — 모델 계열에 맞는 기본 제공 시작점
- **설정 파일** — 컴파일 설정이 담긴 JSON 또는 YAML 파일
- **Python 하위 설정 객체** — Python API에 전달하는 타입 지정 설정 객체

일반적인 모델 계열에는 프리셋을, 반복 가능한 빌드에는 설정 파일을, 스크립트 작업 흐름에는 Python 하위 설정 객체를 사용합니다.

(config-presets)=

## 설정 프리셋

프리셋은 자주 사용하는 모델 계열을 위해 미리 정의된 설정 모음입니다. 캘리브레이션, 양자화, 전처리 등 모델 계열별 기본값을 이미 포함하고 있어 모든 필드를 직접 지정할 필요가 없습니다.

설치된 패키지에서 사용할 수 있는 프리셋 목록을 확인합니다.

```bash
QBCOMPILER_JSONL=1 python -m qbcompiler presets
```

(using-a-preset)=

### 프리셋 사용법

CLI에서는 `--config-preset`을 전달합니다.

```bash
python -m qbcompiler compile \
  --model resnet50.onnx \
  --backend onnx \
  --target-device regulus-rb \
  --config-preset classification \
  --calib-data-path ./calib_resnet50 \
  --output resnet50.mxq
```

Python에서는 `config_preset`을 전달합니다.

```python
from qbcompiler import mxq_compile

mxq_compile(
    model="resnet50.onnx",
    backend="onnx",
    target_device="regulus-rb",
    config_preset="classification",
    calib_data_path="./calib_resnet50",
    save_path="resnet50.mxq",
)
```

프리셋은 시작점이지 모델 식별자가 아닙니다. 프리셋을 선택해도 올바른 모델 경로, 백엔드, target device, 입력 정보, 캘리브레이션 데이터는 별도로 제공해야 합니다. 모델 계열별 프리셋 활용법은 [비전 모델](vision.md)과 [트랜스포머 모델](transformer.md)을 참고합니다. 전체 프리셋 목록과 각 프리셋이 설정하는 값은 {ref}`참조 — 프리셋 목록 <preset-list>`을 참고합니다.

(dump-config-generate-a-config-template)=

## dump-config: 설정 템플릿 생성

`dump-config`는 `CompileConfig`의 모든 필드와 기본값을 JSON 또는 YAML 파일로 출력합니다. 사용 가능한 모든 필드를 확인하거나, 프리셋이 어떤 값을 변경하는지 비교할 때 유용합니다.

(generate-a-default-template)=

### 기본 템플릿 생성

```bash
python -m qbcompiler dump-config --output compile_config.json
```

(generate-a-preset-based-template)=

### 프리셋 기반 템플릿 생성

```bash
python -m qbcompiler dump-config --preset yolo_640 --output yolo_640_config.yaml
```

출력 형식은 파일 확장자로 결정됩니다. `.yaml` 또는 `.yml`이면 YAML, 그 외에는 JSON으로 출력합니다.

(workflow-dump-edit-compile)=

### 작업 흐름: dump → 편집 → 컴파일

1. 모델 계열에 맞는 프리셋에서 템플릿을 생성합니다.
2. 파일을 열고 덮어쓸 필드만 수정합니다.
3. 수정한 파일을 `--compile-config`로 `compile` 또는 `quantize`에 전달합니다.

```bash
# 1. 생성
python -m qbcompiler dump-config --preset classification --output my_config.yaml

# 2. my_config.yaml 편집 (calibration, bit 설정 등 수정)

# 3. 편집한 config로 컴파일
python -m qbcompiler compile \
  --model resnet50.onnx \
  --backend onnx \
  --target-device regulus-rb \
  --compile-config my_config.yaml \
  --calib-data-path ./calib_resnet50 \
  --output resnet50.mxq
```

자동화에 설정 파일을 사용하기 전에, 생성한 템플릿과 기본값을 비교하여 프리셋에서 온 값과 직접 수정한 값을 확인합니다.

(config-save-path-record-the-config-a-build-used)=

## config-save-path: 빌드가 실제로 사용한 설정 기록

`dump-config`는 프리셋이나 기본값에 무엇이 들어 있는지 보여줍니다. `--config-save-path`는
다른 질문에 답합니다. 아래 우선순위가 프리셋과 설정 파일 중 하나를 고르고 그 위에
하위 설정 객체와 명시적 인자가 적용된 뒤,
*이번* 빌드가 실제로 무엇을 가지고 실행되었는가입니다.

qbcompiler 1.3부터 `quantize`와 `compile`에서 사용할 수 있습니다.

```bash
python -m qbcompiler compile \
  --model resnet50.onnx \
  --backend onnx \
  --target-device regulus-rb \
  --config-preset classification \
  --calib-data-path ./calib_resnet50 \
  --output resnet50.mxq \
  --config-save-path resnet50_used_config.yaml
```

```python
qbcompiler.mxq_compile(
    model="resnet50.onnx",
    target_device="regulus-rb",
    calib_data_path="./calib_resnet50",
    save_path="resnet50.mxq",
    config_preset="classification",
    config_save_path="resnet50_used_config.yaml",
)
```

이 파일에는 이 페이지 아래 [설정 해석 우선순위](#설정-해석-우선순위) 절의 모든 단계가 적용되고
모든 하위 설정이 구체화된 정규화된 `CompileConfig`가 들어갑니다. 형식은 확장자를 따릅니다.
`.yaml` 또는 `.yml`이면 YAML, 그 외에는 JSON입니다. 상위 디렉터리는 자동으로 생성됩니다.

자동화에서 유용한 이유는 두 가지입니다.

- 컴파일이 시작되기 **전에** 기록되므로, 실패하거나 중단된 실행에서도 기록이 남습니다.
  설정을 확인하고 싶은 상황이 바로 그때입니다.
- 이 파일을 그대로 `--compile-config` / `compile_config=`로 넘기면 동일한 컴파일을
  재현할 수 있습니다.

`compile` 파이프라인에서는 전체 `CompileConfig`를 들고 있는 quantize 단계가 파일을 씁니다.
parse 단계는 `device`와 `cpu_offload`만 해석합니다. 기록할 수 없는 위치를 지정하면 내부
오류가 아니라 해당 경로를 명시한 `OUTPUT_WRITE_ERROR`로 실패합니다.

(custom-config-file)=

## 사용자 설정 파일

컴파일 설정 파일은 동일한 컴파일을 반복해야 할 때 유용합니다. 모델 내보내기 스크립트와 함께 버전 관리 시스템에 보관합니다.

(cli-usage)=

### CLI에서 사용

`--compile-config`로 파일 경로를 전달합니다.

```bash
python -m qbcompiler compile \
  --model model.onnx \
  --backend onnx \
  --target-device regulus-rb \
  --compile-config my_config.json \
  --calib-data-path ./calib \
  --output model.mxq
```

(python-usage)=

### Python에서 사용

`compile_config` 인자에 파일 경로를 전달합니다. 이 인자는 `CompileConfig` 객체도 받습니다.

```python
from qbcompiler import mxq_compile

mxq_compile(
    model="resnet50.onnx",
    target_device="regulus-rb",
    calib_data_path="./calib_resnet50",
    save_path="resnet50.mxq",
    backend="onnx",
    compile_config="resnet50_compile_config.json",
)
```

설정 파일에는 컴파일 설정만 포함합니다. 모델 경로, 캘리브레이션 데이터 경로, target device, 백엔드, 출력 경로는 일반 CLI 또는 Python 인자로 전달합니다. 같은 필드를 포함하면 JSON과 YAML은 서로 바꿔 사용할 수 있습니다. 설정 파일에는 지원되는 `CompileConfig` 필드만 넣을 수 있으며, `$preset`, `$description`, `$skipValidation` 같은 메타데이터 키를 포함해서는 안 됩니다.

프리셋과 설정 파일은 함께 쌓이는 것이 아니라 둘 중 하나를 고르는 것입니다. 둘 다 주면 프리셋이 쓰이고 파일은 무시되며, 경고도 나오지 않습니다. 프리셋 값에 자기 값을 더하고 싶다면 `dump-config --preset <이름>`으로 시작해 결과를 편집하세요.

생성된 설정 파일을 편집할 때 `inferenceScheme`은 해당 MXQ로 사용할 수 있는 런타임 코어 모드를 결정합니다. ARIES의 코어 모드에는 `single`, `multi`, `global4`, `global8`가 존재합니다. 지원 값과 상세 코어 모드 링크는 [참조 — inferenceScheme](reference.md#inferencescheme)에서 확인할 수 있습니다.

전체 `CompileConfig` 스키마와 필드 설명은 {ref}`참조 — CompileConfig 스키마 <compileconfig-schema>`를 참고합니다.

(python-sub-config-objects)=

## Python 하위 설정 객체

Python API는 세부 영역마다 타입이 지정된 하위 설정 객체를 제공합니다. 재사용 가능한 컴파일 스크립트를 작성할 때 유용합니다.

```python
from qbcompiler import mxq_compile
from qbcompiler.configs import CalibrationConfig, BitConfig

mxq_compile(
    model="resnet50.onnx",
    backend="onnx",
    target_device="regulus-rb",
    calib_data_path="./calib_resnet50",
    save_path="resnet50.mxq",
    config_preset="classification",
    calibration_config=CalibrationConfig(mode=1, output=0),
    bit_config=BitConfig(
        transformer=BitConfig.Transformer(
            weight=BitConfig.Transformer.Weight(
                query=8, key=8, value=8, output=8, head=8, router=8,
                ffn=8,  # 하위 레이어별 지정: BitConfig.Transformer.Weight.Ffn(up=8, gate=8, down=8)
            ),
        ),
    ),
)
```

하위 설정 객체는 프리셋 또는 설정 파일의 해당 섹션을 덮어씁니다. 프리셋의 모델 계열 기본값을 유지하면서 특정 양자화나 LLM 설정만 코드에서 조정할 수 있습니다.

사용 가능한 하위 설정 객체로는 `CalibrationConfig`, `BitConfig`, `LlmConfig`, `HessianQuantConfig`, `BiasCorrectionConfig`, `ModConfig`, `EquivalentTransformationConfig`, `SearchWeightScaleConfig`, `Uint8InputConfig`, `PreprocessingConfig`, `SaveSampleConfig`, `ResourceManagementConfig`, `ExtraOutputConfig`가 있으며, 모두 대응하는 `*_config` 인자를 가집니다. `extra_output_config`는 키워드 전용 인자입니다. 각 양자화 하위 설정의 역할과 튜닝 순서는 {ref}`모델 양자화 — 양자화 설정 <quantization-configuration>`을 참고합니다.

qbcompiler 1.4에서 `LayerBiasCorrectionConfig`의 이름이 `BiasCorrectionConfig`로 바뀌었습니다. 대응하는 인자는 `bias_correction` / `bias_correction_config`이고, 설정 파일 키는 `advancedQuantization.layerBiasCorrection` 대신 `advancedQuantization.biasCorrection`입니다. 1.4부터 bias 보정은 기본으로 켜져 있으므로, 끄려면 `bias_correction=False`를 넘깁니다. 속성은 `applyLayers`와 `excludeLayers`이며, `numSamples`, `iterations`, `correctionRate`는 더 이상 없습니다. `CompileConfig`는 모르는 키를 거부하므로, `layerBiasCorrection`이 남아 있는 1.3 설정 파일은 키 이름을 바꿔야 로드됩니다.

(exporting-intermediate-activations)=

### 중간 활성값 내보내기

qbcompiler 1.4부터 `ExtraOutputConfig`로 이름을 지정한 중간 레이어를 모델의 원래 출력과 함께 MXQ 출력에 추가할 수 있습니다. NPU에서 나온 중간 활성값을 원본 모델과 비교할 때 사용합니다.

```python
from qbcompiler import mxq_compile
from qbcompiler.configs import ExtraOutputConfig

mxq_compile(
    model="resnet50.onnx",
    backend="onnx",
    target_device="regulus-rb",
    calib_data_path="./calib_resnet50",
    save_path="resnet50.mxq",
    extra_output_config=ExtraOutputConfig(apply=True, layers=["layer3_out"]),
)
```

설정 객체에서는 `CompileConfig().with_extra_output(layers=[...])`로 같은 설정을 할 수 있고, 설정 파일 키는 `extraOutput`(`apply`, `layers`)입니다. 출력은 양자화가 끝난 뒤에 추가되므로, 양자화 결과는 출력을 추가하지 않은 빌드와 같습니다. 레이어 이름은 원본 모델이 아니라 fusion 이후 그래프의 이름과 비교합니다. 없는 이름이나 모델 입력 이름을 지정하면 오류가 나고, 이미 출력인 레이어는 그대로 둡니다.

(config-resolution-priority)=

## 설정 해석 우선순위

같은 설정이 여러 위치에 있을 때 다음 우선순위로 적용됩니다 (높은 쪽이 우선).

1. CLI 또는 Python API에서 명시한 인자
2. 개별 하위 설정 객체
3. `compile_config` 파일 **또는** `config_preset` — 주어진 쪽. 둘 다 주면 프리셋이 이기고 파일은 읽히지 않습니다
4. `CompileConfig` 기본값

출발점은 프리셋이나 설정 파일 중 하나로 정하고, 실험용 값은 CLI 또는 Python 호출에서 덮어쓰는 방식으로 관리합니다.

최종 적용값이 확실하지 않을 때는 빌드에 `--config-save-path`를 추가하고 기록된 파일을 확인합니다.
