Skip to content
Markdown

Reasoning-effort control

Scope: the training-time and serving-time machinery behind a reasoning_effort: low | high | max switch. This page covers the four reward shapes that actually produce effort levels (an absolute length penalty, a group-relative length penalty, a hard per-problem budget override, and a phase-alternating gate), the two ways those levels get packaged into one shipped checkpoint (separate specialists plus distillation, or a single conditioned policy), and how to pick an operating point from a cost model rather than by feel. The sibling pages are inference-time scaling, which spends compute without touching weights, and RLVR, which supplies the correctness half of every reward here. Consolidating the trained specialists is multi-teacher on-policy distillation.

The numpy block below is executed and asserted in this page (Python 3.11, numpy 2.x, no other dependencies). It implements the published reward equations on synthetic rollouts, so the reward shapes and their edge cases are verifiable without a training run. It does not reproduce anyone's benchmark numbers; those are quoted from the cited reports and are not independently measured here.

What it is

Reasoning-effort control is the ability to ask a reasoning model for a specific amount of thinking and get it. It exists at two layers that are easy to conflate:

  • The interface layer is a knob. It can be a system-prompt line (Reasoning effort: low, the GPT-OSS style), a structured option message (Kimi K3 exposes effort as a thinking-effort global option in its XTML chat template, placed before all input messages because it governs the whole session), a mode token pair (/think and /no_think in Qwen3's thinking-mode fusion), or a number of tokens written into the prompt (L1's Think for 512 tokens).
  • The behaviour layer is what makes the knob mean anything. A knob with no training behind it is decoration. The behaviour comes from a length-aware reward during RL, which is the actual subject of this page.

Four reward shapes cover essentially all of the published work:

Shape Signal Source
Absolute deviation from a prompted target I(correct) - alpha * abs(n_target - n_out) L1 / LCPO-Exact
Soft one-sided budget I(correct) * clip(alpha*(n_target - n_out) + delta, 0, 1) L1 / LCPO-Max
Group-relative rank within a rollout group shortest correct gets +0.5, longest gets -0.5 Kimi k1.5
Hard per-problem budget override reward becomes -1 past tau * b0(x) Kimi K3

On top of those sits Toggle (Kimi K2.5), which is not a fifth shape but a schedule: it alternates budget-constrained iterations with unconstrained ones to stop the model from forgetting how to use a large budget.

Why use it

  • Thinking tokens are the dominant cost line on a reasoning deployment. A model at max effort can emit several times the tokens of the same model at low effort for the same prompt. Kimi K2.5 reports that Toggle cuts output tokens by 25 to 30% on average "with a negligible impact on performance"; that is a direct serving-cost reduction of the same magnitude with no accuracy trade to defend.
  • Overthinking is a real training pathology, not a user preference. Kimi k1.5 names it explicitly: response length grows steadily during RL, "although this leads to better performance, an excessively lengthy reasoning process is costly during training and inference." The length reward exists to stop the growth, not to please anyone's taste.
  • Effort is the cheapest quality knob you have. Changing effort is a request parameter. Changing models is a deployment. When a tier of traffic needs a few more points of accuracy, raising effort for that tier is the first thing to try, and it composes with everything else.
  • Length control transfers out of distribution. L1 trains only on math and finds the length-following behaviour generalises to logical reasoning and to MMLU, so a budget knob trained in one domain is worth something in another.
  • A short-CoT model distilled from a long-CoT model beats a native short-CoT model. This is the k1.5 long2short result: the short variant reaches 60.8 on AIME and 94.6 on MATH500, well past the short-CoT models it is compared against. Effort control is therefore also a capability technique, not only a cost technique.

When to use it (and when not)

Use it when:

  • You serve a mixed workload where a large fraction of requests are easy. Routing those to low effort is close to free accuracy-neutral savings.
  • You have a hard per-request latency SLO. A budget the model actually respects is the only reliable way to bound decode time; a max_tokens cutoff truncates mid-thought and destroys the answer instead of shortening it.
  • You are already running RLVR and can afford one more reward term. The marginal cost of adding a length term to an existing verifiable reward is small.

Do not use it when:

  • You have no verifier. Every shape here multiplies or adds to a correctness signal. With a noisy or absent correctness term, the length term dominates and you train a model that is confidently brief and wrong.
  • You need a guaranteed hard cap. These are soft trained behaviours. L1 reports low but nonzero mean deviation from the requested length. If the cap is a contractual limit, enforce it in the serving layer as well.
  • Your traffic is uniformly hard. If nearly every request needs max effort, the machinery buys you nothing and the budget-constrained phases cost you accuracy.
  • You are training a single narrow-budget model and expect it to scale up later. This is the length-overfitting failure K2.5 documents: "models trained under rigid budget constraints often fail to generalize to higher compute scales", defaulting to truncated reasoning even when given room. Use an alternating schedule instead.

Architecture

flowchart TB
  subgraph TRAIN["Post-training"]
    SFT["SFT cold start"]
    RL["RLVR loop"]
    LEN["Length-aware reward term<br/>(one of the four shapes)"]
    EXP["Effort specialists<br/>low / high / max"]
    SFT --> RL
    LEN --> RL
    RL --> EXP
  end
  subgraph SHIP["Packaging"]
    MERGE["Consolidate:<br/>multi-teacher on-policy distillation<br/>or weight merge"]
    ONE["Single conditioned checkpoint"]
    EXP --> MERGE --> ONE
  end
  subgraph SERVE["Serving"]
    KNOB["effort knob in the request<br/>(option message / system line / token target)"]
    ROUTE["Router: difficulty to effort tier"]
    CAP["Hard token cap in the engine<br/>(backstop, not the mechanism)"]
    ONE --> KNOB
    ROUTE --> KNOB
    KNOB --> CAP
  end

The load-bearing point of the diagram is that the knob at serving time and the reward at training time have to agree on what low means. If RL trained low against a budget of roughly 3k thinking tokens and the serving tier caps at 1k, the model is being asked for a mode it was never trained on and will truncate rather than compress.

How it works: the reward shapes, validated

import numpy as np


# --- L1 / LCPO-Exact, Eq. 1 of arXiv:2503.04697 -------------------------------
def lcpo_exact(correct: np.ndarray, n_out: np.ndarray, n_target: int,
               alpha: float) -> np.ndarray:
    return correct.astype(float) - alpha * np.abs(n_target - n_out)


# --- L1 / LCPO-Max, Eq. 2 -----------------------------------------------------
def lcpo_max(correct: np.ndarray, n_out: np.ndarray, n_target: int,
             alpha: float, delta: float = 0.5) -> np.ndarray:
    soft = np.clip(alpha * (n_target - n_out) + delta, 0.0, 1.0)
    return correct.astype(float) * soft


# --- Kimi k1.5 group length reward -------------------------------------------
def k15_length_reward(correct: np.ndarray, lengths: np.ndarray) -> np.ndarray:
    lo, hi = lengths.min(), lengths.max()
    if hi == lo:
        return np.zeros(len(lengths))
    lam = 0.5 - (lengths - lo) / (hi - lo)
    return np.where(correct, lam, np.minimum(0.0, lam))


# --- Kimi K3 per-problem budget override -------------------------------------
def k3_budget_override(task_reward: np.ndarray, tokens: np.ndarray,
                       b0: float, tau: float) -> np.ndarray:
    return np.where(tokens > tau * b0, -1.0, task_reward)


# --- Kimi K2.5 Toggle gate ----------------------------------------------------
def toggle_reward(rewards: np.ndarray, lengths: np.ndarray,
                  budget: float, lam: float) -> np.ndarray:
    group_pass = rewards.mean()
    keep = (group_pass < lam) | (lengths <= budget)
    return rewards * keep


def toggle_phase(t: int, m: int) -> int:
    """0 = budget-limited Phase0, 1 = free-scaling Phase1."""
    return (t // m) % 2


def toggle_step(t: int, m: int, rewards: np.ndarray, lengths: np.ndarray,
                budget: float, lam: float) -> np.ndarray:
    if toggle_phase(t, m) == 1:
        return rewards.copy()
    return toggle_reward(rewards, lengths, budget, lam)


def toggle_budget(rewards: np.ndarray, lengths: np.ndarray, rho: float) -> float:
    """Percentile rho of the lengths of the CORRECT rollouts only."""
    correct = lengths[rewards > 0]
    assert correct.size, "no correct rollout: budget is undefined for this prompt"
    return float(np.percentile(correct, rho))


ALPHA_EXACT = 0.0003
N_TARGET = 1000

# 1. LCPO-Exact peaks exactly at the target and is symmetric around it.
lens = np.arange(200, 1801, 50)
r = lcpo_exact(np.ones_like(lens, dtype=bool), lens, N_TARGET, ALPHA_EXACT)
assert lens[r.argmax()] == N_TARGET
assert np.isclose(lcpo_exact(np.array([True]), np.array([800]), N_TARGET, ALPHA_EXACT),
                  lcpo_exact(np.array([True]), np.array([1200]), N_TARGET, ALPHA_EXACT))

# 2. The Eq. 1 crossover: a correct answer far enough off-target scores BELOW a
#    wrong answer that lands on the target. Solve alpha*|d| > 1  =>  |d| > 1/alpha.
d_cross = 1.0 / ALPHA_EXACT
wrong_on_target = lcpo_exact(np.array([False]), np.array([N_TARGET]), N_TARGET, ALPHA_EXACT)[0]
assert wrong_on_target == 0.0
just_inside = lcpo_exact(np.array([True]), np.array([N_TARGET + int(d_cross) - 100]),
                         N_TARGET, ALPHA_EXACT)[0]
just_outside = lcpo_exact(np.array([True]), np.array([N_TARGET + int(d_cross) + 100]),
                          N_TARGET, ALPHA_EXACT)[0]
assert just_inside > wrong_on_target > just_outside, (just_inside, just_outside)

# 3. LCPO-Max: zero for every incorrect answer, exactly delta at the budget, and
#    a correct answer overshooting by more than delta/alpha also collapses to 0.
ALPHA_MAX = 0.0003
assert lcpo_max(np.array([False]), np.array([100]), N_TARGET, ALPHA_MAX)[0] == 0.0
assert lcpo_max(np.array([True]), np.array([N_TARGET]), N_TARGET, ALPHA_MAX)[0] == 0.5
overshoot = int(0.5 / ALPHA_MAX) + 100
assert lcpo_max(np.array([True]), np.array([N_TARGET + overshoot]), N_TARGET, ALPHA_MAX)[0] == 0.0

# 3b. The ceiling is reached only by undershooting (1 - delta)/alpha tokens, which
#     a 1k budget cannot even express: being 900 tokens short still scores 0.77.
assert np.isclose(lcpo_max(np.array([True]), np.array([100]), N_TARGET, ALPHA_MAX)[0], 0.77)
saturating_target = 4096
undershoot_needed = (1.0 - 0.5) / ALPHA_MAX
assert undershoot_needed > N_TARGET  # unreachable at a 1k budget
assert lcpo_max(np.array([True]), np.array([saturating_target - int(undershoot_needed) - 1]),
                saturating_target, ALPHA_MAX)[0] == 1.0

# 4. The vanishing-gradient trap: a GRPO group where every rollout is either
#    wrong or badly over budget has identical rewards, so the advantage is zero.
grp_correct = np.array([False, False, True, True])
grp_len = np.array([1400, 1600, N_TARGET + overshoot, N_TARGET + overshoot + 500])
grp_r = lcpo_max(grp_correct, grp_len, N_TARGET, ALPHA_MAX)
assert grp_r.std() == 0.0 and grp_r.sum() == 0.0

# 5. Kimi k1.5: shortest response gets +0.5, longest -0.5, and a wrong answer
#    can never earn a positive length reward.
c = np.array([True, True, True, False])
L = np.array([400, 700, 1200, 400])
lr = k15_length_reward(c, L)
assert np.isclose(lr[0], 0.5) and np.isclose(lr[2], -0.5)
assert lr[3] <= 0.0
assert np.all(k15_length_reward(c, np.full(4, 800)) == 0.0)

# 6. Kimi K3: the override is a cliff, not a slope. One token past tau*b0 flips
#    a perfect trajectory to -1.
b0, tau = 4000.0, 1.5
tok = np.array([5999, 6000, 6001])
kr = k3_budget_override(np.ones(3), tok, b0, tau)
assert list(kr) == [1.0, 1.0, -1.0]

# 7. Kimi K2.5 Toggle: when the group is solving the problem (pass rate >= lam),
#    only within-budget rollouts keep their reward; when the group is failing,
#    the budget gate is lifted so learning signal survives.
rw = np.array([1.0, 1.0, 1.0, 0.0])
ln = np.array([500, 900, 2500, 600])
solved = toggle_reward(rw, ln, budget=1000, lam=0.5)
assert list(solved) == [1.0, 1.0, 0.0, 0.0]
hard = toggle_reward(np.array([1.0, 0.0, 0.0, 0.0]), ln, budget=1000, lam=0.5)
assert list(hard) == [1.0, 0.0, 0.0, 0.0]
assert toggle_reward(np.array([0.0, 0.0, 0.0, 1.0]), np.array([2500, 2500, 2500, 2500]),
                     budget=1000, lam=0.5).sum() == 1.0

# 7b. Phase alternation every m iterations, and the budget percentile is taken
#     over correct rollouts only (a wrong short answer must not set the budget).
assert [toggle_phase(t, m=4) for t in range(12)] == [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0]
assert list(toggle_step(0, 4, rw, ln, 1000, 0.5)) == [1.0, 1.0, 0.0, 0.0]
assert list(toggle_step(5, 4, rw, ln, 1000, 0.5)) == list(rw)  # Phase1 lifts the gate
b_est = toggle_budget(np.array([1.0, 1.0, 1.0, 0.0]), np.array([500, 900, 2500, 120]), rho=50)
assert b_est == 900.0, b_est

# 8. Budget adherence: mean absolute deviation from the requested length.
def mean_deviation(requested: np.ndarray, produced: np.ndarray) -> float:
    return float(np.mean(np.abs(requested - produced)))

req = np.array([512, 1024, 2048, 3600])
got = np.array([548, 1001, 2110, 3475])
assert abs(mean_deviation(req, got) - 61.5) < 1e-9, mean_deviation(req, got)

# 9. Equal-cost effort comparison.
def equal_cost_score(acc: dict, tokens: dict, budget_tokens: float) -> dict:
    return {k: acc[k] * min(1.0, budget_tokens / tokens[k]) for k in acc}

acc = {"low": 0.62, "high": 0.74, "max": 0.78}
tok_per_q = {"low": 3_000.0, "high": 11_000.0, "max": 26_000.0}
ec = equal_cost_score(acc, tok_per_q, budget_tokens=11_000.0)
assert ec["high"] > ec["max"], ec
assert max(ec, key=ec.get) == "high"

print("all reasoning-effort reward assertions passed")
print("  LCPO-Exact crossover distance (tokens):", int(d_cross))
print("  LCPO-Max zero-reward overshoot (tokens):", int(0.5 / ALPHA_MAX))
print("  equal-cost scores:", {k: round(v, 4) for k, v in ec.items()})

Executed output:

all reasoning-effort reward assertions passed
  LCPO-Exact crossover distance (tokens): 3333
  LCPO-Max zero-reward overshoot (tokens): 1666
  equal-cost scores: {'low': 0.62, 'high': 0.74, 'max': 0.33}

Four results from that block are worth reading carefully, because each is a decision you have to make when you implement this.

Assertion 2 is the reason alpha is the hyperparameter that matters. Under LCPO-Exact the reward is I(correct) - alpha*|d|, so a correct answer that misses the target by more than 1/alpha tokens scores below a wrong answer that hits the target. At alpha = 3e-4 that crossover is 3333 tokens, comfortably outside the range a length-following model wanders into. Set alpha an order of magnitude higher and the crossover moves inside the operating range, at which point you are training a model to prefer being wrong on time over being right late. The paper is explicit about the intent: "a lower value of alpha prioritizes correctness when it is critical, whereas a higher value enforces stricter adherence to the length constraint."

Assertion 3b explains why LCPO-Max's clip(..., 0, 1) upper bound is mostly theoretical at small budgets. The reward only saturates at 1.0 when the model undershoots by (1 - delta)/alpha = 1666 tokens. At a 1000-token budget that is unreachable, so the effective reward range for correct answers is roughly [0, 0.8] and the gradient toward brevity stays alive across the whole range. At a 4096-token budget the ceiling is reachable and the incentive to compress further disappears past that point. The interaction between alpha, delta and your typical budget decides where the model stops trying.

Assertion 4 is the failure mode that will actually bite you. LCPO-Max returns exactly 0 for every incorrect answer and for every correct answer more than delta/alpha over budget. Feed a group of four rollouts where all of them are one or the other into GRPO, and the group standard deviation is zero, so every advantage is zero and the step teaches nothing. This is the same degenerate-group condition GRPO has generally, but the length term makes it much easier to hit, because a hard prompt where the model reliably overshoots produces an all-zero group even when some answers were correct. Watch frac_reward_zero_std.

Assertion 6 shows the K3 override is a cliff. Kimi K3 associates each problem x with an initial budget b0(x) estimated from the cold-start model, then "override[s] the task reward with -1 for trajectories whose total token budget T(y) exceeds a scaled threshold tau * b0(x)". There is no ramp. One token past the threshold turns a fully correct long-horizon trajectory into the worst possible outcome. That is a deliberate choice: it makes the budget behave like a constraint rather than a preference, at the cost of a very sharp gradient at the boundary. Note also what T(y) counts: thinking tokens for general tasks, but for agentic tasks "the cumulative output tokens, including both reasoning traces and tool-call arguments", so a verbose tool call spends the same budget as verbose thinking.

How to use it: pick the operating point from the cost model

Assertion 9 is the calculation most teams skip. Given per-effort accuracy and per-effort token consumption, the question is not "which mode is most accurate" but "which mode is most accurate at the compute I am willing to spend". With the synthetic numbers in the block, max is the most accurate mode in isolation (0.78 against 0.74), but at a fixed budget equal to one high response it can only afford 42% of a max response, so its equal-cost score collapses to 0.33 and high wins.

Real reports show the same shape. Kimi K3's own comparison notes that at high effort it "already matches Claude Opus 4.8's maximum-effort score at roughly one third of the cost", and that on Kimi Code Bench 2.0 it lands 4.0 points behind Claude Fable 5 "at 38% of its cost". DeepSeek-V4 makes the counterpoint: its Max mode, "which employs longer contexts and reduced length penalties in RL, outperforms the High mode on the most challenging tasks". Both statements are true at once. Max effort wins on the hard tail; high effort wins on cost-normalised aggregate. That is exactly why routing exists.

Practical recipe:

  1. Measure accuracy and mean completion tokens per effort level on your eval, not the vendor's.
  2. Compute the equal-cost score at the budget you actually plan to spend per request.
  3. Split traffic. Send the tail that fails at high to max; send everything else down.
  4. Re-measure after any model update. Effort curves move between checkpoints more than raw accuracy does.

How to develop with it: choosing a shape

If you need Use Because
A prompt-specified token target the user controls LCPO-Exact It is the only shape that rewards hitting a target rather than staying under one
A ceiling with no reward for being needlessly short LCPO-Max One-sided, and delta keeps small violations preferable to being wrong
Token efficiency with no per-prompt target at all Kimi k1.5 group reward Needs only the rollout group; no budget estimation step
A budget that is a constraint, not a preference Kimi K3 override The -1 cliff is not negotiable by the policy
Efficiency without losing the ability to scale up K2.5 Toggle Alternation is the documented fix for length overfitting

Two implementation details are easy to get wrong:

  • The k1.5 shape is group-relative, so it is free of any budget estimate but also unanchored. Every group produces one response at +0.5 and one at -0.5 regardless of whether the group is uniformly verbose. If the whole group is 20k tokens, the shortest one still gets the full bonus. It shrinks the spread within a group and relies on that pressure compounding over training rather than on an absolute target. The paper also handles the degenerate case explicitly: when max_len == min_len the reward is zero for everyone, which assertion 5 checks.
  • The Toggle budget must be estimated over correct rollouts only (assertion 7b). The published definition takes the rho-th percentile of {|y_j| : r(x, y_i) = 1}. If you compute the percentile over all rollouts, a short wrong answer drags the budget down and you train the model toward the length of its failures. K2.5 also estimates the budget once at the start of training and holds it fixed, which avoids a feedback loop where the budget chases the policy it is constraining.

Warm-up matters too. Kimi k1.5 found that "length penalty may slow down training during the initial phases" and resolved it by running standard policy optimisation first, then switching on a constant length penalty for the rest of training. Turning the length term on at step zero fights the model while it is still learning to be correct at all.

How to maintain it: keep the specialists, not just the merge

Both K3 and DeepSeek-V4 train separate models per effort level and then consolidate, and this is a maintenance decision as much as a quality one.

  • Kimi K3 crosses three domains (general, general agent, coding) with three effort levels (low, high, max) to get nine expert models, then folds them into one checkpoint with multi-teacher on-policy distillation. Its effort experts come from a stage-wise curriculum over the budget multiplier tau: train a max-budget variant with large tau first while still capping the maximum to suppress overthinking, then anneal tau down to get the high- and low-effort experts. The tau schedule is "configured per domain under human-in-the-loop guidance", so it is not a single global number.
  • DeepSeek-V4 trains distinct specialists per effort mode with "distinct length penalties and context windows during RL", demarcates the modes with <think> and </think> formats, and for its Think Max mode prepends a specific instruction to the system prompt.

Keeping the specialists means a regression in one effort tier can be diagnosed and retrained without touching the others, and a new effort tier can be added by training one more expert rather than redoing the whole run. If you only keep the merged checkpoint you lose that.

For a lighter-weight path, Kimi k1.5's long2short menu still applies and does not require an RL run per level: merge a long-CoT and short-CoT model by averaging weights (model merging); or sample n = 8 responses and SFT on the shortest correct one (shortest rejection sampling); or build DPO pairs with the shortest correct solution as positive and longer responses (wrong ones, plus correct ones more than 1.5x the positive's length) as negatives; or run a short second RL phase with the length penalty on and the max rollout length cut down.

How to run it in production

  • Expose effort as a first-class request field, not a prompt prefix your gateway splices in. K3's design point is worth copying: effort is a global option placed before all input messages because it governs the session and rarely changes. Splicing it into a user turn puts it inside the prompt cache prefix boundary and can invalidate cache hits on every request.
  • Keep an engine-side token cap as a backstop, set above the trained budget. The trained behaviour is soft. The cap catches the tail; it should not be the mechanism.
  • Alert on completion-token distribution per effort tier, not just the mean. The failure you care about is bimodality: a tier that mostly respects its budget but occasionally runs 10x is a latency SLO problem that a mean hides.
  • Budget accounting must match the training definition. If you trained agentic budgets over reasoning plus tool-call arguments (the K3 definition of T(y)), meter the same thing in production or your dashboards will disagree with the policy.
  • Track reasoning-token share. Reasoning tokens are billed output tokens but are not the answer. A tier where reasoning is the large majority of completion tokens is a candidate for a lower effort level.

Failure modes

  • Length overfitting. Trained under a rigid budget, the model cannot use a larger budget later and produces truncated reasoning even when given room. This is the documented motivation for Toggle. Symptom: accuracy flat or falling as you raise the budget at inference.
  • Degenerate reward groups. With one-sided shapes, groups where everything is wrong or over budget give zero advantage (assertion 4). Symptom: frac_reward_zero_std climbing, gradient norm collapsing.
  • alpha set too aggressively. Past 1/alpha inside your operating range, the model prefers a wrong answer of the right length (assertion 2). Symptom: accuracy drops while length adherence improves.
  • Budget estimated over all rollouts. Contaminates the budget with the lengths of failures, biasing the target short.
  • Length penalty enabled from step zero. Slows early training; warm up instead.
  • Reward hacking via verbosity in the judge. For non-verifiable tasks scored by a generative reward model, the model learns to win by writing more. K3 applies a budget-based verbosity control to its judge as well: given a cold-start verbosity estimate l0 and multiplier sigma, a candidate longer than sigma * l0 automatically loses the binary comparison. If your reward model is an LLM, it needs its own length gate.
  • Knob and training disagree. Serving low at a cap tighter than the trained low budget produces truncation, not compression.
  • Effort labels are not portable. One vendor's high is another's max. Any cross-model comparison that does not state the effort setting is uninterpretable; note that published leaderboard comparisons frequently run different models at different effort settings.

References

  • L1 / LCPO, Controlling How Long A Reasoning Model Thinks With Reinforcement Learning: https://arxiv.org/abs/2503.04697
  • Kimi k1.5, Scaling Reinforcement Learning with LLMs (length penalty, long2short): https://arxiv.org/abs/2501.12599
  • Kimi K2.5, Visual Agentic Intelligence (Toggle, token-efficient RL): https://arxiv.org/abs/2602.02276
  • Kimi K3 Technical Report (reasoning-effort RL, nine experts, XTML thinking-effort option): https://github.com/MoonshotAI/Kimi-K3/blob/main/k3_tech_report.pdf
  • DeepSeek-V4, Towards Highly Efficient Million-Token Context Intelligence (effort specialists): https://arxiv.org/abs/2606.19348
  • Qwen3 Technical Report (thinking-mode fusion, /think and /no_think): https://arxiv.org/abs/2505.09388
  • Sebastian Raschka, Controlling Reasoning Effort in LLMs: https://magazine.sebastianraschka.com/p/controlling-reasoning-effort-in-llms
  • S1, Simple test-time scaling (budget forcing baseline L1 is compared against): https://arxiv.org/abs/2501.19393

Related: Inference-time scaling for reasoning · Multi-teacher on-policy distillation · Latent reasoning with outcome-reward RL · RLVR · GRPO · GRPO variants · Reward design · Reasoning distillation · On-policy distillation · Model merging · DPO · Rejection sampling and Best-of-N · Kimi K3 multi-node serving · Prompt caching · LLM inference efficiency · Agent loop economics · Post-training system map