Skip to content

Add StartLux Instant 4B native worker (#160) - #164

Draft
hsliuustc0106 wants to merge 7 commits into
mainfrom
cursor/startlux-instant-4b-native-ba7c
Draft

hsliuustc0106 wants to merge 7 commits into
mainfrom
cursor/startlux-instant-4b-native-ba7c

Conversation

@hsliuustc0106

@hsliuustc0106 hsliuustc0106 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Required human contributor answers

Answer every question before implementation and PR submission, including drafts.
Reuse explicit, still-applicable human answers with a traceable source reference;
ask the human for anything missing and wait. An agent must not invent answers.
Blank fields, placeholders, or an agent-written rationale do not satisfy this gate.
Share only information and source links appropriate for this PR's audience.

  1. What outcome are you trying to achieve?

    Answer: Pin StartLux-Decision Instant 4B behind /v1/systemone for choice, noul, and score, with no silent truncation, and call out the CC BY-NC 4.0 weights. Source: issue #160. The owner then required a native Rust+CUDA worker and an L20X closed-loop latency recipe.

  2. What is the highest-leverage variable for that outcome?

    Answer: Instant 4B first. Issue [New Model]: Support StartLux-Decision v1.1 (4B / 27B Instant) — community help wanted #160 says the comparison charts used Instant / non-thinking. The owner said not to expand into AutoThink or 27B.

  3. How will this work move that variable rather than create busywork?

    Answer: This PR adds the pinned Instant 4B native worker. Source: issue [New Model]: Support StartLux-Decision v1.1 (4B / 27B Instant) — community help wanted #160 and the owner's first-PR instruction. Hongsheng then asked to put Add StartLux Instant 4B native worker (#160) #164 on the same optimize loop as Clef/PPLX: one lever at a time, and replace the latency primary only when both p50 and p95 beat it. The current tip is that one lever. It does not add an external causal_conv1d or FLA dependency, and it does not reshape the attention kernel.

  4. Who is the customer or user, and what do they actually need?

    Answer: Issue [New Model]: Support StartLux-Decision v1.1 (4B / 27B Instant) — community help wanted #160 was opened from the system1 room; Hongsheng reviews. Keep this pull request a draft and do not merge. The next C1 paste decides whether tip d139b22 beats the primary. No win is claimed.

After answering the four questions: is a PR needed at all to achieve this outcome?

Human decision and rationale (or explicit source reference): Yes. The owner said to open the pull request for #160 (draft is fine) and not to merge.

For a bug fix: link actual observed failure evidence.

Evidence: Not a bug fix. Latency primary is the pasted L20X sample at 5bb25be. Scratch reserve 2b4a586, grouped KV load 136ddf8, and packed prompt rows 1b5b1ee were measured and failed the gate. d139b22 has no sample. No win on any tip.

Purpose

Native worker omni-startlux-native for StartLux-Decision v1.1 4B Instant only. Tracks issue #160.

  • Weights: startlux-models/StartLux-Decision-v1.1-4B-Instant revision 416088f77cfce09633906a3675c7cd2e5dabcf10 (CC BY-NC 4.0, not distributed).
  • Prompt/readout source: StartLux-Decision a99977d9332decc9fb27a2488b4a83b533b6cd5f (Apache-2.0). See src/models/startlux/NOTICE.
  • POST /v1/systemone for choice, noul, and score. AutoThink and 27B are refused.
  • Full attention uses in-tree cs1_attention_gated_bidirectional (per-head launch). GDN uses in-tree cs1_gdn_conv and cs1_gdn_prefill. No external causal_conv1d or flash-linear-attention package. No FlashInfer.
  • The PR stays draft. Do not merge.

Hold

No latency primary change until a measured L20X Public231 C1 of head d139b2286cede76aec66a760a81393cfa3398d9a is pasted. Gate versus primary run1 below: both p50 and p95 must be lower, with pass 231/231. A p50-only improvement does not replace the primary. Do not claim a win before that paste.

2b4a586, 136ddf8, and 1b5b1ee failed that gate. Primary stays 5bb25beb. This tip does not include the scratch reserve, the grouped KV kernel, or the packed row offsets. Its only lever versus the primary is a pinned token-id copy that does not synchronize the stream before the embed kernel.

Measured native Public231 C1

Hardware label from the paste: lab L20X, reported sm_89. Not an H200 result. Instant / non-thinking. Warmup 5, concurrency 1, manifest Public231. Clock: successful_latency, post_to_body_json_and_schema_validation.

Head Successful p50 p95
primary 5bb25beb run1 231/231 6.785 ms 51.432 ms
primary run2 231/231 6.510 ms 50.860 ms
primary run3 231/231 6.522 ms 50.939 ms
tip 2b4a586e 231/231 7.811 ms 51.947 ms
tip 136ddf89 231/231 8.148 ms 53.053 ms
tip 1b5b1ee4 231/231 7.980 ms 52.417 ms

Primary for the gate: run1 p50 6.785 ms, p95 51.432 ms. Contract at 5bb25be: 8/8.

2b4a586e Δp50 +1.026 ms (+15.11%), Δp95 +0.515 ms (+1.00%). Gate failed.

136ddf89 Δp50 +1.363 ms (+20.09%), Δp95 +1.621 ms (+3.15%). CUDA was rebuilt for that tip. Gate failed.

1b5b1ee4 Δp50 +1.195 ms (+17.6%), Δp95 +0.985 ms (+1.92%). Rust and CUDA were rebuilt. Gate failed. Do not claim a win.

Operator checklist (L20X, sm_89)

From the repository root. Needs nvcc, cuBLAS headers, and cargo. Rebuild the CUDA library: this tip adds cs1_host_alloc, cs1_host_free, and cs1_upload_async. Attention and GDN kernels are unchanged. An old libqwen3_5_cuda.so will fail Instant load.

src/backends/cuda/qwen3_5/build.sh target/release 89
cargo build --release --locked -p omni-startlux-native -p omni-jev

Serve Instant / non-thinking on http://127.0.0.1:8000/v1/systemone as in recipe/startlux/latency.md, then:

python benchmarks/bench.py run /path/to/public231.jsonl \
  --endpoint http://127.0.0.1:8000/v1/systemone \
  --model StartLux-Decision-v1.1-4B-Instant \
  --metadata run-metadata.json \
  --phase measured \
  --concurrency 1 --warmup 5 --score-decimals 4 \
  --output /tmp/startlux-l20x-c1-run1

Latency hypotheses and measured deltas

5bb25be — share the tokenizer

Measured Public231 C1 is the primary table above. Delta versus the commit before the share: none (no paired run).

2b4a586 — reserve 8192 tokens of scratch before listen

Hypothesis: move the short-warmup realloc out of the bench clock. Measured: 231/231, p50 7.811 ms, p95 51.947 ms. Both percentiles worse. Gate failed. The call is removed.

136ddf8 — one KV load per GQA group, 99 KiB block

Hypothesis: less K/V traffic on the eight full layers. Measured: 231/231, p50 8.148 ms, p95 53.053 ms. Both percentiles worse. Gate failed. The per-head bidirectional kernel is restored.

1b5b1ee — pack each prompt's rows in the high-water scratch

Hypothesis: a shorter prompt would stop striding across the cap-sized GDN workspace. Measured: 231/231, p50 7.980 ms, p95 52.417 ms. Both percentiles worse. Gate failed. Cap offsets are restored.

d139b22 — pinned token-id copy, no stream sync

cs1_upload copies the token ids and synchronizes the stream before any layer kernel is queued. This tip writes those ids into a cudaMallocHost buffer allocated at load and queues cs1_upload_async. The embed kernel follows on the same stream. The last-hidden download still waits before the host reads the result. Scratch layout, attention, and GDN match the primary.

A CPU profile of the pinned tokenizer (release build, not the L20X) ruled out encode-offset skipping: at 121 tokens, encode 0.115 ms versus encode_fast 0.119 ms. At 8,349 tokens the delta was 0.120 ms. The 26×2560 letter dot was 0.039 ms. That is not the 6.785 ms median.

Hypothesis: both p50 and p95 fall versus 6.785 / 51.432 because every request pays the upload wait. The sync was not timed on sm_89. If it is only tens of microseconds, the gate misses inside the primary's 0.275 ms run-to-run p50 gap. Measured delta: none. No win claimed.

Test Plan

System1-Omni Version / Commit: d139b2286cede76aec66a760a81393cfa3398d9a on cursor/startlux-instant-4b-native-ba7c. Measured latency primary: 5bb25be.

  • cargo +1.98.1 test --locked -p omni-startlux-native --test contract: 8 passed.
  • cargo +1.98.1 test --locked -p omni-qwen3-5-native --lib: 24 passed, 14 ignored (CUDA).
  • cargo +1.98.1 clippy --locked -p omni-qwen3-5-native -p omni-startlux-native --all-targets -- -D warnings: clean.
  • No HTTP latency sample at d139b22. GPU parity unverified. The new CUDA symbols were not executed here (no nvcc, no GPU).

Test Result

At 5bb25be: bench pass 231/231, primary p50 6.785 ms, p95 51.432 ms. At 2b4a586: 231/231, p50 7.811 ms, p95 51.947 ms, gate fail. At 136ddf8: 231/231, p50 8.148 ms, p95 53.053 ms, gate fail. At 1b5b1ee: 231/231, p50 7.980 ms, p95 52.417 ms, gate fail. At d139b22: p50 unverified, p95 unverified, bench pass unverified. No win. Contract 8/8.

Demo / evidence

The latency table is the pasted samples for 5bb25be, 2b4a586, 136ddf8, and 1b5b1ee. No capture for d139b22. Illustrations: none.

The branch diff is still above 3000 lines. Self-review below stays unchecked. This draft is not a request for maintainer review.

Self-review

  • I have reviewed the full diff and addressed the issues I found.
  • I have checked that the change follows the project's architecture and stays focused on the stated purpose.
  • I have run the checks appropriate to this change and reported commands, results, and anything I could not verify above.
  • I have checked that the PR description, documentation, and any accuracy or performance claims match the implementation and available evidence.
Open in Web Open in Cursor 

cursoragent and others added 2 commits October 24, 2026 16:13
Serve the pinned Instant 4B checkpoint on /v1/systemone for choice, noul,
and score, with bidirectional full attention and a tied letter readout.
Document the Ada sm_89 build and the L20X closed-loop latency recipe.
Weights stay CC BY-NC 4.0 and are not included.

Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Tokenizer::clone copies the BPE tables onto the bench.py HTTP clock.
encode only needs a shared reference, so each request now takes an Arc
clone. Device scratch is unchanged: the static 65536-token layout is
about 15 GiB before weights, and that buffer was not measured on L20X.

Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>

psv666 commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

For the operator handoff at head 5bb25beb1c23f72497be189156d82f62ffb974da, keep the stated draft/measurement hold. The next useful result is a working, qualified Instant 4B request and then the fixed C1 comparison.

Suggested execution order using the existing recipe:

  1. Build the shared CUDA bundle and native worker for the actual device, check the exported contract, then load the pinned checkpoint and complete warmup. Because this PR adds a shared-library entry point, include the affected existing-consumer build/regression checks.
  2. Exercise choice, noul and score directly and through the Rust frontend, then compare outputs with the pinned Instant/non-thinking reference on identical inputs. In particular, qualify the documented FP32→BF16 conversion of linear_attn.A_log and linear_attn.norm.weight; CPU prompt fixtures cannot establish its numerical effect.
  3. Run the documented Public231 C1 native/reference arms on the same GPU/checkpoint, retain all planned/successful/failed counts and raw error records, and report p50/p95 with head, manifest hash, precision and actual hardware. Separate load/warmup from measured requests and preserve any in-request scratch-growth effect in the raw records.

The existing 8 CPU tests and the tokenizer-copy hypothesis are useful preparation, but there is still no measured speedup or GPU parity claim at this head. Once measurements exist, they can determine the next optimization. Complete the full-diff self-review before requesting readiness; this follow-up does not lift the hold or request speculative optimization commits.

Agent-assisted readiness follow-up using the repository review skill pinned at trusted main cd302b6e3d7723ebfc33bba9698da2c1e881f203 (SHA-256 ae2dfac116376ae2ec41f65122cc1bf5aea10751b8b907198a56154e5d67230e). This comment reconciles current main and the existing discussion; it is not a new full code-review approval or a claim of newly executed model tests.

Public231 C1 on L20X at 5bb25be is 6.785/51.432 ms p50/p95 on the primary
traversal. Process warmup only fills a 1024-token buffer, so a later longer
prompt still allocates inside that clock. Reserve 8192 tokens at load
(~1.9 GiB in the static layout) without changing GEMM M. The delta is
unmeasured.

Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
cursoragent and others added 4 commits October 25, 2026 02:43
The bidirectional kernel keeps the per-head MMA and 32-key softmax tile, and
the four query heads that share a KV head now read each K/V tile once. Causal
attention is unchanged. No C1 sample; both p50 and p95 still have to beat
6.785/51.432 before this is a win.

Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
The 8192-token scratch reserve failed Public231 C1 (7.811/51.947 vs
6.785/51.432), so the worker no longer allocates it. The bidirectional
block keeps 32 query rows per head, 99 KiB, so the grouped K/V load can
opt in on reported compute 8.9 instead of falling back.

Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Grouped KV load failed Public231 C1 (8.148/53.053 vs 6.785/51.432), so
bidirectional attention is the per-head kernel again. A shorter prompt now
uses activation offsets sized to its own token count, instead of striding
across the cap-sized GDN workspace that the 8192-token reserve showed is costly.

Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Packed prompt rows at 1b5b1ee failed Public231 C1 (p50 7.980 ms, p95 52.417 ms). Primary stays 5bb25be. Scratch offsets match that primary again. This tip only removes the pageable upload wait before the embed kernel.

Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants