Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ hf download FunAudioLLM/fsmn-vad-GGUF fsmn-vad.gguf --local-dir .\gguf

## What's new

- 2026/07/19: **v1.3.21 on PyPI** — fixes first-import onboarding in fresh environments where users install `funasr` before choosing a platform-specific PyTorch build. `import funasr` and `funasr.__version__` now work without torch; accessing `AutoModel` still requires PyTorch and raises a clear install hint. Install with `python -m pip install -U "funasr==1.3.21"`. [Release ->](https://github.com/modelscope/FunASR/releases/tag/v1.3.21)
- 2026/07/19: **v1.3.20 on PyPI** — PyPI metadata and install guidance now point at the current FunASR docs, community integrations, and quoted `python -m pip install -U "funasr>=1.3.19"` commands for Fun-ASR-Nano deployment paths. This is a documentation/packaging sync; runtime code remains unchanged from v1.3.19. Install with `python -m pip install -U "funasr==1.3.20"`. [Release ->](https://github.com/modelscope/FunASR/releases/tag/v1.3.20)
- 2026/07/19: **v1.3.19 on PyPI** — realtime WebSocket long-session troubleshooting docs are now shipped with the package. Run the server with `--enable-spk --log-session-stats-interval 30` and attach the emitted `Session stats:` lines when reporting disconnects or memory growth. Install with `python -m pip install -U "funasr==1.3.19"`. [Long-session guide ->](docs/vllm_guide.md#long-session-diagnostics) · [Release ->](https://github.com/modelscope/FunASR/releases/tag/v1.3.19)
- 2026/07/19: **v1.3.18 on PyPI** — CLI SRT/TSV subtitle output now requests sentence timestamps and loads punctuation when needed, so `funasr audio.wav --output-format srt --output-dir ./subs` writes segmented subtitle cues instead of one full-text block. Install with `python -m pip install -U "funasr==1.3.18"`. [Release ->](https://github.com/modelscope/FunASR/releases/tag/v1.3.18)
Expand Down
1 change: 1 addition & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ Whisper 是单个模型,**FunASR 是一个工具箱**——按场景挑模型

## 最新动态

- 2026/07/19:**v1.3.21 已发布到 PyPI** — 修复全新环境里先安装 `funasr`、尚未选择平台对应 PyTorch 版本时的首次导入阻塞。现在 `import funasr` 和 `funasr.__version__` 不再因为缺少 torch 失败;真正访问 `AutoModel` 时仍会要求安装 PyTorch,并给出明确安装提示。安装命令:`python -m pip install -U "funasr==1.3.21"`。[发布页 →](https://github.com/modelscope/FunASR/releases/tag/v1.3.21)
- 2026/07/19:**v1.3.20 已发布到 PyPI** — PyPI 项目页和安装引导已同步到当前 FunASR 文档、社区集成列表,以及 Fun-ASR-Nano 部署路径中带引号的 `python -m pip install -U "funasr>=1.3.19"` 命令。本版本是文档/打包元数据同步,运行时代码与 v1.3.19 保持一致。安装命令:`python -m pip install -U "funasr==1.3.20"`。[发布页 →](https://github.com/modelscope/FunASR/releases/tag/v1.3.20)
- 2026/07/19:**v1.3.19 已发布到 PyPI** — 实时 WebSocket 长会话排障文档已随包发布。启动服务时加上 `--enable-spk --log-session-stats-interval 30`,如果仍遇到断连或内存增长,请在 issue 中附上输出的 `Session stats:` 日志。安装命令:`python -m pip install -U "funasr==1.3.19"`。[长会话诊断 →](docs/vllm_guide_zh.md#长会话诊断) · [发布页 →](https://github.com/modelscope/FunASR/releases/tag/v1.3.19)
- 2026/07/19:**v1.3.18 已发布到 PyPI** — CLI 的 SRT/TSV 字幕输出现在会请求句级时间戳,并在需要时加载标点模型;`funasr audio.wav --output-format srt --output-dir ./subs` 会输出分句字幕,不再退化成一个全文字幕块。安装命令:`python -m pip install -U "funasr==1.3.18"`。[发布页 →](https://github.com/modelscope/FunASR/releases/tag/v1.3.18)
Expand Down
34 changes: 31 additions & 3 deletions funasr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
_IMPORT_ERROR_TRACEBACKS = {}
_IMPORT_DEBUG = os.environ.get("FUNASR_IMPORT_DEBUG") == "1"
_STRICT_IMPORT = os.environ.get("FUNASR_STRICT_IMPORT") == "1"
_LAZY_EXPORTS = {
"AutoModel": ("funasr.auto.auto_model", "AutoModel"),
"AutoFrontend": ("funasr.auto.auto_frontend", "AutoFrontend"),
}


def _record_import_error(name, error):
Expand Down Expand Up @@ -73,7 +77,31 @@ def import_submodules(package, recursive=True):

import_submodules(__name__)

from funasr.auto.auto_model import AutoModel
from funasr.auto.auto_frontend import AutoFrontend

os.environ["HYDRA_FULL_ERROR"] = "1"


def __getattr__(name):
if name not in _LAZY_EXPORTS:
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

module_name, attr_name = _LAZY_EXPORTS[name]
try:
module = importlib.import_module(module_name)
except ModuleNotFoundError as error:
if error.name == "torch":
raise ModuleNotFoundError(
"FunASR requires PyTorch before using AutoModel. Install a "
"platform-appropriate torch build first, for example: "
"`python -m pip install torch torchaudio --index-url "
"https://download.pytorch.org/whl/cu126` for CUDA 12.6, "
"or follow https://pytorch.org/get-started/locally/.",
name="torch",
) from error
Comment on lines +91 to +99

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message is currently hardcoded to mention AutoModel. Since _LAZY_EXPORTS also contains AutoFrontend, attempting to import AutoFrontend when PyTorch is missing will raise an error message that confusingly refers to AutoModel.

We can make this dynamic by using the name parameter passed to __getattr__ to ensure the error message is accurate for whichever component is being imported.

Suggested change
if error.name == "torch":
raise ModuleNotFoundError(
"FunASR requires PyTorch before using AutoModel. Install a "
"platform-appropriate torch build first, for example: "
"`python -m pip install torch torchaudio --index-url "
"https://download.pytorch.org/whl/cu126` for CUDA 12.6, "
"or follow https://pytorch.org/get-started/locally/.",
name="torch",
) from error
if error.name == "torch":
raise ModuleNotFoundError(
f"FunASR requires PyTorch before using {name}. Install a "
"platform-appropriate torch build first, for example: "
"'python -m pip install torch torchaudio --index-url "
"https://download.pytorch.org/whl/cu126' for CUDA 12.6, "
"or follow https://pytorch.org/get-started/locally/.",
name="torch",
) from error

raise

value = getattr(module, attr_name)
globals()[name] = value
return value


__all__ = ["AutoModel", "AutoFrontend", "__version__", "get_import_errors", "get_import_error_tracebacks"]
2 changes: 1 addition & 1 deletion funasr/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.3.20
1.3.21
49 changes: 49 additions & 0 deletions tests/test_top_level_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import os
import subprocess
import sys
from pathlib import Path


def test_top_level_import_without_torch_succeeds():
repo_root = Path(__file__).resolve().parents[1]
script = r"""
import importlib.abc
import sys


class BlockTorch(importlib.abc.MetaPathFinder):
def find_spec(self, fullname, path=None, target=None):
if fullname == "torch" or fullname.startswith("torch."):
raise ModuleNotFoundError("No module named 'torch'", name="torch")
return None


sys.meta_path.insert(0, BlockTorch())

import funasr

print(funasr.__version__)
assert isinstance(funasr.get_import_errors(), dict)
try:
from funasr import AutoModel # noqa: F401
except ModuleNotFoundError as error:
assert error.name == "torch"
assert "requires PyTorch before using AutoModel" in str(error)
else:
raise AssertionError("AutoModel import should fail clearly when torch is missing")
"""

env = os.environ.copy()
env["PYTHONPATH"] = str(repo_root)
env.pop("FUNASR_STRICT_IMPORT", None)
result = subprocess.run(
[sys.executable, "-c", script],
cwd=repo_root,
env=env,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)

assert result.returncode == 0, result.stdout + result.stderr
Loading