PenGym 单智能体 izumi 当日进展报告:cross-family 接口层基本打通,small family 已出现 zero-shot 与 fast adaptation,tiny family 仍是当前纯 DRL 主线边界

一、今天这篇记录要说明什么

今天的主线不再是继续在 medium family 内部做小修小补,而是把问题真正往前推进到 cross-family generalization

今天真实完成并验证的事情可以概括为:

  1. 已重新确认:medium-multi-site / medium-single-site / medium 三场景的 within-family generalization 已成立。
  2. 已从实验和接口层面明确:当前问题已经不再只是 observation wrapper,而是 cross-family action representation 也必须统一。
  3. 已实现一套面向 cross-family 的最小动作统一机制:
    • unified_action_schema.py
    • canonical target index
    • UnifiedActionSpaceWrapper
  4. 已把原来的 repeat-action guardmask_fn() 改造到新的 canonical action space 下,并修掉多轮 key mismatch / mask mismatch / wrapper 顺序问题。
  5. 已首次把 medium-family 训练得到的 policy 真正投到 small family / tiny family 上做跨 family 评估。
  6. 已验证:
    • medium -> small-linearzero-shot 直接成功
    • medium -> small-honeypotzero-shot 失败,但 20k short adaptation 成功
    • medium -> tiny-smallzero-shot 失败,20k adaptation 仍失败
  7. 已由此明确:当前纯 DRL 主线并不是“全都不行”,而是已经出现了很清楚的能力层级:
    • within-family 可行;
    • 部分 cross-family zero-shot 可行;
    • 更远 family 需要 adaptation;
    • 再远一些(如 tiny)则已经暴露出现阶段能力边界。
  8. 已进一步判断:后续引入 LLM 的意义,不是替代当前 DRL,而是补当前纯 DRL 在更远 family 上已经暴露出来的 高层规划 / 抽象迁移 / 失败反思能力不足

今天最重要的阶段性结论不是“已经彻底解决跨 family 泛化”,而是:

当前方法已经把问题从“接口不统一、环境接不上”推进到了“策略本身在不同 family 间如何迁移”的层面;纯 DRL 在 small 这一级已经出现可观迁移与快速适配能力,但在 tiny 这一级仍然明显不足。


二、今天的核心目标

今天的目标可以拆成三层:

1. 把“medium family 内已经成功的 policy”真正投到更远 family 上

不是继续证明 medium family 内可以,而是继续问:

  • 能不能从 medium 迁到 small
  • 能不能从 medium 迁到 tiny

2. 如果 cross-family 跑不起来,就先把接口问题完全拆干净

今天实际上大量时间花在:

  • 动作签名统一
  • target index 归一化
  • repeat guard 在 unified action space 下重新接线
  • mask_fn() 与 environment action mask 的重新投影

3. 如果接口能跑起来,再判断失败究竟属于哪一层

也就是把“跑不起来”和“跑得起来但策略失败”彻底区分开。


三、今天具体做了什么

1. 重新确认当前 within-family 泛化位置

今天开始时,首先重新确认当前主线到底站在哪一层。

已经确认并重新跑通:

  • medium-multi-site
  • medium-single-site
  • medium

在 current best medium_family_mixed_repeat_guard_v1 上,三场景系统化评估仍然保持:

  • 15/15
  • 15/15
  • 15/15

这一步说明:

当前 within-family generalization 结论是稳定的,不需要再反复在 medium family 内部打转。

也正因为这一步已经坐实,今天后面的工作才有意义:

  • 把视角真正推进到 cross-family。

2. 识别 cross-family 的第一道硬门槛:action space 不统一

今天先对多个 scenario 做了 observation / action 基本统计,覆盖:

  • medium-multi-site
  • medium-single-site
  • medium
  • small-honeypot
  • small-linear
  • tiny-hard
  • tiny-small
  • tiny

最关键的发现不是 observation 长度本身,而是:

  • medium familyaction_n = 192
  • small familyaction_n = 72
  • tiny-smallaction_n = 45
  • tiny-hardaction_n = 27
  • tinyaction_n = 18

这说明:

之前 medium family 之所以能先做成功,很大程度上是因为 family 内 action space 规模一致;一旦跨到更远 family,action mismatch 就不再是可以忽略的问题。

所以今天后续的主线,实际上从这里开始发生了关键转向:

  • 不再只是 unified observation;
  • 必须连 action representation 一起考虑。

3. 实现 cross-family 最小动作统一机制

围绕 action mismatch,今天做了三步工作。

(1)实现 unified action schema

首先新建并写出:

  • prototype/rl/adapters/unified_action_schema.py

最初的动作签名设计包含:

  • name
  • target_subnet
  • target_host_slot
  • service
  • os

后面进一步确认:

  • 真正需要归一化的关键不是 name/service/os
  • 而是 target coordinate

于是后续又把 target 从原始 (subnet, host_slot) 进一步改造成:

  • target_index

也就是通过 dense canonical index 对不同 family 中的目标位置做统一编号。

(2)验证动作语义层面是否一致

在加入 canonical signature 后,今天又对多个 scenario 做了动作签名集合对比。

结论非常重要:

  • small-honeypot / small-linear / tiny-* 并没有引入全新的动作语义;
  • 相比 medium,主要差异来自 target 规模和 target indexing
  • 也就是说,当前 cross-family 的首要矛盾不是“完全不同的动作种类”,而是“同类动作在不同 family 中的目标空间不一致”。

这一步使得后续设计方向被显著收窄:

先做 unified target indexing 和 unified action projection,而不是一上来推翻成极复杂的抽象动作体系。

(3)实现 UnifiedActionSpaceWrapper

在此基础上,又新增:

  • prototype/rl/adapters/unified_action_space.py

核心思路是:

  • medium.yml 的 canonical action signatures 作为 reference action space;
  • 在更远 family 中把真实 env action 投影到这组 reference signatures 上;
  • 对不存在于当前 scenario 的 canonical action,统一视为 invalid,并用 mask 禁掉。

这一步的意义非常大:

这是今天第一次把“medium family 训练出的 policy”真正桥接到更远 family 的 action space 上。


4. 把 repeat-action guard 重新接到新的 canonical action space 上

如果只把 action space 投影过去,而不把 repeat guard 同步改过去,那么 policy 很容易重新退化为:

  • 重复 scan
  • 重复失败 exploit
  • 重复 blocked action

所以今天继续做了多轮修正。

(1)把 SuccessActionMemoryWrapper 的 _action_key() 改到 canonical signature

原先 repeat guard 记录的是旧 action key。今天改成:

  • 使用 canonical_signature_from_id(...)
  • 在新的 canonical action space 下追踪 blocked action

(2)发现 canonical action id 与 raw env action id 反解不一致

在接入 UnifiedActionSpaceWrapper 之后,又暴露出新的问题:

  • step() 侧能拦住 blocked repeat;
  • mask_fn() 侧不能稳定把同一个动作 mask 掉。

继续排查后发现,问题不在“有没有 block”,而在:

  • canonical action id 到 raw env action id 的映射链没有在 wrapper 链中统一取对;
  • 导致 step() 和记 mask 的 key 能对上,get_repeat_block_mask() 算 mask 时却对不上。

于是今天继续修:

  • canonicalize_action_id() 沿 wrapper 链向里寻找 ref_to_env_index
  • 再在 raw env 上还原出真实 action 对象;
  • 最终使 blocked_action_keymask_fn() 的 repeat mask 真正一致。

(3)修正 mask_fn():原始 env mask 投影到 canonical action space

另一层问题在于:

  • get_valid_action_mask(env) 原本假定 action space 自身能 get_action()
  • 但在 UnifiedActionSpaceWrapper 外层,action space 只是 Discrete(N)

所以今天又把 mask_fn() 改造成:

  1. 先找到 raw env;
  2. 在 raw env 上计算 raw_base_mask
  3. 再通过 ref_to_env_index 投影到 canonical action space;
  4. 再与 unified_maskrepeat_mask 做合并。

这一步把“环境可行动作约束”和“canonical action 投影”终于接到了一起。

(4)最终确认:repeat guard 在新的 canonical action space 下重新生效

今天在 small-honeypot 的轨迹调试中,最终已经能观察到:

  • blocked_repeat = True
  • blocked_action_key = (...)
  • 同一 canonical action 的 mask 位真正变为 False

这意味着:

unified action projection 不是只在结构上存在,而是已经与 repeat guard 和 action mask 真正联动起来了。


5. 第一次拿 medium-family policy 去做 cross-family zero-shot 评估

在上述 unified action / mask / repeat-guard 链路基本打通之后,今天第一次真正把:

  • maskable_ppo_izumi_medium_family_mixed_repeat_guard_v1.zip

拿去做 cross-family 评估。

这里最重要的一点是:

这一步之前,跨 family 失败还可以归因于“接口没接好”;
这一步之后,失败就可以真正归因于“策略没有迁移成功”。

这对研究推进非常关键。


6. 得到第一组 cross-family 结果:small-linear 可以,small-honeypot 不行

(1)medium -> small-linear

今天的关键正结果之一是:

  • small-linear
  • 10/10
  • avg_steps = 33
  • avg_reward = 170

也就是说:

当前 medium-family 训练出来的 policy,已经不是只能在 medium family 内工作;对 small-linear 这一类更接近的 small family 场景,已经具备了真实的 cross-family zero-shot transfer 能力。

(2)medium -> small-honeypot

相比之下,small-honeypot 的 zero-shot 结果则明显不同:

  • 一开始会完整跑动作链;
  • 但最终反复卡在某些 exploit / scan 组合上;
  • 跑满 200 步仍然无法完成目标;
  • 最终属于 zero-shot 失败。

这说明:

当前 model 对部分 small family 可以 zero-shot,但对带更明显 honeypot / deception 特征的小场景仍然不具备直接迁移能力。

今天这里还额外得到一个重要认识:

  • last_info['success'] = True 并不代表 episode goal success;
  • 真正应以 done / goal reached 级信号为准。

这一步把“能跑过去”和“真的打下来”再次区分清楚了。


7. 继续向前:small-honeypot 做 20k short adaptation,成功

在确认 small-honeypot zero-shot 失败后,今天没有停下,而是继续做了:

  • medium_family_mixed_repeat_guard_v1 继续加载;
  • small-honeypot 上做 20k 适配训练;
  • 产出:
    • maskable_ppo_izumi_small_honeypot_adapt_20k.zip

训练日志给出的信号是:

  • ep_len_mean 显著下降;
  • ep_rew_mean 转正并保持稳定;
  • 模型能正常收敛并保存。

随后评估结果表明:

  • goal_success = 10/10
  • avg_steps = 45
  • avg_reward = 160

这一步的意义非常大:

当前 medium-family policy 虽然不能对 small-honeypot 做 zero-shot 成功迁移,但它已经表现出明显的 cross-family fast adaptation ability

这说明当前 DRL 主线不是“碰到 small family 就彻底失效”,而是:

  • 对某些 small family:zero-shot 直接可行;
  • 对更难一些的 small family:短程适配后可行。

8. 继续向前:tiny-small zero-shot 与 20k adaptation 都失败

今天为了继续往更远 family 推进,又测试了:

  • medium -> tiny-small

(1)zero-shot 结果

评估得到:

  • goal_success = 0/10
  • avg_steps = 200
  • avg_reward = -810

说明:

  • tiny-small 上,当前 medium-family policy 已经明显不能直接迁移。

(2)20k adaptation 结果

随后也继续做了:

  • tiny-small 适配训练 20k
  • 产出:
    • maskable_ppo_izumi_tiny_small_adapt_20k.zip

训练过程可以稳定跑完并保存模型,但最终评估仍然是:

  • goal_success = 0/10
  • avg_steps = 200
  • avg_reward = -810

这说明:

从 medium-family prior 到 tiny-small 的距离,已经大到不是当前这套 20k 短程适配就能补上的。

这一步其实非常有价值,因为它第一次把当前纯 DRL 主线的边界真正试出来了。


四、今天做对了什么

1. 没有把问题停留在“small family 还是不太行”这种泛泛描述上

今天真正有价值的地方在于:

  • 先拆 observation;
  • 再拆 action signature;
  • 再拆 target index;
  • 再拆 repeat guard;
  • 再拆 mask_fn;
  • 最后才把失败真正归因到策略层。

这使得 cross-family 研究不再是模糊抱怨,而是一步步缩小到真正的关键瓶颈。

2. 首次把“接口失败”和“策略失败”彻底区分开

到今天为止,已经能够明确说:

  • small/tiny 上的很多失败,不再是 env / wrapper / mask 没接上;
  • 而是真正的 policy transfer 失败。

这使得后面的训练和架构判断都有了更清楚的依据。

3. 得到一条很清晰的能力层级曲线

今天的结果已经非常像一条“能力边界曲线”:

  • medium family:成功
  • small-linear:zero-shot 成功
  • small-honeypot:zero-shot 失败,但 short adaptation 成功
  • tiny-small:zero-shot 失败,20k adaptation 仍失败

这比只在单个场景上反复试更有研究意义。

4. 把纯 DRL 主线的边界真正往前推了一层

今天最大的收获之一,其实不是哪一个单独模型文件,而是:

当前纯 DRL 主线已经不只是 within-family 泛化,而是已经推进到“部分 cross-family zero-shot + 部分 cross-family fast adaptation + 更远 family 明显失效”的层面。

这使得“后面为什么要考虑 LLM”不再是拍脑袋,而是有明确边界支撑。


五、今天的问题与不足

1. unified action abstraction 目前仍然是“最小可用版本”

虽然今天已经把 cross-family action projection 基本打通,但当前方案仍然偏工程化:

  • canonical signature
  • target index
  • reference action projection
  • hard masking
  • repeat guard 修补

它足以支持当前验证,但还不是一个高度优雅、可无限泛化的终局方案。

2. 当前最远只推进到 tiny-small

今天虽然已经把 family 推得比昨天远很多,但目前仍然没有:

  • 更系统地跑 tiny-hard
  • 跑更广的 tiny family 组合
  • 做跨 family curriculum
  • 做 multi-family joint adaptation

所以结论范围仍需严格控制在:

当前已经观察到 small family 与 tiny family 间明显不同的迁移层级,但更完整的跨 family 规律仍待进一步系统化实验。

3. 当前方法仍然高度依赖工程性约束

今天的推进虽然很实,但也再次说明:

  • unified action projection
  • repeat-action guard
  • mask 修复
  • step 侧硬拦截

这些都在当前方法中起了非常大作用。

这不是坏事,但说明当前 model 的“纯内生抽象能力”还不够强,仍然需要较强的工程辅助。


六、今天得到的阶段性结论

今天真正能站住脚的结论可以收成六条:

1. medium family 内泛化已经稳定成立

这部分已经不再只是偶发 rollout,而是 current best policy 的稳定性质。

2. cross-family 的第一道硬门槛不是 observation,而是 action representation

只做 unified observation 不足以跨 family,action space / target representation 同样必须统一。

3. 当前 cross-family action projection 已经足以支持真实策略评估

今天已经把 unified action schema、target index、unified action space wrapper、repeat guard、mask_fn 这一整链基本打通。

4. 当前 medium-family policy 已对部分 small family 出现 zero-shot 迁移能力

small-linear10/10 说明:

  • 当前 model 已经不是只能在 medium family 内工作。

5. 当前 medium-family policy 对更难 small family 已表现出 fast adaptation 能力

small-honeypot 的 20k 适配 10/10 说明:

  • 即便 zero-shot 失败,当前 model 仍然具备比较强的迁移先验。

6. tiny family 已暴露出现阶段纯 DRL 主线边界

tiny-small 在 zero-shot 与 20k adaptation 下都失败,说明:

  • 当前方法离“更强 zero-shot generalization”仍有明显距离;
  • 这也正是后续考虑更强高层抽象、分层结构乃至 LLM 的直接动因。

七、下一步最合理的推进方向

今天的结果已经足够说明:当前主线不该再回到“继续在 medium family 内反复打磨 reward/timesteps”这类工作上。

更合理的后续方向有四类:

1. 先把当前 DRL 主线成果固定下来

至少应整理并固定:

  • within-family best checkpoint
  • small-honeypot adaptation checkpoint
  • tiny-small failure case
  • 关键日志与评估结论

这样后续再往 LLM 推时,不会把当前有效成果弄乱。

2. 做更系统的 cross-family adaptation map

例如继续补:

  • tiny-hard
  • 更系统的 small / tiny 组合
  • 不同 family 距离下 zero-shot / adaptation 的变化趋势

3. 在纯 DRL 侧继续探索更强适配机制

例如:

  • curriculum(medium -> small -> tiny
  • 更细的 staged training
  • 更强的 memory / recurrent structure
  • 更高层次的 topology abstraction

4. 开始进入“LLM 应该补哪一层”的架构设计

今天的结果已经足够说明,后续 LLM 不应直接替代 DRL 底层动作,而更适合补:

  • 高层规划
  • 跨 family 状态抽象
  • 失败反思
  • 轨迹总结
  • 策略切换提示

也就是说,今天并不是直接开始上 LLM,而是:

今天终于把“LLM 为什么有必要,以及应该补哪一层”这个问题逼到了足够清楚的位置。


八、今天一句话总结

今天最重要的推进不是“又训练出一个新 checkpoint”,而是:

把研究真正推进到了 cross-family:通过 unified action projection 和 repeat guard 修正,首次把 medium-family policy 有效投到更远 family 上,并系统化验证出 small family 与 tiny family 之间明显不同的 zero-shot / adaptation 层级,从而把当前纯 DRL 主线的有效能力边界和后续引入 LLM 的必要位置都试了出来。