CopT: Contrastive On-Policy Thinking with Continuous Spaces for General and Agentic Reasoning

Paper: arXiv:2605.20075 Code: sdc17/CopT Code reference: main @ 343713a8 (2026-05-21)

1. Motivation (研究动机)

现有 Chain-of-Thought (CoT) 推理默认遵循“先完整思考、再输出答案”的顺序。这个范式在数学、代码和 agentic reasoning 上有效,但也带来一个很具体的低效:模型经常已经内部确定了一个 plausibly correct answer,却仍然继续生成很长的显式 reasoning trace;论文把这类现象称为 performative reasoning。它的问题不是 CoT 不会推理,而是 CoT 把“思考”当成回答的必要前置步骤,导致两类浪费:一是用户必须等待完整 reasoning trace 结束才能看到答案;二是简单样本也消耗大量 token。

这篇论文要解决的目标是:在不训练模型、不改变权重的前提下,让 LLM 先给出 draft answer,再只在 draft 不可靠时触发后续 on-policy thinking 来反思和修正。这样既保留 explicit reasoning 的可读性,又避免对所有样本一刀切地执行长 CoT。

这个问题值得研究的原因在于推理型模型的成本瓶颈已经从“是否能生成 reasoning”转向“是否能把 reasoning 用在真正需要的样本上”。如果可以可靠判断 draft answer 是否足够可信,就能把 token budget 从容易样本转移到困难样本;如果还可以控制 draft answer 在后续思考中的可见性,就能利用其中的局部信息,同时降低错误 draft 误导后续推理的风险。这对数学、代码、函数调用和多轮工具交互尤其重要,因为这些任务既需要准确性,也需要延迟和 token 成本可控。

2. Idea (核心思想)

CopT 的核心 insight 是:continuous embeddings 不一定要像 latent CoT 那样直接拿来“生成”隐式思考,它们也可以被当作 inference-time verifier。具体做法是对同一串已生成 token,比较模型在 discrete-token prefix 下和 continuous-embedding prefix 下对这些 token 的支持度;两者差异越大,说明连续空间保留的不确定性越会改变模型对当前回答/思考片段的信心。

方法上,CopT 先强制模型跳过 <think> 直接生成 draft answer,然后用 sequence-level reverse KL estimator 判断 draft 是否可靠;若不可靠,再触发 <think>,进行 conditioned on draft 的 on-policy thinking,并在每个 chunk 结束后用另一个 estimator 决定下一段思考是否能看见 draft answer。

与 Soft-Thinking、SwiReasoning 等 training-free continuous reasoning 方法的根本差异是:后者主要把 continuous embeddings 当作 generation medium,牺牲或弱化显式可读 trace;CopT 则保持输出仍是 explicit natural-language/code reasoning,只把 continuous embeddings 用作 contrastive verifier 和 visibility controller。因此 CopT 的目标不是把思考隐藏在连续空间里,而是在显式思考外面加一个“是否需要思考、以及思考时是否应该参考 draft”的控制层。

3. Method (方法)

3.1 Overall framework: answer-first + contrastive verification

Figure 1 解读:Figure 1a 对比了标准 CoT 和 CopT 的执行顺序:CoT 先 thinking 再 answer,而 CopT 先产出 draft answer,再根据 verifier 决定是否进入 on-policy thinking。Figure 1b 展示了 contrastive verifier 的关键:同一组输出 token 会分别在 discrete inputs 与 continuous inputs 下被打分,分布差异就是 reliability signal。Figure 1c 给出直观 trade-off:CopT 在 matched 或更少 token 下提高 peak accuracy;绿色星号对应 increasing reasoning effort 的设置。

Figure 2 解读:Figure 2 是完整 pipeline。左侧 draft-answer stage 中,模型被强制先输出 </think>,直接进入 answer mode;生成每个 draft token 时同时缓存 chosen-token log-probability 与由 next-token distribution 加权得到的 continuous embedding。中间的 用这些缓存比较 discrete prefix 与 continuous prefix 下的 token support,若 就直接接受 draft;若 ,右侧进入 on-policy thinking。on-policy thinking 被切成多个 chunk,每个 chunk 结束后用 判断当前思考是否稳定,并更新下一 chunk 中 draft answer 的 visibility mask

直觉上,CopT 把“是否应该继续思考”转化为一个 token-support stability 问题。如果 draft answer 是模型在不确定状态下偶然采样出来的,那么把历史 token 替换成 continuous embeddings 后,模型对同一 answer token 的支持度会发生明显变化;反过来,如果 continuous prefix 和 discrete prefix 都支持这串 answer token,则 draft 更可能已经足够可靠。后续 thinking 阶段同理:如果当前 chunk 在 continuous contrast 下不稳定,就暂时隐藏 draft,避免错误 answer anchoring;如果 chunk 稳定,则允许 draft 重新可见,利用其中可能正确的部分信息。

3.2 Draft-answer elicitation

设模型为 ,输入 embedding matrix 为 。给定问题 token 序列 ,CopT 不让模型先生成完整 CoT,而是在开头强制输出 </think>,直接进入 answering mode。draft answer 记为: 生成 draft 的每个 token 时,CopT 缓存两类量: 其中 是实际采样 token 的概率, 是按完整 next-token distribution 加权的 continuous embedding。这个 保留了“模型本来还在考虑哪些 token”的不确定性,而不只保留最终采样出来的 token。

3.3 Draft reliability estimator

draft 结束后,CopT 用 continuous prefix 重新 teacher-force 同一组 answer token。对每个位置: sequence-level reverse KL estimator 定义为: 对固定 draft length ,论文证明它是下面 normalized sequence-level reverse KL 的 unbiased estimator: ,说明 answer token 在 continuous uncertainty 下不再被同样支持,draft 可能不可靠,于是 CopT 强制模型输出 <think>,开始后续 on-policy thinking;若 ,直接接受 draft。

3.4 On-policy thinking and draft visibility control

当 draft 被判为不可靠时,CopT 不是丢弃它,而是启动后续 thinking: thinking trajectory 被分成长度为 的 chunks。第 个 chunk 的开始位置为: 并定义 draft 在该 chunk 是否可见: 在第 个 chunk 内,每个 thinking token 同样缓存: 然后用 modified intra-chunk input embeddings 得到 teacher probability: chunk-level estimator 为: $ \kappa_r^{(k)}(r_{s_k:s_k+C-1}) :=\frac{1}{C}\sum_{t=s_k}^{s_k+C-1}\left[ \log p_\theta(r_t\mid q,a^{(m_k)},r_{T_a+1:t-1})

\log p_\theta(r_t\mid q,a^{(m_k)},r_{T_a+1:s_k-1};e_{s_k:t-1}) \right]. \kappa_r^{(k)}<\tau_r m_{k+1}=\begin{cases} 1,&\kappa_r^{(k)}<\tau_r,\ 0,&\text{otherwise}. \end{cases} $

3.5 Theoretical interpretation: answer-relevant uncertainty

论文给出一个 local mixture-prefix 解释。设 latent reasoning state 集合为 ,答案 token 集合为 。离散 prefix 相当于 commit 到某个 latent state ,其 next-token distribution 为: continuous prefix 可以表示多个 latent states 的 mixture,假设其 next-token distribution 满足 mixture-linear: 对 emitted answer token ,local reverse-KL contribution 是: 定理说明: \mathbb{E}_{S\sim w,A\sim P_S}[\kappa(S,A)] =\sum_{s\in\mathcal{S}}w(s)D_{\mathrm{KL}}(P_s\,\middle\|\,\bar P_w)=I(S;A). 这解释了为什么 测量的不是“latent state 本身是否不确定”,而是“这种不确定性是否会影响 emitted answer token”。如果多个 latent states 虽然不同,但都支持同一答案, 可以很小;如果 unresolved state 会导致不同答案, 会变大。

3.6 Implementation-grounded pseudocode

下面伪代码按 released code generation_utils.py 的实现抽象而来,而不是只按论文公式重写。真实代码有两套路径:generate_copt 用于普通 Transformer cache,generate_copt_hybrid 用于 hybrid cache;generate_copt_general 会根据模型 cache 结构自动分派。

Component A: continuous embedding cache

import torch
import torch.nn.functional as F
 
@torch.no_grad()
def sample_token_and_cache(model, logits, embedding_matrix, temperature=0.6,
                           top_p=0.95, top_k=20, min_p=0.0, do_sample=True):
    # Released code samples from filtered logits but computes cached log-prob/soft-embed
    # from the raw next_token_logits.
    filtered = apply_sampling_filter(logits / temperature,
                                     top_k=top_k, top_p=top_p, min_p=min_p)
    probs = F.softmax(filtered, dim=-1)
    token = torch.multinomial(probs, 1).squeeze(-1) if do_sample else probs.argmax(dim=-1)
 
    raw_logprob = F.log_softmax(logits, dim=-1).gather(1, token[:, None]).squeeze(1)
    soft_embed = F.softmax(logits, dim=-1) @ embedding_matrix
    return token, raw_logprob, soft_embed

Component B: cached reverse-KL teacher pass

@torch.no_grad()
def cached_soft_teacher_reverse_kl(model, teacher_inputs_embeds, target_ids,
                                   student_token_log_probs, sample_attention_mask,
                                   prefix_len):
    if teacher_inputs_embeds.size(1) == 0 or target_ids.size(1) == 0:
        return None
 
    # The released code obtains all teacher probabilities for a span in one
    # forward pass over modified input embeddings.
    teacher_attention_mask = sample_attention_mask[:, :prefix_len + teacher_inputs_embeds.size(1)]
    teacher_outputs = model(inputs_embeds=teacher_inputs_embeds,
                            attention_mask=teacher_attention_mask,
                            use_cache=False)
    teacher_log_probs = F.log_softmax(teacher_outputs.logits, dim=-1)
    teacher_token_log_probs = teacher_log_probs.gather(-1, target_ids[..., None]).squeeze(-1)
 
    token_reverse_kl = student_token_log_probs - teacher_token_log_probs
    return token_reverse_kl.mean().item()

Component C: draft-answer gate

@torch.no_grad()
def draft_answer_gate(sample_ids, draft_soft_embeds, draft_student_log_probs,
                      draft_answer_start, draft_end, tau_a):
    draft_len = draft_end - draft_answer_start + 1
    if draft_len <= 1:
        return "accept"
 
    teacher_inputs_embeds = torch.stack(draft_soft_embeds[:draft_len - 1], dim=0)[None]
    target_ids = sample_ids[:, draft_answer_start + 1:draft_end + 1]
    student = torch.tensor(draft_student_log_probs[1:draft_len])[None]
 
    kappa_a = cached_soft_teacher_reverse_kl(
        model, teacher_inputs_embeds, target_ids, student,
        sample_attention_mask=attention_mask, prefix_len=draft_answer_start,
    )
    return "restart_think" if kappa_a is not None and kappa_a > tau_a else "accept"

Component D: chunk visibility update

@torch.no_grad()
def update_draft_visibility(chunk_positions, restart_all_soft_embeds,
                            restart_chunk_log_probs, sample_ids, tau_r):
    if not chunk_positions:
        return False
 
    span_start, span_end = chunk_positions[0], chunk_positions[-1]
    chunk_len = span_end - span_start + 1
    teacher_inputs_embeds = torch.stack(restart_all_soft_embeds[-chunk_len:], dim=0)[None]
    target_ids = sample_ids[:, span_start:span_end + 1]
    student = torch.tensor(restart_chunk_log_probs[-chunk_len:])[None]
 
    kappa_r = cached_soft_teacher_reverse_kl(
        model, teacher_inputs_embeds, target_ids, student,
        sample_attention_mask=attention_mask, prefix_len=span_start,
    )
    # Released code makes the draft visible iff chunk_kl < tau_r.
    return kappa_r is not None and kappa_r < tau_r

Component E: overall inference loop

@torch.no_grad()
def copt_generate(model, tokenizer, prompt_ids, tau_a, tau_r,
                  max_new_tokens=32768, draft_max_new_tokens=1024):
    # 1. Force </think>, then draft an answer.
    generated = append_forced_tokens(prompt_ids, tokenizer.encode("</think>"))
    draft_logprobs, draft_soft_embeds = [], []
 
    for _ in range(max_new_tokens):
        logits = model(generated).logits[:, -1, :]
        token, logprob, soft_embed = sample_token_and_cache(
            model, logits, model.get_input_embeddings().weight,
        )
        generated = append_token(generated, token)
        draft_logprobs.append(logprob)
        draft_soft_embeds.append(soft_embed)
 
        if token_is_eos(token) or len(draft_logprobs) >= draft_max_new_tokens:
            if draft_answer_gate(generated, draft_soft_embeds, draft_logprobs,
                                 draft_answer_start=answer_start(generated),
                                 draft_end=answer_end(generated),
                                 tau_a=tau_a) == "accept":
                return generated
            break
 
    # 2. Restart explicit thinking and periodically hide/show the draft.
    generated = hide_draft_from_attention(generated)
    generated = inject_tokens(generated, tokenizer.encode("<think>"))
    chunk_size = max(1, len(draft_logprobs) // 4)
    chunk_logprobs, chunk_soft_embeds, chunk_positions = [], [], []
 
    for _ in range(max_new_tokens):
        logits = model(generated).logits[:, -1, :]
        token, logprob, soft_embed = sample_token_and_cache(
            model, logits, model.get_input_embeddings().weight,
        )
        generated = append_token(generated, token)
        chunk_positions.append(current_position(generated))
        chunk_logprobs.append(logprob)
        chunk_soft_embeds.append(soft_embed)
 
        if len(chunk_positions) >= chunk_size:
            visible = update_draft_visibility(chunk_positions, chunk_soft_embeds,
                                              chunk_logprobs, generated, tau_r)
            generated = set_draft_attention_visibility(generated, visible)
            chunk_positions, chunk_logprobs, chunk_soft_embeds = [], [], []
 
        if token_is_eos(token):
            return generated

3.7 Code-to-paper mapping

Code reference: main @ 343713a8 (2026-05-21) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
CopT dispatch for standard vs hybrid cachegeneration_utils.pygenerate_copt_general, _model_has_hybrid_cache_structure
Draft-first inference and forced </think>generation_utils.pygenerate_copt, generate_copt_hybrid
Continuous embedding cache generation_utils.pysampling loop computes raw_soft_embeds = softmax(logits) @ embedding_matrix
Draft reliability estimator generation_utils.py_draft_answer_reverse_kl, _cached_soft_teacher_reverse_kl
On-policy thinking restart with <think>generation_utils.pyinject_queues, restart_triggered, attention-mask draft hiding
Chunk visibility estimator generation_utils.py_restart_chunk_reverse_kl, restart_chunk_positions, restart_chunk_log_probs
General benchmark evaluationrun.pymain, generate_cot, generate_copt_general, answer_match
Agentic/ZebraArena evaluationrun_agents.pyZebraArena loop, per-turn zebra_gen_kwargs, draft_max_new_tokens=512
Default reasoning effort thresholdsconfig/default_effort_*.jsonper-dataset tau_a, tau_r
Result aggregationmerge.pymerges distributed output files for a method/dataset/model

论文公式与 released code 实现差异:未发现关键 estimator 方向或 visibility rule 的明显矛盾;但实现中 restart_chunk_sizes = max(1, draft_len // 4),其中触发处的 draft_len 在普通路径里从 forced </think> 起算,边界上可能比论文记号中的纯 draft-answer length 多包含 sentinel token。这个差异通常只影响 chunk size 的 off-by-one 级别,不改变 / 的定义或 chunk_kl < tau_r 才显示 draft 的规则。

4. Experimental Setup (实验设置)

4.1 Benchmarks and scale

论文评测 10 个 reasoning benchmarks:

GroupBenchmarkScale / splitWhat is measured
MathGSM8K1,319 test problemsgrade-school arithmetic reasoning accuracy
MathMath500500 curated MATH problemshigh-school competition math accuracy
MathAIME 202430 problemscompetition-level numeric-answer reasoning;论文重复 8 次取平均
MathAIME 202530 problemscompetition-level numeric-answer reasoning;论文重复 8 次取平均
STEMGPQA Diamond198 expert-verified multiple-choice questionsexpert-level STEM reasoning
CodingHumanEval164 Python tasksunit-test pass accuracy
CodingLeetCode-Contest180 contest problemsgenerated solution passes all tests
CodingMBPP257 sanitized test problemsexecution-based Python problem solving
AgenticBFCL v42,501 non-live + live function-calling problemsfunction/tool invocation accuracy
AgenticZebraArenaSmall / Medium / Large missing-clue multi-turn splits;论文未详细说明每 split 样本数multi-turn tool-augmented constraint-solving accuracy

4.2 Models, baselines, and metrics

模型覆盖 Qwen3 与 Qwen3.5:general reasoning 使用 pure Transformer Qwen3 models,主表重点报告 Qwen3-8B;agentic reasoning 使用 Qwen3.5-2B 与 Qwen3.5-35B-A3B,因为 Qwen3.5 面向更强 agentic capabilities。论文还在 2B、8B、35B scales 上验证跨模型族、dense/sparse/hybrid 架构的稳定性。

Baselines 包括:standard CoT、CoT (Greedy)、Soft-Thinking、SwiReasoning,以及在 agentic benchmarks 上的 CoT baseline。评价指标主要是 Acc. (%)# Tokens;Fig. 3 还报告 single H200 GPU 上的 average per-sample latency。对 continuous-generation baselines,token counts 按 generation steps 计数,不区分 explicit 或 latent steps。

4.3 Inference and implementation configuration

论文与 released code 一致地使用 Qwen3/Qwen3.5 默认 sampling settings:temperature 0.6、top-p 0.95、top-k 20、min-p 0,并且 do_sample=True。所有实验在 single NVIDIA H200 GPU 上运行。默认 maximum generation length:GSM8K、Math500、GPQA Diamond、HumanEval、LeetCode-Contest、MBPP、BFCL v4 为 32768 tokens;AIME 2024/2025 为 38912 tokens;ZebraArena Small/Medium/Large 分别为 327686553698304 tokens。

released code 的实际 launch/config 锚点如下:

  • General reasoning launch: run.sh 调用 run.py;Qwen3-8B 上 GSM8K batch size 256,Math500 128,GPQA Diamond 32,AIME24/25 30--max_new_tokens 38912
  • Agentic reasoning launch: run.sh 调用 run_agents.py;ZebraArena Small/Medium/Large batch size 分别为 16/8/4,max turns 分别为 16/32/48
  • Default effort configs: config/default_effort_gsm8k.json 设置 tau_a=0.6, tau_r=0.7default_effort_math500.json 设置 0.6, 0.4default_effort_aime_2024.jsondefault_effort_aime_2025.json 设置 1.0, 0.3default_effort_gpqa_diamond.json 设置 1.0, 0.6default_effort_zebra_arena.json 设置 1.5, 0.0
  • Draft/chunk settings: supplement 写明 ;released code 中 generation_utils.pyrestart_chunk_sizes = max(1, draft_len//4)。default draft answer length cap 是 1024,ZebraArena 在 run_agents.py 中显式设置 draft_max_new_tokens=512

5. Experimental Results (实验结果)

5.1 Main general-reasoning results on Qwen3-8B

Table 1 的核心结论是:CopT 可以在 matched 或更高 accuracy 下显著减少 token,也可以通过 increasing reasoning effort 获得更高 peak accuracy。

BenchmarkCoT Acc / TokensCopT token-saving Acc / TokensCopT higher-effort Acc / Tokens
GSM8K95.75 / 213895.98 (+0.23) / 961 (-55.1%)96.36 (+0.61) / 1813 (-15.2%)
Math50096.00 / 498596.20 (+0.20) / 3609 (-27.6%)97.60 (+1.60) / 4851 (-2.7%)
AIME2475.83 / 1207779.17 (+3.34) / 11525 (-4.6%)
AIME2567.50 / 1292470.42 (+2.92) / 12801 (-1.0%)
HumanEval92.68 / 236894.51 (+1.83) / 1023 (-56.8%)96.34 (+3.66) / 1842 (-22.2%)
LeetCode-Contest59.44 / 730661.11 (+1.67) / 6993 (-4.3%)66.11 (+6.67) / 7607 (+4.1%)
MBPP94.16 / 203394.55 (+1.39) / 1997 (-1.8%)
GPQA Diamond59.60 / 812361.62 (+2.02) / 6851 (-15.7%)

需要注意,CopT 并不是所有点都同时降低 token:LeetCode-Contest 的 higher-effort setting 用 7607 tokens,比 CoT 多 4.1%,但 accuracy 提升 6.67。论文因此把 CopT 作为 controllable accuracy-token trade-off,而不是固定 token-reduction trick。

5.2 Comparison with continuous-generation methods

Table 2 对比 training-free continuous methods。Soft-Thinking 与 SwiReasoning 使用 continuous embeddings 作为 generation medium,因此不完全保留 explicit readability;CopT 保留显式输出并取得更好的 accuracy-token trade-off。

MethodGSM8K Acc / TokensAIME25 Acc / TokensHumanEval Acc / TokensGPQA Diamond Acc / TokensFully explicit readability
Soft-Thinking95.38 / 207368.33 / 1366592.07 / 240859.60 / 8153No
SwiReasoning96.06 / 221870.00 / 1391195.73 / 289461.11 / 8359No
CopT96.36 / 181370.42 / 1280196.34 / 184261.62 / 6851Yes

这组结果支撑了论文的核心定位:continuous space 的价值不必体现在“用连续状态替代 token 生成”,也可以体现在“对 token 生成过程进行 verifier-style contrast”。

5.3 Controllable reasoning effort and latency

Figure 3 解读:左、中的曲线展示调节 后的 accuracy-token trade-off。降低 会让更少 draft 被直接接受,从而提高 reasoning effort;降低 会让后续 thinking 更少依赖 draft answer,也提高 correction effort。右图显示 token saving 会转化为真实 latency reduction:在 comparable 或更高 accuracy 下,CopT 在 GSM8K、Math500、HumanEval 上分别降低 37%、20%、69% 的 average per-sample latency,测量环境为 single H200 GPU。

5.4 Agentic reasoning results

Table 3 显示 CopT 在 BFCL v4 和 ZebraArena 上同样有效。BFCL 是 single-turn function calling;ZebraArena 是 multi-turn missing-clue tool-augmented reasoning。

Benchmark / ModelCoT Acc / TokensCopT token-saving Acc / TokensCopT higher-effort Acc / Tokens
BFCL v4, Qwen3.5-2B77.53 / 23478.01 (+0.48) / 139 (-40.6%)78.37 (+0.84) / 164 (-29.9%)
BFCL v4, Qwen3.5-35B-A3B85.77 / 23586.17 (+0.40) / 130 (-44.7%)86.45 (+0.68) / 168 (-28.5%)
ZebraArena Small, Qwen3.5-35B-A3B93.71 / 335796.69 (+2.98) / 3486 (+3.8%)
ZebraArena Medium, Qwen3.5-35B-A3B75.00 / 721788.14 (+13.14) / 5457 (-24.4%)
ZebraArena Large, Qwen3.5-35B-A3B59.21 / 807082.24 (+23.03) / 6486 (-19.6%)

最强信号来自 ZebraArena Medium/Large:多轮交互越长,错误 draft 或冗余 thinking 的累计影响越大,CopT 的“选择性纠错 + 动态 draft visibility”越有价值。Large split 上 accuracy 从 59.21 提升到 82.24,同时 tokens 从 8070 降到 6486。

5.5 Ablations

Figure 4 解读:左图研究 是否真的能抓到错误 draft。随着 更严格,CopT 选出的 unreliable drafts 数量减少,但 precision 上升;uniform selection 的 precision 低且近似平坦,说明不是“随机多想一点”就能定位错误。右图研究 对 draft visibility 的影响:更严格的 visibility control 会让模型更少暴露于可能错误的 draft,并纠正更多实际 draft errors,同时 token usage 上升,体现出 correction-vs-efficiency trade-off。

补充实验还报告了两个实现敏感点:

  • Answer granularity: 默认 对 whole draft answer 计算,在 GSM8K / Math500 上为 95.98 / 961 和 96.20 / 3609;只对 extracted answer span 计算可提升到 96.36 / 885 与 96.40 / 3214,说明更聚焦 answer content 可能进一步节省 token,但论文主实验采用 whole draft answer 作为简单默认。
  • Maximum draft length: 默认 1024 在 GSM8K 上达到 95.98 / 961;Math500 上 512 达到最高 97.00 / 3660,但 2048 降到 94.40 / 3265。作者结论是 draft cap 主要用于防止少数难题在 answer-first 阶段生成重复/无效文本,不是高度敏感的核心 hyperparameter。

5.6 Limitations and takeaways

作者明确指出三类限制。第一, 都基于 inference-time realized trajectory,而不是对多个 continuations 的分布均值做估计;这符合 per-instance control,但方差可能高于 multi-sample estimates,论文通过 token averaging 缓解。第二,CopT 需要访问模型 logits、input embeddings 和 attention mask,因此更适合 open-weight 或可深度控制推理栈的模型;如果只能调用黑盒 API,continuous-prefix teacher pass 和 draft visibility masking 不一定可用。第三,thresholds 仍需要按任务调节,虽然 released configs 给出了默认 effort,但不同模型/任务可能需要重新扫 trade-off 曲线。

总体结论是:CopT 把 continuous embeddings 从“隐式生成空间”重新定位为“显式推理的 verifier/control signal”。它不训练模型,却能在数学、代码和 agentic reasoning 中同时改善 accuracy-token trade-off;尤其在多轮 agentic setting 中,动态决定是否继续思考以及是否参考 draft answer,比固定长 CoT 更适合实际部署。