Skip to content

Consolidate exact trainer-serving parity - #57

Open
kiddyboots216 wants to merge 54 commits into
mainfrom
pr/consolidated-exact-rl
Open

Consolidate exact trainer-serving parity#57
kiddyboots216 wants to merge 54 commits into
mainfrom
pr/consolidated-exact-rl

Conversation

@kiddyboots216

@kiddyboots216 kiddyboots216 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

This consolidates the exact trainer-side work previously split across the earlier XoRL PRs into one branch based directly on main. It is paired with togethercomputer/xorl-sglang#21.

Highlights

  • Adds exact trainer-serving programs for dense and MoE Qwen3.x, GLM-5.2, and DeepSeek-V4, including one-round SwiGLU, exact GDN/attention/head paths, canonical routing replay, and decision-time logprob replay.
  • Supports physical pipeline-parallel training for the exact model paths, carrying model-owned boundary state and ragged metadata while dispatching terminal CE, policy, IS, DRGRPO, CISPO, and ordinary OPD objectives.
  • Composes logical row ownership across mixed DP × CP layouts for GLM and DeepSeek, including ragged rows, DP-aware LoRA/expert routing, and DeepSeek PP × CP storage/wire handling.
  • Replays per-row temperature, top-k, top-p, and min-p from normalized serving metadata.
  • Uses one canonical local MoE arithmetic contract across Qwen, GLM, and DeepSeek: BF16/FP16 transport, deterministic source ordering, FP32 leaf and adjacent/odd-tail tree accumulation, then one final output cast.
  • Retains GLM-5.2 full-parameter block-FP8 training, including scoped trainable components, frozen-trunk backward, optimizer/cache refresh, and full-weight publication.
  • Includes routed-expert replay throughput/side-channel integration and CISPO loss support.

Validation

  • Focused suites cover real PP2 × CP2 DeepSeek forward/backward, physical-PP objectives, mixed and ragged ownership, exact sampling replay, canonical MoE arithmetic, and GLM full-parameter wiring.
  • Cross-engine GPU checks compare the independent trainer and serving leaf/fold implementations for BF16 and FP16 contributor payloads.
  • Changed-range hygiene and focused validation pass locally; GitHub checks are tracked on this PR.

Companion serving change

Out of scope

Sparse-delta receiver integration is intentionally not included.

@broly-code-security-scanner

broly-code-security-scanner Bot commented Aug 13, 2026

Copy link
Copy Markdown

Broly Security Scan

Note

Summary

3 actionable finding(s) in this PR

  • 🟡 3 medium

All actionable items are in the table below.

No finding is at or above high, so this check is not blocking. The findings above are still tracked and reported.

Severity Scanner Issue Location Dismiss Verdict
🟡 MEDIUM SAST Arbitrary File Read via R3 SGLang Spans src/xorl/server/runner/runner_dispatcher.py:1441 d27 🔺 TRUE_POSITIVE · Confidence: HIGH
🟡 MEDIUM SAST Path traversal in R3 source path validation allows
reading file metadata (existence, parent direc...
src/xorl/server/orchestrator/request_processor.py:408 d8 🔺 TRUE_POSITIVE · Confidence: HIGH
🟡 MEDIUM SAST Unsafe deserialization of untrusted files via
torch.load in diagnostic override paths
src/xorl/server/runner/model_runner.py:2304 d26 🔺 TRUE_POSITIVE · Confidence: HIGH

Dismiss false positives

Tick a box to dismiss the finding; untick it to bring the finding back. That is the same as replying /broly dismiss d1 and /broly undismiss d1. To record why it is a false positive, reply with /broly dismiss d1: your reason instead — Broly reuses those reasons to triage similar findings across the org.

  • d8 · 🟡 MEDIUM   · src/xorl/server/orchestrator/request_processor.py:408 · Path traversal in R3 source path validation allows reading file metadata (exi...
  • d26 · 🟡 MEDIUM   · src/xorl/server/runner/model_runner.py:2304 · Unsafe deserialization of untrusted files via torch.load in diagnostic over...
  • d27 · 🟡 MEDIUM   · src/xorl/server/runner/runner_dispatcher.py:1441 · Arbitrary File Read via R3 SGLang Spans

Note

Re-scan this PR anytime with /broly scan — useful after /broly undismiss, or to refresh findings without a new push.

Broly — SAST (zai-org/GLM-5.2) · Secrets · SCA · IaC · GH Actions · Base Images · Supply Chain Threats · Exploit Chains · Adversarial Verification

We're continuously improving Broly's accuracy and finding quality — your feedback is valuable. False positives, missed findings, bugs, and feature requests all welcome.

Ask in #security-engineering   Powered by Together AI

Comment thread scripts/replay_dsv4_exact_trace.py Fixed
@kiddyboots216
kiddyboots216 marked this pull request as ready for review August 13, 2026 19:47
@kiddyboots216
kiddyboots216 force-pushed the pr/consolidated-exact-rl branch 2 times, most recently from b0ad7c3 to 6a62d38 Compare August 13, 2026 20:21
Comment on lines +408 to +421
def _validate_r3_source_path(raw: Any, *, final: bool) -> Path:
path = Path(str(raw or ""))
if not path.is_absolute() or (final and path.name.startswith(".")):
raise ValueError(f"R3 source path must be an absolute payload path: {path}")
configured = os.getenv("XORL_R3_SHARED_ROOTS", "")
roots = [
Path(entry).expanduser().resolve(strict=True) for entry in configured.split(os.pathsep) if entry.strip()
]
if not roots:
raise ValueError("XORL_R3_SHARED_ROOTS must name the trusted SGLang side-channel root")
parent = path.parent.resolve(strict=True)
if not any(parent == root or root in parent.parents for root in roots):
raise ValueError(f"R3 source path is outside XORL_R3_SHARED_ROOTS: {path}")
return path
Comment thread src/xorl/server/runner/runner_dispatcher.py Fixed
Comment thread src/xorl/server/orchestrator/request_processor.py Fixed
Comment thread src/xorl/server/runner/runner_dispatcher.py Fixed
Comment thread src/xorl/ops/kernel_config_pin.py Fixed
@kiddyboots216
kiddyboots216 force-pushed the pr/consolidated-exact-rl branch 2 times, most recently from 7ea50ca to 3b0ccb2 Compare August 14, 2026 12:08
@kiddyboots216
kiddyboots216 force-pushed the pr/consolidated-exact-rl branch from 3b0ccb2 to 19c4328 Compare August 14, 2026 13:39
Comment on lines +1441 to +1501
def _load_sglang_file_routing_slice(self, value: Mapping[str, Any], start: int, count: int) -> List[torch.Tensor]:
if value.get("format") != "spans":
raise ValueError("SGLang R3 source reference must use spans format")
kind = str(value.get("kind", ""))
expected_dtype = torch.int32 if kind == "routed_experts" else torch.float32
expected_dtype_name = "int32" if kind == "routed_experts" else "float32"
items = value.get("items")
total = int(value.get("count", -1))
if kind not in {"routed_experts", "routed_expert_logits"} or not isinstance(items, list):
raise ValueError(f"Invalid SGLang R3 source reference for {kind!r}")
if total != len(items) or start < 0 or count < 0 or start + count > total:
raise ValueError(f"SGLang R3 source slice out of range: start={start}, count={count}, total={total}")

loaded: List[torch.Tensor] = []
for datum_idx, item in enumerate(items[start : start + count], start=start):
if not isinstance(item, Mapping) or item.get("schema") != "xorl.r3.spans.v1":
raise ValueError(f"Invalid R3 span datum {datum_idx}")
shape = item.get("shape")
spans = item.get("spans")
if (
item.get("dtype") != expected_dtype_name
or not isinstance(shape, list)
or len(shape) != 3
or not isinstance(spans, list)
):
raise ValueError(f"Invalid R3 span metadata for datum {datum_idx}")
pieces: List[torch.Tensor] = []
for span_idx, span in enumerate(spans):
if not isinstance(span, Mapping):
raise ValueError(f"Invalid R3 span {datum_idx}/{span_idx}")
rows = int(span.get("rows", -1))
source_row = int(span.get("source_row", -1))
row_nbytes = int(span.get("row_nbytes", -1))
offset = int(span.get("offset", -1)) + source_row * row_nbytes
source_shape = span.get("source_shape")
expected_row_nbytes = math.prod(shape[1:]) * 4
if (
span.get("dtype") != expected_dtype_name
or rows < 0
or source_row < 0
or row_nbytes != expected_row_nbytes
or offset < 0
or not isinstance(source_shape, list)
or len(source_shape) != 3
or source_shape[1:] != shape[1:]
or source_row + rows > int(source_shape[0])
):
raise ValueError(f"Invalid R3 span geometry for datum {datum_idx}/{span_idx}")
path = self._wait_for_r3_source(span)
required = offset + rows * row_nbytes
if path.stat().st_size < required:
raise ValueError(f"R3 source {path} is shorter than span {datum_idx}/{span_idx}")
if rows == 0:
pieces.append(torch.empty((0, *shape[1:]), dtype=expected_dtype))
continue
storage = torch.from_file(str(path), shared=False, size=path.stat().st_size // 4, dtype=expected_dtype)
pieces.append(storage[offset // 4 : required // 4].reshape(rows, *shape[1:]))
if sum(piece.shape[0] for piece in pieces) != int(shape[0]):
raise ValueError(f"R3 span coverage mismatch for datum {datum_idx}")
loaded.append(pieces[0] if len(pieces) == 1 else torch.cat(pieces, dim=0))
return loaded
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