VLA安全对齐:约束学习方法让具身智能机器人更可靠
最近在整理具身智能方向的论文连着读了好几篇视觉-语言-动作模型Vision-Language-Action ModelVLA的工作越读越觉得一个矛盾特别突出模型的能力涨得飞快但让人放心程度完全没跟上。VLA 模型说白了就是把相机画面和自然语言指令同时编码、直接输出机器人底层动作或者动作 token的端到端模型典型代表有 RT-2、OpenVLA、π0 这些。能力确实强零样本让他开个抽屉、拿个杯子都能干。但问题在于这种模型本质上是“从数据里拟合出来的概率分布”训练数据里没见过的情况一出现策略就可能走样你要是真的把它部署到物理世界里那就不只是输出一段不合适文本的问题了而是机械臂真会撞上去、真会把东西碰倒、真会伤到人。这篇《Towards Safety Alignment of Vision-Language-Action Model via Constrained Learning》就是冲这个痛点来的。它讨论的不是怎么把模型变强而是怎么把模型变“安全可控”。核心思想用一句话概括把大模型时代流行的 alignment对齐思想从“让模型更符合人类偏好”升级成“带约束的学习”Constrained Learning让模型在完成任务的同时把安全风险的期望压到一个可接受的阈值以内。这个方向对任何想真正落地 VLA 的人都值得关注。我自己偏算法工程背景读论文的习惯是先啃动机和方法主干再看实验设计最后自己动手推一遍关键公式。下面这篇笔记就是按这个路子写的适合正在做机器人策略学习、VLA 微调或者准备把大模型 alignment 方法迁移到具身智能场景的读者。基础概念我会顺带解释新手也能看清关键脉络。1. VLA 为什么需要独立的安全对齐方案1.1 物理后果的不可逆性决定了它和大模型对齐不是一回事大模型的对齐主要防的是“模型胡说八道”或者“生成违背价值观的内容”。文本输出去错了最多是被用户举报、被运营删帖损失的是信任和流量。但 VLA 输出的是动作是直接作用在物理世界里的指令。一个错误的动作 token可能在几十毫秒内就让机械臂以 2m/s 的速度撞向桌面上的玻璃器皿。物理后果不可逆这是 VLA 安全问题和纯语言模型安全问题的本质区别。另一个不太容易被注意的点是VLA 的“错误模式”更多样。语言模型出错是语义层面的偏差和幻觉VLA 除了语义偏差理解错指令还有感知偏差看错物体位置、动力学偏差同样的动作在不同负载下结果不同、分布外偏差场景没见过等。这意味着安全对齐不能只盯着模型的“意图”还要盯着“动作本身是否超限”“是否碰撞”“是否违反物理约束”。从这个角度看VLA 的安全对齐更像传统机器人学里的安全控制问题而不是纯粹的大模型对齐问题。1.2 直接套 RLHF/DPO会碰到三道墙很多人第一反应是大模型不是有 RLHF、DPO 现成的 alignment 工具吗拿过来用在 VLA 上不就行了理论上可行实际做起来会发现三道墙。第一道墙是目标错位。RLHF 本质上是在优化“人类偏好”的平均值它追求的是大多数情况下让打分的人满意。但安全不是期望优化问题安全是尾部风险问题。一个策略哪怕在 99% 的场景下都表现得非常得体只要有 1% 的概率做出危险动作那这个系统在生产环境里就是不可接受的。平均值优化天然对极端事件不敏感RLHF 能把“平均偏好”拉高却未必能把“最坏情况”压住。第二道墙是数据成本。RLHF 需要大量人类偏好标注而机器人动作层面的安全偏好标注远比文本难收集。文本偏好标注一个标注员一天可以标几千条机器人安全偏好的判定往往要结合场景、轨迹、物体状态需要看视频甚至实地观察一天能标几十条就不错了。数据量上不去偏好模型就学不准确。第三道墙是 reward hacking 在物理世界会被放大。RLHF 训练中模型经常能找到奖励模型的盲区用不符合人类预期的方式刷高分。语言模型刷分最多输出一些别扭的、格式化的文本物理世界的 reward hacking 是策略发现一个能骗过奖励函数的动作模式而这个模式在真实环境里可能是极其危险的路径规划。所以 VLA 的安全问题不能简单当成“偏好优化”来做它需要的是显式的、可度量的、可约束的“安全指标”。1.3 Constrained Learning 给了一个更工程化的框架这篇论文用的框架是约束学习它在数学上把事情说得很清楚任务目标和安全要求不是一起被揉进一个标量奖励里而是拆成“最大化任务回报”和“满足安全约束”两个独立目标。用公式表达VLA 的策略网络 π_θ 接收视觉观测 v 和语言指令 l输出动作 a我们希望max E[ R(τ) ] 使得 E[ C(τ) ] ≤ d其中 R(τ) 是任务回报比如任务成功得 1 分C(τ) 是安全代价比如一次违反安全规则记 1d 是这个安全约束的阈值表示“平均每个 episode 允许的安全违规上限”。当 d 取得很小比如 0.01就相当于要求模型每 100 个 episode 平均最多违规一次。这个框架的价值在于它把“安全”从一个模糊的口号变成了一个可调参的工程目标。不再是模型打好分就行而是必须同时满足约束条件否则就是不合格再怎么强调能力也没用。这就是约束学习和传统 reward 融合的本质区别。2. 方法拆解约束学习到底怎么做安全对齐2.1 拉格朗日松弛把约束问题变成一个轮流博弈直接求解带约束的强化学习问题很麻烦标准的做法是拉格朗日松弛Lagrangian Relaxation。具体来说把约束条件乘上一个拉格朗日乘子 λ加到目标函数上L(θ, λ) E[ R(τ) ] - λ · ( E[ C(τ) ] - d )注意 λ 永远大于等于 0。这个式子的博弈含义很直观策略网络 θ 想让目标函数变大所以它会尽量提高任务回报而 E[C] - d 一旦大于 0也就是安全违规超标了λ 这个正系数就会放大惩罚迫使策略减少违规。反过来λ 自己也在学习如果约束被违反得厉害λ 就增大惩罚变重如果约束一直满足λ 就减小训练重心回到任务表现上。实际训练里策略和 λ 是交替更新的这就是所谓的双循环double-loop训练。内循环更新策略网络参数 θ外循环更新乘子 λ。λ 的更新公式通常是λ ← max(0, λ α_λ · ( E[ C(τ) ] - d ) )α_λ 是乘子的学习率。这个式子写出来就非常直观了当平均安全代价超过阈值 dλ 上升低于阈值λ 下降但由于 max(0, ·) 的限制不会变成负数。整个机制像一个自动调节的“安全罚分阀门”不需要手工去猜到底该给安全惩罚加多少倍权重。2.2 最关键的工程环节安全代价函数 C 怎么设计读这类论文如果只盯着公式看会错过真正的重点。约束学习里最容易翻车的地方不是优化算法而是安全代价函数 C(τ) 的定义。C 定义得不对后面所有数学都白搭。我从工程角度把 C 的设计路径分成三种实际项目里经常混着用第一种是规则驱动型。用程序判断动作是否越界比如机械臂的末端执行器是否进入禁止区域、关节速度是否超限、接触力是否超过了安全阈值。这类 C 的好处是可解释性强、部署简单坏处是覆盖不了复杂语义场景。比如“不要把红酒杯碰倒”这种约束你很难用几条几何规则完全刻画清楚。第二种是学习型安全模型。用一个分类器或者打分模型去估计“某个状态这个动作安不安全”训练数据来自人类标注的危险场景或者仿真里的碰撞检测信号。这类 C 能覆盖复杂场景但容易受到分布外问题的影响评判器本身没见过的新场景时它的判断可能并不可靠。第三种是把大模型当裁判。用 VLM 来给动作序列打安全分这个方向近年来很热门因为 VLM 有较强的语义理解能力。缺点也很明显慢、贵、不稳定而且大模型本身也有不可靠的问题。放在约束学习的框架里裁判模型的不稳定会被 λ 的更新一起放大。实际论文里最常见的设计是“规则为主、学习模型为辅”的混合方案。我自己的体会是C 的定义一定要和最终评估指标闭环如果评估阶段用碰撞检测器训练阶段的安全代价函数最好就包含碰撞信号否则训练出来的“安全”是裁判眼里定义的不是评估指标体系里的安全。2.3 整体训练流程预训练、对齐、再评估从这类工作通常的流程来看VLA 的安全对齐可以拆成三个阶段。第一阶段是通用预训练用大量演示数据做行为克隆让模型具备基本的多模态理解能力和动作生成能力。这个阶段不考虑安全约束目的是让模型“会的多”。第二阶段是安全对齐用约束学习微调模型。这一步可以在仿真环境里用在线强化学习做也可以拿离线数据做类离线 RL 的约束优化。在线 RL 的好处是策略能主动探索到危险区域对约束的估计更准确坏处是训练成本高而且仿真和现实有 gap。离线方案成本低但对数据的覆盖度要求极高危险样本如果本身在数据集里很少模型很难学会规避。第三阶段是评估迭代。对齐不是一次性的动作需要在验证集上反复算“成功率”和“违规率”如果违规率没压到阈值以下可能需要加数据、调阈值或者换安全代价函数。我见过不少团队在这个阶段花了 80% 的功夫因为训练阶段的问题很多时候要到评估阶段才暴露出来。3. 实操视角复现这类方法时最容易踩的坑3.1 拉格朗日乘子不是万能钥匙λ 震荡会要命很多人头一次跑约束学习以为有拉格朗日公式就万事大吉结果训练曲线震荡得怀疑人生。这在双循环优化里是常态原因也很好理解λ 的更新步长 α_λ 和策略更新步长之间如果没调好两个循环就变成在互相“对抗”而不是“协作”。实操里我有几个建议。第一λ 的更新要记得裁剪别让它一下涨到离谱稳定在某个范围内才能让策略慢慢适应。第二λ 的学习率一般比策略的学习率大一个量级因为策略需要时间去收敛乘子应该先快速响应违规程度。第三对 λ 做平滑用滑动平均而不是原始梯度直接更新能明显减少震荡。这些细节论文里通常只提一句“we use clipping”但真正跑实验的人才知道这一步有多关键。3.2 阈值 d 的设定别拍脑袋要用数据标定d 是“平均每个 episode 允许的违规上限”这个值设多大直接决定了模型的保守程度。设太大模型会在意安全但更在意任务成功危险动作还是不少设太小模型会为了安全啥都不干任务成功率崩盘。我的建议是先收集一小批 baseline 模型的评估数据统计当前违规率然后往“比当前违规率低一个数量级”的方向去设 d。举个例子如果预训练模型的违规率是 8%那 d 可以先设 0.8%也就是每 100 个 episode 违规不超过 0.8 次跑一轮看任务成功率损失多少再做微调。这个标定过程虽然笨但比凭感觉设数字靠谱得多。3.3 稀疏安全信号会拖慢训练得想办法稀释还有一个常见的坑安全违规本身就是小概率事件尤其是在训练初期。这意味着一个 batch 里可能几百条轨迹一条违规都没有E[C] 的估计方差巨大λ 根本收不到有效信号。这在强化学习里是典型的稀疏奖励问题。经验做法是给安全代价加入“密度”。比如除了“是否发生碰撞”这种 0/1 信号再加上“离障碍物最近距离”作为连续的安全信号或者用时序差分的方式把最终碰撞的信号一步步回传变成每个时间步的软信号。密度越高λ 的学习越稳定。当然这会引入偏置需要在 C 里小心加权但工程上这一换通常非常值得。3.4 别忘了通用能力保护安全对齐微调最大的副作用是灾难性遗忘。模型被你拿着安全目标一顿约束安全是安全了但原来会的复杂操作技能全忘了变成一个只会“小心翼翼空转”的废物机器人。这个现象在约束学习中比普通微调更严重因为约束项一直在强调“不要做某些事”策略很容易收缩到一个过度保守的局部最优。解决方案里比较有效的是加一个 KL 散度锚点让微调后的策略不要离预训练策略太远。这个思想和 LLM 对齐时的 KL 惩罚类似本质上是在安全、任务表现和通用能力之间找平衡点。代价是训练需要多维护一个 reference policy显存和计算都会增加但从落地角度考虑这点成本很值得。4. 评估设计怎么证明“安全对齐”真的有效4.1 别只报成功率要学会看帕累托前沿我看很多刚入行的同学做安全对齐评估只汇报一个数字任务成功率。这是最大的误区。安全对齐的核心是 trade-off你牺牲了一点任务表现换来了安全违规的下降。如果只报成功率可能你的约束学习策略成功率掉了 20 个点光看这个数字项目直接就被否了。正确做法是画帕累托前沿Pareto frontier。横轴是安全违规率纵轴是任务成功率然后在同一个坐标系里画上 baseline 方法、RLHF 方法、约束学习方法的多个配置点。因为阈值 d 可以调约束学习方法能画出一条完整的曲线。一个方法如果真的更好它的曲线应该在其他方法曲线的右上方即同样违规率下成功率更高或者同样成功率下违规率更低。只看单点不看曲线很难得出可靠结论。4.2 安全指标的鲁棒性测试比平均值重要平均违规率降下去了并不代表系统就安全了。要看的是最坏情况比如某个特定场景下的违规率是不是特别高。实际项目里我会强制要求团队按场景维度拆解评估结果把“易碎物品场景”“狭窄通道场景”“高速运动场景”分开统计。很多时候平均数字好看就是因为某个简单场景把整体拉下来了而真正危险场景的违规率纹丝不动。另外要加分布外测试。训练和评估都用同一组仿真场景模型当然越调越“安全”但到了真实环境表现完全两样。预算允许的话最好准备一个和训练环境参数差异较大的 hold-out 环境换光照、换物体纹理、换背景布局专门用来检验安全策略的泛化能力。安全如果只能在仿真里成立那对物理世界的意义就很有限。4.3 和基线方法对照时要控制同一个 base model做对照实验时最容易被质疑的一点是不同方法用的 base model 或数据管线不一致导致结果差异根本不是方法带来的。这篇论文讨论的约束学习如果想证明自己优于“直接 RLHF”或者“带固定惩罚的微调”必须保证所有方法从同一个预训练 VLA 权重出发、用同一份场景数据、跑同样的评估脚本。看起来这是基本功实际很多论文项目都栽在这上面尤其模型比较大、重新预训练成本高的时候很容易就拿“之前训练好的 checkpoint”凑数一凑数结论就不干净了。5. 读完整篇论文我的几点个人判断把这篇论文放在整个 VLA 发展脉络里看它的意义不在于提出一个全新的优化算法而在于把一个工业界早就知道、学术界却经常回避的事实摆到了台面上端到端 VLA 模型要落地安全必须是第一公民而不是模型能力的附属品。约束学习本身在强化学习里有大量成熟积累把它和安全对齐结合思路是顺理成章的难的是工程细节也正是这些细节决定了这类方法能不能走出仿真。我自己读完比较深的体会是安全代价函数的设计和评估体系的搭建至少占了这类工作一半以上的工作量。很多团队一开始把精力扑在网络结构和优化器上跑到后来发现瓶颈根本不在这里而是“什么叫安全”这件事根本没有定义清楚。所以我给想复现或者扩展这篇工作的朋友一个建议先花两周把安全指标定义清楚、把评估脚本写扎实再动训练流程这个顺序不要颠倒。至于这个方向后续怎么走我个人比较看好三条线。一是离线约束优化把在线 RL 的成本降下来二是把世界模型和安全约束结合起来让模型在想象空间里先推演再执行三是安全 filter 和约束学习的组合让一个低成本的安全监控器兜底训练时再把 filter 的反馈纳入约束代价。这几条线互相之间并不冲突未来大概率会融合。方向是对的剩下的就是工程人一点一点把它磨实。

相关新闻

Octop 数据管道编排实战:核心模型、调度重试与踩坑指南

Octop 数据管道编排实战:核心模型、调度重试与踩坑指南

1. 从“Octop”这个名字说起:它到底指什么第一次看到“Octop”这个词,很多人会下意识联想到章鱼(Octopus),或者某个开源项目的缩写。我最初接触它的时候也走了弯路,以为是个冷门的命令行工具,翻…

2026/10/16 16:09:40 阅读更多 →
279个开箱即用Shell脚本合集:运维自动化与Linux实用工具详解

279个开箱即用Shell脚本合集:运维自动化与Linux实用工具详解

简介:这套资料汇集279个可直接使用的Shell脚本,覆盖DDoS攻击IP自动屏蔽、Linux邮件告警、MySQL单/多循环备份、Nginx访问日志按天切割与分析、网卡实时流量查看等常见运维场景,适合Linux/Unix系统管理员、运维工程师及Shell入门学习者参考使用…

2026/10/16 16:09:40 阅读更多 →
小程序集成百度云人脸识别的避坑指南与架构实践

小程序集成百度云人脸识别的避坑指南与架构实践

1. 项目概述:为什么小程序里要嵌人脸识别,而不是直接跳转H5或App?“小程序调用百度云接口实现人脸识别”——这十个字背后,其实是一整套轻量级身份核验场景的落地闭环。我做过不下二十个政务、金融、教育类的小程序项目&#xff0…

2026/10/16 16:09:40 阅读更多 →

最新新闻

从ONNX到NPU:Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K的OGA混合推理流水线深度解析

从ONNX到NPU:Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K的OGA混合推理流水线深度解析

【免费下载链接】Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K 项目地址: https://ai.gitcode.com/hf_mirrors/amd/Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K 点击查看 免费下载 本文深入解析 Llama-3.2-3B-Instruct 在 AMD Ryzen AI 平台上的 OGA 混合推理流水线。该…

2026/10/16 16:46:26 阅读更多 →
25层堆叠也不发散:VisionHOPE 用“非扩张动力学“把自修改钉进了安全区

25层堆叠也不发散:VisionHOPE 用“非扩张动力学“把自修改钉进了安全区

25层堆叠也不发散:VisionHOPE 用"非扩张动力学"把自修改钉进了安全区 【免费下载链接】VisionHOPE 项目地址: https://ai.gitcode.com/hf_mirrors/PSRben/VisionHOPE 让视觉主干在推理时"边看图边改自己"——这个概念足够诱人&#xff…

2026/10/16 16:46:26 阅读更多 →
AI编程从无状态到有状态:Memory工程与AGENTS.md配置实战

AI编程从无状态到有状态:Memory工程与AGENTS.md配置实战

1. 从无状态到有状态:AI 编程范式转换的底层逻辑1.1 为什么无状态模型是当前 AI 编程的最大瓶颈如果你最近半年深度用过任何一款 AI 编程助手,大概率经历过这种场景:第一轮对话它帮你把某个模块重构得漂漂亮亮,第二轮你让它接着改…

2026/10/16 16:46:26 阅读更多 →
Windows域信任关系失败的三重根因与修复指南

Windows域信任关系失败的三重根因与修复指南

简介:本资源是一份针对Windows域环境中‘工作站和主域间信任关系失败’问题的实操型排错指南,主要面向企业IT运维人员、系统管理员及虚拟化平台(如VMware、Hyper-V)环境下的技术实践者。文档深入剖析该错误成因——域用户在本地计…

2026/10/16 16:46:26 阅读更多 →
Java通讯录管理系统:面向对象建模与工程实践入门指南

Java通讯录管理系统:面向对象建模与工程实践入门指南

简介:这是一份面向Java初学者的GUI实战项目资源,基于Swing框架开发的通讯录管理系统,帮助学习者掌握面向对象编程、集合操作、文件I/O及桌面应用界面设计等核心技能。资源包共16个文件,含6个.java源码文件(如Mainfrm.j…

2026/10/16 16:46:26 阅读更多 →
Nero刻录光盘软件:从数据归档翻车到批量刻录实战

Nero刻录光盘软件:从数据归档翻车到批量刻录实战

简介:这是一份面向需要光盘刻录与影音处理用户的Nero刻录软件安装包,适合初次接触刻录工具或希望快速搭建本地刻录环境的人群使用,可解决系统重装后缺少刻录软件、日常备份数据与制作影音光盘等需求。压缩包为zip格式,共收录140个…

2026/10/16 16:45:24 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →