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)
- User calls
ohos_op_fixwith ONNX file path - System auto-detects or user specifies operators to replace
- Execute operator replacement using
fix_onnx_operators() - Generate fixed ONNX file
- Suggest user to re-run conversion
Case B: Auto Suggestion (After Conversion)
- Call
ohos_convertto convert ONNX model - Parse conversion output for ERROR logs
- Return error analysis with
operators_detected - Suggest using
ohos_op_fixto replace detected operators - 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