Qwen3-ASR-1.7B-RKLLM / convert /audio_encoder /export_audio_encoder_onnx.py
happyme531's picture
更新转换脚本和文档(claude写的,感觉也不是特别好)
b70ae8e verified
Raw
History Blame Contribute Delete
2.95 kB
import argparse
from pathlib import Path
import onnxruntime as ort
import torch
from common import StaticChunkAudioEncoder, get_torch_dtype, load_audio_encoder
def parse_args():
parser = argparse.ArgumentParser(description="Export Qwen3-ASR audio encoder chunk model to ONNX.")
parser.add_argument("--model-path", type=str, default=".", help="Path to Qwen3-ASR model directory.")
parser.add_argument(
"--savepath",
type=str,
default="rknn_deploy/audio_encoder/onnx/qwen3_asr_audio_chunk100.onnx",
help="Output ONNX path.",
)
parser.add_argument("--chunk-frames", type=int, default=100, help="Fixed mel chunk length.")
parser.add_argument(
"--dtype",
type=str,
default="float32",
choices=["float16", "bfloat16", "float32"],
help="Torch dtype used for loading and export.",
)
parser.add_argument("--device", type=str, default="cpu", help="Torch device for export.")
return parser.parse_args()
def main():
args = parse_args()
savepath = Path(args.savepath)
savepath.parent.mkdir(parents=True, exist_ok=True)
tower = load_audio_encoder(model_path=args.model_path, dtype=args.dtype, device=args.device)
wrapper = StaticChunkAudioEncoder(tower=tower, chunk_frames=args.chunk_frames).to(args.device).eval()
input_features = torch.zeros(
(1, 128, args.chunk_frames),
dtype=get_torch_dtype(args.dtype),
device=args.device,
)
feature_len = torch.tensor([args.chunk_frames], dtype=torch.int32, device=args.device)
with torch.no_grad():
torch_features, torch_valid_len = wrapper(input_features, feature_len)
torch.onnx.export(
wrapper,
(input_features, feature_len),
savepath.as_posix(),
input_names=["input_features", "feature_len"],
output_names=["audio_features", "valid_len"],
opset_version=18,
dynamo=False,
dynamic_axes={
"input_features": {0: "batch"},
"feature_len": {0: "batch"},
"audio_features": {0: "batch"},
"valid_len": {0: "batch"},
},
)
ort_session = ort.InferenceSession(savepath.as_posix(), providers=["CPUExecutionProvider"])
ort_features, ort_valid_len = ort_session.run(
None,
{
"input_features": input_features.detach().cpu().numpy(),
"feature_len": feature_len.detach().cpu().numpy(),
},
)
max_diff = float((torch_features.detach().cpu() - torch.from_numpy(ort_features)).abs().max().item())
print(f"saved: {savepath}")
print(f"chunk_frames: {args.chunk_frames}")
print(f"chunk_output_frames: {wrapper.max_aftercnn_len}")
print(f"torch_valid_len: {int(torch_valid_len[0].item())}")
print(f"ort_valid_len: {int(ort_valid_len.reshape(-1)[0])}")
print(f"max_abs_diff(torch_vs_onnx): {max_diff:.8f}")
if __name__ == "__main__":
main()