用 TRL 和 OpenEnv 训练编码模型画水彩:Hugging Face 全流程开源复现
Training a coding model to paint watercolours with TRL and OpenEnv
Hugging Face 博客作者基于 Surya Narreddi 的原始想法,用 TRL、OpenEnv 和 Qwen/Qwen3.5-35B-A3B 复现了让语言模型通过 p5.brush 写 JavaScript 画水彩的 RL 训练流程,所有数据集、环境、脚本和模型均开源在 Hub。
作者用 TRL 和 OpenEnv 完整开源复现了让编码模型画水彩的 RL 配方,含数据池、环境和三组奖励对比,可整体迁移复用。
8 月 23 日,Surya Narreddi 发布了一段由语言模型绘制水彩画的精美视频。该模型通过 p5.brush 编写 JavaScript,这是一个“为 p5.js 添加自然绘图工具”的库。这段视频迅速走红,截至撰写本文时播放量已超过 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,即让模型从人类偏好中学习一个奖励模型。
这里的奖励是审美偏好。不存在正确答案。这个项目的真正问题在于:你是否能针对审美偏好做强化学习。
奖励的定义,按照他的博客所述,也按照我所构建的 RL 环境的实现方式,如下:
| 指标项 | 权重 | 衡量内容 |
|---|---|---|
gate | 0.05 | 草图能编译、能绘制出画面、不作弊 |
length | 0.05 | 轻微偏向更长的代码片段 |
| 两两对比评审器 | 0.60 | 风格,与从池中抽取的参考图进行对比 |
| HPSv3 | 0.30 | 对渲染结果的审美偏好 |
HPSv3 是一个开源的 7B 偏好模型。给它一张图片和一段文字描述,它就会返回一个分数,表示人们对该图片的偏好程度。它是在大量人类对图片两两比较的选择数据上训练的,因此它的分数是许多人品味的平均值。两两比较的评判者是 Qwen3-VL-30B-A3B-Instruct,这是一个通过 HF Inference Providers 调用的通用视觉模型。该评判者会将候选画作与从池中随机选取的四张参考图并排展示,并依据一段书面描述来指导其评判重点(晕染、半透明水洗、柔和边缘),每次比较都会以两种展示顺序进行,其分数就是候选画作在比较中获胜的比例。它唯一的标准就是参考池,因此它的分数就是我的品味,即编码在这些评分中的品味。

奖励函数中的四个项里有两个是模型。两者都是某人品味的代理指标。
这些就是 Narreddi 收敛出的权重。参考池在此定义了品味。这就把工作从调整超参数,转变为构建那个决定何为美的集合。
我使用这一奖励函数训练了三轮实验,它们之间的唯一区别在于两个模型评判器之间的权重分配方式不同:
| 实验轮次 | 成对评判器 | HPSv3 | 角色 |
|---|---|---|---|
judge-led | 0.60 | 0.30 | 原始混合方案,在第 110 步停止 |
hps-led | 0.30 | 0.60 | 中间点方案,在第 110 步停止 |
hps-only | 0.00 | 0.90 | 验证实验,在第 60 步停止 |
我先用 hps-only 验证了这套流程是否真的能学会。一旦奖励在上升、各项指标也健康,就没有必要再跑更久,于是我转而启动了两轮更长的训练。这两轮更长训练要回答的问题是: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 幅画作组成,根据我的个人偏好分为两个层级,love 和 okay。所有这些画作实际上都是由模型生成的。四个开放权重模型通过 Inference Providers 调用,各自基于 iNaturalist 上一张真实且开放许可的芙蓉花照片来编写 p5.brush 草图。一个视觉模型对每张草图给出了书面反馈,并经过三轮迭代优化。随后,每一幅最终渲染图都由我逐一评分,最终有 178 幅入选。
| 生成器 | 绘画数量 |
|---|---|
| GLM-5.2 | 64 |
| Kimi-K3 | 57 |
| Qwen3-Coder-Next | 35 |
| Qwen3.5-122B-A10B | 22 |
在这里,我选择了四个不同的模型家族来测试它们的不同风格。这四款是在快速可靠性检查中每次都能生成有效草稿的开源模型,另外两个候选模型因未通过检查而被淘汰。如果你想建立自己的候选池,也可以选择其他模型。

这两个档次的实际效果对比。对评分持不同意见是合理的——现在,某个人的判断就是奖励函数。
这些层级在奖励机制中确实发挥着实际作用。当成对评判器抽取四个参考样本时,一半来自 love,一半来自 okay,因此策略始终会面对一些它有时能击败的对手,而且无论击败哪一层级,获得的奖励都是一样的。这是我为数不多的几处有意改动之一:原始方法只与最高层级进行比较,而我保留了较容易的层级参与抽取,这样早期较弱的策略仍然能获得有效信号。
其中没有任何人类创作的画作,这是一个实实在在的局限。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 设置的上限 |
| 调度器 | linear | constant_with_warmup | 线性衰减在训练中途就已消耗掉大部分学习率,因此奖励始终没有起飞 |
scale_rewards | group | none | 一个门控的拒绝正在压缩组内其他所有优势 |
target_modules | 手工列表 | all-linear | 覆盖每一个线性层 |
这四项改动促成了首次成功运行(hps-only),奖励值明显提升。
在该配置下,三次运行均成功学习。两个评判(judge)运行均启动 200 步,并在第 110 步停止,此时奖励值仍在缓慢攀升。每一步耗时十五到十八分钟,且不同混合方案之间的对比已经稳定,因此我停止了这两次运行以节省算力。每次运行前三分之一与后三分之一的组平均奖励如下:
| 运行 | 步数 | 前三分之一 | 后三分之一 | Δ |
|---|---|---|---|---|
hps-only | 60 | 0.58 | 0.71 | +0.13 |
judge-led | 110 | 0.45 | 0.72 | +0.27 |
hps-led | 110 | 0.57 | 0.82 | +0.24 |
三条曲线与我的偏好所占权重完全对应。评判者权重越大,起点就越低,爬升过程也越嘈杂。judge-led 在开始移动之前,前三十步几乎保持平直。这与解决调试问题所用的方法是同一个思路:先把问题缩小到能学到东西为止,然后再把困难的部分一项一项加回去。
在两轮使用了成对评判项的运行中,该评判项本身确实在攀升。随着训练推进,模型在与池中样本的对比中赢得更多比较,这正是 hps-only 无法宣称的结论。任何一轮运行中都没有任何分组坍缩到完全相同的奖励——那是 GRPO 会扼杀梯度的失败模式。好奇的读者可以在 仓库中以 CSV 格式查看 各指标的曲线(HPSv3、绘画覆盖率、熵)。
完整的启动命令、硬件配置以及将本次运行转变为另外两轮运行所需的两个环境变量,都写在 配方 中。
它实际学到了什么
在每一次运行中,模型学会的第一件事就是停止产出劣质画作——那些近乎空白的画布和不成形的晕染,其总奖励得分低于 0.3。在 hps-only 中,组均值上升的四分之三来自劣质画作的减少。在裁判(judge)运行中,崩塌更为陡峭:得分低于 0.3 的 rollout 在 judge-led 的三个阶段中从 99 降至 16,在 hps-led 中则从 37 降至 4。
这就是为什么最直观的视觉呈现——每一步的最佳画作——在 hps-only 中几乎看不出差异。它在整个运行过程中移动了 +0.034,而中位数移动了 +0.155。学习过程体现在分布的中间部分。
成对裁判(pairwise judge)改变的是顶端。 在 hps-only 中,画作变得更可靠,却没有变得更好。优质画作的质量仅为组均值贡献了 +0.03,而一旦 HPSv3 看到中心周围的花瓣和花茎,它就不再要求添加更多颜料。有了裁判介入,故事的另一半才显现出来。更好在这里意味着更接近参考池,因此更接近我评为“好”的作品,或我更喜欢的作品。这在 judge-led 中增加了 +0.12,在 hps-led 中增加了 +0.16,每一步的最佳作品也随之提升,两次运行中的颜料覆盖率都翻了一番(0.11 到 0.23,以及 0.13 到 0.30),而 hps-only 几乎未能推动其变化。当有一个参考目标需要超越时,一幅好画还能变得更好,模型也开始因使用更多颜料而获得奖励。
还有一个发现。模型无视了一条明确的指令,而且它这么做是对的。系统提示词要求画出十五到三十个填充形状。但如果我们看真实均值,它介于 7 到 9 之间,而且 n_shapes 在任意一次运行中都与奖励几乎不相关(+0.000、−0.14、+0.07)。该策略并不会因为遵守那句话而获得奖励,所以它不遵守。
hps-only 这条路线也存在天花板。如果每一次 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。在我所有的运行中,这大约占 rollout 的 1.5%,而在最差的一次运行中达到了 5.2%。这会让模型在噪声上进行训练,因此这些路径现在会返回 None,并且该 rollout 会被排除在组外。
我还在 OpenEnv 中发现了一个 bug,并把修复提交到了上游。客户端保持一条持久的 WebSocket 连接,而远端关闭的 socket 仍留在缓存中,导致即使环境本身健康,后续每次调用也都会失败。我花了两轮半途而废的运行才找到这个问题。修复方案已提交到上游,使用该修复启动的运行此后一直保持正常。

judge-led运行中连续两步的结果,各取四张最佳。第 12 步的画作是否看起来差了半分,就由你来判断了。
每一步的奖励取决于它抽到了哪些参照图。成对评判器每一步会抽取四张参照图,因此每一步面对的对手集合都不同,有些抽签天然就更难。 GRPO 本身基本是安全的,因为优势值是在组内计算的,抽到难签会让整组一起受影响。但我当时看的那条曲线并不安全,有些看起来像糟糕步骤的表现,其实只是抽到了难签。上图就是一个例子。第 12 步比第 11 步低了半分,主要是因为它是整次运行中抽到最难参照图的一步,而画作本身看起来相差无几。
成本是多少
取整后的数字,且仅针对已完成的运行。
| 单件作品 | 需要什么 |
|---|---|
| 训练器 | 1 块 H200。60 步约需 18 小时,110 步约需 34 小时 |
| HPSv3 | 一个 a100-large Space,在整个运行期间保持在线 |
| 环境 | 一个 cpu-upgrade Space,能够及时完成渲染 |
| 成对评判器 | 推理提供方(Inference Providers)配额 Qwen/Qwen3-VL-30B-A3B-Instruct |
| 池子、一次性 | 来自 iNaturalist 的开放许可照片、四个生成器的推理提供方配额,以及评分所花费的个人时间 |
一步包含八次 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;显式奖励颜料使用;随着训练推进,将评判器的参考素材从简单逐步过渡到困难,直到只剩 love;扩大十种方法的允许清单以覆盖更多视觉风格(我在这方面的尝试导致更多草图崩溃,也破坏了水彩质感);以及通过给同一张图像打两次分来检验成对评判器的一致性到底如何。
而且这个方法并不局限于花卉。Alex Yango 用同样的机制画了动物,Brendan Hogan 则针对一个由人工评分的片段池训练了画布动画。我之前也用过 Simon Willison 的 pelican 基准 做过类似的尝试,在那个基准里,代码会被渲染成图像并接受评分。
而在这一切之下,潜藏着一个这个项目无法回避的问题。模型生成的 178 幅画作,定义了该训练模型眼中何为美。这个画作池是瓶颈所在,也是整条流水线中唯一没有原则性答案的环节。
我对原方案所做的改动
对于任何想要复现此项目的人,需要说明的是,我在两处有意偏离了 Narreddi 的方案,这两处都在文章前面论证过:
- 成对评判器的参考画作一半来自
love,一半来自okay,而不是只与最高档画作进行比较,这样即使早期策略较弱,也仍能获得有效的反馈信号。 - 提示词中有一句小小的工艺性描述:每片花瓣画两到三遍,先大面积铺一遍底色,再在内部叠一层更小、更不透明的笔触。
其余部分——all-linear 用于 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 |
| 画廊,每一幅画作都可浏览 | watercolour-gallery |
| 训练曲线 | 实时数据:judge-led · hps-led · hps-only,以及 results/ 中的 CSV 文件 |
| 以上全部内容 | 用代码作画 |
本文中每次 rollout 的数据都可以根据已发布的数据集重新计算得出。这里没有任何内容依赖于某个 Space 保持在线运行。
该方法和原始创意出自 Surya Narreddi。该库由 Alejandro Campos Uribe 开发。
来源:Hugging Face:Blog(RSS) · huggingface.co