Repository navigation
fix(websocket): pass client hotwords to AutoModel as words - #3880
Merged
LauraGPT merged 1 commit intoNov 13, 2026
Merged
Conversation
The websocket protocol sends hotwords as a JSON object string that maps each hotword to a weight, and the HTML5, Java, Android and C++ clients and the microphone mode of funasr_wss_client.py send that format. funasr_wss_server.py passed the string to AutoModel unchanged. AutoModel splits a hotword string on whitespace, so the JSON text became <unk> hotwords and the client hotwords had no effect. Keep the words of a JSON object and join them with spaces, as the C++ server does for NN hotwords. Other strings are passed on unchanged.
4 of 9 tasks
LauraGPT
added a commit
that referenced
this pull request
Nov 13, 2026
Preserve original #3880 author ancestry and patch. Carry forward current main without rewriting history; include hotword regressions and real test dependencies. Signed-off-by: LauraGPT <zhifu.gzf@alibaba-inc.com>
LauraGPT
added a commit
that referenced
this pull request
Nov 13, 2026
…d/add conflict Keep the complete previously tested current-main tree and original author ancestry. The final three-file delta is unchanged: 40 CPU tests and 15 real CUDA synthetic routing cases passed. Signed-off-by: LauraGPT <zhifu.gzf@alibaba-inc.com>
LauraGPT
added a commit
that referenced
this pull request
Nov 13, 2026
Preserve original #3880 ancestry; accept scoped CPU, real CUDA synthetic-routing and exact-head hosted CI evidence. No pretrained-quality or full-suite claim. Signed-off-by: LauraGPT <zhifu.gzf@alibaba-inc.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #3879
runtime/python/websocket/funasr_wss_server.pypassed thehotwordsfield of the config message to the offline model unchanged. The websocket protocol (runtime/docs/websocket_protocol.md) sends it as a JSON object string with weights,{"阿里巴巴":20,"通义实验室":30}, and that is what the HTML5, Java, Android and C++ clients andfunasr_wss_client.pyin microphone mode send. AutoModel's hotword models read a hotword string as space-separated words: SeACo-Paraformer (paraformer-zh, the server's offline model) and Contextual Paraformer split it on whitespace ingenerate_hotwords_list. So the JSON text became<unk>hotwords, and the client's hotwords never reached the model as words (#2471, #2514).This PR adds
_model_hotwordsto the server. It turns a JSON object string into its words joined with spaces and returns any other value unchanged.ws_servecalls it where it stores the hotwords for the offline and online models (one line). The weights are dropped because AutoModel takes no hotword weights. The C++ server does the same for its NN hotword model (websocket-server.cpp:314-355,websocket-server-2pass.cpp:469-510): it passes the words of the JSON object joined with spaces, and uses a string that is not JSON as it is.What the offline model's
generatereceives, and the ids that SeACo-Paraformer'sgenerate_hotwords_listmakes from it (toy vocabulary,<unk>= 3,<s>= 1; the script is in the issue):main{"阿里巴巴":20,"通义实验室":30}(HTML5, Java, Android, C++)[[3], [1]]阿里巴巴 通义实验室:[[4, 5, 6, 6], [7, 8, 9, 10, 11], [1]]{"阿里巴巴": 20, "通义实验室": 30}(funasr_wss_client.py, microphone)[[3], [3], [3], [3], [1]]阿里巴巴 通义实验室:[[4, 5, 6, 6], [7, 8, 9, 10, 11], [1]]阿里巴巴 通义实验室[[4, 5, 6, 6], [7, 8, 9, 10, 11], [1]]Type of change
Validation
The new
tests/test_websocket_server_hotwords.pyloads the realfunasr_wss_server.pywith onlyAutoModelreplaced (the server builds its models when it is imported). It sends one offline request throughws_serve(the config message, 0.1 s of PCM, then{"is_speaking": false, "is_end": true}) and checks thehotwordthat the offline model'sgeneratereceives:{"阿里巴巴":20,"通义实验室":30}and{"阿里巴巴": 20, "通义实验室": 30}give阿里巴巴 通义实验室, and{}gives""(no hotwords);阿里巴巴 通义实验室and""(whatfunasr_wss_client.pysends without--hotword) are passed on unchanged.Windows 11, CPU, Python 3.11.17, torch 2.10.0+cpu, numpy 2.4.6, scipy 1.17.1, websockets 17.4:
main(0e52c3c) source with the new test: 3 failed, 30 passed. The three JSON cases fail, for exampleassert '{"阿里巴巴":20,"通义实验室":30}' == '阿里巴巴 通义实验室'.tests/test_paraformer_hotword_file.pypasses as well.I also served
ws_serveover a real socket on 127.0.0.1 withwebsockets.serve(..., subprotocols=["binary"], ping_interval=None), asmain()does, with the models replaced, and sent both JSON forms from awebsocketsclient. The offline model got'阿里巴巴 通义实验室'on this branch and the JSON text onmain. Every request ended with the finalis_endacknowledgement.python -m compileall funasr examples testsblack --line-length=100(24.4.0) leaves the new test unchanged and does not touch the changed lines offunasr_wss_server.py(it would reformat other lines of that file, onmaintoo). No real model was run.User impact
Users of the Python websocket server who send hotwords from the HTML5, Java, Android or C++ clients, or from
funasr_wss_client.pyin microphone mode, get those hotwords passed to the offline model as words. Before, the model got the JSON text, which became<unk>hotwords. Space-separated hotword strings and requests without hotwords are not changed.Notes for reviewers
runtime/python/websocket/**, so CI does not run this test (ortests/test_websocket_file_finalization.py). The test needswebsockets,scipyandtorch, which the server imports, and skips without them. I can add it to a workflow if you want.git merge-tree --write-treeof this branch with the head of Fix/security hardening #3877, which also edits this file, gives no conflicts.