Repository navigation
[Model] Add Laya typed-decision models (Jev /v1/systemone via structured_server) - #58429
Draft
LucasWilkinson wants to merge 2 commits into
Draft
LucasWilkinson wants to merge 2 commits into
LucasWilkinson wants to merge 2 commits into
Conversation
Contributor
|
Documentation preview: https://vllm--58429.org.readthedocs.build/en/58429/ |
This was referenced Sep 25, 2026
Add LayaForDecision, a token_classify pooling model for Laya (https://github.com/NandhaKishorM/laya): vLLM's ModernBERT encoder, Laya's question-type-conditioned head layers, and a pooler that scores each option marker with Laya's calibrated temperatures and runs its action head. Add examples to convert Laya checkpoints, run them offline, and serve the Jev /v1/systemone and structured chat APIs through structured_server.py --backend laya. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Lucas Wilkinson <lwilkins@redhat.com>
Add a CI test comparing LayaForDecision with a PyTorch port of Laya's DecisionModel on a small random checkpoint, covering per-sequence question types, marker gathering, temperature buckets and prompts without markers. Inline single-use helpers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Lucas Wilkinson <lwilkins@redhat.com>
LucasWilkinson
force-pushed
the
laya-typed-decisions
branch
from
September 29, 2026 18:16
34d9abb to
a59977d
Compare
Open
1 task done
17 tasks
This was referenced Oct 6, 2026
This was referenced Oct 7, 2026
Open
This branch has not been deployed
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.
Overview
Adds Laya typed-decision models (
convaiinnovations/laya,convaiinnovations/laya-multilingual) as atoken_classifypooling model,LayaForDecision. It also lets the #57250 structured-decisions server (/v1/systemone, Jev's API) front Laya with--backend laya.Laya came up on #57250 as an encoder alternative to DiffusionGemma structured reads. It answers
choice/score/noulquestions about a state in one forward pass: a ModernBERT/mmBERT encoder plus a small decision head, with no generation.Claims
Agent. Prompt token ids are identical, every answer matches, and probabilities agree to rounding in fp32.structured_server.py --backend layaserves Jev's/v1/systemoneand the schema-in-system-message/v1/chat/completionsin front of vLLM's/pooling. It supportsdepends_on,ask_if,askandinstructions.think, images and raw chat are rejected, because Laya does not generate text.answer_from,skip_reason) leave its output byte-identical.Validation
All on B300, rebased on
cb4f016c5d(model runner v2 active).Parity against Laya's reference
Agent, using a script in the Laya repo's layout: 4 states (dict, text, conversation list, Hindi) × 6 questions (4-way choice, score, noul, noul with custom labels, binary choice, 12-way choice) per checkpoint.laya.common.build_sequenceFLEX_ATTENTION, TF32 offTRITON_ATTN)structured_server.py --backend layaThe bf16 gaps are precision noise, not implementation error: Laya runs under autocast with fp32 LayerNorms, while vLLM runs fully in bf16. The fp32/FLEX row isolates this.
CI test
tests/models/language/pooling/test_laya.py:DecisionModel. One batch mixes question types, option counts (2 to 12, which hits a temperature bucket) and a prompt without markers.[CLS]offset and off-by-one markers each fail the test by 0.036 to 0.62. The real error is 1.5e-3 and the tolerance is 1e-2, so the TF32 attention gap leaves margin on other GPUs.tests/models/language/pooling/, which the Language Models (Extra Pooling) step runs.pytest tests/models/language/pooling/test_laya.py # 1 passedEnd to end:
python examples/pooling/token_classify/laya/convert_checkpoint.py convaiinnovations/laya ./laya-vllm vllm serve ./laya-vllm --served-model-name laya python examples/features/structured_diffusion/structured_server.py --backend laya \ --upstream http://127.0.0.1:8000 --model laya --tokenizer ./laya-vllm/v1/systemone,ask_if+depends_onstaging, the chat-completions schema route and the rejection paths behave as described.laya_offline.pyruns.DiffusionGemma path: the pre- and post-PR
structured_server.decide()were run with the upstream calls stubbed, acrosssamples= 3 /auto/ 1 and a schema usingask_if,depends_onandalone. The outputs are byte-identical. There is no DiffusionGemma checkpoint on this machine, so the diffusion path was not run end to end.Throughput, English checkpoint, 6 questions per request:
predict_batch, batch 8 / 32A single 6-question request takes 14 ms p50. These numbers are from the pre-rebase build.
Details
Design.
LayaForDecisionreusesModernBertModelunchanged. On top it adds Laya's question-type embedding and its two pre-norm head layers, the equivalent ofnn.TransformerEncoderLayer(norm_first=True), running onEncoderOnlyAttention.[CLS](wherepositions == 0).LayaDecisionPoolerfinds each option's[MASK]marker from the prompt token ids and scores it. It applies Laya's per-type and per-option-count temperatures, clamped to [0.5, 5] as Laya'sAgentdoes, and runs the action head on[CLS].[p_option, *p_action].use_activation=falsereturns logits.Split between model and server, the same split as DiffusionGemma. The model definition owns the readout: marker detection, question type and calibration. Prompt construction and answer decoding stay client-side, because Laya budgets in tokens (options capped at 48 tokens, the header at
head_max_len, conversations trimmed from their oldest turn). A chat template cannot express that without changing the token ids. An IO-processor plugin would allow a proxy-free/v1/systemone, but plugins currently load only from installed packages, so that is left for a follow-up.Checkpoint conversion. The Hugging Face repos keep
config.jsonand the tokenizer in subfolders, soconvert_checkpoint.pywrites a loadable directory:architectures, alaya_configblock (head layers, temperatures,mask_token_id, question-type token ids) anddtypeset from Laya'samp_dtype;A repo with a root
config.jsonwould remove this step and allow a normal model test. The registry entry isis_available_online=Falseuntil then.Compatibility and limitations.
ModernBertAttentionsplits the TP-sharded QKV output using the global head count (modernbert.py:147), so every ModernBERT model fails at TP>1 on main. This PR does not touch that file. Laya's checkpoints are 322M/421M parameters, so TP is rarely useful. The fix is small (per-rank head counts) and is better as its own PR.SupportsPPis not implemented.torch.compile. The encoder is still compiled and CUDA-graphed.Router(English vs multilingual by script) is not ported. Run one server per checkpoint.act_probabilityis always 1.0. Laya's runtime gives the same.vllm/, almost all in the self-containedlaya.py, plus a one-line registry entry. There are no changes to core components.Duplicate-work check. Open PR and issue searches for
layaand related terms (re-run 2026-09-29) found nothing. Laya appears only in a comment on #57250.AI assistance (Claude) was used for the implementation, validation and this description. The human submitter is responsible for reviewing and understanding every changed line.
Pull Request Checklist
I used vLLM's
/pr-checklistskill. (From [Docs] Add PR checklist skill for coding agents #57084, not yet merged.)AI assistance was used during the creation of this PR.
Design Fit: Reuses
ModernBertModeland the pooling API unchanged; the model is self-contained, with no core-component changes. The TP>1 limitation comes from existing ModernBERT code.Testing and Validation: Validated against the reference implementation on both public checkpoints and end to end. The added CI test is mutation-checked and has 6× tolerance margin.
Code Quality and Style: Single-use helpers inlined; comments kept to non-obvious reasons; docs table, docs section and examples updated.
Pull Request Contents: Summary, claims with evidence, reproduction commands, design tradeoffs, limitations, duplicate check and AI disclosure.
🤖 Generated with Claude Code