如何部署在 Riva 上使用 NeMo 训练的自定义语言模型 (n-gram)
目录
如何部署在 Riva 上使用 NeMo 训练的自定义语言模型 (n-gram)#
本教程将引导您完成在 NVIDIA Riva 上部署使用 NVIDIA NeMo 训练的自定义语言模型 (n-gram) 的过程。
NVIDIA Riva 概述#
NVIDIA Riva 是一个 GPU 加速的 SDK,用于构建针对您的用例定制并提供实时性能的语音 AI 应用程序。
Riva 提供了一系列丰富的语音和自然语言理解服务,例如
自动语音识别 (ASR)。
文本到语音合成 (TTS)。
自然语言处理 (NLP) 服务集合,例如命名实体识别 (NER)、标点和意图分类。
在本教程中,我们将部署在 Riva 上使用 NeMo 训练的 ASR 语言模型 (n-gram)。
要了解 Riva ASR API 的基础知识,请参阅 Python 中 Riva ASR 入门。
要了解如何使用 NeMo 预训练和微调 ASR 的 n-gram 语言模型,请参阅 本教程。
有关 Riva 的更多信息,请参阅 Riva 产品页面 和 Riva 开发者文档。
NeMo (神经模块) 和 nemo2riva#
NVIDIA NeMo 是一个开源框架,用于使用简单的 Python 接口构建、训练和微调 GPU 加速的语音 AI 和自然语言理解 (NLU) 模型。要使用 NeMo 微调 Conformer-CTC 声学模型,请参阅 Conformer-CTC 微调教程。
nemo2riva 命令行工具提供了导出 .nemo 模型的功能,该模型可以使用 NVIDIA Riva 部署,NVIDIA Riva 是一个高性能应用程序框架,用于使用 GPU 的多模态对话式 AI 服务。nemo2riva 的 Python .whl 文件包含在 Riva 快速入门 资源文件夹中。您还可以使用 pip 安装 nemo2riva,如 Conformer-CTC 微调教程 中所示。
本教程探讨如何使用 .riva 模型(调用 nemo2riva CLI 工具的结果,请参阅 Conformer-CTC 微调教程)并利用 Riva ServiceMaker 框架来聚合 Riva 部署到目标环境所需的所有工件。一旦模型部署在 Riva 中,您就可以向服务器发出推理请求。我们将演示整个过程是多么快速和直接。在本教程中,您将学习如何
使用 Riva ServiceMaker 从
.riva文件构建.rmir模型管道。在本地 Riva 服务器上部署模型。
使用 Riva API 绑定从演示客户端发送推理请求。
先决条件#
在我们开始之前,请确保您已具备
访问 NVIDIA NGC 并能够下载 Riva 快速入门 资源。
您要部署的语言模型文件。
有关训练和导出 n-gram 语言模型的更多信息,请参阅 NeMo 语言建模文档。
语言模型文件可以是以下三种格式之一
.riva。您可以使用nemo2riva命令将.nemo模型文件转换为.riva模型文件。.binary。您可以从 Riva ASR LM NGC 模型页面 下载预训练版本。.arpa。您可以从 Riva ASR LM NGC 模型页面 下载预训练版本。
您要部署的
.riva格式的声学模型文件。您可以使用nemo2riva命令将.nemo模型文件转换为.riva模型文件。有关使用 NeMo 自定义 Conformer-CTC 声学模型并使用
nemo2riva导出结果模型的更多信息,请参阅 Conformer-CTC 微调教程。或者,您可以从 此处 获取英语 ASR 的预训练 Conformer-CTC
.riva模型。有关训练 NeMo 模型的更多信息,请参阅 NeMo 文档中的“训练”部分。
有关 Conformer-CTC 架构的更多信息,请参阅 NeMo ASR 模型页面中的“Conformer-CTC”部分。
有关使用 NeMo 训练 Conformer-CTC 所需的配置文件,请参阅 NeMo ASR 模型配置文件页面中的“Conformer-CTC”部分。
用于逆文本规范化 (ITN) 的加权有限状态转换器 (WFST) 分词器和动词化器文件。
有关 WFST 和 ITN 的更多信息,请参阅论文 NeMo 逆文本规范化:从开发到生产。
您可以从此 NVIDIA GPU Cloud (NGC) 模型页面下载预训练的 WFST ITN 模型文件。
解码器词汇表文件。您可以从 Riva ASR LM NGC 模型页面下载一个。
Riva ServiceMaker#
Riva ServiceMaker 是一组工具,用于聚合 Riva 部署到目标环境所需的所有工件(模型、文件、配置和用户设置)。它有两个主要组件
Riva-Build#
此步骤有助于构建模型的 Riva 就绪版本。它的唯一输出是 Riva 中支持的服务的端到端管道的中间格式(称为 RMIR)。让我们考虑一个 ASR n-gram 语言模型。
riva-build 负责将一个或多个导出的模型(.riva 文件)组合成一个包含中间格式的文件,该中间格式称为 Riva 模型中间表示 (.rmir)。此文件包含整个端到端管道的与部署无关的规范,以及最终部署和推理所需的所有资产。有关更多信息,请参阅 文档。
# IMPORTANT: UPDATE THESE PATHS
# Riva Docker
RIVA_CONTAINER = "<add container name>"
# Example:
# RIVA_CONTAINER = f"nvcr.io/nvidia/riva/riva-speech:{__riva_version__}"
# Directory where model files are stored,
# e.g. $MODEL_LOC/$ACOUSTIC_MODEL_NAME.riva
MODEL_LOC = "<add path to model location>"
# Name of the acoustic model .riva file
ACOUSTIC_MODEL_NAME = "<add model name>"
# Name of the language model .riva (or .arpa or .binary) file
LANGUAGE_MODEL_NAME = "<add model name>"
# Name of the decoder vocab file
DECODER_VOCAB_NAME = "<add decoder vocab file name>"
# Name of the WFST tokenizer
WFST_TOKENIZER = "<add WFST tokenizer model name>"
# Name of the WFST verbalizer
WFST_VERBALIZER = "<add WFST verbalizer model name>"
# Get the Riva Docker container
! docker pull $RIVA_CONTAINER
如果 MODEL_LOC 中尚不存在子目录,请创建它来存储 .rmir 文件。
! mkdir -p $MODEL_LOC/rmir
构建 .rmir 文件#
注意
如果您在调用
nemo2riva时添加了--key标志来加密您的声学模型和/或语言模型,或者您从 NGC 下载了 2023 年之前的预训练模型,则需要在riva-build命令中在模型名称后附加一个冒号,然后是密钥的值,如下所示。您可能会发现设置名为KEY的字符串变量并将$KEY作为参数传递到相应的riva-build参数中很方便。较旧的预训练模型的标准加密密钥是tlt_encode。如果您的语言模型是
.arpa格式,则在调用riva-build时,将/servicemaker-dev/$LANGUAGE_MODEL_NAME:$KEY替换为--decoding_language_model_arpa=/servicemaker-dev/$LANGUAGE_MODEL_NAME。如果您的语言模型是
.binary格式,则在调用riva-build时,将/servicemaker-dev/$LANGUAGE_MODEL_NAME:$KEY替换为--decoding_language_model_binary=/servicemaker-dev/$LANGUAGE_MODEL_NAME。如果您想为美国英语以外的支持语言构建 ASR 管道,请参阅 Riva ASR 管道配置文档。要获取适用于您的特定应用程序的正确
riva-build参数,请从页面第一部分底部的交互式 Web 菜单中选择声学模型(以下参数假设为 Conformer-CTC)、语言和管道类型(本教程的目的是离线)。
# Syntax:
# riva-build <task-name> \
# output-dir-for-rmir/model.rmir[:key] \
# dir-for-riva/acoustic_model.riva[:key] \
# dir-for-riva/lm_model.riva[:key]
! docker run --rm --gpus 1 -v $MODEL_LOC:/servicemaker-dev $RIVA_CONTAINER -- \
riva-build speech_recognition \
/servicemaker-dev/rmir/asr_offline_riva_ngram_lm.rmir \
/servicemaker-dev/$ACOUSTIC_MODEL_NAME \
/servicemaker-dev/$LANGUAGE_MODEL_NAME \
--decoding_vocab=/servicemaker-dev/$DECODER_VOCAB_NAME \
--wfst_tokenizer_model=/servicemaker-dev/$WFST_TOKENIZER \
--wfst_verbalizer_model=/servicemaker-dev/$WFST_VERBALIZER \
--name=offline_riva_ngram_lm_pipeline \
--chunk_size=4.8 \
--left_padding_size=1.6 \
--right_padding_size=1.6 \
--ms_per_timestep=40 \
--max_batch_size=16 \
--nn.fp16_needs_obey_precision_pass \
--language_code=en-US \
--decoder_type=flashlight \
--flashlight_decoder.asr_model_delay=-1 \
--flashlight_decoder.lm_weight=0.2 \
--flashlight_decoder.word_insertion_score=0.2 \
--flashlight_decoder.beam_threshold=20. \
--featurizer.use_utterance_norm_params=False \
--featurizer.precalc_norm_time_steps=0 \
--featurizer.precalc_norm_params=False \
--offline
Riva-Deploy#
部署工具将一个或多个 RMIR 文件和一个目标模型存储库目录作为输入。它创建一个集成配置,指定执行管道,最后将所有这些资产写入输出模型存储库目录。
注意: 如果您在使用 riva-build 构建 .rmir 文件时向其添加了加密密钥,请确保在 riva-deploy 命令中在模型名称后附加一个冒号,然后是密钥的值,如下所示。
# Syntax: riva-deploy -f dir-for-rmir/model.rmir[:key] output-dir-for-repository
! docker run --rm --gpus 0 -v $MODEL_LOC:/data $RIVA_CONTAINER -- \
riva-deploy -f /data/rmir/asr_offline_riva_ngram_lm.rmir /data/models/
启动 Riva 服务器#
生成模型存储库后,我们就可以启动 Riva 服务器了。首先,从 NGC 下载 Riva 快速入门 资源。在此处设置目录路径
# Set the Riva Quick Start directory
RIVA_DIR = "<Path to the uncompressed folder downloaded from quickstart(include the folder name)>"
接下来,我们修改 config.sh 文件以启用相关的 Riva 服务(n-gram 语言模型)、提供加密密钥以及模型存储库 (riva_model_loc) 的路径(在上一步中生成),以及其他配置。
例如,如果模型存储库在 $MODEL_LOC/models 中生成,则可以将 riva_model_loc 指定为与 MODEL_LOC 相同的目录。
在 models_asr/nlp/tts/nmt 中指定的模型的预训练版本是从 NGC 获取的。由于我们正在使用自定义模型,因此我们可以在 models_asr 中注释它(以及任何其他与您的用例无关的模型)。
config.sh 代码片段#
# Enable or Disable Riva Services
service_enabled_asr=true
service_enabled_nlp=true # MAKE CHANGES HERE - SET TO FALSE
service_enabled_tts=true # MAKE CHANGES HERE - SET TO FALSE
service_enabled_nmt=true # MAKE CHANGES HERE - SET TO FALSE
...
# Locations to use for storing models artifacts
#
# If an absolute path is specified, the data will be written to that location
# Otherwise, a docker volume will be used (default).
#
# riva_init.sh will create a `rmir` and `models` directory in the volume or
# path specified.
#
# RMIR ($riva_model_loc/rmir)
# Riva uses an intermediate representation (RMIR) for models
# that are ready to deploy but not yet fully optimized for deployment. Pretrained
# versions can be obtained from NGC (by specifying NGC models below) and will be
# downloaded to $riva_model_loc/rmir by `riva_init.sh`
#
# Custom models produced by NeMo or TLT and prepared using riva-build
# may also be copied manually to this location $(riva_model_loc/rmir).
#
# Models ($riva_model_loc/models)
# During the riva_init process, the RMIR files in $riva_model_loc/rmir
# are inspected and optimized for deployment. The optimized versions are
# stored in $riva_model_loc/models. The riva server exclusively uses these
# optimized versions.
riva_model_loc="riva-model-repo" # MAKE CHANGES HERE - REPLACE WITH $MODEL_LOC
if [[ $riva_target_gpu_family == "tegra" ]]; then
riva_model_loc="`pwd`/model_repository"
fi
# The default RMIRs are downloaded from NGC by default in the above $riva_rmir_loc directory
# If you'd like to skip the download from NGC and use the existing RMIRs in the $riva_rmir_loc
# then set the below $use_existing_rmirs flag to true. You can also deploy your set of custom
# RMIRs by keeping them in the riva_rmir_loc dir and use this quickstart script with the
# below flag to deploy them all together.
use_existing_rmirs=false # MAKE CHANGES HERE - set to true
注意 在继续之前,请确保执行以下操作
或者 手动执行这些任务
在 Jupyter Lab 的文件导航器中,导航到
$RIVA_DIR并打开config.sh按上述代码片段中所示配置设置
将 NLP、TTS 和 NMT 服务设置为
false将
riva_model_loc路径设置为也分配给MODEL_LOC的路径将变量
use_existing_rmirs设置为true
或者 运行下面的单元格
ENABLE_ASR = 'true'
ENABLE_NLP = 'false'
ENABLE_TTS = 'false'
ENABLE_NMT = 'false'
!sed -i "s|service_enabled_asr=.*|service_enabled_asr=$ENABLE_ASR|g" $RIVA_DIR/config.sh
!sed -i "s|service_enabled_nlp=.*|service_enabled_nlp=$ENABLE_NLP|g" $RIVA_DIR/config.sh
!sed -i "s|service_enabled_tts=.*|service_enabled_tts=$ENABLE_TTS|g" $RIVA_DIR/config.sh
!sed -i "s|service_enabled_nmt=.*|service_enabled_nmt=$ENABLE_NMT|g" $RIVA_DIR/config.sh
!sed -i "/\sriva_model_loc=.*/! s|riva_model_loc=.*|riva_model_loc=\"$MODEL_LOC\"|g" $RIVA_DIR/config.sh
!sed -i "s|use_existing_rmirs=.*|use_existing_rmirs=true|g" $RIVA_DIR/config.sh
# Ensure you have permission to execute these scripts
! cd $RIVA_DIR && chmod +x ./riva_init.sh && chmod +x ./riva_start.sh
# Run Riva Init. This will fetch the containers/models
# YOU CAN SKIP THIS STEP IF YOU ALREADY RAN RIVA DEPLOY
! cd $RIVA_DIR && ./riva_init.sh config.sh
# Run Riva Start. This will deploy your model.
! cd $RIVA_DIR && ./riva_start.sh config.sh
运行推理#
在 Riva 服务器启动并使用您的模型运行后,您可以发送推理请求来查询服务器。
要发送 gRPC 请求,您可以为客户端安装 Riva Python API 绑定。这可以作为 PyPI 上的 Python 模块使用。
# Install the Client API Bindings
! pip install nvidia-riva-client
import riva.client
连接到 Riva 服务器并运行推理#
调用此推理函数会查询 Riva 服务器(使用 gRPC)以转录音频文件。
def run_inference(audio_file, server='localhost:50051', print_full_response=False):
with open(audio_file, 'rb') as fh:
data = fh.read()
auth = riva.client.Auth(uri=server)
client = riva.client.ASRService(auth)
config = riva.client.RecognitionConfig(
language_code="en-US",
max_alternatives=1,
enable_automatic_punctuation=False,
)
response = client.offline_recognize(data, config)
if print_full_response:
print(response)
else:
print(response.results[0].alternatives[0].transcript)
现在我们可以实际查询 Riva 服务器了。
audio_file = "<add path to .wav (PCM-, A-Law-, or U-Law-encoded), .flac, .opus, or .ogg (Opus-encoded) file>"
run_inference(audio_file)
您可以在关闭 Jupyter 内核之前停止 Riva 服务器。
! cd $RIVA_DIR && ./riva_stop.sh