# 릴리즈 노트

## v1.3.0

**출시일:** 2026년 9월 10일<br>
**유형:** Minor

모델을 부분 단위로 컴파일하는 기능, provenance 기록으로 재현 가능해진 `.mblt`, 더 빠르고 가벼워진 HessianQuant, PATH에 등록되는 `qbcompiler` 명령을 제공합니다.

(added)=

### 추가

- **[Highlight]** **`model_part` / `model_part_options` — 모델을 부분 단위로 컴파일** — VLM처럼 여러 부분으로 구성된 모델은 하나의 그래프가 아니라 부분 단위로 컴파일합니다. `model_part`가 부분 이름(`"vision"`, `"language"`, `"encoder"` 등)을 지정하고, `model_part_options`가 그 부분에 필요한 추가 인자를 전달합니다. 부분을 하나만 선언한 모델은 `None`에서 자동으로 결정되고, 여러 개를 선언한 모델은 이름을 반드시 지정해야 합니다.

  ```python
  # 이 모델이 선언한 부분 확인
  from qbcompiler.model_dict.parser.patcher.parts import available_parts
  print(available_parts(model))

  qbcompiler.mblt_compile(
      model=model,
      mblt_save_path="audio.mblt",
      target_device="aries-rb",
      backend="torch",
      model_part="audio",
      model_part_options={"mel_frames": 100},
  )
  ```

  호출자를 대신해 Hugging Face 모델을 로드해주던 `hf_config` 인자를 대체합니다. 모델은 직접 로드해서 `model`로 넘기세요.

- **[Highlight]** **재현 가능한 `.mblt`와 모든 파일에 기록되는 provenance** — 파싱을 반복 가능하게 만드는 두 가지 변경입니다.

  먼저 파싱 단계에 시드가 적용됩니다. `ParserConfig.random_seed`는 그동안 죽은 설정이었습니다. 두 백엔드 파서 모두 값을 저장만 하고 읽지 않았고 값도 지정되지 않은 채였는데, 이 때문에 같은 명령을 두 번 실행해도 서로 다른 가중치 바이트가 기록될 수 있었습니다. `forward`에서 `torch.randn`을 호출하는 traced torch 모델은 그 값이 상수로 그래프에 박히고, ONNX 로더는 `feed_dict`가 없으면 `numpy.random`으로 더미 입력을 만들어내기 때문입니다. 이제 `random_seed`는 기본값 `12345`로 실제 적용됩니다. 모델 로드 시 `random`, `numpy.random`, `torch`에 시드를 적용한 뒤 호출자의 RNG 상태를 원래대로 복원합니다. `tf`, `tflite`, `torchscript`가 지나는 레거시 파서는 다른 상수로 시드를 겁니다.

  또한 모든 `.mblt`가 자신이 어떻게 만들어졌는지 기록합니다. qbcompiler와 mblt-graph의 커밋, 해석된 `ParserConfig`, `parse()` 입력(`dynamic_axes`와 `feed_dict` 지문), 페이로드를 바꾸는 쓰기 옵션, 그리고 원본 모델의 SHA-256(torch 모델은 Hugging Face 허브 리비전)입니다. 온디스크 포맷 변경은 아닙니다. 현재 포맷에서는 manifest 섹션에, 레거시 포맷에서는 model dictionary 안에 들어가므로 기존 리더는 영향을 받지 않습니다.

  ```bash
  qbcompiler info --mblt model.mblt
  ```

  ```python
  print(qbcompiler.read_provenance("model.mblt"))
  ```

  `read_provenance()`가 `None`을, `qbcompiler info`가 `null`을 내는 것은 기록이 없는 파일뿐입니다. provenance 도입 이전에 만들어졌거나 기록을 끄고 만든 경우입니다. 레거시 컨테이너도 기록을 담으며, manifest 섹션이 아니라 직렬화된 model dictionary 안에 들어갑니다. 확인할 수 없는 항목은 파싱을 실패시키는 대신 오류 문자열로 기록됩니다. 아무것도 기록하지 않으려면 `QBCOMPILER_PROVENANCE=0`을 설정하세요. 이 경우 원본 모델 해시 계산도 생략됩니다. 현재 형식의 `.mblt`로 만든 MXQ는 그 manifest를 그대로 담고, 여기에 target device와 확정된 양자화 설정이 함께 들어갑니다. 레거시 형식의 `.mblt`에는 manifest 섹션이 없으므로 그 MXQ에는 기록 대신 없는 이유가 남습니다.

- **[Highlight]** **더 빠르고 가벼워진 HessianQuant** — 누적된 Hessian을 어디에 어떤 형식으로 둘지 결정하는 두 개의 옵션이 추가되었습니다.

  ```python
  from qbcompiler.configs import HessianQuantConfig

  qbcompiler.mxq_compile(
      model="model.onnx",
      target_device="aries-rb",
      calib_data_path="calib",
      save_path="model.mxq",
      hessian_quant_config=HessianQuantConfig(
          apply=True,
          hessian_dtype="bf16",
          accumulation_device="gpu",
      ),
  )
  ```

  `hessian_dtype="bf16"`은 누적된 Hessian의 메모리 사용량을 절반으로 줄입니다. CPU에 있으면 호스트 RAM을, GPU에 있으면 VRAM을 아낍니다. 연산은 영향을 받지 않습니다. 배치별 matmul과 누적은 여전히 float32로 수행되고 solve 단계에서 누적기를 float32로 올리므로, bfloat16이 되는 것은 상주하는 누적기뿐입니다. expert FFN마다 Hessian을 갖는 MoE 모델에서 효과가 가장 큽니다.

  `accumulation_device="gpu"`는 레이어마다 배치마다 *d*×*d* 누적기 전체를 디바이스 밖으로 복사하는 대신 캘리브레이션 디바이스에서 바로 누적하며, 벤더 벤치마크 기준 3~5배 빠릅니다. 마지막 배치가 끝나는 즉시 Hessian을 호스트로 옮기므로 이후 컴파일 구간의 최대 VRAM은 늘지 않습니다. `"cpu"`는 캘리브레이션 중의 VRAM 자체를 억제하며 둘 중 느린 쪽입니다. **기본값은 `"cpu"`로 결정되므로**, HessianQuant를 켜고 디바이스를 지정하지 않은 컴파일은 느린 경로를 탑니다. 캘리브레이션 GPU에 여유가 있으면 `accumulation_device="gpu"`를 넘기세요. 기본값 `"auto"`는 이 컴파일이 VRAM에 쫓기는지를 이미 나타내고 있는 `resourceManagement.useGPUOnlyForCalibration` 설정을 따르되, 방향은 반대입니다. 이 설정은 *GPU를 캘리브레이션에만 쓴다*는 뜻이므로 기본값인 `true`에서는 `"auto"`가 `"cpu"`로, `false`에서는 `"gpu"`로 결정됩니다. CPU 컴파일은 항상 호스트에서 누적합니다.

  이와 함께 HessianQuant의 순차 solve가 병렬 solve로 교체되었고, Hessian이 전부 0인 레이어는 컴파일을 중단시키는 대신 메시지를 남기고 건너뜁니다.

- **레이어 bias 보정** — 캘리브레이션만으로 동작하는 새 정확도 개선 패스입니다. 부동소수점 활성값과 양자화된 활성값 사이의 채널별 계통 오차를 측정해, 감쇠된 보정값을 정수 bias를 가진 레이어의 bias에 접어 넣습니다. 삽입된 레이어와 모델 출력은 대상에서 제외됩니다. 반복 사이에 보정값을 다시 계산해 상류의 변화를 반영합니다. 레이블도 Minimum Output Difference 최적화도 쓰지 않으므로, 학습 루프가 아니라 캘리브레이션 몇 회분의 비용만 듭니다. 다만 디스크는 듭니다. 이 패스를 켜면 `weightMemory.method`가 `DeleteFloat`인 경우 `SaveFloat`로 올라가, 부동소수점 가중치를 버리지 않고 기록합니다. 다른 값은 그대로 둡니다. `method`는 이 이름들이 아니라 `weightMemory.methodList`의 인덱스입니다. `0`이 `DeleteFloat`, `1`이 `SaveFloat`, `2`가 `MoveFloat`, `3`이 `KeepFloat`, `4`가 `KeepAll`입니다.

  ```python
  qbcompiler.mxq_compile(
      model="model.onnx",
      target_device="aries-rb",
      calib_data_path="calib",
      save_path="model.mxq",
      layer_bias_correction=True,
  )
  ```

  `layer_bias_correction_config=`로 세부 조정합니다. 조정 항목은 설정 객체가 아니라 `Attributes`에 있습니다.

  ```python
  from qbcompiler.configs import LayerBiasCorrectionConfig

  cfg = LayerBiasCorrectionConfig(
      apply=True,
      attributes=LayerBiasCorrectionConfig.Attributes(
          num_samples=256,      # 반복마다 사용할 캘리브레이션 샘플 수
          iterations=5,         # 감쇠 반복 횟수
          correction_rate=0.05, # 반복마다 적용할 측정 오차의 비율
      ),
  )
  ```

- **PATH에 등록되는 `qbcompiler` 명령** — qbcompiler를 설치하면 콘솔 스크립트가 함께 설치되므로, CLI를 더 이상 `python -m qbcompiler`로 쓰지 않아도 됩니다.

  ```bash
  qbcompiler compile --model model.onnx --target-device aries-rb \
      --calib-data-path calib --output model.mxq
  ```

  두 형태 모두 동일한 진입점을 동일한 출력 프로토콜로 실행하며, 사용법과 인자 오류 메시지는 실제로 호출된 형태를 그대로 표시합니다. 서브커맨드는 변경되지 않았습니다. [설치 및 환경 확인](installation.md)을 참고하세요.

- **`config_save_path` — 실제로 사용된 설정 기록** — 컴파일이 시작되기 전에 완전히 해석된 `CompileConfig`를 기록합니다. 우선순위의 모든 단계가 적용되고 모든 하위 설정이 구체화된 정규화 결과입니다. 컴파일보다 먼저 기록되므로 실패하거나 중단된 실행에서도 기록이 남고, 이 파일을 그대로 `compile_config=`로 다시 넘기면 동일한 컴파일을 재현할 수 있습니다.

  ```bash
  qbcompiler compile --model model.onnx --target-device aries-rb \
      --calib-data-path calib --output model.mxq \
      --config-save-path used_config.yaml
  ```

  ```python
  qbcompiler.mxq_compile(
      model="model.onnx",
      target_device="aries-rb",
      calib_data_path="calib",
      save_path="model.mxq",
      config_save_path="used_config.yaml",
  )
  ```

  확장자가 `.yaml` 또는 `.yml`이면 YAML로, 그 외에는 JSON으로 기록하며 상위 디렉터리는 자동으로 생성됩니다. `compile` 파이프라인에서는 전체 설정을 들고 있는 quantize 단계가 파일을 씁니다. 기록할 수 없는 위치를 지정하면 내부 오류가 아니라 해당 경로를 명시한 `OUTPUT_WRITE_ERROR`로 보고됩니다. [컴파일 설정](compile_configuration.md)을 참고하세요.

- **`mxq_compile_from_source()`와 `mxq_compile_from_mblt()`** — `mxq_compile()`이 수행하던 두 가지 일을 직접 호출할 수 있습니다. `mxq_compile()`은 시그니처와 동작을 그대로 유지한 채 둘 사이를 분기하므로 기존 호출부는 변경이 필요 없습니다. `.mblt` 진입점은 이미 파싱된 그래프에 적용할 수 없는 파서 전용 인자(`save_subgraph_type`, `output_subgraph_path`, `feed_dict`, `dynamic_axes`, `in_dformats`, `yolo_decode_include`, `exclude_first_subgraph`, `model_part`, `model_part_options`)를 시그니처에 두지 않습니다. 다만 거부하지는 않습니다. `**kwargs`로 끝나며 받은 것을 그대로 넘깁니다. `.mblt` 입력에 뒤의 둘을 주면 거부하는 쪽은 `mxq_compile()`입니다. 첫 인자 이름은 `model`이 아니라 `mblt`입니다.

- **`regulus-rb-usb` target device** — `aries-rb`, `regulus-ra`, `regulus-rb`에 이어 네 번째 컴파일 타겟입니다. NPU I/O 경계가 부동소수점이 아니므로 `regulus-rb`용으로 빌드한 MXQ와 호환되지 않습니다. [설치 및 환경 확인](installation.md)을 참고하세요.

- **[Breaking]** **트랜스포머 비트 폭 세분화** — `bit.transformer.activation`과 `bit.transformer.weight`에 MoE 라우터 게이트용 `router`가 추가되었고, 단일 `ffn` 비트 폭이 `{up, gate, down}` 하위 객체로 바뀌어 SwiGLU 게이트와 두 projection에 서로 다른 값을 줄 수 있습니다. `ffn`에 정수를 그대로 넘기면 세 값이 모두 설정되므로 기존 설정 파일은 그대로 동작합니다. 다만 이 필드를 다시 읽는 Python 코드는 숫자 대신 객체를 받게 됩니다. `bit.layerOverrides`에는 기존 `weight16Bits`에 대응하는 `weight8Bits`가 추가되었습니다.

- **quant scheme 단계별 캘리브레이션 샘플 수 상한을 설정할 수 있습니다** — `calibration.maxSampleSizeForQuantScheme`. 상한과 기본값 16 자체는 새로운 것이 아니고, `CompileConfig`에서 지정할 수 있게 된 것이 새로운 부분입니다. [모델 양자화](model_quantization.md#calibrationconfig)를 참고하세요.

- **파서 설정 두 가지** — `ParserConfig`나 대응하는 `MBLT_HL_PARSER_` 환경변수로 지정합니다. `force_np_supported_types`(기본 켜짐)는 torch 가중치를 numpy dtype으로 변환해 bfloat16을 float32로 만듭니다. 이전에는 무조건 수행하던 동작이므로, 새로워진 부분은 이를 끄고 원래 dtype을 유지해 이 복사를 건너뛸 수 있다는 점입니다. 이 복사를 감당하기 어려운 모델에서 쓸 수 있습니다. `transform_skip_on_error`는 예외를 던지는 변환 규칙을 파싱 실패로 만들지 않고 보고한 뒤 넘어갑니다.

- **Qwen3-VL의 배치 LLM 컴파일** — Qwen3-VL을 배치 LLM으로 컴파일할 수 있습니다. 배치 LLM은 `llm.apply`가 켜진 상태에서 `llm.attributes.runtime.batchSize`를 1보다 크게 설정해 요청합니다. `llm` 프리셋은 `llm.apply`를 켜지만 `batchSize`는 1로 두므로, 배치 크기는 어느 경우든 직접 지정해야 합니다. 이 기능은 단일 번들 모델에만 적용됩니다. 다중 번들 모델은 메시지와 함께 거부됩니다. 런타임 쪽은 qb Runtime v1.2.0의 `BatchParam`이 담당합니다.

(revised)=

### 변경

- **[Breaking]** **v1.1.0부터 뒤바뀌어 있던 `llm`과 `llm_fast` 프리셋이 바로잡혔습니다.** v1.1.x와 v1.2.0에서는 `config_preset="llm"`이 정확도 관련 변환을 하나도 적용하지 않고 `llm_fast`가 전부 적용했습니다. 이름이 뜻하는 바와 정반대였습니다. v1.3.0부터 `llm`은 등가 변환(QK, UD, VO, SpinR1, SpinR2, OptimizeFFN)과 전체 시퀀스 길이 캘리브레이션을 활성화하고, `llm_fast`는 이들을 비활성화해 컴파일을 빠르게 합니다. 두 프리셋 중 하나에 고정된 파이프라인은 컴파일 시간과 정확도가 모두 달라집니다. v1.2.0의 동작을 유지하려면 프리셋 이름을 서로 바꾸세요.
- **[Breaking]** **`inference_scheme`이 target device 기준으로 검증됩니다.** `multi`, `global4`, `global8`은 각각 두 개 이상의 NPU 코어를 묶으므로, 단일 코어 디바이스(모든 REGULUS 변종)에서는 나중에 실패하는 대신 즉시 거부됩니다. 디바이스가 지원하는 것을 요청하는 `all`은 이 경우 실패 대신 `single`로 좁혀집니다. 스킴과 target device 중 무엇을 먼저 설정했는지와 무관하게 양자화 이전에 검사하므로, 불가능한 조합은 전체 캘리브레이션을 마친 뒤가 아니라 수 초 안에 실패합니다.
- `HessianQuant`의 `attributes.blockSize` 기본값이 128에서 256으로 변경되었습니다.
- **[Breaking]** `classification_torchvision` 프리셋이 이제 `height` / `width` 대신 `size`로 크기를 조정합니다. `size`는 torchvision `Resize(<int>)`처럼 짧은 변을 기준으로 조정하며 종횡비를 유지하고, `height` / `width`는 정확한 크기로 조정합니다. 정방형이 아닌 캘리브레이션 이미지에서는 둘이 서로 다른 텐서가 되므로, 이 프리셋에 고정된 파이프라인은 오류 없이 수치가 달라집니다. 두 표기 모두 v1.2.0부터 유효했고 함께 주면 `size`가 우선합니다. `size`를 이미 쓰던 설정에도 닿는 변경이 둘 더 있습니다. 최단변 계산이 반올림에서 절삭으로 바뀌었고, `centerCrop`이 홀수 여백을 항상 내림하지 않고 짝수 쪽으로 나눕니다. 둘 다 크롭 위치를 한 픽셀 옮길 수 있습니다.
- `compile`과 `quantize` 서브커맨드가 동작합니다. 1.2.0에서는 두 명령 모두 필수 인자인 target device 없이 컴파일 진입점을 호출해, 실행할 때마다 내부 오류로 끝났습니다. 기본 설정에서는 아무것도 출력되지 않았고, `INTERNAL_ERROR`는 JSONL 채널을 켠 경우에만 나왔습니다. 이제 `quantize`도 자체 `--target-device`를 받고, `compile --target-device`는 MBLT 단계뿐 아니라 두 단계 모두에 적용됩니다.
- **[Breaking]** 전처리 `resize` 연산이 `alignCorners`와 `antialias`를 무시하지 않고 실제로 적용합니다. 두 값은 파싱된 뒤 고정값으로 덮어써지고 있었습니다. 그 고정값이 지금도 기본값이므로, 둘 중 하나를 명시한 파이프라인만 달라집니다.
- 전처리 `colorConvert` 연산의 RGB↔BGR 변환이 동작합니다. 채널 교환에 음수 step 슬라이스를 쓰고 있었는데 텐서 라이브러리가 이를 거부해, 변환이 수행되지 않고 예외가 났습니다.
- `resourceManagement.weightMemory.method`가 실제로 리소스 매니저에 적용됩니다. 그동안은 값을 받기만 하고 무시했습니다.
- **[Breaking]** 1.2에서 생성한 설정 파일에는 이번 릴리즈에서 제거된 키가 들어 있을 수 있습니다. 모르는 키는 예전부터 거부해 왔으므로 그런 파일은 로드 자체가 실패합니다. 바뀐 것은 로더가 아니라 키 목록입니다. `dump-config`로 다시 생성한 뒤 지정했던 값을 옮기세요.
- CLI 인자 오류에서 아무 출력 없이 종료하던 문제가 해결되었습니다. 모든 오류 경로가 stderr에 `ERROR [CODE]: message` 형태로 출력하며, JSONL 채널이 켜져 있으면 그 대신 code가 `ARGUMENT_ERROR`인 구조화된 `error` 이벤트를 발생시킵니다. 둘 중 하나만 나옵니다. `--target-device`를 생략하면 내부 `TypeError` 대신 사용 가능한 디바이스 목록을 보여주고, 지원하지 않는 `--backend`도 내부 오류가 아니라 인자 오류로 보고됩니다.
- **[Breaking]** 배치 LLM 컴파일이 `single`로 강제하지 않고 요청한 `inferenceScheme`을 따릅니다. `global4`와 `global8`은 이제 지정한 대로 빌드되고, `multi`와 `all`은 조용히 `single`이 되는 대신 오류로 거부됩니다. 둘 중 하나를 넘기고 조용한 대체에 기대던 파이프라인은 이제 실패하고, `global4`에 고정된 파이프라인은 1.2와 다른 MXQ를 받습니다.
- ONNX 파서가 `GroupNormalization`을 처리합니다. v1.2.0에는 없던 기능이라, 이 연산을 포함한 ONNX 모델은 호출을 바꾸지 않아도 파싱과 분할 결과가 달라집니다.
- **[Breaking]** 멀티펑션 유닛이 필요한 연산이 `regulus-ra`에서 올바르게 거부됩니다. 이 target에는 해당 유닛이 없는데도 지원되는 것으로 분류되어 빈 레이어로 내보내졌고, 그래서 이 연산을 쓰는 모델은 1.2에서 빌드는 되었지만 잘못된 결과를 냈습니다. 이전에 컴파일되던 모델이 이제 빌드에 실패할 수 있습니다.
- **[Breaking]** `backend="torch"`가 `onnx`와 같은 파이프라인으로 파싱됩니다. v1.2.0에서는 `onnx`만 이 경로를 탔습니다. 호출은 그대로여도 생성되는 그래프, 연산 커버리지, NPU/CPU 분할, 수치가 모두 달라질 수 있습니다. `tf`, `tflite`, `torchscript`는 여전히 레거시 파서를 씁니다.
- **[Breaking]** 알 수 없는 `backend`는 API 경계에서 허용되는 이름 목록과 함께 거부됩니다. v1.2.0에서 쓸 수 있던 `hf`, `nemo`, `wenet`, `outetts`, `mellotts`는 이제 받지 않습니다. 특히 `hf`는 모델을 직접 로드해 `backend="torch"`로 넘기는 방식으로 대체됩니다.
- **[Breaking]** JSON 이름 맵으로 준 캘리브레이션 입력은 형상으로 매칭하고, 형상이 같은 입력들 사이에서는 이름으로 구분합니다. 형상이 같은 입력 둘은 그동안 위치 순서로 대체 매칭되어 엉뚱한 입력으로 조용히 캘리브레이션됐는데, 이제 그런 그룹에서 이름이 모델과 맞지 않으면 오류입니다.
- 분할 모델에서 광고되는 입출력 순서가 원본 모델이 선언한 순서를 따릅니다. 그동안은 서브네트워크를 순회한 그래프 등장 순서였는데, quantizer는 샘플을 선언 순서로 번호 매기므로 버퍼를 위치 기반으로 넘기던 호출자는 전부 엉뚱한 입력에 넣게 됐습니다. 1.3 이전에 빌드한 분할 모델 MXQ는 다시 빌드하는 편이 좋습니다.
- 지원되는 가장 큰 서브그래프만 남기는 선택이, 본문만이 아니라 그것이 호출하는 서브그래프까지 함께 남깁니다. 호출 대상이 되는 서브그래프는 본문 후보에서 제외됩니다. `get_body_subgraph()`와 `extract-body` 서브커맨드가 내보내는 것이 이것이고 파싱 경로도 같은 선택을 쓰므로, 본문이 서브그래프를 호출하는 모델이라면 결과 `.mblt`가 달라지고 이를 후처리하는 스크립트는 다른 파일을 보게 됩니다.
- 조용히 잘못된 결과를 내던 `regulus-ra` 코드 생성 결함 두 건이 수정되었습니다. 비트 연산 ALU 로워링 두 곳과, 해당 세대에 존재하지 않는 레지스터에 쓰던 문제입니다. 이전 릴리스로 `regulus-ra`용으로 빌드한 MXQ는 다시 빌드할 만합니다.
- **[Breaking]** `qbcompiler.model_dict`가 이제 신규 파서 파이프라인을 담습니다. 레거시 파이프라인은 `qbcompiler.model_dict_legacy`로 옮겨졌고 `qbcompiler.model_dict_new`는 사라졌습니다. `qbcompiler.model_dict`에서 import하던 코드는 실패하는 대신 다른 모듈에 바인딩되므로 변경이 드러나지 않습니다.
- 서브그래프가 둘 이상인 모델은 변환이 병렬로 수행됩니다. 서브그래프마다 워커를 하나씩 fork하며, 상한은 `ParserConfig.num_work` 또는 `MBLT_HL_PARSER_NUM_WORK`로 지정하며, 기본값은 프로세스가 쓸 수 있는 CPU 수에서 2를 뺀 값입니다. 서브그래프가 하나인 모델은 영향이 없습니다. 워커 수는 메모리 사용량을 고려하지 않습니다. 최대 호스트 메모리가 워커 수에 비례하므로, 서브그래프가 유난히 무거운 모델에서는 `num_work`를 낮춰야 합니다.
- 양자화 이후 단계인 바이너리 코드 생성이 최대 약 3배 빨라졌습니다. 희소 liveness 저장은 모든 컴파일에 적용되고, 컴파일 유닛을 각각 별도 프로세스로 fork하는 부분은 Global 계열 inference scheme(`global4`, `global8`)에만 적용됩니다. 단일 코어 디바이스는 이 스킴을 받지 않습니다. 같은 단계의 비결정성 세 건도 함께 수정되었습니다.
- 양자화 정확도와 안정성: EfficientViT 정확도가 개선되었고, 비대칭 zero-point가 matmul 누적기 bias, *x*² 스케일 탐색, `InputConstant` 정수 코드, average pooling의 depthwise 변환을 통해 올바르게 전달됩니다. 16비트 가중치는 INT16 전체 범위 대신 BINT16 범위 `[-32768, 32639]`를 사용하고, 히스토그램 모드 캘리브레이션의 샘플 가중치가 수정되었습니다. `aries-rb`와 `regulus-ra`에서 패딩된 컨볼루션으로 들어가는 모델 입력은, 비대칭으로 두면 하드웨어 입력 reshape를 잃게 되는 경우에 한해 대칭으로 유지됩니다.
- Multi-Function Unit이 라이브러리에 내장된 비트 단위로 동일한 fp16 룩업 테이블로 처리됩니다. 함께 배포되던 `libmfu_wrapper.so`는 사라졌습니다.
- 양자화된 활성값이 float이 아니라 실제 정수 dtype으로 저장되어 대형 모델의 호스트 메모리 사용량이 줄었습니다.
- **[Breaking]** **`qbcompiler.exceptions`, `qbcompiler.progress`, `qbcompiler.logging`이** 각각 `qbcompiler.reporting.exceptions`, `qbcompiler.reporting.progress`, `qbcompiler.reporting.logging`으로 이동했습니다. 최상위에 shim을 남기지 않았으므로 이전 경로는 `ModuleNotFoundError`가 납니다. 패키지 최상위에서 예외 클래스를 가져오는 방식(`from qbcompiler import QBCompilerError`)은 변경되지 않았으며 이 방식이 계속 권장됩니다.

(removed)=

### 삭제

- **[Breaking]** **`_V2` 함수 별칭.** `mxq_compile_V2`, `mblt_compile_V2`, `mxq_compile_with_callback_V2`, `mblt_compile_with_callback_V2`가 제거되었습니다. `mxq_` 계열 둘은 접미사만 떼면 되지만, `mblt_` 계열 둘은 인자 순서도 바뀌었습니다. `mblt_compile`과 `mblt_compile_with_callback`은 출력 경로를 target device보다 먼저 받는데, `mblt_compile_V2`와 `mblt_compile_with_callback_V2`는 target device가 먼저였습니다. 위치 인자로 넘기던 코드는 문자열 두 개가 오류 없이 뒤바뀝니다. 키워드 인자로 넘기는 호출부는 영향이 없습니다.

  ```python
  # 이전 (v1.2.0)
  qbcompiler.mxq_compile_V2(model=..., target_device=..., ...)

  # 이후 (v1.3.0)
  qbcompiler.mxq_compile(model=..., target_device=..., ...)
  ```
- **[Breaking]** **`hf_config`.** 이제 대체 방법을 알려주는 `ValueError`를 발생시킵니다. Hugging Face 모델은 직접 로드해 `backend="torch"`와 함께 `model`로 넘기고, 컴파일할 부분은 `model_part` / `model_part_options`로 지정하세요.
- **`CalibrationConfig.clustering_methods`**, `clusteringMethods`, `clusteringMethodsList`, `LutClusteringMethod` 열거형이 제거되었습니다. 이들은 Python 계층에만 존재했고 v1.2.0의 어떤 컴파일러 구성요소도 읽지 않았으므로, 이 값을 지정한 컴파일도 이미 새 기본값과 동일하게 동작했습니다. 룩업 테이블 탐색은 `calibration.groupLut`(`irlsIter`, `droEps`, `coverFloor`)와 `calibration.optimizeLut.optimizationLevel`로 설정합니다. `optimizationLevel`은 `0`이 대리 목적함수만 쓰는 빠른 탐색, `1`이 실제 목적함수로 다시 다듬는 탐색입니다.
