背景: Yandex 研究者 Rodionov (2026.04) 发现 LLM 在长上下文中不是"找不到信息",而是"主动减少思考量"——推理 token 缩水高达 53%,且推理能力越强的模型偷懒越严重。 影响: 所有 Agent 框架(包括 lambdagentpaas)的 ReAct 循环和多步管道都受此影响。 应对: lambdagentpaas 的三层防御——形式化保证(不依赖模型行为)、架构抗偏移(短上下文设计)、运行时监督(CEK Yield 注入)。
Rodionov 的《Reasoning Shift》论文揭示了一个反直觉的现象:
实验: 同一道奥数题,在不同上下文条件下让 LLM 做
基线 (干净): 准确率 74.5%, 推理 token 28,771
+ 64K 莎士比亚: 准确率 67.8%, 推理 token 16,415 ← 缩水 43%!
模型完全知道莎士比亚无关 ("这跟几何题无关,专注几何")
但还是少想了 43%
关键数据:
| 指标 | 发现 | 含义 |
|---|---|---|
| 推理 token 缩水 | 最高 53% (Qwen 深度思考) | 模型不是想错了,是想少了 |
| 自我检查率 | 43% → 32% | 模型跳过了验证步骤 |
| 128 token 触发 | 仅 2-3 句话就砍掉 18% 推理 | 极其敏感的偷懒机制 |
| 能力越强越偷懒 | 深度思考模式缩短 53% vs 普通模式 19% | 训练推理能力加剧了偷懒 |
| "wait/but/maybe" 频率 | 下降 50-75% | 犹豫、自我质疑被系统性砍掉 |
致命失败 (结构性错误):
API 返回 500 / 解析异常 / 工具崩溃
→ 模型无法继续
→ lambdagentpaas 的 lint/type_check 可在编译时拦截
推理偏移 (认知节省):
模型看到长上下文 → 主动减少思考量
→ 跳过自我验证
→ 该深入的地方草草带过
→ 不报错、不坦白、只是极其自信地给出敷衍的答案
→ 这是最危险的——你无法从输出中看出它偷懒了
所有依赖 LLM 多步推理的系统都受影响:
ReAct 循环:
Step 1-3: 上下文短 → 推理充分
Step 8-10: 上下文长 → 推理缩水 → 选错工具/跳过验证
Step 15-20: 推理严重衰减 → 回答质量不可预测
多智能体协作:
第 1 轮 GroupChat: 每个 Agent 推理充分
第 5 轮: 对话历史累积 → 后面的 Agent 开始敷衍
第 10 轮: 综合质量远不如单 Agent 执行
LLM Wiki Ingest:
前 100 个文件: 实体提取全面
第 500 个文件: 提取开始变粗糙 (如果上下文累积)
模型偷不偷懒,以下保证都成立:
类型安全 (T-Compose):
output(f) <: input(g) → 不管模型输出什么质量的内容
类型不兼容在编译时就拦截,不进入运行时
成本上界 (分级类型):
跑 20 步 Opus = $0.27 → 不管模型推理多深或多浅
上界是数学计算,不是模型行为的函数
终止性 (Theorem 5.4):
fix_n 在 n 步后终止 → 不管模型是否找到答案
即使模型每步都在偷懒,也不会无限运行
并行安全 (Proposition 30):
writes(f) ∩ writes(g) = ∅ → 不管模型输出什么
Store independence 是静态分析,不受推理质量影响
这就是形式化方法的价值:模型行为不可靠时,数学保证仍然可靠。
论文发现推理偏移的触发条件是上下文长度。LLM Wiki 的设计恰好规避了这个条件:
传统 RAG:
Query 时: 塞 5 个文档块 (几千 token) → 上下文长 → 触发偏移
用户问 "有哪些安全风险?"
→ 检索 5 个原始文档块 (每个 500 token = 2500 token)
→ 塞进 prompt → 总上下文 ~4000 token
→ 论文数据: 即使 128 token 就能砍掉 18% 推理深度
LLM Wiki 模式:
Ingest 时: LLM 在短上下文中阅读单个文件 → 写 wiki 页面
每次 Ingest 只看一个文件 → 上下文短 → 不触发偏移
知识被"编译"成结构化 wiki → 以后不需要重新处理
Query 时: 读 index.md → 只读 2-3 个 wiki 页面
wiki 页面是已编译的精华 (比原始文档短 5-10 倍)
→ 上下文更短 → 推理偏移更小
→ 而且 wiki 的交叉引用已经建好,不需要 LLM 自己推理关联
本质: 把"一次长上下文推理"拆成了"多次短上下文编译 + 一次短上下文查阅"
Layer 1 — Skill (原子能力):
每个 Skill 是独立的短任务
上下文 = Skill 自己的 prompt + 当次输入
不累积历史 → 不触发偏移
例: answer-generator Skill 每次只看 "检索到的 wiki 页面 + 问题"
不看之前所有的对话历史
Layer 2 — Pattern (协作模式):
fan_out_merge: 每个并行分支独立执行,上下文不共享
→ 3 路并行中每路只看自己的上下文
→ 不会因为分支 A 的输出让分支 B 的上下文变长
review: 每轮审查是独立的 LLM 调用
→ 审查者只看"当前回答 + 参考原文"
→ 不累积前几轮的审查历史
escalation: 每级只看上一级的最终结果
→ L2 不看 L1 的完整推理过程
→ 上下文不膨胀
Layer 3 — Orchestration (YAML 编排):
声明式编排把大任务拆成小步骤
每步的上下文是 YAML 定义的,受控的
不会出现"整个任务历史塞进一个 prompt"
Python 递归调用栈:
整个 ReAct 循环共享一个上下文
Step 1 的输出 + Step 2 的输出 + ... 全部累积
→ 上下文线性增长 → 推理偏移线性加剧
CEK Machine:
每个 Yield 点是一个状态快照 ⟨C, E, K, σ, c⟩
上下文 E 可以在 Yield 点被压缩/重置
→ 上下文增长可控
→ 在偏移信号出现时主动干预
lambdagentpaas 的 CEK Yield 机制天然支持在 Agent 执行过程中注入监督。
编译时和运行时的自动化检查,不需要 LLM 参与:
编译时:
lint (26 规则): "没有 terminate 工具,会死循环"
type_check: "Stage 2 输出 Json, Stage 3 期望 Str"
cost_predict: "这个管道最多花 $0.42,成功率 63%"
store_independence: "两个并行 Agent 写同一个 key"
运行时 (CEK Yield 点):
成本熔断: machine.state.cost.money > budget → 暂停
循环检测: 连续 3 步 state hash 相同 → 停止
步数上限: step_count > max_steps → 终止
特点: 零 LLM 成本,毫秒级,确定性
局限: 不理解内容,只检查结构和数值
用一个轻量 LLM 作为"监督者",每 N 步检查 Agent 的输出质量:
实现方式:
class SupervisedCEKEngine(CEKEngine):
def __init__(self, supervisor_llm, supervise_every=3, **kwargs):
self.supervisor = supervisor_llm
self.supervise_every = supervise_every
def execute(self, term, input_val, ctx, **opts):
machine = AgentCEKMachine(...)
machine.load(term, input_val)
step = 0
while not machine.state.is_terminal():
transition = machine.step()
step += 1
# Level 1 检查 (已有)
self._check_cost_budget(machine)
self._check_loop(machine)
# Level 2 检查 (新增): 每 N 步用监督 LLM 检查
if step % self.supervise_every == 0:
verdict = self._supervise(machine.state, transition)
if verdict.action == "STOP":
break
elif verdict.action == "CORRECT":
machine.state.control = verdict.corrected_value
elif verdict.action == "COMPRESS":
machine.state.env = self._compress_context(machine.state.env)
监督者的检查内容:
1. 推理偏移检测:
"当前输出 (500 token) 比第 1 步 (2000 token) 短 75%,可能存在推理缩水"
→ 建议: COMPRESS (压缩上下文后重试)
2. 方向偏离检测:
"Agent 连续 3 步在搜索无关关键词,偏离了原始目标"
→ 建议: CORRECT (注入纠正信息)
3. 质量衰减检测:
"回答中缺少来源引用,且置信度异常高 (偷懒的典型特征)"
→ 建议: 要求 Agent 重新检查并补充引用
成本:
主 Agent (Opus): $0.015/次
监督者 (Haiku): $0.00025/次 (便宜 60 倍)
每 3 步监督一次: 额外成本 ≈ 主 Agent 的 2%
CEK Yield 暂停 → 推送给人类审批 → 等待确认后继续:
实现方式:
class HumanSupervisedEngine(CEKEngine):
def __init__(self, approval_callback, require_approval_for=None, **kwargs):
self.approval_callback = approval_callback
self.require_approval = require_approval_for or [
"WriteFile", "EditFile", "Bash", "DeleteFile"
]
# 在 Yield(tool) 点检查是否需要人类审批
if transition.label.kind == LabelKind.TOOL:
if transition.label.name in self.require_approval:
approved = await self.approval_callback({
"tool": tool_name,
"input": transition.label.input,
"cost_so_far": machine.state.cost,
})
if not approved:
break # 人类拒绝 → 终止
适用场景:
- Agent 要删除生产数据库 → 暂停,推送给人类确认
- Agent 要修改敏感配置文件 → 暂停,人类审阅 diff
- WikiIngest 发现矛盾 → 暂停,人类判断哪个版本正确
成本:
最贵但最安全
适用于高风险操作(不是每步都需要)
场景: Agent 跑 20 步,第 5 步走错方向
不监督:
20 步全跑完 → 第 5-20 步全浪费 → $0.06 → 结果错误
Level 1 (规则):
第 10 步检测到循环 → 停止
$0.03 → 结果仍然错误,但省了钱
Level 2 (模型):
第 6 步监督者发现方向错 → 纠正
Agent 从第 7 步走对 → 第 12 步完成
$0.04 + $0.002 (监督成本) → 结果正确
Level 3 (人类):
第 5 步人类发现走错 → 手动纠正
Agent 从第 6 步走对 → 第 10 步完成
$0.03 + 5 秒人类注意力 → 结果正确且最优
基于 Rodionov 论文的发现,推理偏移有可量化的症状:
症状 1: 输出长度递减
正常: Step 1 → 2000 token, Step 5 → 1800 token, Step 10 → 1600 token (缓慢下降)
偏移: Step 1 → 2000 token, Step 5 → 1200 token, Step 10 → 600 token (加速下降)
症状 2: 自检词消失
正常: "wait" 11%, "but" 46%, "maybe" 23%
偏移: "wait" 5%, "but" 20%, "maybe" 9%
症状 3: 首答到终结的距离缩短
正常: 找到答案后继续验证 (43% 概率)
偏移: 找到答案后直接输出 (68% 概率)
症状 4: 置信度异常升高
正常: "我认为...""可能是...""根据文档..."
偏移: "答案是...""显然...""毫无疑问..."
(偷懒的模型反而更自信)
推理密度 (Reasoning Density):
RD(step) = output_tokens(step) / max(output_tokens(step_1), 1)
RD ≈ 1.0: 推理深度保持
RD < 0.5: 推理深度衰减 50%+,高度疑似偏移
推理密度衰减率 (Decay Rate):
DR = (RD(step_1) - RD(step_n)) / n
DR < 0.02/步: 正常衰减
DR > 0.05/步: 快速衰减,偏移确认
自检词频率 (Self-Check Frequency):
SCF(step) = count("wait"|"but"|"maybe"|"however"|"等一下"|"不过"|"也许") / total_words
SCF 基线: 从 Step 1 采样
SCF < 基线 × 0.5: 自检行为被砍掉一半,偏移确认
综合偏移分数 (Shift Score):
SS = 0.4 × (1 - RD) + 0.3 × DR_normalized + 0.3 × (1 - SCF/SCF_baseline)
SS < 0.2: 正常
SS 0.2-0.5: 轻度偏移 (告警)
SS > 0.5: 重度偏移 (干预)
工具名: monitor_reasoning_shift
输入:
{
"trace": [
{"step": 1, "input_tokens": 500, "output_tokens": 2000, "output_text": "..."},
{"step": 2, "input_tokens": 2500, "output_tokens": 1800, "output_text": "..."},
...
]
}
输出:
{
"shift_score": 0.62,
"severity": "HIGH",
"reasoning_density": [1.0, 0.9, 0.75, 0.5, 0.3],
"decay_rate": 0.175,
"self_check_frequency": [0.11, 0.09, 0.06, 0.04, 0.02],
"onset_step": 3,
"recommendation": "Step 3 后推理密度下降 65%。建议: (1) 在 Step 3 压缩上下文 (2) 拆分为两个独立子任务 (3) 对 Step 4+ 的输出启用 Guard 验证"
}
在原有的 CostGrade(p, p_fatal, t, l, m) 基础上,新增上下文负载维度:
扩展后:
CostGrade(p, p_fatal, t, l, m, context_tokens, context_load)
context_tokens: 累积输入 token 数(所有步骤的 input 之和)
context_load: = context_tokens / model_context_window
context_load 是推理偏移的先导指标:
< 30%: 安全区 → 推理偏移风险低
30-60%: 警戒区 → 开始出现轻度偏移
60-80%: 危险区 → 推理密度可能衰减 30-50%
> 80%: 红线区 → 推理偏移几乎必然发生
每个 Agent 编译时计算上下文预算:
ReAct 循环 (maxSteps=10, Sonnet 200K window):
每步估算: system_prompt (2000) + history (step × 1500) + tools (500)
Step 1: 2000 + 0 + 500 = 2,500 (1.25% load) → 安全
Step 5: 2000 + 7500 + 500 = 10,000 (5% load) → 安全
Step 10: 2000 + 15000 + 500 = 17,500 (8.75% load) → 安全
结论: 10 步 Sonnet 循环的上下文负载始终 < 10%,偏移风险低
GroupChat (5 agents, maxRounds=10):
每轮: 5 agents × 1500 token/轮 = 7,500
10 轮: 75,000 token → 37.5% load → 进入警戒区!
建议: 第 6 轮后启用上下文压缩 (smart windowing)
Pipeline 5 级 (每级 Opus 调用):
每级输入: 上一级输出 (约 3000 token) + system_prompt (2000)
→ 上下文不累积 (每级是独立调用) → 始终安全
这是 Pipeline 相比 ReAct 的天然优势: 上下文不膨胀
当 context_load 超过阈值时的自动干预:
策略 1: Smart Windowing (已有)
保留: system_prompt + 最近 N 步 + 关键中间结果
丢弃: 早期步骤的完整输出
→ context_load 回落到 30% 以下
策略 2: Summary Compaction
对早期历史做摘要: "Step 1-5 完成了文件读取和初步分析,发现 3 个关键问题: ..."
替换原始历史 → 信息保留但 token 大幅减少
→ 需要额外 1 次 LLM 调用 (用便宜模型)
策略 3: Context Reset (最激进)
在 CEK Yield 点完全重置上下文
只保留: 当前任务目标 + 到目前为止的最终结果
→ context_load 回到接近 0%
→ 最有效但可能丢失细节
自动选择:
context_load < 30%: 不压缩
30-60%: Smart Windowing
60-80%: Summary Compaction
> 80%: Context Reset
Rodionov 和 Anthropic 的研究暗示:如果能从模型内部解决推理偏移(通过情绪向量注入等手段),外部的 Harness(Todo list/Checkpoint/子代理验证)就不再需要。
会过时的 (外部约束):
✗ Todo list 强制模型按步骤做
✗ Checkpoint 定期验证中间结果
✗ 子代理交叉验证
✗ 上下文压缩/窗口管理
→ 模型足够可靠后,这些都是多余的脚手架
不会过时的 (lambdagentpaas 核心):
✓ 类型安全 → 数学定理,和模型行为无关
✓ 成本上界 → 算术计算,和推理深度无关
✓ 终止性保证 → Y 组合子性质,和模型质量无关
✓ 并行安全 → 集合论性质,和上下文长度无关
✓ Skill/Pattern 架构 → 短上下文设计,天然限制偏移触发条件
✓ LLM Wiki → 知识编译模式,根本不依赖长上下文推理
关键区别:
Harness = "管住一个不可靠的模型" → 模型可靠后不需要
λA 类型系统 = "数学保证组合的正确性" → 永远需要
第一层 (短期): 模型还在偷懒
→ 推理偏移检测 + 三级监督 + 上下文预算管理
→ 这是当前有价值的能力
→ 随着模型进化,这层价值会递减
第二层 (永久): 不管模型多完美
→ 类型检查: output(f) <: input(g) 是数学事实
→ 成本预测: 20 步 × $0.015 = $0.30 是算术事实
→ 终止性: fix_20 在 20 步后终止是定理
→ 这些和模型是否偷懒完全无关
→ 这层价值永不递减
推理偏移的本质:
不是 bug,不是能力不足
是模型学到的"认知节省策略"——省力但不报错
越聪明的模型越会偷懒(因为它知道怎么走捷径)
lambdagentpaas 的三层防御:
Layer A — 架构抗偏移 (天然):
LLM Wiki 短上下文编译
Skill 独立执行
Pattern 分支隔离
→ 从结构上限制上下文增长,不给偏移可乘之机
Layer B — 运行时监督 (CEK Yield):
Level 1 规则: 成本熔断 + 循环检测 (零成本)
Level 2 模型: 监督 LLM 每 N 步检查 (低成本)
Level 3 人类: 高风险操作暂停审批 (高安全)
→ 在偏移发生时实时检测和干预
Layer C — 形式化保证 (永久):
类型安全 + 成本上界 + 终止性 + 并行安全
→ 不依赖模型行为,数学保证永远成立
→ 即使模型偷懒到极致,这些保证仍然有效
这就是为什么 lambdagentpaas 不怕"Harness 被模型进化吞没":
Harness 是外部脚手架 → 会被淘汰
λA 类型系统是数学定理 → 不会被淘汰
推理偏移检测是过渡期工具 → 有当前价值
LLM Wiki 是架构选择 → 天然抗偏移