5986 Commits
Author SHA1 Message Date
Grapette.L e7e61293d3 fix(frontend): read cmvn statistics without crashing on blank lines (#3760)
Both package cmvn readers index line_item[0] and lines[i + 1] without
checking, so a blank or whitespace-only line anywhere in the file
(trailing newline at EOF, a separator between sections) aborts frontend
construction with IndexError, and a file whose tags the walker does not
recognize returns empty statistics that only fail much later at inference.
Skip blank lines, bound the lookahead, and raise a ValueError naming the
file when neither <AddShift> nor <Rescale> parsed.
2026-10-08 14:50:05 +08:00
Pratik Gandhi 75494e73ea docs: fix contact image paths in runtime SDK tutorials (#3764) 2026-10-08 14:42:44 +08:00
zhifu gaoandLauraGPT 1af45b9a49 ci: cover timestamp and Paraformer hotword regressions (#3765)
Signed-off-by: LauraGPT <[email protected]>
Co-authored-by: LauraGPT <[email protected]>
2026-10-08 14:25:24 +08:00
Mohammad Hijjawi 8f8931dc9a fix(paraformer): skip blank lines and read hotword files as UTF-8 (#3761)
SeACo-Paraformer and Contextual Paraformer turn every line of a hotword
.txt file into a hotword. A blank line (e.g. an extra newline at the end
of the file) became an empty hotword, and its zero length made
pack_padded_sequence raise "Length of all samples has to be greater
than 0" in the bias encoder, so inference failed.

The file was also opened with codecs.open() without an encoding, i.e.
the locale encoding. On Windows a UTF-8 Chinese hotword file decoded
into mojibake, so every hotword became <unk> (or reading raised
UnicodeDecodeError on GBK locales).

Read the local and downloaded hotword files as UTF-8 and skip blank
lines, matching parse_hotword_file() in funasr/utils/postprocess_hotwords.py.
2026-10-08 14:09:17 +08:00
Grapette.LandLesereingrape 22b42827a0 fix(auto): skip blank lines when reading wav.scp and jsonl file lists (#3758)
A blank or whitespace-only line in a file list crashes prepare_data_iterator:
the id/data branch indexes lines[0] on an empty split (IndexError), and the
.jsonl branch feeds an empty string to json.loads (JSONDecodeError). Skip
blank lines so a trailing or separator line no longer aborts the whole batch.

Co-authored-by: Lesereingrape <[email protected]>
2026-10-08 14:08:32 +08:00
Chi-Wei Lee d77b31d8c2 fix: retain unpunctuated tail in sentence timestamps (#3754) 2026-10-08 14:07:12 +08:00
Hulk d98f6eee4d fix(auto-model): preserve resampled rate for speaker inference (#3763) 2026-10-08 13:37:51 +08:00
zhifu gaoandLauraGPT 66d7a4c264 fix(realtime): recover merged long-segment partials (#3755)
Signed-off-by: LauraGPT <[email protected]>
Co-authored-by: LauraGPT <[email protected]>
2026-10-02 12:50:16 +08:00
zhifu gao 14f12f1dc0 docs(ops): make site monitoring aware of log rotation (#3753)
docs(ops): make site monitoring aware of log rotation
2026-10-02 09:29:24 +08:00
LauraGPT dce73ccb98 docs(ops): make site monitoring aware of log rotation
Signed-off-by: LauraGPT <[email protected]>
2026-10-02 00:02:05 +00:00
zhifu gao 2ddbd3d997 Merge pull request #3752: cover CLI regressions in CPU NumPy checks
ci: cover CLI regressions in CPU NumPy checks
2026-10-02 05:55:55 +08:00
LauraGPT cfc8c47708 ci: cover CLI regressions in CPU NumPy checks
Signed-off-by: LauraGPT <[email protected]>
2026-10-01 21:52:13 +00:00
zhifu gao bb303f85ea Merge pull request #3751: explicit PCM16 input and VAD source rates
feat(audio): support explicit PCM16 input without container probing
2026-10-02 00:40:50 +08:00
LauraGPT 2d6cb0ed21 ci: install ffmpeg for audio byte regression coverage
Signed-off-by: LauraGPT <[email protected]>
2026-10-01 16:01:50 +00:00
LauraGPT 9d611293f4 feat(audio): support explicit PCM16 input without container probing
Signed-off-by: LauraGPT <[email protected]>
2026-10-01 15:17:23 +00:00
zhifu gao 4a84879ae8 ci: run rich transcription regressions in ONNX package checks (#3749)
ci: run rich transcription regressions in ONNX package checks
2026-10-01 16:50:21 +08:00
LauraGPT afd5c88ee2 ci: run rich transcription regressions in ONNX package checks
Signed-off-by: LauraGPT <[email protected]>
2026-10-01 08:47:20 +00:00
zhifu gao 800f7565e8 fix(runtime): skip empty deduplicated event segments (#3748)
fix(runtime): skip empty deduplicated event segments
2026-10-01 13:01:25 +08:00
LauraGPT d7a33c862c Merge main with timestamp and event mapping fixes
Signed-off-by: LauraGPT <[email protected]>
2026-10-01 04:58:02 +00:00
LauraGPT 643f443ba2 fix(runtime): skip empty deduplicated event segments
Signed-off-by: LauraGPT <[email protected]>
2026-10-01 04:54:48 +00:00
Mohammad Hijjawi 217d10aa99 fix(sensevoice): stop rendering the Cough event as the Sneeze emoji (#3747)
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.
2026-10-01 12:49:24 +08:00
Mohammad Hijjawi b0fa25b12c fix: keep token separators in timestamp_sentence raw_text (#3746)
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.
2026-10-01 12:48:39 +08:00
Chi-Wei Lee 43329e8cef fix(hotwords): stop fuzzy postprocess matching from rewriting nearby text (#3744)
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").
2026-10-01 12:47:56 +08:00
zhifu gao 23f50baacb docs(ops): record verified product-site release (#3745)
docs(ops): record verified product-site release
2026-10-01 07:18:31 +08:00
LauraGPT 2cae67958e docs(ops): record verified product-site release
Signed-off-by: LauraGPT <[email protected]>
2026-09-30 22:34:56 +00:00
zhifu gao 460f006754 docs: surface merged speech-to-speech SenseVoice integration (#3743)
docs: surface merged speech-to-speech SenseVoice integration
2026-10-01 00:57:08 +08:00
LauraGPT a31746dea0 docs: surface merged speech-to-speech SenseVoice integration
Signed-off-by: LauraGPT <[email protected]>
2026-09-30 16:36:43 +00:00
Chi-Wei Lee be7557f27c fix: stop timestamp_sentence_en reusing a stale sentence start (#3741)
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.
2026-09-30 22:52:09 +08:00
zhifu gao 7b098acefc fix(auto): warn when unavailable accelerators fall back to CPU (#3742)
fix(auto): warn when unavailable accelerators fall back to CPU
2026-09-30 20:42:24 +08:00
LauraGPT 9c9067f334 fix(auto): warn when unavailable accelerators fall back to CPU
Signed-off-by: LauraGPT <[email protected]>
2026-09-30 12:02:57 +00:00
li-lizhe 7f85ddd299 fix(amp): resolve autocast/GradScaler device type for non-CUDA accelerators (#3735)
* 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]>
2026-09-30 16:48:49 +08:00
zhifu gao e9d002b54d docs: diagnose actual AutoModel GPU placement (#3740)
docs: diagnose actual AutoModel GPU placement
2026-09-30 15:37:12 +08:00
LauraGPT 03e18dccb1 docs: explain actual AutoModel device placement
Signed-off-by: LauraGPT <[email protected]>
2026-09-30 06:56:53 +00:00
zhifu gao 12e417f4fa Merge pull request #3736: correct LiteLLM website transcription route
Validate the combined website and SenseVoice tree against current main.

Signed-off-by: LauraGPT <[email protected]>
2026-09-29 14:43:39 +08:00
zhifu gao 15c1959811 Merge pull request #3737: preserve SenseVoice word boundaries
Normalize leading and standalone SentencePiece boundaries and add CPU timestamp regression coverage.

Signed-off-by: LauraGPT <[email protected]>
2026-09-29 14:26:04 +08:00
LauraGPT a57cc3f92a fix(sensevoice): keep words separate at standalone boundaries
Signed-off-by: LauraGPT <[email protected]>
2026-09-29 06:12:59 +00:00
LauraGPT 2ddabb2c91 fix(sensevoice): normalize first word before joining subpieces
Signed-off-by: LauraGPT <[email protected]>
2026-09-29 05:58:08 +00:00
LauraGPT f950854db3 fix(website): correct LiteLLM transcription route and guards
Signed-off-by: LauraGPT <[email protected]>
2026-09-29 03:10:14 +00:00
zhifu gao 55203a9995 feat(benchmark): report first nonempty transcript latency (#3734)
feat(benchmark): report first nonempty transcript latency
2026-09-28 21:57:23 +08:00
LauraGPT 99ef3b727b feat(benchmark): report first nonempty transcript latency
Signed-off-by: LauraGPT <[email protected]>
2026-09-28 13:36:31 +00:00
zhifu gao e1ceba0aa8 Merge pull request #3733 from modelscope/codex/speaker-overlap-accounting-20260928
fix: assign sentence speakers by total overlap without double counting
2026-09-28 20:55:07 +08:00
LauraGPT e7006a9315 fix: count speaker overlap once per diarization segment
Signed-off-by: LauraGPT <[email protected]>
2026-09-28 12:50:06 +00:00
da12182b6b Fix invalid escape sequences in text normalization and models (#3709)
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]>
2026-09-28 16:08:01 +08:00
Jingguo Yao 2d4566d4a4 Remove unused imports (#3731)
Removes two unused slice_padding_audio_samples imports.
2026-09-27 11:17:40 +08:00
YYDH 9e7f6af8c3 fix: avoid deep-copying the checkpoint in load_pretrained_model (#3729) 2026-09-26 18:56:23 +08:00
Bruce-YiiandBruce-Yii 41778c45de fix(nano): correct punctuation timestamps across VAD merges (#3703)
* fix(nano): correct punctuation timestamps across VAD merges

Anchor zero-acoustic-mass punctuation at the preceding spoken token end (FunASR #3702). Reviewed patch only.

* fix(nano): keep byte-fragment spoken timestamps

* test(nano): cover byte-fragment timestamp preservation

* fix(nano): preserve semantic symbol timestamp spans

* test(nano): preserve semantic symbol timestamp spans

---------

Signed-off-by: Bruce-Yii <[email protected]>
Co-authored-by: Bruce-Yii <[email protected]>
2026-09-25 10:16:47 +08:00
LiuZi816 3ff9259aad docs: 新增《在昇腾 NPU 上运行 FunASR》指南 (#3708)
* Create ascend_npu.md

* Update ascend_npu.md

* Update ascend_npu.md

* docs: 补全 funasr 1.3.14 声明依赖清单并区分镜像预装

补全 hydra-core、modelscope、huggingface_hub、safetensors、transformers、tiktoken 等全部声明依赖(取自 PyPI 1.3.14 元数据),注明目标版本;区分常见 NPU 镜像预装与需手动安装的包;标注此前 dry-run 解析出的 7 个包为该环境当次差异、非通用依赖表。回应 #3707 的审查意见。

* docs: 固定 funasr==1.3.14 并限定 torch 配对论述的适用范围

安装命令钉到 1.3.14,与依赖清单及验证环境一致;将已配对 torch 不被解析触碰的结论限定到 #3707 的 dry-run 环境与命令;写明 --no-deps 仅覆盖第一条命令、后续普通 pip 安装仍解析传递依赖,建议安装前 dry-run 检查或用 constraint 固定 torch。
2026-09-24 10:18:09 +08:00
zhifu gao 02f8b43fc9 docs(nano): clarify training-speed evidence and release scope (#3725)
docs(nano): clarify training-speed evidence and release scope
2026-09-21 19:42:39 +08:00
zhifu gao f027d65110 docs(nano): clarify training speed evidence and release scope
Signed-off-by: zhifu gao <[email protected]>
2026-09-21 11:36:49 +00:00
zhifu gao 8d8a1a6b6e docs: note mixed-device support in PyPI 1.4.16 (#3724)
docs: note mixed-device support in PyPI 1.4.16
2026-09-21 18:34:47 +08:00