难负样本阶段被忽略的三个细节为什么你的CLM打分总是不如官方【免费下载链接】CLMContrastive Language Models (CLMs) are a new class of System One model trained with a contrastive learning objective that connects states and actions.项目地址: https://gitcode.com/gh_mirrors/clm2/CLMCLM-8B 大概是最近一周 Agent 圈讨论密度最高的开源模型之一它把 Agent 的动作决策从生成式整体改造成状态-动作向量匹配用冻结的 Qwen3-8B 编码器加两个约 20M 参数的投影头projection head做对比学习打分在计算机使用、游戏与工具调用任务上与 Jev 持平的同时延迟最高降低约 9 倍作为 verifierbest-of-N 选择器轻量微调后在 Terminal-Bench 2.1 与 DeepSWE 上分别刷到 87.6% 和 81.6%而 Jev 在这些长程任务上连 pass1 都打不过。热度一高复现的人就多了随之而来的典型抱怨是我按文档微调/部署了为什么打分分布、top-1 准确率和官方数字对不上这个问题大多不是玄学而是出在数据配方与评分协议上。本文不写口号直接对照 README.md 的 Data Recipe 与仓库里的训练、评估、服务端源码拆三件事难负样本到底怎么构造的、正负样本配比与温度参数如何直接决定分布形态以及从打分不如官方反推出来的三个最常被忽略的细节。难负样本的构造方式相似但错误从合成到批内CLM 的训练不是单一阶段。官方配方README.md 的 Data Recipe 一节是三段式预训练约 6000 万条 Nemotron DQA 问答对问题是 state、答案是 action用双向 InfoNCE 学宽泛语义表示难负样本强化mid-training约 3000 万条合成难负样本由 Gemini 2.5 Flash-Lite 生成——语义上与正确答案相似、但确实是错误的答案被逐条加进 InfoNCE 损失Agent 轨迹后训练约 100 万条 ADPAgent Data Protocol轨迹步骤外加 Endless-Terminals、LiteCoder-Terminal-SFT 的终端轨迹每个轨迹步就是一个 (state, action) 对。关键在第二阶段。难负样本不是简单地往 batch 里塞随机句而是只作用于 state→action 这一个方向且只针对当前正样本做归一化L_{s \rightarrow a}^{\mathrm{hard}}-\frac{1}{B}\sum_i\log\frac{\exp\left(s_i^\top a_i / \tau\right)}{\exp\left(s_i^\top a_i / \tau\right)\sum_k\exp\left(s_i^\top h_{ik}^{(a)} / \tau\right)}其中 $h_{ik}^{(a)}$ 是状态 $s_i$ 的第 $k$ 个难负样本动作。也就是说模型被要求在若干看着都对的错误答案里把正确的挑出来这是 fine-grained discrimination 的来源——也是为什么你的打分看起来钝的第一个伏笔如果你的评估集里没有这种相似但错误的干扰项模型在分布层面的区分力根本无从体现。更有意思的是训练时序。README 明确给出了一个反直觉的消融在约 10 万条留出问题上1 个标准答案 10 个难负样本纯预训练不看任何难负样本就能到52.1%top-1加一段短 mid-training 直接跳到69.2%而从一开始就带难负样本训练虽然前期涨得快峰值只有62.4%就会过拟合。换句话说难负样本是预训练之上的精修而不是替代品——两阶段配方在同一预算下高出约 7 个点。如果你图省事把难负样本直接混进初始训练或者跳过 mid-training 直接微调你的打分能力天然就少了这 7 个点。后训练阶段还有一个容易忽略的防遗忘设计40% 的 Nemotron DQA replay 60% Agent 轨迹。带 replay 时 Nemotron 难负样本 top-1 只从 69% 微降到 68.5%而纯 Agent 数据训同样步数会掉到56.2%。很多复现者微调时把 replay 洗掉、只喂轨迹数据打分在通用语义上就这样悄悄塌了。正负样本配比与温度参数分布形态的隐形开关训练侧的正负样本配比由两件事决定batch 大小in-batch negative 数量和分组掩码。train/finetune.py 的_clm_loss是核心state_z F.normalize(state_head(states), dim-1) action_z F.normalize(action_head(actions), dim-1) logits logit_scale.exp().clamp(max100.0) * state_z action_z.t() labels torch.arange(len(states), devicestates.device) same codes.unsqueeze(0) codes.unsqueeze(1) same.fill_diagonal_(False) forward F.cross_entropy(logits.masked_fill(same, float(-inf)), labels) backward F.cross_entropy(logits.t().masked_fill(same, float(-inf)), labels) return (forward backward) / 2, logits, labelsclm 任务默认--batch 2048即每个正样本面对约 2047 个批内负样本codes按(task_id, step_idx)分组同一轨迹内的状态-动作对彼此屏蔽避免作弊负样本。这就是官方校准的环境数千个随机负样本的检索任务。微调时--tasks-per-batch 4、--sampler random/task-blocked进一步控制批内任务构成。choice 任务默认--batch 256且--loss可选infonce批内双向或softce每个问题自己的候选上做 softmax、--targets可选soft标注者分布/hardgold label——这些参数任何一个换掉训练出的分布性质都不同。温度参数是第二个开关。对比学习里的温度在仓库里表现为可训练参数logit_scaletrain/finetune.py 初始化为log(1/0.07)约 2.66作为nn.Parameter参与训练前向与服务端都 clamp 到上限 100src/clm/heads.py 加载时同样exp().clamp(max100)。而推理侧还有第二个温度POST /v1/systemone的temperature字段默认 1在 softmax 之前除logitssrc/clm/engine.pyanswers[qid] answer_from_logits(questions[qid], keys, (scale * cos / temperature).tolist())这意味着最终分布 softmax(exp(logit_scale) * cos / temperature)。logit_scale 是在千级负样本 3000 万难负样本的语境下学出来的把它套到只有 2~5 个候选的在线问题上分布天然会更尖锐。仓库里的 T-Rex 实测最能说明分数分布不等于决策质量examples/t_rex/results/clm_realtime.json 与 examples/t_rex/results/jev_realtime.json 显示同一个 Choice 问题jump/duck/run 三选一CLM 与物理规划器最佳动作的一致性中位数只有 0.658Jev 高达 0.987但两者都是 5/5 存活、0 死亡CLM 的 p50 端到端延迟 16.5ms模型部分 2.6msJev 是 149.8ms模型 131.9ms。分布不同 ≠ 能力差但如果你拿着 CLM 的概率分布去对照 Jev 的分布习惯或者对照官方论文表格里的数字就一定会得出不如官方的结论。从打分不如官方反推最常被忽略的三个细节细节一官方 verifier 打分用的是余弦相似度不是 softmax 概率这是最隐蔽、最致命的一条。CLM 的 API 返回的是 softmax 概率answer_from_logits但官方 best-of-N 评估 evaluation/bon_eval.py 根本不用 softmax它逐轨迹步计算投影后向量的点积L2 归一化后即余弦相似度然后取末尾窗口的均值作为整条轨迹的分数zq F.normalize(sh(se[i:i chunk].float().to(device)), dim-1) za F.normalize(ah(ae[i:i chunk].float().to(device)), dim-1) out.append((zq * za).sum(-1).cpu()) # ... def aggregate(scores, window): tail scores[-window:] return sum(tail) / len(tail)随后best_of_n按均值分选最优候选平局按均匀期望处理。README 复现命令里也写得很清楚--n 4 --window 12每组 4 个候选、取末尾 12 步均值。官方打分 投影空间的余弦相似度时序均值既没有 logit_scale 也没有 temperature更没有 softmax。训练侧选 checkpoint 用的指标同样不是概率校准而是within_task_top1/within_task_meanranktrain/finetune.py 的_evaluate_clm即检索排序质量。所以拿 API 的 probabilities 做阈值、做 best-of-N、或直接跟官方 81.6%/87.6% 对表都是在拿两套不同的量纲硬比。想复现官方数字请用bon_eval.py的余弦相似度聚合协议。细节二嵌入与文本配方必须逐字对齐截断是最常见的隐性偏差投影头绑定的是文本如何变成 token这件事。仓库把配方写死在 train/embed_utils.py 的Recipe里状态文本走 Qwen3 的 chat template 且取尾state_ids动作/答案文本不加特殊 token 且取头text_ids(keephead)choice 任务则全部取尾。选项文本是什么就嵌什么——src/clm/schema.py 明确注释候选不添加任何前缀Noul 的默认候选是Yes. This is true: …/No. This is false: …这种模板句。任何一步改掉嵌入就变了打分就偏了。更隐蔽的是截断不一致训练侧--max-len默认 8192README 的 DeepSWE 预计算而 src/clm/server.py 的clm-serve默认--max-tokens 2048超长状态会被截断后才送编码器README 明确提示states longer than 2048 tokens are truncated要同时调大 vLLM 的--max-model-len和clm-serve --max-tokens。如果你评估的 Agent 轨迹动辄几千 token服务端默认配置下你打的分和官方在 8K 上下文下训练/评估的分根本不是同一批向量。此外 head 与编码器强绑定a head only makes sense with the encoder and pooling it was trained against——Qwen3-8B last-token pooling。换了编码器、换了池化方式、或用了clm-raw原始编码器空间的余弦scale 固定 100分数都没有可比性。细节三难负样本是强化而非起点候选集构成决定分数可比较性把第一节的消融数字翻译成复现清单就是三条硬约束难负样本要在预训练之后加不然 62.4% vs 69.2%Agent 后训练必须保留 replay不然 56.2% vs 68.5%微调时要用官方命令——注意 README 给出的 DeepSWE 微调示例是--batch 512不是默认的 2048而学习率由规则2e-3 * sqrt(1024/width) * sqrt(batch/1024)随 batch 联动train/finetune.py改 batch 不改 lr 等于同时改了两个超参python train/finetune.py --task clm --init-ckpt $(clm-download) --out-dir runs/deepswe \ --holdout-tasks heads/deepswe/heldout_tasks.json --batch 512 python evaluation/bon_eval.py --hf-dataset Contrastive-LM/deepswe-clm-embeddings-8k \ --checkpoint heads/deepswe/best_head.pt \ --tasks-file heads/deepswe/heldout_tasks.json --n 4 --window 12更进一步候选集构成本身就是评分协议的一部分官方在千级批内负样本 30M 合成难负样本下校准了 logit_scale评估时若你的候选全是易负样本或只有正样本加随机句分布会明显变钝若候选全是极难负样本top-1 会骤降但排序未必差。这与 examples/t_rex/README.md 里的做法一致——T-Rex 用物理规划器把每个动作标注为 Safe/Unsafe 再拼进 criteria 描述等于人为构造了语义相近但含正确性信息的候选池。候选描述写得好不好、有没有标注安全信息直接决定 CLM 在这组候选上的分布质量。结语打分不如官方的归因路径其实很清晰先确认你比的是余弦相似度还是 softmax 概率细节一再确认嵌入配方、截断长度与池化方式是否逐字一致细节二最后确认难负样本的时序、replay 与 batch/lr 规则是否照着官方配方来细节三。三条都对齐了CLM 才会给你它训练时所承诺的那份分数对不齐差的就不是运气而是协议。【免费下载链接】CLMContrastive Language Models (CLMs) are a new class of System One model trained with a contrastive learning objective that connects states and actions.项目地址: https://gitcode.com/gh_mirrors/clm2/CLM创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考