Add Cua-S1 0.2 multimodal CUDA worker with upstream parity - #12
Conversation
|
Thanks, this lines up well with #11. I added a small follow-up commit to #11 so both workers answer errors the same way: error bodies are The text worker will sit next to yours in |
|
fix conflicts |
Resolve the .gitignore and recipe/README.md conflicts with the frontend merge (ThinkFlowLab#2): use the same Python ignores as ThinkFlowLab#12, and list the Cua-S1 text recipe next to the Laya one. Signed-off-by: Tianyao Wu <rayroy31@gmail.com>
hsliuustc0106
left a comment
There was a problem hiding this comment.
Two actionable findings: unsupported image aspect ratios currently return HTTP 500, and lock-release assertions race with handler cleanup.
Validation: full CPU suite: 61 passed, 1 failed; focused server rerun: 24 passed, 1 failed. Both failures were the lock assertion on different malformed inputs. The reused environment had Pillow 12.3.0 rather than pinned 11.3.0. The aspect-ratio case was reproduced through the real worker handler with a processor stub invoking the smart_resize function extracted from pinned Transformers 5.17.0. Archived reference/candidate reports agree exactly on tensor fingerprints and probabilities for all nine forwards. GPU inference was not rerun.
| if source.format != expected[prefix]: | ||
| raise InvalidRequest("image format does not match its MIME type") | ||
| w, h = source.size | ||
| if ( |
There was a problem hiding this comment.
[P2] Reject unsupported image aspect ratios with 422
A 2048×1 PNG passes these size checks, but the pinned Qwen image processor rejects aspect ratios above 200 with ValueError. Since prepare() does not translate this input error into InvalidRequest, the HTTP handler returns 500 ("inference failed") for a well-formed unsupported request, contrary to the documented 422 contract. Reproduced through the worker handler using the pinned resize function. Validate the aspect ratio before processing and add a regression test for its HTTP rejection.
There was a problem hiding this comment.
Fixed in e6cf582: images above 200:1 now return 422 before inference. Added HTTP rejection and boundary tests for both orientations.
| server.engine.predict = unexpected | ||
| status, body = call(url + "/v1/systemone", raw) | ||
| assert status == 400 and set(body) == {"detail"} | ||
| assert not server.inference_lock.locked() |
There was a problem hiding this comment.
[P2] Synchronize the lock-release assertion with handler cleanup
Receiving the complete HTTP response does not guarantee the server thread has executed its finally block: send_json() writes the response before inference_lock.release(). This immediate assertion therefore races with cleanup. It failed in both the full suite and a focused server rerun, on different malformed inputs. Wait for handler completion or use a bounded lock acquisition (releasing it afterward) to verify eventual cleanup. The assertion in test_model_failure_is_not_reported_as_success at line 88 has the same race.
There was a problem hiding this comment.
Fixed in e6cf582 with bounded lock acquisition and deterministic delayed-cleanup tests. All 70 tests pass with Pillow 11.3.0 and 12.3.0; the 14 cleanup cases also passed three extra runs.
| @@ -0,0 +1,21 @@ | |||
| MIT License | |||
| @@ -0,0 +1,136 @@ | |||
| """Small loopback HTTP worker; the Rust frontend remains the public serving layer.""" | |||
There was a problem hiding this comment.
do we need to push server under the model folder?
| @@ -0,0 +1,102 @@ | |||
| { | |||
Remove archived experiment outputs and assistant planning notes. Keep runtime code, reproducible tools, and model verification metadata unchanged. Link historical reports to an immutable commit and ignore future local artifacts. Remove only tests tied to the deleted historical evidence bundles.
Remove supplemental tests, recipe tools, documentation, CI, and configuration changes from the PR diff. Runtime Python source and inline third-party notice are unchanged. Validation uses the pre-cleanup test/tool snapshot outside the checkout.
|
Thanks for the implementation and parity validation. I’d like to clarify the architectural direction before merging. The current Cua-S1 plan explicitly starts with a Transformers/PEFT worker, so this PR follows that approach. However, I want System1-Omni to prioritize native model execution with CUDA/Metal backends. Expanding the Python worker to multimodal inference doesn’t advance that goal. Please keep this implementation available as a correctness reference and rework the production contribution toward a minimal native Cua-S1 text/prefill path first. Vision and LoRA support can follow incrementally. We should update the existing Cua-S1 plan to reflect this direction as well. |
|
For the text path, #19 already runs Cua-S1 natively: Rust and its own CUDA kernels for Qwen3.5-4B, with the |
|
@Levius-Fubuki I will merge it for now but please check my comments |
|
Thanks for merging |
Add a /v1/systemone worker for the Cua-S1 4B 0.2 text adapter in src/models/cua_s1/text/, next to the multimodal worker proposed in ThinkFlowLab#12. It loads the base model and the PEFT adapter directly through Transformers and PEFT, follows the contract in src/models/cua_s1/README.md, and answers choice questions only. Add the fixed input set and tests in tests/cua_s1/ (contract and HTTP tests that need no weights, and tokenizer checks), and recipe/cua_s1/text.md with setup, launch, a parity check against upstream FourBModel and a latency script. Ignore the recipe's weights/ and .venv/ with the same .gitignore lines as ThinkFlowLab#12. Part of ThinkFlowLab#10. Signed-off-by: Tianyao Wu <rayroy31@gmail.com>
Change
Add screenshot-conditioned Cua-S1 inference with strict inline-image/request validation, pinned weight verification, direct Transformers/PEFT execution, and a loopback HTTP worker. The HTTP adapter lives in
src/frontend/cua_s1.py; model execution and protocol handling live insrc/models/cua_s1/multimodal/.Scope
Only runtime Python source is included in the diff against
main: 3 files, +571/-0 lines. Tests, recipe/benchmark/profiling tools, documentation, dependency lists, CI and ignore-file changes are excluded. The upstream license notice remains in the source header.Validation
934e1ad1: 73 passed, using the preserved pre-cleanup tests and recipe helpers outside this checkout, with imports directed at this head's runtime source.frontend.cua_s1 --helpentry point pass.Setup and archived support files
Pinned dependencies, weight downloader and setup guide and the validation suite are retained at the immutable pre-cleanup revision. These helper files are no longer part of the current branch. The worker still requires the verified upstream
weights.lock.jsonbeside the base checkpoint directory.Launch the prepared environment with: