[{"content":"我最近在搭一套围绕生活与工作的个人 Agent 基础设施（personal agent infrastructure）。它不是“安装几个 AI 工具”，也不是给同一个聊天机器人换几套人格提示词；我更关心的是：当 Agent 开始长期运行、接触不同数据并执行不同权限的动作后，怎样让系统仍然以人为中心、边界清楚、可审计且可替换。\n截至 2026 年 8 月 5 日，这套系统已经有三个实际运行的 profile：default、hermes-ops 和 blog。后面的 infra、coding、life、research 仍只是规划，不会为了“看起来完整”而提前创建。本文记录的是当前的设计判断与已经落地的部分，而不是某个产品的广告。\n我想解决的不是人格问题，而是上下文污染 最容易开始的方式，是让一个 Agent 同时处理所有事：服务器的 root 操作、代码细节、博客草稿、日程、研究资料、提醒和告警。短期很方便，长期却几乎必然失控：记忆混在一起，工具权限不断累加，定时任务难以追踪，敏感信息也容易越过原本不该越过的边界。\n所以我把 profile 理解为一个领域自治单元，而不是“人格皮肤”。一个 profile 有自己的 config.yaml、.env、SOUL.md、memory、sessions、skills、cron、state DB、gateway 状态和 bot 凭据。它应该对一组数据、权限和长期知识负责，也只处理自己有权处理的那部分。\n边界的划分标准不是“任务名字”，而是下面三个问题：\n谁拥有这份数据？ 谁承担这个动作的风险？ 谁需要维护相关的长期知识？ 一件工作当然可以跨领域，但跨 profile 的协作应该通过 Mattermost 线程、task ID 和明确产物交接完成，而不是互相读取 memory、session DB 或 secrets。\nMattermost：我的统一人机控制台 我选择 Mattermost，并不是因为它有最多的协作功能，恰恰相反，是因为它足够纯净。\n飞书、钉钉、企微都很成熟，但它们面向企业协作，天然带着大量会分散注意力的东西。需要文档时，我可以接入飞书文档；需要日程时，可以接入 Google Calendar。对我而言，整个编排层只有 Mattermost 的摩擦力最低：我可以自己建立、自己管理凭据、通过 API 快速验证一个想法，并且把它作为自己基础设施的一部分，而不是一个不可控的 SaaS 黑箱。\n在这里，频道是天然的领域空间：#infra、#coding、#blog；线程是天然的任务空间。每个 bot 都有清晰的领域身份，日志、diff、测试状态、告警和表格这类机器输出也适合沉淀在同一个界面里。\n目前 Mattermost 通过 Docker Compose 在本机运行：mattermost-app 与 postgres:15-alpine 两个容器保持 healthy，Web/API 服务在 localhost:8065，数据持久化在 ~/mattermost/volumes/。这不是为了追求“全都自己造”，而是为了让控制面在我自己手里。\nHermes：运行时、身份与持久状态层 Hermes 在这套架构中承担的不是“最聪明的模型”，而是运行时、身份和持久状态管理层。\nCodex、Claude Code、Kimi Code 都是优秀的专职 coding agent；但它们的典型 session 更接近单任务、单代码库的工作方式，并不天然解决跨消息平台的长期对话、多领域独立记忆、生活/研究/编码之间的路由问题。对这些问题，Hermes 的 profile 是一等概念；skills、memory、session search、cron、MCP、ACP 和 delegation 也在同一运行时内。\n因此我采用的关系是：\nHermes编排 · 身份 · 持久状态 · 消息入口 ⇄ Specialist executionCodex · Claude Code · Kimi Code\n高能力、可替换的专业执行 worker 对于编码任务，理想的闭环是 worker 在 git worktree 中隔离实现，另一种模型或 worker 做审查，最后由 Hermes 以测试和 diff 收口。实现与审查不必由同一个工具承担。\n这也意味着我并不神化 Hermes。若未来 OpenClaw 在多 bot 路由、飞书接入或长任务队列上经实测更合适，就应该替换对应层。一个健康的个人基础设施不应要求某个产品包办一切。\n五层模型：把“聊天”放回整个系统中 我目前用下面的五层来理解整个系统：\n01Interaction / control planeMattermost · 飞书 · 钉钉 · 企微 · Telegram 02Agent runtime / orchestrationHermes · OpenClaw · 自建工作流系统 03Specialist executionCodex · Claude Code · Kimi Code · CI runners 04State, data and auditGit · Postgres · Calendar · Docs · Logs 05InfrastructureVPS · Tailscale · systemd · containers 最顶层是人与系统交互、确认和追踪状态的控制面；最底层才是服务、容器和网络。模型和 coding agent 很重要，但它们位于中间的 specialist execution 层，不应该抢占顶层身份。作者的决策、确认和偏好始终在系统中心，高风险动作必须经过明确批准。\n对应到 Mattermost 与 profile，目标拓扑如下：\n作者 ↓ Mattermost：统一控制台（自托管） ↓ @hermes（default）总控 · 协调 · 路由\n理解跨域意图，汇总交付物 领域 bot × N专业任务 · 专属数据 · 专属权限\n一 bot · 一 profile · 一 token ↓ hermes-ops控制面运维 infraVPS / 网络 coding项目 / 编码 life日程 / 生活 blog内容 / 发布 research调研 / 监控 其中 default 是 chief-of-staff / orchestrator：理解跨域意图、做路由、汇总结果，但不长期持有每个领域的细粒度操作记忆，更不应默认为生产环境的万能执行者。\n一 bot、一 profile、一个故障域 这里还有一条实现层面的约束：一个 Mattermost bot 对应一个独立 Hermes profile，并使用独立 token。bot 不是一个隐藏在后台的通道，它是用户可理解的领域身份。看到 @blog，我就知道它只处理博客的素材、草稿、构建和经过确认的发布流程；看到 @hermes-ops，我知道它处理的是控制面本身，而不是替我操作任意一台业务服务器。\n这层映射带来的不只是界面上的清晰。profile 的配置、定时任务、状态数据库与 gateway 凭据都是独立的，所以可以把每个 profile 放到独立的 systemd gateway 服务中。这样某一个领域的模型调用失败、依赖升级或 gateway 故障，不会天然拖垮全部领域。Hermes 也可以由主 gateway multiplex 多个 profile；我当前更偏向一 profile 一服务，因为故障域和排障路径都更直接。\n独立并不等于放弃协调。默认 profile 可以把一个跨域请求拆成多个有明确边界的子任务，例如由 research 给出资料、blog 形成草稿、coding 提供可运行的示例；但最终应回到同一个 Mattermost 线程里，交付物、任务 ID、审批点和结论都必须可追溯。协调者负责“把事情接起来”，不负责绕开边界。\n权限矩阵比“能力清单”更重要 Agent 系统很容易只讨论“它能做什么”，而我更想先写清楚“它默认不能做什么”。当前的权限边界是：\nProfile 应具备 默认不应具备 default 任务路由、跨域只读、通知 未经确认的生产 SSH、发布、删除 hermes-ops profile/gateway/bot/skills/cron/备份/升级管理 任意 root SSH、读取其他 profile 私密数据 infra Fleet、SSH、Tailscale、服务管理 日历、博客内容库、项目密钥 coding 项目目录、Git、Coding worker、CI VPS root 全权限、生活数据 blog 博客 repo、媒体、发布工具 生产服务器任意管理权限 life Calendar、任务、生活记录 SSH、deploy keys、生产 secrets research Web/X/RSS、归档 生产修改权限、私人生活写入 这个表也解释了为什么我不打算一开始就把 bot 拆得很细。过早拆分会让人不知道“该找谁”；正确的做法是先识别确实需要长期跟踪的领域，再按数据所有权和权限建立边界。\nhermes-ops：运维控制面的控制面 我认为这套设计里最关键的一层，是把“运维 Mattermost + Hermes 多 profile 系统本身”和“运维 VPS/业务”分开。\n前者属于 @hermes-ops / hermes-ops profile：它是 Personal Agent Control Plane Operations，也是后续 bot 的 Bot Father。它负责 profile 与 bot 的生命周期、gateway/systemd 健康、消息链路的分段定位，以及凭据绑定的治理；它只检查状态，不在聊天中暴露凭据明文。\n它还负责变更治理：提出变更后先描述影响范围、备份和 sandbox 验证方案；得到确认后才应用，再做健康检查并记录可回滚点。它的 Mattermost system-admin automation identity 凭据只存在自己的 .env 中，权限为 0600；即使它权限较高，也不是无限权限，只通过私密频道或 DM 暴露。\n当一个新领域确实值得长期维护时，接入流程是这样的：\n01发现领域确认它值得被长期跟踪，而非一次性任务。 02Domain Charter明确目的、数据所有权、工具、审批与回滚。 03作者确认在创建身份、凭据或服务前取得明确批准。 04最小 profile干净创建，不使用 --clone-all。 05绑定独立 bot一 bot、一 profile、一 token；只建必要频道。 06配置与验收独立 gateway/systemd，验证链路与重启恢复。 07登记与回滚把拓扑、健康检查与 rollback 写入 CONTROL_PLANE.md。 这里有几条我希望长期坚持的安全不变量：不对同一个 profile home 跑两个 gateway；不复用主 bot token；不在聊天中打印 token 或密钥；删除 profile、轮换凭据、重启关键服务、对外暴露 Mattermost 等高风险变更，必须先说明影响与回滚并获得明确批准。\n已经落地，而不是纸面架构 截至本文写作时，default 使用 kimi-coding / k3-256k 作为主控入口；hermes-ops 与 blog 都使用 openai-codex / gpt-5.6-terra，并各自以独立 systemd gateway 服务运行。hermes-ops 已完成独立 bot、私有 DM home channel、pairing、真实模型调用和控制面安全约束的链路验收。\nblog 也按相同模式上线：它有专属 @blog bot 与私有 #blog 频道，频道白名单只允许 #blog，需要 @ 提及才回复，并在任务线程中工作。更重要的是它的发布闸门：新文章默认 draft: true，没有当前线程里的明确批准，不得 push 或 deploy。\n这些规则看起来不如“一个万能 bot”惊艳，但它们让系统在长期运行时仍能解释：谁做了什么、为什么能做、在哪个边界里做，以及失败时怎样回退。\n还没有解决的问题 这套架构仍然很早期。我特别警惕三种反模式：第一，过早拆分 bot，导致入口变多、反而增加认知负担；第二，按任务名字而不是数据与权限划分边界；第三，跨 profile 隐式共享状态，最后又回到一个看似分开、实则混乱的“大脑”。\n接下来我会按需完成 infra、coding、life、research 的 onboarding，而不是照着组织架构图填空。每增加一个 profile，都要先回答它的长期价值、数据归属、最小权限、审批点和 rollback 是什么。\n对我来说，个人 Agent 基础设施的目标不是让自动化替我做更多决定，而是把重复劳动、信息流和专业执行组织得更清楚，让最终决定仍然属于我。\n","permalink":"https://styleofwong.cn/posts/personal-agent-infrastructure-hermes-mattermost/","summary":"我想搭建的不是几个彼此孤立的 AI 工具，而是一套以人为中心、可长期运行、可审计也可替换的个人 Agent 基础设施：Mattermost 作为统一控制台，Hermes profile 作为领域自治单元，Coding Agent 作为可替换的专业 worker。","title":"我的个人 Agent 基础设施：用 Hermes 与 Mattermost 搭一套可治理的控制面"},{"content":"今天给小站做了一次基础设施整理。改动不大，但都和日常体验有关：能更清楚地了解文章被怎样阅读，也让备案信息和资源加载方式更规范。\n访问统计：同时覆盖国内与海外 现在站点同时接入了两套统计服务：\n百度统计：更适合观察国内搜索、来源渠道和页面访问情况； Google Analytics 4：补充海外访问与国际搜索来源的数据。 两者的数字不会完全相同——浏览器的隐私设置、网络环境和脚本加载情况都会造成差异。这里更看重长期趋势，而不是把某一天的 PV 当作绝对答案。\n这些数据会用于判断哪些主题值得继续写、哪些文章需要补充或修订，不会影响读者正常阅读内容。\n页脚：备案信息终于有了合适的位置 页脚现在按三层排列：\n站点版权； ICP 备案与公安联网备案； Hugo 与 PaperMod 的技术署名。 公安备案号旁边加入了对应图标，两个备案号都可以直接跳转到官方查询页面。移动端会在空间不足时自动换行，避免长备案号把页面挤乱。\n缓存：让该快的资源更快，让更新及时生效 这次也重新划分了静态资源的缓存规则：\nHugo 生成的带内容指纹资源（如 CSS、JavaScript）可缓存一年。文件内容一变，URL 也会变化，因此可以放心长期缓存； 图标、图片等固定 URL 的资源缓存 30 天。这样既减少重复下载，也避免替换同名文件后长时间看不到更新； HTML 页面不做长期缓存，仍通过 ETag 和最后修改时间进行校验，发布新文章或更新页面后能及时看到新版本。 服务器也继续提供 gzip 与 zstd 压缩，减少文本资源的传输体积。\n接下来 基础设施的价值不在于堆叠工具，而在于保持简单、可维护。后续我会根据实际访问情况继续优化内容和性能，也会逐步补充站点的数据与隐私说明。\n感谢每一次访问。🙂\n","permalink":"https://styleofwong.cn/posts/site-infrastructure-update-20260713/","summary":"今天为小站补齐了国内外访问统计、备案信息展示，并重新梳理了静态资源缓存策略。","title":"小站基础设施更新：统计、备案与缓存"},{"content":"核心结论(金字塔顶端) 要在 Balatro 白注(White Stake)稳定达到 99% 的 Ante 8 通关率,纯端到端的深度强化学习(如 PPO)走不通。可行的路线是「分层架构 + 混合搜索」:\n战术层(单回合内):把\u0026quot;选牌出牌\u0026quot;建模成组合优化问题,用 MCTS 或精确枚举求近似最优解——但要注意,这层不能脱离战略层独立求解(见 §3.3:积累型 joker 让战术动作带有长期后果) 战略层(跨回合 + 商店):这才是 RL 真正该发力的地方——构筑(joker 选择)、资源管理(金币/抽牌/弃牌)、风险控制,并为战术层提供长期价值估计 $V(s\u0026rsquo;)$ 奖励塑形:稀疏的\u0026quot;通关\u0026quot;信号必须被稠密化,但又要避免 agent 学到\u0026quot;刷分\u0026quot;而非\u0026quot;通关\u0026quot; 下面分层拆解。先说清楚为什么这个目标既硬核又可行。\n一、先校准目标:99% 白注通关率意味着什么? 1.1 难度基准(人类水平) 白注是 Balatro 的最低难度(无任何 stake 修正)。但即便如此,通关 Ante 8 也绝不轻松。根据社区统计 1:\n玩家层次 白注通关率 普通玩家 ~20-30% 熟练玩家 ~50% 顶尖玩家 ~80%(个别卡组如 Checkered 能更高) 📌 关键判断:99% 这个目标显著高于人类顶尖水平。它意味着 agent 不能依赖\u0026quot;运气好的构筑\u0026quot;,必须系统性地规避死亡风险、最大化每个决策的期望通关概率。这恰恰是 RL 相对人类的天然优势——RL 能优化长期期望,而人类受限于单局的情绪与可见范围。\n1.2 分数墙:Ante 8 的硬门槛 白注下 Ante 8 的 Boss Blind 要求分数(以 Red Deck 基准)2:\nAnte 小盲 大盲 Boss Blind 1 300 450 600 4 8,000 12,000 16,000 8 ~100,000 ~150,000 ~200,000+ 某些 Boss(如 The Wall)Ante 8 分数墙可达 300,000 3。这意味着:进入 Ante 7-8,agent 必须具备指数级的分数增长能力(xMult joker + 牌型升级)。构筑路径选择在前中期就已经决定了后期能否突破这道墙。\n二、把游戏建模成 MDP:状态、动作、奖励 这是所有 RL 工作的根基。Balatro 的难点在于它的决策是混合的、稀疏的、且高度依赖构筑。\n2.1 状态空间 $S$ 一个完整的状态需要编码:\n状态 = ( 手牌(花色/点数/增强), # 当前可打出的牌 牌堆/弃牌堆(残差信息), # 推断剩余牌分布 当前 blind 目标分数 + 已得分, 剩余出牌次数 / 弃牌次数, # 资源 金币, # 商店购买力 当前 joker 列表 + 每张效果, # ★ 核心构筑,150+ 种 # ★★ 每张 joker 的运行时累积状态(如 Green Joker 当前 mult、Ride the Bus 计数、Supernova 永久加成) # 这一项绝不能省——见 §3.3,它是跨回合耦合的根源 牌组(deck)构成, # 已增删/增强的牌 消耗品(塔罗/星球/光谱), 当前 ante / blind 类型 / Boss 效果, 商店内容(若在商店阶段) ) 编码挑战:joker 效果极其异质(有的 +chips,有的 ×mult,有的条件触发,有的重写计分规则如 Burglar / Eternal 类)。不能简单 one-hot,需要用结构化/嵌入编码——这是后续网络设计的重点。更关键的是,每个 joker 还必须带上运行时累积状态(当前 mult/chips 加成、触发计数等),否则模型无法理解\u0026quot;弃牌攒 buff\u0026quot;这类长程投资(详见 §3.3)。\n2.2 动作空间 $A$(这里有个大坑) Balatro 的动作是分阶段、异构的:\n阶段 动作 动作数 出牌 选 1~5 张牌并打出 $\\binom{8}{1..5} + \\text{排序变体}$,但实际只关心牌型组合,约 $10^2$ 量级 弃牌 选 1~5 张弃掉 同上 商店 买 joker / 消耗品 / 重置商店 / 卖 joker / 跳过 ~20-30 排序 重新排列手牌 影响部分 joker(如 从左到右触发) ⚠️ 关键洞察:出牌动作的\u0026quot;组合爆炸\u0026quot;是伪命题。8 张手牌选 1~5 张,组合数 $\\sum_{k=1}^{5}\\binom{8}{k} = 218$,再排除非法牌型后实际有效出牌往往只有 几十种。这个子问题用枚举+精确计分就能解,不需要 RL!\n2.3 奖励 $R$:最需要小心的设计 直接的奖励是\u0026quot;通关 = +1,失败 = 0\u0026quot;。但这个信号太稀疏——一局 15~40 分钟、上百个决策,只有一个终局信号,信用分配几乎不可能。\n参考 OpenAI Five 在 Dota 上的经验 4,必须做奖励塑形,但要注意方向:\n塑形项 是否推荐 理由 通关 +1 / 失败 0 ✅ 终局主信号 必须保留,定义\u0026quot;赢\u0026quot; 击败 Blind 的金钱奖励 ✅ 弱 与游戏内经济一致 超额完成分数 ⚠️ 慎用 易导致 agent 刷分而非控血 存活到下一个 ante ✅ 推荐 稠密化进度信号 购买 joker 后的\u0026quot;战力增量\u0026quot; ✅ 推荐 引导构筑质量 剩余出牌/弃牌次数 ⚠️ 弱 避免过度挥霍资源 核心原则(借鉴 OpenAI Five 的零和思想 4):塑形奖励的净效果不应偏离\u0026quot;通关\u0026quot;目标。一个实用做法是 potential-based reward shaping $F = \\gamma\\Phi(s\u0026rsquo;) - \\Phi(s)$,其中 $\\Phi$ 是一个手工或学习到的\u0026quot;通关势函数\u0026quot;,它理论上不改变最优策略,只加速学习 5。\n三、算法选型:为什么纯 PPO 不够,需要 MCTS+RL 混合架构 3.1 纯端到端 PPO 的失败原因 直觉上,Dota 2 用 PPO 成功了,Balatro 也该行?不行,原因有三:\n样本效率:Dota 靠 256 GPU + 45,000 年游戏经验堆出来的 6。Balatro 社区模拟器(如 Jackdaw)虽然快,但单局长、决策密,要堆到 Dota 的量级不现实。 组合动作的精度:出牌是离散组合,PPO 用随机策略采样,很难稳定收敛到\u0026quot;当前手牌的最优子集\u0026quot;——而这恰恰是可以精确求解的。 构筑的长程依赖:Ante 3 买哪个 joker,直接决定 Ante 8 能否过关。PPO 的信用分配跨度太大。 3.2 推荐架构:战术层精确 + 战略层学习 借鉴 AlphaZero 的核心思想——用搜索做\u0026quot;策略改进算子\u0026quot;,用网络指导搜索 7 8——但分层:\n┌─────────────────────────────────────────────┐ │ 战略层(跨回合,RL 的主战场) │ │ - 商店决策:买/卖/跳过/重置 │ │ - 资源管理:金币、抽牌、弃牌的分配 │ │ - 风险控制:何时安全过 blind、何时贪分 │ │ 算法:PPO 或 AlphaZero-style 策略价值网络 │ └──────────────────┬──────────────────────────┘ │ (提供当前状态 + 战略意图) ▼ ┌─────────────────────────────────────────────┐ │ 战术层(单回合内,组合优化) │ │ - 出牌选牌:从手牌中选最优子集 │ │ - 精确计分:含 joker 链触发顺序 │ │ 算法:精确枚举 / MCTS / 分支限界 │ └─────────────────────────────────────────────┘ 为什么这样分工(初步设想)看起来有效?\n战术层似乎\u0026quot;可精确求解\u0026quot;——手牌就 8 张,有效出牌组合几十个,直接枚举每个组合的实际计分(考虑所有 joker 触发),选最优的。 战略层才是 RL 的用武之地——商店构筑、资源调度是真正的长期规划问题,RL 在这里学\u0026quot;未来导向\u0026quot;的策略。 这样似乎能大幅压缩 RL 的动作空间和决策频率。 ⚠️ 但这个\u0026quot;分工\u0026quot;有一个致命漏洞,见下一节 §3.3。初步设想的\u0026quot;战术层独立精确求解\u0026quot;在 Balatro 的真实机制下不成立。\n3.3 关键修正:跨回合状态耦合,战术层无法独立求解 上面\u0026quot;战术层可精确求解\u0026quot;的判断,只在纯计分类 joker(如 +chips、+mult)存在时成立。但 Balatro 有一大类 joker,它的内部状态会随战术动作改变,并跨回合延续——这直接打破了\u0026quot;单回合封闭\u0026quot;的假设。\n典型例子:积累型 joker\njoker 机制 跨回合影响 Green Joker 每弃牌 +1 mult,每出牌 -1 mult ★ mult 加成永久累积,影响后续所有回合 Ride the Bus 每打出不含面牌的一手 +0.2 mult 累积 mult,直到打出面牌归零 Banner 每剩余弃牌 +30 chips 弃牌次数本身是跨回合资源 Supernova 牌型本次得分永久 +mult 整局永久记忆 Mystic Summit 前几次弃牌触发 +mult 一次性消耗,跨回合预算 一个具体推演(以 Green Joker 为例):手牌里有一个稳赢的对子,直接出即可过关。但如果先弃牌 2 次再出对子,这一回合 mult 永久 +2,会延续到后续所有回合。真正的决策是:\n方案 A:直接出对子 → 过关,mult 不变 方案 B:先弃牌 2 次 → 攒永久 mult → 再出对子 → 过关,mult +2(全周期有效) 方案 C:弃牌 5 次 → 攒更多 mult → 但可能把好牌弃了,过不了关 \u0026ldquo;是否弃牌攒 buff\u0026quot;是一个长期投资决策,不是单回合最优。 \u0026ldquo;战术层精确求解\u0026quot;的假设,在这类 joker 存在时直接崩塌。\n结论:Balatro 表面是卡牌游戏,底层其实是一个伪装成卡牌游戏的资源管理 + 长期投资博弈。 它的很多机制设计(积累型 mult、deck 演化、消耗品投资)本质都是\u0026quot;现在牺牲、换取未来收益\u0026quot;的权衡。这类问题 RL 比 MCTS 更擅长——因为 MCTS 擅长离散对抗搜索(围棋),RL 擅长长程投资的规划与信用分配。\n3.4 修正后的架构:战术层依赖战略层的长期价值 原架构里战术层是\u0026quot;独立黑盒求解器\u0026rdquo;,修正后它必须由战略层网络引导,两层端到端联合训练:\n┌─────────────────────────────────────────────────┐ │ 战略层(RL:学习长期价值 V(s)) │ │ - 输入:完整状态(★ 含 joker 运行时累积状态) │ │ - 输出:V(s) = 期望通关率 │ │ - 用途:① 商店决策 ② 给战术层提供长期价值 │ └──────────────────┬──────────────────────────────┘ │ 提供 V(s\u0026#39;) —— 操作后状态的价值 ▼ ┌─────────────────────────────────────────────────┐ │ 战术层(组合优化 + 长期价值引导) │ │ - 枚举出牌/弃牌组合 c │ │ - 对每个组合 c,精确计算综合价值: │ │ 单回合得分 + γ · V(操作后状态 s\u0026#39;) │ │ - 选综合价值最高的组合 │ └─────────────────────────────────────────────────┘ 关键改变:战术层不再追求\u0026quot;单回合得分最高\u0026rdquo;,而是追求\u0026quot;单回合得分 + 折扣后长期价值\u0026ldquo;的综合最优。Green Joker 的\u0026quot;弃牌攒 mult\u0026quot;操作,其长期价值会被战略层网络 $V(s\u0026rsquo;)$ 识别并奖励。\n对状态编码的影响:Set Transformer 的输入不再是\u0026quot;joker 类型 embedding\u0026rdquo;,而是 \u0026ldquo;joker 类型 + 运行时累积状态(当前 mult/chips 加成、触发计数等)\u0026ldquo;的联合 embedding。\n对训练的影响:两层必须联合优化、梯度互通,接近 AlphaZero 式\u0026quot;用网络引导搜索、用搜索改进网络\u0026quot;的架构——而非\u0026quot;战术层独立、战略层独立\u0026rdquo;。\n3.5 战略层的具体网络设计 状态编码(关键创新点)用 Set Transformer / GNN 处理 joker 集合,因为 joker 顺序和组合都重要:\njoker 编码 = Transformer/SetEncoder(joker_embeddings) 全状态向量 = concat(标量状态, 手牌编码, joker编码, deck编码, 盲注信息) ↓ 策略网络 π(a|s) → 商店动作分布 价值网络 V(s) → \u0026#34;从当前状态出发的期望通关率\u0026#34; 价值网络 $V(s)$ 输出的是期望通关概率,这正是我们最终要最大化的量——让 agent 直接学会评估\u0026quot;我现在这个构筑、这个局面,有多大把握通关 Ante 8\u0026rdquo;。\n四、训练流程:课程学习 + 自我对弈 4.1 课程学习(Curriculum) 不要一上来就训 Ante 8。参考通用 RL 工程经验 9:\n阶段 1:先训 Ante 1-3,让 agent 学会基础计分和商店节奏 阶段 2:Ante 4-6,引入构筑协同和资源管理 阶段 3:Ante 7-8,聚焦突破分数墙和 Boss 应对 阶段 4:全 ante 随机种子,完整一局训练 ⚠️ 注意:OpenAI Five 在 Dota 上没有手工课程 4。但 Balatro 不同——它的 ante 是天然递增的难度阶梯,利用这个结构做课程是合理且高效的。\n2.2 自我对弈 + 对手池 由于 Balatro 是单人对随机环境(非对抗性),不需要对手池。但可以维护一个种子池/难度池:把 agent 容易输的随机种子(罕见 Boss 组合、烂商店)加权采样,做 prioritized experience——这等价于 AlphaStar 的\u0026quot;利用者\u0026quot;思想 10 在单 agent 场景的迁移。\n五、关键技术风险与缓解 风险 说明 缓解 模拟器保真度 Jackdaw 等第三方模拟器可能与真实游戏有出入 用真实游戏 API(如 BalatroBot)做 A/B 校验;关键计分逻辑用单元测试对齐官方 wiki 2 奖励黑客(reward hacking) agent 可能找到模拟器 bug 或边缘行为刷分 终局信号以通关为准;塑形奖励做零和/势函数化;定期人工审计 agent 行为 joker 组合空间爆炸 150+ joker 的组合策略空间极大 Set Transformer 编码 + 迁移学习(先训小 joker 子集) 罕见 Boss 应对不足 Ante 8 的 The Wall(300k 分)等极端 Boss 对抗性种子采样,专门强化极端场景 过拟合到固定随机性 RL 可能在固定种子上\u0026quot;背答案\u0026quot; 训练时大量随机种子,评估时用 held-out 种子集 六、99% 真的可达吗?我的判断 可达,但有条件:\n白注的随机性是有限的:商店商品随机,但不是对抗性的——不存在\u0026quot;必输局\u0026quot;。理论上几乎每个随机种子都有解,只是难度不同。 人类顶尖能到 ~80% 1,说明剩余的 19% 失败大多来自次优决策而非\u0026quot;死局\u0026quot;。RL 系统性优化长期期望,有空间把这 19% 吃掉。 瓶颈在构筑层的长期规划,而这正是 AlphaZero 式\u0026quot;搜索+学习\u0026quot;架构的强项——MCTS 能在商店决策时前瞻模拟若干回合。 🎯 现实预期:用 Jackdaw + 战术层精确 + 战略层 AlphaZero 风格的混合架构,在中等算力(单机多卡)训练数周后,白注 Ante 8 通关率从随机 baseline 的接近 0% 提升到 90%+ 是有社区先例支撑的;再通过对抗性采样和架构打磨冲到 99% 是激进但非空想的目标。\n社区已有 RL 项目在真实游戏中拿到首胜的报道 11,证明这条路是通的。\n七、可落地的技术栈推荐 组件 推荐方案 备注 模拟器 Jackdaw(Python, Gymnasium) 首选,原生 Python 无 Lua 依赖 真实游戏对接 BalatroBot(JSON-RPC API) 校验模拟器保真度 战术层求解 精确枚举 + 计分模拟 8 选 5 完全可枚举 战略层算法 PPO(Stable Baselines3)或 AlphaZero 风格 SB3 上手快,AlphaZero 上限高 网络架构 Set Transformer + MLP 编码 joker 集合 训练框架 Ray RLlib / CleanRL 分布式训练 评估 held-out 10k 种子通关率 防过拟合 八、总结:三句话记住这个设计 战术层不能脱离战略层:积累型 joker 让单回合动作带有长期后果(§3.3),战术层必须由战略层的长期价值 $V(s\u0026rsquo;)$ 引导,两层端到端联合训练。 奖励塑形要小心:稠密化进度信号可以,但终局必须锁定\u0026quot;通关\u0026quot;,避免 reward hacking。 白注 99% 可达:因为随机性有限、人类已证明 ~80% 是次优决策造成的,RL 优化长期期望有空间补齐。 下一篇会动手实现一个最小可运行的 Balatro RL demo(基于 Jackdaw),把战术层精确求解器写出来,跑通第一个 baseline。Happy hacking! 🃏\n参考资源 Jackdaw — Balatro Simulator for RL BalatroBot — JSON-RPC API Balatro Wiki — Stakes Reddit r/balatro, What is an overall good winrate on Balatro, https://www.reddit.com/r/balatro/comments/1ctabl2/what_is_an_overall_good_winrate_on_balatro/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nBalatro Wiki, Blinds and Antes, https://balatrowiki.org/w/Blinds_and_Antes\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nReddit r/balatro, Is the Ante 8 Boss Blind always 300,000?, https://www.reddit.com/r/balatro/comments/1bkyqtg/is_the_ante_8_boss_blind_always_300000_or_did_i/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nBerner, C. et al., Dota 2 with Large Scale Deep Reinforcement Learning, arXiv:1912.06680. https://arxiv.org/abs/1912.06680\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nNg, A. et al., Policy Invariance Under Reward Transformations, ICML 1999. (potential-based reward shaping 理论基础)\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nOpenAI, OpenAI Five, https://openai.com/index/openai-five/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nSilver, D. et al., Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm, arXiv:1712.01815. https://arxiv.org/abs/1712.01815\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nSurag Nair, A Simple AlphaZero Tutorial, https://suragnair.github.io/posts/alphazero.html\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nNarvekar, S. et al., Curriculum Learning for Reinforcement Learning Domains: A Framework and Survey, arXiv:2103.04794.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nDeepMind, AlphaStar: Grandmaster Level in StarCraft II, https://deepmind.google/blog/alphastar-grandmaster-level-in-starcraft-ii-using-multi-agent-reinforcement-learning/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nReddit r/reinforcementlearning, My Balatro RL project just won its first run, https://www.reddit.com/r/reinforcementlearning/comments/1m0te9n/my_balatro_rl_project_just_won_its_first_run_in/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://styleofwong.cn/posts/balatro-rl-design/","summary":"如果要在 Balatro 白注达成 99% 的 Ante 8 通关率,RL 算法该怎么设计?本文从游戏机制建模、状态/动作空间、奖励塑形到算法选型,给出一份可落地的技术蓝图,并解释为什么纯 PPO 走不通、必须用 MCTS+RL 的混合架构。","title":"驯服小丑牌:用强化学习把白注通关率推向 99%"},{"content":"核心结论(金字塔顶端) AlphaZero 和 OpenAI Five(Dota 2)之所以能超越人类,不是因为发明了全新的强化学习算法,而是因为它们各自用极具针对性的工程与设计,攻克了强化学习在复杂博弈中的三道共性难关:\n数据从哪来? —— 没有人类标注,如何生成训练数据 训练如何稳定? —— 自我对弈带来的\u0026quot;非平稳性\u0026quot;与\u0026quot;灾难性遗忘\u0026quot; 规模如何上去? —— 状态空间与计算量的指数级膨胀 接下来的每一节,我都会先讲清楚\u0026quot;遇到了什么问题\u0026quot;,再讲\u0026quot;用了什么方法\u0026quot;,最后给出可考证的事实证据(论文/官方博客数据)。\n📌 本文所有关键数字与机制均引用自原始论文与官方资料,文末附完整引用清单。\n第一道关:数据从哪来?—— 自我对弈(Self-Play) 问题:没有人类标注,强化学习如何获得训练信号? 监督学习需要 (输入, 标签) 的配对数据。但在棋类和复杂即时战略游戏里,\u0026ldquo;正确的下一步\u0026quot;根本不存在客观标准——下棋没有标准答案,只有\u0026quot;最终赢没赢\u0026quot;这个延迟信号。\n更深的问题是:即使有人类高手的棋谱,那也只是人类的局部最优。AlphaZero 之前的 AlphaGo 先用人类棋谱做监督学习预训练,再自我对弈。但 DeepMind 想知道一个更激进的问题:\n能否完全不依赖任何人类知识,从零开始(tabula rasa)学会超越人类的策略?\n解决方案:自我对弈 + 神经网络引导搜索 AlphaZero 的解法——自我对弈(Self-Play)策略迭代:\n用当前神经网络 + 蒙特卡洛树搜索(MCTS) 自己和自己下棋,生成对局数据 神经网络有两个输出头:策略头(下一步走法概率)和价值头(局面胜率评估) MCTS 不是暴力穷举,而是用网络的预测来有方向地搜索,把搜索结果作为\u0026quot;更优的标签\u0026quot;反哺训练网络 网络变强 → 自我对弈质量更高 → 训练数据更好 → 网络更强……形成正向循环 关键洞见是:MCTS 扮演的是\u0026quot;策略改进算子\u0026quot;的角色——网络的原始预测经过搜索被\u0026quot;打磨\u0026quot;得更准,这些打磨后的走法成为新一轮训练的目标 1。\nOpenAI Five 的解法——大规模自我对弈:\nDota 2 无法用 MCTS(状态空间太大、连续动作、信息不完全),所以 OpenAI Five 走了另一条路:纯粹的策略梯度方法 + 海量自我对弈。它不搜索、不规划,直接用神经网络输出动作,通过 PPO 算法在赢/输的最终反馈上学习。它的训练强度极其惊人:\nOpenAI Five 每天自我对弈的量,相当于人类玩家 约 180 年的游戏时长;整个训练累计了约 45,000 年的 Dota 2 游戏经验 2 3。\n事实证据 AlphaZero:2017 年 12 月发表于 Science。论文显示,它从零开始,在国际象棋上仅训练 4 小时(约 30 万步)就超越了当时最强的国际象棋引擎 Stockfish;在将棋(Shogi)上仅 2 小时 4 5。 AlphaZero 对 Stockfish 的 100 局评测赛:28 胜、72 和、0 负 6。 OpenAI Five:官方页面明确说明训练使用 256 块 GPU + 128,000 个 CPU 核心,运行 PPO 算法,每 2 秒处理约 200 万帧 2 7。 第二道关:训练如何稳定?—— 非平稳性与灾难性遗忘 问题:自己在和自己下棋,数据分布一直在变 这是自我对弈最隐蔽、也最致命的难题。在监督学习里,数据集是固定的;但在自我对弈中,生成数据的\u0026quot;对手\u0026rdquo;(也就是网络自身)每一轮都在变。这带来两个严重后果:\n后果一:非平稳性(Non-stationarity)。 训练数据是由\u0026quot;当前版本的网络\u0026quot;生成的,网络一更新,数据分布立刻跟着变。用学术语言说,这是一个非平稳的数据流问题——网络在追一个不断移动的靶子 8。\n后果二:灾难性遗忘(Catastrophic Forgetting)。 神经网络用分布式表示存储知识,新学到的策略会覆盖旧的、甚至已经掌握得很好的策略。RL 智能体常常出现\u0026quot;昨天还会的招式,今天突然忘了\u0026quot;的现象 9。\n在 AlphaZero 早期自我对弈阶段,这个问题尤其明显:网络权重随机初始化时,早期对局质量极差,和棋率从约 17% 迅速攀升到约 35%——网络还没真正学会\u0026quot;如何赢\u0026quot; 10。\n解决方案 AlphaZero 的解法 —— 滑动窗口经验回放(Sliding-Window Replay Buffer):\n这是稳定训练的关键设计。AlphaZero 保留最近约 50 万局(对应一个时间窗口)的自我对弈数据,每次训练时从整个窗口里均匀采样小批量,而不是只用最新数据 11 8。\n这个机制的作用是时间平滑:\n不只用最新数据 → 避免被当前版本的偏见主导 丢弃过老的数据 → 避免用\u0026quot;远古弱版本\u0026quot;生成的数据污染训练 窗口大小是工程上的精妙权衡:太大则数据陈旧,太小则失去平滑效果、训练不稳。\nOpenAI Five 的解法 —— 多重稳定化设计:\nOpenAI Five 面对 Dota 2 这种长达 4.5 万年的训练量,稳定性的挑战更艰巨。它用了几个相互配合的手段:\nPPO 的截断代理目标(CPPO Surrogate Objective):PPO 不直接用原始策略梯度,而是用一个\u0026quot;代理损失\u0026quot;,把重要性采样比率截断在一个范围内,等价于隐式约束策略更新的步长(类似信任域),保证大规模训练不会一步迈太大而崩溃 7。\n零和奖励塑形(Zero-Sum Reward Shaping):论文明确写道——\n\u0026ldquo;我们通过从每个英雄的奖励中减去敌方英雄奖励的平均值,来确保所有奖励都是零和的。\u0026rdquo; 7\n这一步极其关键。它防止两个智能体集体\u0026quot;刷分\u0026quot;——比如双方都在安全区域闷头发育,虽然每个英雄的金币/经验都在涨(局部奖励为正),但这对\u0026quot;赢下比赛\u0026quot;毫无帮助。零和化后,一方的收益必然是另一方的损失,优化目标被牢牢锁定在\u0026quot;击败对手\u0026quot;上。\n稠密奖励替代稀疏信号:Dota 一局约 30~45 分钟,如果只在终局给一个 +1/-1 的奖励,信号太稀疏,信用分配(credit assignment)几乎不可能。OpenAI Five 设计了基于金币、经验、击杀、推塔、肉山等频繁事件的塑形奖励,给智能体密集反馈,大大加速学习 12。\n事实证据 AlphaZero 的滑动窗口回放缓冲区机制,在原始论文(Silver et al., 2017)及 ELF OpenGo 的复现研究中有详细描述 11 8。 OpenAI Five 论文(arXiv:1912.06680,共 66 页)专门用章节论述了 PPO、奖励塑形与零和化的设计 7。 灾难性遗忘与持续学习的理论背景,见 IBM 与 NeurIPS 相关综述 9 13。 第三道关:规模如何上去?—— 计算与复杂度的指数级挑战 问题:状态空间大得无法穷举 这是博弈 AI 最直观的挑战。先看几个让人头皮发麻的数字:\n游戏 状态空间规模(数量级) 国际象棋 $\\approx 10^{47}$ 围棋 $\\approx 10^{170}$ Dota 2 连续状态 + 连续动作 + 部分可观测,无法用计数衡量 传统的极小极大搜索(Minimax + Alpha-Beta 剪枝)在象棋上还能勉强应付,但围棋的分支因子太大,暴力搜索彻底失效。而 Dota 2 更甚——它没有\u0026quot;离散状态\u0026quot;可言:英雄位置是连续坐标、装备组合是组合爆炸、而且受\u0026quot;战争迷雾\u0026quot;影响,玩家看不到对手的全部信息(部分可观测)。\n解决方案 AlphaZero 的解法 —— 用神经网络压缩价值判断,用 MCTS 做智能搜索:\nAlphaZero 放弃了\u0026quot;穷举到底再评估\u0026quot;的传统思路,转而用神经网络直接评估局面——给一个棋盘,网络立刻输出\u0026quot;这个局面有多好\u0026quot;和\u0026quot;下一步该走哪\u0026quot;。MCTS 只做有限深度(典型为几十次模拟)的搜索,用网络的预测来引导搜索方向。\n结果令人震撼:Stockfish 每秒搜索约 7000 万个局面,而 AlphaZero 每秒只搜索约 8 万个局面——但 AlphaZero 赢了。 它靠的不是算力碾压,而是\u0026quot;看一眼就知道好坏\u0026quot;的直觉式评估 14。\nOpenAI Five 的解法 —— 不搜索,直接靠规模和算力\u0026quot;暴力\u0026quot;学习:\nDota 2 的复杂性使得 MCTS 完全不可行(无法枚举、信息不完全)。OpenAI Five 的选择非常\u0026quot;简单粗暴\u0026quot;:完全放弃搜索,纯靠自我对弈的规模堆出能力。\n它的训练配置是当时 RL 史上最大规模的工程实践之一 2 15:\n256 块 NVIDIA Tesla P100 GPU(部署在 Google Cloud) 128,000 个 CPU 核心(用于跑大量并行的 Dota 实例) 连续训练约 10 个月 分布式系统 Rapid 框架,处理海量 rollout 的调度 但\u0026quot;暴力\u0026quot;并不等于\u0026quot;无脑\u0026quot; —— OpenAI Five 同时做了大量的简化来让问题变得可学,这些简化恰恰是工程智慧的体现:\n限制英雄池:只训练约 17 个英雄,每局从池中随机抽取 5 个组队。OpenAI 估算,支持全部英雄只需多约 20% 的训练量,但英雄间的技能/物品交互使组合爆炸,在时间线上不现实 7。 早期为镜像对局(mirror match):两边用相同阵容,简化对称性,后期才放开独立选秀。 \u0026ldquo;投降\u0026quot;机制:让明显劣势的对局提前结束,避免浪费算力在已无悬念的局面上(类似 curriculum 的效果,但并非手工设计课程)。 ⚠️ 一个重要的诚实声明:OpenAI Five 论文明确指出,它并没有手工设计课程(curriculum)。原文写得很清楚——\u0026ldquo;这些机制并非为了构建完美课程而逐步引入\u0026rdquo;。难度梯度主要来自自我对弈的对手采样(智能体面对的是不同历史版本的自己),自然形成自适应难度曲线 7。\n事实证据 AlphaZero 推理仅需 1 台机器 + 4 块 TPU;对战时 Stockfish 使用 64 线程,但搜索量是 AlphaZero 的近千倍却落败 16。 OpenAI Five 的硬件配置(256 GPU + 128k CPU)与 10 个月训练时长,见官方页面与论文 2 7。 关于英雄池限制与简化条件,论文 arXiv:1912.06680 有专节论述。 延伸:AlphaStar 把\u0026quot;部分可观测 + 多智能体\u0026quot;推到极致 如果想理解 RL 在复杂游戏上的\u0026quot;终极挑战\u0026rdquo;,DeepMind 的 AlphaStar(星际争霸 2)值得一提。它面对的难点比 Dota 更棘手 17 18:\n部分可观测:战争迷雾下看不到对手 随机性:游戏内有随机元素 多智能体:每方控制大量单位 非传递性策略循环:石头剪刀布式的相克关系(策略 A 克 B,B 克 C,C 克 A),容易导致自我对弈陷入局部最优 AlphaStar 的核心创新是 \u0026ldquo;联盟训练\u0026rdquo;(League Training):不是单一的智能体自我对弈,而是维护一个多样化的智能体群体——主智能体、联盟利用者(league exploiters)、主利用者(main exploiters)三类,它们专门去\u0026quot;钻\u0026quot;彼此策略的漏洞,从而主动制造策略多样性,打破非传递性带来的循环死锁 17。最终 AlphaStar 达到了**大师级(Grandmaster)**水平,位列人类玩家前 0.2%。\n金字塔收束:三个项目的横向对比 回到金字塔顶端,用一个表格把三道难关与破局之法浓缩起来:\n维度 AlphaZero(棋类) OpenAI Five(Dota 2) AlphaStar(星际 2) 数据来源 自我对弈 + MCTS 大规模纯自我对弈 联盟自我对弈(多智能体群体) 核心算法 MCTS + 策略价值网络 PPO(策略梯度) 离策略多智能体 RL 稳定性方案 滑动窗口回放缓冲区 PPO 截断 + 零和奖励塑形 + 稠密奖励 联盟利用者打破循环 规模方案 神经网络压缩评估,4 TPU 推理 256 GPU + 128k CPU,10 个月 大规模分布式 + 策略多样化 代表成果 4 小时超越 Stockfish(28-0-72) TI8 击败职业选手 大师级(前 0.2%) 总结与启示 强化学习在 AlphaZero 和 OpenAI Five 上的突破,本质上不是某个\u0026quot;神来之笔\u0026quot;的算法,而是一系列相互咬合的工程与算法决策:\n没有数据? 用自我对弈自己造,把\u0026quot;延迟的胜负信号\u0026quot;变成可优化的目标。 训练不稳? 用回放缓冲区平滑非平稳性、用 PPO 约束更新步长、用零和奖励锁定真正的优化目标。 规模爆炸? 用神经网络压缩估值(AlphaZero)、用算力与简化工程(OpenAI Five)、用群体多样性对抗策略循环(AlphaStar)。 这些经验早已走出游戏,渗透到机器人控制、推荐系统、大模型对齐(RLHF)等领域。理解了它们如何\u0026quot;撞墙\u0026quot;又如何\u0026quot;破局\u0026quot;,你也就握住了现代强化学习的核心脉络。\n下一篇,我会继续写策略梯度与 PPO 的细节,把 OpenAI Five 背后那个\u0026quot;截断代理目标\u0026quot;讲透。\nHappy learning! 🚀\n参考文献与引用 Surag Nair, A Simple AlphaZero Tutorial, https://suragnair.github.io/posts/alphazero.html\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nOpenAI, OpenAI Five, https://openai.com/index/openai-five/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nWikipedia, OpenAI Five, https://en.wikipedia.org/wiki/OpenAI_Five\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nSilver, D. et al., A general reinforcement learning algorithm that masters chess, shogi, and Go through self-play, Science (2018).\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nDeepMind, AlphaZero: Shedding new light on the chess, shogi, and Go, https://deepmind.google/blog/alphazero-shedding-new-light-on-chess-shogi-and-go/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nChess.com, Google\u0026rsquo;s AlphaZero Destroys Stockfish In 100-Game Match, https://www.chess.com/news/view/google-s-alphazero-destroys-stockfish-in-100-game-match\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nBerner, C. et al., Dota 2 with Large Scale Deep Reinforcement Learning, arXiv:1912.06680 (2019). https://arxiv.org/abs/1912.06680\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nTian, Y. et al., ELF OpenGo: An Analysis and Open Reimplementation of AlphaZero, ICML 2019. https://yuandong-tian.com/reproducibility.pdf\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nIBM, What is Catastrophic Forgetting?, https://www.ibm.com/think/topics/catastrophic-forgetting\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nAI StackExchange, AlphaZero chess: high portion of draws during first rounds of self-play, https://ai.stackexchange.com/questions/43517\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nSilver, D. et al., Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm, arXiv:1712.01815 (2017). https://arxiv.org/abs/1712.01815\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nOpenAI Blog, OpenAI Five (reward shaping discussion), https://openai.com/index/openai-five/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nExperience Replay for Continual Learning, NeurIPS. http://papers.neurips.cc/paper/8327-experience-replay-for-continual-learning.pdf\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nReberLab, AlphaZero Beats Chess In 4 Hours, https://www.reberlab.psych.northwestern.edu/2017/12/12/alphazero-beats-chess-in-4-hours/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nAlignment Forum, How OpenAI Five Distributed Their Training Computation, https://www.alignmentforum.org/posts/6tikKda9LBzrkLfBJ/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nChess StackExchange, Hardware used in AlphaZero vs Stockfish match, https://chess.stackexchange.com/questions/19366\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nDeepMind, AlphaStar: Grandmaster Level in StarCraft II Using Multi-agent Reinforcement Learning, https://deepmind.google/blog/alphastar-grandmaster-level-in-starcraft-ii-using-multi-agent-reinforcement-learning/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nAlphaStar Unplugged: Large-Scale Offline Reinforcement Learning, arXiv:2308.03526. https://arxiv.org/abs/2308.03526\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://styleofwong.cn/posts/rl-breakthroughs-alphazero-dota/","summary":"AlphaZero 与 OpenAI Five 是强化学习的两座里程碑。它们各自撞上了哪些墙?又用怎样的工程与算法创新把它们撞倒?本文用金字塔结构拆解:三大共性难关 —— 数据、稳定性、规模 —— 以及各自的破局之道。","title":"从 AlphaZero 到 Dota 2:强化学习的三道难关与破局之法"},{"content":"为什么需要强化学习? 你已经熟悉监督学习:给一堆 (输入, 标签),模型学会从输入预测标签。但现实里很多问题没有标签——\n下棋:没有标准答案,只有「赢了 / 输了」这个延迟的反馈 自动驾驶:没有「正确操作」的标注,目标是「安全到达」 游戏 AI:目标是「通关」,但每一步该走哪没有现成答案 这类问题的共同特征是 「序列决策 + 延迟奖励」:智能体(Agent)在环境中连续做出决策,影响未来状态,最终获得奖励。这就是强化学习(Reinforcement Learning, RL) 要解决的问题。\n💡 一句话直觉:强化学习就是让 AI 在试错中学会做事,通过奖励信号自己摸索出最优策略。\n一、核心概念:MDP 五元组 强化学习问题通常被建模为马尔可夫决策过程(Markov Decision Process, MDP)。一个 MDP 由五个要素定义:\n符号 名称 含义 $S$ 状态空间 State Space 所有可能的环境状态集合 $A$ 动作空间 Action Space 智能体能采取的所有动作 $P(s\u0026rsquo;|s,a)$ 转移概率 Transition 在状态 $s$ 执行动作 $a$ 后,转移到 $s\u0026rsquo;$ 的概率 $R(s,a)$ 奖励函数 Reward 在状态 $s$ 执行动作 $a$ 获得的即时奖励 $\\gamma$ 折扣因子 Discount 未来奖励的折扣率,取值 $[0,1]$ 「马尔可夫」性质的意思是:下一个状态 $s\u0026rsquo;$ 只依赖于当前状态 $s$ 和动作 $a$,与历史无关。也就是:\n$$P(s_{t+1} \\mid s_t, a_t, s_{t-1}, a_{t-1}, \\dots) = P(s_{t+1} \\mid s_t, a_t)$$\n这个假设极大简化了问题——我们不需要记住全部历史,只需关注「当前状态」即可决策。\n二、目标:最大化累积奖励 强化学习的目标是找到一个策略(Policy) $\\pi$——一个从状态到动作的映射 $\\pi: S \\to A$,使得累积奖励的期望最大化。\n由于未来的奖励不如眼前的奖励「值钱」(今天的 100 块比明天的 100 块有价值),我们引入折扣因子 $\\gamma \\in [0,1]$,定义回报(Return) $G_t$:\n$$G_t = R_{t+1} + \\gamma R_{t+2} + \\gamma^2 R_{t+3} + \\cdots = \\sum_{k=0}^{\\infty} \\gamma^k R_{t+k+1}$$\n$\\gamma = 0$:只看眼前,目光短浅 $\\gamma = 1$:对未来一视同仁,可能不收敛 实践中常取 $\\gamma = 0.9 \\sim 0.99$ 我们的终极目标是求最优策略 $\\pi^*$,使得期望回报最大:\n$$\\pi^* = \\arg\\max_\\pi \\mathbb{E}\\left[\\sum_{k=0}^{\\infty} \\gamma^k R_{t+k+1} \\right]$$\n三、价值函数:衡量「一个状态有多好」 直接求 $\\pi^*$ 太抽象,我们需要更具体的工具——价值函数。\n状态价值函数 $V^\\pi(s)$ 在策略 $\\pi$ 下,从状态 $s$ 出发的期望回报:\n$$V^\\pi(s) = \\mathbb{E}_\\pi \\left[ G_t \\mid S_t = s \\right]$$\n动作价值函数 $Q^\\pi(s,a)$ 在策略 $\\pi$ 下,从状态 $s$ 执行动作 $a$ 后的期望回报:\n$$Q^\\pi(s,a) = \\mathbb{E}_\\pi \\left[ G_t \\mid S_t = s, A_t = a \\right]$$\n两者的关系很直观——状态价值是该状态下所有动作价值的(按策略加权的)平均:\n$$V^\\pi(s) = \\sum_a \\pi(a \\mid s) , Q^\\pi(s,a)$$\n💡 直觉:$V(s)$ 告诉你「站在这里有多好」,$Q(s,a)$ 告诉你「站在这里做某个动作有多好」。后者信息更丰富,是大多数 RL 算法的核心。\n四、贝尔曼方程:RL 的基石 价值函数满足一个优美的递推关系——贝尔曼方程(Bellman Equation)。它把「当前状态的价值」和「下一状态的价值」联系起来。\n$V$ 的贝尔曼方程 $$V^\\pi(s) = \\sum_a \\pi(a \\mid s) \\sum_{s\u0026rsquo;} P(s\u0026rsquo; \\mid s,a) \\left[ R(s,a) + \\gamma V^\\pi(s\u0026rsquo;) \\right]$$\n直觉:当前状态的价值 = 所有动作的(即时奖励 + 折扣后的下一状态价值)的期望。\n$Q$ 的贝尔曼方程 $$Q^\\pi(s,a) = \\sum_{s\u0026rsquo;} P(s\u0026rsquo; \\mid s,a) \\left[ R(s,a) + \\gamma \\sum_{a\u0026rsquo;} \\pi(a\u0026rsquo; \\mid s\u0026rsquo;) Q^\\pi(s\u0026rsquo;,a\u0026rsquo;) \\right]$$\n贝尔曼最优方程 对于最优价值函数 $V^$ 和 $Q^$,动作选择不再是「按策略加权」,而是「直接取最大」:\n$$Q^(s,a) = \\sum_{s\u0026rsquo;} P(s\u0026rsquo; \\mid s,a) \\left[ R(s,a) + \\gamma \\max_{a\u0026rsquo;} Q^(s\u0026rsquo;,a\u0026rsquo;) \\right]$$\n这就是整个 RL 的核心——只要能求出 $Q^*$,最优策略就是每个状态下选 $Q$ 值最大的动作:\n$$\\pi^(s) = \\arg\\max_a Q^(s,a)$$\n五、Q-Learning:无模型学习的经典算法 现实中,转移概率 $P$ 和奖励函数 $R$ 往往未知(称为 model-free 场景),我们只能通过与环境的交互来学习。Q-Learning 是最经典的解法。\n核心思想 维护一个 Q 表(表格化的 $Q(s,a)$),通过与环境的交互不断更新它,最终收敛到 $Q^*$。\n更新规则 $$Q(s,a) \\leftarrow Q(s,a) + \\alpha \\left[ r + \\gamma \\max_{a\u0026rsquo;} Q(s\u0026rsquo;,a\u0026rsquo;) - Q(s,a) \\right]$$\n其中:\n$\\alpha \\in (0,1]$ 是学习率 $r + \\gamma \\max_{a\u0026rsquo;} Q(s\u0026rsquo;,a\u0026rsquo;)$ 是TD Target(时序差分目标) $\\delta = r + \\gamma \\max_{a\u0026rsquo;} Q(s\u0026rsquo;,a\u0026rsquo;) - Q(s,a)$ 是TD Error 直觉:用「实际经验」$(r, s\u0026rsquo;)$ 算出的新估计,去修正旧的 $Q(s,a)$,每次朝目标靠近一点点。\n探索与利用(Exploration vs. Exploitation) Q-Learning 用 $\\varepsilon$-greedy 策略平衡探索与利用:\n以概率 $\\varepsilon$:随机选动作(探索,避免陷入局部最优) 以概率 $1-\\varepsilon$:选 $Q$ 值最大的动作(利用已知信息) 通常 $\\varepsilon$ 从 1.0 衰减到 0.1,前期多探索,后期多利用。\n六、代码示例:Q-Learning 走迷宫 下面用一个最经典的例子——网格世界(GridWorld)走迷宫——展示 Q-Learning 的完整流程。智能体从起点走到终点,避开陷阱。\nimport numpy as np import random # 网格世界:4x4 # S = 起点, G = 终点(+1), X = 陷阱(-1) # . = 普通格子(0) grid = [ [\u0026#39;S\u0026#39;, \u0026#39;.\u0026#39;, \u0026#39;.\u0026#39;, \u0026#39;X\u0026#39;], [\u0026#39;.\u0026#39;, \u0026#39;X\u0026#39;, \u0026#39;.\u0026#39;, \u0026#39;.\u0026#39;], [\u0026#39;.\u0026#39;, \u0026#39;.\u0026#39;, \u0026#39;.\u0026#39;, \u0026#39;X\u0026#39;], [\u0026#39;X\u0026#39;, \u0026#39;.\u0026#39;, \u0026#39;.\u0026#39;, \u0026#39;G\u0026#39;], ] N = 4 ACTIONS = [\u0026#39;up\u0026#39;, \u0026#39;down\u0026#39;, \u0026#39;left\u0026#39;, \u0026#39;right\u0026#39;] def get_reward(cell): if cell == \u0026#39;G\u0026#39;: return 1.0 # 到达终点,正向奖励 if cell == \u0026#39;X\u0026#39;: return -1.0 # 踩到陷阱,负向奖励 return -0.01 # 普通格子,小惩罚(鼓励尽快到达) def is_terminal(cell): return cell in (\u0026#39;G\u0026#39;, \u0026#39;X\u0026#39;) def step(state, action): \u0026#34;\u0026#34;\u0026#34;执行动作,返回 (next_state, reward, done)\u0026#34;\u0026#34;\u0026#34; r, c = state if action == \u0026#39;up\u0026#39;: r = max(0, r - 1) elif action == \u0026#39;down\u0026#39;: r = min(N - 1, r + 1) elif action == \u0026#39;left\u0026#39;: c = max(0, c - 1) elif action == \u0026#39;right\u0026#39;: c = min(N - 1, c + 1) next_state = (r, c) cell = grid[r][c] return next_state, get_reward(cell), is_terminal(cell) # Q 表:state -\u0026gt; action -\u0026gt; value Q = {} def q_value(state, action): return Q.setdefault(state, {}).setdefault(action, 0.0) # === Q-Learning 训练 === alpha, gamma, epsilon = 0.1, 0.95, 1.0 EPISODES = 2000 for ep in range(EPISODES): state = (0, 0) # 起点 S done = False while not done: # ε-greedy 选动作 if random.random() \u0026lt; epsilon: action = random.choice(ACTIONS) # 探索 else: action = max(ACTIONS, key=lambda a: q_value(state, a)) # 利用 next_state, reward, done = step(state, action) # Q-Learning 更新 td_target = reward + gamma * max( (q_value(next_state, a) for a in ACTIONS), default=0.0 ) Q.setdefault(state, {})[action] += alpha * (td_target - q_value(state, action)) state = next_state # epsilon 衰减:从探索逐渐转向利用 epsilon = max(0.1, epsilon * 0.995) # === 提取学到的最优策略 === print(\u0026#34;学到的最优策略:\u0026#34;) arrows = {\u0026#39;up\u0026#39;: \u0026#39;↑\u0026#39;, \u0026#39;down\u0026#39;: \u0026#39;↓\u0026#39;, \u0026#39;left\u0026#39;: \u0026#39;←\u0026#39;, \u0026#39;right\u0026#39;: \u0026#39;→\u0026#39;} for r in range(N): row = [] for c in range(N): cell = grid[r][c] if cell in (\u0026#39;G\u0026#39;, \u0026#39;X\u0026#39;, \u0026#39;S\u0026#39;): row.append(f\u0026#39; {cell} \u0026#39;) else: best = max(ACTIONS, key=lambda a: q_value((r, c), a)) row.append(f\u0026#39; {arrows[best]} \u0026#39;) print(\u0026#39;\u0026#39;.join(row)) 运行后,你会看到智能体学到的路径——它会绕开陷阱、走向终点,即使我们从未告诉它「该怎么走」。\n七、从 Q-Learning 到深度强化学习 Q-Learning 的致命限制:Q 表无法应对大状态空间。国际象棋有 $10^{47}$ 个状态,围棋有 $10^{170}$ 个——表格根本存不下。\n解决思路很自然:用神经网络近似 $Q$ 函数 $Q_\\theta(s,a)$,这就是 DQN(Deep Q-Network),DeepMind 用它让 AI 第一次在 Atari 游戏上达到人类水平。\nDQN 的关键创新:\n经验回放(Experience Replay):把交互数据存进缓冲区,随机采样训练,打破数据相关性 目标网络(Target Network):用单独的网络计算 TD Target,稳定训练 再往后,RL 家族不断演化:\n类别 代表算法 特点 基于价值 DQN, Rainbow 学习 $Q$ 函数 策略梯度 REINFORCE, A2C, A3C 直接优化策略 $\\pi_\\theta$ Actor-Critic PPO, SAC 结合价值与策略,当前主流 AlphaGo/Zero MCTS + RL 蒙特卡洛树搜索 + 自我博弈 八、写在最后 强化学习的美妙之处在于:它用一套统一的数学框架(贝尔曼方程 + 价值函数),描述了「如何在没有老师的情况下,通过试错学会做事」。这或许是最接近「智能本质」的学习范式。\n本文梳理了从直觉到 Q-Learning 的核心脉络:\nMDP 建模问题 价值函数 衡量好坏 贝尔曼方程 给出递推关系 Q-Learning 实现无模型学习 DQN 用深度网络扩展到大状态空间 建议的下一步学习路径:\n📖 Sutton \u0026amp; Barto《Reinforcement Learning: An Introduction》(RL 圣经,免费 PDF) 🎮 OpenAI Gym / Gymnasium —— 跑各种 RL 环境的标准工具 🧪 Stable Baselines3 —— 开箱即用的 RL 算法实现(PPO/SAC 等) 🏆 从简单环境(CartPole)开始,逐步挑战复杂任务 下一篇会写策略梯度方法,聊聊为什么「直接优化策略」在某些场景下比价值方法更强大。\nHappy learning! 🚀\n","permalink":"https://styleofwong.cn/posts/reinforcement-learning-intro/","summary":"强化学习是让 AI 学会『在试错中成长』的范式。本文从最核心的直觉出发,讲清楚 MDP、贝尔曼方程、Q-Learning,并附一个可运行的 Python 示例。","title":"强化学习入门:从直觉到 Q-Learning"},{"content":"👋 你好! 欢迎来到 王辉赳的小站!这是我用来分享知识的个人空间。\n🧑‍💻 关于我 职业:程序员 兴趣:算法研究、玩游戏 当前方向:专注在 AI 领域 📝 这里会有什么 这个站点主要会分享这些内容:\nAI 技术笔记 —— 大模型、机器学习、深度学习的实践与思考 算法研究 —— 刷题心得、算法原理、数据结构 编程经验 —— 开发技巧、踩坑记录、工具推荐 游戏体验 —— 一些值得聊的游戏 💻 一段示例代码 这个站点本身也是用技术搭起来的(Hugo + Nginx):\npackage main import \u0026#34;fmt\u0026#34; func main() { fmt.Println(\u0026#34;Hello, World! 博客上线 🎉\u0026#34;) } 🚀 下一步 慢慢写,慢慢积累。感谢你的来访!\n","permalink":"https://styleofwong.cn/posts/hello-world/","summary":"这是王辉赳的个人博客的第一篇文章,记录这个小站的诞生。","title":"你好,世界 —— 博客上线啦"}]