inference_cli.py never loads the SoVITS model: change_sovits_weights is a generator and is called without being iterated
Summary
GPT_SoVITS/inference_cli.py calls change_sovits_weights() as a plain statement, but that
function is a generator function. The call therefore creates a generator object and returns
immediately — the function body never runs, and the SoVITS weights are never loaded.
Inference still produces audio, because inference_webui already loaded a SoVITS model at import
time. So --sovits_model is silently ignored: you get output, no error, and no indication that a
different model than the one you asked for was used.
change_gpt_weights() is a normal function, so --gpt_model works. The asymmetry is what makes
this easy to miss.
Evidence
1. Static
On current main:
GPT_SoVITS/inference_webui.pyL261def change_sovits_weights(...), withyieldat L295 and L377 → generator function.GPT_SoVITS/inference_cli.py:
L30: change_gpt_weights(gpt_path=GPT_model_path)
L31: change_sovits_weights(sovits_path=SoVITS_model_path)L31 is never iterated.
>>> inspect.isgeneratorfunction(change_sovits_weights)
True
>>> inspect.isgeneratorfunction(change_gpt_weights)
False2. Dynamic
Same process, same weight path, two calling styles, comparing a SHA256 fingerprint of the loaded model's parameters:
initial state : 4a17cbb61d7d79da version=v2Pro class=SynthesizerTrn
after plain call : 4a17cbb61d7d79da version=v2Pro class=SynthesizerTrn <-- unchanged
(returned object : generator)
after consuming : 63d735ba8b62f4f0 version=v3 class=SynthesizerTrnV3 <-- changedThe plain call leaves the parameters bit-identical and does not even change the model class.
3. Behavioural
Requesting v3 and v4 weights through the CLI-style call produced 32000 Hz output for both — the sample rate of the already-loaded v2Pro model. After consuming the generator, the same requests produced 24000 Hz (v3) and 48000 Hz (v4), the correct rates for those vocoders.
Reproduce
import inspect, hashlib
import GPT_SoVITS.inference_webui as iw
def fp():
h = hashlib.sha256(); n = 0
for p in iw.vq_model.parameters():
h.update(p.detach().float().cpu().numpy().tobytes())
n += p.numel()
if n > 5_000_000: break
return h.hexdigest()[:16], iw.model_version, type(iw.vq_model).__name__
print(inspect.isgeneratorfunction(iw.change_sovits_weights)) # True
print("before :", fp())
iw.change_sovits_weights("GPT_SoVITS/pretrained_models/s2Gv3.pth",
prompt_language="日文", text_language="日文")
print("after plain :", fp()) # identical
for _ in iw.change_sovits_weights("GPT_SoVITS/pretrained_models/s2Gv3.pth",
prompt_language="日文", text_language="日文"):
pass
print("after consume :", fp()) # changedWhy this went unnoticed
inference_webui auto-loads a SoVITS model at import time, picking one from the weights directory.
If that happens to be the model you wanted, everything appears to work. The bug only shows up when
you try to switch — and even then it fails silently with plausible audio, so it is easy to
attribute the wrong-sounding result to the model or the data rather than to the loader.
Note also that passing prompt_language=None / text_language=None (the defaults) raises
UnboundLocalError: local variable 'prompt_text_update' referenced before assignment once the
generator is consumed, because the branch that assigns those locals is skipped. So a naive fix of
just wrapping the existing call in a loop is not enough — the language arguments have to be passed
as well.
Suggested fix
In inference_cli.py:
for _ in change_sovits_weights(sovits_path=SoVITS_model_path,
prompt_language=ref_language,
text_language=target_language):
passA more robust alternative would be to split the weight-loading logic out of the Gradio-facing generator into a plain function that both the WebUI and the CLI call, so this class of mistake cannot recur.
Environment
Windows 11, GPT-SoVITS-v2pro-20250604 integrated package, but the two source files above are
unchanged on current main, so the issue is in the repository rather than in the packaging.
Source: RVC-Boss/GPT-SoVITS