Skip to content

[multi-lora] /v1 post-training API with per-adapter token metering - #1822

Closed
yushengsu-thu wants to merge 12 commits into
mainfrom
radixark/multi-lora-api
Closed

[multi-lora] /v1 post-training API with per-adapter token metering#1822
yushengsu-thu wants to merge 12 commits into
mainfrom
radixark/multi-lora-api

Conversation

@yushengsu-thu

@yushengsu-thu yushengsu-thu commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Declarative post-training API over the multi-LoRA controller: submit LoRA jobs against a shared base model, meter every adapter's token usage (rollout/training, counting only — no pricing), and operate everything from a single-file web console. Tinker-style execution core untouched; legacy /adapter_runs ops plane unchanged.

Screenshot 2026-07-27 at 1 40 18 AM

APIs

  • POST /v1/postTrainingJobs — create a LoRA post-training job
  • GET /v1/postTrainingJobs[/{id}] — list/inspect jobs, live progress and usage
  • POST /v1/postTrainingJobs/{id}:cancel — stop one adapter's training
  • DELETE /v1/postTrainingJobs/{id} — remove terminal job, ledger kept
  • GET /v1/postTrainingJobs:batchGetState — cheap bulk state poll
  • POST|GET|DELETE /v1/datasets — register cluster datasets
  • POST|GET|DELETE /v1/evaluators — register reward configs
  • GET /v1/models[/{id}] — adapter states and checkpoints
  • GET /v1/models/{id}:download — checkpoint file paths
  • GET /v1/usage — per-registration token ledger (billing substrate)
  • GET /v1/info — capacity and limits
  • GET /ui — web console: launch server, create/cancel jobs

Tests: 74 control-plane tests (tests/fast/ray/multi_lora/, --noconftest); e2e-verified on an 8×H200 devbox (4 jobs × 5 steps, 2 cancelled mid-run).


To-do

  1. Rebase feat(multi-lora): enable and validate MoE expert adapters #1794
  2. remove ui and ui test

yushengsu-thu and others added 7 commits July 25, 2026 11:45
Training-side support for putting multi-LoRA adapters on MoE experts, on top of
MultiLoRAGroupedExpertLinear in megatron-bridge.

Force moe_permute_fusion off for multi-LoRA runs that target expert leaves. Most
bridge MoE providers default it on (Qwen3-MoE among them), and with it on the
dispatcher records TE's row_id_map instead of a token gather index, which expert
adapters cannot replay. Disabling it only costs the fused permute kernel, so this
turns off an optimization rather than refusing to build.

Fix two things that would have corrupted or lost expert adapters:

* slice_lora_to_rank addressed the rank axis from the front, so a packed
  grouped-expert export ([num_experts, rank, in] / [num_experts, out, rank]) was
  sliced on its expert or output axis. Address it from the end instead.
* Megatron-native adapter shards were named by (tp, pp) only and written by DP
  rank 0. Expert-parallel ranks sharing a (tp, pp) coordinate hold different
  local experts, so their shards collided and a resume loaded one EP rank's
  experts onto every rank. Shards are now keyed by (tp, pp, ep) — the suffix is
  omitted at ep_size 1 so existing checkpoints stay loadable — and both the
  writer election and the completeness check come from one cached gloo all-gather
  of the realized coordinates. Neither can be derived locally: no single group
  rank elects one writer per coordinate, and the realized coordinates are not the
  cross product of the group sizes once expert TP is smaller than tensor TP,
  which expert multi-LoRA requires.

Validate the configurations the adapter cannot serve. Model-dependent checks live
in _validate_multi_lora_moe_support, where the provider values are concrete:
expert TP must be 1, experts must be grouped (SequentialMLP linears are skipped,
so the experts would train nothing), no fp8/fp4 experts, no capacity padding, and
both expert projections must be targeted since sglang applies the expert delta
after gate_up and after down together. Launch-time checks cover pipeline size 1
and --qkv-format thd; the latter closes a pre-existing hole, as per-slot token
spans assume samples pack contiguously in the sequence-major flattening, which
bshd's [b, s] batch does not.

Expert TP is deliberately NOT checked against the CLI: its default is None and
Megatron only resolves it to tensor_model_parallel_size in its own validate_args,
which runs after miles' — so comparing the raw value rejected runs that simply
omitted the flag.

Also stop forwarding exclude_modules to MultiLoRA: ModuleMatcher asserts it is
empty whenever target_modules is set, and the exclusion has already been
subtracted from target_modules during argument validation.
Comment-only change addressing the 19 review comments: every flagged
docstring/comment block keeps its load-bearing constraint and drops the
derivation. No code change; the four touched fast-test files pass 48/48.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 27, 2026 08:44
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@yushengsu-thu
yushengsu-thu force-pushed the radixark/multi-lora-api branch from 2d18968 to 700dd80 Compare July 27, 2026 09:00
@yushengsu-thu yushengsu-thu changed the title [multi-lora] /v1 fine-tuning API with per-adapter token metering [multi-lora] /v1 lora rl API with per-adapter token metering Jul 27, 2026
Every adapter registration carries a monotonic TokenUsage meter split by
class (prefill / cached-prefill / sample / scoring-prefill / train) and
side (rollout vs training). Rollout tokens are counted at engine-response
receipt (aborted/stale/filter/retire drops included, itemized in detail
buckets); train tokens bank through the existing exactly-once
record_batch_adapters -> mark_batch_trained commit. Cross-process
reporting uses incarnation-keyed cumulative snapshots (idempotent under
at-least-once delivery). A timestamped JSONL journal under
{save}/multi_lora_controller/ is the durable ledger: replayed on restart,
frozen per registration at slot free, retained across job deletion. An
external billing backend consumes the ledger; no rates live in miles.
Declarative resource surface over the existing controller verbs:
postTrainingJobs (create/get/list/cancel/delete/batchGetState), datasets,
evaluators, models (checkpoint scan + :download), /v1/info and /v1/usage.
Typed error envelope with requestId, idempotent create, reserved names,
429 on slot capacity, shadow EXTERNAL jobs for ops-plane registrations,
stopReason derivation (user/ops/max-steps). Slot indices never leak. The
legacy /adapter_runs ops plane is unchanged, and the gateway never
reaches into registry internals, so a Tinker-style primitives API can
mount later as a sibling driver.
ui/console.html: zero-dependency console over /v1 — launch/stop server,
one-click job creation with prefilled defaults (auto-provisions the demo
dataset/evaluator), per-LoRA cancel, live slot usage (a/n), token-usage
ledger and model/checkpoint views. Served at GET /ui by the gateway.
ui/launcher.py: standalone host so the UI exists before the server does —
serves the console, proxies /v1, starts/stops the miles server.
ui/run.sh: one-command entry (tunnel + launcher + server + browser);
--fresh wipes the usage ledger and checkpoints for a clean demo slate.
examples/multi_lora/v1_api_demo.py drives the public surface end to end:
dataset/evaluator registration, N job submissions, step/usage polling,
mid-run cancellation, final ledger and model/checkpoint readout. Same
flow verified live on an 8xH200 devbox (4 jobs x 5 steps, 2 cancelled).
@yushengsu-thu
yushengsu-thu force-pushed the radixark/multi-lora-api branch from 700dd80 to ffc5229 Compare July 27, 2026 09:06
@yushengsu-thu yushengsu-thu changed the title [multi-lora] /v1 lora rl API with per-adapter token metering [multi-lora] /v1 post-training API with per-adapter token metering Jul 27, 2026
Base automatically changed from radixark/multilora-moe-experts to main July 30, 2026 01:42
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