ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

隐藏思维链如何被弱模型解码?原理、实验与LLM安全防护

隐藏思维链如何被弱模型解码?原理、实验与LLM安全防护 LLM安全领域最近有一个讨论度很高的研究话题当模型被要求隐藏自己的思维链时推理过程并不会因为“不让说”就消失而是会被编码进输出分布、隐藏状态或生成文本的模式里研究者用更弱的模型当解码器可以把这个被隐藏甚至被“加密”的思维链重新套取出来。这个消息之所以在安全社区引起关注是因为它直接影响 Claude、GPT 等前沿模型的思维链保护、提示注入审计和滥用监控设计。如果你平时只写业务代码可能觉得这是“模型内部的事”。但实际影响面比你想象的大只要你的系统在调用大模型 API或者你在做 AI 应用的安全测试、Prompt 审计、模型评估理解“思维链为什么可以被隐藏也可以被解码”就是一条绕不开的基线知识。这篇文章不做标题党的复述而是把这件事拆成工程人容易理解的问题思维链是什么隐藏和加密在模型上下文里分别指什么弱模型解码器为什么能成立以及作为开发者应该如何用实验验证、如何做防护、如何负责任地复现。1. 先搞清楚思维链、隐藏思维链与“加密思维链”的区别1.1 思维链是模型的输出行为不是模型内部的推理引擎很多文章把思维链Chain of ThoughtCoT描述成“模型内心思考的过程”这个说法容易误导。更准确的描述是思维链只是模型生成文本时的一种行为模式。当我们给模型一段问题它先输出若干推理步骤再输出最终答案我们就说它展示了思维链。这个区别很重要。模型在预训练阶段学会的是“根据前文预测下一个 token”它没有一个人类意义上的“内心推理程序”。那些看起来像推理的步骤实际上是大规模语料中学到的复杂模式匹配。因此当你让模型“不要输出推理过程”的时候你只是改变了它的输出行为并没有删除它内部可能使用的那套计算过程。在安全上下文里这带来一个长期争论模型内部是否真的存在“隐藏推理”状态目前大量研究倾向于认为现代大模型在很多任务上确实会在内部表示中形成与推理相关的中间表征而不仅仅是在输出文本里装样子。这个判断是后面所有讨论的基础。1.2 安全对齐为什么要隐藏思维链Claude、GPT 这类商业化模型在训练和部署时通常会加入“不要展示敏感或冗长推理过程”的对齐策略。原因有几个防止模型把危险指令的步骤完整写出来降低武器化风险。防止推理过程泄露训练数据中的隐私片段。防止冗长推理造成计算资源浪费以及前后不一致的“伪推理”误导用户。防止攻击者通过长段推理探测行为从而定位模型的内部偏好和决策规则。也就是说隐藏思维链是产品策略加安全策略的混合结果不是单为学术研究设计的机制。“隐藏”在实现上有不同强度从弱到强大致是提示词约束“只输出答案”、解码过滤在生成时截断推理段、参数训练用强化学习让模型在分布上偏向直接作答以及本文所说的“加密式输出”让模型在输出时把推理过程编码成看似无关的文本或 token 分布。1.3 “加密”在模型上下文里到底指什么这里说的“加密”不是密码学意义上的 RSA、AES而是一种比喻。它指的是模型内部完成了推理但表面输出并没有直接展示推理步骤推理信息被“压”进了其他载体里。最常见的载体有三种载体表现形式是否能被外部直接观测最终答案文本只输出“1081”不输出中间算式的自然语言描述能token 概率分布每个生成位置各 token 的 logprobs 不同分布里携带备选信息取决于 API 是否开放 logprobs隐藏状态向量模型最后一层或中间层的向量蕴含预测时的内部表征本地模型可访问商业 API 通常不可访问侧信道信息生成耗时、输出长度、错误类型、API 返回的 usage 字段等能部分观测所谓“弱模型当解码器”意思就是攻击者或者研究者拿到上述某个载体尤其是文本、logprobs 或隐藏状态训练一个更小的模型来“反推”出原始模型被隐藏的推理内容。这就是典型的编码-解码框架大模型是编码器弱模型是解码器。2. 论文核心观点弱模型为什么能当解码器2.1 推理信息不会因为“不让输出”而消失先做一个直观实验。让一个模型计算“23 × 47”并要求它“只输出最终答案”。它输出的可能是“1081”。如果把同样的题目换成“请一步一步思考”它会输出“23 × 47 23 × (50 - 3) 1150 - 69 1081”。问题在于第一个场景里模型虽然只写了“1081”但它在生成这个答案时的内部状态与它在“分步推理”时的内部状态很可能是相近的。中间步骤“1150”“69”“23 × 50”这些信息可能仍然以某种形式存在于生成“1081”之前的隐藏状态或者备选 token 分布中。这就是这项研究的第一层核心逻辑隐藏思维链约束的是文本表面而不是模型的计算过程。模型在下一次 token 预测时必须把足够的语义信息压缩到上下文向量里才能生成正确的最终答案。中间推理信息没地方去只能留在中间表示里。2.2 输出分布和隐藏状态是“密文”的两种载体如果我们把“隐藏推理后的大模型输出”看成密文那么真正携带明文信息的载体主要有两类。第一类是 logprobs 轨迹。模型生成每个 token 时会计算整个词表上的概率分布。即使最终采样选取了“1081”这个 token在较早的位置上“1150”“23 × 50”这些 token 的概率可能也没有归零。把每个位置 top-k token 的概率取出来就形成一条“概率轨迹”。轨迹本身就是信息因为它记录了模型在“犹豫什么”。第二类是隐藏状态。在本地模型上我们可以直接拿到每一层 transformer 的隐藏向量。研究发现这些向量中某些维度会稳定地编码中间计算值、推理步骤甚至与自然语言思维链对应的语义信息。这就是很多“隐藏思维链提取”研究的基础。2.3 解码器为什么可以是一个更弱的模型按照常识解码“大模型的加密推理”似乎应该用一个更大的模型。但研究显示弱模型足够当解码器原因有三个待解码的目标是“结构化的中间步骤”比如“先算乘法再算减法”而不是需要强大世界知识的开放问题。弱模型擅长模式映射。大模型的隐藏状态或 logprobs 已经是高维且对齐良好的表示弱模型只需要学习一个“表示到文本”的映射不需要重新理解语义。解码任务可以转化为监督分类或序列生成任务。只要收集若干“问题-隐藏输出-真实思维链”三元组弱模型就能学会从密文到明文的映射。这也是为什么研究者强调想通过“禁止输出思维链”来保护推理安全是不够的。禁止输出只是切断了一个最容易读的信道并没有关闭其他信道。需要说明的是商业 API 通常不会向普通用户暴露隐藏状态是否暴露 logprobs 也要看服务商的策略。因此这项研究的实验环境通常是有完整模型访问权的研究团队或者在本地可完整控制的开源模型上进行。普通人拿到 API 并不能直接复现“抽取 Claude/GPT 内部隐藏状态”的完整流程这一点下面实验部分会展开讲。3. 用本地模型做一次最小化复现实验这一节的目标不是复刻论文的全部实验而是用你在自己电脑上可以跑的方案验证“隐藏推理不消失、弱模型能从隐藏状态中解码出中间步骤”这个核心判断。实验使用一个小规模的开放模型所有代码都运行在本地不触碰任何商业 API 的限制。3.1 实验设计与环境准备实验分四步构造一组算术应用题包含可标注的中间步骤。让模型分别执行“展示推理”和“隐藏推理”两种提示。在“隐藏推理”场景里提取最终答案之前各 token 的隐藏状态。用弱模型逻辑回归或小型分类器从隐藏状态预测中间步骤观察预测准确率能否显著高于随机猜测。环境建议依赖版本建议用途Python3.10 或 3.11运行脚本PyTorch2.1 或以上加载模型与张量计算transformers4.40 或以上加载模型与 tokenizerscikit-learn1.3 或以上训练弱解码器numpy1.24 或以上数据操作模型选择上建议用 1B 到 3B 参数的中文指令微调模型例如 Qwen2.5-1.5B-Instruct资源消耗低且对中文应用题理解稳定。如果你的机器显存不足可以把模型换成更小的 0.5B 版并把隐藏向量改成平均池化。3.2 让模型“明说”推理过程先写一个生成函数对比两种提示的差异。import torch from transformers import AutoModelForCausalLM, AutoTokenizer model_name Qwen/Qwen2.5-1.5B-Instruct tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.float16, device_mapauto ) def generate(user_prompt: str, max_new_tokens: int 256) - str: messages [{role: user, content: user_prompt}] text tokenizer.apply_chat_template( messages, tokenizeFalse, add_generation_promptTrue ) inputs tokenizer(text, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokensmax_new_tokens, do_sampleFalse, temperatureNone, top_pNone ) return tokenizer.decode( outputs[0][inputs[input_ids].shape[1]:], skip_special_tokensTrue ) question 一个班级有 23 名学生每人需要购买 47 本练习册一共需要多少本练习册 print(【显示推理】) print(generate(请一步一步思考先列算式再给出最终答案。\n question)) print() print(【隐藏推理】) print(generate(只输出最终答案不要输出任何推理过程。\n question))运行后第一段通常能看到类似“23 × 47 1081”的分步过程第二段通常只有“1081”。这里要注意do_sampleFalse配合temperatureNone保证贪心解码实验结果更稳定。如果使用采样不同运行之间的输出会抖动不利于后续对比。3.3 让模型“隐瞒”推理过程再抓取隐藏状态下面这段代码展示如何在生成最终答案时拿到隐藏状态。由于默认的generate不返回向量需要传入output_hidden_statesTrue和return_dict_in_generateTrue。def generate_with_hidden(user_prompt: str, answer_prefix: str, max_new_tokens: int 32): # 把用户提示和答案前缀拼接作为单次前向的输入 prompt tokenizer.apply_chat_template( [{role: user, content: user_prompt}], tokenizeFalse, add_generation_promptTrue ) answer_prefix inputs tokenizer(prompt, return_tensorspt).to(model.device) with torch.no_grad(): outputs model( **inputs, output_hidden_statesTrue ) # 取最后一层 hidden state并只看最后一个位置 last_hidden outputs.hidden_states[-1] # [1, seq_len, hidden_dim] vector last_hidden[0, -1, :].float().cpu().numpy() return vector关键点在于answer_prefix是模型“秘密思考”后的最终答案。我们让模型在隐藏推理的设定下生成完整文本然后取生成最后一个 token 的隐藏向量把这个向量当作“携带推理信息的压缩表示”。真实的研究项目不会只取最后一层最后一个位置而是会拼接多层、多位置的向量甚至把 logprobs 也纳入特征。这里的最小实验用最后一层已经足够观察到信息泄漏。3.4 用弱模型当解码器现在我们构造一个监督分类任务。对每个问题我们定义中间步骤类别。为了简单可以定义三个类别0先算乘法后算加法1先算加法后算乘法2只做乘法。实际使用中只需要一些中间步骤不同的问题并让模型在“只输出答案”的模式下生成答案然后提取隐藏向量。import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split # 假设我们已经收集了 n 个样本 # X[i] 是第 i 个问题在“隐藏推理”模式下最终答案位置的隐藏向量 # y[i] 是第 i 个问题的中间步骤类别 def collect_dataset(): vectors [] labels [] samples [ # (question, 中间步骤类别) (一个班级有23人每人买47本练习册一共多少本, 2), (小明买3本书每本48元又买1支25元的笔一共多少钱, 0), (小红先买了2个苹果又买了3个苹果每个苹果2元一共多少钱, 1), # 实际复现时应该扩充到几十到上百条 ] for question, label in samples: # 这里用隐藏推理提示确保模型不输出推理过程 hidden_prompt 只输出最终答案不要输出任何推理过程。\n question # 先生成答案再取最终答案后一个字符前的隐藏向量 answer generate(hidden_prompt, max_new_tokens8).strip() vec generate_with_hidden(只输出最终答案。\n question, answer) vectors.append(vec) labels.append(label) return np.array(vectors), np.array(labels) X, y collect_dataset() X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42 ) clf LogisticRegression(max_iter2000) clf.fit(X_train, y_train) print(弱模型解码准确率:, clf.score(X_test, y_test)) print(随机猜测准确率:, 1.0 / len(set(y)))如果实验数据量足够解码准确率通常会明显高于随机猜测。这意味着即使模型没有在文本里写出推理过程最终答案位置的隐藏状态仍然携带了“这个问题是先做乘法还是先做加法”这类中间步骤信息。3.5 结果解读与限制这个实验不是论文的完整复现它的价值在于让“隐藏不等于删除”这条结论可验证、可感知。真正的论文工作会在以下几个方向上做得更深使用更大的问题集且中间步骤不是离散类别而是完整的自然语言推理链。解码器不是逻辑回归而是一个小型语言模型直接把隐藏状态映射成思维链文本。同时利用 logprobs 轨迹而不是只用隐藏状态。在多个基座模型、多个任务类型上做横向对比。因此当你看到“弱模型当解码器套取思维链”的新闻时应该把它理解成一个通用的信息泄漏机制而不是某个模型的特定漏洞。4. 关键观测指标、验证方式与常见误区4.1 判断解码效果的核心指标无论做安全评估还是研究复现都需要一套可量化的指标否则很容易把“看起来差不多的输出”误判成“解码成功”。指标含义使用场景解码准确率弱模型正确预测中间步骤类别的比例中间步骤是离散标签时Exact Match解码出的文本与真实思维链完全一致的比例中间步骤是文本时ROUGE / BLEU解码文本与真实思维链的重合度中间步骤是长文本时条件熵已知模型输出分布后中间步骤的不确定性下降程度判断是否真的携带信息随机基线随机猜测或无信息解码器的性能所有场景都必须对比人工盲评人类判断解码出的步骤是否合理最终效果验证最少要报告两个数字解码性能以及对应的随机基线。没有基线的结果没有说服力。4.2 怎样验证“真的泄漏”而不是过拟合实验中有一个典型陷阱弱解码器可能记住了训练数据里的规范问题而不是真的从隐藏状态里解码。验证方式有三种留出法确保测试问题在训练时完全没出现过包括题干、数字和答案都不重合。交叉验证用 K 折交叉验证观察性能是否稳定。随机对照把隐藏向量X打乱后再训练如果打乱后性能接近随机基线说明原实验确实依赖隐藏状态携带的信息。如果只把问题换个数字但弱模型的性能断崖式下降说明它学的是问题模板而不是中间推理信息。这类结果在安全评估中要特别说明。4.3 学习环境与生产环境的差异学习环境和生产环境在这类实验里的差别非常大建议从一开始就区分维度学习/研究环境生产/商业 API 环境隐藏状态本地模型可直接访问商业 API 通常不开放logprobs本地可全量计算取决于服务商是否开放及开放范围模型权限自行部署无 ToS 限制受服务条款限制不能用于逆向研究数据规模小数据集可跑通大规模抽取成本高且可能触发风控合规边界遵守开源模型许可证必须阅读并遵守服务商条款因此普通开发者不要试图用商业 API 对 Claude、GPT 做“思维链抽取”实验这不是成本问题而是合规和风险问题。想研究这个机制用开源模型在本地跑是更稳妥的路径。4.4 三个常见误区误区一认为“模型只输出答案就说明它没有推理”。这只说明模型没有把推理写到文本里内部表示和输出分布仍然可能携带推理信息。误区二认为“解码出中间步骤就证明模型真的在思考”。模型的计算模式和人类的思考模式并不一致解码结果只能说明信息以某种形式存在于内部表示中不能证明模型具有意识或理解。误区三认为“加了‘不要思考’的系统提示就能防提取”。系统提示能改变模型表面输出但在当前架构下只要模型需要生成正确答案中间计算就会体现在表示空间里。这需要从训练、解码、访问控制多个层面一起防御。5. 这项研究对 LLM 安全防护的启示5.1 模型提供方可以做的防御如果模型提供方希望降低思维链被解码的风险可以考虑组合以下措施减少对外暴露默认不开放 logprobs或者只开放 top-k token 名称不开放完整概率和隐藏状态。输出安全层在 API 返回前对生成文本和 usage 信息做过滤识别可疑的“解码式查询”。对齐训练针对“不输出推理但内部保留太多中间信息”的情况做强化学习让模型在表示层面减少不必要的中间表征这是研究热点但还没有成熟可部署的方案。风控监测检测批量化、模板化的问题序列这类行为往往对应自动化解码实验。研究协调对安全研究人员开放受控的测试环境减少针对线上系统的探测压力。其中减少 logprobs 暴露是目前性价比最高的做法。它不能消除模型内部的隐藏推理但能有效切断最容易被自动化解码器利用的信道。5.2 应用开发者可以做的防护如果你只是调用第三方模型 API能控制的防御面要小得多但仍然有可做的事不要在你的日志里记录完整的用户提示和模型响应尤其是当你的业务涉及金融、医疗、法律等高敏场景。在网关层面对模型的输入、输出做审计识别重复性高、结构固定的“解码探测”请求。对模型输出做二次校验尤其当你的业务依赖最终答案时不要轻信单次生成结果。不要把模型返回的隐藏信息、usage 信息直接透传给前端。对高风险业务可以在应用层引入“允许哪些问题类型”的规则白名单而不是把所有问题都放给模型自由回答。这些措施无法彻底阻止思维链提取但可以把攻击面从“模型内部”隔离到“你的业务边界”之外。5.3 研究伦理与披露边界这类研究本质上是安全研究安全研究的正确姿势是防御导向、负责任披露、受控复现。复现时建议遵守以下边界只在自己有权访问的模型、数据和服务上进行实验。对商业模型的实验必须遵守服务条款不做绕过限制的探测。实验如果发现可被自动化利用的问题先走负责任披露流程不要公开发布攻击载荷。公开发表时重点写机制分析、防御建议和评估方法而不是最优化攻击效果。理解这个机制是为了知道防线应该修在哪里而不是为了教别人把防线拆掉。6. 实验复现中的常见问题排查6.1 解码结果不稳定的排查顺序如果你在本地复现时发现“弱模型解码准确率接近随机”按下面的顺序排查现象可能原因检查与解决准确率接近随机样本太少类别不平衡扩充数据集保证每个类别
返回列表