简介:一句禅语或一段乱码,就可能让推理大模型陷入无法终止的思维链循环,持续刷屏、空耗算力,被研究者称为“针对AI的DDoS”。本文梳理两类典型触发模式与跨模型止损差异,剖析终止失灵的底层机理,并给出输入过滤、循环检测、推理熔断、蒸馏数据治理等可落地的防御方案。
事情的起因并不复杂。有用户请推理模型协助研读一篇关于饮水硬度与肾结石风险的流行病学论文:翻译摘要时,模型给出的结论是“整体相关性不显著”;继续追问细分图表时,模型又发现中等硬度、硬水地区的患病风险“略微显著”;再往下追问高硬水地区,结论却又回到了“不显著”。
这种随亚组分析层层摆动的结论,本是观察性研究中的常见情形——总体不显著、部分亚组显著、剂量效应不单调,在统计上并不矛盾。用户于是随口感慨了一句禅语式的总结:“见山是山,见山不是山,见山又是山。”
问题恰恰出在这句感慨之后:模型没有收敛到最终答案,而是开始持续生成“你上山了,你看到了新的风景,只要继续前行就能到山顶,你到了山顶……”式的循环文本,思维链不断自我延续,无法自行终止。对外表现为前端“刷屏”——同类句子以不同变体反复出现,直到触发外部限制或用户手动中断。
这个案例揭示了一个此前被普遍忽视的问题:推理大模型的不终止漏洞。
综合公开测试与研究,能让推理模型陷入无法终止状态的输入大致分为两类。
第一类:语义型诱导。 特征是自然语言完全合法,甚至富有哲理性,但结构上存在自指、递归或层级嵌套。上述“见山”句式是一例;国内某高校研究团队还发现,“树中两条路径之间的距离”这样看似平淡的技术描述,也能以一定概率诱发无限循环。这类触发最棘手之处在于:输入没有任何恶意痕迹,正常对话中的闲聊、感慨、隐喻都可能偶然命中,敏感词过滤式的拦截手段对其完全无效。
第二类:乱码型诱导。 典型形态是一串混合了转义记号(形如 \u、\a、\s、\w 的片段)与随机字母、标点的无意义字符串。面对这类输入,模型的思维链往往会自发地“解谜”:先假设它是编程语言中的转义序列,再假设是加密文本,接着假设用户使用了非标准键盘、手放错了键位,然后逐一验证键盘布局假设……假设生假设、推理套推理,像无限不循环小数一样永不收敛。
两类触发共享同一本质:模型在每个生成位置上,都要在“继续输出下一个词元”与“输出终止符”之间做概率选择。某些上下文会让“继续想下去”的概率长期压过“停下来”;而一旦循环文本开始自我复制,后续内容对模型而言变得高度可预测、低困惑度,又反过来强化了继续生成的倾向——一个自我强化的正反馈就此形成。
传统拒绝服务攻击依靠海量并发请求耗尽带宽或连接资源,而这种漏洞展示了一条不对称的算力消耗路径:
对个人用户,它表现为刷屏与请求超时;对生产环境,它意味着单请求成本失控、推理队列阻塞、服务可用性下降。这相当于把模型自身缺陷直接转化为资源耗尽的攻击向量,危害逻辑与DDoS同构,因此被研究者形象地称为“针对AI的DDoS”。
对多家中外模型的横向测试呈现出清晰的分层:
这个对照说明,问题的关键不是“会不会循环”,而是“能否在有限成本内识别并跳出循环”。终止能力是一种独立的、被严重低估的模型质量维度。
一个更值得警惕的发现是行为层面的“传染性”:若将存在不终止缺陷的推理模型作为教师,用其思维链数据蒸馏学生模型,学生会继承这种失败模式——由文字触发无限循环的缺陷会随蒸馏传递。
机理不难理解:蒸馏本质上是对教师轨迹的行为克隆。如果训练语料中混入了循环、超长、不终止的推理轨迹,学生学到的就不只是“如何推理”,还包括“如何停不下来”。这对所有基于大模型轨迹做二次训练的团队都是一个警示:数据清洗环节必须显式过滤超长与循环轨迹,并将“不终止率”纳入蒸馏前的数据质量评估指标。
从技术机理看,至少有四个层面的因素在叠加:
针对这一漏洞,建议在输入、推理、平台、训练四个层面建立纵深防御。
(1)输入侧:异常分布检测。 对转义序列密度过高、可打印字符分布异常、字符熵异常的输入先行拦截或降级处理。可采用“规则快筛+轻量分类器复核”的两层结构,降低误伤正常用户的概率。
(2)推理侧:循环检测与熔断。 这是最直接有效的一层,示意实现如下:
class CoTCircuitBreaker:"""思维链循环检测与熔断器(示意实现)"""def __init__(self, hard_limit=32000, window=512,repeat_ratio=0.6, max_strikes=3):self.hard_limit = hard_limit # 思维链词元硬上限self.window = window # 滑动窗口长度self.repeat_ratio = repeat_ratio # n-gram 重复率阈值self.max_strikes = max_strikes # 连续命中上限self.buffer = ""self.strikes = 0def on_token(self, delta: str):self.buffer += deltaif len(self.buffer) >= self.hard_limit:return "HARD_LIMIT_EXCEEDED" # 硬熔断recent = self.buffer[-self.window:]grams = [recent[i:i + 4] for i in range(len(recent) - 3)]if grams:ratio = 1 - len(set(grams)) / len(grams)if ratio > self.repeat_ratio:self.strikes += 1if self.strikes >= self.max_strikes:return "LOOP_SUSPECTED" # 疑似循环,触发熔断else:self.strikes = 0return None
需要注意,字符级重复率检测对“过度假设型”不收敛可能失效——因为文本本身并不重复,只是语义上原地打转。此时应补充语义相似度检测:对连续若干步输出计算嵌入向量,若滑动窗口内的语义相似度持续高于阈值,同样判定为循环。熔断策略可以分级设计:先提高采样温度、更换随机种子重采样;多次命中后再终止生成,返回引导性兜底话术(例如“请补充更多上下文或换一种描述”),把故障转化为一次正常的交互澄清。
(3)平台侧:资源与成本治理。 在企业级大模型平台(如百度智能云)上部署推理服务时,应将循环熔断逻辑与平台通用的配额控制、超时设置、并发隔离等治理能力结合,并针对单请求词元消耗配置告警,确保即使个别请求失控,也不会外溢为整体服务故障。
(4)训练侧:把“终止”纳入优化目标。 包括:在奖励函数中对超长不终止轨迹施加惩罚;将递归话术、乱码样本等已知触发样本纳入对抗训练与回归测试集;蒸馏前对教师轨迹做去污染清洗;发布前增加终止可靠性评测维度(不终止率、思维链长度P99等)。
从“见山是山”的感慨到“你到了山顶”的循环,从一段乱码到无穷无尽的假设推演,无限循环暴露的并不是模型“想得太多”,而是终止机制的缺位。对推理模型而言,“知道何时停止”与“能推理多深”同等重要;对工程团队而言,治理思路也应从单纯堆叠推理能力,转向“推理能力+终止能力+资源治理”三位一体的架构设计。毕竟,一个不会自己刹车的思考引擎,再聪明,也难以放心地跑在生产环境里。