项目文件夹

文件
wehub-resource-sync ba4be087d5
Create PR to main with cherry-pick from release / cherry-pick (push) Failing after 0s
CICD NeMo / pre-flight (push) Failing after 0s
CICD NeMo / configure (push) Has been skipped
Build, validate, and release Neural Modules / pre-flight (push) Failing after 1s
CICD NeMo / code-linting (push) Has been skipped
Build, validate, and release Neural Modules / release (push) Has been skipped
Build, validate, and release Neural Modules / release-summary (push) Has been cancelled
CICD NeMo / cicd-test-container-build (push) Has been cancelled
CICD NeMo / cicd-import-tests (push) Has been cancelled
CICD NeMo / L0_Setup_Test_Data_And_Models (push) Has been cancelled
CICD NeMo / cicd-main-unit-tests (push) Has been cancelled
CICD NeMo / cicd-main-speech (push) Has been cancelled
CICD NeMo / Nemo_CICD_Test (push) Has been cancelled
CICD NeMo / Coverage (e2e) (push) Has been cancelled
CICD NeMo / Coverage (unit-test) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
CICD NeMo / cicd-wait-in-queue (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:28:58 +08:00

119 行
5.1 KiB
Python

# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from dataclasses import dataclass
import torch
from omegaconf import MISSING, open_dict
from nemo.collections.asr.inference.utils.manifest_io import prepare_audio_data
from nemo.collections.asr.metrics.wer import word_error_rate
from nemo.collections.asr.models import EncDecRNNTBPEModel
from nemo.collections.asr.parts.context_biasing.biasing_multi_model import BiasingRequestItemConfig
from nemo.collections.asr.parts.context_biasing.boosting_graph_batched import BoostingTreeModelConfig
from nemo.collections.asr.parts.utils.manifest_utils import write_manifest
from nemo.collections.asr.parts.utils.rnnt_utils import Hypothesis
from nemo.collections.asr.parts.utils.transcribe_utils import get_auto_inference_device
from nemo.core.config import hydra_runner
from nemo.utils import logging
from nemo.utils.exceptions import NeMoBaseException
@dataclass
class TranscriptionBoostGroundTruthConfig:
dataset_manifest: str = MISSING
model_path: str | None = None # Path to a .nemo file
pretrained_name: str | None = None # Name of a pretrained model
batch_size: int = 128
boosting_alpha: float = 1.0
output_filename: str | None = None
device: str | None = None
@hydra_runner(config_name="TranscriptionBoostGroundTruthConfig", schema=TranscriptionBoostGroundTruthConfig)
def main(cfg: TranscriptionBoostGroundTruthConfig):
"""
Script to test per-utterance boosting. We boost ground truth tests with `asr_model.transcribe(...)`.
Sanity check: boosting ground truth should result in better WER (for CTC and RNN-T –
not always 0 even with high boosting weight if the transcription is inconsistent with the audio)
"""
# Reading audio filepaths
audio_filepaths, manifest, _, _ = prepare_audio_data(cfg.dataset_manifest, sort_by_duration=True)
logging.info(f"Found {len(audio_filepaths)} audio files")
assert manifest is not None, "This script works only with manifest"
device = torch.device(cfg.device) if cfg.device is not None else get_auto_inference_device()
asr_model: EncDecRNNTBPEModel
if cfg.model_path is not None:
asr_model = EncDecRNNTBPEModel.restore_from(cfg.model_path)
elif cfg.pretrained_name is not None:
asr_model = EncDecRNNTBPEModel.from_pretrained(model_name=cfg.pretrained_name)
else:
raise NeMoBaseException("Either `model_path` or `pretrained_name` should be not None")
assert isinstance(asr_model, EncDecRNNTBPEModel), "Only RNN-T model supported"
asr_model.to(device)
# Change Decoding Config: ensure greedy_batch + label-looping enabled
with open_dict(asr_model.cfg.decoding):
asr_model.cfg.decoding.strategy = "greedy_batch"
asr_model.cfg.decoding.greedy.loop_labels = True
asr_model.cfg.decoding.greedy.enable_per_stream_biasing = True
asr_model.change_decoding_strategy(asr_model.cfg.decoding)
batch_size = cfg.batch_size
for start_batch_i in range(0, len(manifest), batch_size):
end_batch_i = min(start_batch_i + batch_size, len(manifest))
# use transcribe with empty partial hypotheses with boosting requests with one phrase
results = asr_model.transcribe(
audio=audio_filepaths[start_batch_i : start_batch_i + batch_size],
partial_hypothesis=[
Hypothesis.empty_with_biasing_cfg(
biasing_cfg=BiasingRequestItemConfig(
boosting_model_cfg=BoostingTreeModelConfig(
key_phrases_list=[manifest[i]["text"]],
),
boosting_model_alpha=cfg.boosting_alpha,
),
)
for i in range(start_batch_i, end_batch_i)
],
return_hypotheses=True,
batch_size=end_batch_i - start_batch_i,
)
for i, result in zip(range(start_batch_i, end_batch_i), results):
manifest[i]["pred_text"] = result.text
cer = word_error_rate(
hypotheses=[record["pred_text"] for record in manifest],
references=[record["text"] for record in manifest],
use_cer=True,
)
wer = word_error_rate(
hypotheses=[record["pred_text"] for record in manifest],
references=[record["text"] for record in manifest],
use_cer=False,
)
logging.info(f"Dataset WER/CER {wer:.2%}/{cer:.2%}")
# Dump the transcriptions to a output file
if cfg.output_filename is not None:
write_manifest(output_path=cfg.output_filename, target_manifest=manifest)
logging.info("Done!")
if __name__ == "__main__":
main()