name: onnx-converter-operator-fix description: Use when ONNX conversion produces ERROR logs about unsupported operators that cause inference failures. Detects problematic operators from conversion output and suggests replacement. Can be called explicitly or triggered automatically after detecting ERROR logs. Also covers manual operator fixes for Split, StrideSlice, NMS, GRU, Einsum, Gather, MatMul, Gemm, Squeeze, and structural patterns.

ONNX Operator Fix Skill

Fixes ONNX operators that cause MindSpore Lite conversion errors or inference failures.

When to Use

Trigger this skill when:

  • Conversion output contains [ERROR] logs
  • User mentions operator issues: HardSigmoid/HardSwish/Swish/Mish/Split/StrideSlice/NMS/GRU/Einsum/Gather/MatMul/Gemm/Squeeze
  • As a follow-up to harmonyos-model-convert failure
  • User mentions "算子替换", "算子修复", "转换失败", "转换报错"

Supported Operators (Auto-fix via ohos_op_fix)

Operator Replacement Formula Error Pattern
HardSigmoid Mul→Add→Min→Max max(min(x*α+β, 1), 0) sigmoid_mul_fusion
HardSwish Add→Clip→Div→Mul x * clip(x+3, 0, 6) / 6 HardSwish
Swish/SiLU Sigmoid→Mul x * sigmoid(x) Swish
Mish Softplus→Tanh→Mul x * tanh(ln(1+e^x)) Mish

Manual Fix Knowledge Base (实战案例)

以下算子问题需要手动修改 ONNX 图或使用异构方案,无法通过 ohos_op_fix 自动修复:

1. Split — 只支持单输出

问题:Split 连接多个输出时转换报错

解决:将 Split 替换为多个 Slice 算子,每个 Slice 取一个输出分片

2. StrideSlice — Cann kit 不支持5维输入

问题:StrideSlice 算子输入为5维时报错

解决:如果第0轴为1,在 StrideSlice 前插入 Squeeze 折叠维度,计算后再 Unsqueeze 恢复

3. NonMaxSuppression (NMS) — Cann kit 不支持

问题:NMS 算子无法转换

解决:NMS 主要用于检测结果去冗余,可以先去除 NMS 算子,或使用异构方案(CPU 执行 NMS 部分)

4. transpose→softmax→conv 结构 — conv format=NHWC 时失败

问题:特定算子组合在 conv 的 format 为 NHWC 时转换失败

解决:用 MatMul 替代 Conv 算子

5. MatMul 左矩阵连接 Transpose 报错

问题:MatMul 的左矩阵输入直接连接 Transpose 会报错

解决:在 Transpose 与 MatMul 中间插入一个 shape 不变的 Reshape 算子,将两者隔开

6. Gemm 精度问题

问题:ONNX 图中有 Gemm 算子时,转换后精度异常

解决:将 Gemm 算子异构到 CPU 执行

7. 大 shape 的 MatMul — batch 过大

问题:MatMul 右矩阵 shape 如 3072x768,3072 过大导致报错

解决:将 MatMul 拆分,如 3072x768 拆成 3 个 MatMul,每个右矩阵 shape 为 1024x768

8. GRU — NPU 不支持

问题:GRU 算子在 NPU 上无法运行

解决:异构方案,将 GRU 跑在 CPU 上

9. Einsum — NPU 不支持

问题:Einsum 算子 NPU 不支持

解决:用 Unsqueeze + Mul + ReduceSum 替代 Einsum

10. Squeeze — 不支持两个输入

问题:Squeeze 算子有2个输入(data + axes)时报错

解决:将 axes 从输入转换为 Squeeze 的属性(attribute)

11. Gather — axis=-1 不支持

问题:Gather 算子 axis 值为 -1 时 NPU 不支持

解决:将 -1 改写成等效的正数值(如 axis=3 对于4维张量)

Operator Fix Decision Tree

转换报错
  │
  ├─ 错误日志包含具体算子名
  │  ├─ HardSigmoid/HardSwish/Swish/Mish → ohos_op_fix 自动替换
  │  ├─ Split → 替换为 Slice
  │  ├─ StrideSlice(5维) → 插入 Squeeze/Unsqueeze
  │  ├─ NMS → 去除或异构到CPU
  │  ├─ Gemm → 异构到CPU
  │  ├─ GRU → 异构到CPU
  │  ├─ Einsum → Unsqueeze+Mul+ReduceSum
  │  ├─ Squeeze(2输入) → axes转为属性
  │  ├─ Gather(axis=-1) → 改写为正数axis
  │  └─ MatMul(大shape) → 拆分为多个小MatMul
  │
  ├─ transpose→softmax→conv 结构失败 → conv改matmul
  ├─ MatMul左矩阵连Transpose → 中间插Reshape
  │
  └─ 不确定问题 → 使用 ohos_runtime_analyze 分析日志

Workflow

Case A: Explicit Call (User Initiated)

  1. User calls ohos_op_fix with ONNX file path
  2. System auto-detects or user specifies operators to replace
  3. Execute operator replacement using fix_onnx_operators()
  4. Generate fixed ONNX file
  5. Suggest user to re-run conversion

Case B: Auto Suggestion (After Conversion)

  1. Call ohos_convert to convert ONNX model
  2. Parse conversion output for ERROR logs
  3. Return error analysis with operators_detected
  4. Suggest using ohos_op_fix to replace detected operators
  5. User confirms and calls fix command

Tools

ohos_op_fix

Call: ohos_op_fix
Arguments: {
  "onnx_path": "<path-to-onnx-file>",
  "output_path": "<output-path>",       // Optional, defaults to *_fixed.onnx
  "operators": ["HardSigmoid", ...]     // Optional, auto-detect if not specified
}

Output:

{
  "success": true,
  "operators_replaced": ["HardSigmoid"],
  "nodes_per_operator": {"HardSigmoid": 30},
  "output_path": "model_fixed.onnx",
  "message": "建议重新执行转换"
}

ohos_task_status (with Error Analysis)

When a conversion task completes, ohos_task_status returns error_analysis field:

{
  "status": "completed",
  "output_file": "model.ms",
  "error_analysis": {
    "has_errors": true,
    "error_count": 30,
    "operators_detected": ["HardSigmoid"],
    "suggested_fix": "建议使用 op_fix 命令替换: HardSigmoid"
  },
  "suggested_action": "Use ohos_op_fix to replace: HardSigmoid"
}

Example Usage

Example 1: Explicit Fix

User: "test_rec.onnx 转换报 HardSigmoid 错误,帮我修复"

Call: ohos_op_fix
Arguments: {
  "onnx_path": "D:\\pyproject\\agent\\test\\model\\test_rec.onnx",
  "operators": ["HardSigmoid"]
}

Result:
- Fixed file: test_rec_fixed.onnx
- 30 HardSigmoid nodes replaced
- Suggest: re-run conversion

Example 2: Auto-Suggest After Conversion

User: "转换 test_rec.onnx"

Step 1: ohos_convert(test_rec.onnx)
Result: Conversion completed, but error_analysis shows:
  - has_errors: true
  - operators_detected: ["HardSigmoid"]
  - error_count: 30

Step 2: Agent suggests:
  "[SUGGEST] 检测到 HardSigmoid 算子错误,建议使用 op_fix 修复"

File Locations

  • Replacement Scripts: .opencode/skills/onnx-converter-operator-fix/scripts/onnx_op_replace.py
  • Operator Examples: .opencode/skills/onnx-converter-operator-fix/examples/*.json
  • MCP Server: ohos_model_claw/mcp_server.py
  • Core Logic: ohos_model_claw/aiclaw.py

Notes

  • Replacement preserves mathematical equivalence
  • Output tensor references are correctly updated
  • Graph topology is maintained after replacement
  • Multiple operators can be replaced in one call
  • Supports sequential replacement when multiple operators present

Technical Details

Error Pattern Detection

OPERATOR_ERROR_PATTERNS = {
    "hardsigmoid_fusion": {
        "pattern": "sigmoid_mul_fusion.*activation type is not sigmoid",
        "operator": "HardSigmoid"
    },
    "hardswish_unsupported": {
        "pattern": "HardSwish",
        "operator": "HardSwish"
    }
}

Replacement Implementation

Uses onnx_graphsurgeon for graph manipulation:

  • Preserves tensor data types
  • Maintains downstream consumer references
  • Updates graph outputs when necessary
  • Performs cleanup and topological sort after modification