Skip to content

Error Analysis and Solution for paraformer-zh is not registered

Error Analysis and Solution for SenseVoiceSmall is not registered

In short, it's an internal self-check behavior of PySide6 conflicting with ModelScope's lazy loading mechanism. You need to modify the ModelScope source code, as shown below. For specific reasons and explanations, please read this article.

image

After performing an interface operation in PySide6, call Funasr for speech recognition.

  • Run in a separate test script? Everything works smoothly.
  • Call by clicking a button in the PySide6 application? An endless stream of xxx is not registered errors.

And all of this began with a seemingly simple and harmless error message.

Error paraformer-zh is not registered

Initially, the error thrown in the console was: AssertionError: paraformer-zh is not registered

Similarly, if you are using sensevoicesmall, you will encounter the same error SenseVoiceSmall is not registered

As an experienced developer, my first thought was: this must be an issue with the model registration process. In frameworks like Funasr and ModelScope, models need to be "registered" in a global list before use. This error clearly indicates that when AutoModel(model='paraformer-zh') is called, it doesn't recognize the name 'paraformer-zh'.

Why doesn't it recognize it in the PySide6 environment? A series of "usual suspects" flashed through my mind:

  • Wrong Python environment? sys.executable and sys.path printed identically. Ruled out.
  • Changed working directory? os.getcwd() also showed normal. Ruled out.
  • Missing dependencies? Repeatedly checked and reinstalled; dependencies were complete. Ruled out.

Intuition told me the problem was deeper. The event loop of the GUI application and the complex runtime environment must have altered the code's behavior somewhere.

Process Isolation—The Right Direction, Wrong Depth

To escape potential "contamination" from the PySide6 main thread, I deployed the standard weapon: multiprocessing. I placed the entire recognition logic into a separate function and launched it in a brand-new process using the spawn context. I was confident that a clean, isolated process should work, right?

Yet, the same error appeared again.

This made me ponder. Although multiprocessing creates a new process, it still has intricate connections with the main process to pass data and objects between processes. The child process, upon starting, still imports certain modules from my project, which in turn depend on PySide6. Perhaps this "contamination" was at a deeper level.

So, I switched to the more isolated subprocess (implemented with QProcess in PySide6). I created a "self-calling" architecture: my main program sp.py could start in a pure "worker mode" via a special command-line argument --worker-mode.

This approach finally changed the error message! It was like seeing a glimmer of light after a long walk in a dark tunnel.

Cannot import __wrapped__—The Truth Emerges

The new error log pointed directly to ModelScope's lazy loading mechanism: ImportError: Cannot import available module of __wrapped__ in modelscope...

After arduous tracing and even considering modifying ModelScope's __init__.py to "disable" lazy loading (a dead end leading to circular import hell—don't try it!), I finally found the crime scene in a long call stack:

File "shibokensupport/signature/loader.py", ...
File "inspect.py", ... in _is_wrapper
    return hasattr(f, '__wrapped__')
File "modelscope/utils/import_utils.py", ... in __getattr__
ImportError: Cannot import available module of __wrapped__...

It turns out, the real culprit was PySide6 itself!

Let me translate this "forensic report":

  1. shibokensupport is PySide6's underlying support module. When my worker process starts and imports modelscope, even if it doesn't create any windows, certain "ghost" modules of PySide6 are still active in the background.
  2. This "ghost" module, with good intentions, tries to check if the newly imported modelscope module is an object wrapped by PySide6.
  3. Its inspection method is very standard: it uses Python's built-in inspect library to ask: hasattr(modelscope, '__wrapped__') ("Do you have the __wrapped__ attribute?").
  4. This question hits exactly where ModelScope is vulnerable. To implement lazy loading, ModelScope uses a special LazyImportModule object that masquerades as the modelscope module itself. This object intercepts all attribute accesses.
  5. When LazyImportModule is asked about __wrapped__, its __getattr__ method is triggered. It mistakenly assumes this is a normal request and tries to import a module named __wrapped__ from libraries like transformers—which, of course, doesn't exist. Thus, it throws the fatal ImportError.

Conclusion: An innocuous internal self-check behavior of PySide6 and ModelScope's clever but fragile lazy loading mechanism had an unexpected, disastrous chemical reaction.

Final Solution: Modify ModelScope Source Code

With the root cause identified, the solution became exceptionally clear. We can't stop PySide6 from checking, but we can "educate" ModelScope on how to respond correctly to this check. We only need to make a tiny, surgical modification to the ModelScope source code.

Target file: [Your virtual environment]/lib/site-packages/modelscope/utils/import_utils.pySurgery plan: Add a "special case handling" logic at the very beginning of the __getattr__ method in the LazyImportModule class:

python
# modelscope/utils/import_utils.py

class LazyImportModule(ModuleType):
    # ... other code ...
    def __getattr__(self, name: str) -> Any:
        # ==================== PATCH ====================
        # When PySide6's underlying check asks for the '__wrapped__' attribute,
        # we directly tell it "this attribute does not exist" instead of triggering the dangerous lazy loading.
        if name == '__wrapped__':
            raise AttributeError
        # =======================================================
        
        # ... keep the original lazy loading logic unchanged ...

After applying this patch, in the development environment, everything returned to normal! The application started with python sp.py could finally call Funasr happily.