LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 196 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/9
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningBayesian Inference from EvidenceStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/15
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageStatistical Learning and GeneralizationConformal Prediction and UncertaintyClustering and PCAProbabilistic Generative ModelsCore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingCausal Inference and CounterfactualsPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/25
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernancePrivacy-Preserving Machine LearningData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/17
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningTraining Run OperationsReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/31
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceAccelerator Architecture Field GuideCorrect GPU Profiling and BenchmarkingGPU Kernel Performance Engineering LabGPU Parallel Primitives LabGPU Compilers and Kernel LanguagesGEMM From Naive CUDA to Tensor CoresLow-Precision GPU ProgrammingGPU Runtime Execution LabAI-Generated Kernel EngineeringModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingGPU Failure OperationsDistributed Inference Data PlaneServing Benchmark EngineeringA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning Agent System Design
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnSystem Design CapstonesReasoning Agent System Design
🏗️HardSystem Design

Reasoning Agent System Design

Design a production reasoning agent that routes by difficulty, evaluates candidate work, requires evidence before release, and survives serving bottlenecks like key-value (KV) cache growth.

45 min read
Learning path
Step 175 of 196 in the full curriculum
Real-Time Voice AI AgentAI Lab Coding Interview: Python Systems

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

A release owner sees a canary at 10%: smoke tests passed, but one latency panel spiked after a config flag changed. The agent must choose rollback, hold, or continue the rollout. A plausible recommendation is cheap. A defensible one needs the rollout state, smoke-test result, latency evidence, and config diff before it spends more search.

That is the running incident. A human SRE would gather those observations, compare them with policy, and only then recommend hold, promote, or rollback. This design spends extra test-time compute on that checked work, then asks whether the extra budget earned a safer release.

A standard large language model (LLM) generates each continuation left to right. It can't rewrite tokens already emitted, though later tokens can state a correction. Extra checking still needs a controller that can call tools, request a revision, or generate competing attempts.

Reasoning models such as OpenAI's earlier o-series, including o1 [1]Reference 1o1 Preview Modelhttps://developers.openai.com/api/docs/models/o1-preview, and DeepSeek-R1 [2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 spend additional compute before returning an answer. That native internal reasoning is not the same as a product controller that samples candidates, calls tools, scores partial states, or searches a tree. They have different evidence and serving contracts.

We'll follow one canary through the controller. First, try one bounded path. If several complete plans are plausible, sample a few and rerank them. If a partial dependency decision needs backtracking, search a tree. Exact checks and learned verifiers decide which branches remain eligible. A difficulty router and stop policy keep that work within latency, cost, and KV-cache limits.

Fast answers aren't a release contract

Suppose the model says "hold" before it has seen the metrics result. What can the release gate prove? Single-pass decoding only samples the next token from everything so far. Without a controller or tool, it can emit a fluent hold/rollback recommendation that never touched the deploy API, smoke-test log, or latency panel. Hidden "slow thinking" isn't an enforceable control. The shippable controls are external candidate state, tool evidence, evaluator behavior, and release gates.

Treat this request as a budgeted search and verification problem, not one left-to-right decoding loop. A controller can explore candidate actions, score partial solutions, consult external evidence, and spend extra compute only when evaluation justifies it.

The extra work is called test-time compute: the floating-point operations (FLOPs) and tokens spent during inference, after training is done. In a FLOPs-matched study, Snell et al. show that a smaller model plus a suitable inference-time strategy can beat a 14x larger model on prompts where the smaller model already has a non-trivial chance of succeeding [3]Reference 3Scaling LLM Test-Time Compute Optimally Can Be More Effective Than Scaling Model Parameters.https://arxiv.org/abs/2408.03314. The same paper finds that the best strategy depends on prompt difficulty, so the gain isn't a free substitute for a stronger base model. The knob we can operate is a measured inference budget, not model size alone.

What is the product difference between training compute and test-time compute?

Answer

Training compute is spent before deployment to build the model. Test-time compute is spent per request to search, verify, rerank, or allocate more internal reasoning budget. Production systems can vary test-time compute by task difficulty instead of making every request pay for the same model size.

Three budget policies on the same canary workload: fixed 1x for every request, escalate after a weak first pass, and adaptive routing that spends 12x only on the parser graph.
Same three requests, three policies. Adaptive routing keeps the rollback FAQ cheap and spends the deep budget on the parser graph.

Three policies put that trade-off on one canary workload. A fixed budget spends the same tokens on every request. An escalation rule adds compute after a weak first attempt. An adaptive budget routes by difficulty before expensive search begins. We will build the adaptive policy, then make its evidence, stop, and serving contracts explicit.

The simplest form of extra compute: one deliberate path

What if the supplied tool observations already settle the canary decision? Start with the cheapest control: give one candidate a bounded reasoning budget. On supported reasoning APIs, reasoning.effort is that budget control. A structured response format is only an outward interface for checked milestones and a final answer. XML doesn't make the model think longer. Classic Chain of Thought prompts asked a model to "think step by step" [4]Reference 4Chain-of-Thought Prompting Elicits Reasoning in Large Language Models.https://arxiv.org/abs/2201.11903, but a production controller should separate hidden reasoning budget from evidence the application can validate.

OpenAI's current reasoning guide uses GPT-5.6 in its examples and frames reasoning.effort as a tuning knob alongside a clear task, constraints, and output contract [5]Reference 5Reasoning modelshttps://developers.openai.com/api/docs/guides/reasoning. It advises against prescribing hidden intermediate steps or asking for a scratchpad. Request the outward artifacts the application needs: tool evidence, concise checked milestones, and a final answer. Hidden reasoning tokens aren't proof or an audit log.

Supported effort values are model-dependent. GPT-5.5, for example, documents none, low, medium (default), high, and xhigh [6]Reference 6GPT-5.5 Modelhttps://developers.openai.com/api/docs/models/gpt-5.5. Lower effort favors latency and fewer reasoning tokens; higher effort permits more internal work before answering. Raise effort only when evals show a quality gain that justifies extra latency and cost, and keep the lowest useful setting for fast, deterministic tasks. Treat it as the single-path version of the difficulty router introduced later.

Use a lightweight parser for the interface you want the model to satisfy. It turns a compact XML response into visible checkpoints plus a final answer:

the-simplest-form-of-thinking-longer-one.py
1from dataclasses import asdict, dataclass 2import json 3import xml.etree.ElementTree as ET 4 5@dataclass 6class ReasoningStep: 7 kind: str 8 content: str 9 10@dataclass 11class ReasoningTrace: 12 steps: list[ReasoningStep] 13 final_answer: str 14 15class SinglePathReasoner: 16 RESPONSE_TEMPLATE = """ 17 Answer using supplied tool observations only. 18 19 Return XML with this structure: 20 <response> 21 <checkpoint>major milestone only</checkpoint> 22 <checkpoint>major milestone only</checkpoint> 23 <verification_summary>brief check against supplied evidence</verification_summary> 24 <final_answer>final answer</final_answer> 25 </response> 26 27 Keep checkpoints concise. Do not dump a full scratchpad. 28 """ 29 30 def parse(self, content: str) -> ReasoningTrace: 31 root = ET.fromstring(content) 32 checkpoints = [node.text.strip() for node in root.findall("checkpoint") if node.text] 33 steps = [ReasoningStep("checkpoint", cp) for cp in checkpoints if cp] 34 verification = self._extract_text(root, "verification_summary") 35 if verification: 36 steps.append(ReasoningStep("verification", verification)) 37 return ReasoningTrace( 38 steps=steps, 39 final_answer=self._extract_text(root, "final_answer"), 40 ) 41 42 def _extract_text(self, root: ET.Element, tag: str) -> str: 43 text = root.findtext(tag, default="") 44 return text.strip() 45 46model_response = """ 47<response> 48 <checkpoint>Deploy API reports canary still at 10%.</checkpoint> 49 <checkpoint>Smoke-test tool reports the release passed.</checkpoint> 50 <verification_summary>Metrics tool shows latency above watch threshold but below rollback threshold.</verification_summary> 51 <final_answer>Hold the canary at 10%, keep rollback armed, and inspect the config flag before promotion.</final_answer> 52</response> 53""" 54 55trace = SinglePathReasoner().parse(model_response) 56print(json.dumps({ 57 "steps": [asdict(step) for step in trace.steps], 58 "final_answer": trace.final_answer, 59}, indent=2))
Output
1{ 2 "steps": [ 3 { 4 "kind": "checkpoint", 5 "content": "Deploy API reports canary still at 10%." 6 }, 7 { 8 "kind": "checkpoint", 9 "content": "Smoke-test tool reports the release passed." 10 }, 11 { 12 "kind": "verification", 13 "content": "Metrics tool shows latency above watch threshold but below rollback threshold." 14 } 15 ], 16 "final_answer": "Hold the canary at 10%, keep rollback armed, and inspect the config flag before promotion." 17}

The split matters. RESPONSE_TEMPLATE constrains output to major evidence-backed milestones, but it doesn't make claims true. Downstream code still needs to require tool results for external facts. Hidden token-by-token deliberation stays inside the model runtime; the application receives a compact interface it can validate.

For the canary, one bounded path should expose only the observations needed to justify its action:

  1. The deploy tool reports that the canary is still at 10%.
  2. The smoke-test tool reports that the release passed.
  3. The metrics tool shows elevated latency below the rollback threshold.
  4. The final answer holds the canary, keeps rollback armed, and inspects the changed config flag before promotion.

That is enough when tool evidence or an exact check settles the result. If multiple plans remain plausible, the next move is a small set of candidates, not a tree by default.

releasing-only-evidence-backed-claims.py
1import json 2 3def release_answer(tool_results: dict[str, str | None]) -> dict[str, object]: 4 missing = [key for key, value in tool_results.items() if value is None] 5 if missing: 6 return {"release": False, "missing_evidence": missing, "next_step": "request_tool_data"} 7 return { 8 "release": True, 9 "answer": ( 10 f"Canary action: {tool_results['canary_policy']}. " 11 f"Latency status: {tool_results['latency_status']}." 12 ), 13 } 14 15attempts = [ 16 {"canary_policy": "hold at 10%", "latency_status": None}, 17 {"canary_policy": "hold at 10%", "latency_status": "below rollback threshold"}, 18] 19 20print(json.dumps([release_answer(attempt) for attempt in attempts], indent=2))
Output
1[ 2 { 3 "release": false, 4 "missing_evidence": [ 5 "latency_status" 6 ], 7 "next_step": "request_tool_data" 8 }, 9 { 10 "release": true, 11 "answer": "Canary action: hold at 10%. Latency status: below rollback threshold." 12 } 13]

A checkpoint is a parseable milestone. The release gate still needs the matching tool observation:

Diagram showing Candidate claim, Required tools present?, Block and request evidence, and Exact constraint pass?.
Candidate claim, Required tools present?, Block and request evidence, and Exact constraint pass?.

Why should a reasoning API expose checkpoints instead of raw chain-of-thought?

Answer

Checkpoints give users and downstream systems useful milestones without exposing long internal scratchpads. They're shorter, safer to audit, easier to parse, and less likely to leak policy reasoning or hidden verifier details.

Asking several agents: Best-of-N sampling

What changes when both "hold" and "rollback" look plausible after the first pass? Generate a small set of candidate answers and rank them before selecting a response. In an incident-analysis workflow, several independent candidates enter a policy check or validated reviewer.

This is Best-of-N sampling. Run the single-path generator N times with a diversity-producing configuration, rank candidates with the most reliable evaluator available, and release an eligible winner. Temperature is one knob: low temperature tends to collapse diversity, while a higher value can produce different plans. Neither setting guarantees diversity or correctness.

Use a deterministic version of the selector first. A live canary would generate those candidates from separate model calls, but the selection rule stays the same:

asking-several-agents-best-of-n-sampling.py
1from dataclasses import asdict, dataclass 2import json 3import math 4 5@dataclass 6class CandidateTrace: 7 candidate_id: str 8 answer: str 9 verifier_score: float 10 11class BestOfNSampler: 12 @staticmethod 13 def probability_at_least_one_success(base_success_rate: float, n: int) -> float: 14 return 1 - math.pow(1 - base_success_rate, n) 15 16 def choose(self, traces: list[CandidateTrace]) -> CandidateTrace: 17 return max(traces, key=lambda trace: trace.verifier_score) 18 19traces = [ 20 CandidateTrace("A", "Rollback immediately; latency panel is unknown.", 0.61), 21 CandidateTrace("B", "Hold canary; tests passed and latency is below rollback threshold.", 0.93), 22 CandidateTrace("C", "Promote to 100% because smoke tests passed.", 0.28), 23 CandidateTrace("D", "Disable all traffic before checking metrics.", 0.44), 24 CandidateTrace("E", "Ignore the spike because rollout is partial.", 0.19), 25] 26 27sampler = BestOfNSampler() 28winner = sampler.choose(traces) 29 30print(json.dumps({ 31 "n": len(traces), 32 "base_success_rate": 0.30, 33 "at_least_one_success": round( 34 sampler.probability_at_least_one_success(0.30, len(traces)), 35 3, 36 ), 37 "selected": asdict(winner), 38}, indent=2))
Output
1{ 2 "n": 5, 3 "base_success_rate": 0.3, 4 "at_least_one_success": 0.832, 5 "selected": { 6 "candidate_id": "B", 7 "answer": "Hold canary; tests passed and latency is below rollback threshold.", 8 "verifier_score": 0.93 9 } 10}

Why this helps: a worked example

Suppose the base model has a 30% chance of producing a correct mitigation plan for a complex canary incident. Before looking at the selector, predict what five independent attempts buy you. With one sample, success is 30%. With five, the probability that at least one is correct is:

P(at least one success)=1−(1−0.30)5=1−0.168=0.83P(\text{at least one success}) = 1 - (1 - 0.30)^5 = 1 - 0.168 = 0.83P(at least one success)=1−(1−0.30)5=1−0.168=0.83

That 83% describes the event that a correct candidate exists under the independence assumption. It's not an 83% success rate for the returned answer: selection succeeds only when a checker or verifier recognizes the correct candidate. Extra sampling is wasted if candidates are correlated or the verifier can't identify the useful one.

A reward model is only a proxy for correctness, so pushing N too high can backfire. Gao et al. show that true (gold) quality can drop as optimization against a learned reward model keeps increasing its proxy score, a Goodhart-style effect they call reward-model overoptimization [7]Reference 7Scaling Laws for Reward Model Overoptimizationhttps://arxiv.org/abs/2210.10760. Cap N, evaluate on held-out outcomes, and don't trust the verifier score alone.

When an exact checker exists, it outranks a persuasive learned score. The next selector chooses a tested dependency path rather than the answer with the highest style score:

prefer-exact-checks-over-proxy-scores.py
1import json 2 3candidates = [ 4 {"id": "A", "path": ["api", "legacy_adapter", "database"], "proxy_score": 0.96}, 5 {"id": "B", "path": ["api", "feature_flag", "database"], "proxy_score": 0.82}, 6] 7blocked_edges = {("api", "legacy_adapter")} 8 9def passes_constraints(path: list[str]) -> bool: 10 edges = set(zip(path, path[1:])) 11 return not bool(edges & blocked_edges) 12 13checked = [ 14 {**candidate, "exact_check": passes_constraints(candidate["path"])} 15 for candidate in candidates 16] 17eligible = [candidate for candidate in checked if candidate["exact_check"]] 18winner = max(eligible, key=lambda candidate: candidate["proxy_score"]) 19 20print(json.dumps({"checked": checked, "selected": winner["id"]}, indent=2))
Output
1{ 2 "checked": [ 3 { 4 "id": "A", 5 "path": [ 6 "api", 7 "legacy_adapter", 8 "database" 9 ], 10 "proxy_score": 0.96, 11 "exact_check": false 12 }, 13 { 14 "id": "B", 15 "path": [ 16 "api", 17 "feature_flag", 18 "database" 19 ], 20 "proxy_score": 0.82, 21 "exact_check": true 22 } 23 ], 24 "selected": "B" 25}

Self-consistency: Best-of-N without a reward model

When the answer is a comparable string, such as a number, label, or parse, you can sometimes skip a learned reward model. Self-consistency samples several traces and returns the most frequent answer [8]Reference 8Self-Consistency Improves Chain of Thought Reasoning in Language Models.https://arxiv.org/abs/2203.11171. It can improve selected reasoning benchmarks when correct answers concentrate more than incorrect ones, but majority vote isn't verification: correlated wrong answers still win. Prefer an exact checker whenever available; use voting only when endpoints are comparable and evaluation supports it.

When does Best-of-N help, and when is it wasted?

Answer

It helps when the base model has a meaningful chance of producing at least one correct trace and the verifier can identify it. It's wasted when samples are near-identical, the base model has near-zero task competence, or the reward model can't distinguish good traces from bad ones.

Where beam search fits

Beam search is the classic decoding baseline: keep the top-kkk most likely partial continuations at each step. It's easy to batch, but on tasks requiring distinct hypotheses its high-probability branches can become near-duplicates rather than useful alternatives. Evaluate it as a baseline or pruning mechanism against sampling and search on the task distribution you serve.

Why can beam search underperform on reasoning tasks?

Answer

Beam search keeps high-probability continuations, which can become small variations of the same path. For tasks needing diverse hypotheses and backtracking, compare it with sampling or broader search and use it as a pruning mechanism only when evaluation supports that choice.

When one path isn't enough: exploring a tree

The canary is held. That is the right release action once the tools agree, but it doesn't explain why latency spiked: the changed flag enabled parser-v2. A single path can recommend hold. It can't pin a version, discover a runtime conflict, undo that pin, and try another branch.

Diagnosis is now a search problem. The resolver must choose package versions while respecting API compatibility, Python version floors, and security advisories. If it pins parser-v2 and later learns that parser-v2 calls an API the deployed runtime removed, it needs to backtrack.

Tree of Thoughts (ToT), proposed by Yao et al. [9]Reference 9Tree of Thoughts: Deliberate Problem Solving with Large Language Models.https://arxiv.org/abs/2305.10601, treats reasoning as tree search. At each step, the model generates possible next actions, scores them, and explores promising branches while pruning weak ones. For dependency resolution, each branch is a candidate version assignment; each evaluator check asks whether that partial assignment still satisfies known constraints.

Parser-pin search tree: nightly is pruned at depth 1, parser-v2 expands then loses the removed-API child, and parser-v1 plus a sanitizer patch survive as finalists.
Nightly dies on the runtime floor. Parser-v2 keeps a shim and drops the removed-API call. Parser-v1 plus a sanitizer patch is the other valid plan.

The canary's config flag turns into that tree. From the initial state, three version choices are possible. Predict which branch should die before reading the scores: nightly violates the runtime constraint. Parser-v2 looks usable, so it expands into two sub-choices. Calling the removed API breaks compatibility and gets pruned. The compatibility shim and the parser-v1 sanitizer patch both reach valid solutions.

To implement this, maintain a search beam that keeps only candidate branches active. At each depth, generate next steps, score them with a task-specific evaluator, and prune paths below its threshold. The evaluator may be an exact constraint checker, a learned reward model, or a combination:

when-one-path-isnt-enough-exploring-a-tree.py
1from dataclasses import dataclass 2import json 3 4EXPANSIONS = { 5 "start": ["Pin parser v2", "Pin parser nightly", "Keep parser v1"], 6 "Pin parser v2": ["A.1 add compatibility shim", "A.2 call removed API"], 7 "Keep parser v1": ["C.1 patch sanitizer", "C.2 defer security fix"], 8} 9 10SCORES = { 11 "Pin parser v2": 0.74, 12 "Pin parser nightly": 0.12, 13 "Keep parser v1": 0.81, 14 "A.1 add compatibility shim": 0.70, 15 "A.2 call removed API": 0.18, 16 "C.1 patch sanitizer": 0.96, 17 "C.2 defer security fix": 0.39, 18} 19 20@dataclass 21class ThoughtNode: 22 content: str 23 depth: int 24 score: float 25 parent: "ThoughtNode | None" = None 26 27 def trace(self) -> str: 28 if self.parent is None: 29 return self.content 30 return f"{self.parent.trace()}\n{self.content}" 31 32class TreeOfThoughts: 33 def __init__(self, beam_width: int = 2, min_score: float = 0.35): 34 self.beam_width = beam_width 35 self.min_score = min_score 36 37 def search(self, max_depth: int = 2) -> dict[str, object]: 38 root = ThoughtNode("start", depth=0, score=1.0) 39 beam = [root] 40 rounds = [] 41 42 for depth in range(max_depth): 43 candidates = [] 44 for node in beam: 45 for thought in EXPANSIONS.get(node.content, []): 46 candidates.append(ThoughtNode(thought, depth + 1, SCORES[thought], node)) 47 48 survivors = [node for node in candidates if node.score >= self.min_score] 49 survivors.sort(key=lambda node: node.score, reverse=True) 50 beam = survivors[:self.beam_width] 51 rounds.append({ 52 "depth": depth + 1, 53 "kept": [node.content for node in beam], 54 "pruned": [ 55 node.content for node in candidates 56 if node.score < self.min_score 57 ], 58 }) 59 60 best = max(beam, key=lambda node: node.score) 61 return {"winner": best.trace().split("\n"), "rounds": rounds} 62 63print(json.dumps(TreeOfThoughts().search(), indent=2))
Output
1{ 2 "winner": [ 3 "start", 4 "Keep parser v1", 5 "C.1 patch sanitizer" 6 ], 7 "rounds": [ 8 { 9 "depth": 1, 10 "kept": [ 11 "Keep parser v1", 12 "Pin parser v2" 13 ], 14 "pruned": [ 15 "Pin parser nightly" 16 ] 17 }, 18 { 19 "depth": 2, 20 "kept": [ 21 "C.1 patch sanitizer", 22 "A.1 add compatibility shim" 23 ], 24 "pruned": [ 25 "A.2 call removed API" 26 ] 27 } 28 ] 29}

This is a beam-search realization of Tree of Thoughts: simple to batch, simple to reason about, and often a sensible first version. Start with the problem, expand each active node into branching_factor children, evaluate every child, and keep only the beam_width highest-ranked candidates for the next round.

What makes Tree of Thoughts different from Best-of-N?

Answer

Best-of-N samples full traces independently and reranks them at the end. Tree of Thoughts evaluates partial states, can prune low-ranked branches early, and can backtrack before spending tokens on a candidate that fails its evaluator or constraints.

How does Tree of Thoughts handle non-deterministic outputs?

Answer

Use a diversity-producing generation policy at each node, then apply the most reliable evaluator available: exact constraints first, learned scoring where exact checks are unavailable. If every generation call returns the same continuation, tree search loses its main advantage.

When revisiting branches beats a fixed beam

Tree of Thoughts is a general framework. If you need adaptive revisits instead of level-by-level pruning, you can swap the beam for Monte Carlo tree search (MCTS). In LLM settings, a common variant is PUCT (Predictor + Upper Confidence bounds applied to Trees), the AlphaZero-style selection rule that combines a value estimate with the model's next-step prior [10]Reference 10Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm.https://arxiv.org/abs/1712.01815:

PUCT(s,a)=Q(s,a)+cpuct⋅P(s,a)⋅N(s)1+N(s,a)\text{PUCT}(s, a) = Q(s, a) + c_{\text{puct}} \cdot P(s, a) \cdot \frac{\sqrt{N(s)}}{1 + N(s, a)}PUCT(s,a)=Q(s,a)+cpuct​⋅P(s,a)⋅1+N(s,a)N(s)​​

Where:

  • Q(s,a)Q(s, a)Q(s,a) is the estimated downstream value for taking action aaa in state sss (from rollouts, a value model, or another evaluator)
  • P(s,a)P(s, a)P(s,a) is the policy prior for the next thought
  • N(s)N(s)N(s) is the total number of visits to the parent node
  • N(s,a)N(s, a)N(s,a) is the number of visits to the child node
  • cpuctc_{\text{puct}}cpuct​ is the exploration constant that balances exploration vs exploitation

The first term exploits high-value branches. The second favors a strong model prior or a child that hasn't been explored much. Beam search is usually easier to run on GPUs because every frontier expansion can be batched. MCTS becomes attractive when evaluator calls are expensive and revisiting a promising node is cheaper than expanding every branch evenly.

When would you choose MCTS over level-by-level beam expansion?

Answer

Choose MCTS when revisiting promising branches beats expanding every frontier node evenly, especially when verifier calls are expensive or search depth varies by branch. Beam expansion is simpler to batch on GPUs and is often the first production version.

Who judges the plans? Verifiers and reward models

The search only helps if the controller can identify an eligible result. Use exact checkers for objective constraints wherever possible. When exact checking is unavailable, a learned verifier can score candidate traces, but its job must remain explicit.

An Outcome Reward Model (ORM) scores only the final answer. It resembles an audit that checks whether the dependency plan is valid without inspecting intermediate version choices. An ORM is cheaper to train because it needs one label per chain, but the signal is sparse: if the answer is wrong, it doesn't tell you where reasoning broke.

A Process Reward Model (PRM) scores individual reasoning steps, not only the final answer [11]Reference 11Let's Verify Step by Step.https://arxiv.org/abs/2305.20050. When step quality is labelable and the PRM is validated on the served domain, it can prune low-scored branches before complete traces are generated. It remains a learned proxy, not proof that a step is correct. Exact compatibility checks still outrank it for the parser pin.

Why can a validated PRM be more useful than an ORM for search?

Answer

An ORM scores only the final answer. A PRM can score intermediate steps, so a search controller can prune low-scored branches earlier and avoid spending more tokens on them. Exact checkers still outrank either learned score when available.

The PRM estimates risk at each dependency step. When a candidate calls a removed API, a validated PRM may give that step a low score. If an exact compatibility checker exists, it makes the authoritative rejection. Otherwise, the score is only a pruning signal whose false positives and negatives need measurement.

How a PRM works

Lightman et al. train a step classifier over human labels: Positive, Negative, or Neutral. They released PRM800K, about 800,000 step-level labels across 75,000 solutions, because step supervision is the bottleneck for building these verifiers well [11]Reference 11Let's Verify Step by Step.https://arxiv.org/abs/2305.20050. A search controller can reduce that three-way distribution to a scalar such as P(positive)P(\text{positive})P(positive), then prune below a held-out threshold. A one-dimensional sigmoid head is a common production simplification, not the original 3-way labeler:

P(positive∣context,s1...t)=σ(W⋅ht)P(\text{positive} \mid \text{context}, s_{1...t}) = \sigma(W \cdot h_t)P(positive∣context,s1...t​)=σ(W⋅ht​)

hth_tht​ is the hidden representation of the current step, WWW is a learned linear layer, and σ\sigmaσ is a sigmoid that maps the result into (0,1)(0, 1)(0,1). Treating that number as a calibrated probability still requires separate calibration and held-out validation.

There are three practical sources for training data. Experts can label individual steps as Positive, Negative, or Neutral. Monte Carlo estimation can roll out NNN completions from a step and use roughly M/NM/NM/N as its score when MMM completions reach the correct answer. A stronger verifier or frontier model can pre-label steps for scale, but those labels need an audit before they drive pruning.

How do you train the Process Reward Model effectively?

Answer

Use dense step-level supervision when you can: human labels for partial steps, Monte Carlo rollouts that estimate whether a step leads to correct completions, and audited teacher-model labels for scale. An ORM can bootstrap early experiments, but a real PRM needs examples of correct, incorrect, and neutral intermediate reasoning steps.

Use this scoring interface to make the failure visible. A shipped PRM is a model with a reward head; this version uses deterministic rules so you can see how a weak parser step pulls down the whole trace:

how-a-prm-works.py
1from dataclasses import asdict, dataclass 2import json 3 4@dataclass 5class StepScore: 6 step: str 7 score: float 8 9class ProcessRewardModel: 10 def score_step(self, step: str) -> float: 11 lowered = step.lower() 12 if "removed api" in lowered or "runtime conflict" in lowered: 13 return 0.15 14 if "checked" in lowered or "compatible" in lowered: 15 return 0.92 16 return 0.65 17 18 def score_full_trace(self, steps: list[str]) -> dict[str, object]: 19 scores = [StepScore(step, self.score_step(step)) for step in steps] 20 trace_score = min(score.score for score in scores) if scores else 0.0 21 return { 22 "step_scores": [asdict(score) for score in scores], 23 "trace_score": trace_score, 24 "decision": "prune" if trace_score < 0.35 else "keep", 25 } 26 27trace = [ 28 "Checked parser version against runtime compatibility.", 29 "Call removed API from the parser adapter.", 30 "Recommend hold until compatibility tests pass.", 31] 32 33print(json.dumps(ProcessRewardModel().score_full_trace(trace), indent=2))
Output
1{ 2 "step_scores": [ 3 { 4 "step": "Checked parser version against runtime compatibility.", 5 "score": 0.92 6 }, 7 { 8 "step": "Call removed API from the parser adapter.", 9 "score": 0.15 10 }, 11 { 12 "step": "Recommend hold until compatibility tests pass.", 13 "score": 0.65 14 } 15 ], 16 "trace_score": 0.15, 17 "decision": "prune" 18}

The score_full_trace method uses the minimum score as a conservative pruning heuristic. Set live thresholds against held-out canary outcomes, and prefer exact checks for constraints such as runtime compatibility or rollback thresholds.

ORM vs PRM at a glance

FeatureOutcome Reward Model (ORM)Process Reward Model (PRM)
ScoringOnly scores the final answerScores every intermediate step
Feedback signalSparse (1 signal per chain)Dense (1 signal per step)
Search utilityOnly helps select final outputGuides search; enables early pruning
Training costLower (less labeling effort)Higher (requires step-level labels)
Token timeline where an outcome reward model spends the full trace before scoring 0.15, while a process reward model scores each parser step and prunes at the removed-API call.
ORM pays for every step, then scores 0.15. PRM scores as it goes, prunes at the removed API, and never generates the later tokens.

Lightman et al. (2023) [11]Reference 11Let's Verify Step by Step.https://arxiv.org/abs/2305.20050 found that process supervision outperformed outcome supervision in their challenging math setting. Carrying that result into release-policy, planning, or code tasks requires domain-specific data and validation.

A correct answer can hide a broken evaluator

An evaluator may accept invalid reasoning because the final answer looks right. Sun et al. isolate this failure with Valid-Answer-Invalid-Reasoning (VAIR) math examples: GPT-5.4 scored 47.9% when asked to grade solutions that contained simple reasoning flaws but valid answers, despite near-perfect production on the same problems.[12]Reference 12An Enigma of Artificial Reason: Investigating the Production-Evaluation Gap in Large Reasoning Modelshttps://arxiv.org/abs/2606.01462 Their analysis finds evidence of answer confirmation bias, where the model works backward from the correct endpoint and rationalizes flawed steps.

That result is from one controlled math setting, so don't turn 47.9% into expected production accuracy. Use it as an evaluation design warning:

TestFailure it exposes
Valid answer, invalid intermediate stepEvaluator trusts endpoint and misses broken derivation
Invalid answer, valid early stepsEvaluator rejects useful partial work because endpoint is wrong
Answer hidden until step verdicts are lockedFinal-answer leakage into process judgment
Same trace with answer perturbedVerdict flips because answer changed, not reasoning

For release decisions, exact tool evidence remains authoritative. When learned process scoring is necessary, score steps before revealing the final candidate where the interface permits, calibrate on held-out adversarial cases, and track false acceptance separately from ordinary solver accuracy. Solver pass rate and evaluator error rate are different production metrics.

Why isn't a correct final answer enough to validate the reasoning trace or its evaluator?

Answer

The correct endpoint can coexist with invalid steps, accidental cancellation, or unsupported evidence. Test the evaluator on valid-answer-invalid-reasoning cases and compare step verdicts before the final answer can influence the judgment.

Training reasoning models with RL

External search controllers aren't the only route. DeepSeek-R1 describes a complementary path where reinforcement learning improves the base policy's ability to produce structured reasoning traces [2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948.

Group Relative Policy Optimization (GRPO) is one algorithm in that work. Compared with PPO (Proximal Policy Optimization), GRPO removes the need for a separate critic model [2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948. For one problem, the policy samples a group of outputs, scores each with task rewards, exact verifiers, or validated reward models, and compares each reward with the group mean. The update then favors outputs with higher relative reward.

That removes a separate critic network from this training setup. It can make the base model more effective at test time, but it doesn't remove production routing, budget limits, or verifier design. Training-time improvement and request-time control still solve different problems.

What does GRPO improve, and what does it not replace?

Answer

GRPO can train the base policy to produce better reasoning traces with lower RL overhead than critic-based PPO. It doesn't replace production routing, token budgets, verifier quality, safe streaming, or serving capacity planning.

Putting it together: a production reasoning agent

We now have the pieces: one bounded path, candidate sampling, partial-state search, judges, and stop rules. A production system connects them in that order: classify the problem, choose a strategy, search, verify, and stream only safe progress.

What the system must handle

Before drawing boxes, make responsibilities concrete. The system must accept multi-step work such as canary triage, dependency resolution, and multi-file debugging. It must keep candidate actions, tool observations, and evaluator results outside the model's hidden scratchpad so search and audit have a shared state.

It also needs adaptive compute. A request asking for the rollback threshold for checkout-api shouldn't trigger a 20-second tree search, while a compatibility graph may justify one. Streaming should expose status or safe progress summaries, never an unverified conclusion as a completed check. Finally, token, time, branch, and cost budgets can vary by product tier, but none may weaken evidence requirements.

On the non-functional side, declare measurable objectives: concurrency for a target workload, quality lift over single pass on representative verifiable tasks, p95 latency, and per-request cost by route. A 3x or 10x budget is an experiment parameter, not a production guarantee.

What are the five core responsibilities of a production reasoning agent?

Answer

It must classify difficulty, choose a compute strategy, run search or sampling, verify candidates, and stream safe progress plus the final answer while enforcing cost, latency, and token budgets.

Architecture overview

The full pipeline has one gateway, one difficulty router, and three lanes: a fast path, a medium Best-of-N path, and a deep Tree-of-Thoughts path. Branching lanes should use the best available evaluator and reuse key-value (KV) cache prefixes only where the serving runtime safely supports compatible sharing.

Gateway and difficulty router send a canary request into a 1x single path, a Best-of-3 lane, or a capped tree, then rejoin at one verifier before the release gate.
Route the canary by difficulty first. Fast, medium, and deep lanes all rejoin at one verifier before anything is released.

At request time, one shared prefix can fan into live branches. A weak branch dies early, and only a grounded answer reaches the release gate.

Canary request shares one prefix cache, continues two live branches, prunes a third early, then verifies survivors before releasing a hold decision.
Share the canary prompt and early tool context once. Pay extra KV only for suffixes that still look valid, then release one grounded hold.

The difficulty router

Not every problem needs extended thinking. A simple factual query wastes compute if treated as a reasoning task. The router evaluates input complexity and assigns a strategy plus token budget. Predict the route first: a threshold lookup should stay on the fast path, a canary diagnosis may need candidates, and a compatibility graph may need backtracking.

This small lab uses keyword matches as a transparent demo. A production router is a cheap classifier trained on features such as length, tool need, historical difficulty, and verifier fail rate. Judge it on held-out under-routing and over-routing cost, not on a hardcoded substring list.

The minimal implementation keeps those route decisions visible:

the-difficulty-router.py
1from dataclasses import asdict, dataclass 2import json 3 4@dataclass 5class Route: 6 difficulty: str 7 strategy: str 8 max_tokens: int 9 budget_multiplier: int 10 11class DifficultyRouter: 12 CONFIGS = { 13 "trivial": Route("trivial", "single_pass", 500, 1), 14 "easy": Route("easy", "single_path", 2_000, 2), 15 "medium": Route("medium", "best_of_3", 4_000, 5), 16 "hard": Route("hard", "tree_search", 8_000, 10), 17 "extreme": Route("extreme", "tree_search", 16_000, 20), 18 } 19 20 def classify(self, problem: str) -> Route: 21 text = problem.lower() 22 if "satisfies" in text or "constraints after" in text: 23 return self.CONFIGS["hard"] 24 if "canary" in text or "debug" in text: 25 return self.CONFIGS["medium"] 26 if "rollback threshold" in text or "policy" in text: 27 return self.CONFIGS["easy"] 28 return self.CONFIGS["trivial"] 29 30router = DifficultyRouter() 31problems = [ 32 "What is the rollback threshold for checkout-api?", 33 "Debug this canary: smoke tests passed, but p95 latency spiked after the parser_v2 flag.", 34 "Find a parser pin that satisfies runtime, API, and security constraints after the flag change.", 35] 36 37print(json.dumps([asdict(router.classify(problem)) for problem in problems], indent=2))
Output
1[ 2 { 3 "difficulty": "easy", 4 "strategy": "single_path", 5 "max_tokens": 2000, 6 "budget_multiplier": 2 7 }, 8 { 9 "difficulty": "medium", 10 "strategy": "best_of_3", 11 "max_tokens": 4000, 12 "budget_multiplier": 5 13 }, 14 { 15 "difficulty": "hard", 16 "strategy": "tree_search", 17 "max_tokens": 8000, 18 "budget_multiplier": 10 19 } 20]

The router should be cheap relative to solving work. Its job is to avoid expensive search on requests that don't benefit while escalating tasks whose risk and verifiability justify more work. Misclassification isn't harmless: under-routing can release an incorrect answer, while over-routing can increase cost, latency, and exposure to verifier overoptimization.

Why should the router be cheap and conservative?

Answer

The router runs before every expensive reasoning decision, so it must not dominate latency. Evaluate both under-routing quality failures and over-routing cost or proxy-score failures; high-stakes cases may require tools, exact checks, or human review regardless of router confidence.

How would you optimize latency for the easy path?

Answer

Use a cheap router, direct instructions, low reasoning effort, and a small output schema. Bypass learned scoring and branch management when exact evidence already answers the request. Decode optimizations may help after profiling, but avoiding unnecessary reasoning stages is usually the first latency lever to measure.

Compute-optimal scheduling

Snell et al. [3]Reference 3Scaling LLM Test-Time Compute Optimally Can Be More Effective Than Scaling Model Parameters.https://arxiv.org/abs/2408.03314 show that no single test-time strategy dominates every prompt. The best move depends on problem difficulty and on whether the base model already has a plausible path to the correct answer. Ask what the first score can change: a strong exact result should stop cheaply, a weak but verifiable result can justify more candidates, and an unverifiable high-impact claim needs a tool or human. A production scheduler turns those signals into escalation:

compute-optimal-scheduling.py
1import json 2 3class ComputeOptimalScheduler: 4 def choose_strategy( 5 self, evaluation_score: float, verifiable: bool, high_impact: bool = False 6 ) -> dict[str, object]: 7 if high_impact and not verifiable: 8 return {"strategy": "tool_or_human_review", "reason": "high-impact claim lacks verifier"} 9 if not verifiable: 10 return {"strategy": "single_pass", "reason": "creative output; no objective ranking"} 11 if evaluation_score >= 0.90: 12 return {"strategy": "single_path", "reason": "first trace passed verifier"} 13 if evaluation_score >= 0.60: 14 return {"strategy": "best_of_3", "reason": "plausible trace needs reranking"} 15 return {"strategy": "tree_search", "reason": "weak trace needs backtracking"} 16 17requests = [ 18 {"task": "Rollback-threshold FAQ", "evaluation_score": 0.94, "verifiable": True}, 19 {"task": "Ambiguous canary hold", "evaluation_score": 0.72, "verifiable": True}, 20 {"task": "Parser compatibility graph", "evaluation_score": 0.41, "verifiable": True}, 21 {"task": "Incident-postmortem titles", "evaluation_score": 0.52, "verifiable": False}, 22 {"task": "Approve production write without policy record", "evaluation_score": 0.82, "verifiable": False, "high_impact": True}, 23] 24 25scheduler = ComputeOptimalScheduler() 26for request in requests: 27 request.update(scheduler.choose_strategy(request["evaluation_score"], request["verifiable"], request.get("high_impact", False))) 28 29print(json.dumps(requests, indent=2))
Output
1[ 2 { 3 "task": "Rollback-threshold FAQ", 4 "evaluation_score": 0.94, 5 "verifiable": true, 6 "strategy": "single_path", 7 "reason": "first trace passed verifier" 8 }, 9 { 10 "task": "Ambiguous canary hold", 11 "evaluation_score": 0.72, 12 "verifiable": true, 13 "strategy": "best_of_3", 14 "reason": "plausible trace needs reranking" 15 }, 16 { 17 "task": "Parser compatibility graph", 18 "evaluation_score": 0.41, 19 "verifiable": true, 20 "strategy": "tree_search", 21 "reason": "weak trace needs backtracking" 22 }, 23 { 24 "task": "Incident-postmortem titles", 25 "evaluation_score": 0.52, 26 "verifiable": false, 27 "strategy": "single_pass", 28 "reason": "creative output; no objective ranking" 29 }, 30 { 31 "task": "Approve production write without policy record", 32 "evaluation_score": 0.82, 33 "verifiable": false, 34 "high_impact": true, 35 "strategy": "tool_or_human_review", 36 "reason": "high-impact claim lacks verifier" 37 } 38]

This creates an adaptive system that spends small budgets on easy, checkable problems and escalates only when expected quality lift is worth extra latency and KV-cache pressure. "Unverifiable" isn't permission to make a high-impact decision.

Escalation also needs an exit. A branch may be looping, capped, or producing no new evaluator signal. Check those conditions before expanding another child, then return the best trace that still satisfies hard evidence requirements:

enforcing-branch-stop-budgets.py
1import json 2 3def stop_reason( 4 tokens_used: int, 5 token_cap: int, 6 elapsed_ms: int, 7 wall_clock_cap_ms: int, 8 repeated_state: bool, 9 score_history: list[float], 10) -> str: 11 if repeated_state: 12 return "repeated_state" 13 if tokens_used >= token_cap: 14 return "token_cap" 15 if elapsed_ms >= wall_clock_cap_ms: 16 return "wall_clock_cap" 17 if len(score_history) >= 3 and max(score_history[-3:]) <= max(score_history[:-3], default=-1): 18 return "no_recent_score_improvement" 19 return "continue" 20 21branches = [ 22 {"tokens_used": 1200, "token_cap": 4000, "elapsed_ms": 800, "wall_clock_cap_ms": 3000, 23 "repeated_state": True, "score_history": [0.54, 0.55]}, 24 {"tokens_used": 2500, "token_cap": 4000, "elapsed_ms": 1800, "wall_clock_cap_ms": 3000, 25 "repeated_state": False, "score_history": [0.72, 0.70, 0.71, 0.69]}, 26 {"tokens_used": 900, "token_cap": 4000, "elapsed_ms": 500, "wall_clock_cap_ms": 3000, 27 "repeated_state": False, "score_history": [0.40, 0.55]}, 28] 29 30print(json.dumps([stop_reason(**branch) for branch in branches], indent=2))
Output
1[ 2 "repeated_state", 3 "no_recent_score_improvement", 4 "continue" 5]

Those stop reasons are the loop condition. The controller expands only while a branch is eligible and still improving. When one fires, the branch stops; it doesn't get a final burst of unbounded tokens:

Diagram showing Live branch, Repeated, capped, or plateau?, Return best eligible, and Expand and score.
Live branch, Repeated, capped, or plateau?, Return best eligible, and Expand and score.

What signal should trigger escalation from single path to Best-of-N or tree search?

Answer

Use an exact-check result or a learned evaluator validated against task outcomes, not user impatience or arbitrary prompt length alone. Escalate when the first path performs weakly under that signal, the task is verifiable, and measured quality lift is worth the extra latency and KV-cache pressure.

KV cache limits live branch width

Long reasoning traces can stress memory as well as floating-point operations (FLOPs). Every live generated token adds a new key and value vector for every transformer layer, so key-value (KV) cache pressure grows linearly with live context length and multiplies across unshared branches.

KV cache pressure

Before choosing a branch width, estimate what one live token costs. A back-of-the-envelope formula is:

KV bytes per token≈2⋅L⋅Hkv⋅dhead⋅bytes per element\text{KV bytes per token} \approx 2 \cdot L \cdot H_{kv} \cdot d_{\text{head}} \cdot \text{bytes per element}KV bytes per token≈2⋅L⋅Hkv​⋅dhead​⋅bytes per element

Here LLL is the number of layers, HkvH_{kv}Hkv​ is the number of KV heads, and dheadd_{\text{head}}dhead​ is the head dimension. HkvH_{kv}Hkv​ isn't always the full attention-head count when the model uses grouped-query attention (GQA). For an 80-layer model with 8 KV heads, head dimension 128, and bfloat16 (BF16) activations:

2⋅80⋅8⋅128⋅2=327,680 bytes per token=320 KiB/token2 \cdot 80 \cdot 8 \cdot 128 \cdot 2 = 327{,}680 \text{ bytes per token} = 320 \text{ KiB/token}2⋅80⋅8⋅128⋅2=327,680 bytes per token=320 KiB/token

(327,680/1024=320327{,}680 / 1024 = 320327,680/1024=320 KiB; these are binary kibibytes, not decimal KB.) At 16k live tokens, one branch needs roughly 5.0 GiB of KV cache. Without prefix reuse, eight active branches need about 40 GiB before model weights or temporary activations. That multiplication is why an algorithmically reasonable beam can still fail at serving time.

Prefix sharing and paged KV storage

Best-of-N and tree search create many branches that share the same prompt and often the same early reasoning prefix. If you duplicate that prefix for every branch, memory usage grows with the number and length of branches. Systems like vLLM use PagedAttention to manage KV memory in blocks, which cuts fragmentation and makes long contexts much easier to serve [13]Reference 13Efficient Memory Management for Large Language Model Serving with PagedAttentionhttps://arxiv.org/abs/2309.06180.

PagedAttention and radix-style prefix caches solve related but different problems. PagedAttention makes allocation cheaper. RadixAttention-style caches, as used in SGLang, index shared prefixes in a tree so sibling branches can reuse the same cached prefix instead of copying it branch by branch [14]Reference 14SGLang: Efficient Execution of Structured Language Model Programshttps://arxiv.org/abs/2312.07104. In a reasoning agent you usually want both: block-level memory management plus prefix-aware reuse.

Now redo the arithmetic with sharing. If eight branches share a 12k-token prefix and each adds a 4k-token suffix, the effective footprint is one 12k prefix plus eight 4k suffixes, or about 14 GiB, not the 40 GiB worst case. The saving depends on how quickly branches diverge and whether the runtime shares prefixes at token or block granularity.

Naive search copies a 12k-token stem into every branch for about 40 GiB, while prefix reuse keeps one stem plus suffixes for about 14 GiB on the same eight 16k-token branches.
Eight unshared 16k branches cost about 40 GiB of KV. One 12k stem plus eight 4k suffixes is about 14 GiB, if the runtime can actually share that prefix.

This is one reason test-time search is an infrastructure problem, not a prompting trick alone. A search policy may be sound on paper while its branch width, trace length, or lack of compatible prefix reuse exhausts the serving memory budget before useful search completes.

Why does tree search stress KV cache more than normal chat?

Answer

Each live branch carries keys and values for every generated token. Without prefix sharing, branch count multiplies memory usage. Paged KV allocation and prefix-aware reuse let sibling branches share common prompt and early-reasoning blocks.

Compression needs value awareness; recurrent depth changes architecture

Prefix sharing removes duplicate stems, but each surviving suffix still grows. Token eviction can cap memory by dropping old KV entries, yet a reasoning trace may depend on a small earlier detail. Value-Aware Stochastic KV Cache Eviction (VaSE) reports that evicting rare, large-magnitude value states can trigger repetitive failure loops; its mitigation protects those states and adds stochasticity to eviction.[15]Reference 15Value-Aware Stochastic KV Cache Eviction for Reasoning Modelshttps://arxiv.org/abs/2606.03928 Treat that as one 2026 method evaluated on its reported models and tasks, not a universal importance rule.

An eviction policy needs four separate checks. Pin prompt constraints, tool observations, branch decisions, and other application-known critical spans. Use measured attention or value-state signals for remaining tokens. Free losing suffix pages immediately, but never evict a prefix while live children reference it. Then replay long reasoning tasks at the target compression ratio and measure loop rate, exact-check pass rate, and final quality against the uncompressed baseline.

Recurrent-depth models attack a different source of growth. Instead of expressing every extra unit of compute as more visible chain-of-thought tokens, a recurrent block can unroll additional latent depth while sharing model parameters and KV state. Geiping et al. present a 3.5B-parameter proof-of-concept with per-token adaptive compute, KV-cache sharing, and speculative decoding.[16]Reference 16Scaling up Test-Time Compute with Latent Reasoning: A Recurrent Depth Approachhttps://proceedings.neurips.cc/paper_files/paper/2025/hash/3b01972cf31e6fa0fe29e4b8b5c2a0a1-Abstract-Conference.html It's a model-architecture choice, not a cache flag you can add to a conventional autoregressive checkpoint. A capacity plan should separate mitigations available now from changes that require training and serving a different architecture.

MitigationDeployable on conventional model?Main risk
Prefix sharing and paged allocationUsually, with runtime supportIncompatible prefixes or unsafe sharing
Value-aware evictionSometimes, with compatible attention/cache pathDiscarding reasoning-critical state
Recurrent depthNo, requires purpose-built modelNew training, quality, and serving behavior

Why can't recurrent depth replace KV eviction as a drop-in runtime optimization?

Answer

It changes how the model allocates computation and represents iterative state. Existing token-reasoning checkpoints still append KV per generated token; the recurrent-depth benefit requires a model and runtime designed for that architecture.

First update vs final-answer latency

Extended reasoning changes the latency contract. At the model-serving layer, a long hidden search phase can inflate time to first token (TTFT). At the product layer, a quick status event can make first-update latency look healthy while final-answer latency and total budget still fail. Measure all three separately.

That's why production systems can stream progress events instead of raw scratchpads. Safe events include selected strategy, budget usage, branch counts, or summaries of externally confirmed checks. Treat learned verifier scores as internal diagnostics unless they're calibrated and presented with an appropriate contract.

Why do deep reasoning workflows need both first-update and final-answer latency metrics?

Answer

Without progress events, hidden search can make first visible output unacceptably slow. With progress events, first-update latency can be fast while final-answer latency or cost still exceeds its budget. Track both while keeping raw scratchpads private.

A sample capacity plan

This table uses the 320 KiB/token estimate to show how quickly memory usage grows as you add longer traces or more live branches:

WorkloadLive BranchesContext per BranchApprox KV CacheOperational Implication
Single CoT18k tokens2.5 GiBUsually easy to colocate with the base model
Best-of-448k tokens10.0 GiBParallel sampling is practical, but batching headroom shrinks
Tree Search816k tokens40.0 GiBUsually needs dedicated search workers and aggressive prefix reuse

Those are worst-case branch-multiplication numbers. Strong prefix reuse can cut the effective KV footprint substantially.

Streaming safe updates

Users need feedback while the system is spending extra inference budget, but that doesn't mean you should dump raw internal scratchpad text or expose an uncalibrated reward score as confidence. A safer pattern is to stream strategy selection, budget usage, and externally grounded summaries while the solver keeps search details private:

streaming-safe-updates.py
1from dataclasses import dataclass 2import json 3 4@dataclass 5class StreamEvent: 6 type: str 7 content: str 8 internal_score: float | None = None 9 10class ReasoningSolver: 11 def solve_stream(self) -> list[StreamEvent]: 12 return [ 13 StreamEvent("progress", "checked canary status", 0.82), 14 StreamEvent("progress", "verified rollback threshold", 0.91), 15 StreamEvent("final", "Hold canary at 10% and inspect the config flag.", 0.88), 16 ] 17 18def stream_reasoning(config: dict[str, object], solver: ReasoningSolver) -> list[dict[str, object]]: 19 events = [ 20 {"type": "status", "content": "Analyzing problem difficulty..."}, 21 { 22 "type": "config", 23 "content": f"Using {config['strategy']} with budget {config['max_tokens']} tokens", 24 }, 25 ] 26 27 for event in solver.solve_stream(): 28 if event.type == "progress": 29 events.append({ 30 "type": "progress", 31 "content": event.content, 32 }) 33 elif event.type == "final": 34 events.append({ 35 "type": "final_answer", 36 "content": event.content, 37 }) 38 return events 39 40config = {"strategy": "best_of_3", "max_tokens": 4_000} 41print(json.dumps(stream_reasoning(config, ReasoningSolver()), indent=2))
Output
1[ 2 { 3 "type": "status", 4 "content": "Analyzing problem difficulty..." 5 }, 6 { 7 "type": "config", 8 "content": "Using best_of_3 with budget 4000 tokens" 9 }, 10 { 11 "type": "progress", 12 "content": "checked canary status" 13 }, 14 { 15 "type": "progress", 16 "content": "verified rollback threshold" 17 }, 18 { 19 "type": "final_answer", 20 "content": "Hold canary at 10% and inspect the config flag." 21 } 22]

The solver still keeps internal_score for routing and diagnostics, but stream_reasoning strips that field before the event reaches the client. The user sees confirmed work, not an uncalibrated proxy.

When reasoning is the wrong tool

Ask first whether more inference can create evidence or only more text. Not every canary question needs a search tree. Tree search or Best-of-N on the rollback FAQ just burns tokens.

Simple source-of-truth queries such as "What is the rollback threshold for checkout-api?" belong against the runbook or policy source. Extra internal reasoning won't recover a missing or current fact.

Retrieval failures need retrieval, search, or tool use. Longer internal reasoning can't invent the external observation the task requires.

Open-ended copy such as "Write three titles for the incident postmortem" has no single objective answer unless the application defines and validates a rubric. Deep PRM-driven search is usually unjustified.

Latency-sensitive conversational turns need measured response objectives. If a deep path exceeds the objective, acknowledge, defer, or avoid the search.

Cost-sensitive batch processing changes the arithmetic again. Across millions of documents, a large inference multiplier can erase a small quality gain. Escalate only request cohorts whose measured lift pays for the extra cost.

Allocate substantial test-time compute when evaluation shows gain for the request class and evidence or verification can keep the answer trustworthy. Creative revision may still use a small candidate budget, but it isn't proof-oriented reasoning.

Overthinking: when more thinking lowers accuracy

Longer reasoning isn't monotonically better. Ghosal et al. find that sequentially stretching a trace with prompts such as "Wait" often raises accuracy at first, then drops it past a problem-specific sweet spot: extra steps add error accumulation, and a model can talk itself out of a correct answer it already found [17]Reference 17Does Thinking More Always Help? Mirage of Test-Time Scaling in Reasoning Modelshttps://arxiv.org/abs/2506.04210. At a matched token budget, their parallel traces with majority vote beat the sequential "think more" policy.

That is the same boundary as Best-of-N. Extra compute helps when it creates comparable candidates a checker can rank, not when it lengthens one wandering path. It can also burn thousands of reasoning tokens on a trivial question. Keep trivial work on the fast route, cap reasoning.effort or tokens, and stop when exact results are sufficient or validated evaluation stops improving. Treat reasoning budget as a tuned hyperparameter, not a dial set to maximum.

Why can adding more test-time compute hurt accuracy, and how do you defend against it?

Answer

Beyond a problem-specific sweet spot, extra sequential steps accumulate errors and can override a correct answer the model already reached, while inflating cost and latency. Defend with difficulty routing, a capped reasoning-effort or token budget, a stop rule based on exact completion or validated evaluation improvement, and parallel candidates when you have remaining budget.

Why a bigger model isn't enough

It's tempting to deploy a bigger frontier model for every reasoning workload. Quality may move, but its cost pattern differs from request-time search:

ApproachCost PatternControl
Bigger model (Training / model switch)Higher steady-state inference costFixed after deployment; every request pays for the larger model
Test-time compute (Inference)Higher per-request latency and token costDynamic per problem; easy to scale up or down

If the base model has near-zero task competence, reranking or sampling is unlikely to manufacture the missing capability. Test-time compute amplifies evaluated candidate quality; it doesn't supply missing knowledge or tools. Snell's FLOPs-matched comparison puts numbers on that boundary: extra inference can beat a much larger model on prompts the small model can already sometimes solve, but the advantage stops on the hardest ones [3]Reference 3Scaling LLM Test-Time Compute Optimally Can Be More Effective Than Scaling Model Parameters.https://arxiv.org/abs/2408.03314.

When is switching to a bigger model better than adding test-time search?

Answer

Use a stronger model when the current base model has near-zero competence, lacks required domain knowledge, or fails before search can produce useful candidates. Test-time search magnifies an existing capability; it doesn't create missing knowledge or tools.

Common pitfalls

"Higher temperature will reveal a great answer if I sample enough"

If Best-of-N produces varied traces but quality barely improves, diversity isn't the missing ingredient. Without a verifier that tracks correctness, more samples mostly add noise. Increase temperature only when a PRM, ORM, or exact checker can separate strong traces from fluent wrong ones.

"Tree search is always better than single-path reasoning"

If easy requests become slower and more expensive while accuracy barely moves, search budget reached requests that didn't need it. Route by difficulty, keep trivial and easy work on the fast path, and escalate only when the first trace scores weakly.

"More thinking always improves the answer"

If a decent first answer degrades while the system keeps exploring, it has crossed a task-specific sweet spot. Stop when exact checks pass or a validated evaluator plateaus, cap reasoning effort, and keep the best eligible fallback.

"One budget policy can serve every request"

If cheap FAQ traffic burns deep-search budget while hard debugging tasks run out of depth, compute was allocated uniformly. Separate routing, branch limits, token caps, and wall-clock caps by request class. Budget policy belongs to product design, not model tuning alone.

"Users need raw chain-of-thought to trust the system"

If streams become long and unstable while downstream tools can't tell what is final, internal scratchpad text has replaced a progress interface. Stream strategy, budget usage, and short evidence-backed summaries. Keep hidden search traces and uncalibrated evaluator scores inside the runtime.

"Reasoning quality comes only from prompts"

If prompt tweaks plateau on hard tasks, model capability, verifier quality, cache reuse, and stopping logic may have been collapsed into one prompt-design problem. Treat the base model, search controller, verifier, and serving runtime as separate levers, then improve the bottleneck.

"Stop criteria are an optional cleanup detail"

If branches revisit the same semantic state until they exhaust tokens or wall-clock time, the controller lacks a hard policy for repetition, budget exhaustion, or diminishing verifier returns. Enforce token, depth, wall-clock, and repeated-state limits per branch, then return the highest-ranked surviving trace that satisfies required checks.

What happens if the reasoning trace enters an infinite loop?

Answer

The controller stops it. Enforce hard token, depth, and wall-clock budgets; reject repeated or circular states; and prune branches that revisit the same semantic state. Return the highest-ranked surviving trace that satisfies required checks when the budget expires.

Final design checklist

Make each handoff defensible. Explain why trivial, medium, and hard verifiable tasks receive different budgets, and when a single path, Best-of-N, tree search, or a stronger base model is appropriate. Name the judge for each task, show what fails when you choose the wrong one, and test learned evaluators with correct-answer, flawed-reasoning cases so endpoint confirmation can't masquerade as process verification.

Then prove that the system can run. Check arithmetic and scheduling constraints before generating branches. Estimate KV pressure for one branch, many branches, and a shared prefix. Distinguish lossless reuse, evaluated value-aware eviction, and a recurrent-depth architecture. Define hard limits for depth, tokens, wall-clock time, and repeated states.

Finally, describe the handoff to the user. Stream strategy, budget, and externally confirmed progress. Keep raw scratchpads and uncalibrated scores private. A defensible answer isn't merely a correct-looking trace; it's an eligible trace that survived evidence, capacity, and stop policies.

Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.A small model sometimes solves checked dependency-resolution tasks, but a kernel-debugging request has no trace source to inspect. Which compute policy is defensible?

Correct answer: Use extra compute where dependency evals show lift; retrieve the missing kernel trace or abstain until evidence exists.

Test-time compute can amplify a capability that already has a measurable chance of success. When source evidence is absent, neither more sampling nor a stronger model makes the diagnosis grounded; the kernel path must obtain the trace through retrieval or tools, or abstain.

2.A solver emits a valid XML checkpoint claiming, 'Metrics API reports p95 latency below rollback threshold,' but no metrics-tool observation exists in the trace. What should the release gate do?

Correct answer: Block the claim and request the missing tool result; a checkpoint is a visible milestone, not evidence that an external fact is true.

Checkpoints provide a compact interface for milestones, but downstream gates still require matching tool observations for external facts. A valid format, a long hidden trace, or a plausible sentence cannot substitute for the metrics result.

3.Five independent candidates each have a 0.30 chance of being correct. The controller computes 1 - (1 - 0.30)^5 ≈ 0.83. What does that quantity mean?

Correct answer: At least one candidate is correct with probability about 0.83 under the independence assumption, not that selection will return it.

The formula measures candidate-set coverage. Returning a correct answer still depends on a verifier identifying it, and correlated samples or reward-model error can make returned accuracy much lower than the probability that a correct candidate exists.

4.A dependency planner must reject a parser version as soon as it violates a runtime API constraint, before completing the rest of a plan. Which search strategy fits that control loop?

Correct answer: Tree of Thoughts, because it evaluates partial assignments, prunes invalid branches early, and can backtrack among surviving paths.

Tree search exposes a frontier of partial states and evaluates them before full traces exist. Best-of-N and self-consistency compare completed candidates, while a single path has no explicit branch to prune or revisit.

5.A candidate dependency path calls an API that the deployed runtime removed. You have an exact compatibility checker, a validated PRM, and an ORM. Which component decides eligibility?

Correct answer: The exact compatibility checker rejects the path, because objective constraints outrank learned process or outcome scores.

Exact checks are authoritative for runtime compatibility. A PRM can guide pruning when a precise checker is unavailable, and an ORM can rank final outcomes, but learned proxies can be wrong or overoptimized and cannot override a hard constraint.

6.A dependency trace scores 0.72 on a validated evaluator. It is verifiable, plausible but weak, and does not need branch-level backtracking. What bounded escalation should follow?

Correct answer: Generate a bounded Best-of-3 set and rerank it with the validated evaluator before deciding whether the result is eligible.

A plausible but weak verifiable trace is a good fit for bounded parallel candidates and reranking. Tree search adds branch management when backtracking is needed, while immediate release would treat a proxy score as proof.

7.A branch passed required exact checks, then its last three evaluator scores stopped improving; another branch repeats a semantic state and the token cap is near. What should the controller return?

Correct answer: Stop repeated or plateaued branches and return the highest-ranked surviving trace that still satisfies the required evidence checks.

Hard token, wall-clock, repeated-state, and no-improvement rules keep search bounded. More tokens can accumulate errors or talk a model out of a correct result, so the safe fallback is the best eligible trace after required checks pass.

8.One branch uses 320 KiB of KV per live token. An unshared tree has eight 16k-token branches; a shared layout keeps one 12k prefix plus eight 4k suffixes. Which capacity comparison is closest?

Correct answer: The unshared layout is about 40 GiB, while the shared layout is about 14 GiB if the runtime can safely reuse the common prefix.

One 16k branch is about 5 GiB, so eight unshared branches are about 40 GiB. Sharing 12k tokens plus eight 4k suffixes gives 44k live tokens, or roughly 14 GiB at 320 KiB each. The saving depends on compatible block or token-level prefix reuse.

9.A learned evaluator accepts a dependency trace with an invalid intermediate step whenever the final version set is correct. Which evaluation design isolates this failure?

Correct answer: Use valid-answer-invalid-reasoning cases, lock step verdicts before revealing the endpoint, and track false acceptance separately from solver accuracy.

A correct endpoint can bias a judge into rationalizing a broken path. Counterfactual cases and answer-hidden verdicts test process evaluation directly, while separate solver and evaluator metrics reveal whether failures come from generation or acceptance.

9 questions remaining.

Next Step
Continue to AI Lab Coding Interview: Python Systems

You can now design a controller that allocates inference compute, checks evidence, and stops when search stops helping. The next phase turns that architecture into interview execution: production-shaped Python systems, staged requirements, concurrency invariants, and tests you can defend.

PreviousReal-Time Voice AI Agent
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

o1 Preview Model

OpenAI · 2024

https://developers.openai.com/api/docs/models/o1-preview

DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning

DeepSeek-AI · 2025

https://arxiv.org/abs/2501.12948

Scaling LLM Test-Time Compute Optimally Can Be More Effective Than Scaling Model Parameters.

Snell, C., et al. · 2024 · arXiv preprint

https://arxiv.org/abs/2408.03314

Chain-of-Thought Prompting Elicits Reasoning in Large Language Models.

Wei, J., et al. · 2022 · NeurIPS

https://arxiv.org/abs/2201.11903

Reasoning models

OpenAI · 2026

https://developers.openai.com/api/docs/guides/reasoning

GPT-5.5 Model

OpenAI · 2026

https://developers.openai.com/api/docs/models/gpt-5.5

Scaling Laws for Reward Model Overoptimization

Gao, L., Schulman, J., & Hilton, J. · 2023

https://arxiv.org/abs/2210.10760

Self-Consistency Improves Chain of Thought Reasoning in Language Models.

Wang, X., et al. · 2023 · ICLR 2023

https://arxiv.org/abs/2203.11171

Tree of Thoughts: Deliberate Problem Solving with Large Language Models.

Yao, S., et al. · 2023 · NeurIPS

https://arxiv.org/abs/2305.10601

Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm.

Silver, D., et al. · 2017 · arXiv preprint

https://arxiv.org/abs/1712.01815

Let's Verify Step by Step.

Lightman, H., et al. · 2023 · ICLR

https://arxiv.org/abs/2305.20050

An Enigma of Artificial Reason: Investigating the Production-Evaluation Gap in Large Reasoning Models

Sun, M., Yeo, T., Solar-Lezama, A., & Tan, Z.-X. · 2026

https://arxiv.org/abs/2606.01462

Efficient Memory Management for Large Language Model Serving with PagedAttention

Kwon, W., et al. · 2023 · SOSP 2023

https://arxiv.org/abs/2309.06180

SGLang: Efficient Execution of Structured Language Model Programs

Zheng, L., Yin, L., Xie, Z., et al. · 2024 · NeurIPS 2024

https://arxiv.org/abs/2312.07104

Value-Aware Stochastic KV Cache Eviction for Reasoning Models

Chang, T.-Y., Fu, H. Y., Fu, D., Yang, C., Thomason, J., & Jia, R. · 2026

https://arxiv.org/abs/2606.03928

Scaling up Test-Time Compute with Latent Reasoning: A Recurrent Depth Approach

Geiping, J., McLeish, S., Jain, N., Kirchenbauer, J., Singh, S., Bartoldson, B. R., Kailkhura, B., Bhatele, A., & Goldstein, T. · 2025 · NeurIPS 2025

https://proceedings.neurips.cc/paper_files/paper/2025/hash/3b01972cf31e6fa0fe29e4b8b5c2a0a1-Abstract-Conference.html

Does Thinking More Always Help? Mirage of Test-Time Scaling in Reasoning Models

Ghosal, S. S., Chakraborty, S., Reddy, S., et al. · 2025

https://arxiv.org/abs/2506.04210

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.