Add EasyMagpie vLLM-Omni serving - #15931
Conversation
df4f340 to
8f85db5
Compare
|
/ok to test 0734cee |
blisc
left a comment
There was a problem hiding this comment.
Overall the PR looks good from my end. The immediate concerns are
- How we package this component? It looks like it is currently constructed to be completely standalone from the rest of NeMo Speech which can be done.
- On packaging, despite that decision, we need tests to run which means that for testing, the requirements need to be added to NeMo's pyproject.toml and tests need to be moved to the NeMo tests folder, and we need to make sure that they run.
- The current implementation is slightly hard-coded which is fine for initial version, but we need much more strict config validation functions that explain what parameters will break the current implementation, and how we can update the implementation to allow future parameters
| # pipeline: easymagpie_talker | ||
| # | ||
| # scripts/benchmark_model.py uses this deploy config by default. | ||
| pipeline: easymagpie_talker |
There was a problem hiding this comment.
Let's make a better naming convention. Not sure that easymagpie_talker should be used for the pipeline without the codec. @paarthneekhara, what should we refer to the backbone+LT as?
There was a problem hiding this comment.
@paarthneekhara could you please advise on the canonical name for the backbone + LT stage? I’d prefer to use the established EasyMagpie terminology rather than introduce a new name here.
There was a problem hiding this comment.
Sorry, missed these. How about easymagpie_codecLM or just easymagpie_LM ?
There was a problem hiding this comment.
Let's go with EasyMagpieTTS which decomposes into
- EasyMagpie_LM
- EasyMagpie_LM_Backbone
- EasyMagpie_LM_LT
- SpectralCodec-BWE-22kHz
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| """NeMo-free EasyMagpie spectral codec implementation. |
There was a problem hiding this comment.
Perhaps instead of keeping a nemo-free implementation here, we ought to have a nn.Module base class that both will inherit.
There was a problem hiding this comment.
The serving decoder has a different runtime contract: NeMo uses NeuralModule, length masks, and weight normalization, while vLLM uses packed batches and explicit cache state. Sharing a base from nemo.collections would also make the isolated serving package depend on Speech. That dependency could make sense if we identify enough reusable components, but currently the serving components require substantially different implementations, so a shared base would add coupling without removing much duplication.
There was a problem hiding this comment.
How do we ensure that changes to the torch path won't break this initial vllm implementation? Or if it breaks, how can we get notified that vllm changes are needed?
I want to avoid the situation where torch changes doesn't get noticed until the end.
Should we add a test between the two paths in the repo? Or should we start enforcing doing evals with vllm?
It might be out of scope for this PR, but I want to start some sort of discussion on this.
CC @rlangman
There was a problem hiding this comment.
+1
I agree: I only looked at the codec part, but it looks like the codec implementation is duplicated from torch into the VLLM case. From the comments above, it sounds like there is no way around that. But yes, we should have tests that catch drift between the two, which will inevitably happen as time passes. There are a few things to discuss:
- How to test that the two implementations produce the same result: we'll need to about which scenarios to check; define some tolerances; think about random seeding; and minimize autoregressiveness in the tests so that unavoidable numeric differences don't accumulate.
- Does every commit into the torch path require a corresponding change in the vllm implementation? If we don't do that, the tests will break. But then again, it is a bit of a high bar to require porting every (possibly experimental) change to VLLM. So it may be that these tests are only run on demand, not be part of CI.
- Given the difficulty and error-proneness of keeping two impelmentations in sync over the long term: (a) it's probably worthwhile to give more thought about whether there's any way to rearchitect our code such that less duplication between the torch and vllm exists. (b) failing that, maybe there are ways to automate the porting to vllm since we'll need to do it regularly. The more tests exists, the more we can hand that task off to an agent with confidence.
|
[🤖]: Hi @vklimkov-nvidia 👋, We wanted to let you know that a CICD pipeline for this PR just finished successfully. So it might be time to merge this PR or get some approvals. |
143dd29 to
5d396c6
Compare
|
@blisc I moved the tests under |
|
/ok to test 87779cb |
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
87779cb to
3cd711a
Compare
|
[🤖]: Hi @vklimkov-nvidia 👋, We wanted to let you know that a CICD pipeline for this PR just finished successfully. So it might be time to merge this PR or get some approvals. |
Summary
POST /v1/audio/speech, and incremental text/audio streaming throughWS /v1/audio/speech/stream.Why
EasyMagpie generates stacked acoustic codes autoregressively and then decodes them into audio. Running both stages in vLLM-Omni provides batched, high-throughput inference while retaining progressive audio output for streaming and voice-agent use cases.
The conversion tool turns the training-time EasyMagpie and causal codec
.nemocheckpoints into a self-contained model directory. It converts the model weights, precomputes the text-embedding lookup, bundles the native codec, saves the tokenizer, and optionally stores speaker embeddings. After conversion, serving requires vLLM/vLLM-Omni and this plugin package, but does not require NeMo at runtime.The native codec keeps its causal history in vLLM-managed state pages, allowing each invocation to process only newly generated acoustic frames and emit asynchronous PCM chunks without replaying the full context.
Validation
pytest -q examples/tts/easymagpie_vllm_omni/tests: 70 passed, 1 skipped.add_special_tokens,NemotronHConfig,ModelLoadConfig, andload_easy_magpie_modelresolve from the Speech checkout.