浮之静

RL 局限与反思 & 细菌编程

Andrej Karpathy 最近两个帖子挺有趣,我把它们整理在一起,并做了些补充。

RL 的局限与反思

Image

目前,扩展强化学习(RL)规模成为研究热点。从当前趋势来看,RL 很可能会继续带来一系列中间层级的性能突破;但我们也有理由相信,它并不是通向通用智能的终极解法。

从原理上看,RL 的核心机制其实相当朴素:某个策略恰好带来了好的(或坏的)结果,那就略微提升(或削弱)该策略中各个动作未来被采样的概率。这种“事后加权”的方式虽然在形式上接近生物启发,但信息利用效率极低:一段长达数分钟甚至数小时的交互过程,最后仅产生一个标量奖励值,然后我们就基于这个值来微调整个策略梯度。这样的方式,随着任务时长与复杂度的上升,显得愈发不对称与低效。

📌 强化学习

如果监督学习是记忆,强化学习则更像经验;它让模型不只是认知,还能决策和行动。

Image

强化学习场景的典型框架:代理(Agent)在环境(Environment)中采取行动(Action),该行动被解释(Interpreter)为奖励(Reward)和状态(State)表示,然后反馈给代理。

强化学习(RL:Reinforcement Learning)是一种让智能体通过与环境的互动来“学会做决策”的机器学习方法。它模拟的是人类或动物在真实世界中通过试错(trial and error)获得经验的过程——每当采取某个行为后,环境会给予一定的反馈(奖励或惩罚),智能体据此调整未来的行为策略,以最大化长远的收益。

在强化学习中,智能体与环境构成一个闭环系统。智能体首先观察当前的“状态”,然后选择一个“动作”来影响环境,环境再反馈新的状态与奖励。这个循环不断重复,智能体在过程中逐步学习:哪些动作在当前情境下是“好”的,哪些是“差”的。这种学习过程通常建模为“马尔可夫决策过程”(MDP:Markov Decision Process),强调未来只取决于当前状态与行为,而与历史无关。

强化学习的目标不是追求短期最优,而是学习一种策略,使得“长期总奖励最大化”。这种“回报”通常按时间折扣累计,即对未来奖励的重视程度逐渐降低。为了实现这一目标,强化学习的方法主要分为三类:基于价值函数的方法(如 Q-learning)、基于策略的方法(如 REINFORCE、PPO),以及两者结合的“演员-评论家”方法(Actor-Critic)。

强化学习在许多需要连续决策的领域表现出强大能力,例如自动驾驶、机器人控制、游戏(如 AlphaGo)以及推荐系统等。它的最大优势在于“不需要显式标签”,只依靠环境反馈即可学习,有很强的探索能力和泛化能力。

然而,RL 也存在显著的挑战。首先是样本效率低,模型往往需要成千上万次交互才能学会有效策略,这在现实环境中成本极高。其次,奖励设计非常关键也非常敏感,不当的奖励信号可能导致模型学到错误行为。此外,在复杂任务中,奖励往往是“稀疏”的——也就是说,只有在任务最后才知道成败,过程中的行为该如何评估就变得困难。

总的来说,强化学习是一种“具备自主性和探索能力”的学习框架,适用于那些无法用传统监督学习手段建模的“动态决策问题”。尽管存在效率低下、调参困难等问题,但它仍然是构建类人智能不可或缺的组成部分。

更关键的是,这种范式并不贴近人类的智能学习机制。在大多数认知任务中,人类学习远远不止“结果 + 惩奖”这么简单。我们会在每一次尝试后进行自我回顾和反思:哪里做得好?哪里出现了问题?我下次要如何调整策略?这种元认知过程本质上是一个高信息密度的监督信号提取通道,其产出通常是某种明确的“教训”或“启发”,可以作为显式结构写入后续行为策略中,甚至被系统化地整合为长期记忆,就像睡眠中的记忆重组与抽象化过程。

这种以“反思-归纳-提示注入”为核心的学习范式,目前在主流 RL 环境中几乎缺位。以 Atari[1] 或 Mujoco[2] 为代表的经典强化学习任务中,既没有语言模型,也没有上下文窗口,更不存在从文本中抽象行为原则的能力——因此,自然也就没有“在执行后进行自我教学”的机制。

📌 Atari & Mujoco

Atari

Atari 是一系列上世纪的经典街机电子游戏(如“乒乓”、“太空入侵者”、“Breakout” 等)。在 AI 研究中,尤其是强化学习中,Atari 游戏被用作测试智能体是否能在复杂视觉输入下学会策略的标准基准。如 DeepMind DQN(Deep Q-Network)在 2016 年就以“像素级观察 + 动作控制”的方式,在多个 Atari 游戏中达到了超越人类的水平(Deep Reinforcement Learning[3])。Atari 任务的特点是:

  • 输入是像素图像(视觉),输出是离散动作(上下左右、跳跃等)。
  • 奖励函数简单,如得分加奖励、死亡扣分。
  • 没有语言输入,也没有文本输出。
  • 学习完全基于试错和最终得分,智能体对自己的行为没有“反思”或“注释”的能力。
Image

Mujoco

MuJoCo[4](Multi-Joint dynamics with Contact)是一个用于物理仿真的引擎,被广泛用于机器人控制任务中的强化学习研究。比如让一个虚拟机械臂学会抓物、让一个机器人狗学会行走。Mujoco 任务的特点是:

  • 输入是机器人的传感器状态(位置、角度、速度等)。
  • 动作是连续控制信号(如施加多少扭矩)。
  • 奖励往往与目标距离、稳定性等物理量相关。
  • 同样没有语言、没有文本、没有“抽象概念”或“任务结构”。

但我们在语言模型中,却可能已经拥有这种能力的原型。以 ChatGPT 的 Memory 功能为例,尽管它目前主要用于个性化调优,但本质上已经具备一种低级的、长期状态保持机制。如果我们进一步拓展它的用途:让模型在完成若干轮任务后将历史经验、奖励反馈、失败原因集中整理,通过 meta-prompt 生成一段 “lesson string”——即明确表达的策略调整建议——并将其动态添加进系统提示词中,甚至进一步蒸馏进模型权重,那么我们或许正在迈向一种新型的学习系统:既具备反思能力,也能显式保留可迁移的策略经验。

比如,大模型在处理字母计数这类任务时经常出错,根源在于 tokenizer 与内部结构难以精确处理字符级模式。Claude 系统提示中曾采用一个“显式补丁”的方式绕过这个问题:加入一句“若用户要求你数字母,请先用逗号分隔所有字母,并显式维护一个计数器……”这就是典型的 “lesson string”。它不是人类通过 trial-and-error 模糊获得的权重微调,而是某种带有结构性的明确指令,可以被语言模型理解、执行、甚至抽象化。这就引出了一个核心问题:这样的“教训”,是否能不依赖工程师显式注入,而通过模型自身的 agentic 实践过程自动生成?以及,如何将这些教训逐步内化而不造成上下文爆炸?

结论

RL 很可能在短期内继续带来增益,特别是在利用 verifier function 等高杠杆结构时,它比纯监督微调更贴近“苦涩经验”的精神,更具可扩展性。但这仍不够。我们需要寻找超越传统 RL 的新型学习曲线——那些只能在语言模型这种具有内在结构、自我反思能力的系统中显现的 S 型增长点。这一方向尚未被充分探索,却极有可能是下一代 AI 架构真正智能跃迁的关键。

细菌编程

Image

如何像细菌写代码,从而构建繁荣的开源社区?细菌的代码(也就是它们的基因组)有几个关键特征:

  • 精简小巧:每一行“代码”都需要消耗能量,因此必须高效。
  • 模块化:基因被组织成可互换的“操纵子”单元(operons)。
  • 自包含性强:非常容易被“复制-粘贴”——这正是水平基因转移的基础。

如果你的代码是由小型、模块化、自包含、易复制粘贴的块组成,那它就像细菌的 DNA 一样,能够在社区中被高效传播。每当你写下一个函数(就像一个“基因”)或一个类(像一个“操纵子”)时,请自问:

  • 有没有可能某个开发者可以直接 “yoink”(顺手牵羊)你这段代码,不需要理解上下文、不需要引入新依赖,就能立刻获得收益?
  • 你的代码是否具备成为 GitHub 热门 Gist 的潜力?
📌 AI 编程范式

在传统的编程范式中,组件通常被封装在远程依赖中,像黑盒一样被调用。虽然提升了抽象层级,但也带来了高耦合、难以修改、演化成本高等问题,制约了代码的可组合性与自由度。而以 Vue、React、Tailwind CSS 尤其是 shadcn/ui[5] 为代表的现代组件化体系(经常看我文章的朋友或许已发现我最近经常提到 tailwind、shadcn,比如这里:NuxtLabs 牵手 Vercel,Vue 和 React 真的要“一家亲”了?、关于 AI 编程的一些浅思),则更贴近一种“细菌式编程”模式:模块小巧、自包含、极易拷贝与重组。特别是 shadcn/ui,它并不主张通过库引用来使用组件,而是将组件源码直接安装进本地项目中,开发者可以像操控 DNA 片段一样,自由组合、定制、微调。这种方式显著提升了代码的“水平传播能力”,无需庞大的上下文依赖,也不必承担版本封锁或封装开销,让组件真正成为可流通、可进化的最小功能单位,彻底区别于过去“单体式工程”的封闭思路。

Tailwind CSS 则通过将样式“原子化”(Atomic CSS),进一步推动了这一变革,它为 AI 编程带来了显著优势。每一个 Tailwind 的原子类(如 text-xl, bg-blue-500, rounded-md)都直接绑定某个视觉特征,无需额外上下文解释,AI 可以清晰地理解并精准生成,消除了传统 CSS 中类名语义模糊、行为隐藏等障碍。同时,这些原子类高度解耦、可组合,AI 可像拼积木一样构造界面,而不用处理 CSS 的选择器优先级或层叠问题,完美契合语言模型逐 token 输出的生成逻辑。此外,Tailwind 的原子类自带完整信息,AI 无需维护全局样式上下文,节省了上下文窗口,提升 token 效率。更重要的是,它的输出具备高度可控性与可调试性,几乎所见即所得,非常适合 AI 快速生成 UI 原型。响应式、状态变体(如 hover:、md:)也以结构化方式表达,使得生成行为明确、无歧义。

总体来看,这种以“源码可嵌入 + 样式原子化”为核心的细菌式组件开发模式,极大地降低了 AI 参与前端开发的复杂度,让 UI 构建从黑盒变得透明、从静态变得可演化,为人机协同开发打开了新的范式窗口。

这种“细菌式编程风格”正是自然界最强的原型开发模式。数十亿年来,它让细菌得以渗透进地球上几乎所有生态缝隙——从极寒到极热,从强酸到强碱,甚至漂浮在太空中。它支持惊人的代谢多样性与适应性演化,能够快速试错、迭代、传播。

但它有一个天然的局限:细菌代码无法构建复杂生命。相比之下,真核生物的基因组就像一个巨大且耦合紧密的 monorepo[6]。它规模庞大、结构复杂、组织严谨,虽然“发明力”低很多,却是构建完整器官系统、实现全局协调不可或缺的基础。

对我们来说,优势在于智能设计能力:我们可以两者兼得。

如果必须构建一个“真核式 monorepo 骨架”,那就构建它。但在任何可以松耦合、轻量化的地方,最大化地利用细菌式 DNA 模式:小模块,低依赖,可快速移植与组合。

📌 Monorepo

Monorepo(全称 monolithic repository,意为“单体代码仓库”)是一种将多个项目、模块或软件包统一存放在一个代码库中的代码管理方式。与之相对的是 polyrepo(多存储库),即每个项目/服务都有独立的仓库。

Image

Monorepo 并不是一个特定工具或框架,而是一种组织代码的策略,旨在提升团队协作、代码共享与整体开发效率。

核心特点

  • 单一仓库,多个模块:所有服务、组件、包、工具等都在一个 Git 仓库中。
  • 统一的构建与发布流程:使用构建系统(如 Turborepo[7]、Nx[8]、Bazel[9])管理依赖关系和构建步骤。
  • 强依赖可视化:包之间的依赖关系清晰可见,有助于防止“隐式耦合”。
  • 跨项目修改方便:修改多个模块或服务时,无需跨仓库操作,可统一提交、测试、部署。

常见工具生态

JavaScript / TypeScript:

  • Turborepo:由 Vercel 推出,适用于现代前端项目,极速构建与缓存。
  • Nx:功能全面、插件丰富,适用于大型企业项目。
  • Lerna:老牌工具,适合管理多个 npm 包,适用于发布型 monorepo。

其他语言领域:

  • Bazel:由 Google 推出,适合超大规模 monorepo,强调可重复构建和增量编译。
  • Pants[10]、Buck[11]:适用于 Python/Java/C++ 等多语言场景。

举个例子

假设你在开发一个现代网站,包含:

  • 一个前端 Web 应用(Next.js)
  • 一个移动 App(React Native)
  • 一个后端 API(Node.js + Express)
  • 一套 UI 组件库(React + Tailwind)
  • 一组共享的工具函数(utils)

使用 monorepo,你可以将这些全部放在一个仓库中,比如:

my-app/
├── apps/
│   ├── web/
│   └── mobile/
├── packages/
│   ├── ui/
│   └── utils/
└── api/

团队成员可以在同一个 pull request 中同时修改 UI 组件和 Web 页面,无需在多个仓库之间切换、发包或等待对方合并。测试与构建系统也能自动追踪哪些模块被改动,只构建真正受影响的部分。

总结

Monorepo 是一种将所有相关代码模块集中管理的工程策略,强调可组合性、协作性和构建优化。它已成为大中型团队(如 Google、Meta、Vercel、Airbnb)提高开发效率和组织灵活性的关键实践。

📌 依赖地狱

其实,预构建模块和软件包生态最初就是想走这条“细菌式传播”路线的。但现实是:我们如今面临的是一个深不见底的依赖网络噩梦——包依赖层层嵌套,难以解耦,稍一动就崩。

Image

代码的边际成本太低,几乎没有代价,导致结果就是:疯狂膨胀、脆弱难测、结构混乱...

References

[1]

Atari:https://atari.com

[2]

Mujoco:https://mujoco.org

[3]

Deep Reinforcement Learning:https://deepmind.google/discover/blog/deep-reinforcement-learning

[4]

MuJoCo:https://github.com/google-deepmind/mujoco

[5]

shadcn/ui:https://github.com/shadcn-ui/ui

[6]

monorepo:https://monorepo.tools

[7]

Turborepo:https://turborepo.com

[8]

Nx:https://nx.dev

[9]

Bazel:https://bazel.build

[10]

Pants:https://www.pantsbuild.org

[11]

Buck:https://buck.build