
人工智能语音深度学习预训练模型推理服务【免费下载链接】wenetProduction First and Production Ready End-to-End Speech Recognition Toolkit项目地址https://gitcode.com/gh_mirrors/we/wenet点击查看免费下载wenet 提供了面向生产环境的端到端语音识别工具链。本文围绕 runtime/gpu/tensorrt/README.md 展开完整讲解如何将流式 u2ppUnified Two-PassConformer 模型从 PyTorch 导出为 FP16 ONNX再经图优化、TensorRT 引擎转换与 Triton Inference Server 的 Ensemble 编排最终落地为一个低延迟、高并发的流式 ASR 服务。读完本文你将掌握run_streaming_small_model.sh整条流水线中每个阶段的作用与参数含义理解 LayerNorm 自定义插件、动态 shape 引擎、多 Profile 优化等关键技术的底层实现并能复现 README 中记录的并发吞吐基准。一、方案定位与整体思路TensorRT 是 NVIDIA 推出的 GPU 推理优化引擎通过算子融合、层间融合、精度校准如 FP16和内核自动调优等手段显著提升神经网络在 GPU 上的推理效率。Triton Inference Server 则负责模型的部署管理、动态批处理、并发调度与序列状态管理。在 wenet 的这套 GPU 部署方案中两者各司其职TensorRT负责流式编码器Encoder的 FP16 推理并通过自定义LayerNorm 插件绕开 ONNX 默认 LayerNorm 算子在 TensorRT 中的低效实现Triton通过 Python Backend、TensorRT Backend、ONNX Runtime Backend 与 Ensemble Scheduling 把「特征提取 → 编码 → CTC 前缀束搜索 → Attention 重打分」串成一条完整可服务的链路ONNX Runtime负责解码器Decoder的 Attention Rescoring 计算。这套方案的全部脚本与模型仓库模板都位于 runtime/gpu/tensorrt 目录一键入口是 run_streaming_small_model.sh。整体数据流为wav chunk → feature_extractor(FPBank) → encoder(TensorRT, FP16 LayerNorm 插件) → wenet(CTC 前缀束搜索) → decoder(ONNX Runtime 重打分) → 文本二、环境准备Docker 镜像与依赖安装README 推荐直接使用配套的 Triton Docker 镜像省去手动安装 TensorRT、CUDA、Triton 的繁琐步骤。镜像内已预置 Triton Server 与 TensorRT 运行环境# 使用 runtime/gpu/Dockerfile/Dockerfile.server 对应的 docker 镜像 docker pull soar97/triton-wenet:22.12 docker run -it --rm --name wenet_trt_test --gpus all --shm-size 1g --net host soar97/triton-wenet:22.12其中--gpus all将全部 GPU 透传给容器--shm-size 1g增大共享内存以支撑 Triton 的序列批处理--net host使用宿主机网络便于客户端直接访问服务端口。仓库自带的 Dockerfile.server 展示了镜像内部的构建思路基于nvcr.io/nvidia/tritonserver:23.01-py3安装swig、cmake、torch、kaldifeat用于 FBank 特征提取以及ctc_decoderCTC 前缀束搜索的 SWIG 绑定。进入容器后克隆 wenet 仓库并切换到 TensorRT 示例目录git clone https://github.com/wenet-e2e/wenet.git cd wenet/runtime/gpu/tensorrt若已在当前仓库环境下操作直接进入 runtime/gpu/tensorrt 目录即可。安装 Python 依赖。脚本依赖 requirements.txtpip3 install nvidia-pyindex pip3 install -r requirements.txtrequirements.txt 中值得注意的几个关键依赖依赖版本/来源用途tensorrt8.5.1.7TensorRT Python API用于构建/加载 engineonnx_graphsurgeon0.3.21来自 NGC PyPIONNX 图结构修改LayerNorm 替换polygraphy无版本约束模型图精简常量折叠与在线检查onnxruntime-gpu无版本约束解码器 rescoring 推理cuda-python/onnxmltools无版本约束引擎测试与模型工具若网络受限无法访问默认源可先安装nvidia-pyindex为 NVIDIA 包提供索引并为requirements.txt指定可用的 PyPI 镜像源后重试README 中的提示原文即为此意。三、一键流水线从 ONNX 到 Triton 服务run_streaming_small_model.sh 是整个流程的编排脚本以stage/stop_stage分段控制默认stage-1、stop_stage4可逐步或整体执行Stage职责关键产物-1下载 Aishell2 u2pp Conformer 预训练模型并导出 FP16 流式 ONNXu2pp_aishell2_onnx/0编译 LayerNorm CUDA 插件exp_streaming_trt/LayerNorm.so1常量折叠 用插件替换 ONNX 中的 LayerNorm 子图encoderV2/V3/V4.onnx2trtexec构建 FP16 动态 shape TensorRT engineencoder_fp16.plan3用 convert.py 生成 Triton Model Repository 并拷入 engine 与插件model_repo_stateful_trt/4启动tritonserver在线服务5多 Profile 引擎导出与 ONNX/TensorRT 吞吐对比测试注释中的可选阶段基准数据Stage -1下载模型并导出 FP16 ONNX脚本从公共地址下载 Aishell2 的20210618_u2pp_conformer_exp.tar.gz预训练模型解压后调用 wenet/bin/export_onnx_gpu.py 导出流式 FP16 ONNXexport PYTHONPATH$PYTHONPATH:$(pwd) python3 wenet/bin/export_onnx_gpu.py \ --config$model_dir/train.yaml \ --checkpoint$model_dir/final.pt \ --cmvn_file$model_dir/global_cmvn \ --ctc_weight0.5 \ --output_onnx_dir$onnx_model_dir \ --fp16 \ --streaming || exit 1 cp $model_dir/words.txt $model_dir/train.yaml $onnx_model_dir对照 export_onnx_gpu.py 的参数定义各参数含义如下参数默认值说明--config必填训练配置文件train.yaml内含 encoder/decoder 结构、FBank 与 resample 等配置--checkpoint必填模型权重文件final.pt--cmvn_file全局 CMVN 文件流式编码器需要内嵌 global_cmvn--ctc_weight-1.0回退到配置文件两遍解码中 CTC 分数的权重示例取0.5--beam_size10束大小同时决定 CTC top-k 输出宽度--output_onnx_dironnx_modelONNX 模型输出目录--fp16False是否导出 FP16 权重模型--streamingFalse是否导出流式编码器带 chunk cache 输入--decoding_chunk_size16流式解码 chunk 大小--num_decoding_left_chunks5允许的左向上下文 chunk 数流式导出会产生encoder_fp16.onnx、decoder.onnx等文件其中流式编码器的输入输出签名可以从脚本内的StreamingEncoder类export_onnx_gpu.py确认输入为chunk_xs / chunk_lens / offset / att_cache / cnn_cache / cache_mask输出为chunk_out / chunk_out_lens / ctc_log_probs / beam_log_probs / beam_log_probs_idx等——这正是后续trtexec动态 shape 与 Triton 配置中出现的全部张量名。Stage 0编译 LayerNorm 自定义插件LayerNorm 在 ONNX 导出中会被展开成ReduceMean → Sub → Pow → ReduceMean → Add → Sqrt → Div → Mul → Add一长串小算子TensorRT 逐算子推理效率不高。仓库在 LayerNormPlugin 目录提供了一个融合的自定义 CUDA 插件将整段计算合并为一次规约加一次逐元素变换。编译方式cd ./LayerNormPlugin make clean make cp LayerNorm.so $outputs_dirMakefile 中通过GENCODE为多种 GPU 架构sm_60/61/70/75/80/86预编译 SASS并链接cudart、cublas与nvinfer。从 LayerNormPlugin.cu 的 kernel 实现可以看到其核心思路每个线程块用cub::BlockReduce一次规约出均值mu与平方和随后计算rsigma rsqrt(sum - mu*mu 1e-6)再按gamma*(x-mu)*rsigma beta写回对 FP32 与 FP16 分别实例化了layerNormKernelfloat,64,4与layerNormKernelhalf,32,8并通过REGISTER_TENSORRT_PLUGIN注册到 TensorRT 插件库插件类型名为LayerNorm见 LayerNormPlugin.h。插件支持kFLOAT/kHALF两种精度且输出形状与输入一致。该目录还附带 testLayerNormPlugin.py可用于在 Python 侧加载LayerNorm.so、构建只含该插件的测试网络并与 CPU 版 LayerNorm 结果逐元素对比验证弱比较阈值1e-6同时统计单次推理的平均耗时。Stage 1ONNX 图优化与 LayerNorm 替换Stage 1 依次执行三步polygraphy surgeon sanitize $onnx_model_dir/encoder_fp16.onnx --fold-constant -o $outputs_dir/encoderV2.onnx python3 replace_layernorm.py --input_onnx $outputs_dir/encoderV2.onnx \ --output_onnx $outputs_dir/encoderV3.onnx \ || exit 1 polygraphy surgeon sanitize $outputs_dir/encoderV3.onnx --fold-constant -o $outputs_dir/encoderV4.onnx用polygraphy surgeon sanitize --fold-constant做常量折叠预先化简图中可离线计算的常量子图运行 replace_layernorm.py用onnx_graphsurgeon匹配「ReduceMean → Sub → Pow → ReduceMean → Add → Sqrt → Div → Mul → Add」这一标准 LayerNorm 子图模式把该子图折叠为一个自定义LayerNorm算子节点并将原来独立的weightgamma与biasbeta常量提取为插件的第二、第三个输入脚本对输出端还有一个特殊处理当 LayerNorm 的结果恰是图的输出chunk_out时会在插件输出后接Squeeze并转为np.float16以匹配 FP16 引擎replace_layernorm.py再次常量折叠得到干净的encoderV4.onnx供引擎构建使用。Stage 2trtexec 构建 FP16 动态 shape TensorRT engineStage 2 使用 TensorRT 官方命令行工具trtexec构建引擎同时启用 FP16 与动态 shapeDynamic Shape并挂载自定义插件MIN_BATCH1 OPT_BATCH16 MAX_BATCH32 $trtexec \ --fp16 \ --onnx$outputs_dir/encoderV4.onnx \ --minShapeschunk_xs:${MIN_BATCH}x67x80,chunk_lens:${MIN_BATCH},offset:${MIN_BATCH}x1,att_cache:${MIN_BATCH}x12x4x80x128,cnn_cache:${MIN_BATCH}x12x256x7,cache_mask:${MIN_BATCH}x1x80 \ --optShapeschunk_xs:${OPT_BATCH}x67x80,chunk_lens:${OPT_BATCH},offset:${OPT_BATCH}x1,att_cache:${OPT_BATCH}x12x4x80x128,cnn_cache:${OPT_BATCH}x12x256x7,cache_mask:${OPT_BATCH}x1x80 \ --maxShapeschunk_xs:${MAX_BATCH}x67x80,chunk_lens:${MAX_BATCH},offset:${MAX_BATCH}x1,att_cache:${MAX_BATCH}x12x4x80x128,cnn_cache:${MAX_BATCH}x12x256x7,cache_mask:${MAX_BATCH}x1x80 \ --plugins$outputs_dir/LayerNorm.so \ --saveEngine$outputs_dir/encoder_fp16.plan各输入张量含义可与 export_streaming_conformer_trt.py 中构造测试输入的逻辑相互印证输入张量形状以 batch 为例含义chunk_xsB × 67 × 80当前 chunk 的 FBank 特征67 帧 × 80 维chunk_lensB每个 chunk 的实际帧数offsetB × 1全局帧偏移保留 1 维以便 Triton 状态管理att_cacheB × 12 × 4 × 80 × 12812 层、4 头注意力 KV 缓存80 cache_size128 d_k*2cnn_cacheB × 12 × 256 × 712 层卷积模块缓存cache_maskB × 1 × 80缓存掩码这里67即解码窗口decoding_window80为 Mel 分箱数二者均由 convert.py 从train.yaml的fbank_conf与流式 ONNX 配置计算得到。构建成功后得到encoder_fp16.plan它就是 Triton 中 TensorRT Backend 实际加载的引擎文件。Stage 3生成 Triton Model RepositoryStage 3 调用 runtime/gpu/scripts/convert.py 生成完整的 Triton Model Repositorypython3 ../scripts/convert.py --config$onnx_model_dir/train.yaml --vocab$onnx_model_dir/words.txt \ --model_repo$model_repo_path --onnx_model_dir$onnx_model_dir cp $outputs_dir/encoder_fp16.plan $model_repo_path/encoder/1/ cp $outputs_dir/LayerNorm.so $model_repo_path/../convert.py的核心逻辑是读取训练配置与 ONNX 导出配置把model_repo_stateful_trt/下的config_template.pbtxt模板中的占位符如#beam_size、#num_mel_bins、#frame_shift、#frame_length、#sample_rate、#output_size、#DTYPE、#cache_size、#chunk_size_in_seconds、#num_layers、#num_head、#att_cache_output_size、#cnn_module_cache、#decoding_window、#bidecoder等替换为实际数值逐个模型生成config.pbtxt并把decoder.onnx/encoder_fp16.onnx拷入各模型目录convert.py。对于双向解码器decoder以bi开头会选择config_template2.pbtxt生成不带反向输入的解码器配置convert.py。Stage 4启动 Triton ServerLD_PRELOAD./LayerNorm.so tritonserver --model-repository $model_repo_path \ --pinned-memory-pool-byte-size2512000000 --cuda-memory-pool-byte-size0:2024000000这里的关键是LD_PRELOAD./LayerNorm.soTensorRT Backend 加载encoder_fp16.plan时需要反序列化其中的自定义LayerNorm插件因此必须先把插件动态库预加载进进程否则引擎加载会因找不到插件而失败。--pinned-memory-pool-byte-size与--cuda-memory-pool-byte-size分别控制主机端与 GPU 端的缓存池大小。Stage 5验证与吞吐测试脚本中额外预留了 Stage 5默认注释用于三组验证用 export_streaming_conformer_trt.py 以--test模式对多 Profile 引擎做端到端正确性测试用trtexec --loadEngine ... | grep qps对单 Profile 引擎做batch1/4/8/16/32的 QPS 扫描用 benchmark_onnx_throughput.py 对encoder_fp16.onnx做batch_sizes1,4,8,16,32,64,128,256的 ONNX Runtime 吞吐对照。四、Triton Ensemble 模型编排详解model_repo_stateful_trt 目录包含 5 个子模型其中streaming_wenet是 Ensemble集成调度入口其余为实际执行模型streaming_wenet (ensemble) ├── feature_extractor (python backend kaldifeat FBank) ├── encoder (tensorrt backend, encoder_fp16.plan) ├── wenet (python backend ctc_decoder 前缀束搜索) └── decoder (onnxruntime backend, attention rescoring)各模型配置要点如下feature_extractorconfig_template.pbtxtPython Backend输入原始wav与wav_lens输出speech与speech_lengths。其实现 model.py 用kaldifeat.Fbank在 GPU 上提取 80 维 FBank通过Feat类按corrid维护每条音频流的波形缓冲按frame_stride由chunk_size_s与frame_shift_ms计算切帧保证每个输出 chunk 恰好是解码窗口大小。默认 FBank 参数frame_length_ms25、frame_shift_ms10、sample_rate16000、chunk_size_s0.64。encoderconfig_template.pbtxtTensorRT Backenddefault_model_filename: encoder_fp16.planmax_batch_size: 32。核心是sequence_batching中的state段把offset、att_cache、cnn_cache、cache_mask四个输入声明为「序列状态」由 Triton 自动维护上一 chunk 的缓存输出并作为下一 chunk 的输入从而实现真正的无状态请求式流式推理——客户端无需自己管理缓存只需持续提交音频 chunk。wenetconfig_template.pbtxtPython Backend负责 CTC 前缀束搜索与可选的 Attention 重打分编排。从参数模板可以看到生产级默认值beam_size、cutoff_prob0.9999、alpha2、beta1、rescoring1并可配置外部语言模型lm_path通过Scorer注入。其实现 model.py 用self.seq_states[corrid]记录每条流的前缀树PathTrie与 encoder 历史输出wenet_onnx_model.py 中的batch_ctc_prefix_beam_search_cpu调用 SWIG 编译的ctc_beam_search_decoder_batch做多进程束搜索batch_rescoring则在序列结束时把束内候选送入decoder模型重打分最终经map_batch映射为文本。decoderconfig_template.pbtxtONNX Runtime Backend输入encoder_out、encoder_out_lens、hyps_pad_sos_eos、hyps_lens_sos、r_hyps_pad_sos_eos、ctc_score双向解码器时包含反向束输出best_indexmax_batch_size: 640采用dynamic_batching聚合重打分请求。streaming_wenetconfig_template.pbtxtEnsemble 模型对外暴露WAV/WAV_LENS输入与TRANSCRIPTS输出内部通过ensemble_scheduling将上述模型的输入输出张量按名映射串联客户端只需请求这一个模型即可获得流式识别结果。五、性能基准README 给出了基于 Aishell1 测试集的真实基准服务端使用 A10 GPU16 vCPU / 60GB 内存客户端为 4 vCPU / 16GB 内存测试音频总时长 36108.919 秒采用非模拟流式模式non-simulate-streaming即真正按 chunk 逐段推理。数据来源为 small u2pp ONNX 模型并发任务数处理时间秒20onnx fp16123.79640onnx fp1684.55760onnx fp1673.23280onnx fp1666.86220trt fp16 layernorm plugin90.58240trt fp16 layernorm plugin75.41160trt fp16 layernorm plugin69.60280trt fp16 layernorm plugin65.603可以看到在低并发20 路时 ONNX 与 TensorRT 方案差距明显123.796s vs 90.582sTensorRT 方案在 40 路以下并发下相对 ONNX 均有可观收益并发升至 60~80 路时两者处理时间趋近说明瓶颈逐渐从编码器算力转移到整体服务链路的其他环节特征提取、CTC 搜索、批处理调度等。这一结果同时印证了 LayerNorm 插件融合与 FP16 引擎对编码器推理效率的实际提升。六、进阶多 Profile 引擎与引擎直测为了同时兼顾小 batch 的实时性与大 batch 的吞吐仓库提供了 export_streaming_conformer_trt.py可通过 Python API 构建包含两个优化 Profile的引擎。其用法示例如下export CUDA_VISIBLE_DEVICES0 python3 export_streaming_conformer_trt.py \ --fp16 \ --onnxFile exp6_fp16/encoderV4.onnx \ --chunk_xs 1x67x80,32x67x80,64x67x80,1x67x80,4x67x80,8x67x80 \ --chunk_lens 1,32,64,1,4,8 \ --offset 1x1,32x1,64x1,1x1,4x1,8x1 \ --att_cache 1x12x4x80x128,32x12x4x80x128,64x12x4x80x128,1x12x4x80x128,4x12x4x80x128,8x12x4x80x128 \ --cnn_cache 1x12x256x7,32x12x256x7,64x12x256x7,1x12x256x7,4x12x256x7,8x12x256x7 \ --cache_mask 1x1x80,32x1x80,64x1x80,1x1x80,4x1x80,8x1x80 \ --plugin exp6_fp16/LayerNorm.so \ --trtFile exp6_fp16/encoder_test.plan \ --test每个张量参数依次传入 6 个 shapemin/opt/max各 2 组脚本会创建两个 optimization profile 分别对应两个 batch 区间export_streaming_conformer_trt.py。--test模式会在导出后自动以batch1/4/8/16/32做正确性与延迟测试先 5 次 warm-up再统计 10 次推理的平均延迟、90/95/99 分位延迟与 QPSget_latency_result。当引擎存在两个 Profile 时测试代码会以 batch 阈值8自动选择 Profiletest 函数模拟服务端在大、小 batch 间切换 Profile 的调度策略。脚本还支持--useTimeCache将引擎构建时的 timing cache 序列化保存二次构建时可复用缓存以大幅缩短调优耗时export_streaming_conformer_trt.py。在run_streaming_small_model.sh的 Stage 5 中这条多 Profile 导出路径以注释形式保留便于按需启用python3 export_streaming_conformer_trt.py \ --fp16 \ --onnxFile $outputs_dir/encoderV4.onnx \ --chunk_xs ${MIN_BATCH1}x67x80,${OPT_BATCH1}x67x80,${MAX_BATCH1}x67x80,${MIN_BATCH2}x67x80,${OPT_BATCH2}x67x80,${MAX_BATCH2}x67x80 \ --chunk_lens ${MIN_BATCH1},${OPT_BATCH1},${MAX_BATCH1},${MIN_BATCH2},${OPT_BATCH2},${MAX_BATCH2} \ ... --plugin $outputs_dir/LayerNorm.so \ --trtFile $outputs_dir/encoder_fp16.plan \ --test || exit 1七、总结wenet 的 TensorRT Triton 方案给出了一条清晰可复制的流式 ASR GPU 服务化路径导出用 export_onnx_gpu.py 以--fp16 --streaming导出带缓存输入的流式编码器图优化先polygraphy常量折叠再用 replace_layernorm.py 把低效的 LayerNorm 子图替换为自研 LayerNormPlugin 融合算子引擎化trtexec或 export_streaming_conformer_trt.py 构建 FP16 动态 shape甚至多 Profileengine服务化convert.py 生成 Model RepositoryTriton 通过sequence_batching的 state 机制自动维护流式缓存Ensemble 把特征提取、编码、CTC 搜索、重打分串成单个对外模型验证Stage 5 提供了插件数值校验、多 Profile 正确性测试与 ONNX/TensorRT 吞吐对照。对于需要把 wenet 流式模型部署到 GPU 生产环境的开发者可以直接以 run_streaming_small_model.sh 为模板替换为自己训练的模型与配置再结合本文对各阶段参数的解析按需调整 batch、Profile 与内存池大小即可获得一套可复现、可扩展的高性能流式 ASR 服务。赞分享人工智能语音深度学习预训练模型推理服务【免费下载链接】wenetProduction First and Production Ready End-to-End Speech Recognition Toolkit项目地址https://gitcode.com/gh_mirrors/we/wenet点击查看免费下载相关推荐WeNet GPU加速部署终极指南TensorRT和Triton推理服务器配置教程WeNet GPU加速部署终极指南TensorRT和Triton推理服务器配置教程 WeNet是一款面向生产环境的端到端语音识别工具包Production人工智能语音深度学习预训练模型推理服务CosyVoice 加速部署实战基于 NVIDIA Triton 推理服务器与 TensorRT-LLM 的三套解决方案CosyVoice 加速部署实战基于 NVIDIA Triton 推理服务器与 TensorRT LLM 的三套解决方案 本文是 CosyVoice 仓库 r语音音频人工智能大模型微调预训练模型推理服务CosyVoice 基于 DiT Token2Wav 的 Triton TensorRT-LLM 服务化加速全指南CosyVoice 基于 DiT Token2Wav 的 Triton TensorRT LLM 服务化加速全指南 本指南以 CosyVoice 仓库 ru语音音频人工智能大模型微调预训练模型推理服务上一篇你的数字足迹会说话MouseTracks鼠标轨迹可视化工具深度解析下一篇如何用百灵快传实现手机电脑大文件秒传局域网文件共享的3大创新方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考