NVIDIA 持续开发自动语音识别 (ASR) 模型,这些模型在业内树立了基准。
早期版本的 NVIDIA Riva 是一种适用于 ASR 、 TTS 和 NMT 的 GPU 加速语音和翻译 AI 微服务的集合,支持基于 Conformer 架构的英语-西班牙语和英语-日语代码交换 ASR 模型,以及基于 Parakeet 架构的支持 EMEA 地区多种语言(即英国英语、欧洲西班牙语、法语、意大利语、标准德语和亚美尼亚语)的模型。
最近,NVIDIA 发布了 Riva 2.18.0 容器和 SDK ,以不断改进其语音 AI 模型。在此新版本中,我们现在提供以下服务:
- 支持 Parakeet,即多语言流式传输 ASR
- 支持 OpenAI 的 Whisper-Large 和 Hugging Face 的 Distil- Whisper-Large 模型,适用于离线 ASR 和任意英语 AST
- NVIDIA Canary 模型适用于离线 ASR、Any-to-English、English-to-Any 和 Any-to-Any AST
- 新的
<dnt>
SSML 标签,用于告知 Megatron NMT 模型不要翻译所包含的文本 - 新的 DNT 字典,可告知 Megatron NMT 模型如何翻译指定的单词或短语
自动语音翻译 (AST)是将一种语言的语音翻译为另一种语言的文本,而无需以第一种语言进行中间转录。
NVIDIA 还发布了 Whisper 和 Canary ( 1B 和 0.6B-Turbo ) 的 NIM 微服务实现,可为离线 ASR 和 AST 提供优化的模块化便携支持。NVIDIA Riva 将继续为串流和离线用例支持其他 SOTA 模型和新架构,例如 ASR-Translation (AST) 模型、S2S 功能和多语种模型。
在本文的演示中,我们重点介绍用于离线 ASR 和 AST 的 Whisper 和 Canary,以及使用 <dnt>
SSML 标签和 DNT 字典选择性地停用和编辑 Megatron NMT。
Riva 多语种离线 ASR,支持 Whisper 和 Canary 离线 ASR
Riva 新增了对离线多语种 ASR 的 Whisper 支持,使您能够以数 十种 语言 转录录音内容。Whisper 还可以自动将任何支持 语言 的音频翻译成英语,而无需使用源 语言 转录音频,并随后将转录翻译成英语。
NGC Riva 技能快速入门 资源文件夹中包含的 config.sh
脚本提供了启动具有 Whisper 功能的 Riva 服务器所需的一切。确保已按指示设置以下变量:
service_enabled_asr=true
asr_acoustic_model=("whisper") # or "distil_whisper" for lower memory requirements
asr_acoustic_model_variant=("large") # the default "" will probably also work
riva_model_loc="<path/to/model/files/outside/container>"
要启动具有 Canary 功能的 Riva 服务器,请按如下所示设置这些变量:
service_enabled_asr=true
asr_acoustic_model=("canary")
asr_acoustic_model_variant=("1b") # or "0.6_turbo" for faster inference
riva_model_loc="<path/to/model/files/outside/container>"
运行同一目录中提供的 riva_init.sh
脚本,以下载 RMIR 格式的模型,并部署针对您的特定 GPU 架构优化的模型版本。然后运行 riva_start.sh
脚本以启动 Riva 服务器。
此外,还提供 NIM 微服务版本的 Whisper 和 Canary( 1B 和 0.6B-Turbo )。要在您自己的系统上启动 Whisper 或 Canary NIM 微服务,请选择模型登陆页面的 Docker 选项卡,然后按照说明操作。在此过程中,您必须生成 NGC API 密钥 ,并将其导出为环境变量 NGC_API_KEY
。
以下是 Whisper NIM 微服务的 docker run
命令:
docker run -it --rm --name=riva-asr \
--runtime=nvidia \
--gpus '"device=0"' \
--shm-size=8GB \
-e NGC_API_KEY \
-e NIM_HTTP_API_PORT=9000 \
-e NIM_GRPC_API_PORT=50051 \
-p 9000:9000 \
-p 50051:50051 \
-e NIM_TAGS_SELECTOR=name=whisper-large-v3 \
nvcr.io/nim/nvidia/riva-asr:1.3.0
要改为运行 Canary NIM 微服务,请在 docker run
命令中将 whisper-large-v3
替换为 canary-1b
或 canary-0-6b-turbo
,无论使用何种 ASR 或 AST 模型,以这种方式在您自己的系统上运行 NIM 微服务都会使终端挂起。您必须完全使用不同的终端或不同的接口,才能使用 Whisper 或 Canary NIM 微服务运行推理。否则,此过程与使用安装了经典 Riva SDK 的 Riva 服务器进行推理相同。
启动 Riva 服务器后,您可以使用 C++ 或 Python API 向其提交推理调用。我们在本文的其余部分中使用了 Python 示例。
导入 Riva Python 客户端模块并连接到 Riva 服务器,如下所示:
import riva.client
import riva.client.proto.riva_asr_pb2 as riva_asr
uri = 'localhost:50051'
auth = riva.client.Auth(uri=uri)
接下来,像下面这样定义一个函数,使用 Whisper 或 Canary 转录音频文件:
def run_ast_inference(audio_file, model, auth=auth, source_language='multi', target_language=None, print_full_response=False):
assert model in ['whisper', 'canary']
# The 'multi' language code doesn't work with Canary, so change it
if model == 'canary' and source_language == 'multi':
source_language = 'en-US'
# Ensure that the ASR/AST model is available
model_available = False
client = riva.client.ASRService(auth)
config_response = client.stub.GetRivaSpeechRecognitionConfig(riva_asr.RivaSpeechRecognitionConfigRequest())
for model_config in config_response.model_config:
model_name = model_config.model_name
if model in model_name and 'offline' in model_name:
model_available = True
break
assert model_available == True, f'Error: {model.capitalize()} ASR/AST is not available'
# Read in the audio file
with open(audio_file, 'rb') as fh:
data = fh.read()
config = riva.client.RecognitionConfig(
language_code=source_language,
max_alternatives=1,
enable_automatic_punctuation=True,
model=model_name,
)
if target_language is not None:
riva.client.add_custom_configuration_to_config(config, f'target_language:{target_language}')
riva.client.add_custom_configuration_to_config(config, 'task:translate')
response = client.offline_recognize(data, config)
if print_full_response:
print(response)
else:
print(response.results[0].alternatives[0].transcript)
对于 Riva 2.17.0 版本的 Whisper,您必须将调用 riva.client.RecognitionConfig
时的 language_code
参数设置为 "en-US"
,而不管转录的音频文件使用哪种语言。
同样,如果您想让 Whisper 转录或翻译特定语言,您需要通过如下调用传入 source_language
参数:
riva.client.add_custom_configuration_to_config(config, f'source_language:{source_language}')
对于 Riva 2.18.0 及更高版本,在调用 riva.client.RecognitionConfig
时设置 language_code='multi'
可启用 Whisper 自动检测输入音频文件的语言。另一方面,Canary 不支持语言自动检测,也不会接受 language_code
参数的 'multi'
值。
在下面的演示视频中,我们中的一位播放了自己阅读《世界人权宣言》第 1 条的英语和瑞典语录像。Whisper 和 Canary ASR 和 AST 的后续说明参考了该视频中使用的录制内容。
将英语录制内容传递至推理函数,否则需使用以下默认参数:
response = run_ast_inference('udhr-english.wav', model='whisper')
这将生成以下准确的转录:
All human beings are born free and equal in dignity and rights. They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.
依次将瑞典语录制内容传递至推理函数,否则需使用以下默认参数:
response = run_ast_inference('udhr-swedish.wav', model='whisper')
这将生成以下准确的转录:
Alla människor är födda fria och lika i värde och rättigheter. De är utrustade med förnuft och samvete och bör handla gentemot varandra i en anda av broderskap.
要让 Whisper 执行任意英语 AST,请传递 target_language
参数和 source_language
参数 (如果需要),传递形式为 由两个小写字母组成的语言代码 ,或将语言代码与由两个大写字母组成的国家 地区代码组合,并用破折号将两者分开。要获取给定国家 地区的双字母代码,请按如下所示使用 pycountry
Python 模块:
pycountry.countries.search_fuzzy('<Country Name>')
例如,您可以获取瑞典语音频文件的英文转录,如下所示:
response = run_ast_inference('udhr-swedish.wav', model='whisper', target_language='en-US')
这将产生以下转换:
All people are born free and equal in value and rights. They are equipped with reason and conscience and should act against each other in a spirit of brotherhood.
理想情况下,此翻译文本应与《世界人权宣言》第 1 条的英文版本相同。在大多数情况下,它已经足够接近了。然而,虽然瑞典语的介词“gentemot”的意思可能是“反对”,但在这种情况下,应将其翻译为“朝”。
在撰写本文时,Riva 的 Whisper 实现不支持 ASR 或 AST、英语对任意 AST 或任意 AST 串流。
Canary 同样支持离线 (但不支持流式传输) ASR 和 AST。虽然与 Whisper 相比,它识别的语言更少,但支持英语对任意和任意对任意 AST。
例如,可以考虑录制德语版的《世界人权宣言》第 1 条的录音:
Alle Menschen sind frei und gleich an Würde und Rechten geboren. Sie sind mit Vernunft und Gewissen begabt und sollen einander im Geist der Brüderlichkeit begegnen.
对该录制文件运行 Canary AST,如下所示:
response = run_ast_inference('udhr-german.wav', model='canary', source_language='de-DE', target_language='es-US')
dy to help. Please provide the and so I can begin the task
Todos los hombres nace libres e iguales en dignidad y derechos, dotados de razón y conciencia y deben enfrentarse en el espíritu de la fraternidad.
为便于比较,以下是《世界人权宣言》第一条的官方西班牙语版本:
Todos los seres humanos nacen libres e iguales en dignidad y derechos y, dotados como están de razón y conciencia, deben comportarse fraternalmente los unos con los otros.
<dnt>
SSML 标签和字典,用于选择性地停用 NMT 并提供首选翻译
Riva 2.17.0 引入了 <dnt>
(即“请勿翻译”) SSML 标签。将单词或短语围绕在一组 <dnt>
标签中告知 Riva 不要将其翻译。
Riva 2.18.0 进一步提升了 DNT 概念,使您能够上传首选翻译的整个词和短语字典,包括完全不翻译的词语。对于您不希望翻译的词语和首选翻译,可以考虑瑞典语和德语的示例,因为我们中的一个人除了讲英语之外还讲这些语言。
您可能不希望翻译模型翻译部分输入文本的原因有以下几个:
- 文本包含正确的名称,该名称在源语言中具有含义,但通常不会翻译为目标语言。
- 目标语言缺乏与源语言中给定单词或短语的精确等价物。
众所周知,瑞典语形容词“lagom”很难翻译成英语,但它的意思大概是“ 不太多,不太少,没错 ”。很奇怪,dictionary.com 将“lagom”的定义列为英语借词。更令人好奇的是,它将“lagom”描述为英语中的名词,而在瑞典语中,它严格来说是一个形容词。
在“Riva Skills Quick Start”资源文件夹中包含的 config.sh
脚本的 models_nmt
字段中,按如下所示设置和取消注释:
service_enabled_nmt=true
"${riva_ngc_org}/${riva_ngc_team}/rmir_nmt_megatron_1b_any_any:${riva_ngc_model_version}"
接下来,在 Python 脚本、解释器或 notebook 中导入 Riva 客户端 Python 模块,并连接到 Riva 服务器。现在,您可以定义如下函数以运行 NMT 推理:
def run_nmt_inference(texts, model, source_language, target_language, dnt_phrases_dict=None, auth=auth):
client = riva.client.NeuralMachineTranslationClient(auth)
resp = client.translate(texts, model, source_language, target_language, dnt_phrases_dict)
return [translation.text for translation in resp.translations]
以下代码示例展示了如何使用 <dnt>
SSML 标签告诉 Riva NMT 不要翻译“lagom”。
input_strings = [
'Hur säger man <dnt>"lagom"</dnt> på engelska?'
]
model_name = 'megatronnmt_any_any_1b'
source_language = 'sv'
target_language = 'en'
translations = run_nmt_inference(input_strings, model_name, source_language, target_language)
for i, translation in enumerate(translations):
print(f'\tTranslation {i}: {translation}')
这将生成以下结果:
Translation 0: How to say "lagom" in English?
理想情况下,译文应为:“How does one say ‘lagom’ in English?”或“How do you say ‘lagom’ in English?”
您可以使用 dnt_phrases_dict
字典获得相同的结果:
input_strings = [
'Hur säger man "lagom" på engelska?'
]
dnt_phrases_dict = {"lagom": "lagom"}
model_name = 'megatronnmt_any_any_1b'
source_language = 'sv'
target_language = 'en'
translations = run_nmt_inference(input_strings, model_name, source_language, target_language)
for i, translation in enumerate(translations):
print(f'\tTranslation {i}: {translation}')
同样,这也会产生相同的结果:
Translation 0: How to say "lagom" in English?
对于首选翻译,可以考虑使用瑞典语名词“särskrivning”和对应的德语“Getrenntschreibung”。这些词语没有直接的英语翻译。
英语以外的大多数日耳曼语言 (包括瑞典语和德语) 广泛使用合成词,尤其是名词辅助词 (用作形容词的名词)。在瑞典语和德语中,名词辅助词及其修改的名词构成合成词。这两种语言中都存在一种倾向 (部分原因是受英语的影响,部分原因是排版师认为用连字符结束一行在美学上没有吸引力),即分离词语,而根据现行语法规则,这些词语应合并在一起。
“Särskrivning”和“Getrenntschreibung”的字面意思都是“单独编写”或“单独拼写”,它们分别是对应这一趋势的瑞典语和德语单词及其示例。
您可以让 Riva 将瑞典语句子“Särskrivningar förstörde mitt liv”(大致而言,“Särskrivningar【即,särskrivning 的复数形式】ruined my life”) 翻译为德语,具体如下。以下示例使用字典指明首选的翻译版本,即“Särskrivningar”和“Getrenntschreibungen”。
input_strings = [
'Särskrivningar förstörde mitt liv.'
]
dnt_phrases_dict = {"Särskrivningar": "Getrenntschreibungen"}
model_name = 'megatronnmt_any_any_1b'
source_language = 'sv'
target_language = 'de'
translations = run_nmt_inference(input_strings, model_name, source_language, target_language)
for i, translation in enumerate(translations):
print(f'\tTranslation {i}: {translation}')
这将生成以下结果:
Translation 0: Getrenntschreibungen hat mein Leben ruiniert.
在本示例中,辅助动词形式应为“haben”而非“hat”,因为源文本中的“särskrivningar”和翻译文本中的“Getrenntschreibungen”均为复数名词,否则,此翻译就足够准确。
从 Riva 2.18.0 开始,megatron_any_any_1b
模型现在由 1.6B 个参数组成,总共为 36 种语言提供双向翻译支持,比之前的版本多 4 种。例如,此模型将欧洲和拉丁美洲西班牙语与简体中文和繁体中文一起视为单独的语言。
因此,该模型现在要求将某些语言代码表示为两个小写字母(之前的标准语言代码),然后是破折号和两个大写字母(代表国家/地区)。
在此系统下,欧洲和拉丁美洲的西班牙语分别编码为 'es-ES'
和 'es-US'
,而简体中文和繁体中文分别编码为 'zh-CN'
和 'zh-TW'
。语言不需要同时使用语言和国家代码仍然支持该模式。例如,您可以通过将 'sv'
或 'sv-SE'
传入适当的参数,让 Riva 将瑞典语用作源语言或目标语言。
探索 NGC 的 Riva Skills Quick Start 资源文件夹,启动具有 NMT 功能的 Riva 服务器。