rich_transcription_postprocess() maps SenseVoice event tags through
event_dict, which used 🤧 for both <|Sneeze|> and <|Cough|>, so coughs
were displayed as sneezes. emoji_dict and event_set already use 😷 for
coughs; use it in event_dict too, in funasr and in the funasr_onnx and
funasr_torch runtime copies.
timestamp_sentence() stripped the trailing space from sentence_text_seg
on every token instead of once when the sentence is emitted, so the
per-sentence raw_text lost all separators ("iphone pro max" became
"iphonepromax"). Trim it only at the sentence boundary, as
timestamp_sentence_en() already does.
The fuzzy key was built with lazy_pinyin(errors="ignore"), which drops
every non-Chinese character. A window holding the hotword plus an
adjacent full stop, comma, digit or Latin letter got the same key as the
target and scored 1.0, and the tie-break on length then picked it, so
the replacement deleted that character. A Latin-only target such as
"FunASR" had an empty key and matched every Latin window of similar
length, overwriting the transcript.
Exact occurrences of a target were skipped but not reserved, so an
overlapping near match could still rewrite correct text and duplicate
the first character of the hotword.
Keep non-Chinese characters in the key, and drop a fuzzy candidate when
it overlaps an exact occurrence of the target it would write. Other
targets can still replace across that span, so a short target found
inside a longer one does not block the longer one.
Lower-cased Latin letters can spell pinyin, so a window with Latin
letters is only compared with targets that contain Latin letters, and a
window with Chinese characters only with targets that contain Chinese
characters. Targets that mix both scripts are compared with any window.
A window also may not start or end inside a run of ASCII letters or
digits, so a Latin target cannot rewrite part of a word or a number
(with target "Win11", "Win10" no longer becomes "Win110").
When punc_id_list is longer than timestamp_postprocessed (a mismatch
the function already logs a warning for), the entries past the end of
timestamp_postprocessed get timestamp=None from zip_longest. For the
sentence that starts on one of those entries, the is_sentence_start
flag was consumed unconditionally on the first iteration regardless of
whether timestamp was None, so sentence_start kept whatever value was
left over from the previous, unrelated sentence instead of being
reported as unknown.
The sibling function timestamp_sentence already handles this correctly
by resetting sentence_start to None after each flush and only setting
it once a real timestamp shows up. Mirror that logic here instead of
the one-shot is_sentence_start flag.
Before: a trailing sentence whose first word has no timestamp gets
start reused from the previous sentence (wrong, looks valid).
After: start is None for that sentence, matching timestamp_sentence.
* fix(amp): resolve autocast/GradScaler device type for non-CUDA accelerators
funasr/utils/amp.py pinned device_type="cuda" in the torch.amp compatibility shim, so on Ascend NPU (and XPU/MPS) builds torch.amp only warned "CUDA is not available ... Disabling autocast" and the context became a no-op: use_fp16/use_bf16 training silently ran in float32 and GradScaler(enabled=True) was silently disabled.
Resolve the device type from the running accelerator (torch.accelerator), the same policy funasr/models/fun_asr_nano/device_utils.py already applies to the inference path, and keep "cuda" as the historical no-op default when no accelerator is available so CPU behaviour is unchanged. GradScaler prefers an accelerator-specific implementation (e.g. torch.npu.amp.GradScaler) when one exists.
Signed-off-by: li-lizhe <[email protected]>
* fix(amp): honour an explicit device before choosing the GradScaler implementation
An explicit device (positional or keyword) now selects the scaler for that
device instead of the active accelerator, so GradScaler(device="cpu") no longer
reaches torch.npu.amp.GradScaler (its constructor has no device parameter and
raised TypeError) and GradScaler("cpu") no longer consumed "cpu" as init_scale.
The device argument is dropped before dispatching to an accelerator-specific
scaler and forwarded unchanged to the generic one; torch.cpu.amp is no longer
mistaken for a backend-specific scaler. Explicit keyword/positional/torch.device
coverage added.
Signed-off-by: li-lizhe <[email protected]>
* fix(amp): bind the generic GradScaler signature before native dispatch
The accelerator scalers do not share the generic torch.amp.GradScaler
positional order: torch_npu inserts `dynamic` before `enabled`, so
forwarding the caller's positional tail unchanged turned
GradScaler("npu", 1024.0, 2.0, 0.5, 2000, False) into an enabled static
scaler while the keyword form kept working. Bind a call written against
the generic signature to its parameter names first, drop the `device`
the accelerator constructor does not accept, and forward the rest by
name. Calls that do not match the generic signature keep the previous
plain re-export behaviour.
Tests: cover the positional enabled=False/True tail against a strict
torch_npu-signature stand-in (a *args/**kwargs recorder cannot detect a
shifted argument slot).
Signed-off-by: li-lizhe <[email protected]>
* docs(amp): narrow the _generic_arguments docstring claim
Signed-off-by: li-lizhe <[email protected]>
---------
Signed-off-by: li-lizhe <[email protected]>
Three modules use invalid escapes in non-raw string literals:
- fun_text_processing/text_normalization/normalize.py - \., \w
- funasr/models/fsmn_kws/encoder.py - \[
- funasr/models/fun_asr_nano/tools/format5res.py - \.
On Python 3.12+ each raises SyntaxWarning: invalid escape sequence on
import, and FunASR runs the 3.10-3.12 CI matrix. Escaping the
backslashes leaves every string value identical (ruff W605-style).
Claude-Session: https://claude.ai/code/session_014HBQNzAf5C2E3MiJC48HQw
Co-authored-by: Mehdi Boutayeb <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
* fix: use y.device instead of hardcoded .cuda() in data2vec compute_var
In compute_var(), zc = torch.tensor(y.size(0)).cuda() unconditionally
calls .cuda() which raises RuntimeError: Torch not compiled with CUDA
enabled on non-CUDA accelerators (Ascend NPU, XPU, HPU, MPS).
Use device=y.device to respect the input tensor's current device.
Signed-off-by: li-lizhe <[email protected]>
* test: add CPU/Gloo regression tests for data2vec compute_var
Cover both the uninitialized (no process group) branch and a real
2-rank Gloo process group with unequal local row counts, pinning the
device-agnostic contract introduced in the parent commit (PR #3710).
Signed-off-by: li-lizhe <[email protected]>
* fix(test): resolve compute_var import and f32_worker spawn pickle
* fix(test): ensure Manager and workers are cleaned up on failure paths
join(timeout) does not terminate a still-running worker, so a crashed or
hung rank could leak a subprocess on test failure. Wrap the two-rank
runner in try/finally that terminate()+join()s any alive worker and shuts
down the Manager.
Signed-off-by: li-lizhe <[email protected]>
---------
Signed-off-by: li-lizhe <[email protected]>
Apply ncpu to BLAS without rolling back torch OpenMP settings, compute only the required leading spectral pairs, and add regression coverage for repeated AutoModel construction and process-wide thread limits.
Record the verified release, package, website deployment, announcement, and model-card audit in the community growth ledger.
Signed-off-by: LauraGPT <[email protected]>
Prepare the 1.4.16 Python release, synchronize four-language release entry points, and make the native Transformers site contract follow the current package version.
Signed-off-by: LauraGPT <[email protected]>