Skip to content

perf(megatron): autotune fused LM-head Triton kernels - #2373

Merged
avigyabb merged 3 commits into
mainfrom
dyurk/triton-fused-lm-autotune
Oct 31, 2026
Merged

avigyabb merged 3 commits into
mainfrom
dyurk/triton-fused-lm-autotune

Conversation

@dyurk-lila

@dyurk-lila dyurk-lila commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Autotune the fused LM-head Triton kernels across bounded shape buckets and skip entropy work for log-probability-only calls.

TLDR: select launch geometry for each workload class while keeping autotuning inputs immutable and log-sum-exp stable for strongly negative logits.

How it works

  • Tune tile dimensions, pipeline stages, and warp counts instead of using one fixed launch configuration.
  • Bucket token counts so neighboring lengths reuse compiled kernels and tuning results.
  • Keep raw, reduced, and result buffers separate: Triton executes multiple candidates during tuning, so an epilogue must not overwrite inputs needed by later candidates.
  • Start log-sum-exp from the true row maximum, including rows where every logit is negative.
  • Remove unreachable vendored reductions and backward strategies, and release the final partial d-logits buffer before its projections.

H100 benchmark

The standalone sweep used one 8x NVIDIA H100 80GB node with 180 CPU requested and limited, Torch 2.11.0+cu130, and Triton 3.6.0. It covered four public LM-head configurations, total token counts from 16K through 256K, and every (TP, CP) combination in {1,2,4,8} with TP*CP <= 8. The 200 logical cases collapse to 104 unique rank-local (M,H,V) shapes. This is a synthetic kernel-shape sweep; it does not consume dataset examples.

Compared with the prior fixed five-stage mainloop:

Metric across 104 local shapes Autotuned
Mean latency reduction 5.57%
Median latency reduction 3.63%
p90 latency reduction 14.47%
Maximum latency reduction 26.82%
Shapes faster 88 / 104
Regressions greater than 1% 4 / 104
Worst regression 1.40%

Mean reductions by LM-head shape were 1.90% for (H=4096,V=154880), 2.02% for (4096,131072), 7.49% for (7168,163840), and 10.89% for (8192,131072).

The largest observed win was the Nemotron Ultra 550B shape at local (M=8192,H=8192,V=131072), from 34.91 ms to 25.54 ms. These are isolated fused-mainloop results on one GPU generation, not end-to-end training claims; the candidate set intentionally retains schedule diversity for other models and accelerators.

Dense log-prob-only specialization

A separate recorded sweep on one 8× NVIDIA H100 80 GB node, with 180 CPU requested and limited, compared the general entropy-capable launch with the log-prob-only specialization used by the SkyRL adapter. It timed the combined fused forward/backward call, with no loss masking. The 22 points covered four LM-head shapes at TP4/CP2 and 16K–256K total tokens, plus (H=4096,V=131072) at TP1/CP1 and TP8/CP1 with 16K tokens.

All 22/22 points were faster: 7.06% mean, 7.17% median runtime reduction, with a 3.28–10.86% range.

LM-head shape (hidden, vocabulary) at TP4/CP2 Mean reduction Range
Nemotron Super 120B (4096, 131072) 9.00% 8.17–10.06%
Nemotron Ultra 550B (8192, 131072) 5.24% 3.28–9.56%
GLM-5.3 Flash (4096, 154880) 8.53% 6.97–10.86%
Kimi K3 (7168, 163840) 4.78% 3.95–5.61%

The additional TP checks reduced runtime by 7.30% at TP1 and 10.11% at TP8. Removing entropy state saved 128 KiB–2 MiB of measured peak allocation as rank-local token count increased. These results measure the specialization separately from the autotuning comparison above; the percentages should not be added together. They are isolated kernel forward/backward results on H100, not whole-training throughput or other-GPU claims. Recorded benchmarks predate the current rebase and were not rerun for it.

Compile and tuning behavior

A specialization probe measured:

  • 20,000 tokens, new 32K bucket: 13.27 s cold compile+tune;
  • 20,001 tokens, same bucket: 6.13 ms, with no exact-length recompile or retune;
  • 40,000 tokens, new 64K bucket: 4.66 s retune.

Crossing a power-of-two bucket intentionally retunes because the winning geometry can change. Broad cold tuning is nontrivial (14.9 s median first call and 514 s for the largest unsharded Kimi case in this sweep), so long-running jobs should warm expected buckets before timing.

Validation

Before the short-tail metrics follow-up, focused CPU suites passed in both mirrors: 415 tests across collation, DP sampling, worker batching, layout, active spans, and Megatron correctness (13 Megatron-only skips); 40 bin-packer tests; and 3 unpacked active-span guard tests with megatron-core installed. Ruff and Black passed. Seven targeted Triton value/gradient tests passed on one H100; the full GPU suite and benchmarks were not rerun.

After the metrics follow-up, 39 focused SFT CPU tests passed in each mirror, including synchronous and asynchronous short-tail logging; Ruff, Black, and secret detection passed on the changed files.

Review order

Part 5 of 9 in a linked series. The stack is based on main; each later PR targets the preceding layer. Review and merge from bottom to top.

Depends on #2372. Review only this layer.

  1. perf(sft): use modified first-fit decreasing packing #2369 — use modified first-fit decreasing packing
  2. perf(train): make sequence packing alignment-aware #2370 — make sequence packing alignment-aware
  3. refactor(megatron): share packed segment layout derivation #2371 — share packed segment layout derivation
  4. perf(sft): align packed bin counts to data parallelism #2372 — align packed bin counts to data parallelism
  5. perf(megatron): autotune fused LM-head Triton kernels #2373 — autotune fused LM-head Triton kernels
  6. feat(megatron): fuse LM-head entropy for RL #2374 — fuse LM-head entropy for RL
  7. feat(megatron): add block-sparse fused LM-head forward #2375 — add block-sparse fused LM-head forward
  8. perf(megatron): add block-sparse fused LM-head backward #2376 — add block-sparse fused LM-head backward
  9. perf(megatron): fuse sample-support candidate projection with Triton #2521 — fuse sample-support candidate projection with Triton

Note

Medium Risk
Changes core fused LM-head Triton math, tensor-parallel epilogues, and backward memory behavior; incorrect numerics or autotune cache behavior would affect training loss and gradients, though tests and benchmarks target these paths.

Overview
This PR retunes SkyRL’s fused LM-head Triton path for Megatron: forward/backward/epilogue kernels now autotune over expanded tile schedules with cached, power-of-two token buckets (exact num_tokens still drives launches), and the SkyRL adapter calls the stack with compute_entropy=False so entropy-only work is compiled out on the log-prob-only training path.

Numerics and autotune safety are tightened: epilogues initialize and pad max reductions with -inf so all-negative logits stay finite, and final log-probs/entropy are written to separate result buffers so repeated tuning cannot corrupt inputs. Backward is simplified to the split-vocab d_logits path only (unused VERL reductions/wrappers removed), with an early release of the staging d_logits buffer on the last split to cut peak memory.

Benchmarks gain --autotune-sweep and an entropy-vs-logprob-only probe; GPU tests add schedule/bucket invariants and a strongly negative logits regression case.

Reviewed by Cursor Bugbot for commit ae7d851. Bugbot is set up for automated code reviews on this repo. Configure here.

@dyurk-lila
dyurk-lila added this pull request to stack #2377 October 1, 2026 14:10

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors and optimizes the Triton fused linear log-prob kernel, introducing cached and bucketed autotuning to prevent recompilation churn, compiling out entropy-only operations when unused, and ensuring numerical stability for strongly negative logits by using the true row maximum for epilogue shifts. It also updates the benchmark suite and adds comprehensive tests. The review feedback correctly identifies an optimization opportunity in the backward pass: when vocab_size is smaller than 9504, hardcoding vocab_per_split to 9504 causes unnecessary memory allocation and redundant copy overhead. Implementing the suggested min(vocab_size, 9504) limit will improve efficiency.

Comment on lines +1051 to +1053
vocab_per_split = 9504
num_splits = (vocab_size + vocab_per_split - 1) // vocab_per_split
d_logits = torch.empty((num_tokens, vocab_per_split), device=hidden.device, dtype=hidden.dtype).contiguous()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

When vocab_size is smaller than 9504 (which is very common per rank when using Tensor Parallelism), hardcoding vocab_per_split = 9504 leads to allocating a significantly larger d_logits staging buffer than necessary. Furthermore, because split_width will be less than vocab_per_split, the code will fall into the else block and perform an expensive .contiguous() copy to slice the tensor, before freeing the original.\n\nBy setting vocab_per_split = min(vocab_size, 9504), we can avoid allocating excess columns, eliminate the redundant copy overhead, and significantly reduce peak GPU memory usage.

    vocab_per_split = min(vocab_size, 9504)\n    num_splits = (vocab_size + vocab_per_split - 1) // vocab_per_split\n    d_logits = torch.empty((num_tokens, vocab_per_split), device=hidden.device, dtype=hidden.dtype).contiguous()

@greptile-apps

greptile-apps Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[High risk] Rewrites Triton kernel autotuning and scheduling logic.

The PR appears safe to merge, with non-blocking benchmark-fidelity and regression-coverage improvements recommended.

Findings

  1. P2 Sweep measures different kernel ▶
  2. P2 TP path lacks regression coverage ▶
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[SkyRL fused LM-head adapter] -->|compute_entropy=False| B[Production mainloop]
  C[Autotune sweep] -->|COMPUTE_ENTROPY=True| D[Measured mainloop]
  B --> E[Log-probabilities]
  D --> F[Reported winning schedule]
Loading

Reviews (1) · Last reviewed commit: "fix(megatron): pass entropy mode in auto..."

config.num_warps,
)


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Sweep measures different kernel The sweep launches candidates with COMPUTE_ENTROPY=True, but the SkyRL adapter uses compute_entropy=False. These kernels do different work, so the reported winning schedule and latency gains may not represent the production path. Measuring the log-probability-only specialization would make the results useful for that path.

Comment on lines +361 to +363
logprobs, entropy, maximum, accumulate, entropy_b = fused_linear_logprob_triton.efficient_entropy_forward(
hidden, weight, labels, 1.0, None
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 TP path lacks regression coverage This negative-logit test uses the local, entropy-enabled forward path. Tensor parallelism uses a separate epilogue, and the production adapter disables entropy, so the test would not catch a regression in that combination. A TP log-probability-only case would cover the changed production path.

Knowledge Base Used: Backend workers and distributed strategies

@dyurk-lila
dyurk-lila force-pushed the dyurk/triton-fused-lm-autotune branch from 0f50e56 to d219a61 Compare October 7, 2026 18:38
@dyurk-lila
dyurk-lila force-pushed the dyurk/triton-fused-lm-autotune branch from d219a61 to 5566c6d Compare October 15, 2026 15:55
@dyurk-lila
dyurk-lila force-pushed the dyurk/triton-fused-lm-autotune branch from 5566c6d to d68c42b Compare October 15, 2026 17:16
@dyurk-lila
dyurk-lila force-pushed the dyurk/triton-fused-lm-autotune branch from d68c42b to ae7d851 Compare October 19, 2026 18:24
@dyurk-lila
dyurk-lila force-pushed the dyurk/triton-fused-lm-autotune branch from ae7d851 to 690e082 Compare October 20, 2026 17:38
@dyurk-lila
dyurk-lila force-pushed the dyurk/triton-fused-lm-autotune branch from 690e082 to e2c58d5 Compare October 21, 2026 20:45
Signed-off-by: Dominic Yurk <dyurk@lila.ai>
Signed-off-by: Dominic Yurk <dyurk@lila.ai>
Signed-off-by: Dominic Yurk <dyurk@lila.ai>
@dyurk-lila
dyurk-lila force-pushed the dyurk/triton-fused-lm-autotune branch from 8eeef97 to 8cc8466 Compare October 28, 2026 15:50
@avigyabb
avigyabb merged commit f4fbe75 into main Oct 31, 2026
9 checks passed
avigyabb pushed a commit that referenced this pull request Oct 31, 2026
# What does this PR do?

Compute selected-token log-probabilities and policy entropy from one
fused LM-head projection for RL.


## How it works

Metric-only entropy reuses the forward reductions without adding
entropy-gradient work. Entropy-loss mode keeps the entropy derivative in
the fused autograd path.

Torch and dense Triton return log-probabilities and entropy through the
same packed TP/CP gather/scatter contract. #2375 adds block-sparse
forward computation on top of this shared entropy path, and #2376 adds
block-sparse backward computation.

## Usage

Existing fused LM-head settings also cover entropy metrics and
`use_entropy_loss`; the caller’s gradient requirement selects the
entropy backward behavior.

## Performance

Recorded measurements on one 8× NVIDIA H100 80 GB node compared the
combined dense Triton path with fused selected-token log-probability
scoring followed by the previous separate metric-entropy projection.
Across **115 points**, the combined path was a median **1.44× faster**.
The sweep covered four LM-head shapes, 16K–256K tokens, and
representative TP/CP layouts with `TP × CP <= 8`.

For differentiable entropy at TP4/CP2, `(H=4096,V=131072)`, and 16K
tokens, the recorded speedup versus fused log-probability scoring plus a
separate differentiable entropy projection was:

| Active rows | Dense combined / previous two-pass speedup |
| ---: | ---: |
| 100% | 2.15× |
| 95% | 2.13× |
| 73% | 2.13× |
| 64% | 2.11× |
| 23% | 2.17× |

The differentiable-entropy measurements used 180 CPU requested and
limited. The small variation across activity levels is measurement
noise: this PR's dense path does not inspect the activity pattern. #2375
measures the additional benefit from skipping inactive forward tiles
against this shared entropy baseline.

These are isolated kernel measurements on one GPU generation and four
model shapes, not end-to-end training throughput or universal model/GPU
claims. Recorded benchmarks predate the current rebase and were not
rerun for it.

## Test coverage

Tests compare entropy values, selected-token log-probabilities, hidden
gradients, and weight gradients with materialized-logit references,
including packed TP2/CP2 and metric-only entropy.

## Validation

Before the short-tail metrics follow-up, focused CPU suites passed in
both mirrors: 415 tests across collation, DP sampling, worker batching,
layout, active spans, and Megatron correctness (13 Megatron-only skips);
40 bin-packer tests; and 3 unpacked active-span guard tests with
megatron-core installed. Ruff and Black passed. Seven targeted Triton
value/gradient tests passed on one H100; the full GPU suite and
benchmarks were not rerun.

After the metrics follow-up, 39 focused SFT CPU tests passed in each
mirror, including synchronous and asynchronous short-tail logging; Ruff,
Black, and secret detection passed on the changed files.

## Review order

Part **6 of 9** in a linked series. The stack is based on `main`; each
later PR targets the preceding layer. Review and merge from bottom to
top.

Depends on #2373. [Review only this
layer](d219a61...1c449ae).

1. #2369 — use modified first-fit decreasing packing
2. #2370 — make sequence packing alignment-aware
3. #2371 — share packed segment layout derivation
4. #2372 — align packed bin counts to data parallelism
5. #2373 — autotune fused LM-head Triton kernels
6. #2374 — fuse LM-head entropy for RL
7. #2375 — add block-sparse fused LM-head forward
8. #2376 — add block-sparse fused LM-head backward
9. #2521 — fuse sample-support candidate projection with Triton

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes fused autograd and distributed log-prob/entropy math on the
Megatron training hot path; mistakes would skew RL policy gradients or
entropy bonuses, though new reference tests cover torch/Triton and TP
layouts.
> 
> **Overview**
> Megatron’s **fused LM-head** path now returns **per-token entropy from
the same hidden→vocab projection** as selected-token log-probs, for both
the PyTorch chunked op and the Triton adapter. Callers pass
`return_entropy` / `compute_entropy` and `entropy_requires_grad`;
metric-only entropy skips backward work, while `use_entropy_loss`
threads entropy gradients through the fused autograd backward (including
TP/CP gather and packed scatter-back via new
`_unpack_prediction_values`).
> 
> The Megatron worker **drops the separate no-grad entropy projection**
and the prior `NotImplementedError` when `fused_lm_head_logprob` and
`use_entropy_loss` were both on—it reuses fused entropy for RL
objectives (non–cross-entropy). Standalone helpers
`from_parallel_hidden_to_entropy_packed_sequences` /
`_fused_vocab_parallel_entropy_from_hidden` are removed in favor of this
single pass.
> 
> GPU tests compare fused entropy+log-prob outputs and gradients to
materialized-logit references (torch and Triton); worker CI adds fused
torch/triton + entropy-loss cases.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f6712a4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: Dominic Yurk <dyurk@lila.ai>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ArturNiederfahrenhorst added a commit to ArturNiederfahrenhorst/SkyRL that referenced this pull request Nov 2, 2026
Reconciles the backend_config validation with NovaSky-AI#2529, now on main:

- check_lora_group_flags lost its strategy argument, and the critic's
  pre-worker call now passes the critic's init_adapter_path (the server-side
  trainer.critic.model.lora value is the one the workers will load), matching
  the policy-side and multi-tenant calls.
- _build_critic keeps the dead rank check removed: the client-carried keys'
  outright rejection at the policy's first create_model still covers the
  critic, so no check is reintroduced for the merge.
- Everything else is main's own: NovaSky-AI#2529's Megatron narrow honour, the OPD
  entrypoint (NovaSky-AI#2256) and the fused LM-head kernels (NovaSky-AI#2373, NovaSky-AI#2374).

Co-Authored-By: Claude Code <noreply@anthropic.com>
avigyabb added a commit that referenced this pull request Nov 4, 2026
# What does this PR do?

Skip LM-head projection and softmax work for wholly inactive loss-mask
row tiles in SFT and RL.


## How it works

The explicit `triton_block_sparse` backend tests whether a row tile
contains any active loss positions before projecting it. Active rows
retain their original token coordinates, and inactive outputs are
zeroed. The shared entropy path comes from #2374. This layer keeps dense
backward computation; #2376 adds sparse backward work.

The worker forwards the required targets and activity mask through
packed and unpacked Megatron paths. Torch and dense Triton remain
available through the same backend selector.

## Usage

Enable `trainer.fused_lm_head_logprob=true` and set
`trainer.fused_lm_head_logprob_backend=triton_block_sparse`.

Benchmark representative masks and TP/CP layouts before selecting this
backend: nearly fully active masks can regress. Sample-support replay is
outside this series.

## Performance

A recorded sweep on one 8× NVIDIA H100 80 GB node, with 180 CPU
requested and limited, compared dense Triton with forward tile skipping,
keeping backward computation identical between arms. Seven post-warmup
CUDA-event repetitions used rotated order and the slowest TP/CP rank.
These are isolated fused LM-head forward-plus-backward latencies, not
whole-training throughput.

Across 58 recorded loss-mask/layout measurements, skipping won
**55/58**, with **4.67% mean** and **4.62% median** latency reduction;
the range was **−2.49% to +10.00%**. All 40 TP4/CP2 model/length points
won:

| LM-head shape `(hidden, vocabulary)`, 16K–256K tokens | Wins | Mean
latency reduction | Range |
| --- | ---: | ---: | ---: |
| Nemotron Super 120B `(4096, 131072)` | 10/10 | 4.59% | 2.59–6.99% |
| Nemotron Ultra 550B `(8192, 131072)` | 10/10 | 5.10% | 3.34–8.75% |
| GLM-5.3 Flash `(4096, 154880)` | 10/10 | 4.56% | 2.30–9.41% |
| Kimi K3 `(7168, 163840)` | 10/10 | 5.73% | 3.42–9.31% |

The three regressions had only 2K–4K rank-local rows.

For RL with differentiable entropy at TP4/CP2, `(H=4096,V=131072)`, and
16K tokens, recorded speedups were:

| Active rows | Sparse combined / previous two-pass | Sparse / dense
combined | Metric-only sparse / dense median |
| ---: | ---: | ---: | ---: |
| 100% | 2.10× | 0.98× | 1.00× |
| 95% | 2.11× | 0.99× | 1.01× |
| 73% | 2.13× | 1.00× | 1.02× |
| 64% | 2.35× | 1.11× | 1.16× |
| 23% | 2.99× | 1.38× | 1.41× |

The two-pass comparison includes the entropy-projection savings
introduced in #2374; the dense-combined comparison isolates this PR's
increment over that shared path. Those ratios are approximate. The
metric-only medians come from the broader sweep at the same activity
levels, rather than only the single shape used for the
differentiable-entropy comparison.

The benefit depends on whole inactive tiles, not just the percentage of
masked tokens. Near-dense masks, short local sequences, other shapes,
and other hardware can favor dense Triton; the backend remains opt-in.
Recorded benchmarks predate the current rebase and were not rerun for
it.

## Test coverage

GPU reference tests cover forward parity and inactive outputs, while
worker and configuration tests cover backend selection, loss-output
gating, and packed TP/CP layouts.

## Validation

Before the short-tail metrics follow-up, focused CPU suites passed in
both mirrors: 415 tests across collation, DP sampling, worker batching,
layout, active spans, and Megatron correctness (13 Megatron-only skips);
40 bin-packer tests; and 3 unpacked active-span guard tests with
megatron-core installed. Ruff and Black passed. Seven targeted Triton
value/gradient tests passed on one H100; the full GPU suite and
benchmarks were not rerun.

After the metrics follow-up, 39 focused SFT CPU tests passed in each
mirror, including synchronous and asynchronous short-tail logging; Ruff,
Black, and secret detection passed on the changed files.

## Review order

Part **7 of 9** in a linked series. The stack is based on `main`; each
later PR targets the preceding layer. Review and merge from bottom to
top.

Depends on #2374. [Review only this
layer](1c449ae...0d8e3cf).

1. #2369 — use modified first-fit decreasing packing
2. #2370 — make sequence packing alignment-aware
3. #2371 — share packed segment layout derivation
4. #2372 — align packed bin counts to data parallelism
5. #2373 — autotune fused LM-head Triton kernels
6. #2374 — fuse LM-head entropy for RL
7. #2375 — add block-sparse fused LM-head forward
8. #2376 — add block-sparse fused LM-head backward
9. #2521 — fuse sample-support candidate projection with Triton

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes fused LM-head numerics and gradients on a hot Megatron
training path (TP/CP/packed layouts), though behavior is opt-in and
heavily tested; misconfigured masks or near-dense activity could still
skew loss or performance.
> 
> **Overview**
> Adds an opt-in **`triton_block_sparse`** fused LM-head backend that
threads an **`active_mask`** from the RL/SFT **loss mask** through
Megatron’s packed and unpacked log-prob paths.
> 
> The Triton forward **skips wholly inactive row tiles** (no reordering
or row gathers) while inactive tokens still get **zero
log-probs/entropy** and **zeroed gradients** on the dense backward path.
**`FusedLmHeadBackend`** and trainer config validation gate the new
mode; the Megatron worker **builds and packs** the mask, rejects
**sample-support replay**, and **sanitizes inactive RL operands** so
ratio-style losses do not NaN. The pure-torch fused path applies the
same mask via **`masked_fill`**. Benchmarks and GPU/CPU tests cover
parity, autotune keys, and backend selection.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
9602a10. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: Dominic Yurk <dyurk@lila.ai>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Avigya Basnet <avigyabb@gmail.com>

This branch was successfully deployed

1 active deployment
Preview — 8cc8466b Deployed Oct 28, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants