# 用 TRL 和 OpenEnv 训练编码模型画水彩：Hugging Face 全流程开源复现

- 来源：Hugging Face：Blog（RSS）
- 发布时间：2026-09-03 08:00
- AIHOT 分数：62
- AIHOT 标记：精选
- AIHOT 链接：https://aihot.virxact.com/items/cmtl9l0kb0mksroal28uvoaug
- 原文链接：https://huggingface.co/blog/train-to-paint-with-code

## 精选理由

作者用 TRL 和 OpenEnv 完整开源复现了让编码模型画水彩的 RL 配方，含数据池、环境和三组奖励对比，可整体迁移复用。

## AI 摘要

Hugging Face 博客作者基于 Surya Narreddi 的原始想法，用 TRL、OpenEnv 和 Qwen/Qwen3.5-35B-A3B 复现了让语言模型通过 p5.brush 写 JavaScript 画水彩的 RL 训练流程，所有数据集、环境、脚本和模型均开源在 Hub。

## 正文

8 月 23 日，Surya Narreddi 发布了一段精美的视频，展示了一个语言模型绘制的水彩画。该模型通过 p5.brush（一个“为 p5.js 添加自然绘图工具”的库）编写 JavaScript。这段视频迅速走红，截至撰写本文时，观看量已超过 150 万次。

这段视频附带了一篇博客文章，解释了该项目早期、范围更窄阶段的训练过程——当时是特写花卉，而非视频中的完整构图，遗憾的是尚未开放任何工件。他的网站显示，完整的技术报告即将发布，所以请务必关注他。最初的创意来自他本人，源于艺术与设计领域，他在那方面的技能远超于我。我的尝试则侧重于工程方面，以开放的方式复现这一方法，并公开每一个环节。

注意：关于该项目的背景，由 Surya 本人讲述，请观看他的论文答辩视频。

在本文中，我尝试使用 TRL 和 OpenEnv 复现他的想法。参考池数据集、RL 环境、训练脚本以及训练好的模型，全部开放。

整个流水线端到端运行在 Hugging Face 上：

在 Jobs 上进行训练

RL 环境和评分模型作为 Spaces 部署

通过 Inference Providers 进行成对评判

所有工件都托管在 Hub 上，并汇集在一个集合中

两个 Space 就绪后，配方就只剩一条命令。复制环境和评分模型，为奖励混合设置两个环境变量，然后启动：

hf jobs uv run train/watercolour_grpo.py --flavor h200 --timeout 48h --secrets HF_TOKEN -- \ --env-url https://<you>-watercolour-env.hf.space \ --model Qwen/Qwen3.5-35B-A3B --lora --all-linear --bf16 --gradient-checkpointing \ --subject 'a peach hibiscus' --references 4 \ --top-p 0.95 --top-k 20 \ --lr 5e-5 --lr-scheduler constant_with_warmup --warmup-steps 5 \ --scale-rewards none \ --steps 110 --n-episodes 240 --num-generations 8 \ --per-device-batch-size 1 --gradient-accumulation-steps 8 \ --max-completion-length 8192 \ --run-tag my-run --out <you>/watercolour-grpo --push-to-hub

本文其余部分讲述的是达成这一结果的过程，所有内容都已放入代码仓库。

我一步步跟随原博客的步骤，只在确有必要时才做改动。我自己的每个想法都记入清单而非直接用于实验，这份清单最终成为文末的“我接下来想尝试的方向”，旁边附有全部已发布产物的完整列表。如果你已经读过他的文章，那么框架和奖励设计会让你感到熟悉。新增内容在于开源的实现、人工评分的样本池，以及三组经过训练并相互对比的奖励混合方案，这一切从“你需要构建的 RL 环境”一节开始。

三次运行，对应三种奖励混合方案，并行演进。每一帧展示的是某一步的中位数画作。目前还无需区分它们，文章会说明哪次运行对应哪种方案。

人们为何喜爱它

这些画作看起来松散、不完美、带着手工感，而当下图像模型产出的却是完美（统计上平均）的画面。我猜测，这种反差正是视频走红的重要原因。这让我想起生成式 AI 艺术的早期，那时的意义在于探索媒介本身。DeepDream（2015）本是调试工具，却被人们变成了艺术；像 Edmond de Belamy（2018）这样的作品出自艺术家对 GAN 能力的探索；而 Mario Klingemann 等艺术家在那几年用神经网络创作出梦幻般的肖像。

这个项目让人感觉更接近那些早期岁月。在他的论文中，Surya 描述了通往这里的路径。他最初是给文生图模型写提示词，在那种模式下，提示词是你唯一能操控的杠杆，而增加细节能带来的控制力提升终究是有限的。直接训练模型本身则更进一步。这个想法的另一半在于媒介。模型会编写一段约 150 行的 JavaScript 程序来绘制图像。模型的输出就是代码。你可以阅读它、编辑它并重新运行它，每一笔笔触背后的决策都是可见的。而这种风格源自一个限制：模型只被允许使用该库中的十个方法。更多细节见下文。

在同一时期，Anna Ridler 拍摄了数千朵郁金香，为每一朵都手工标注，将数据集本身作为艺术品展出，后来又用这个数据集训练了一个模型。我是在构建这个项目时，通过 AI 智能体带回的参考文献发现她的作品的，我非常喜欢，因为这个项目做了非常相似的事情——手工策展一组图像，然后针对它们进行训练。

基于品味的强化学习

近期大多数关于语言模型的强化学习工作，使用的都是可以被验证的奖励。例如，有已知答案的数学题、能通过测试的代码，或者对错分明且运行成本低廉的评分器。而这个项目更接近那个较早的例外——RLHF，即模型从人类偏好中学习出一个奖励模型。

在这里，奖励是审美偏好。没有正确答案。这个项目真正要探讨的问题是：你是否能对品味进行强化学习。

这个奖励，正如他的博客所定义的那样，也正如我所构建的强化学习环境所实现的那样：

术语 权重 衡量内容

门控 0.05 草图可编译、能绘制出内容、不偷工减料

长度 0.05 温和引导生成更长的代码片段

成对评判器 0.60 风格，与从样本池中抽取的参考作品进行对比

HPSv3 0.30 对渲染结果的审美偏好

HPSv3 是一个开源的 7B 偏好模型。给它一张图片和一段文字描述，它就会返回一个分数，表示一个人对这张图片的偏好程度。它是在大量人类对图片对进行选择的标注数据上训练的，因此它的分数是许多人品味的平均值。成对评判器是 Qwen3-VL-30B-A3B-Instruct，这是一个通过 HF Inference Providers 调用的通用视觉模型。成对评判器会将候选画作与从图池中随机选取的四张参考图放在一起进行对比，并依据一段书面描述来指导评判时应侧重哪些方面（晕染、透明水洗、柔和边缘），每次对比都会以两种呈现顺序进行，最终得分是候选画作在对比中获胜的比例。它唯一的标准就是图池本身，因此它的分数就是我的品味——正如那些评分所编码的那样。

奖励函数中的四个项里有两个是模型。它们都是对某人品味的代理指标。

这些就是 Narreddi 收敛得到的权重。图池在这里定义了品味。这就把工作从调整超参数转移到了构建那个决定何为美的集合上。

我用这个奖励函数训练了三次运行。它们的区别仅在于两个模型评判器之间的权重分配方式不同：

运行 成对评判器 HPSv3 角色

评判器主导 0.60 0.30 原始混合，在第 110 步停止

hps 主导 0.30 0.60 中间点，在第 110 步停止

仅 hps 0.00 0.90 验证运行，在第 60 步停止

我先从仅 hps 开始，以验证该流程确实能够学习。一旦奖励开始上升且各项指标正常，就没有必要继续运行更久，因此我转而启动了两个更长的运行。这两个更长运行要回答的问题是：HPSv3 的能力有多少可以交给成对评判器？评判器权重越大，奖励就越代表我的品味而非大众品味，爬升的难度也就越大。顺带一提，如果你把权重推得足够高，或者你的风格与平均水平相差太远，模型可能会完全停止。

幸运的是，它并没有停止，两轮开启成对评判器的运行也都成功学到了东西。人工评分池至少从指标和最终画作来看，能够引导策略。具体数字如下。

免责声明。如果我们使用前沿模型，它已经能够根据提示词生成绘制水彩画的 JavaScript 代码。这是起点。这里的工作重点在于教会一个较小的模型完成这件事，并结合个人自身的艺术偏好。

你需要构建的 RL 环境

该环境封装了模型与奖励之间的所有环节，包括模型用于绘画的 JavaScript 库、限制其行为的系统提示词、渲染每幅草稿的无头 Chromium，以及拒绝作弊行为的门控机制。

这个库所做的工作比表面上看起来更多。p5.brush 由 @acamposuribe 开发，它模拟的是一种绘画媒介而非绘制形状：颜料会渗出填充区域的边缘，纸张具有纹理，笔触具有质量，流场会带动笔触移动。当模型调用 brush.fillBleed(0.25) 时，它是在决定墨水洇开的程度。

备注。p5.brush 的作者早在这一切发生之前就一直在尝试教机器绘画。2022 年，他创作了一个生成艺术系列，其中隐藏着一篇关于教 p5.js 像孩子一样绘画的日记：“它几乎不会用蜡笔……它无法遵循简单的指令。今天就到这里吧，太让人恼火了。”该系列原本计划包含三件作品，而他完成了两件。当 Surya 的视频走红后，他引用了该视频，分享了那篇日记，并表示这件作品是第三件，它自行到来了。

p5.brush 暴露了 47 个方法。提示词只允许使用其中 10 个：scaleBrushes、noStroke、fill、noFill、fillBleed、fillTexture、beginShape、vertex、endShape 和 circle。其余三十七个方法（线条、阴影线、自定义笔刷等）会破坏水彩效果。有了这十个方法，模型只能绘制填充形状，而库会为每一个形状添加颜料晕染效果。

某次 rollout 中 draw() 的一部分及其渲染结果。注释是模型自己写的。奖励值 0.864，129 行，第 22 步。每幅画的完整源代码都包含在 rollouts 数据集中。

他的博客文章为我节省了大量本可能浪费在反复迭代提示词上的时间。冗长的 API 参考会让模型编造出不存在的方法，而他经过 200 次 GEPA 迭代收敛到了一个没有文档的严格白名单。我遇到了同样的失败，于是手动编写了白名单。我对那个方案唯一的补充是一句话：每片花瓣画两到三次，先画一大笔，再在里面画一笔更小、更不透明的一笔。这个小小的改动让我的输出色彩丰富了许多。

备注。如果你是第一次听说 GEPA，它是一个自动提示词优化器。语言模型用通俗的语言反思当前提示词在哪些地方失败了，并提出一个更好的提示词，如此循环往复。

这道关卡是最后一块拼图。草图必须能够编译，必须使用该库而不是直接调用 p5，必须将真正的颜料画到画布上，并且不能试图欺骗评分器，例如通过在画布上写文字。

池子就是奖励函数

这个画库包含 178 幅画作，根据我个人偏好分为两档：喜爱和一般。所有画作实际上都是由模型生成的。四个开放权重模型通过 Inference Providers 调用，各自基于 iNaturalist 上一张真实、开放许可的芙蓉花照片，编写了 p5.brush 草图。一个视觉模型对每张草图给出了书面反馈，并经过三轮迭代优化。随后，每一幅最终渲染图都由我逐一评分，最终有 178 幅入选。

生成器 画作数量

GLM-5.2 64

Kimi-K3 57

Qwen3-Coder-Next 35

Qwen3.5-122B-A10B 22

在这里，我选择了四个不同的模型家族来测试它们的不同风格。这四款是在快速可靠性检查中每次都能生成有效草图的开放模型，另外两个候选模型因未通过该检查而被淘汰。如果你想生成自己的画库，也可以选择其他模型。

这两个层级，实际看起来就是这样。对评分持不同意见是合理的——现在，某个人的判断就成了奖励函数。

这些层级在奖励机制中发挥着实际作用。当两两比较的评判器抽取四个参考样本时，一半来自“喜爱”层级，一半来自“尚可”层级，因此策略总会面对一些它有时能击败的对手，而且无论对手来自哪个层级，获胜获得的奖励都是一样的。这是我自己为数不多的刻意改动之一：原始版本只与最高层级进行比较，而我保留了较容易的层级参与抽取，这样早期较弱的策略仍然能获得有效信号。

其中没有任何人类创作的画作，这是一个实实在在的局限。p5.brush 是一个小众库，其中带有可获取代码的人类作品也只有寥寥几件，远达不到训练语料库所需的数量，他的博客也提到了这一点。

这里有趣的想法，正如我之前已经讨论过的，是模型将学会模仿语料池中所包含的内容。如果我们把环境指向一个不同的数据集，奖励就会自动改变，而无需改动一行代码。对于我生成并公开分享的数据集，我也附带了源草图。

如果我们更仔细地审视这些评判器，会发现它们回答的是不同的问题。HPSv3 判断它是不是一朵花，而两两比较的评判器判断它是否以我选择的风格被画得很好。

再来一次 yolo 运行

在一切开始奏效之前，有一段漫长的奖励曲线平直期。如果你曾尝试在没有开放工件的情况下复现一篇研究论文或博客，你大概能感同身受。每一次运行都在检验我当时认为合理的、关于问题出在哪里的理论。一次运行要花很长时间，所以我一边分析上一次运行的结果，一边把下一次运行排进队列。一如既往，答案是从一个更简单、能跑通的东西开始，然后再在其基础上叠加。第一个真正学会的尝试是一个简单的控制任务，没有浏览器、没有裁判，而原因在于我的学习率实在太低了。

针对奖励做了三个实验，得到三条平直线。我更换了样本池、去掉了渲染器噪声、关闭了成对裁判，但曲线纹丝不动。真正让曲线动起来的那次运行改的是训练器配置，所以差异出在训练器上，而不是奖励组合。

另一个让我花了不少时间才发现的问题是正确调整 LoRA 参数。通常的 target_modules 列表假设的是稠密模型，而 Qwen/Qwen3.5-35B-A3B 是一个混合专家模型，它的大多数投影层命名方式不同，所以适配器只训练了四十层中的十层。我通过把它改成 all-linear 解决了这个问题，这样能覆盖每一个线性层。该架构中的路由专家是融合张量，即使 all-linear 也会让它们保持冻结，但其余每一层都挂上了适配器，而这已经足够让模型学会任务了。

修复方案是对 TRL 的 GRPOTrainer 做四处改动：

把 从 改为 为什么

学习率 2e-5 5e-5 LoRA Without Regret 为 GRPO 设置的学习率上限

调度器 线性 带预热的常数 线性衰减在训练中途就已消耗掉大部分学习率，因此奖励始终没有起色

scale_rewards 组 无 组内一个门控被拒绝，导致其他所有优势都被压缩

target_modules 手工列表 全线性层 覆盖每一个线性层

这四项改动带来了第一次成功运行（仅超参数调整），奖励明显提升。

在这种配置下，三次运行都能正常学习。两次 judge 运行均设定为 200 步，在 110 步时停止，此时奖励仍在缓慢上升。每一步耗时十五到十八分钟，且不同混合方式之间的对比已经趋于稳定，因此我停止了这两次运行以节省算力。每次运行前三分之一和后三分之一的组平均奖励如下：

运行 步数 前三分之一 后三分之一 Δ

仅 hps 60 0.58 0.71 +0.13

judge 主导 110 0.45 0.72 +0.27

hps 主导 110 0.57 0.82 +0.24

三条曲线与我的品味所占权重完全对应。评判权重越高，起点就越低，攀升过程中的波动也越大。judge-led 在最初三十步几乎持平，之后才开始移动。这与解决调试问题用的是同一种方法：先把问题缩小到能学到东西的程度，再把困难的部分一次一个地加回去。

在使用了成对评判的两组运行中，成对评判项本身都在攀升。随着训练推进，模型在与样本池的对比中赢得更多比较，这是仅用 hps 无法做到的。任何一组运行中都没有出现各组奖励收敛到完全相同的情况——那是会扼杀梯度的 GRPO 失败模式。好奇的读者可以在仓库中找到按指标划分的曲线（HPSv3、画面覆盖率、熵），格式为 CSV。

完整的启动命令、硬件配置，以及将本次运行转变为另外两次运行所需的两个环境变量，都记录在配方中。

它实际学到了什么

在每一次运行中，模型首先学到的是停止生成糟糕的画作——那些近乎空白的画布和不成形的色块，其总奖励低于 0.3。在仅用 hps 的运行中，组均值上升的四分之三来自劣质画作的减少。在加入评判的运行中，下降更为陡峭：在 judge-led 中，低于 0.3 的 rollout 从 99 降至 16（按三段划分）；在 hps-led 中则从 37 降至 4。

这就是为什么最直观的视觉呈现——每一步的最佳画作——在仅用 HPS 的跑动中几乎看不出差异。它在整个跑动过程中移动了 +0.034，而中位数移动了 +0.155。学习效果在分布的中段清晰可见。

成对评判器改变的是顶端。在仅用 HPS 的情况下，画作变得更可靠，却没有变得更好。优质画作的质量仅为组均值增加了 +0.03，而一旦 HPSv3 看到了中心周围的花瓣和花茎，它就不再要求更多颜料。有了评判器参与，故事的另一半才显现出来。这里的“更好”意味着更接近样本池，也就是更接近我评为“好”或我更喜欢的作品。这在评判器主导的跑动中增加了 +0.12，在 HPS 主导的跑动中增加了 +0.16，每一步的最佳画作也有所提升，并且两次跑动中的颜料覆盖率都翻倍了（0.11 到 0.23，以及 0.13 到 0.30），而仅用 HPS 时几乎没怎么变动。有了可供超越的参照物，一幅好画还能变得更好，模型也开始因使用更多颜料而获得奖励。

还有一个发现。模型忽略了一条明确的指令，而它这样做是对的。系统提示词要求十五到三十个填充形状。如果我们看实际均值，它在 7 到 9 之间，而且 n_shapes 在任何跑动中与奖励的相关性都微乎其微（+0.000、−0.14、+0.07）。策略并不会因为遵守那句话而获得奖励，所以它不遵守。

仅用 HPS 的路线也存在一个上限。如果每次 rollout 都能达到其最佳水平，那次跑动的均值会停在 0.771。更多步骤是否能突破这个上限，仍是一个悬而未决的问题。

这些画作还展现了表格所遗漏的东西。在每一轮运行内部，所有画作看起来都很相似。随着训练推进，每组内部的奖励值越来越接近，开场视频中处于中位水平的画作看起来就像同一朵花的不同拍摄版本。这正是 GRPO 在基于单一主题构建的样本池上运行时，所发挥的它应有的作用。样本池决定了什么算作多样性，就像它决定了什么算作质量一样。如果奖励只奖励画出一朵特定的花，模型就会学会画那一朵花。更多样的输出需要更多样的样本池，而构建这样的样本池需要更多的策展工作。Surya 较新的构图就是这方面的一个例子。Alex Yango 的动物画作采用了同样的配方，只是在样本池中做了不同的选择。这是审美奖励与数学评分器之间最大的区别。在数字背后，有一项非常人性化的工作，即决定什么该被纳入奖励集。Jason Liu 关于品味（taste）的文章用一句话概括了普遍版本：AI 将瓶颈从“创作”转移到了“发现”。

Surya 在博客结尾分享了他最喜欢的一些画作。与其由我来挑选，不如在下面展示一面墙，上面有奖励机制在两轮评审运行中评分最高的 178 幅画作，数量与参考样本池中的数量相同，排列不分先后。打开它，挑选你自己的最爱吧。

奖励机制在两轮评审运行中选出的 178 幅最爱画作，已随机打乱顺序。现在，来挑选你的最爱吧。

为了做出选择，你浏览了许多画作并保留了几幅，而这正是构建本项目奖励机制所需的工作。每一轮运行的每一幅画作，连同其草图与奖励值，都包含在 rollout 数据集中，并可在本画廊中浏览。

每一轮最后一次运行的中位绘画结果，排列顺序与开场视频一致。相同的基础模型、相同的候选池、三种奖励混合方式、三种风格。

由于奖励部分基于我的个人审美，最后以我作为观看者的评价来收尾是公平的。在我看来，judge-led 是最终结果最多样化、艺术趣味最丰富的一轮。hps-led 画出了令人信服的水彩画，但它最好的作品共享一种柔和、湿画法的质感，几乎自成一种风格。hps-only 收敛得最厉害，它的大多数画作都落在相同的配色上。你可以在画廊中自行判断，那里有每一轮的每一幅画，可按步骤和奖励排序。

基础设施很难

这个项目主要是基础设施工作。一轮运行需要一个训练器、两个 Space、一个推理路由和一个 WebSocket 来连续数小时保持健康运行，而每一个悄悄失败的组件都会在别处变成一个错误的数字。一半的工作是检查你读到的数字是否与实际发生的情况相符。

基础设施的故障会以零值的形式进入奖励。一次渲染超时或评分器无响应，与一幅糟糕的画作得分相同，组内都是 0.0。在我所有的运行中，这大约占 rollouts 的 1.5%，在最差的一轮中达到了 5.2%。这会让模型在噪声上训练，因此这些路径现在返回 None，该 rollout 会被排除在组外。

我还在 OpenEnv 中发现了一个 bug，并把修复提交到了上游。客户端会保持一条持久的 websocket 连接，而远端关闭的 socket 仍会留在缓存中，导致即使环境运行正常，后续每次调用也都会失败。我为此损失了两次跑到一半的实验才找到问题。修复已提交到上游，使用该修复启动的实验运行至今一直保持正常。

这是由裁判主导的那次运行中连续两步的对比，每一步取四张中最好的结果。第 12 步的画作是否看起来差了半分，由你来判断。

每一步的奖励取决于它抽到了哪些参照图。成对裁判每一步会采样四张参照图，因此每一步面对的对手组合都不同，有些抽签本身就更难。GRPO 本身基本是安全的，因为优势值是在组内计算的，抽到难签会让整组一起移动。而我所观察的曲线并不安全，一些看起来像是表现不佳的步骤，其实只是抽到了难签。上图就是一个例子。第 12 步比第 11 步低了半分，主要是因为它在整个运行中抽到了最难的参照图，而画作本身看起来相差无几。

成本是多少

取整后的数字，且仅针对已完成的运行。

张 需要什么资源

训练器 1 块 H200。60 步约需 18 小时，110 步约需 34 小时

HPSv3 一个 a100-large 规模的 Space，在整个运行期间保持在线

运行环境 一个 cpu-upgrade 规模的 Space，渲染时间充裕、流畅完成

成对比较评判器 Qwen/Qwen3-VL-30B-A3B-Instruct 的 Inference Providers 配额

共享资源池，一次性使用 来自 iNaturalist 的开放许可照片、四个生成模型的 Inference Providers 配额，以及你自己投入的评分时间

一步包含八次 rollout，耗时十五到十八分钟，其中 70% 到 80% 的时间用于渲染。单次渲染需要 69 到 96 秒，而截止时间是 90 秒。部分原因在意料之中：该 Space 没有 GPU，因此 Chromium 以软件方式渲染 WEBGL 画布，而 p5.brush 的晕染和纹理是计算量很大的像素操作。即便如此，我原本预期会更快，而且我还没有找到全部原因。

一个评分模型的成本可能超过使用它的训练本身：HPSv3 必须在整个运行期间保持在线，所以运行结束后要暂停该 Space，或设置其休眠定时器。

四个付费服务必须同时保持健康运行。只有 Hub 和 trackio 能比这次运行活得更久。

一切都在 HF Jobs 上运行，环境采用 Docker Space 形式，指标记录在 trackio 中。

我接下来会尝试什么

这个项目的规则是用全部开放资源复现配方，而不是改进它，所以一路走来积累了一堆未尝试的想法。以下是我真正会去尝试的，按证据充分程度排序。

多步生成，并让模型看到自己画了什么。这是我会首先尝试的。原博客训练的是单轮，所以我也训练了单轮，在这种设置下，模型是闭着眼睛作画的。没有任何图像输入，它得到的唯一反馈就是一个数字。反馈回路有效的证据就是画作池本身。参考画作出自一个在视觉评判器下迭代三轮的模型，而后面的轮次质量更好。定义奖励的材料是用策略模型永远接触不到的回路制作出来的。

更小的模型。有证据表明 35B 超出了实际需要。在我的旁路实验中，一个 4B 模型已经能写出通过门控的有效草图。如果 4B 就能学会这个，实验成本会下降一个数量级。

清单上的其他想法包括：在开始强化学习之前先在画作池来源上做 SFT；显式奖励颜料用量；随着训练推进，把评判器的参考混合从简单逐渐过渡到困难，直到只剩下“爱”；扩大十种方法的允许清单以获得更多视觉范围（我在这方面的尝试导致更多草图崩溃，也破坏了水彩质感）；以及通过给同一张图打两次分来检验成对评判器到底有多一致。

而且这种方法并不局限于花朵。Alex Yango 用同样的机制绘制了动物，Brendan Hogan 则用一批人工评分的视频片段来训练画布动画。我之前也用过 Simon Willison 的 pelican 基准做过类似的尝试——把代码渲染成图像再打分。

而在这一切背后，悬着一个这个项目无法回答的问题：由模型生成的 178 幅画作，定义了这款训练模型认为什么是美。这个评分池是瓶颈所在，也是整条流程中最没有原理性答案的一环。

我相对原作做了哪些改动

对于任何想复现这项工作的人，需要说明的是，我在两个地方有意偏离了 Narreddi 的做法，这两点在前文都已讨论过：

成对评判器的参考样本一半取自“喜爱”档、一半取自“还行”档，而不是只与最高档对比，这样早期较弱的策略仍然能获得有效信号。

提示词里有一句很小的工艺性描述：每片花瓣画两到三遍——先大笔铺一遍，再在内部叠一层更小、更不透明的笔触。

其余部分——LoRA 全程使用全线性调度、基础设施故障时返回 None 而不是 0.0、评判器运行在第 110 步停止——都是我在过程中不得不做的决定，因为他的博客没有写明这些细节。他的实现没有公开，所以我无法判断这些选择是与他的做法一致还是有所偏离。

所有内容均已公开

产物 位置

配方及复现方法 02-watercolour/

参考池，含全部源草图 watercolour-reference-pool

环境，可直接复制 watercolour-env

HPSv3 评分器，可直接复制 watercolour-hpsv3

仅 HPS 的适配器与 rollout watercolour-grpo-hps-only · watercolour-rollouts-hps-only

裁判主导的适配器与 rollout watercolour-grpo-judge-led · watercolour-rollouts-judge-led

HPS 主导的适配器与 rollout watercolour-grpo-hps-led · watercolour-rollouts-hps-led

画廊，全部画作可浏览 水彩画廊

训练曲线 实时：裁判主导 · HPS 主导 · 仅 HPS，以及 results/ 目录下的 CSV 文件

全部内容 用代码作画

本文中每次 rollout 的数据都可以根据已发布的数据集重新计算。本文内容不依赖任何 Space 保持在线运行。

该方法和原始创意出自 Surya Narreddi。该库由 Alejandro Campos Uribe 编写。
