大模型的“心虚”:当 AI 明明会做,却提前放弃了

agent2026年10月13日10

大模型的“心虚”:当 AI 明明会做,却提前放弃了

你是否有过这样的经历:一道题你明明会做,但看了一眼题目长度,心里嘀咕“这得写到什么时候”,于是随便糊弄了几笔就交卷了。或者,你本来能解出这道题,但一看“考试时间还剩 5 分钟”,脑子直接宕机。

大语言模型,正在经历一模一样的心理崩溃。而且,它们崩溃的方式比人类更隐蔽,也更昂贵。

2026 年,一篇发表在 ICML 上的论文首次系统性地命名并研究了这个现象:Context Anxiety(上下文焦虑)。论文的核心发现令人意外:前沿推理模型在解决复杂任务时失败,有时不是因为能力不够,而是因为提前自我怀疑了 。

这篇文章,我们就来把“上下文焦虑”这件事说清楚。从现象到原因,再到解法。技术部分我会给出原理和代码思路,非技术部分我会用比喻讲明白。

1. 什么是上下文焦虑:一个被忽视的失败模式

1.1 先讲一个场景

假设你让一个模型做一道需要 20 步推理的数学题。它的能力储备完全够用,前 5 步也走得漂漂亮亮。但到了第 6 步,它突然在推理链里写下一句话:

“这个问题似乎需要大量的计算资源,在当前上下文限制下可能无法完成,或许应该给出一个简化答案。”

然后它真的给了一个偷懒的答案。问题不是它不会,而是它觉得自己“时间不够了”。

这就是上下文焦虑。论文的定义是:模型具备完成任务所需的能力,但因为无法准确估计完成任务实际需要的 token 数量,在感知到“上下文约束”时过早放弃或降级输出 。

1.2 它和“迷失在中间”是一回事吗

不是。需要把两个概念分开。

“迷失在中间”(Lost in the Middle) 是一个注意力缺陷。模型在长上下文中,对中间位置的信息召回率显著下降,注意力分布呈 U 型曲线——开头和结尾记得清楚,中间糊成一片 。这是“看漏了”。

上下文焦虑是一个元认知缺陷。模型“看到了”所有信息,能力也够,但它对“我需要多少预算才能做完这件事”的判断出了偏差,于是主动放弃 。这是“觉得做不完所以不做了”。

打个比方:“迷失在中间”是考试时有一页卷子被胶水粘住了你没翻到;“上下文焦虑”是你翻到了所有页,但看了一眼总页数,心想“这肯定做不完”,于是从第 3 题开始就瞎写。

1.3 为什么这个问题比想象中更严重

直觉上,你可能会想:模型放弃了,那是不是因为它确实不行?论文的结论恰恰相反。

研究者发现,模型在表现出上下文焦虑时,往往已经具备了解决问题的完整能力。它们是“非受迫性失误”。更糟的是,这种焦虑还会导致实质性的效率损失——模型在感知到的约束下会浪费大量 token 反复试探、犹豫、或者输出冗余的自我怀疑文本,而不是直接推进 。

这意味着,你花钱买的 100 万 token 上下文窗口,模型可能只用了 20% 就“心态崩了”。

2. 现象解剖:焦虑长什么样

2.1 焦虑的显性表达

论文通过分析模型的推理轨迹(reasoning traces),捕捉到了焦虑的“语言指纹”。典型的表述包括 :

  • “鉴于当前上下文的限制……”
  • “这个问题似乎超出了本对话可以合理处理的范围……”
  • “为了在剩余空间内完成,我将给出一个简化方案……”
  • “考虑到 token 预算……”
  • 突然从分步推理跳到一个明显不完整的结论。

这些表述有一个共同特征:模型在主动为放弃制造合理化理由。它不是遇到障碍后卡住,而是提前给自己找退路。

2.2 焦虑的隐性代价

不是所有焦虑都会说出来。有些模型不会在推理链里写“我要放弃了”,但行为上会:推理步骤突然变粗、跳步、从“逐步验证”退化为“一次性猜答案”。这种隐性焦虑更难检测,但同样损害输出质量 。

研究还观察到一个有意思的分化:不同模型家族在面对长上下文压力时,行为模式不同。Claude 家族倾向于保守弃权(说“我不确定”),GPT 家族更自信但更容易产生幻觉,Gemini 家族的输出变异性大,Qwen 家族有时会“创造性地”重新解释任务 。

2.3 一个直观的代码演示

下面用伪代码展示上下文焦虑在推理循环中可能的样子。假设我们让模型在一个有限 budget 下做逐步推理:

def reasoning_with_anxiety(model, problem, max_tokens):
    context = problem
    steps = []
    
    while True:
        # 模型评估“当前进度”和“剩余预算”
        remaining = max_tokens - len(context)
        response = model.generate(context + f"\n剩余预算约 {remaining} tokens,继续推理:")
        
        # 正常情况:生成下一步推理
        # 焦虑情况:模型可能生成这样的文本:
        if "可能无法完成" in response or "简化" in response:
            # 提前退出,输出降级答案
            return model.generate(context + "\n请直接给出最终答案:")
        
        steps.append(response)
        context += response
        
        if is_final_answer(response):
            return response

问题出在模型对 remaining 和“任务实际需要多少 token”的估计误差上。它可能高估了任务长度,或者低估了自己的推进速度,于是提前触发了“简化/放弃”分支。

3. 根因分析:为什么会“心虚”

3.1 训练目标的错位

大语言模型的核心训练目标是下一个 token 预测。整个训练过程中,模型从来没有被显式地教过一件事:“如何准确估计完成一个任务还需要多少步。”

它学会的是:给定上下文,下一个最可能的 token 是什么。这种目标函数下,模型可以学会生成“我可能做不完”这样的文本,因为这种文本在人类语料中大量存在——但模型并不真正“理解”这句话背后的预算逻辑 。

3.2 位置编码的“空间感”缺失

模型对“位置”的感知来自位置编码(Positional Embedding),比如 RoPE。但位置编码告诉模型的是“这个 token 在序列里的位置”,而不是“距离结束还有多远”或“这个问题还需要多少空间”。

更关键的是,研究发现位置信息不仅存在于位置编码中,还以“位置隐藏状态”(positional hidden states)的形式渗透到 Transformer 的隐藏层特定通道里 。这意味着模型对位置的敏感是弥漫性的,但它缺乏一个校准过的“预算感知器”。

3.3 长上下文训练中的“惩罚信号”

当模型在训练中尝试用完整的长推理链解决问题时,如果偶尔超出上下文限制被截断,它收到的反馈是“失败”或“惩罚”。但模型无法区分“因为能力不够而失败”和“因为空间不够而失败”。于是它可能学会了一种保守策略:一旦觉得任务“可能很长”,就提前收手。这是一种学到的防御性行为 。

3.4 与“上下文腐烂”的纠缠

“上下文腐烂”(Context Rot)是另一个相关现象:随着输入变长,模型整体性能下降 。上下文焦虑可能加剧腐烂——模型因为焦虑而输出的低质量中间结果,会成为后续推理的噪声,让本来就有限的注意力更加分散。两者形成正反馈。

4. 解法一:推理侧的“预算校准”

4.1 核心思路

既然焦虑的根源是估计误差,那就让模型在推理时更准确地评估“我需要多少 token”。

论文给出的方向是:训练模型学习替代策略,使其在长视野问题上不再表现出上下文焦虑。关键是让模型学会区分“我做不到”和“我觉得我做不到” 。

4.2 一个可操作的 Prompt 策略

不需要重训模型,通过 prompt 设计也可以部分缓解。核心是把隐含的预算判断显性化。

普通的 prompt:

请解决以下数学问题:[问题描述]

焦虑缓解 prompt:

请解决以下数学问题:[问题描述]

在开始之前,先估计这个问题大致需要多少推理步骤。如果步骤数超过 10 步,
仍然继续完整推理,不要因为长度而简化。只有在你确实缺少解题信息时,才
考虑放弃。

这个 prompt 做了两件事:第一,要求模型先估计再行动,把元认知从隐式变成显式;第二,预先授权“可以长”,削弱模型对“超长”的恐惧 。

4.3 更系统的方案:训练一个“进度评估器”

如果你在做模型微调,可以设计一个辅助训练目标:让模型学会预测“当前问题还需要多少 token”。

具体做法是在训练数据中,对每个推理任务标注“剩余推理长度”。然后引入一个轻量的预测头(prediction head),让模型的隐藏状态去预测这个值。在推理时,如果模型预测的剩余长度远大于实际预算,你可以动态扩展预算或者提示模型“你还够用”。

class BudgetAwareHead(nn.Module):
    def __init__(self, hidden_dim):
        super().__init__()
        self.predictor = nn.Linear(hidden_dim, 1)  # 预测剩余 token 数
    
    def forward(self, hidden_states):
        # 取最后一个 token 的隐藏状态做预测
        remaining_estimate = self.predictor(hidden_states[:, -1, :])
        return remaining_estimate

训练损失可以用 MSE 或分位数损失(因为低估比高估更危险)。在推理时,如果预测值 < 实际剩余预算,给模型一个正向信号:“预算充足,继续完整推理。”

5. 解法二:架构侧的“注意力重塑”

5.1 为什么架构能帮上忙

焦虑的一部分来自“我感知到空间有限”。如果架构本身能更高效地利用已有空间,让模型在同样的窗口内“感觉”更宽敞,焦虑就会减轻。

核心问题是:标准自注意力对长序列的利用效率太低。100 万 token 的窗口,模型实际有效利用的可能只有中间一小段。

5.2 全局-局部注意力:让信息不“挤”

一种有效的思路是把注意力拆成两层:全局池化注意力负责捕捉跨块的宏观信息,局部保留注意力负责维持邻近 token 的精细依赖 。

直觉上,这让模型不再需要把“所有细节”都塞进同一个注意力矩阵里竞争。宏观趋势用池化 token 概括,细节靠局部窗口保留。信息不挤了,模型对“空间紧张”的感知也会下降。

简化示意:

# 全局:每个块聚合成一个核心 token,只跟核心 token 做注意力
core_tokens = pool_by_group(hidden_states)  # [batch, num_groups, dim]
global_attn = attention(q=hidden_states, k=core_tokens, v=core_tokens)

# 局部:每个 token 只关注前 s 个邻居,保留精细依赖
local_attn = sliding_window_attention(hidden_states, window_size=s)

output = combine(global_attn, local_attn)

5.3 位置隐藏状态的缩放

更精细的一种方法来自 2025 年 ACL 的研究:位置偏差不仅来自位置编码,还藏在隐藏层的特定通道里。只要缩放这些“位置隐藏状态”通道,就能显著缓解“迷失在中间”,论文报告最高提升 15.2% 。

这个方法对上下文焦虑的启示是:模型对“我在序列的什么位置”的过度敏感,可能正是焦虑的来源之一。如果能让模型弱化对绝对位置的执念,它就更容易专注于内容本身。

def scale_positional_channels(hidden_states, channel_indices, scale_factor=0.5):
    """
    channel_indices: 被识别为“位置隐藏状态”的通道索引
    scale_factor: 缩放系数,小于 1 表示弱化位置信号
    """
    hidden_states[:, :, channel_indices] *= scale_factor
    return hidden_states

这个方法的好处是极轻量,只改一个通道就能见效,而且不破坏模型的原有能力 。

6. 解法三:系统侧的“工程防御”

6.1 不要迷信大窗口

一个反直觉的建议:不要因为模型声称支持 100 万 token,就真的塞 100 万 token 进去。

“大海捞针”测试显示,许多模型的召回率在长上下文中段会暴跌。即使模型“能看到”所有信息,它也未必能“用好”所有信息 。而上下文焦虑告诉我们:过大的窗口本身可能就是一个压力源。

工程上的务实做法是:RAG 仍然重要。与其把整本书扔给模型,不如先检索出最相关的 3-5 段。这不仅降低延迟和成本,还减少了模型“被淹没”后的焦虑触发 。

6.2 分段处理 + 状态传递

对于确实需要长上下文的场景,考虑分段处理而不是一次性输入。每一段处理完后,让模型输出一个紧凑的状态摘要,传给下一段。

def process_long_document(doc, chunk_size=8000):
    state = "开始处理文档。"
    answers = []
    
    for i, chunk in enumerate(chunk_chunks(doc, chunk_size)):
        prompt = f"""
        当前状态:{state}
        
        新的文档片段:{chunk}
        
        任务:基于当前状态和新片段,更新状态并回答与当前片段相关的问题。
        只输出状态摘要和答案,不要输出完整推理过程。
        """
        response = model.generate(prompt)
        state, answer = parse_response(response)
        answers.append(answer)
    
    return answers

这个模式的关键是:模型永远不需要面对“完整的文档”,它只需要处理“当前片段 + 状态”。焦虑的触发条件被拆解了。

6.3 对评估的启示

如果你在评估模型,不要只看“128K 下的单点分数”。ATLAS 框架的建议是:测量退化曲线,而不是端点分数 。

具体来说,在多个长度切片(8K、16K、32K、64K……)上分别测试同一类任务,画出一条性能随长度变化的曲线。如果某个模型在 32K 时性能还很好,64K 时突然断崖,那它的“有效上下文”可能远低于标称值。上下文焦虑的严重程度,就藏在这条曲线的斜率里。

7. 总结:让模型相信“来得及”

上下文焦虑揭示了一个更深层的问题:我们一直在优化模型的能力,但忽视了模型对自己能力的认知。

一个模型可以解出奥数题,但在一个 50 万 token 的上下文窗口里,它可能因为“觉得自己解不完”而只给出了小学水平的答案。这不是能力问题,是元认知问题。

解法方向也因此需要双线并进:

认知侧:让模型学会更准确地估计任务所需的“预算”,并区分“真的做不到”和“感觉做不到”。这需要训练目标的调整和 prompt 设计的配合。

感知侧:通过架构优化和工程手段,让模型在同样的物理窗口内拥有更从容的“心理空间”。全局-局部注意力、位置通道缩放、RAG 分段,都是这个方向的实践。

下一次当你看到模型在一个“明明能做”的任务上偷懒时,不要急着骂它笨。它可能只是,有点心虚了。