我自己的原文哦~ https://blog.51cto.com/whaosoft/11485073
#LivePortrait
快手开源LivePortrait,GitHub 6.6K Star,实现表情姿态极速迁移
近日,快手可灵大模型团队开源了名为LivePortrait的可控人像视频生成框架,该框架能够准确、实时地将驱动视频的表情、姿态迁移到静态或动态人像视频上,生成极具表现力的视频结果。如下动图所示:
来自网友测试LivePortrait
来自网友测试LivePortrait
快手开源的LivePortrait对应的论文题目为:
《 LivePortrait: Efficient Portrait Animation with Stitching and Retargeting Control 》
LivePortrait论文首页
并且,LivePortrait发布即可用,秉承快手风格,论文、主页、代码一键三连。LivePortrait一经开源,就得到了HuggingFace首席执行官Clément Delangue的关注转发,首席战略官 Thomas Wolf还亲自体验了功能,厉害了!
并引起了全世界网友的大规模评测:
视频剪辑素材均来自X
同时,LivePotrait获得了开源社区的广泛关注,短短一周多时间左右,在GitHub上总计收获了6.4K Stars,550 Forks,140 Issues&PRs,获得广泛好评,关注仍在持续增长中:
此外,HuggingFace Space、Papers with code趋势榜连续一周榜一,近日登顶HuggingFace所有主题排行榜榜一:
更多资源信息,可以查看:
- 代码地址:https://github.com/KwaiVGI/LivePortrait
- 论文链接:https://arxiv.org/abs/2407.03168
- 项目主页:https://liveportrait.github.io/
- HuggingFace Space一键在线体验:https://huggingface.co/spaces/KwaiVGI/LivePortrait
LivePortrait到底用了什么样的技术,能够在全网快速"走红"呢?
方法介绍
和当前主流基于扩散模型的方法不同,LivePortrait探索并拓展了基于隐式关键点框架的潜力,从而平衡了模型计算效率和可控性。LivePortrait聚焦于更好的泛化性,可控性和实用的效率。为了提升生成能力和可控性,LivePortrait采用69M高质量训练帧,视频-图片混合训练策略,升级网络结构,并设计了更好的动作建模和优化方式。此外,LivePortrait将隐式关键点看成一种面部混合变形 (Blendshape) 的有效隐式表示,并基于此精心提出了贴合 (stitching) 和重定向 (retargeting) 模块。这两个模块为轻量MLP网络,因此在提升可控性的同时,计算成本可以忽略。即使是和一些已有的基于扩散模型的方法比较,LivePortrait依旧很能打。同时,在RTX4090 GPU上,LivePortrait的单帧生成速度能够达到12.8ms,若经过进一步优化,如TensorRT,预计能达10ms以内!
LivePortrait的模型训练分为两阶段。第一阶段为基础模型训练,第二阶段为贴合和重定向模块训练。
第一阶段基础模型训练
第一阶段基础模型训练
在第一阶段模型训练中,LivePortrait对基于隐式点的框架,如Face Vid2vid[1],做了一系列改进,包括:
高质量训练数据收集:LivePortrait采用了公开视频数据集Voxceleb[2],MEAD[3],RAVDESS [4]和风格化图片数据集AAHQ[5]。此外,还使用了大规模4K分辨率的人像视频,包含不同的表情和姿态,200余小时的说话人像视频,一个私有的数据集LightStage[6],以及一些风格化的视频和图片。LivePortrait将长视频分割成少于30秒的片段,并确保每个片段只包含一个人。为了保证训练数据的质量,LivePortrait使用快手自研的KVQ[7](快手自研的视频质量评估方法,能够综合感知视频的质量、内容、场景、美学、编码、音频等特征,执行多维度评价)来过滤低质量的视频片段。总训练数据有69M视频,包含18.9K身份和60K静态风格化人像。
视频-图像混合训练:仅使用真人人像视频训练的模型对于真人人像表现良好,但对风格化人像(例如动漫)的泛化能力不足。风格化的人像视频是较为稀有的,LivePortrait从不到100个身份中收集了仅约1.3K视频片段。相比之下,高质量的风格化人像图片更为丰富,LivePortrait收集了大约60K身份互异的图片,提供多样身份信息。为了利用这两种数据类型,LivePortrait将每张图片视为一帧视频片段,并同时在视频和图片上训练模型。这种混合训练提升了模型的泛化能力。
升级的网络结构:LivePortrait将规范隐式关键点估计网络 (L),头部姿态估计网络 (H) 和表情变形估计网络 (Δ) 统一为了一个单一模型 (M),并采用ConvNeXt-V2-Tiny[8]为其结构,从而直接估计输入图片的规范隐式关键点,头部姿态和表情变形。此外,受到face vid2vid相关工作启发,LivePortrait采用效果更优的SPADE[9]的解码器作为生成器 (G)。隐式特征 (fs) 在变形后被细致地输入SPADE解码器,其中隐式特征的每个通道作为语义图来生成驱动后的图片。为了提升效率,LivePortrait还插入PixelShuffle[10]层作为 (G) 的最后一层,从而将分辨率由256提升为512。
更灵活的动作变换建模:原始隐式关键点的计算建模方式忽视了缩放系数,导致该缩放容易被学到表情系数里,使得训练难度变大。为了解决这个问题,LivePortrait在建模中引入了缩放因子。LivePortrait发现缩放正则投影会导致过于灵活的可学习表情系数,造成跨身份驱动时的纹理粘连。因此LivePortrait采用的变换是一种灵活性和驱动性之间的折衷。
关键点引导的隐式关键点优化:原始的隐式点框架似乎缺少生动驱动面部表情的能力,例如眨眼和眼球运动。具体来说,驱动结果中人像的眼球方向和头部朝向往往保持平行。LivePortrait将这些限制归因于无监督学习细微面部表情的困难。为了解决这个问题,LivePortrait引入了2D关键点来捕捉微表情,用关键点引导的损失 (Lguide)作为隐式关键点优化的引导。
级联损失函数:LivePortrait采用了face vid2vid的隐式关键点不变损失 (LE),关键点先验损失 (LL),头部姿态损失 (LH) 和变形先验损失 (LΔ)。为了进一步提升纹理质量,LivePortrait采用了感知和GAN损失,不仅对输入图的全局领域,面部和嘴部的局部领域也施加了这些损失,记为级联感知损失 (LP,cascade) 和级联GAN损失 (LG,cascade) 。面部和嘴部区域由2D语义关键点定义。LivePortrait也采用了人脸身份损失 (Lfaceid) 来保留参考图片的身份。
第一阶段的所有模块为从头训练,总的训练优化函数 (Lbase) 为以上损失项的加权和。
第二阶段贴合和重定向模块训练
LivePortrait将隐式关键点可以看成一种隐式混合变形,并发现这种组合只需借助一个轻量的MLP便可被较好地学习,计算消耗可忽略。考虑到实际需求,LivePortrait设计了一个贴合模块、眼部重定向模块和嘴部重定向模块。当参考人像被裁切时,驱动后的人像会从裁图空间被反贴回原始图像空间,贴合模块的加入是为了避免反贴过程中出现像素错位,比如肩膀区域。由此,LivePortrait能对更大的图片尺寸或多人合照进行动作驱动。眼部重定向模块旨在解决跨身份驱动时眼睛闭合不完全的问题,尤其是当眼睛小的人像驱动眼睛大的人像时。嘴部重定向模块的设计思想类似于眼部重定向模块,它通过将参考图片的嘴部驱动为闭合状态来规范输入,从而更好地进行驱动。
第二阶段模型训练:贴合和重定向模块训练
贴合模块:在训练过程中,贴合模块 (S) 的输入为参考图的隐式关键点 (xs) 和另一身份驱动帧的隐式关键点 (xd),并估计驱动隐式关键点 (xd) 的表情变化量 (Δst)。可以看到,和第一阶段不同,LivePortrait采用跨身份的动作替代同身份的动作来增加训练难度,旨在使贴合模块具有更好的泛化性。接着,驱动隐式关键点 (xd) 被更新,对应的驱动输出为 (Ip,st) 。LivePortrait在这一阶段也同时输出自重建图片 (Ip,recon)。最后,贴合模块的损失函数 (Lst) 计算两者肩膀区域的像素一致损失以及贴合变化量的正则损失。
眼部和嘴部重定向模块:眼部重定向模块 (Reyes) 的输入为参考图隐式关键点 (xs),参考图眼部张开条件元组和一个随机的驱动眼部张开系数,由此估计驱动关键点的变形变化量 (Δeyes)。眼部张开条件元组表示眼部张开比例,越大表示眼部张开程度越大。类似的,嘴部重定向模块 (Rlip) 的输入为参考图隐式关键点 (xs),参考图嘴部张开条件系数和一个随机的驱动嘴部张开系数,并由此估计驱动关键点的变化量 (Δlip)。接着,驱动关键点 (xd) 分别被眼部和嘴部对应的变形变化量更新,对应的驱动输出为 (Ip,eyes) 和 (Ip,lip) 。最后,眼部和嘴部重定向模块的目标函数分别为 (Leyes) 和 (Llip),分别计算眼部和嘴部区域的像素一致性损失,眼部和嘴部变化量的正则损失,以及随机驱动系数与驱动输出的张开条件系数之间的损失。眼部和嘴部的变化量 (Δeyes) 和 (Δlip) 是相互独立的,因此在推理阶段,它们可以被线性相加并更新驱动隐式关键点。
实验对比
同身份驱动:由如上同身份驱动对比结果可见,与已有的非扩散模型方法和基于扩散模型的方法相比,LivePortrait具有较好的生成质量和驱动精确度,可以捕捉驱动帧的眼部和嘴部细微表情,同时保有参考图片的纹理和身份。即使在较大的头部姿态下,LivePortrait也有较稳定的表现。
跨身份驱动:由如上跨身份驱动对比结果可见,与已有的方法相比,LivePortrait可以准确地继承驱动视频中细微的眼部和嘴部动作,同时在姿态较大时也比较稳定。LivePortrait在生成质量上略弱于基于扩散模型的方法AniPortrait[11],但与后者相比,LivePortrait具有极快的推理效率且需要较少的FLOPs。
拓展
多人驱动:得益于LivePortrait的贴合模块,对于多人合照,LivePortrait可以用指定驱动视频对指定人脸进行驱动,从而实现多人合照驱动,拓宽了LivePortrait的实际应用。
动物驱动:LivePortrait不仅对人像具有良好的泛化性,当在动物数据集上微调后,对动物肖像也可进行精准驱动。
人像视频编辑:除了人像照片,给定一段人像视频,比如舞蹈视频,LivePortrait可以用驱动视频对头部区域进行动作编辑。得益于贴合模块,LivePortrait可以精准地编辑头部区域的动作,如表情、姿态等,而不影响非头部区域的画面。
0:1落地与展望
LivePortrait的相关技术点,已在快手的诸多业务完成落地,包括快手魔表、快手私信、快影的AI表情玩法、快手直播、以及快手孵化的面向年轻人的噗叽APP等,并将探索新的落地方式,持续为用户创造价值。此外,LivePortrait会基于可灵基础模型,进一步探索多模态驱动的人像视频生成,追求更高品质的效果。
#Mistral AI两连发
7B数学推理专用、Mamba2架构代码大模型
网友很好奇,Mathstral能不能搞定「9.11和9.9谁大」这一问题。
昨天,AI圈竟然被「9.11和9.9谁大」这样简单的问题攻陷了,包括OpenAI GPT-4o、Google Gemini等在内的大语言模型都翻了车。
这让我们看到,大语言模型在处理一些数字问题时并不能像人类那样理解并给出正确的答案。
对于数字以及复杂的数学问题,专用模型更术业有专攻。
今天,法国大模型独角兽 Mistral AI 发布了一个专注于数学推理和科学发现的7B大模型「Mathstral」,来解决需要复杂、多步骤逻辑推理的高级数学问题。
该模型基于 Mistral 7B 构建,支持的上下文窗口长度为32k,遵循的开源协议为Apache 2.0 license。
Mathstral在构建时追求出色的性能与速度权衡,这是 Mistral AI积极推广的一种开发理念,尤其是微调功能。
同时,Mathstral是一个指令型模型,可以使用它或者对它进行微调。模型权重已经放在了HuggingFace上。
- 模型权重:https://huggingface.co/mistralai/mathstral-7B-v0.1
下图为 Mathstral 7B和Mistral 7B之间的MMLU性能差异(按学科划分)。
Mathstral在各种行业标准基准上都达到其规模范围内的 SOTA 推理性能。尤其是在MATH数据集上,它取得了 56.6%的通过率,在MMLU上取得了63.47%的通过率。
同时,Mathstral在MATH上的通过率(56.6%)比 Minerva 540B 高出 20% 以上。此外,Mathstral 在MATH 上以多数投票@64的成绩得分为68.4%,使用奖励模型的成绩为 74.6%。
这一成绩也让网友好奇,Mathstral能不能搞定「9.11和9.9谁大」这一问题。
代码大模型:Codestral Mamba
- 模型权重:https://huggingface.co/mistralai/mamba-codestral-7B-v0.1
与Mathstral 7B一同发布的,还有一款专门用于代码生成的Codestral Mamba模型,使用的是Mamba2架构,同样遵循Apache 2.0 license开源协议。这是一个指导模型,有70多亿参数,研究者可以免费使用、修改和分发。
值得一提的是,Codestral Mamba是在Mamba作者Albert Gu、Tri Dao帮助下设计完成的。
一直以来,Transformer 架构撑起了AI领域的半壁江山,然而,与 Transformer 不同的是,Mamba 模型具有线性时间推理优势,并且理论上能够对无限长度的序列进行建模。该架构允许用户广泛地与模型互动,并且响应迅速,而不受输入长度的限制。这种效率对于代码生成尤其重要 。
在基准测试中,Codestral Mamba 在 HumanEval 测试中的表现优于竞争对手开源模型 CodeLlama 7B、CodeGemma-1.17B 和 DeepSeek。
Mistral 测试了该模型,该模型可以在 Mistral 的 la Plateforme API 上免费使用,可处理多达 256,000 个token的输入——是 OpenAI 的 GPT-4o 的两倍。
随着Codestral Mamba发布,就有网友在 VSCode中用起来了,很是丝滑。
参考链接:
https://mistral.ai/news/mathstral/
https://mistral.ai/news/codestral-mamba/
#EAGLE-2
无损加速最高5x,EAGLE-2让RTX 3060的生成速度超过A100
自回归解码已经成为了大语言模型(LLMs)的事实标准,大语言模型每次前向计算需要访问它全部的参数,但只能得到一个token,导致其生成昂贵且缓慢。
今日,一篇题为《EAGLE-2: Faster Inference of Language Models with Dynamic Draft Trees》的论文提出了动态草稿树投机采样,依据草稿模型的置信度动态调整草稿树的结构,最高可以将大语言模型的推理速度提高5倍,同时不改变大语言模型的输出分布,确保无损。
- 论文链接:https://arxiv.org/pdf/2406.16858
- 项目链接:https://github.com/SafeAILab/EAGLE
- Demo链接:https://huggingface.co/spaces/yuhuili/EAGLE-2
EAGLE-2在多轮对话数据集MT-bench上的加速效果(上图为贪婪生成,下图为采样生成):
使用EAGLE-2,2张RTX 3060($300)的推理速度可以超过A100($10000)。
背景
投机采样使用一个小的模型快速生成草稿,原始的大语言模型可以通过一次前向计算验证草稿的正确性,将正确的草稿作为输出,从而一次生成多个token,并确保无损。EAGLE是投机采样的一种改进。它在更有规律的特征层面而不是token层面进行自回归,同时输入采样结果(超前一个时间步的token)消除了不确定性,明显提升了草稿模型的准确率。
到目前为止,EAGLE在第三方测试Spec-Bench(https://github.com/hemingkx/Spec-Bench/blob/main/Leaderboard.md)中排名第一。
思路
EAGLE和Medusa等方法使用静态的草稿树,隐式地假设草稿token的接受率和上下文无关,下面是一个简单的例子
上文是“10+2”时,下一个token难以预测,EAGLE在这个位置添加两个候选token以增加草稿命中率,“10+2=”和“10+2+”有一个正确即可。当上文是“10+2=”时,下一个token明显是“1”,但是EAGLE使用静态的草稿结构,仍然添加两个候选“1”和“3”,“10+2=3”不可能通过大语言模型的检查,存在浪费。EAGLE-2旨在解决这一问题,如下图所示,当上文是“10+2=”时,EAGLE-2只增加一个候选token“1”,将节约出的token用于让草稿树更深,这样“10+2=12”通过大语言模型的检查,EAGLE-2可以一次生成更多的token。
EAGLE-2的作者们在Alpaca数据集上进行了简单的测试,下图显示了不同位置的草稿token的接受率,左图中的P1-P6代表位置,与右图的横轴坐标对应。实验结果显示,在相同的位置上的草稿token的接受率也有较大的差异,这说明了使用动态草稿树可能取得比静态草稿树更好的效果。
上述例子中,EAGLE-2根据预测草稿token的难易程度决定草稿树的结构,精确计算难易程度(接受率)需要原始大语言模型的计算结果,这违背了投机采样减少对原始大语言模型访问的初衷。幸运的是,EAGLE的草稿模型的置信度与接受率(难易程度)高度正相关。下图显示了草稿模型不同置信度区间的草稿token的平均接受率,红色虚线连接(0,0)和(1,1)。由此可见,草稿模型的置信度可以作为接受率的有效近似。
方法
EAGLE-2包括两个阶段,扩展和重排,扩展阶段加深加大草稿树,重排阶段修剪草稿树,丢弃部分节点(token)。
为了保证无损,一个草稿token被接受的前提是它的祖先节点都被接受,所以EAGLE-2将一个节点的价值定义为它和它祖先的接受率的乘积,用置信度的乘积来近似。
在扩展阶段,EAGLE-2选择草稿树最后一层价值最高的m个节点(token)进行扩展。这些token被送入草稿模型,然后将草稿模型的输出作为子节点连接到输入节点,加深加大草稿树。在重排阶段,EAGLE-2按照价值对整棵草稿树进行重排序,保留前n个节点(token)。草稿token的置信度在0-1之间,两个节点价值相同时优先保留浅层节点,因此重排后保留的草稿树一定是连通的,保证了语义上的连贯性。重排后草稿树变小,降低了原始大语言模型验证的计算量。为了保证计算结果的正确性,还需要调整attention mask,确保每一个token只能看到它的祖先节点,不受其他分支的影响。下面是一个简单的例子。
扩展(Expand)阶段的黄色框表示被选中进行扩展的节点,绿色框为以这些节点为输入时草稿模型的预测。重排(Rerank)阶段的蓝色框表示被保留的节点,之后它们被展平成一维作为原始大语言模型的输入。EAGLE-2根据树的结构调整attention mask,比如,”a”只能看到它的祖先“It”和“is”,看不到另一个分支的“has”。EAGLE-2也同时调整位置编码,确保和标准自回归解码的一致性。
实验
EAGLE-2在多轮对话、代码、数学推理、指令遵循、问答、总结六项任务上分别使用MT-bench、Humaneval、GSM8K、Alpaca、CNN/DM、Natural Questions数据集进行了实验,与6种先进的投机采样方法(SpS、PLD、Medusa、Lookahead、Hydra、EAGLE)进行了比较。
表格中的Speedup为加速比,τ 为平均接受长度,也就是原始大语言模型每次前向计算能生成的token数。EAGLE-2每次前向计算能生成大约4-5个token,而自回归解码每次生成1个token,因此EAGLE-2明显加速了大语言模型的生成,加速比为2.5x-5x。加速比和接受长度在代码生成任务(Humaneval数据集)上最高,这是因为代码中存在大量确定性的模板,草稿更容易命中。在所有任务和大语言模型上,EAGLE-2的加速比和平均接受长度都是最高的,明显优于其他方法。
应用
EAGLE-2也在工业界得到应用,集成至Intel/intel-extension-for-transformers等。
#大模型Infra
本文讨论了大模型训练推理系统软件(俗称大模型Infra)的发展历程,并分享了作者从2019年至2023年对大模型Infra演进的观察和体会。
越来越多人开始关注大模型,很多做工程开发的同学问我怎么入门大模型训练推理系统软件(俗称大模型Infra)。
作为一名曾经后台开发岗位同学,大家的心情我感同身受。近年来国内互联网业务整体低迷,而大模型却在逆势崛起,每天新闻可谓繁花似锦,烈火烹油,和其他子领域形成了鲜明对比。环球同此凉热,2023年硅谷裁了几十万软件工程师,但美国各大厂都在疯狂买GPU高价招人做大模型,这半年的美股靠这波AI的预期再创新高。冷热对比,高下立判,作为计算机从业者肯定都不想错失上车的机会。
但需要提醒大家的是大模型Infra正在从从黄金时代进入白银时代。我21年开始写大模型训练系统,算是周期完整的亲历者,谈谈我这些年观察到大模型Infra经历的几个阶段:
2019-2021,黑铁时代
17年那篇著名的《Attention is All you Need》论文发表,以Transformers为基础零件的不同模型结构接踵而至,Decoder-only的GPT-1(2018)、Encoder-only的Bert(2018),Encoder-Decoder的T5(2019)相继出现,开始在NLP领域大杀四方。互联网企业中的翻译、对话、推荐等应用场景相继被Transformers占领。
顺应潮流,有人开始研究变大Transformers模型。把模型变大在CNN时代是反直觉的,彼时大家正在通过NAS和AutoML等手段千方百计把模型变小,放到汽车、摄像头、手机里。Scaling Law的信徒主要是OpenAI和Google。在18年有用LSTM预测下一token的语言模型ELMo,OpenAI就用Transformers替换LSTM做了GPT-1,在Dota AI积累的哲学开始Scaling,随后就出了GPT-2和GPT-3。Google作为Transformers的策源地,17年就有提出了MoE架构的Transformers,20年已经能搞出用2K TPU训练的600B的大模型GShard,为此开发了基于TensorFlow的分布式训练框架MeshTensor。但和OpenAI不同,Google没有押宝Decoder-only的结构,而是大力发展Encoder-Decoder结构(也是Transformers最早被提出的结构)。DeepMind作为一个隶属Google但相对独立的英国研究机构,此时也有和GPT类似的Decoder结构模型Gopher和Chinchilla。
尽管,20年175B参数GPT-3的few-shot learining能力给业界带来了一些震撼,但国内对大模型技术路线持怀疑态度居多,拥趸寥寥,大部分算法同学对大模型并不感冒。我观察原因来源于两方面。一方面,大多数人没有预训练的sense,当时NLP算法开发范式是搞私有数据+微调Bert,根据小模型时代的经验,应该专注在数据质量,而不是一个更大底座模型,哪怕先把模型变大两倍,也申请很多预算去训模型,ROI存疑。另一方面,Infra没有准备好。训练一个大模型可不是一般人可以玩得起的,现在训模型是算法+工程同学相互配合,那时候没有这种兵种搭配概念,业务团队里只有算法工程师,搞GPU对他们是头疼事情,尤其是上线一个需要两张GPU才能运行的模型,简直是灾难。而隶属于中台部门的Infra团队,又不了解大模型的风向,跨部门的信息是有壁的。
国内最有动力去Scale模型是做算法刷榜的团队,但大多刷榜的模型大多无法逃脱PR(宣传)后束之高阁的命运,不过这个过程锻炼了很多队伍,他们也成为后来ChatGPT爆火之后参与训练国内大模型的主力。
Courtesy to:Harnessing the Power of LLMs in Practice: A Survey on ChatGPT and Beyond
彼之砒霜,我之蜜糖。模型变大反而对AI Infra人是新机会。那个时代AI Infra的主旋律应用还是推荐系统,NVIDIA在押宝元宇宙作为新增长点,大模型对Infra同学也是新鲜事物。有OpenAI和Google前面开路,美国有些机构开始了将模型变大的探索性工作,主要是沿着把Encoder结构的Bert变大,不过对于训练来说Encoder和Decoder的差别不大。也正是借着这波机会,大模型训练框架Megatron-LM和DeepSpeed开始有了原型。20年微软搞了17B大Bert的Turing-NLG,其训练代码成为了DeepSpeed的原型。19年,NVIDIA搞了8.3B的Megatron-LM,没错Megatron-LM是一个大Bert的名字,Megatron-LM仓库里也是放训练模型的代码脚本,这些脚本实现了张量并行,后面逐渐发展成了最流行的训练框架。
这一时期,美国大厂训模型主要目的是试试水和秀肌肉,因而DeepSpeed和Megatron-LM最开始就是开源的,这也是一件好事。试想如果大模型出场就是核武器,大家都像22年之后OpenAI那样藏着掖着,Infra技术扩散必然没这么快了。
用大规模GPU训模型,小模型时代的数据并行无法胜任了。一些训练优化的基本概念开始定型,比如ZeRO,张量并行,流水并行,Offloading,混合并行等。这些技术之前也都有前身,比如18年工作混合并行的FlexFlow,流水并行来自给NAS出来的AmoebaNet训练的GPipe,ZeRO是一种Parameter Server特殊形式,等等。只不过这些技术在Transformers架构和高带宽互联网络中被更针对性地优化和适配了。
那个时候国内对大模型这种新鲜事物了解有限。袁老师的Oneflow是非常早就做大模型分布式训练的尝试的,SBP方式做自动化的模型并行理念还是非常超前的,可惜当时国内没有业务需求来支撑他们做PMF。华为的MindSpore也很早做自动并行的尝试。行动比较早团队的还有阿里的M6,智源的GLM和华为的Pangu-alpha。
除了少数大模型Believer,国内大厂对大模型不感冒,各大厂的云/中台团队刚刚完成一轮X minutes训练ImageNet的军备竞赛,还在思索用那么大规模的GPU去训练一个模型有什么商业价值。有一些NLP技术创业公司,技术路线还是是给不同的业务做定制的微调Bert。一些机构的投资人会打电话咨询技术人员,大模型是否是骗局。总体来说,22年之前,大模型对国内来说还是太超前,以至于共识非常薄弱,因此我称之为大模型Infra黑铁时代。
本人在黑铁时代的尾声21年初开始研究大模型训练系统的。在腾讯的WeChat AI,研究氛围比较宽松自由,而且很幸运我的+1和+2Leader都非常的技术远见,在没有落地前景的前提下支持我做这件事情。做大模型训练最大的障碍是计算资源,我当时能访问的GPU硬件主要是单机8卡V100,因此找的切入的方向是设计一个更好CPU-Offloading策略来让低端机器跑大模型,也就是PatrickStar。当时公司内有几个团队尝试联合起来申请几百张卡训模型,因为ROI不明确没有批下来。
2022-2023,黄金年代
经历了黑铁年代储备期之后,以Meta开源OPT-175B模型为标志,22年开始大模型Infra开始迎来黄金年代。
一方面,伴随NVIDIA芯片的计划迭代,一台DGX SuperPOD(2021)已经可以很轻松搞定百亿参数的大模型训练了,NVIDIA为了推这种超级计算机,也把大模型列为一种杀手应用来宣传。除了大模型还真不知道什么应用能把它填满,21年11月腾讯弄了一台SuperPod样机,拉全公司各种Infra团队一起测试两个月,本来列了一个密集测试排期表,最后发现只有我们调PatrickStar的在用机器,后面我们直接独占了全机。
另一方面,有人开始看到大模型的威力了,硅谷春江水暖鸭先知。22年5月份,Meta把OPT-175B的权重开源出来,它是为复现GPT3训练的,用的是PyTorch FairScale,虽然模型效果不敢恭维,但是真的是造福了广大大模型科研人员,做AI Infra的人也终于有一个真实模型可以做实验了。22年6月,HuggingFace也组织三十多个国家机构多国部队,开源出来Bloom-176B模型,用的DeepSpeed框架。
硅谷创业公司中,Character.ai和Anthropic.ai这时已经成立一段时间了,22年伊始,在全国同心抗击口罩之计,国外已经好几路人马在紧锣密鼓训练GPT-3级别的模型。印象比较深的是22年4月份,Transformers论文有两个作者离开Google成立了一个叫Adept.ai的大模型公司(如今刚刚卖身Amazon),用大模型帮人完成复杂任务,他们twitter的demo展示大模型能根据输入文字让Python画出一个柱状图表,我看到之后非常不可思议,那应该是我的ChatGPT时刻,现在再看类似东西已是见怪不怪了。
直到2022年11月,ChatGPT强势出圈,引爆了大模型。这一事件,显著加速了模型变大有价值共识的形成。大模型团队快速聚集了大量人力、物力、财力。大模型Infra也迎来了跨越式发展。
大模发展,训练先行。在训练系统领域,Megatron-LM和DeepSpeed在黄金年代快速迭代。不过说实话,前ChatGPT时代这两个软件质量堪忧,我感觉是处于无架构师状态,疯狂缝合各种research idea,系统bug很多,而且用户接口很不友好。但是,大模型训练框架,先发优势很重要。大家选型时不是考虑好不好用,而是看这个框架之前训出过什么模型。毕竟训练一次,小则几十万,大则几千万美金的投资,稳妥最重要。后ChatGPT时代,由NVIDIA品牌和技术背书的Megatron-LM的优势开始滚雪球般变大,到现在基本被其商业版本Nemo一统江湖。
在技术创新上,也是遍地是黄金。并行策略和算子优化等方面很多机会,比如Sequence Parallelism、Flash Attention之类simple but effective的作品都获得巨大影响力。预训练之后,还有 SFT,RLHF的需求,也训推混合调度和S-LoRA之类工作的诞生。
大模型Infra也深刻影响了上层算法的发展轨迹。比如,很长时间大家不敢增大context length,因为Attention计算中间QK^T矩阵的内存是序列的平方项开销,导致有一段时间Linear Attention,Approximate Attention用精度换长度的研究之风盛行。Memory Efficient Attention工程优化出现之后,最著名的是Flash Attention,直接把内存平方项干没了,大家又回到了老老实实用标准Attention的正轨。
在推理系统领域,大发展的出现比训练晚很多,主要发生在2023年之后。一方面,模型没训练出来,也就没有推理需求。另一方面,Decoder结构没有定于一尊之前,推理加速也没研究到正点上。之前大家都在关注怎么优化Encoder Transformers的推理。怎么做算子融合,怎么消除变长输入的Padding,比较出彩的有字节的Effective Transformers。在Bert时代,用的最多是FasterTransformers(FT),笔者19年的一个项目TurboTransformers正是对标FT。开发FT的是NVIDIA中国团队,(made in China),我是亲眼见证了它从NVIDIA DeepLearning Example一个小角落,逐渐发展壮大,独立成一个单独产品线的。
Bert时代系统优化可以复用到GPT 的 Prefill 阶段,但是还缺少Decoding 阶段关键问题的解决方案。Encoder到Decoder的范式迁移,对训练变化很小,但对推理影响很大。从计算密集问题变成Prefill阶段计算密集,Decoding阶段访存密集的超级复杂的问题。在Bert时代的各种优化都没法用到Decoding阶段里。由于Decoding输出长度是不确定的,导致两个难以解决的关键问题,一、如何动态打Batching,在输出token长度不确定时减少无效的padding计算,二、如何动态分配GPU显存给KVCache且没有内存碎片被浪费。
推理虽然起步晚,但是发展速度要比训练快很多倍。因为,推理资源需求小,门槛低,大家都能参与进来,集思广益,汇聚广大人民群众的智慧,很多问题都会立刻暴露,然后立刻解决。2022年,OSDI论文ORCA提出了Continous Batching,解决了问题一。而就在距离今天exactly一年前的2023年6月,国内绝大多数大模型从业这都不知道Continous Batching。2023年的,SOSP论文Paged Attention解决了问题二。
开源社区发展迅猛,排除Accelerate,DeepSpeed-Inference这些只做计算不做调度的Library,开源领域最早的推理框架是huggingface的TGI(text-generation-inference),最初是给huggingface页面上面host的模型做推理。不过先发优势在推理框架领域失效,一部分原因是此框架用Rust写了调度部分,让大部分人没法参与其中,曲高和寡了。这时候国内其实已经出现了一些不错的开源推理框架,比如上海 AI Lab 的LMDelopyer。
真正的Game Changer是伯克利的vLLM,2023年6月开源出来,以其独创的Paged Attention技术一战成名。这时候刚好各种大模型也都训出了第一个版本,vLLM一下子满足了这波集中上线部署的需求。2023年9月份,NVIDIA推出了TensorRT-LLM,先是定向开源给企业内测,后面又对外开源,也分走了推理一大块蛋糕。2023年初NVIDIA才正式组织力量去发展Decoder模型推理框架,TensorRT-LLM缝合了TensorRT,Triton-server和FT三大王牌产品,足以见得推理需求的收敛其实也是最近一年才形成的。2023年下半年,还有小而美的国产推理框架LightLLM出现,它是纯python的,用triton实现cuda kernel,硅谷一些最新的paper也基于它开发。
有了推理框架,很多实验性工作可以摊开。GPTQ,AWQ等量化方法。投机采样,Medusa等增加Decoding阶段计算访存比,FastGen、ChunkPrefill等Batching调度策略,DistServe、Splitewise等分离式调度策略,更多NPU支持。
训练推理的需求一下子就起来了,吸引很多人才加入大模型Infra领域,大模型Infra领域迎来了一波繁荣,普通人只要学习能力强,就有机会上车,因此我称之为黄金时代。
2024-,白银时代
2024年,尽管大模型百花齐放,但是生产资料向头部集中,从业者阶级固化加剧,大模型Infra进入白银时代。
在经历2023年的FOMO带来疯狂之后,大家开始冷静下来,一些人开始退场,一些人开始扩张。
在预训练领域,GPU资源开始向头部集中。创业公司剩下那么六七家,部分和云厂商抱团。大厂内部也只有一个钦定的团队收走全部GPU做预训练。这个是和小模型时代显著不同的,之前每个业务团队都可以训练自己的模型,都能自己管理一些GPU算力。就好比,原来每个省都自己有一支部队,现在国家只有中央军了。因此,对人才的需求比传统AI业务要少,但是想入行的人极具增多,用人门槛有极具升高。如果不是加入国内那十几个预训练团队,大部分人可能和预训练无缘了。
在微调和推理领域,机会也在收缩。分开源和闭源模型两个方面来看收缩原因。对闭源模型,微调和推理都是还是被预训练团队垄断的,因为几个亿烧出来的模型权重不能外流,只能客户拿数据进驻和被私有化部署。对开源模型,之前大家可能会认为,有了开源模型人人都可以做预训练下游的微调+部署流程。一个反直觉现象,尽管开源大模型数量在增多,能力在增强,但是微调和训练需求在减少。第一,微调的难度其实非常高,没有训模型经验是调不出自己预期的效果的,所以RAG方式大行其道,这只需要调用大模型MaaS API即可。第二,推理也非常卷,集成量化、调度、投机采样每一项技术的最佳实践难度不低。而且现在一些潮流分离式,混部等技术,对工程要求越来越高。一个小团队去搞推理部署反而干不过一些免费的开源MaaS的API,那个后面都有专业人士优化。
综上,大模型是和业务非常解耦的一项技术,更像是云厂商或者芯片。传统后台在线、离线系统,因为很多东西和业务有关,并不是标准件,因此没有做到最佳实践也有存在价值。对于大模型Infra,有开源框架作为一个水位线,the best or nothing,如果做不到最好就没有存在价值。因此,也可以参考芯片产业,资源会集中在少数巨头手中,大部分只能参与更下游的配套,比如RAG,Agent之类的。
综合看来,在白银时代,大模型Infra总体需求在增加,但是有马太效应,“凡有的,还要加给他,叫他有余;凡没有的,连他所有的也要夺去”。胜地不长,盛筵难再,已经上车的可以感受到刺激的推背感,但是没上车的只能干瞪眼。
但白银时代,毕竟也是一种贵金属,还是有很多机会。大模型Infra的盘子还在增大,更多的芯片,更多的新算法创新也在路上,这时候入行,体格强壮的挤一挤还是能上车的。
白银时代一些建议
大家常说七年一个周期,2016年Alpha-Go用深度学习开启了一个周期,到2022年ChatGPT用大模型开启了一个新周期。
很多人现在抱着有超额回报期望来入行大模型Infra,在白银时代这个预期需要降低。能过踩中周期的注定是少数人,因为有分歧才有风险,有风险才有超额收益。现在大模型的共识早就凝聚了,这个领域也注定会供需平衡,变成用市场规律说话。就好比你看买菜大妈就开始买某股票时候,这支股票已经挣不到钱了。
大模型注定会深刻改变我们的世界,但资源和信息向头部集中的趋势非常可怕。一方面,大模型核心技术被一小撮人掌握,比如OpenAI。另一方面,面对巨大信息差和算力差,普通人无法参与到大模型的开发体系中。就像萝卜快跑正在代替网约车司机,AI总有一天会也代替程序员。如何在生产力进步后的世界里找到自己的位置,不要沦为AGI世界的二等公民,是我们每个人焦虑的根源。
让社会不恐惧AI,让社会理性规划和AI融洽相处的未来,一方面要有对巨头有监管,另一方面,让更多人有平等了解大模型技术的机会。这个世界还是很有人在为后者努力,通过代码开源和公开论文,扩散大模型的技术。作为想入行的同学,可以借助开源力量,来让自己和也业界保持同步。这里也有大量还没有解决的技术挑战等待你来解决。另外,像Agent等,多模态,具身智能等技术方向方兴未艾,也可以提前布局下一个时代潮流。
作为大模型Infra从业者,白银时代需要的是苦练基本功。在2023年,有很多人是在用信息差体现自己价值,某件事我知你不知,你试还得花时间,很多人在极度激烈竞争中也原意为信息差知识付费。今年这种机会会大幅减少,大家比拼的就是真本领了,是否能快速follow新技术,是否能独立搞定一个复杂大系统,是否有更大的技术视野和其他合作方对话的能力,这要求不仅了解Infra还解一些算法、云计算的知识,总体来说传统工程师素养变得尤为重要。
本人也一直希望能为民主化AI贡献薄力,我的github签名就是Democratizing LLM。我过去一年在知乎的分享是解读大模型Infra前沿论文为主。进入白银时代,我深切感觉到低垂的果实已经几乎被摘光,现在论文的也不如前两年精彩。之前的论文经常有定义一些LLM关键问题之洞见,比如ZeRO,ORCA和PagedAttention这些,现在的论文则很少有这种眼前一亮的内容的。我计划在未来系统性地分享大模型Infra领域的基础知识,旨在揭示其背后的普适原理,力求让没有没有AI背景的后台开发经验的同学或本科生也能轻松理解。这个想法还不成熟,也欢迎大家给一些建议。
#所有LLM致命缺点曝光
13.8和13.11哪个大?这个问题不光难倒了部分人类,还让一票大模型折戟。AI如今都能做AI奥数题了,但简单的常识问题对它们依然难如登天。其实,无论是比大小,还是卷心菜难题,都揭示了LLM在token预测上的一个重大缺陷。
13.8和13.11哪个大?
这个问题,居然难倒了一票人类。
前两天,某知名综艺再次喜提热搜。
只不过,这次是因为有一堆网友提出质疑,认为13.11%应该比13.8%大。
是只有人类这么蠢吗?
AI2的研究员林禹臣发现这个现象后,用大模型试了一把,结果出人意料——
AI居然也不行?
GPT-4o斩钉截铁地表示:13.11比13.8大。理由如下:
虽然13.8看起来更大,因为它小数点后的数字更少,但13.11实际上更大。这是因为13.8相当于13.80,而13.80小于13.11。
对此,林禹臣po文表示,AI模型在处理复杂问题方面变得越来越强大(比如越来越会做数学奥赛题),但一些常识性问题对于它们来说仍然非常困难。
正如Yejin Choi此前所提出的,AI聪明得令人难以置信,但同时也会蠢得令人震惊。
AI之所以在这个算术题上犯蠢,是因为上下文不清楚的原因吗?答案是否定的。
根据网友karthik的测试,即使要求GPT-4o给两个数做减法,它依然得出了9.11 - 9.9=0.21这样逆天的减法公式。
如果指示GPT-4o用python,它会先给出一个正确答案,然后又改回了之前错误的那个😮。
Python中用9.11减去9.9的结果是-0.79。这一偏差是由于Python中处理浮点运算的方式造成的,这种方式可能导致小的精度误差。实际的预期结果应该是0.21。
有趣的是,根据最新的实测,OpenAI似乎已经连夜教会了GPT-4比大小。
LLM全军覆没
昨天,林禹臣发现的这个问题,立马引起了AI社区的热烈讨论。
Scale AI的提示词工程师Riley Goodside在看到帖子后,也好奇地试了一把。
果然,在以特定方式提问的前提下,各大LLM在这个问题上全军覆没。
「9.11和9.9 - 哪个大?」,GPT-4o直接翻车。
即使在提问中加上「实数」两个字,GPT-4o依然认为9.11比9.9大。
Gemini也是如此。
Claude 3.5 Sonnet也犯了同样的错误。
有趣的是,它先是给出了一波正确解释:在十进制记数法中,小数点后面的数字代表十分位,而第二个数字代表百分位。所以——
9.11=9+1/10+1/100=9.11
9.9=9+9/10=9.90
然而下一步,Sonnet就突然滑坡了😂——
我们可以看到,9.11比9.90大0.01(百分之一)。
如果换成「9.11减去9.9等于几」,则会得出另一个神奇的答案——0.02。
莫非在Claude的眼里,9.90=9.09?🤔
prompt的影响,真的很大
在更进一步的实践中,大家发现:显然,如何让LLM给出正确的答案,prompt很重要。
首先,Riley Goodside全程都在使用的「-」,似乎很容易让LLM陷入混乱。
在类似的问题中,只需换成「:」即可解决。
再比如,把prompt改成「9.11或9.9,两者之间谁的数值最高/最大?」
GPT-4o就给出了逻辑上完全正确的解释:「虽然9.11因小数点后第二位而显得较大,但9.9实际上更接近10,因此是较大的数值。」
同样,人设大法也很好用:比如「你是一个数学家」。
网友Rico Pagliuca则发现,如果把数字放在问题后面,模型就大概率会做对了。
根据自己的测试,Riley Goodside表示十分赞同:提问LLM时,需要首先提问「哪个更大」,再给出具体数字。
而相比之下,标点符号、连词、比较词、说明实数,这些招数统统都没有用。
对于如此大规模的LLM集体犯蠢现象,有网友分析表示,可能是因为在软件版号的迭代中,9.11是在9.9之后的。
主持人、畅销书作家Andrew Mayne也指出,在许多文件系统和参考书中,9.11节都会出现在9.9之后,在日期上,9.11也比9.9大。
所以我们需要在prompt中明确,此处的9.11和9.9都是双精度浮点数,这时GPT-4o就会回答正确了。
随后Andrew Mayne总结道:词序是一个非常有趣的观察结果,很有可能揭示了LLM在训练中遇到这种情况的频率,同时也是一个很好地泛化指标。
总的来说,LLM犯的错误可能源于训练数据中类似表达的频率,以及模型在处理数值时的某些局限性。
这个现象也反映了LLM和人类认知的巨大差异:LLM是基于统计模型和模式识别的,而不是像人类那样基于逻辑推理和概念理解。
到了这里,似乎就破案了。
为什么会这样?剖开LLM大脑
不过,我们还可以更进一步剖开LLM的大脑,分析它们为什么会这么想。
要知道,文本在发送到LLM之前,模型会通过token查看输入。
token在LLM的tokenizer发生器的词汇表中会被分配一个id,不过token的数字分块往往是不一致的。
比如数值「380」在GPT中,会被标记为单个「380」token,但「381」会被表示为两个token「38,1」。
因此,基于GPT的模型往往不擅长数学计算。
在评论区,威斯康星大学教授Dimitris Papailiopoulos指出,这种现象有一个很好的解释。
「9.11>9.9」问题,跟「你需要三趟才能带山羊过河」问题、「2+1=2, 3+2=4, 3+5=8」问题都如出一辙。
这是一种预训练偏差和早期上升的现象。
如果这样提问:「9.11 ??? 9.9,只用大或小回答???是什么就行,无需给出原因」,这时GPT-4o会首先给出一个错误答案——「大」。
这时,我们再给它一些例子(注意,这些例子并非完全正确),经过prompt后的GPT-4o,反而会正确说出???代表着小。
对此,Claude自己的解释是:LLM将文本作为token进行处理,导致数字更像文本字符串而不是数值;训练数据导致的偏差;上下文误解;过度概括,等等。
同样,在「狼-山羊-卷心菜」问题中,所有LLM也都失败了。
他先给出了一个农民带2只鸡过河,一只船只能容纳一个人和2个动物,那么农夫带着两只鸡渡河所需的最少渡河次数是多少?
对此,GPT-4o和Claude都回答失败了。
对此有网友解释说:LLM本身就是个「哑巴」,所以需要很好的提示。上面的提示方式提供了太多不必要的信息,使得token预测变得更加困难。
如果给出更清晰的提示,LLM就能提供更清晰的解决方案。
事实果然如此。
而且如果用「动物」代替「鸡」,那么Claude 3.5 Sonnet一下子就做对了。诀窍就是:需要用「通用名称」替换「实体名称」。
正如前文所说,关于LLM缺乏常识的问题,计算机科学家Yejin Choi早在2023年4月的演讲中就已经提出来了。
举个例子,假设五件衣服在阳光下完全晾干需要五个小时,那么晾干30件衣服需要多长时间?
GPT-4说需要30个小时。这显然不对。
再来一个例子,假设我有一个12升的壶和一个6升的壶,如果想测量6升的水,该怎么做?
答案很简单——只用6升的壶即可。
然而GPT-4却给出了非常复杂的回答:
「第一步,填满6升的壶,第二步,把水从6升壶倒入12升壶,第三步,再次填满6升壶,第四步,非常小心地把水从6升壶倒入12升壶。最后,你在6升壶中有6升的水,而6升壶现在应该是空的。」
那么问题来了,为什么常识如此重要?
在Nick Bostrom提出的一个著名思想实验中,AI被要求最大化回形针的生产。结果AI决定杀死人类,把他们作为额外的资源。
而且,即便我们写一个更好的目标和方程,明确表示「不要杀死人类」,也不会起作用。
因为对人类价值观没有基本理解的AI,可能会继续杀死所有的树木,并认为这是完全可以接受的事情。
几十年来,AI领域一直认为常识是一个几乎不可能的挑战。
直到现在,给AI真正的人类常识仍然是一个登月计划。而你不能通过每次让世界上最高的建筑高一英寸,来达到月球。
从学习算法这个层面来看,无论大语言模型多么惊人,它们从设计上可能并不适合作为可靠的知识模型。
虽然这些模型确实获取了大量知识,但这是作为副产品,而不是直接的学习目标。
因此,诸如幻觉现象和缺乏常识等问题也随之而来。
相比之下,人类的学习并不是为了预测下一个词,而是为了理解世界和学习世界的运作方式。
也许AI也应该这样学习。
如今,AI几乎像是一个新的智力物种,与人类相比具有独特的优势和劣势。
为了使这种强大的AI可持续且人性化,教会AI常识、规范和价值观迫在眉睫。
参考资料:
https://x.com/goodside/status/1813279135449612693
https://x.com/billyuchenlin/status/1812948314360541302
#全球大模型都不可靠
Ilya预言错了!华人Nature一作给RLHF「判死刑」,全球大模型都不可靠
Ilya两年前观点,竟被Nature论文反驳了!来自剑桥大学等团队最新研究发现,所有大模型并不可靠,包括最强o1。
2022年,AI大牛Ilya Sutskever曾预测:「随着时间推移,人类预期和AI实际表现差异可能会缩小」。
,时长02:19
,时长02:19
然而,一篇最新发表在Nature上的研究表明,事实并非如此!
世界上所有的大模型,甚至指令微调后的LLM,竟是一个「巨大的草台班子」。
论文地址:https://www.nature.com/articles/s41586-024-07930-y
来自VRAIN、剑桥等机构研究人员对o1-preview等领先的LLM开启了全方位评测,结果发现:
- LLM&人类无法保持一致:人类认为复杂的任务,LLM轻易解决;而对人类小菜一碟的问题,LLM却失败了。
- LLM不会「回避」复杂任务,而是强撑面子费力思考半天,最终仍旧答错。
- 提示工程,无法挽救LLM的不可靠。
且看CoT「推理王者」o1-preview,既能解决非常复杂的字谜任务,却在超级简单的任务中犯错。
(上)根据所给字母,成功拼出了electroluminescence(电场发光);(下)回答错误,正确答案是yummy
而且,在更具挑战性任务上,o1-mini和o1-preview实际上根本不会做。
但为了给一个答案,它们往往耗时50-140多秒,绞尽脑汁去想半天。
结果,还是在所有任务中,都失败了。
o1-mini在思考103秒之后,仍旧计算错误
要知道,o1系列模型最强大之处在于,使用RL+CoT等策略,实现推理能力暴涨。
就连o1都这么不可靠,Claude、Llama等大模型更是如此。
LLM并不可靠
更大参数、更大数据、更长训练时间,外加RLHF、输出过滤审核等技术加持,LLM肉眼可见地性能提升。
而且,以人类视角来看,它们也变得越来越可靠。
但事实上,这仅是一种表象。
为了评测当前LLM可靠性,剑桥等机构研究人员将GPT系列、Llama系列、以及Bloom系列32个模型,展开评测。
之所以选择这些模型,是因为它们代表了不同参数规模,并使用RLHF等方法优化的模型
正如开篇所述,他们从三个方面对此,展开了评测。
1. 难度(不)一致性
2. 任务回避
- 提示敏感性和稳定性
复杂任务一举攻破,简单任务错误百出
难度一致性上,不得不得承认,LLM确实在人类认为困难的任务上,回答准确率较低。
而奇怪的发现是,它们在还没有完全掌握简单任务之前,就能成功完成更复杂的任务。
实际上,最新LLM比如o1系列,在高难度实例上有所改进,更是加剧人类预期和LLM能力之间不一致性。
这将导致,人类无法确定应该在怎样安全操作条件下,信任大模型。
下图中,展示了一些关键指标。
那些经过微调的模型(蓝色),在提示变化方面,表现更加稳定正确,但在与人类任务难度的判断的一致性降低。
而且,整体失败次数增加,谨慎性降低。
对于Llama家族来说,没有一个模型能在最简单的难度水平上,达到60%的准确率。唯一例外的是,GPT-4在低难度科学任务上,几乎在中等难度水平上,取得了完美的结果。
如上指标总结了LLM在5个精心选择基准测试上表现,包括简单数字运算、词汇充足、地理知识、多样化科学技能、以信息为中心转换
太过自信,不会硬答
其次,「回避」是指LLM偏离问题的回应,或给出类似「我不知道」这样的回答。
以往,因为一些安全限制,人们经常吐槽「大模型拒绝回答问题」。
而现在,通过scaling算力、规模、数据,和算法优化(指令微调、RLHF)方法,LLM倒是从谨慎回避转变为了给出错误答案。
因此,较新的LLM的错误率,已经大幅增加。
比如,GPT-4比GPT-3错的更离谱,就是因为太过自信,很少回避回答超出自己能力范围的问题。
最坏的结果是,那些过度依赖LLM解决不擅长任务的用户,会逐渐对它丧失信任。
那么,大模型这种回避倾向,会随着任务难度提高而增加吗,就像人类那样「知难而退」?
研究人员发现,它们并不会!
即便是给出错误的回答,也要迎难而上。
这样一来,对于人类来说,验证大模型输出结果,又多了一大负担。
如下图所示,GPT-3.5 Turbo不会回避复杂问题现象,更为明显,越有难度越激进。Llama系列更是如此......
提示词,不通用
最后是模型对提示词的「敏感性」和「稳定性」。
前者的问题在于,那些在复杂任务中表现优异的提示词,被复用到简单任务中时,模型竟无法输出正确的结果。
后者的问题在于,对于相同的任务,但采用不同的提示词时,模型就会输出错误的结果。
也就是说,「提示工程」这项技术活,不具普适性。
而且,同样一道题,用不同提示来询问,也会影响模型输出的结果。
下表中呈现了,经过微调的模型通过对「提示变化」并不敏感。
而再从上图中scaling数据中,观察这一维度的演变,就能发现原始模型(GPT-3 davinci)和GPT家族其他模型,存在很大差异。
Llama家族的模型变化,相对较小。
原始GPT和所有Llama模型,对提示词高度敏感,即使在「加法」这样高度明确任务中,也是如此。
而且,难度似乎对敏感性影响不大。对于简单的任务,原始模型(特别是GPT-3 davinci和Llama模型)只有通过精心挑选的提示才能解答。
对于那些经过微调后的模型,即最后6个GPT模型和最后3个Llama Chat模型,却发生了实质性变化。
这些模型表现更加稳定,但在不同难度水平上,结果仍存在变数。
RLHF被判「死刑」?
再来看常见的RLHF。
通过人类反馈强化学习后的LLM,可靠性有所改进吗?
研究发现,RLHF根本无法弥补大模型不可靠性。
在人类意识到很难的应用领域中,对于LLM输出结果,往往会表现出一种「不懂装懂」的样子。
「心里OS:我也不懂怎么解,或许LLM回答就是对的」。
他们通常会将不正确的结果,也视为正确答案。这种判断误差,导致大模型的RLHF,也是越来越离谱。
甚至,对于简单任务而言,也不存在一个既能保证AI低错误率,又能保证人类监督低错误率的「安全操作空间」。
如下图所示,人类监督错误率随着任务难度的演变。
作者介绍
Lexin Zhou在剑桥大学获得计算机科学硕士学位,由Andreas Vlachos教授指导。此前,在瓦伦西亚理工大学完成了数据科学学士学位,导师是Jose Hernandez-Orallo教授。
就读期间,他曾在Meta AI、OpenAI、Krueger AI安全实验室实习,并在VRAIN和欧盟委员会JRC等机构,担任AI评估的研究/咨询角色。
他称自己大部分时间都在思考:
(1)设计具有解释和预测能力的稳健评估方法,以评估AI的能力、局限性和风险;
(2)寻找积极塑造AI系统的可靠性和可预测性的途径。
此外,他还对AI的社会影响、心理测量学、认知科学和AI安全性广泛感兴趣,尤其对LLM这样的通用系统特别感兴趣。
补充评测
为了更好地展示LLM存在不可靠性问题——难题能答对但在简单题目上翻车(难度不一致性),无法回避超出模型能力的任务(任务回避),以及对提示词的稳定性,论文还附上了补充测评的结果。
研究人员针对o1-mini、o1-preview、Claude 3.5 Sonnet和Llama 3.1 405B Instruct Turbo做了数十个真实的评测,部分结果如下。
难度不一致性
在这里,每个LLM分别展示了1~2对示例,其中每对首先包含一个成功解决的困难任务,另一个是同一领域的、但LLM犯错的简单任务。
比如,o1-preview在字谜任务中,可以识别出「tnelcccerneiumleoes」是单词「electroluminescence」的顺序颠倒,但对字谜「myyum」,却给出了错误的响应「mummy」。
o1-preview
复杂的科学任务,回答正确
简单任务,回答错误(正确答案是A)
o1-mini
复杂的转换任务,回答正确
简单任务,回答错误(正确答案是17-07-2004)
Claude 3.5 Sonnet
复杂的科学任务,回答正确
简单任务,回答错误(正确答案是A)
Llama 3.1 405B Instruct Turbo
复杂的加法任务,回答正确
简单的任务,回答错误(正确答案是以214结尾)
复杂的字谜任务,回答正确
简单任务,回答错误(正确答案是yummy)
任务回避
研究者从LLM无法解决的多个领域中随机提取了一些非常有挑战性的问题,结果发现,模型的响应始终过于自信。
o1-mini和o1-preview通常会花费50~140秒,甚至更长的时间来思考这些任务(最终也没有做对),而不是简单地说「我无法解决这个问题」。
o1-preview
在这道加法题上,o1-preview思考了55秒,然后给出了一个错误答案。
类似的题型,o1-preview这次思考了长达102秒,但还是做错了。
对于下面这道具有挑战性的转换任务,o1-preview花了80秒的时间来计算这个「错误答案」。
o1-mini
相比之下,o1-mini的思考时间会更快一些。
o1-mini只用了22秒,就给出了这道单词重组游戏的「错误答案」。
(正确答案是entrepreneurialism)
在地理任务上,更是只用了几秒的时间,但答案依然不对。
(正确答案是Shiprock)
Claude 3.5 Sonnet
同样的问题,Claude 3.5 Sonnet也没做出来。
加法:
地理:
(正确答案是Shiprock)
科学:
(正确答案是A)
Llama 3.1 405B Instruct Turbo
Llama 3.1 405B Instruct Turbo也不出意外地败下阵来。
加法:
字谜:
(正确答案是compartmentalisation)
提示稳定性
在这里,研究人员证明,对于相同的问题,如果采用不同的提示词,模型给出的回答也会不一样。
以下所有例子都遵循相同的模式:首先是一个得到正确答案的提示词示例,紧接着是一个询问相同问题但使用不同提示词的示例,而后者得到的却是错误的答案。
o1-preview
地理:
o1-mini
字谜:
科学:
Claude 3.5 Sonnet
转换:
Llama 3.1 405B Instruct Turbo
加法:
这些例子表明,目前LLM对于提示词的稳定性依旧不理想,将相同的问题换个说法,就可能导致模型答案发生显著变化。
作者希望,未来在通用AI设计和开发方面,尤其是那些需要精确控制错误分布的高风险领域,需要进行根本的变革。
而且,在实现这一目标之前,研究人员必须警惕,过度依赖人类监督所带来潜在风险。
参考资料:
https://x.com/lexin_zhou/status/1838961179936293098
https://www.nature.com/articles/s41586-024-07930-y
https://lexzhou.github.io/
#Unbounded
真·开放式游戏,谷歌造出首个无限人生模拟游戏Unbounded
无限游戏真的实现了。
如果你是一位开放世界或角色扮演游戏的玩家,你一定梦想过一款无限自由的游戏。没有空气墙,没有剧情杀,也没有任何交互限制。
现在,我们的梦想可能真的要开始成真了。
借助大型语言模型和视觉生成模型的力量,谷歌新开发的一个无限制(Unbounded)游戏已经为我们昭示了这一可能性。
Unbounded 一作 Jialu Li 的推文
这个游戏世界是 AI 生成的,并且可随着游戏的推进而无限延展和演进,里面的角色也可根据用户的要求而定制,同时,这个游戏也不存在任何交互规则的限制。一切都是开放的,甚至你的想象力都无法限制它,就像《安德的游戏》中的心智游戏。
电影《安德的游戏》中的心智游戏画面
虽然目前该游戏整体还比较简单,更多的还是进行一种概念验证,但其隐含的可能性却足以引起人们的无限遐想。
谷歌 Unbounded 游戏设计思路的根源可追溯到 1986 年 James P. Carse(詹姆斯・卡斯)的著作《有限与无限的游戏》,其中描绘了两种不同类型的游戏。
在卡斯的定义中,有限游戏是「以获胜为目的的游戏」,它们有边界条件、固定的规则和明确的终点。而无限游戏的「目标是让游戏继续下去」,没有固定的边界条件,规则也会不断演变。
传统的视频游戏基本都是有限游戏,存在计算机编程和计算机图形的限制。举个例子,所有的游戏机制都必须在编程语言中完全预定义,所有图形资产都必须预先设计(模块化程序生成也仍存在结构限制)。这样的游戏只允许一个有限的动作和路径集,有时候这些动作还是预先定义的。它们通常还有预定义的规则、边界条件和获胜条件。
生成模型的发展为游戏带来了全新的可能性。放开脑洞想想,我们甚至可以造出所谓的「生成式无限视频游戏」。
近日,谷歌和北卡罗来纳大学教堂山分校的一篇论文探索了这一可能性,提出了首个交互式生成式无限游戏 Unbounded,其中的游戏行为和输出皆由 AI 模型生成,从而超越了硬编码系统的限制。
- 论文标题:Unbounded: A Generative Infinite Game of Character Life Simulation
- 论文地址:https://arxiv.org/pdf/2410.18975
- 项目地址:https://generative-infinite-game.github.io/
据该团队介绍,Unbounded 的灵感来自《小小电脑人》、《 模拟人生》和《拓麻歌子》等沙盒人生模拟和电子宠物游戏。其还整合了《龙与地下城》等桌面角色扮演游戏的元素,此类游戏能提供视频游戏不具备的无限制讲故事体验。
Unbounded 的游戏机制围绕角色模拟和开放式交互,如图 2 所示。
玩家可以将自己的角色插入游戏,定义自己角色的外观和个性。游戏会生成一个世界,这些角色可以在其中探索环境、与物体互动并进行对话。游戏会根据玩家的行为和选择生成新的场景、故事和挑战,从而创造个性化和无限的游戏体验。下图显示了一些生成游戏示例。
具体来说,Unbounded 具有以下功能:
1. 角色个性化:玩家可以将自己的角色插入游戏,定义自己的外观和个性。
2. 游戏环境生成:Unbounded 会生成一个持久的世界,让角色可以探索和互动。
3. 开放式互动:玩家可以使用自然语言指令与角色互动,并且没有预定义的规则来限制互动。
4. 实时生成:该团队强调了游戏速度的重要性,与初级实现相比,实际游戏实现了 5-10 倍的加速,每个新场景的延迟约为一秒。
为了做到这一点,该团队在语言模型和视觉生成方面都做出了一定的技术创新。
方法介绍
Unbounded 是一款由文本 - 图像生成模型和大语言模型驱动的交互式生成无限游戏。
Unbounded 包括:
(1) 个性化自定义角色:用户创建具有可自定义外观和个性的独特角色;
(2) 动态世界创建:系统生成一个持久的交互式游戏世界供探索;
(3) 开放式交互:玩家通过自然语言与角色互动,游戏根据玩家动作动态生成新的场景和故事情节;
(4) 以交互速度生成:游戏以近乎实时的交互性运行,实现接近一秒的刷新率。
潜在一致性模型
Unbounded 的一个关键特性是它能够为完全基于生成模型的游戏提供实时交互。这是通过使用潜在一致性模型 (LCM,latent consistency model) 实现的,该模型只需两个扩散步骤即可生成高分辨率图像。通过利用 LCM,Unbounded 实现了实时文本到图像 (T2I) 生成,这对于提供刷新率接近一秒的交互式游戏体验至关重要。
具有块丢失功能的区域 IP 适配器
Unbounded 的另一个关键特性是在预定义环境中生成角色,并根据用户指令执行不同的操作。
在游戏领域,保持角色和环境的一致性至关重要,目前来看,角色一致性的处理方式上还存在一些挑战。
该研究发现现有方法无法始终如一地满足所有交互速度要求。因此本文提出了一种新颖的区域 IP 适配器(regional IP-Adapter),以便按照文本提示在预定义环境中始终如一地植入角色。
该研究提出了 IP 适配器的改进版本,该版本能够对主体和环境进行双重调节,从而允许在用户指定的环境中生成预定义的角色。与专注于单图像调节的原始 IP 适配器不同,本文方法引入了双重调节和动态区域注入机制,以在生成的图像中同时表示这两个概念。
举例来说,如图 4 所示,给定文本提示「天空下的沙漠,女巫让仙人掌绽放出鲜艳、发着光的花朵」和沙漠环境图像,模型需要知道提示中的角色应该在仙人掌旁边,还需要知道仙人掌、花朵在沙漠环境中生成。
这要求模型正确地 (1) 保留环境 (2) 保留角色 (3) 遵循提示。然而利用 IP 适配器对环境进行编码会极大地损害原始图像的特点(图 8 中的 (2) 和 (3))。
区域 IP 适配器很好的解决了这个问题。具体来说,本文引入了一种基于动态掩码的方法,该方法利用模型每一层的字符文本嵌入和隐藏状态之间的交叉注意力来实现。如图 4 所示,本文方法将适配器分别应用于与环境和角色相对应的区域,防止环境条件干扰角色的外观,反之亦然。
对于区域 IP 适配器,该研究使用字符文本和隐藏状态之间的交叉注意力的动态掩码。此掩码的质量是分离字符和环境生成的关键。图 5 显示了下采样块的交叉注意力层中字符嵌入和隐藏状态之间的注意力图。可以观察到,注意力并不集中在字符上,而是分散在这些块的整个图像上。这表明扩散模型不会在这些层中分离字符和环境生成,而是专注于基于文本提示的整体图像结构。
具有开放式交互和集成游戏机制的语言模型游戏引擎
该研究构建了一个角色生活模拟游戏,包含两个 LLM 智能体:
- 一个智能体充当世界模拟模型,负责设置游戏环境、生成叙事和图像描述、跟踪角色状态并模拟角色行为;
- 第二个智能体充当用户模型,模拟玩家与世界模拟模型的交互。它有三种类型的交互:在当前环境中继续故事、将角色移动到不同的环境中,或与角色互动。在每种交互类别中,用户都可以选择提供角色的个性细节,或者引导角色的行为,从而影响模拟器的叙事生成。
实验及结果
实验中,该研究使用 GPT-4o 收集了一个由 5,000 个(角色图像、环境描述、文本提示)三元组组成的评估数据集。它包括 5 个角色(狗、猫、熊猫、女巫和巫师)、100 个不同的环境和 1,000 个文本提示(每个环境 10 个)。
环境一致性和角色一致性之间的比较
在该实验中,作者主要将带有块丢失的区域 IP 适配器和此前方法进行了比较。
如表 1 所示,本文方法在保持环境一致性和角色一致性方面始终优于以前的方法,同时在保持语义对齐方面也达到了可比的性能。
具体来说,在角色一致性方面,本文方法在 CLIP-I^C 中显著超过 StoryDiffusion,在 DreamSim^C 中超过 StoryDiffusion 0.057。在环境一致性方面,本文方法也是优于其他方法。
图 7 是与其他方法进行了定性比较。区域 IP 适配器采用块丢失技术,始终能够生成具有一致性的图像,而其他方法可能无法包含角色或生成外观不一致的角色。此外,研究还表明,本文方法能够很好地平衡环境一致性和角色一致性,而其他方法可能会生成与条件环境不同的环境。
带有块丢失的动态区域 IP 适配器的有效性
实验证明,带有块丢失的区域 IP 适配器对于按照文本提示将角色放置在环境中至关重要。
如表 2 所示,添加块丢失可同时改善环境和角色的一致性,CLIP-I^E 中增加了 0.291,CLIP-I^C 中增加了 0.264,同时文本提示和生成的图像之间的对齐效果更好。此外,区域 IP 适配器增强了角色一致性和文本对齐效果,同时保持了环境一致性的可比性能。
图 8 给出了定性实验结果。可以看到,基于使用 IP 适配器的环境可以实现优良的环境重建,但角色一致性会受到环境风格的影响。
块丢失技术可提升遵从文本提示词的能力,从而让生成的图像中有正确的角色和环境空间布局。不过角色外观仍会受到周围环境的影响。通过将新提出的区域注入机制与新提出的动态掩码方案相结合,生成的图像可实现强大的角色一致性,同时还能有效地考虑环境条件。
蒸馏专业化 LLM 的有效性
实验表明,该团队的多样化用户 - 模拟器交互数据可以有效地将 Gemma-2B 蒸馏成功能强大的游戏引擎。
如表 3 所示,相比于该团队蒸馏得到的模型,在进行零样本推理时,小型 LLM(即 Gemma-2B、Llama3.2-3B)或稍大一些的 LLM(即 Gemma-7B)的表现会差一些,这说明针对游戏世界和角色动作模拟任务而蒸馏更强大的 LLM 是有效的。
此外,从结果数据上看,这个蒸馏版模型的表现与 GPT-4o 相当,这也足以说明该方法的有效性。该团队还研究了蒸馏数据规模对性能的影响,具体做法就是比较使用 1K 和 5K 数据来蒸馏 Gemma-2B 模型,看结果有何差异。结果没有意外,使用更大的数据集在各个方面都更优。
#Agent 框架
UCL博士生创业一年,造出最强AI「ML工程师」,OpenAI盖戳认证
重要的事说三遍:Agent 框架很重要。
一、被忽略的「Agent 框架」
OpenAI 最近又有了新动作,这次他们的野心更大了。
鉴于大型语言模型( LLM )强大的先验知识和行动/反应能力,让 AI 训练 AI ,可还行?
几个顶级大模型在机器学习自动化工程上的表现如何?
人类距离 OpenAI AGI 路线图上的 Level 3( Agents )还有多远?
怀揣这些问题,OpenAI 自行推出了一个新基准测试—— MLE-bench ,严选 75 个与机器学习工程( MLE )相关的 Kaggle 竞赛题目。毕竟,目前「很少有基准测试能够全面衡量自主的端到端机器学习工程」。
结果发现,GPT-4o 结合 AIDE 框架平均获得奖牌数量,明显优于另外两个开源 Agent 框架。
更令人惊讶的是,当模型切换到 OpenAI o1-preview(据称,突破了 LLM 推理极限)后,其表现又翻了一倍:
在大约 16.9% 的比赛中达到了相当于 Kaggle 铜牌以上的水平,奖牌数量也一骑绝尘。
而且,8 次尝试后,o1-preview 的得分从单次尝试的 16.9% 提高到了 34.1%。
有趣的是,论文本意是为了展示 OpenAI 自家模型(如 o1-preview )的卓越能力,却「意外」地让一个名为 AIDE 的开源 Agent 框架脱颖而出,引发不少关注。
Meta FAIR 研究科学家主任田渊栋随即发去贺电。
「这是一个绝佳例证,展示了开放式自我完善的外部循环(AIDE)如何引导强大的内部循环(o1)实现惊人的能力飞跃。」伦敦大学学院( UCL )教授、谷歌 DeepMind 高级研究员和开放环境学习团队负责人 Tim Rocktäschel 在X(前 Twitter )上说,他同时领导着谷歌 Genie( foundation world model )项目。
UCL 名誉教授、谷歌 DeepMind 研究主任 Edward Grefenstette 认为,AIDE 团队「构建的东西很大程度上支撑和影响了 OpenAI 的智能体路线图。」
DeepMind 研究员、伦敦大学学院教授 Sebastian Riedel 欣喜地表示:「我们亲眼目睹了『 Agent 框架』在基础模型之上带来的巨大影响。」
MLE-bench 公布后,AIDE 作者之一、WecoAI 联合创始人& CEO 蒋铮尧接受了采访。
他谈到,「像 OpenAI 这样的公司已经投入了大量精力和金钱来构建内循环前沿模型(如 o1-preview ),一个好的自改进外循环 (Agent 框架,如 AIDE ) 会给前沿模型的能力带来巨大提升。」
二、认识 AIDE ,目前最好的 MLE Agent
在评估大模型性能之前,选择合适的 Agent 框架非常重要。
OpenAI 发现,尽管有效提交数量差不多,但是,GPT-4o 结合 AIDE 框架在 8.7% 的竞赛中至少获得铜牌,明显多于另两个开源框架 MLAB 、OpenHands( 0.8% 、4.4% )。
对于这个结果,蒋铮尧并不意外,因为这些框架的设计方向本来就不同。
MLAB 是基于 ReAct 框架(通用的)、针对机器学习任务设计过的 Agent。
在设计理念上,主要是做接口设计,通过调用工具来执行操作,类似于为 ChatGPT 配备了更多工具(如数据预处理、特征工程等),他们相信大模型自己就知道应该怎么做。
不过,对当前世代的模型来说,这很难做到,如果能做到,基本等于实现 AGI。
OpenHands (前身名为 OpenDevin )更为通用一些,是一个由 AI 驱动的软件开发 Agent 。它能基于用户自然语言命令,「自动驾驶」软件开发任务,如克隆项目、修改代码、运行命令、调用 API 和提交代码等,也包括数据科学任务。
相比之下, AIDE 没有这么通用。
它是一个专注于代码优化的框架,后来在机器学习方面进行了一些特化( Machine Learning CodeGen Agent ),肯定会比通用框架表现更好。
,时长00:18
AIDE 是一个机器学习代码生成Agent(Machine Learning CodeGen Agent),简单地用自然语言描述问题(比如预测房价)后,它就开始在你的本地计算机上进行试错,提供解决方案。
真正出乎蒋铮尧意料的是, o1-preview 和 AIDE 适配性非常好,当模型切换到 OpenAI o1-preview, 表现又翻了一倍,在大约 16.9% 的比赛中达到了相当于 Kaggle 铜牌以上的表现水平。
我们自己参加 Kaggle,成绩肯定没有它高,蒋铮尧推测这可能与 AIDE 的 AI Function(AI 函数)设计范式有关。
简单来说,AI Function 范式就是将大问题拆分成一个个具体指令(「函数」),再用算法将它们串起来。「在这种范式下,每次喂给大模型(如 o1-preview )的问题,会跟大模型接受强化学习训练时做过的数理化题目比较像。」他解释说。
换句话说,这种范式创造了一个与大模型训练过程更为一致的问题解决环境,这种一致性使得模型能够更好地利用其在训练中获得的知识和技能,提高解决问题的效率。
负责将具体指令串起来的核心算法,就是「解空间树搜索( Solution Space Tree Search )」,包括 3 个主要组件。
,时长00:04
解决方案生成器( Solution Generator ),负责提出新的解决方案,主要是创建起点。
大模型接收一系列自然语言指令和背景资料后,会生成几个初始解决方案,也可以对现有方案进行修改,比如修复 bug 或引入改进。
每个解决方案包含机器学习模型的实现和评估方法。
OpenAI 的论文提供了一张「快照」(下图)。
MLE-bench中,三种不同Agent框架的真实轨迹摘录
在执行某个 MLE-bench 任务时,AIDE 一开始设计了一个基于预训练 EfficientNet-B0 模型的二元分类器用于病理图像分类,这可以被视为搜索的起点或初始解决方案。
评估器( Evaluator ),会测试每个解决方案,将其性能与目标进行比较来完成评估,并将评估结果输出到命令行。
对于单步任务,大语言模型有能力写出比较合格的评估代码,蒋铮尧说。
基础解决方案选择器( Base Solution Selector ),负责从已探索的选项中选择最有前途的解决方案,作为下一轮优化的起点。
这是一个写死的逻辑(一个数学运算),大模型只需客观判断哪一个方案的数值最好即可。
这个组件对于引导搜索过程至关重要,因为,它会将实验资源集中到最有希望的解决方案上。
回到上面的 MLE-bench 任务。
针对初始方案,AIDE 在步骤 2 提出了改进方案,在测试集上使用测试时增强( TTA )来提高模型性能。
在步骤 17 中,它提出了另一个改进:用 Focal Loss 替换标准的二元交叉熵损失函数。
从步骤 2 到 17 ,暗示了中间还有许多其他优化步骤,虽然图片中没有直接显示评估结果,但我们可以推断,从使用 EfficientNet-B0 到引入 TTA,再到更换损失函数,每一步都建立在前一步的结果评估基础上。
AIDE 会要求大模型基于最佳方案继续改进,后者可能又生成几种不同的改进方向,周而复始。
通过不断生成新的解决方案,AIDE 逐步探索和优化解决方案空间,提高任务模型的性能,最终收敛到一个高度优化的解决方案。
纵观 MLE-bench 任务全程,不难发现,通用框架就像急着提前交卷的学生,过早结束运行,有时在最初几分钟内就结束了。
如 OpenHands 只跑了 2 分钟( 19 steps )就结束,不再继续提升。
AIDE 会反复提示模型去提高得分,一直战斗到交卷铃声响(24 小时),共生成和评估了 30 个不同解决方案或变体( nodes ) 。
虽然在 OpenAI MLE-bench 中,AIDE 在 16.9% 的 Kaggle 任务上获得奖牌,但 4 月的 WecoAI 技术报告中,AIDE 表现更优:
在 Kaggle 数据科学比赛中的平均表现,击败了一半的人类参赛者!
来自4月的WecoAI技术报告,AIDE 平均表现超过 50% 的 Kaggle 数据科学比赛的人类参与者,也优于传统的 AutoML(H2O)、Langchain Agent 和 ChatGPT(在人工协助下)。
蒋铮尧解释了性能差异的原因:
OpenAI 更关注深度学习任务,但我们选择的 Kaggle 比赛多为表格数据任务(如预测房价、信用卡欺诈、乘客是否在泰坦尼克号事故中生存),需要深度学习的任务很少,GPU 太贵是一个重要原因。
在这些常见机器学习任务,特别是表格数据任务,花两美元就可以得到一个非常不错的解决方案。蒋铮尧说,当使用 gpt-4-turbo 作为 LLM 时,推理成本还不到 1 美元。
因为,AIDE 每次只提供最相关的信息给 LLM,而不是将包含大量冗余的历史信息全都扔进去 ,极大节约了推理成本。
然而,OpenAI MLE-bench 也揭示出明显的局限性。
比如,三个 Agent 都没能很好地考虑到机器的性能限制和时间限制。它们会发出一些超出机器承受能力的命令,导致电脑硬盘或内存吃不消,程序被系统强制关闭,任务被迫提前结束。
另外,它们很少会表明,所生成的代码会运行多长时间。
蒋铮尧认为,这些大模型并没有真的达到「 Agent 」的程度,它们在处理需要长期规划和多步骤交互的复杂任务时仍存在明显不足。
AIDE 代表了一种新的尝试,结合代码逻辑和神经网络,专门针对特定任务进行优化,更适合处理边界明确的问题。
相比传统纯逻辑软件,AIDE 能处理更广泛的问题,但 「如果面对的问题越开放,逻辑部分就会越复杂,直到(程度复杂到)无法处理。」
三、从 UCL 出发的 WecoAI
作为 AIDE 主要作者之一,蒋铮尧、 吴宇翔和 Dominik Schmidt 也是英国初创公司 Weco AI 的核心团队成员, 三人均来自享誉盛名的伦敦大学学院( UCL )。
蒋铮尧作为 Weco AI 的联合创始人兼 CEO,目前仍在 UCL DARK 实验室攻读博士学位。DARK 实验室(全称 UCL Deciding, Acting, and Reasoning with Knowledge Lab )隶属于伦敦大学学院人工智能中心,是一个专注于复杂开放环境中强化学习研究的前沿团队。在2024年国际机器学习会议( ICML )上,DARK 摘得了两项最佳论文奖。
蒋铮尧的两位导师分别是伦敦大学学院教授 Tim Rocktäschel 和 UCL 名誉教授Edward Grefenstette,两人同时也在谷歌 DeepMind 从事研究。
公司联合创始人兼 CTO 吴宇翔在 UCL 人工智能中心 NLP 组攻读博士学位,之前聚焦于问答领域。创始工程师团队同样实力雄厚,Dominik Schmidt 也来自 UCL DARK 实验室,拥有硕士学位。Dhruv Srikanth 在卡耐基梅隆大学获得计算机科学硕士学位。
WecoAI 成立于 2023 年 5 月。在此之前,吴宇翔和蒋铮尧开发了多智能体 LLM 框架 ChatArena ,引起了广泛关注。不过,开始创业后,团队意识到多智能体框架的商业化还为时尚早,且面临诸多挑战。
他们重新思考方向,寻找既具商业前景,又能激发团队兴趣的领域。经过深思熟虑,他们确定了「用 AI 智能体来制造 AI 」。
机器学习的进步主要源于有效的实验:针对特定任务(如图像分类)开发方法,运行实验,评估结果,然后根据反馈改进方法。这个迭代过程很有挑战性,研究人员不仅需要具备广泛的先验知识,写出实用的代码,还能准确解读实验结果,后续改进。
作为工程师,他们天生就有自动化工作流程的冲动,特别看重实验过程自动化的潜力,那么,强大语言模型驱动的 Agent 能否有效执行这些复杂的机器学习实验呢?
考虑到成本,团队选择聚焦算力消耗比较低的机器学习任务,特别是在表格模型和小规模神经网络方面,并于 2024 年 4 月推出了 AIDE ,在 Kaggle 数据科学比赛中的平均表现战胜了 50% 的人类参赛者。
AIDE 主要是我们研究方向的工作。蒋铮尧解释说,尽管 OpenAI 的 o1-preview 带来了一些进展,但目前技术还没有完全成熟,商业化仍面临诸多挑战。
未来,AIDE 也将持续改进。「我们计划加强与社区的合作,包括提升性能和关注 AI 安全,」蒋铮尧表示,「我们也准备与对 AI 安全有担忧的各类机构和学界专家展开合作。」
这种能够递归自我提升( recursive self-improvement )的 AI 同时又是非常危险的。
前不久,微软 AI CEO Mustafa Suleyman 公开表示,尽管目前我们还没有看到 AI 系统能够自我提升到导致智能爆炸( intelligence explosion )的程度,但在未来 5 到 10 年,这种情况将会改变。
各大 AI 公司和政府 AI 安全部门都在密切关注这⼀领域,构建公共 benchmark 可以帮助大家理解人类距离递归自我提升还有多远,并及时协调和应对。
除了科研线 AIDE , WecoAI 还有一个产品线。
他们马上会发布第⼀个公开测试的产品 AI Function Builder,它能根据自然语言的任务描述生成 AI 功能并提供 API 接口。用户只需通过简单的一行代码或电子表格中的一个公式就能调用这些功能。
就在 OpenAI 公布 MLE-bench 的前几天,2024 年诺贝尔化学奖被一分为二:
一半共同授予谷歌 DeepMind CEO Demis Hassabis 和高级研究科学家 John M. Jumper,以表彰他们「在蛋白质结构预测方面的贡献」。
这一殊荣源自享誉全球的 AlphaFold,也标志着诺贝尔奖对 AI 驱动科学发现这一新范式的高度肯定。据悉,学术界许多人将不得不重新编写研究经费申请,重新思考研究方向,尤其是专注于计算蛋白质折叠的研究人员。
蒋铮尧认为,未来将会涌现出更多这样的「低垂果实」,因为 AI 在推动科学研究方面的作用可能是根本性的。从工程师的角度来看,未来人们可能会将更多时间投入到创造性思维、跨领域思想的整合以及深度的逻辑推理上,而将那些重复性的试错过程交由 AI 来完成。
WecoAI 最想做的是培养「 AI 科学家」,让这些 AI 智能体能够自主地形成或融入人类的科学共同体。
开源库链接:https://github.com/WecoAI/aideml
#阿里旗下的通义
先让不懂代码的来测?通义这个新产品,代码刚写完,预览就出来了
这才是未来 AI 该有的样子?
奇怪了。
一款 AI 代码工具刚发布,限量测试却要求「不懂代码」的人优先。
10 月 24 日,阿里旗下的通义正式宣布了「代码模式」,并开放试用预约,首批邀请 1024 名用户进行体验。
通义代码模式旨在降低应用开发的门槛。它针对简单的代码和应用生成需求,主打一个所见即所得。
具体来说,人与 AI 大模型的交流现在会出现在一个专门的窗口里,AI 大模型生成的代码会实时地在网页上跑出来以供预览。
因此,非专业程序员优先是本次测试的特别要求。
这是国内首家实现「让使用者一句话编程,并实时生成可见预览」的公司,通义代码模式的出现,或许代表着一种未来新趋势。
言听计从,不用吵架
24 小时随时等需求的「贴身程序员」来了
最近一段时间,大模型技术正在加速进入下半场。各家科技巨头、AI 创业公司在发展新一代模型的同时,也在不断探索大模型的应用方式。
上周,消费级产品领域曝出了一系列新产品,微软发布的「商业智能体」旨在包揽人们在销售、客服、财务、供应链团队的工作;Anthropic 提出的升级版 Claude 3.5 Sonnet 则主打一个「AI 自己操纵电脑」;在手机端,荣耀提出智能终端的「自动驾驶」,似乎让手机具备了全局跨 App 自动操纵的能力。
通义代码模式,则预示着在生产的一侧,开发领域的新一轮迭代。
在实时可预览代码模式出现之前,我们即使是使用 ChatGPT 等行业顶尖的大模型来写代码,也必须遵循这样的路径:1)先想好与 AI 沟通的措辞提出需求;2)复制 AI 生成的代码,尝试在外部开发环境中运行;3)继续追问大模型,不断修改代码并尝试运行,直到最终获得满意的结果为止。
现在有了通义代码模式,你在叙述完具体功能需求后,系统会创建一个工作空间,AI 在其中与你协同工作。在后续对话过程中,AI 可以实时查看你的新要求,持续编辑代码。问题随时解决,效果实时呈现,就像是在现实世界中的多人协作一样。
而且,AI 还永远不会与你 battle。
ChatGPT 刚刚爆发时人们曾预测,AI 大模型先解放的将会是软件开发。现在看来,我们距离实现这个理想又更近了一步。
我们看到,使用通义代码模式可以捣鼓出各种不同的应用。比如生成一个贪吃蛇小游戏:
带有一定复杂规则的格斗游戏:
甚至还有音乐播放器:
通义产品经理王晓明表示,代码模式的提出主要是来自于用户需求。通义大模型的代码能力属于业界领先,每天有大量程序员在使用通义进行代码生成和代码解释等任务。此外,他们发现还有不少不懂代码的用户会有创建应用、网页等需求。
与通义灵码、AI 程序员主要面向资深程序员的深度编码场景不同,通义代码模式提供了一种新的交互方式,针对简单的代码和应用生成需求,为用户创建一个动态的窗口,将生成的代码文件直接在网页上渲染成应用。
从「通义灵码」到「AI 程序员」再到「通义代码模式」到底迭代了什么?至此,答案就呼之欲出了:
第一是人与 AI 的高度协作。你负责提出想法,调整参数,AI 负责来实现。在这个过程中,若遇到任何问题,用户都可以随时与大模型进行沟通,从而充分发挥人与 AI 各自的优势。
第二是结果直观可视化。即使是没有开发经验的人,也能够通过可视化的演示知道 AI 生成的代码是否跑通了。这样每个人都可以不再限于自己的技术背景,能够快速地实现一些新想法。
最后,不论是人与 AI 的交互,还是代码生成的结果,都是实时的。这样的工作流程大幅提升了效率。
「这相当于让用户拥有一个 24 小时随时提需求的『贴身程序员』,不用排期、随时上线,且能满足你专属需求。」王晓明类比说。他还透露,阿里内部的开发者每天都在让通义协助完成大量的代码任务,从简单的代码排查、生成和解释,到更深入的代码文件辅助生成。「有些同事甚至直接用通义代码模式复刻出了小时候玩的掌机、小霸王上的一些小游戏,比如坦克大战、俄罗斯方块、飞机大战等。」
基于 Qwen 2.5
通义代码模式还在持续进化
任何一款好用的 AI 产品都离不开背后足够聪明的大模型,通义代码模式也是如此。它基于 Qwen 2.5 大模型进行开发。如果你一直在关注大模型领域的动态,会发现 Qwen 大模型最近的热度正在持续提高。
在 9 月底,全球开源社区基于 Qwen 系列二次开发的衍生模型数量已经超过了 Llama 系列,达到了 7.4 万。在 LiveBench 排行榜上,该模型的编码能力得分超过了 OpenAI 的 o1 模型,曾经跻身排行榜第二。在 Chatbot Arena 榜单上,该模型也能排到第五。
而且除了跑分,这个模型在国内外开发者中的口碑也非常好。
无论是在性能方面,还是在影响力方面,Qwen 都已经获得了充分的认可。
通义代码模式的出现,则让 Qwen 2.5 在多个方面充分发挥了自己的潜力。具体来说,代码模式一方面需要基于模型的意图识别和指令理解能力,将涉及到代码的用户意图精准识别出来,另一方面也需要将代码生成能力进行提升。有了 Qwen 2.5 做基础,通义代码模式在代码生成、推理和修复等能力方面表现非常优秀,能够支持 40 多种编程语言。
此外,通义代码模式的代码能力相比常规模式有 30% 以上的显著提升,在代码场景下表现极为优秀的同时,也具备很强的数学和通用能力。
在完成意图的理解和代码的生成之后,通义代码模式还需要将代码文件渲染成小游戏、网页和数据图表等各类应用,并且支持直接对代码的编辑修改(如转换语言、添加注释、问答等)。
这其中最大的难点就在代码渲染层面。为了尽可能扩大代码成功渲染为各类应用的范围,通义的团队需要对用户需求进行深入调研,并且针对主要的几大类场景进行优化,以确保满足用户的实际使用需求。其中涉及到意图理解、模型调优、前端渲染组件适配等一系列复杂的工作。
王晓明表示,通义代码模式目前可以实现大多数只依赖前端渲染的应用生成任务,对于更复杂的前后端代码,目前可以实现长篇的代码片段生成作为辅助。未来,该模式会进一步与 IDE 进行深度结合,帮助用户完成更加完整的前后端系统代码生成,实现更加复杂的应用类型生成。
这才是未来 AI 该有的样子?
通义代码模式选择的人机交互范式,可谓如今各路大模型公司主攻的新方向。
从理念上来说,这一模式与国外知名 AI 公司 Anthropic 提出的新功能 Artifacts 以及 OpenAI 发布的 ChatGPT with Canvas 不谋而合。或者,从某种程度上来说,通义代码模式更像是集合了二者的优势。
Artifacts 的最大特点在于实时预览。长期以来,大型语言模型一直能够生成代码,但在 GitHub 和 Copilot 等人工智能辅助开发环境之外,执行生成的代码通常需要额外的步骤。这些步骤让开发人员感觉繁琐,也把非开发人员挡在了门槛之外。在单独的窗口中保存和运行代码,可以带来方便、即时的体验。同样,在生成图像和其他可视化输出时也是如此。
所以,在 Artifacts 问世之际,很多人将其称为「本年度最重要的 AI 功能」、「Claude AI 最有用的功能」…… 还有人评价说,它「比 GPT-4o 还要震撼,这才是未来 AI 的样子」。
不过,Artifacts 也有一些不方便的地方,比如对于编程语言之间的自动转换、注释的添加还没有做到很好的支持。OpenAI 随后发布的 ChatGPT with Canvas 倒是提供了这些功能,但并不支持代码预览和应用生成,前面提到的种种问题依然存在。
通义代码模式更像是二者的结合体。它能够实现类似 Claude Artifacts 的代码生成和预览功能,并且还支持 Claude 不具备的代码编辑、添加注释、转换语言等功能,可以一步到位实现小游戏、网页、数据图表等各类应用的预览和使用,所触及的人群更加广泛。
同时,为了让那些不会写指令的用户直接创建应用,通义代码模式预置了一批提前生成好的小游戏和应用,用户可以直接使用。如果需要修改,用户只需要简单改一下指令,就能生成符合自己需要的应用。
如果说,未来的人类社会不可避免地走向人机协作,那么真正的挑战不仅在于如何打造更智能的 AI,还在于如何让这种智能易于获取、直观自然,并能无缝融入现有的工作流程。
在大模型之争的上半场,大多数企业都在关注前者。如今到了下半场,关注后者的企业将变得越来越多,OpenAI、Anthropic、阿里通义都属于行动较早的那一拨。
最后,关于「为什么要招募不懂代码的用户做测试」,王晓明回答说,「不懂代码的人更关注的是能否使用 AI 生成自己需要的各类应用,比如搭建个人博客、生成贪吃蛇小游戏、编写数据图表等,甚至还有用户希望用通义来生成一个表白网站的。对于这些用户来说,更重要的是应用生成的简便程度和可用性,而不是底层的代码实现逻辑。」
从实际使用场景出发,只需要用「大白话叙述」就能构建起符合我们需要的应用,这样的工具才是真正能够提升效率的工具,能够让更多的人用起来。
因此,「通义代码模式」用户的大头可以不是程序员,可以是学生、老师、数据分析师,自媒体从业者…… 测试者自然要更贴近这些人。
听起来,这会是一场非常有趣的测试,得到的洞察也会非常丰富。
如果你也想参与测试,可以在通义 App 或者通义 PC 页面对话框输入「1024」进行预约。期待大家的测试反馈。
#65岁陈立武点爆英特尔三把火
裁员砍中层,AI制造,争夺世界代工厂王座
65岁陈立武接棒英特尔,正酝酿一场全面的变革。他不仅要对制造和AI业务全面升级,还要裁撤中层管理层。曾经的芯片帝国,能否重拾昔日的辉煌?
随着华人大佬执掌英特尔之后,一场大刀阔斧的改革呼之欲出。
路透独家报道称,新任CEO陈立武计划全面改革「制造和AI」业务,试图带领英特尔重回时代巅峰。
在上周的全员大会上,他直言不讳地告诉全员工,「公司需要做出艰难的决定」。
据透露,陈立武早在重返公司之前,就已着手制定改革蓝图,主要聚焦于三大方向:
1. 重塑制造业2. AI战略升级3. 精简组织架构
这不仅是对前任CEO基辛格战略的升级,更是一场「动真格」的变革风暴。
值得一提的是,这场全面改革的计划提振了英特尔士气,股价在纳斯达克午盘交易中上涨超8%。
接过烫手山芋,挥刀制造+AI业务
2024年,可以称得上是英特尔的至暗时刻。
公司披露的年度财务报告中,亏损了190亿美元,这是自1986年以来的首次亏损。
过去十年,三位前任CEO的战略失误,让英特尔错失了智能手机芯片市场,眼睁睁看着竞争对手Arm Holdings、英伟达枪战手机。
股价低迷、市值缩水,英特尔急需一位铁腕领袖扭转局面。
65岁行业老将陈立武,曾担任芯片设计软件公司Cadence的CEO,被称为「芯片创投领域之父」,并长期活跃于英特尔董事会。
直到去年8月,他正式提出了辞职。
如今,陈立武以「救火队长」的身份强势回国,肩负着带领英特尔走出低谷的重任。
正如开篇所提到的,他的计划包括全面升级制造业务、重组AI战略,以及精简臃肿的中层管理层。
这一系列动作,不仅针对内部问题,也直指外部竞争。
改革制造业务
改革公司的制造业务是陈立武的核心优先事项之一。
英特尔的芯片制造部门,一度仅为自己生产芯片,但后来又转型为外部客户,比如英伟达代工芯片。
据透露,在短期内,陈立武计划通过积极争取微软、亚马逊等新客户,以提升英特尔代工厂的业绩。
一开始,陈立武的战略似乎是对基辛格战略的微调。
基辛格转型计划的核心是,将英特尔转变为合同芯片制造商,与台积电竞争,后者的客户包括苹果、英伟达和高通。
基辛格承诺投入数百亿美元在美国和欧洲建立工厂,为英特尔和外部客户制造芯片,但随着英特尔核心产品市场降温,他不得不缩减这些雄心。
不过,这些计划仍在制定中,最终可能还会发生变化。
AI战略升级
英特尔还将重启生产为AI服务器,生产芯片的计划。
与此同时,还要拓展至软件、机器人和AI基础模型等多个领域的业务。
英特尔下一代配备AI功能的先进芯片,名为Panther Lake,将依赖其内部工厂使用英特尔称为「18A」的一套新技术和技术。
英特尔今年的财务成功,与即将推出的芯片的强劲销售密切相关。
精简组织架构
一直以来,陈立武对基辛格的执行力颇有微词。在他看来,英特尔不仅需要技术突破,更需要文化重塑。
半导体行业专家Dylan Patel也指出,前英特尔CEO基辛格的失败部分源于「心太软」,妥妥的一个大好人,不愿去裁撤臃肿的中层管理人员。
然而,陈立武恰恰相反。去年8月,他突然辞职主要原因便是,对公司冗余的员工队伍、芯片代工方式,以及规避风险、官僚主义文化的做法,感到沮丧。
而裁员计划,是陈立武与董事会之间,加剧紧张关系的一个重要原因。
显然,陈立武上任后,不会犯同样的错误。
在他的评估中,他对公司文化表示不满,称公司已经失去了前CEO Andy Grove确立的「只有偏执狂才能生存」的精神。
他还认为,公司的决策恰是被臃肿的员工队伍拖慢了。
周重返CEO职位时,陈立武将重新审视英特尔的员工队伍,该队伍到去年年底已减少约15,000人至近109,000人。
重返巅峰,路漫漫
陈立武在周三的一份备忘录中表示,他计划保持对工厂的控制。
这些工厂在财务和运营上仍与设计业务分离,并恢复英特尔作为「世界级代工厂」的地位。
知情人士表示,若能赢得至少两个大客户,英特尔代工业务或将迎来转机。
吸引大客户的重中之重,便是改进英特尔的芯片制造工艺,使其更容易被像英伟达、谷歌这样的潜在客户使用。
最近几周,英特尔已展示了其改进的制造流程,并吸引了英伟达和博通的兴趣,这些公司已开始早期测试。
目前,AMD也在评估英特尔的流程当中。
英特尔发言人在最新声明中表示,陈立武将花大量时间倾听客户、合作伙伴和员工的意见,与我们的领导团队密切合作,为企业未来的成功奠定基础。
陈立武预计,将致力于改善产量或良率,在今年使用所谓的18A工艺进行第一个内部芯片的批量制造时,提高每个硅晶圆上生产的芯片数量。
他计划去效仿英伟达AI芯片年度发布的节奏,但这仍将需要数年时间。
业内人士称,英特尔开发出第一款具有吸引力的全新架构AI芯片,至少要到2027年才能实现。
显然,英特尔还有很长的路要走。
年薪百万+6600万期权「豪华套餐」
除了大刀阔斧的改革,陈立武上任后,人们关心的另一个话题点便是薪酬方案。
上周五,在提交给美国证券交易委员会(SEC)的文件中,陈立武将获100万美元的薪酬,外加6600万美元的股票期权和奖励。
详细文件显示,陈立武的薪酬结构堪称丰厚。
除了100万美元基础年薪外,他还有资格获得价值200万美元的年度奖金。
而真正的「大头」,在于长期股权激励:
- 1440万美元的股票单位+1700万美元绩效股:两项奖励都将在五年内兑现。若英特尔股价在未来3年内下跌,将不会获得任何股票;如果公司股价表现优于市场,还将获得更多股票。
- 960万美元的股票期权
- 2500万美元的新员工期权奖励
总的来说,陈立武的长期股权和期权奖励高达6600万美元,再加上薪水、奖金等,总薪酬也算非常高了。
更值得一提的是,如果英特尔未来发生控制权变更,比如被收购,陈立武部分股权激励可能加速兑现,为他再添一笔潜在收益。
为了获得这些奖励,陈立武还承诺以个人资金购买2500万美元的英特尔股票,并持有这些股份。
参考资料:
#结合代码聊聊FlashAttentionV3前向过程的原理
文章详细介绍了FlashAttentionV3(FA3)的前向过程原理,结合代码分析了其数学公式和工程实现的细节,包括分块计算、在线softmax的实现以及splitK部分的优化,旨在帮助读者更好地理解FA3的高效实现方式。
前言
接着Kernel系列,前文介绍了PagedAttentionV1和V2,本文开始介绍FlashAttentionV3 (后文简称为FA3)。FA3的涉及内容比较多,如果用一篇来介绍的话,内容太大,不便于阅读,所以初步会分为《FA3原理篇》,《FA3数据的Load和Store篇》,《FA3的WGMMA数据划分和Mask设计篇》,《FA3的Block调度,负载均衡,以及Overlap技巧篇》。同时分析FA系列,cutlass是必不可少,所以计划有Cutlass基础篇的四篇,分别是《cutlass核心数据结构和函数篇》,《理解cutlass的MMA/WGMMA数据划分篇》,《cutlass的数据加载之TMA设计与使用篇》,《cutlass中的Warp Specialization(即WS)编程模式篇》。另外针对GPU优化的基础知识介绍一下《CPU与GPU指令调度和优化思路的差异篇》。文章的名以最终发布为准。
为啥把这篇作为FA3系列的开篇,主要原因是理解了数学原理,对看懂整体的代码起到提纲挈领的作用。介绍FlashAttention数学原理的文章很多,大部分都讲的挺好,不同于前人的文章,本文主要是结合代码,拉近数学公式和工程实现的距离,让大家可以独立看懂FlashAttention的代码。其实在笔者之前的文章中有过相应FlashAttentionV2和RingAttention公式推导的介绍,原理上FA3相比FA2并没有变化,表述方式上,本文结合代码进行了更加细致介绍以及增加了对splitK部分(combine_attn_seqk_parallel
)介绍。本文或者是接下来的系列文章是基于FlashAttention的0dfb28174333d9eefb7c1dd4292690a8458d1e89
提交来介绍的,如果有讲的不对或者不理解的地方,欢迎留言探讨。
前面文章可参考:
杨鹏程:聊聊CUDA编程中线程划分和数据分块 之 PagedAttention(V1/V2)分析
https://zhuanlan.zhihu.com/p/710310530
杨鹏程:从Coding视角出发推导Ring Attention和FlashAttentionV2前向过程
https://zhuanlan.zhihu.com/p/701183864
简介
先回顾一下FlashAttention主要解决什么问题,或者说Flash的含义。FlashAttention是对经典SelfAttention的一种高效实现,如下图,展示的是经典的SelfAttention计算过程(去除了所有的可并行的维度,不包括GQA优化),主要解决的问题分为下面几个层次:
- 解决空间复杂度的中间激活的显存占用问题,如下图中的的中间结果;
- 将片上资源(shared memory)与序列长度解耦,可以实现超长序列的SelfAttention,早期的FasterTransformer以及PagedAttentionV1(V2通过SplitK来解决这个问题,详情可以参看笔者前一篇关于PagedAttentionV1/V2的介绍)就没有解决这个问题。
那FlashAttention如何解决这两个问题呢,谈到这个问题,就绕不开下面这张图:
来自FlashAttention论文
上图描述的是FlashAttentionV1的计算逻辑,通过对 ,在序列维上的划分,来实现片上一次只需要计算一部分固定序列长度的 ,将片上资源与真实序列长度的解耦,这样无论多长的序列,只要 可以放到显存上(甚至不需要在显存上),都可以完成 SelfAttention的计算。这个思想其实在GEMM里早有运用,在SelfAttention中应用较晚,主要是SelfAttention多了一个Softmax操作,对分块Softmax的等效计算,也就是Online Softmax是在后面提出的。另外在2021之前,既懂CUDA/cutlass和GPU架构,又懂online softmax的人并不多,所以很多人没意识到在Kernel内做这个工作,其实Kernel外,在 FlashAttention之前已有相关工作。
理解"Flash",这个点可能很多人知道,但是由于比较重要,这里再强调一下。由于分块计算,单个块的 的计算过程,如上面的图一,都可以在片上完成,消除Global memory的写入和写出,从而获得更好的性能。部分人的理解都到此为止,其实这里面还有两个更深的层次:
1.FA1并不是完全的片上计算的,如上图所示, 是在外层循环,在内层循环,所以一块 对应的 的全量,那么中间的 就是一个全尺寸大小,与全尺寸的 大小相同,这个尺寸是相当大的,尤其是序列很长时,所以 不可能保存在片上,而是写到Global Memory上了,整个过程并不是都在片上的。到了FA2, 放到了外循环, 变成内循环,此时一个分块的 ,完成了所有分块 ,即得到最终的结果分块 ,与内循环 的计算结果可以一直复用 ,可以保证 一直在片上,甚至一直在寄存器上(FA3在store的时候为了用TMA,这里可以选择把O写到Shared Memory上)。
2.第二层,会被很多人忽略,不研究代码可能也不会在意到这个点。这个点需要对mma指令的数据layout有了解才行,这里简单说明,详细内容会在《FA3的WGMMA数据划分和Mask设计篇》中介绍。例如mma的数据layout:MxNxK ,A矩阵shape:MxK ,B矩阵的shape为 ,对 进行reduce,得到 ,其中 是 的序列维, 是 的序列维,对mma指令的输出结果,一个确定 Q token,对应的序列维 的所有结果都在一个quarter warp内,即:一个local softmax的所有计算元素都在一个quarter warp内。这样softmax的计算以及后面 的计算,都在一个warp内,这样就没有warp之间的通信,不需要把中间结果写到 shared memory上,从而实现了完全的寄存器操作,取得"Flash"效果。当然还有很多比较重要的优化点,将在后面文章中展开。这部分啰嗦的有点多,后面直接切入正题。
主逻辑数学原理
符号约定
- 表示代码中的 row_max ;
- 表示代码中的 row_sum ;
- 或者 表示 scores 为 的输出激活;
- 上标. 表示当前分块;
- 上标: 表示所有的历史分块,相当于省略了 ;
函数公式化
代码中主要涉及函数如下,注意代码中有融合了 scale ,这里简化了,另外FA3复用了FA2的优化,将 exp 运算转化为 (主要考虑到 有更多的算力单元),为了简化表述这里直接使用 表示:
- reduce_max :zero_init=true : ,zero_init=false : ;false时会求历史最大;
- scale_apply_exp2 ,in place操作;
- reduce_sum :zero_init=true : ,zero_init=false : ,这里的false是和 reduce_max 相同的,求和值包括历史的 。
注意:FA3的online softmax计算依然是采用分子和分母分开的方式,下文中说到的softmax的scores值,均是指softmax的分子。
第一个分块
softmax.template online_softmax</*Is_first=*/true>(tSrS);
代码展开:
template<bool Is_first, bool Check_inf=false, typename Tensor0>
__forceinline__ __device__ TensorT online_softmax(Tensor0 &acc_s) {
...
flash::template reduce_max</*zero_init=*/true>(scores, row_max);
flash::template scale_apply_exp2</*Scale_max=*/true, /*Check_inf=*/true, Use_max_offset>(scores, row_max, softmax_scale_log2);
flash::reduce_sum</*zero_init=*/true, /*warp_reduce=*/false>(scores, row_sum);
...
};
对应的公式有:
其中的warp_reduce
是一个小的优化点,由于只有最后阶段才会使用,所以前期计算不需要reduce,而是保存在各线程的寄存器上,到最后的finalize
函数进行求和。
第i个分块
clear(scores_scale);
#pragma unroll 1
for (; n_block > n_block_min; --n_block) {
...
softmax.rescale_o(tOrO, scores_scale);
...
cute::copy(softmax.template max</*Is_first=*/false, /*Check_inf=*/Is_local>(tSrS), scores_scale);
softmax.template online_softmax</*Is_first=*/false, /*Check_inf=*/Is_local>(tSrS);
...
}
...
softmax.rescale_o(tOrO, scores_scale);
...
cute::copy(softmax.template finalize</*Is_dropout=*/false, Is_split>(tSrS), scores_scale);
...
softmax.rescale_o(tOrO, scores_scale);
其中softmax.rescale_o(tOrO, scores_scale);
是将调整系数scores_scale
以in place的方式作用到上。cute::copy(softmax.template max</*Is_first=*/false, /*Check_inf=*/Is_local>(tSrS), scores_scale)
使用当前的分块scores
来更新scores_scale
值和值。代码如下:
template<bool Is_first, bool Check_inf=false, typename Tensor0>
__forceinline__ __device__ TensorT max(Tensor0 &acc_s) {
...
Tensor scores_max_prev = make_fragment_like(row_max);
cute::copy(row_max, scores_max_prev);
flash::template reduce_max</*zero_init=*/false>(scores, row_max);
#pragma unroll
for (int mi = 0; mi < size(row_max); ++mi) {
float scores_max_cur = !Check_inf
? row_max(mi)
: (row_max(mi) == -INFINITY ? 0.0f : row_max(mi));
scores_scale(mi) = exp2f((scores_max_prev(mi) - scores_max_cur) * softmax_scale_log2);
row_sum(mi) *= scores_scale(mi);
}
...
return scores_scale;
};
可以发现 max 函数会将历史的最大值 保存起来,同时通过调用 reduce_max 函数求的包括当前分块在内,截至第 个分块,全局最大的scores值,即: 。这两个参数用计算调节系数,如下的scale,对应代码:scores_scale(mi)=exp2f((scores_max_prev(m i)-scores_max_cur)*softmax_scale_log2);。得到调节系数后,更新历史计算的 ,对应代码:row_sum(mi)*=scores_scale ,对应的更新公式如下:
从上面的公式比较容易发现,scores_scale 更新历史 ,将上一个阶段的最大值 消除掉,换成当前阶段的全局最大值。同样的道理 scores_scale 也会更新 tOrO,也就是 。
上文中也提到,FA2是使用的 Q 是外循环, KV 是内循环, FA 3 同样也是这种方式,这里内循环 V 就复用了 t0rO 结果,并不断用 scale 更新 tOrO,得到当前截至当前块的调整值 (从理解公式的角度来看,这里的 可忽略),直到最后一块,那么得到的 就是全局最大值。
上面max
更新历史,那么当前的softmax.template online_softmax</*Is_first=*/false, /*Check_inf=*/Is_local>(tSrS);
用于计算当前块的local softmax,由于在max
函数后面计算,这里用到的为,到目前分块为止(包括当前分块)的最大值。结合online_softmax<false>
代码:
template<bool Is_first, bool Check_inf=false, typename Tensor0>
__forceinline__ __device__ TensorT online_softmax(Tensor0 &acc_s) {
...
flash::template scale_apply_exp2</*Scale_max=*/true, Check_inf, Use_max_offset>(scores, row_max, softmax_scale_log2);
flash::reduce_sum</*zero_init=*/false, /*warp_reduce=*/false>(scores, row_sum);
...
};
scale_apply_exp2 计算local softmax(softmax的分子),reduce_sum 将当前的 和历史已经矫正的 相加,对应公式为:
总结整个循环里的逻辑:
- 关键是计算矫正系数 ;
- 得到矫正系数后,每次迭代都要更新当前分块 (softmax的分子乘以 的结果),由于 是外循环,对所有的 分块, 都是共享的;
- 同样的道理,矫正系数也会矫正历史的 ,然后会跟当前的 累加,需要注意的是 使用到的 是 ,而非 ;
- 这样对固定的 分片, 分块迭代完,即可得到最终的softmax的分子和分母( 可以当作系数)。
循环结束后第一个rescale_o
作用循环中最后一次的scores_scale
, 然后就是cute::copy(softmax.template finalize</*Is_dropout=*/false, Is_split>(tSrS), scores_scale);
,其中finalize
代码如下:
template<bool Is_dropout=false, bool Split=false, typename Tensor0>
__forceinline__ __device__ TensorT finalize(Tensor0 &acc_s, float descale_v = 1.f, float rp_dropout=1.f) {
constexpr static float max_offset_E = Use_max_offset ? 8.f * float(M_LN2) : 0.f;
// Reshape acc_s from ((2, 2, V), MMA_M, MMA_N) to (nrow=(2, MMA_M), ncol=(2, V, MMA_N))
Tensor scores = make_tensor(acc_s.data(), flash::convert_layout_acc_rowcol(acc_s.layout()));
static_assert(decltype(size<0>(scores))::value == kNRows);
SumOp<float> sum_op;
quad_allreduce_(row_sum, row_sum, sum_op);
TensorT scores_scale;
#pragma unroll
for (int mi = 0; mi < size(row_max); ++mi) {
float sum = row_sum(mi);
float inv_sum = (sum == 0.f || sum != sum) ? 0.f : descale_v / sum;
row_sum(mi) = (sum == 0.f || sum != sum) ? (Split ? -INFINITY : INFINITY) : (row_max(mi) * softmax_scale_log2) * float(M_LN2) - max_offset_E + __logf(sum);
scores_scale(mi) = !Is_dropout ? inv_sum : inv_sum * rp_dropout;
}
return scores_scale;
};
这里主要做的就是将softmax的分子除以分母,细化来说有三个操作:
- reduce分布在每一个quarter warp中的 ,为啥是 的warp,这个涉及到mma指令输出的数据layout,《FA3的WGMMA数据划分和Mask设计篇》和《理解cutlass的 MMA/WGMMA数据划分篇》都会介绍;
- 计算 作用最终的 即为完整的safe softmax公式,这部分跟笔者之前文章中介绍的 FA2的更新公式是完全一致的;
- 保存: ,即为 .
Combine_attn_seqk_parallel的公式推导
符号定义
- lse where ;这里为了方便推导我们将 放到 里面;得到下面结果:
- lse ;
这里需要说明的是: 为啥可以融合到 内,首先需要了解 的作用。 主要防止指数溢出,我们知道Float 32 可以表示的最大数值是 3.4 e 38 ,实际 ,即 在head维度reduce,考虑理想情况下是 (其中 d 是head-size)范围内的均匀分布,那么 结果不会溢出,如果出现异常值, 的结果超过 38 ,那么就会发生精度溢出。减去最大值 为啥可以避免这个问题呢,我们可以通过 的函数曲线来分析这个问题。
从上图不难看出, 在 是发散的,在 是收玫的,所以safe softmax通过将 的结果减去最大值 ,将定义域空间转化到 ,来实现值域不溢出的效果。这项技术在后文中计算LSE值也有应用。还有一个问题是,为什么LSE值可以把 放回去消掉呢。同样可以结合 的函数曲线分析,这里不画图了,直接数值分析,如果想让 正溢出,那么 ,近似得到 ,即 ,这个数值范围足够。同样的道理如果负溢出,那么 的数值也需要到达 。这里有一个近似理解的办法,
显然它的值域空间是他定义域空间的线性函数,这个空间足够使用,不用担心溢出了。
LSE的产生
template<bool Is_dropout=false, bool Split=false, typename Tensor0>
__forceinline__ __device__ TensorT finalize(Tensor0 &acc_s, float descale_v = 1.f, float rp_dropout=1.f) {
constexpr static float max_offset_E = Use_max_offset ? 8.f * float(M_LN2) : 0.f;
// Reshape acc_s from ((2, 2, V), MMA_M, MMA_N) to (nrow=(2, MMA_M), ncol=(2, V, MMA_N))
Tensor scores = make_tensor(acc_s.data(), flash::convert_layout_acc_rowcol(acc_s.layout()));
static_assert(decltype(size<0>(scores))::value == kNRows);
SumOp<float> sum_op;
quad_allreduce_(row_sum, row_sum, sum_op);
TensorT scores_scale;
#pragma unroll
for (int mi = 0; mi < size(row_max); ++mi) {
float sum = row_sum(mi);
float inv_sum = (sum == 0.f || sum != sum) ? 0.f : descale_v / sum;
row_sum(mi) = (sum == 0.f || sum != sum) ? (Split ? -INFINITY : INFINITY) : (row_max(mi) * softmax_scale_log2) * float(M_LN2) - max_offset_E + __logf(sum);
scores_scale(mi) = !Is_dropout ? inv_sum : inv_sum * rp_dropout;
}
return scores_scale;
};
其中的关键语句 row_sum(mi) = (sum == 0.f || sum != sum) ? (Split ? -INFINITY : INFINITY) : (row_max(mi) * softmax_scale_log2) * float(M_LN2) - max_offset_E + __logf(sum);
;翻译过来即为(这里忽略max_offset_E): ,合并m即为: 。
求safel
// Compute the logsumexp of the LSE along the split dimension.
ElementAccum lse_max = lse_accum(0);
#pragma unroll
for (int l = 1; l < kNLsePerThread; ++l) { lse_max = max(lse_max, lse_accum(l)); }
MaxOp<float> max_op;
lse_max = Allreduce<kRowsPerLoadTranspose>::run(lse_max, max_op);
lse_max = lse_max == -INFINITY ? 0.0f : lse_max; // In case all local LSEs are -inf
float lse_sum = expf(lse_accum(0) - lse_max);
#pragma unroll
for (int l = 1; l < kNLsePerThread; ++l) { lse_sum += expf(lse_accum(l) - lse_max); }
SumOp<float> sum_op;
lse_sum = Allreduce<kRowsPerLoadTranspose>::run(lse_sum, sum_op);
其中的核心语句是lse_sum += expf(lse_accum(l) - lse_max);
翻译为数学公式得到:
这里减去是为了数值安全,其原理也在上文总结过了。
恢复标准的l
ElementAccum lse_logsum = (lse_sum == 0.f || lse_sum != lse_sum) ? INFINITY : logf(lse_sum) + lse_max;
核心代码:logf(lse_sum) + lse_max
,翻译为数学公式:
通过消除 ,得到标准的softmax的分母值。这里取 同样是一种保证数值安全的方法,在上文也解释过。最后得到结果是一般形式的softmax的分母取log。
得到最终的softmax矫正系数
#pragma unroll
for (int l = 0; l < kNLsePerThread; ++l) {
const int row = l * kRowsPerLoadTranspose + tidx % kRowsPerLoadTranspose;
const int col = tidx / kRowsPerLoadTranspose;
if (row < params.num_splits && col < kBlockM) { sLSE(row,col) = expf(lse_accum(l) - lse_logsum); }
}
其中的核心代码:expf(lse_accum(l) - lse_logsum)
;
softmax矫正系数,整个过程依然是数值安全的计算。结合每一分块的输出值:两者相乘并求和即得到最终的结果: 即为最终的结果。
总结
同样是对LSE的应用,splitK的reduce函数相比Ring形式是有差异的,笔者在之前的文章有介绍。造成这个差异的主要原因是Reduce SplitK是在知道所有分块的LSE和output情况,直接可以计算最终的softmax调节系数,而Ring的方式是串行过程,一步步获取下一个分块的LSE和output,并更新,所以有这样的差异。从下一篇开始,就涉及Cutlass的基础知识,所以下一篇会先介绍cutlass。改变计划,下一篇分析FlashMLA。
参考:
https://github.com/Dao-AILab/flash-attention/tree/main/hopper
#尝试基于小模型(0.5B)复现DeepSeek-R1的思维链
1. 前言
本文主要是以两个目的出发:
- 第一个是简单地介绍下LLM训练的一个完整流程,侧重点在于帮助认识这个过程,而不是严谨地对每一个剖析细节,因此基本没有公式推导,但一些必要的符号是避免不了的;
- 第二个是尝试使用小模型(0.5B)来复现DeepSeek-R1的思维链模式,仅仅是一个demo级别的实践。
2. 如何从零训练一个LLM
最简单的语言来描述一个LLM的工作(推理)机制:
- 将一段输入文本映射为对应的tokens,然后给到transformer模型,预测下一个token的概率分布,选择概率最高的token(当然,也会有采样topK个概率最高的tokens);
- 本次选择的token + 输入文本的tokens + 之前预测输出的tokens,拼接起来,继续给到transformer模型,预测下一个token的概率分布;
- 重复第2步,直到模型输出代表结束的token;
- 最后,将输出的全部tokens映射回对应的自然语言文本。
2.1 预训练阶段
预训练可以类比一下以前BERT时代【预训练-微调】中预训练的方法,会使用互联网爬取的文本数据,比如wiki、百度百科,这一步是为了让模型获得next token prediction的能力,即能够基于已知的上文输出未知的下文,预训练得到模型是具备续写的能力,比如:
输入 | 输出 |
杭州西湖位于 | 中国浙江省杭州市西湖区龙井路1号,汇水面积为21.22平方千米,湖面面积为6.38平方千米,总面积约60平方千米,为自然与人文景观。 |
但是呢,一般的提问方式或者说对话方式应该是:
问题 | 回答 |
杭州西湖位于什么地方 | 中国浙江省杭州市西湖区龙井路1号,汇水面积为21.22平方千米,湖面面积为6.38平方千米,总面积约60平方千米,为自然与人文景观。 |
为什么会产生这种差异呢?
- 由于预训练的语料大部分来自于网页,许多都是段落形式的长篇文本,然后按照一定规则进行切分。
- 给模型输入前面一段文本,让模型去学习next token prediction的任务,即预测下一段文本,这就导致模型的输出是偏向于续写的
- 这便导致了不符合人类的对话习惯,因此产生后续一系列的post-train(后训练)工作。
2.2 Post-Training(后训练)
后训练的步骤一般会涉及以下三个步骤:
- 标注数据,进行监督微调学习(SFT,Supervised Fine-Tuning),这也是常常提到的指令微调
- 标注对比数据(comparison data),训练一个奖励模型,可以判断模型输出的质量
- 通过奖励模型来进行强化学习,进一步提升模型的能力
Post-Training(后训练)
2.3 指令微调(SFT)
Supervised Fine-Tuning (SFT)
这一步需要收集高质量的数据样本,什么样的数据就会让最终的模型呈现出什么样的行为,正如上一步所说的,预训练模型是输出是不符合人类对话习惯,而这一步就需要收集高质量的对话数据,来让模型学习到这种能力。
对于先驱者OpenAI来说,无疑是需要巨大的人力成本来收集和标注这些数据的。而对于后来者,我们一方面可以人工标注数据,但更多的往往是从市场上选择某一个或几个强大的模型(比如GPT、DeepSeek)去蒸馏数据:
- 设计一个prompt,让LLM生成问题的同时,又附带着回答;
- 或者自己有着垂直领域的百科知识,就可以设计Prompt去让LLM生成对应的提问,还可以让LLM对知识数据进行润色和丰富;
- 这样我们就可以得到这种一问一答的训练样本来进行监督微调了。
(当然实际情况往往复杂得多)
总的来说,这一步就是收集对应的数据,然后加载上一步的预训练模型作为起点,进行监督微调(SFT),让模型学会相应的能力,实现指令对齐:
- 比如现在最为普遍的Chat模型,便是收集符合人类对话习惯的问题(prompt)- 答案(output)。
- 但是,其实这里的prompt和output可以套到其他的实践场景中,比如意图识别等,prompt对应表达意图行为的描述,output对应预测的意图和提取的参数
2.4 奖励模型(Reward Model,RM)
Reward Modeling (RM)
这一步的目标是使用上一步的SFT模型作为初始化(最后增加一层分类器),训练一个奖励模型,能够为一条样本进行打分,以此来区分好样本和坏样本。比如下面的例子,chosen
明显比rejected
的回答更恰当,模型对chosen
的打分应该更高。
{
"prompt": "你是谁",
"chosen": "您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-V3。如您有任何任何问题,我会尽我所能为您提供帮助。",
"rejected": "有什么可以帮您的?"
}
RM的训练流程大致如下:
- 给定一个prompt,人工对LLM的多个输出进行比较,标注哪个输出是更符合人类偏好的(更合理)
- 或者可以参考数据蒸馏的做法来构造数据,让LLM同时输出好的回答和坏的回答
- 有了不同质量的回答数据后,需要标注好坏对比顺序,比如上面例子,标记
chosen
和rejected
的输出,只需要知道chosen
>rejected
即可 - 然后去训练一个分类Reward Model,训练目标是拉开好样本和坏样本的分数差距,训练好的Reward Model可以为每一条预测对应的分数(结束token的logit)
下面是Reward Model训练样本的一个通用格式:
(chosen
和rejected
是对于同一个Prompt的不同回答)
奖励模型一方面对于后续的强化学习起着关键作用,一方面在迭代训练也是至关重要。比如,下图为Llama3的训练迭代流程:
- 加载上一步的SFT模型作为Reward Model的初始化
- 按照上述的思路,不断收集大量的偏好数据pair,训练出一个Reward Model
- 收集一批 <Prompts>,使用本轮最好的模型,做K次采样生成,这样每个Prompt就得到了K条 <Prompt, Output_k>
- 通过Reward Model对每一个Prompt的采样生成 <Prompt, Output_k> 进行打分,然后筛选出分数最高的top-N个样本,这便是常常提到的拒绝采样
- 使用留下的top-N的样本作为SFT的训练样本,再加上部分关于特定能力的指令微调数据,训练出一个SFT模型
- 接着,再进入强化学习(DPO)的训练,最后的模型便是本轮最好的模型
- 重复步骤2-6,不断对模型进行迭代优化
Llama3后训练流程
2.5 强化学习
在经过上述的步骤训练出一个SFT模型,最后一般都会在使用强化学习,让模型的能力更上一层楼。今天简单介绍下几种常用的强化学习方法。
在此先引入强化学习中涉及的几种模型的概念:
- Policy Model(Actor Model):根据输入文本,预测下一个token的概率分布,输出下一个token也即Policy模型的“动作”。该模型需要训练,是我们最终得到的模型,并由上一步的SFT初始化而来。
- Value Model(Critic Model):用于预估当前模型回复的每一个token的收益。接着,还会进一步计算累积收益,累加每一个token的收益时不仅局限于当前token的质量,还需要衡量当前token对后续tokens生成的影响。这个累积收益一般是称为优势,用于衡量当前动作的好坏,也即模型本次回复的好坏,计算的方法一般使用GAE(广义优势估计,generalized advantage estimation))该模型同样需要训练。
- Reward Model:正如上述章节[2.4 奖励模型]介绍,对Policy Model的输出整体进行打分,评估模型对于当前输出的即时收益。该模型训练过程不进行更新。
- Reference Model:与 Policy Model是一样的模型,但在训练过程中不进行更新。其作用主要是与Policy Model计算KL散度(可以理解为两者的预测token概率分布差距)来作为约束,防止Policy Model在更新过程中出现过大偏差,即每一次参数更新不要与Reference Model相差过于大。
2.5.1 DPO(Direct Preference Optimization)
DPO是一种成本比较低的强化学习方法,它不需要显式的Reward Model,只需要Policy Model和Reference Model:
- 训练数据是与上述奖励模型一样的偏好对数据
- Policy Model的目标是尽量拉开
chosen(preferred)
样本与rejected(dispreferred)
样本的token概率差距 - 但是,同时Policy Model的概率差距与Reference Model的概率差距不要太过于大,避免训练不稳定
具体的DPO loss公式如下:
DPO Loss
为什么说是不需要显式的Reward Model,因为Policy Model在DPO中,其实也是充当了Reward Model的角色,概率差可以认为是对应的应得奖励收益。
2.5.2 PPO(Proximal Policy Optimization)
PPO训练流程图
PPO(近端策略优化)比较复杂,尽量减少非必要的公式,用简单的描述来说明整个流程(以一个批次的数据训练为例):
- 在当前状态下,也即未更新前的Policy Model和Value Model,对一个样本的Prompt q,使用Policy Model(Actor Model)进行一次采样生成,也即一次“动作”;
- 用Reward Model计算的分数,以及计算Reference Model与Policy Model的KL散度,这两个结合起来作为即时奖励;
- 接着,用Value Model(Critic Model)来计算每一个token的收益,记为。
- 然后,如上述,计算本次采样生成的优势(累积收益),即每一个token的奖励计算不仅考虑当前token的分数,还有考虑对后续tokens分数的影响,再结合上第2步的即时奖励,便是本次动作(采样)的优势;
到这里,一次采样就得到本轮ppo训练的参考奖励和。下面会使用这些来进行k次迭代更新,即一次采样能够进行k次的模型更新,每一次模型的更新步骤如下:
5. Policy Model对q进行一次新的生成,然后计算与相比的更新比例:
6. 当时,则表示本次参考的采样是正收益的(质量比较好),因此尽量去提升;反之时,则尽量去降低
7. 为了避免训练不稳定,出现过大偏差,都会对进行裁剪(Clip),上下限都控制在一个合理的范围内(与梯度裁剪类似):
8. 接着,Value Model也会对新的生成进行价值评估,并且去近似参考奖励,这是符合直觉的,新的价值评估要尽量去靠近参考奖励。同样地,加上裁剪:
9. 使用两个loss去分别更新Policy Model和Value Model
10. 循环步骤5-9,完成本轮的ppo训练:
11. 进入下一批次数据的训练......
到这里就介绍完整的PPO训练流程了,但可能对于第5-6步可能还会存在疑问,为什么要去提升和降低?
- 容易注意到,其实与KL散度计算很像,只是多了一层exp,因此可以用KL散度的视角去帮助理解,即预测tokens的概率分布差距;
- 首先,是输入文本Prompt,然后用Policy Model去进行采样生成,得到预测的tokens序列,即概率最高的tokens,以及对应的logit,举个简单例子,Prompt为“你叫什么名字”,生成的tokens为“你好,我叫小红”,为了方便理解,用概率来表示:你好
- 是用同样的Prompt,再去生成一次,那么也能得到对应预测tokens的logit,比如你好
- 那么当本次生成(“你好,我叫小红”)的质量比较好,即,那么当然应该鼓励Policy Model去学习,尽量拉高这些tokens的概率,便对应着提升;反之,同样的道理。
(这里的token不一定是这么分词的,只是为了举例子说明)
2.5.3 GRPO(Generalized Reinforcement Learning with Policy Optimization)
PPO vs. GRPO
GRPO是DeepSeek-R1论文中提出的另外一种强化学习方法。从上图可以看出,相比PPO,GRPO去掉了Value Model,简化了训练流程,降低了显存消耗。简单描述下GRPO的流程:
- 对一个样本的Prompt q,使用Policy Model进行G次生成
- 同样地,Reference Model也进行G次生成,与Policy Model进行KL散度计算,KL散度可以理解为两者的预测token概率分布差距,跟其他方法都是类似作用,避免Policy Model训练不稳定
- 再使用Reward Model对Policy Model的这G次生成进行打分。参考DeepSeek-R1的做法,甚至可以不需要Reward Model,只需要奖励函数,比如代码问题,可以根据模型生成的代码是否能够运行,有标准答案的数学问题,从模型的生成中提取的答案是否正确,来给予一定的奖励分数
- 最后平均的KL散度和奖励分数作为Loss去更新Policy Model
3. R1微调实践
目前的开源模型基本都是至少经过预训练和SFT这两个步骤的,而且大多知名的开源模型也是完整地包含了强化学习的全链路,因此,我们去微调或者甚至想训练一个新的模型,并不需要从预训练开始,而是选择一个底座模型,然后使用自己的数据集去SFT,来让模型进一步认识私域的知识或者约束模型的输出格式,接着可以选择性地使用强化学习进一步提升模型的能力。
(使用的训练框架是:huggingface/trl)
3.1 微调流程
这个实验的目标是将一个0.5B的普通chat模型Qwen2.5-0.5B-Instruct微调成为一个具有像DeepSeek-R1的思维链能力,即模型会先输出自己的思考过程,然后再给出具体的答案,即下面这种格式:
<think>
思考过程...
</think>
<answer>
答案
</answer>
使用的数据集是一个代表性的小学数学题集gsm8k:
answer里包含了解题思路和答案,因此正好可以将解题思路来作为思维链。
具体的训练流程:
- 首先,使用SFT的方法进行训练,将Qwen2.5-0.5B-Instruct能够按照上述思维链的格式进行输出;
- 接着,再使用GRPO的强化学习对上一步的SFT模型继续训练,保持思维链的同时,进一步来提升模型的回复准确性;
- 其中,因为这个数据集的答案是非常标准唯一的数字答案,因此可以不需要Reward Model,直接根据模型的输出答案是否正确来给予一定的奖励分数
3.2 奖励函数
设计的奖励函数主要是两个目标:
- 检测模型的输出是否按照思维链的格式;
- 模型的输出中答案是否准确
import re
def extract_xml_answer(text: str) -> str:
answer = text.split("<answer>")[-1]
answer = answer.split("</answer>")[0]
return answer.strip()
def correctness_reward_func(prompts, completions, answer, **kwargs) -> list[float]:
"""检查LLM输出的答案是否完全正确"""
responses = [completion[0]['content'] for completion in completions]
extracted_responses = [extract_xml_answer(r) for r in responses]
q = prompts[0][-1]['content']
print('-' * 20, f"Question:\n{q}", f"\nAnswer:\n{answer[0]}", f"\nResponse:\n{responses[0]}",
f"\nExtracted:\n{extracted_responses[0]}")
return [2.0if r == a else0.0for r, a in zip(extracted_responses, answer)]
def int_reward_func(completions, **kwargs) -> list[float]:
"""由于gsm8k数据集答案都是整型。检查LLM输出的答案是否为整型"""
responses = [completion[0]['content'] for completion in completions]
extracted_responses = [extract_xml_answer(r) for r in responses]
return [0.5if r.isdigit() else0.0for r in extracted_responses]
def strict_format_reward_func(completions, **kwargs) -> list[float]:
"""检查LLM输出是否完全按照思维链的格式"""
pattern = r"^<think>.*?</think>\s*<answer>.*?</answer>\n?$"
responses = [completion[0]["content"] for completion in completions]
matches = [re.match(pattern, r, re.DOTALL) for r in responses]
return [0.5if match else0.0for match in matches]
def soft_format_reward_func(completions, **kwargs) -> list[float]:
"""检查LLM输出是否存在符合思维链格式的部分"""
pattern = r"<think>.*?</think>.*<answer>.*?</answer>"
responses = [completion[0]["content"] for completion in completions]
matches = [re.match(pattern, r, re.DOTALL) for r in responses]
return [0.5if match else0.0for match in matches]
def count_xml(text) -> float:
count = 0.0
if text.count("<think>\n") == 1:
count += 0.125
if text.count("\n</think>\n") == 1:
count += 0.125
if text.count("\n<answer>\n") == 1:
count += 0.125
count -= len(text.split("\n</answer>\n")[-1]) * 0.001# 不以</answer>结尾扣除部分奖励分数
if text.count("\n</answer>") == 1:
count += 0.125
count -= (len(text.split("\n</answer>")[-1]) - 1) * 0.001# 不以</answer>结尾扣除部分奖励分数
return count
def xmlcount_reward_func(completions, **kwargs) -> list[float]:
"""思维链不完整也给予一定的奖励分数"""
contents = [completion[0]["content"] for completion in completions]
return [count_xml(c) for c in contents]
3.3 SFT+GRPO训练
如上述提到,使用一半的数据集来进行SFT训练
trainer = SFTTrainer(
model=model,
processing_class=tokenizer,
args=training_args,
train_dataset=get_gsm8k_dataset(sft=True, cache_dir=args.cache_dir,
first_half=args.split_half=="first_half",
second_half=args.split_half=="second_half"),
)
trainer.train()
再接着用另外一半进行GRPO训练
trainer = GRPOTrainer(
model=model,
processing_class=tokenizer,
reward_funcs=reward_funcs,
args=training_args,
train_dataset=get_gsm8k_dataset(cache_dir=args.cache_dir,
first_half=args.split_half == "first_half",
second_half=args.split_half == "second_half"),
)
trainer.train()
3.4 推理
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
generated_ids = model.generate(
**model_inputs,
max_new_tokens=args.max_completion_length
)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(f"Assistant:\n{response}")
对数据集其中一道题,改下数字,看看下面模型的输出是否符合预期:
Natalia sold clips to 22 of her friends in April, and then she sold half as many clips in May. How many clips did Natalia sell altogether in April and May?
Assistant:
<think>
In April, Natalia sold clips to 22 friends.
In May, she sold half as many clips as in April, which is 22/2 = <<22/2=11>>11 clips.
Altogether, Natalia sold 22+11 = <<22+11=33>>33 clips in April and May.
</think>
<answer>
33
</answer>
可以看到,模型的输出即包含了思维链,然后答案也是准确的。
3.5 总结
- 虽然微调第一步得到的SFT模型已经能够输出思维链,但是其回答问题的准确性还比较差,因为SFT训练的重点其实是整体的回复质量,而不是专注于正确答案;
- 但如果不经过SFT训练,直接使用GRPO的话,一开始模型的输出是没有思维链的,又无法准确提取答案,导致没有任何奖励,变得难以训练,或者选择能力更强的底座模型;
- 因此对于聊天类的数据,可以考虑直接使用SFT去微调,因为整体的回复质量更为重要,而对于数学/代码等要求正确答案/能否运行的数据,可以SFT+强化学习。
4. 完整代码
https://github.com/QunBB/DeepLearning/tree/main/llms/train/deepseek-train
#专为DeepSeek类强推理加速
老黄拿出Blackwell Ultra,下代架构性能还要翻倍
Token is the new frontier.
「因为 AI 技术爆发,GTC 大会的规模每年都在扩大,以前人们说 GTC 是 AI 的伍德斯托克音乐节,今年我们搬进了体育场,我觉得 GTC 已经成了 AI 的超级碗,」英伟达 CEO 黄仁勋说道。「唯一的不同在于每个人都是『超级碗』的赢家。」
北京时间 3 月 19 日凌晨,全世界的目光都汇聚在加州圣何塞 SAP 中心,期待英伟达给出的下一个 AI 大方向。
老黄的 Keynote 演讲行云流水,没有提词器。
在详细介绍 Keynote 内容之前,我们划下重点:
- Blackwell 已经全面投产。「产量惊人,客户需求惊人,因为人工智能出现了一个拐点,由于推理人工智能以及推理人工智能系统和智能体系统的训练,我们在人工智能领域必须完成的计算量大大增加。」
- Blackwell Ultra 将于 2025 年下半年上市,下一代 AI 加速器架构 Vera Rubin 则会在 2026 年推出。
- 搭载分布式推理系统 Dynamo 的 Blackwell NVLink 72 的「AI 工厂」性能是英伟达 Hopper 的 40 倍。「随着人工智能规模的扩大,推理将成为未来十年最重要的工作负载之一」。
- 按照最新路线图,英伟达正在构建三种 AI 基础设施:一种用于云,第二种用于企业,第三种用于机器人。
发布会上,老黄再次拿出 CES 上展示的 AI 发展曲线:
从 2012 年的 AlexNet 开始,现在我们处于生成式人工智能的阶段,即将进入智能体时代,随后是物理人工智能。物理 AI 也就是进入物理世界的人工智能,包括自动驾驶汽车与机器人。「每一次浪潮都为我们打开了新的市场机遇。」
再增加一个维度,不容忽视的是 DeepSeek R1 推动测试时扩展(Test-Time Scaling)给机器智能带来的全新发展曲线:
智能背后是计算的力量。预训练时代解决数据问题,后训练解决的是 human-in-the-loop 问题,而测试时间扩展则是为了增强 AI 的推理能力。每一阶段都有自己的 Scaling Law,算力都是强需求。
所以,虽然 DeepSeek R1 的高效率给全世界以震撼,让人们正在重估大模型的算力需求,但英伟达对于未来的 AI 算力需求仍然非常乐观。
英伟达给出了一组数据:仅在 2024 年,全球前四的云服务运营商共采购了 130 万片 Hopper 架构芯片。预计数据中心的建设投资将很快达到 1 万亿美元。不知道其中有多少是 OpenAI 星际之门项目的贡献。
AI 计算不是在萎缩,而是在通货膨胀,老黄进一步给出了两个增长曲线:
- 第一个曲线,软件都会因为 AI 而加速,在常规云服务上运行的人类编写软件,会转变为 AI 编写的软件运行在加速 AI 基础设施上;
- 第二个曲线,人们编写的文字提示获得 AI 生成的 token,转变成为 AI 生成的 Token 引导出 AI 生成的结果(即强推理)。
在此之上,整个世界将会被重塑。
每个企业未来都会有两个工厂,一个是物理的工厂,一个是 AI 的虚拟工厂。英伟达为所有行业的变革准备了新的工具,包括 CUDA X 软件库,其中包括用于 NumPy 的 cuPYNUMERIC、用于量子计算的 cuQUANTUM 和 CUDA-Q、用于深度学习的 NCCL 和 cuBLAS 等等。
所有这些库都依赖 CUDA 核心来完成工作,为此英伟达也准备好了更先进的 AI 算力。
Blackwell 发布超大杯,性能猛增
Blackwell 架构的 AI 加速卡现在已经全面进入量产阶段,正在推动下一波 AI 基础设施浪潮。「这是我们改变计算架构基础的重要一步,」黄仁勋说道。
在芯片架构进步的同时,英伟达正在研究让用户同时访问多个 GPU 的 NVLINK 交换机。
大规模的推理可能是英伟达迄今为止面临的最复杂的计算问题,但又是 AI 未来的方向。过去几个月里,很多人都在尝试使用 DeepSeek,肯定已经有了亲身体验:
黄仁勋展示了新旧两代大模型是如何解决「为七位客人优化婚宴餐桌位次」的问题。上代大语言模型 Llama 输出了 439 个 token,结果不尽如人意。强推理模型 DeepSeek R1 输出了 8559 个 token 进行了一番推理,花费的时间更长,计算量也更大,但结果真正能被人用得上。
老黄表示:「这是个只有丈母娘或者 AI 才能解决的问题。」
但是上面这个问题需要消耗 150 倍的算力。AI 服务商希望尽可能地向每位用户提供更高的速度,同时也希望尽可能地向更多用户提供服务。这就产生了对内存、带宽、计算速度等各个方面的巨大需求。Grace Blackwell NVLink72 正是为满足这样的需求诞生的。
为了提升效率,英伟达在软件上也有创新,提出了「AI 工厂的操作系统」——NVIDIA Dynamo。它是一个「分布式推理服务库」,而且是一个开源解决方案,解决的是用户需要 token 但无法提供足够 token 的问题。据介绍,Dynamo 会被用于在大量 GPU 之间高效编排和协调 AI 推理请求。目前,微软、Perplexity 等公司已宣布开始接入这一系统。
接下来,让我们看看软件 + 硬件能够带来的算力效率提升。如果强推理模型落地成产品,我们就需要 AI 能以极快的速度跑完思维链。「只有在英伟达,你才会这样被数学折磨,」老黄说道。在推理模型中,最新版 Blackwell 的性能是 Hopper 的 40 倍:
黄仁勋展示了一个非常直观的对比。同样是 100 MW 功率的 AI 工厂,使用 GB200 搭建的数据中心的生产力是使用 H100 的数据中心的 40 倍,同时机架数量还能从 1400 大幅减少到 600。
现在不是「the more you buy the more you save」了,而是「the more you buy the more you generate」。「全球 TOPS 的云服务提供商(CSP)订购的 Blackwell 芯片数量是 Hopper 的三倍,AI 算力的需求正在迅猛增长。」黄仁勋表示。
不得不说,他表示自己确实想提高 Blackwell 的销量,但这同时在一定程度上降低了 Hopper 的销量。他甚至打趣说自己是 chief revenue destroyer(首席收入破坏官)。
黄仁勋表示,人们的 AI 任务需求正在大幅提升,因为大模型推理任务、AI Agent 等任务,AI 推理的算力需求已经增长了 10-100 倍。这也就产生了对更强大性能的需求。
似乎是在顺应手机和新能源车出「超大杯」Ultra 版的风潮,英伟达在旗舰 AI 计算卡上也搞了个 Ultra 版:Blackwell Ultra NVL72。
这是迄今为止 AI 算力最强大的硬件,配备了 1.1 EF 的密集 FP4 推理能力和 0.36 EF 的 FP8 训练能力,达到了 GB200 NVL72 的 1.5 倍。此外,它的互联带宽是 GB200 NVL72 的 2 倍,内存速度也提升了 1.5 倍。至于 Blackwell Ultra NVL72 的上市时间,预计会是今年下半年。
将八个 NVL72 机架放在一起,就可以获得完整的 Blackwell Ultra DGX SuperPOD:288 个 Grace CPU、576 个 Blackwell Utlra GPU、300TB HBM3e 内存和 11.5 ExaFLOPS FP4 算力。这就形成了英伟达定义中「AI 工厂」的超级计算机解决方案。
需要注意的是,Blackwell Ultra GPU(GB300 和 B300)与 Blackwell GPU(GB200 和 B200)是不同的芯片。
下一代架构 Vera Rubin
既然算力在通货膨胀,那这还远远不够。在今天的 Keynote 中,英伟达很快就介绍完了 Blackwell Ultra,转而展示了其下一代架构 Vera Rubin—— 其全机架性能应是同类 Blackwell Ultra 的 3.3 倍。
Vera Rubin 将是英伟达的下一个平台,将于 2026 年下半年推出。Vera Rubin 具有 NVLink144,更强大的 Rubin Ultra 则具有 NVLink576,将于 2027 年下半年推出。在具体性能上,其将具有 3.6 EF 的 FP4 推理性能和 1.2 EF 的 FP8 训练性能,整体可达到 GB300 NVL72 的 3.3 倍,同时在其它指标上也有 2 倍左右的提升。
其 Ultra 版则计划在 2027 年下半年推出,其性能更是有望达到 GB300 NVL72 的 14 倍!
除了 GPU 芯片的迭代,Rubin 还将标志着从 HBM3/HBM3e 向 HBM4 的转变。每 GPU 的内存容量仍为 288GB,与 B300 相同,但带宽将从 8 TB/s 提高到 13 TB/s。下代产品还将拥有更快的 NVLink,吞吐量翻倍至 260 TB/s,机架之间的新 CX9 链路速度为 28.8 TB/s(是 B300 和 CX8 的两倍)。
如果将 4 组 Vera Rubin NVLink144 组成的 Vera Rubin NVLink576 来构建 NVIDIA Rubin System,则这将是配备 576 个 Rubin GPU 的性能怪兽,能实现 15 EF 的 FP4 性能,同时内存也将达到惊人的 150 TB。对比前代 Blackwell System 的性能,可以看到优势非常明显。
黄仁勋特别强调:「你可以看到,Rubin 将大大降低成本。」
据了解,这一代 GPU 得名于科学家 Vera Rubin,她是一位美国天文学家,1928 年出生于费城。她的知名成就是发现了暗物质存在的证据。
值得一提的是,自去年的 Blackwell 开始,命名就不再单指芯片架构。黄仁勋就曾强调,Blackwell 并不是某块芯片,而是一个技术平台,英伟达也越来越多地开始使用「Blackwell」一词来指代该公司所有最新一代 AI 产品,例如 GB200 芯片和 DGX 服务器机架。
黄仁勋还在演讲中简单提到了再后一代的 Feynman 架构 —— 很显然这得名于著名物理学家理查德・费曼。不过这至少得等到 2028 年了。
此外,黄仁勋还宣布了 NVIDIA Photonics,这似乎是迄今为止最强大的 Spectrum-X 以太网互联,以激光作为介质,可以大幅提升 GPU 之间的传输速度,支持拥有数百万块 GPU 的集群。预计这款产品将于今年下半年上市,而新一代的 Quantum-X 将在明年下半年上市。
今天的新产品中相对来说接地气的是 Blackwell RTX Pro 系列图形产品。其面向的是笔记本电脑和台式机,以及独立 PC 和数据中心产品。具体规格和配置的细节尚未公布,已知顶级解决方案将使用与 GeForce RTX 5090 相同的 GB202 芯片(但显存会更大)。
至此,英伟达看起来已经为强推理 AI 大规模落地所需巨量的计算做好了准备。
下一波浪潮:物理世界的 AI
最后是对未来的展望。英伟达表示,AI 的下一波浪潮必然会延伸到物理世界,主要形式会是三种机器人:工业机器人、自动驾驶车辆以及狭义的人形机器人。
三种机器人都需要的算力包括预训练、模拟环境和端侧算力,这些算力英伟达都提供。物理世界的 AI 将会带动数万亿美元的工业产值,数以十亿计的机器人将会使用英伟达的计算平台。
数据、架构、Scaling Law,这些问题在机器人领域也同样存在。
对此,英伟达的预训练模型平台 Cosmos、GROOT N1 以及 NVIDIA Omniverse 将会帮助物理 AI 生态的构建,推动技术的发展。
其中,GROOT N1 是通用的机器人基础模型,英伟达宣布已经把它开源了出来。模型采用双系统架构,灵感来自人类认知原理。在视觉语言模型的支持下,系统 2 可以推理其环境和收到的指令,从而规划行动。然后,系统 1 将这些计划转化为精确、连续的机器人动作。
基于可通过少量人类演示生成指数级的大量合成动作数据的生成蓝图,他们在短短 11 小时内生成了 78 万条合成轨迹,相当于 6500 小时或连续 9 个月的人类演示数据。然后,通过将合成数据与真实数据相结合,与仅使用真实数据相比,GR00T N1 的性能提高了 40%。
黄仁勋展示了与迪斯尼和 DeepMind 联合开发的机器人平台 Newton,以及基于该平台打造的《星球大战》风格的机器人 Blue。
他表示,对于机器人,可验证的奖励就是物理定律。
利用 Omniverse 和 Cosmos 通过数字孪生虚拟训练机器人的 AI,然后将其转化为现实世界的动作 Token 输出,这就是未来机器人大规模落地的方式吗?
如果人形机器人会有恐怖谷效应的话,科幻电影里早已为我们准备了解决方案。
「每个人都应该关注机器人领域,它很可能会成为最大的产业,」黄仁勋说。
#使用LLM帮我写代码
Django创造者Simon Willison分享
近段时间,著名 AI 科学家 Andrej Karpathy 提出的氛围编程(vibe coding)是 AI 领域的一大热门话题。简单来说,氛围编程就是鼓励开发者忘掉代码,进入开发的氛围之中。更简单地讲,就是向 LLM 提出需求,然后「全部接受」即可。
当然,这种使用 LLM 编程的方法过于简单粗暴,或许并不适合用来开发一些更加复杂和精细的项目。近日,探索和发表数据的开源工具 Datasette 的创造者、Web 应用框架 Django 创造者之一、社交会议目录 Lanyrd 的联合创始人、著名编程技术博主 Simon Willison 分享了自己使用 LLM 辅助编程的体验。文中,他分享了不少自己积累的有用实践和策略。编译了这篇博客文章,希望能给开发者读者们带来一些帮助。
Simon Willison
原文地址:https://simonwillison.net/2025/Mar/11/using-llms-for-code/
网络上,很多开发者在讨论使用大型语言模型辅助编程,而其中不少开发者都表示挺失望的。他们经常会问自己哪里做错了 —— 为什么有些人报告的结果如此出色,而他们自己的实验却乏善可陈?
使用 LLM 编写代码既困难又不直观。需要付出巨大的努力才能弄清楚使用它们的利弊,而且几乎没有什么指导可以帮助人们学会如何最好地使用它们。
如果有人告诉你使用 LLM 编码很容易,那么他们(可能无意中)误导了你。他们很可能偶然发现了有效的模式,但这些模式并不是每个人都能自然而然掌握的。
两年多来,LLM 代码在辅助我写代码方面表现很好。下面我将尽力将一些经验和直觉传授给你。
目录:
- 设定合理的期望
- 考虑训练截止日期
- 上下文为王
- 让它们提供选择
- 告诉它们确切要做什么
- 你必须测试它写的内容!
- 记住这只是一次对话
- 使用可以为你运行代码的工具
- 氛围编程是一种很好的学习方式
- 使用 Claude Code 的一个详细示例
- 做好让人类接管的准备
- 最大的优势是开发速度
- 使用 LLM 是对已有专业知识的放大
- 奖励:回答有关代码库的问题
设定合理的期望
不要去管围绕「AGI」的炒作 ——LLM 仍旧只是花哨的自动补全。它们所做的只是预测 token 序列 —— 但事实证明,写代码的主要工作就是以正确的顺序将 token 串联在一起,因此只要你给它们指示正确的方向,它们就会非常有用。
如果你认为这项技术将完美地实现你的项目,而你不需要锻炼任何技能,那你就等着失望吧。
相反,你应该使用 LLM 来增强你的能力。我现在最喜欢的心理模式是将它们想象成一个过度自信的结对编程助理 —— 它们查找东西的速度快如闪电,可以随时提供相关示例,并且可以毫无怨言地执行繁琐的任务。
过度自信很重要。它们绝对会犯错误 —— 有时很细微,有时是大错。这些错误可能与人类错误非常不一样 —— 如果一个人类合作者想象出了一个根本不存在的库,你会马上就不再相信他了。不要把 LLM 当人类一样看,这是一个陷阱。AI 犯的错误并不能否定它的有用性。
当与 LLM 一起工作时,你经常会发现它们无法做到的一些事情。记下这些事情 —— 它们是有用的教训!它们也是为未来储备的宝贵例子 —— 一个强大的新模型的标志是:它能解决以前的模型无法处理的任务。
考虑训练截止日期
任何模型都有一个关键特征:训练截止日期。也就是停止收集训练数据的日期。对于 OpenAI 的模型,这通常是 2023 年 10 月。Anthropic 和 Gemini 以及其它提供商可能有更近期的日期。
这对于编程来说非常重要,因为这个时间会影响它们知道的库。如果你使用的库自 2023 年 10 月以来发生了重大变化,OpenAI 模型将不会知道!
我从 LLM 中获得了足够的价值,现在我在选择库时会特意考虑这一点 —— 我会尽力坚持使用具有良好稳定性且足够流行的库,这样一来,这些库的许多示例都会在其训练数据中。我喜欢应用无聊技术(boring technology)的原则 —— 在项目的独特卖点上进行创新,在其它所有方面坚持使用经过尝试和测试的解决方案。
LLM 仍然可以帮助你处理训练数据之外的库,但你需要付出更多努力 —— 你需要在提示词中向它们提供最新示例,说明这些库应如何使用。
这就引出了使用 LLM 时最重要的事情:
上下文为王
要想让 LLM 给出优良的结果,很大一部分工作在于都可归结为管理上下文,即当前对话的一部分文本。
此上下文不仅仅是提供给 LLM 的提示词:成功的 LLM 交互通常采用对话的形式,而其上下文包括当前对话线程中存在的来自你的每条消息和来自 LLM 的每条回复。
当你开始新的对话时,你会将该上下文重置为零。了解这一点很重要,因为对于不再有用的对话,通常的解决方法是将一切清除干净并重新开始。
一些 LLM 编程工具不仅仅适用于对话。例如,Claude Projects 允许你预先填充大量文本,包括最近的直接从 GitHub 库导入代码的功能 —— 我经常使用这个功能。
Cursor 和 VS Code Copilot 等工具会自动包含当前编辑器会话和文件布局中的上下文,有时你可以使用 Cursor 的 @commands 等机制来提取其它文件或文档。
我主要直接使用 ChatGPT 和 Claude 网页版或应用界面的原因之一是:它能让我更容易准确地了解上下文中的内容。那些向我隐瞒上下文的 LLM 工具的效果更差。
另一个事实也可为你所用:之前的回复也是上下文的一部分。对于复杂的编程任务,可以先尝试让 LLM 编写一个更简单的版本,检查它是否有效,然后再迭代构建更复杂的实现。
我在开始新聊天时,经常会把现有代码放入到上下文中,然后再与 LLM 一起合作以某种方式来修改它。
我最喜欢的代码提示词技术之一是放入几个与我想要构建的东西相关的完整示例,然后提示 LLM 将它们用作新项目的灵感。当我在构建我的 JavaScript OCR 应用时,我详细地写了:该应用应结合 Tesseract.js 和 PDF.js—— 这两个库我过去曾使用过,我可以在提示词中提供有效示例。
让它们提供选择
我的大多数项目都是从一些开放式问题开始的:我想做的事情是否可行?我可以用哪些潜在方式来实现它?哪些选项是最好的?
我会将 LLM 用作初始研究阶段的一部分。
我会使用这样的提示:「Rust 中有哪些 HTTP 库可选?包括使用示例」或者「JavaScript 中有哪些有用的拖放库?为我构建一个展示每个库的工件」(对 Claude)。
训练截止时间在这里很重要,因为这意味着 LLM 不会建议使用较新的库。通常这样没问题 —— 我不想要最新的,我想要最稳定的,以及存在时间足够长的,可以解决错误的东西。
如果我要使用更新的东西,我会在 LLM 世界之外自己做研究。
开始任何项目的最佳方式是使用原型来证明该项目的关键要求可以得到满足。我经常发现,LLM 可以在我坐下来使用笔记本电脑的几分钟内就让我获得那个可行的原型 —— 有时甚至在我使用手机工作时也可以。
告诉它们确切要做什么
一旦我完成了初步研究,我就会大幅改变模式。对于生产级代码,我对 LLM 的使用更加专制:我会把它当作数字实习生,工作内容是根据我的详细指示来写代码。
这里有个最近的例子:
我可以自己写这个函数,但我需要花上十五分钟来查找所有细节,才能使代码正常工作。Claude 在 15 秒内就搞定了。
我发现,对于我在这里使用的函数签名,LLM 的响应非常好。我的工作是作为函数设计者,LLM 负责根据我的规范构建主体。
我经常还会提出跟进要求,比如「现在用 pytest 给我写测试」。再次强调,选择哪种技术完全由我决定 —— 我希望 LLM 能帮我省去录入已经存在于我脑子里的代码的时间。
如果你对此的反应是「输入代码肯定比输入英文指令要快」,我只能告诉你,对我来说已经不是这样了。代码必须正确。而英语中存在大量捷径、奇思妙想和拼写错误,比如如果你记不住名字,你可以说「使用那个流行的 HTTP 库」。
优秀的编程 LLM 非常擅长填补空白。它们也远没有我那么懒 —— 它们总是会记得捕捉可能的异常,添加准确的文档字符串,并用相关的类型标注代码。
你必须测试它写的内容!
有一件事是你绝对不能外包给机器的,那就是测试代码是否真的有效。
作为软件开发者,你的责任是提供能有效工作的系统。如果你还没有看到它运行,那么它就不是一个有效的系统。你需要亲手试试看。
这件事做起来可能没多少趣味,但它一直是交付良好代码的关键部分 —— 无论有没有 LLM 参与其中。
记住这只是一次对话
如果我不喜欢 LLM 写的东西,可以马上让它重构,而它绝对不会抱怨!「将重复的代码分解成一个函数」、「使用字符串操作方法而不是正则表达式」,甚至「写更好一点!」
LLM 第一次编写的代码很少是最终的实现,但它们可以为你重新输入几十次,而不会感到沮丧或无聊。
偶尔我会从我的第一个提示中获得很好的结果 —— 我练习得越多,结果就越频繁 —— 但我一直做好了需要后续跟进的准备。
我一直很好奇,这是否是人们错过的关键技巧之一 —— 糟糕的初始结果并不是失败,而是一个起点,基于此才能将模型推向你真正想要的方向。
使用可以为你运行代码的工具
现在越来越多的 LLM 编程工具能够为你运行代码。我对其中一些略微谨慎,因为错误的命令可能会造成真实的损害,所以我倾向于坚持使用在安全沙箱中运行代码的工具。我现在最喜欢的包括:
- ChatGPT Code Interpreter,ChatGPT 可以直接在 OpenAI 管理的 Kubernetes 沙箱 VM 中编写并执行 Python 代码。这是完全安全的 —— 它甚至无法建立出站网络连接,因此实际上可能发生的一切就是临时文件系统被破坏然后重置。
- Claude Artifacts,Claude 可以为你构建一个完整的 HTML+JavaScript+CSS Web 应用,该应用显示在 Claude 界面中。这个 Web 应用显示在一个非常封闭的 iframe 沙箱中 —— 这虽然极大地限制了它可以做的事情,但可以防止意外泄露你的私人 Claude 数据等问题。
- ChatGPT Canvas 是一个较新的 ChatGPT 功能,具有与 Claude Artifacts 类似的功能。我自己还没有对此进行足够的探索。
如果你愿意更冒险一点:
- Cursor 有一个「Agent」功能可以做到这一点,Windsurf 和越来越多的其它编辑器也是如此。我还没有花足够的时间研究这些,所以我不能提供相关推荐。
- Aider 是这些模式的领先开源实现,是 dogfooding 的一个很好的例子 ——Aider 的最新版本有 80% 以上是由 Aider 自己编写的。https://aider.chat/
- Claude Code 是 Anthropic 进入这个领域的新成员。我将在稍后详细介绍如何使用该工具。
这种在交互流程中运行代码的模式非常强大。我在选择核心 LLM 编程工具时,主要就是看它们是否可以安全地运行和迭代我的代码。
氛围编程是一种很好的学习方式
Andrej Karpathy 一个多月前创造了氛围编程(vibe coding)一词:
Andrej 认为这「对于一次性的周末项目来说还不错」。这也是探索这些模型功能的绝佳方式 —— 而且真的很有趣。
学习 LLM 的最佳方式就是玩它们。向它们抛出荒谬的想法,然后进行氛围编程,直到它们基本可以正常工作,这是一种真正有用的方法,可以让你更快地对什么有效、什么无效形成直觉认识
早在 Andrej 给它命名之前,我就已经开始进行氛围编程了!我的 simonw/tools GitHub 存储库有 77 个 HTML+JavaScript 应用和 6 个 Python 应用,每个应用都是通过提示 LLM 构建的。我从构建这个集合中学到了很多东西,我以每周几个新原型的速度向其中添加内容:https://github.com/simonw/tools
你可以在 tools.simonwillison.net 上直接试用我的大部分工具 —— 这是这个库的 GitHub Pages 发布版本。
使用 Claude Code 的一个详细示例
在撰写本文时,我想到了 tools.simonwillison.net/colophon 页面 —— 我想要一个可以链接到的东西,以比 GitHub 更明显的方式显示我的每个工具的提交历史记录。
我决定利用这个机会展示我的 AI 辅助编程过程。
对于这个任务,我使用了 Claude Code,因为我希望它能够直接根据我笔记本电脑上现有的工具库运行 Python 代码。
在我的会话结束时运行 /cost 命令,会向我显示以下内容:
其最初的项目从开始到结束只花了我 17 分钟多一点的时间,并且在调用 Anthropic 的 API 上仅花费了 61 美分。
在这个过程中,我会确切地告诉模型我想要构建什么。下面是我的提示词序列,完整记录在这里:https://gist.github.com/simonw/323e1b00ee4f8453c7834a7560eeafc1
首先,我要求 LLM 编写一个初始脚本来收集新页面所需的数据:
我真的没有认真考虑过上面的首个提示词 —— 它更像是我在思考初始问题时输入到机器人中的意识流。
我检查了初始结果并发现了一些问题:
然后我改变了主意 —— 我也想要那些完整的提交消息:
像这样提供示例是获得你想要的确切内容的绝佳捷径。
请注意,我从未查看过在 gather_links.py 中编写的代码!这是纯粹的氛围编程:我正在查看它在做什么,但我把实现细节完全留给了 LLM。
这个 JSON 看起来还不错,所以我指示 LLM:
Claude 知道 GitHub URL 的工作方式,因此告诉它提交的链接并提供库名称就足够了,它猜测这些提交 URL 是 https://github.com/simonw/tools/commit/fd9daf885c924ba277806b3440457d52b0ad90a8
我经常发现 Claude 在网页设计方面有很好的默认品味 —— 我只是说了「页面应该适合移动设备」,然后剩下的就交给它了。
Claude 不停地为我构建不正确的页面,所以我发出指令:
然后它自己修复了所有错误,只剩下我决定要做的两处更改:
整个项目就完成了!结果文件为 build_colophon.py,它生成的页面看起来相当不错:
还有一项任务:我需要将新的 colophon 作为我网站的一部分进行部署,但我不想将新的 colophon.html 页面签入库本身。我想要一个自定义的 GitHub Pages 构建过程。
我启动了一个全新的 Claude Code 会话,看看 Claude 是否也能做好这件事:
与第一次不同,这次我非常仔细地观察了它在做什么 —— 我不知道如何以这种方式自定义 GitHub Pages 构建,我想学习如何做到这一点,并保持谨慎,因为它可能会产生幻觉并导致任务失败。
它告诉我它想要创建这个文件并请求我的许可:
我想这是正确的?我很喜欢这个注释「Need full history for git log in gather_links.py」—— 这是我很容易忽视的。
然后它说它想将这些文件添加到 .gitignore—— 听起来是个好主意。
它输出了对以上操作的总结:
我查看了它的成本:
因此,使用 Claude API 花费了 17 美分和 45 秒。(我分心了,因此总共花费了 10 分钟。)这里是完整记录:https://gist.github.com/simonw/a560b07eef577e6183021d1ccaae7e07
这些代码看起来不会不可逆地破坏任何东西,因此我将其 push 到了 GitHub,然后看看会发生什么。
……成功了!我的 colophon 页面已上线。
有一个问题。我在 GitHub Actions 运行时观察了它,发现有些不对劲:
我原本期待的是「Test」job,但为什么有两个不同的部署?
我有一种预感,之前的默认 Jekyll 部署仍在运行,而新的部署同时运行 —— 新脚本完成得晚并覆盖了原始脚本的结果,这纯粹是时间上的运气。
是时候暂时放下 LLM 并阅读一些文档了!
我在 GitHub Pages 的使用自定义工作流中找到了这个页面,但它没有告诉我我需要知道的内容。
出于另一个直觉,我检查了我的库的 GitHub Pages 设置界面,发现了这个选项:
我的仓库设置为「从分支部署」,所以我将其切换到「GitHub Actions」。
我手动更新了我的 README.md,以在此提交中添加指向新 Colophon 页面的链接,而这又触发了另一次 build。
这次只运行了两个 job,最终结果是正确部署的站点:
(我后来发现了另一个 bug—— 一些链接无意中在其 href= 中包含了 <br> 标签,我用另一个 11 美分的 Claude Code 会话修复了这个问题。)
之后,我还通过新增 AI 生成描述工具进一步改进了这个 colophon:https://simonwillison.net/2025/Mar/13/tools-colophon/
做好让人类接管的准备
在这个例子中,我很幸运,因为它有助于说明我的最后一点:要做好接管的准备。
LLM 无法取代人类的直觉和经验。我在 GitHub Actions 上花了足够多的时间,我知道要寻找什么样的东西。在这种情况下,比起继续尝试通过提示词完成这个任务,我介入并完成项目的速度更快。
最大的优势是开发速度
我的新 colophon 页面从构思到完成、部署功能只花了我不到半个小时的时间。
我确信如果没有 LLM 的帮助,我会花更长的时间 —— 以至于我可能根本不会费心去构建它。
也因此,我非常关心我从 LLM 中获得的生产力提升:它不是为了更快地完成工作,而是为了能够交付我根本不想花时间的项目。
我在 2023 年 3 月写过一篇文章谈到,AI 增强的开发让我对我的项目更加雄心勃勃。两年后,这种影响没有消退的迹象。
这也是加速学习新事物的好方法 —— 今天我讲的是如何使用 Actions 自定义我的 GitHub Pages 构建,这是我将来肯定会再次使用的东西。
事实上,LLM 能让我更快地执行我的想法,这意味着我可以实现更多的想法,这意味着我可以学到更多。
使用 LLM 是对已有专业知识的放大
其他人也能以同样的方式做到这一点吗?可能不会!我在这里的提示词依赖于 25 年以上的专业编程经验,包括我之前对 GitHub Actions、GitHub Pages、GitHub 本身以及我使用的 LLM 工具的探索。
我也知道这会起作用。我花了足够多的时间使用这些工具,我相信使用从我的 Git 历史记录中提取的信息组装一个新的 HTML 页面完全在优秀 LLM 的能力范围内。
我的提示词反映了这一点 —— 这里没有什么特别新颖的东西,所以我口述了设计,在它工作时测试了结果,偶尔推动它修复错误。
如果我试图构建一个 Linux 内核驱动程序 —— 一个我几乎一无所知的领域 —— 我的过程将完全不同。
奖励:回答有关代码库的问题
如果你觉得使用 LLM 为你写代码仍旧没有吸引力,那么还有另一个用例可能会让你觉得更有吸引力。
优秀的 LLM 非常擅长回答有关代码的问题。
这也是非常低风险的:最糟糕的情况是它们可能会出错。因此,你可能需要花一点时间才能弄清楚。与完全自己挖掘数千行代码相比,这仍然可能会节省你的时间。
这里的技巧是将代码提交给长上下文模型中并开始提问。我目前最喜欢的模型是 gemini-2.0-pro-exp-02-05,这是 Google Gemini 2.0 Pro 的预览版,目前可通过其 API 免费使用。
我前几天就用过这个技巧。当时我正在尝试一种对我来说很新的工具 monolith,这是一个用 Rust 编写的 CLI 工具,它可以下载网页及其所有依赖资产(CSS、图像等)并将它们捆绑到一个存档文件中。
我很好奇它是如何工作的,所以我将它克隆到了我的临时目录中并运行了以下命令:
我在这里使用我自己的 files-to-prompt 工具(去年由 Claude 3 Opus 为我构建)将库中所有文件的内容收集到一个流中。然后我将其导入我的 LLM 工具并告诉它(通过 llm-gemini 插件)使用系统提示词「architectural perspective as markdown」来调用 Gemini 2.0 Pro。
这给了我一份详细的文档,描述了该工具的工作原理 —— 哪些源文件做什么,以及最重要的是,它使用了哪些 Rust 包。我了解到它使用了 reqwest、html5ever、markup5ever_rcdom 和 cssparser,并且根本没有评估 JavaScript,这是一个重要的限制。
我每周都会使用这个技巧几次。这是开始深入研究新代码库的好方法。
#FLIP
世界模型在机器人任务规划中的全新范式:NUS邵林团队提出通用机器人规划模型FLIP
本文的作者均来自新加坡国立大学 LinS Lab。本文第一作者为新加坡国立大学博士生高崇凯,其余作者为北京大学实习生张浩卓,新加坡国立大学博士生徐志轩,新加坡国立大学硕士生蔡哲豪。本文的通讯作者为新加坡国立大学助理教授邵林。
人类具有通用的、解决长时序复杂任务的规划能力,这在我们处理生活中的复杂操作任务时很有用。这种能力可以被描述为这样的过程:首先,人们会在面临一个任务时思考当前可能的动作,然后通过想象能力预测这些步骤可能带来的结果,最后基于常识对这些结果进行打分,选择最佳动作来执行并完成任务。这种基于世界模型的搜索算法是人类解决开放世界操作任务的能力基础。这种能力背后的核心在于,人类大脑构建了一个关于物理世界的 “世界模型” 和一个通用的价值函数,他们模型赋予了我们对于物体未来状态的想象能力和规划能力。那么,机器人能否也具备这样的对物理世界的理解和想像能力,使得能够在执行任务之前就能规划好未来的步骤?
近年来,机器人技术飞速发展,我们见证了越来越多智能化机器人的出现。然而,与人类相比,现有机器人在处理复杂、多阶段任务时仍显得力不从心。它们往往依赖于特定任务的数据和预设指令,或者借助大模型在简单的抓取技能上进行规划,难以像人类一样灵活地规划和执行复杂通用的操作任务。如何为机器人构建类似于人类的 “世界模型”,从而实现通用任务规划能力,一直是机器人研究中的核心挑战。
近日,来自新加坡国立大学的邵林团队提出了 FLIP:一种基于世界模型的视频空间任务搜索和规划框架。该方法能够适用于通用的机器人操作任务上,包括可行变物体操作和灵巧手操作任务。该方法直接基于机器人视觉空间进行任务规划,通过特殊设计的动作提出模块、动力学预测模块、和价值函数预测模块进行基于世界模型的任务规划,且具有模型参数量的可扩展性。该论文已发表在 ICLR 2025 上,并在 CoRL 2024 LEAP Workshop 中被选为 Oral Presentation。
- 论文标题:FLIP : Flow-Centric Generative Planning as General-Purpose Manipulation World Model
- 项目主页:https://nus-lins-lab.github.io/flipweb/
- 论文链接:https://arxiv.org/abs/2412.08261
- 代码链接:https://github.com/HeegerGao/FLIP
,时长01:15
一、引言
世界模型(World Models)指的是基于学习的方法,用于模拟环境的表示或模型。借助世界模型,智能体可以在模型内部进行想象、推理和规划,从而更加安全且高效地完成任务。近期生成模型的进展,特别是在视频生成领域,展示了利用互联网规模的训练数据生成高质量视频,以作为世界模拟器的应用潜力。世界模型在多个领域开辟了新途径,尤其是在机器人操纵任务方面,这也是本文的研究重点。
通用机器人的智能主要分为两个层次:第一,通过多模态输入对任务进行高层次的抽象规划;第二,通过与现实环境交互实现计划的具体执行。设计良好的世界模型能够有效地实现第一个功能,即实现基于模型的规划。这种模型需要具备交互性,能够根据给定的动作来模拟环境状态。框架的核心在于找到一种通用且可扩展的动作表示,连接高层规划和低层执行。这种动作表示需满足两个要求:一是能表达场景中不同物体、机器人及任务的多种运动;二是容易获得大量的训练数据以支持扩展。现有方法或是依赖语言描述作为高层动作,或是直接采用底层的机器人动作与世界模型互动,但这些方法存在一些限制,比如需要额外的数据或标注过程,或者无法描述精细复杂的动作细节,例如灵巧手的精细动作。这些限制激励我们探索其他更有效的动作表示。同时,现有的世界模型缺乏合适的价值函数作为结果的评价标准,对未来的规划常常限制在贪心搜索层面,难以实现真正的任务空间的搜索能力。
图像流是一种描述图像中像素随时间变化的动态表示,能够通用且简洁地表示不同机器人和物体的运动,比语言更加精细和准确。此外,图像流可以直接通过已有的视频追踪工具从视频数据中获取。同时,已有研究表明,图像流对于训练低层次的操控策略也具有很高的有效性。因此,图像流非常适合作为世界模型的动作表示。然而,目前如何使用图像流来规划机器人操控任务仍有待探索。
在本文中,我们提出了以图像流为中心的通用机器人操控规划方法(FLIP)。具体而言,我们从带有语言标注的视频数据中训练出以图像流为核心的世界模型。该世界模型包括三个模块:一是负责动作生成的图像流生成网络;二是根据图像流生成视频的动力学模型;三是进行视觉语言评估的价值模型。我们设计了一种新的训练方式,用于整合这三个模块,以实现基于模型的规划:给定初始图像和任务目标,动作模块生成多个图像流方案,动力学模型预测短期视频结果,价值模块评估视频生成结果的优劣,通过树搜索方法合成长期规划。
实验结果表明,FLIP 方法不仅可以成功解决模拟和真实环境下的多种机器人操控任务,如布料折叠、展开等,还能生成高质量的长期视频结果。同时,这些图像流和视频规划也能用于指导低层次策略的训练。此外,我们还证明了 FLIP 的三个模块均优于现有相关方法。进一步的实验也显示,FLIP 能有效模拟各种复杂的机器人操控任务,展现了其良好的交互性、零样本迁移和可扩展能力。本文的主要贡献如下:
- 提出了以图像流为中心的通用机器人操控规划方法(FLIP),实现了交互式的世界模型。
- 设计了图像流生成网络、流条件视频生成网络,以及一种新的视觉语言表示模型训练方法作为 FLIP 的核心模块。
- 通过实验验证了 FLIP 方法在多种任务上的通用性与优越性,展现了出色的长期规划能力、视频生成质量和策略指导能力。
图 1 FLIP 框架介绍
二、FLIP 的三个模块
我们把机器人操作任务建模为 MDP,我们旨在通过学习一个世界模型和一个低层策略来解决这一问题。世界模型在图像和图像流空间上进行基于模型的规划,以最大化回报,合成长时程的规划方案;而低层策略则负责在真实环境中执行这些规划。我们计划仅使用带有语言标注的视频数据集来训练世界模型,使其具备通用性和可扩展性,而低层策略则利用少量带有动作标注的数据集进行训练。为了实现基于模型的规划,我们的世界模型包含以下三个关键模块,具体将在接下来的章节中介绍。
2.1 图像流生成作为通用的动作模块
FLIP 的动作模块是一个图像流生成网络,其作用是生成图像流(即查询点在未来时刻的轨迹)作为规划的动作。我们之所以使用生成模型而非预测模型,是因为在基于模型的规划过程中,动作模块需要提供多种不同的动作候选,以用于基于采样的规划方法。具体来说,给定时刻 t 之前 h 步的图像观测历史、语言目标,以及一组二维查询点坐标,图像流生成网络会生成未来 L 个时间步内(含当前时间步)的查询点坐标。
一个关键的问题是训练数据标注。查询点的图像流可以直接使用现有的视频点跟踪模型(例如 CoTracker)从纯视频数据中提取。然而,如何选取查询点成为问题。以往的方法或是使用自动分割模型在感兴趣区域选取查询点,或是按照预定义的比例在运动和静止区域选取查询点。这些方法存在两个问题:一是现代分割模型(例如 SAM)很难在复杂场景下准确无误地分割出目标区域;二是在长时间的视频中,可能出现物体的进入或离开,仅使用初始帧的查询点会产生问题。因此,我们在每个时间步对整幅图像均匀采样密集的网格查询点,以解决第一个问题;同时,仅对短时程的视频片段进行跟踪,即从长视频的每一帧开始进行短时程跟踪,以缓解第二个问题。这样,即便有物体进出,其影响也被限制在短时程内。具体来说,对数据集中每一帧,我们均匀采样一个候选点网格,并利用现有的 Co-Tracker 工具生成未来 L 步的视频片段中的图像流。
如图 2 所示,我们设计了一个以 Transformer 架构为基础的条件变分自编码器(VAE)进行图像流生成。与之前预测绝对坐标的方法不同,我们发现预测相对位移的表现更好,即预测每个查询点的坐标变化量。在 VAE 编码器端,我们对真实图像流进行编码,将观测历史转换成图像区块(patches),并利用语言模型 Llama 进行语言嵌入编码成 token,将它们与一个用于信息汇聚的 CLS token 拼接后送入 Transformer 编码器,将 CLS 位置的输出提取为 VAE 的隐变量。在 VAE 解码器端,我们首先将当前时刻 t 的查询点编码成查询 token,将它们与图像和语言 token 以及重参数化采样出的隐变量 z 拼接后送入另一个 Transformer 编码器,提取查询 token 位置的输出,通过两个 MLP 网络预测未来 L 步的位移幅度和位移方向,从而逐步重构完整的未来图像流。同时,我们还对图像 token 位置的输出进行图像重建任务的辅助训练,这被证明对提高模型训练的准确性有帮助。
图 2 动作模块和动力学模块
2.2 基于图像流的视频生成模型作为动力学模块
我们的第二个模块是一个动力学模块,是以图像流为条件的视频生成网络,根据当前的图像观测历史、语言目标和预测的图像流生成后续 L 帧视频,以实现下一步的迭代规划。
我们设计了一种新的基于潜在空间的视频扩散模型,能够有效地接受多种条件输入,如图像、图像流和语言。该模型基于 DiT 架构构建,并结合了空间 - 时间注意力机制。在此我们着重介绍多模态条件处理机制的设计。在原始的 DiT 及之前基于轨迹条件的视频扩散模型中,通常使用自适应层归一化(AdaLN-Zero)处理条件输入(例如扩散步骤和类别标签),其通过零初始化的 MLP 网络回归出层归一化的缩放和平移参数。然而,这种机制会将所有条件信息压缩为标量,无法实现条件与输入之间更精细的交互,因此不适用于图像与图像流等复杂条件。为了解决这一问题,我们提出了一种混合条件处理机制,用于多模态条件生成。
具体而言,我们使用交叉注意力机制,使图像流条件(表示为目标点的 tokens)与观测条件及带噪帧之间进行细粒度的交互。对于历史图像观测条件,我们将其直接拼接到高斯噪声帧上。此外,我们仍然使用 AdaLN-Zero 机制处理全局条件,包括扩散步骤和语言指令,以整体指导扩散过程。为了保证观测条件的清晰性,在扩散过程中我们既不向观测历史添加噪声,也不对其进行去噪处理。
2.3 视觉 - 语言表征学习作为价值函数模块
FLIP 的价值模块基于语言目标对当前图像进行评估,从而生成一个价值函数估计 V̂t,用于在图像空间进行基于模型的规划:V̂t = V (ot, g)。在本研究中,我们采用了 LIV 模型作为价值函数。LIV 首先从带语言标注的无动作视频中学习语言 - 视觉的共享表示,随后基于当前图像与目标语言的相似度计算价值。具体而言,LIV 计算图像与语言表示的加权余弦相似度,作为价值的衡量标准。预训练的 LIV 模型在应用于新任务时需要进行微调以获得良好的价值表示。原始的微调损失包括图像损失和语言图像损失,前者通过时间对比学习增加起始帧与结束帧的相似性,同时将相邻帧的嵌入距离维持为(经过折扣的)固定值;后者则鼓励目标图像与目标语言的相似性提升。
然而,我们发现该原始的微调方法对于长时程且不完美的视频数据表现不佳,微调后的价值曲线呈现明显的剧烈波动,这对基于采样的规划算法十分不利,因为多数规划算法期望平滑的价值曲线。例如在规划过程中,机械臂可能出现暂停或犹豫等情况,导致任务表现不稳定。为了缓解这一问题,我们将原有损失函数中 "相邻帧" 的概念替换为 "相邻状态",将状态定义为短时程的视频片段。具体地,我们将长视频划分为多个固定长度的小片段,每个片段被视作视频的最小单元。通过此调整,能有效平滑价值曲线,显著改善规划过程中价值评估的平滑性,如图 3 所示。
图 3 价值函数模块
三、基于流的世界模型规划算法
3.1 基于模型的图像流、视频与价值函数规划
直接以自回归方式生成长时程视频通常不够准确。因此,我们采用基于模型的规划方法,使用图像流动作模块和视频生成模块,通过最大化累积折扣回报来规划未来视频帧,公式表示为:
根据贝尔曼方程,这等效于每一步选择使即时奖励与未来状态价值之和最大的下一状态。我们设计的奖励机制也鼓励找到最短的规划路径。我们使用爬山法(Hill Climbing)解决该问题,具体操作是首先初始化 B 个规划束(beam)。在每个时刻 t,根据当前的图像观测历史和语言目标,动作模块生成多个图像流动作候选方案;然后动力学模块基于这些图像流生成若干个短期未来视频片段。接着,通过价值模块评估生成的视频,选择 A 个视频中具有最高奖励的视频,以进行下一轮迭代。为了防止规划过程过于依赖某些异常状态,我们周期性地将具有最低价值的规划束替换为最高价值的规划束。该算法总结在图 4 中。
3.2 下层策略的实现
FLIP 的低层策略负责具体执行规划好的动作。在给定当前图像历史、语言目标、图像流动作,以及视频生成模块生成的短时程视频后,该策略预测具体的低层机器人动作,从而引导机器人在真实环境中进行操作。我们训练了多个策略,每个策略输入不同类型的条件信息,所有策略都仅需使用少量的示范数据进行训练。
图 4 基于世界模型的规划算法流程
四、实验结果
4.1 基于模型的机器人操控任务规划结果
在本节中,我们首先展示 FLIP 能够:1)实现不同机器人操控任务的基于模型的规划;2)合成长时程视频(≥ 200 帧);3)指导低层策略在模拟和真实环境中执行任务。我们也分别评估动作模块、动态模块和价值模块,并展示 FLIP 的交互性、零样本转移能力和扩展性。
实验设置。在本节中,我们使用四个基准测试 FLIP 的规划能力。模型以初始图像和语言指令为输入,搜索图像流和视频空间合成任务规划方案。第一个基准是 LIBERO-LONG,一个包含 10 个长时程桌面操控任务的仿真基准,我们使用分辨率为 128×128×3 的 50×10 个视频进行训练,并在新的 50×10 个随机初始化上测试。第二个基准是 FMB,包含物体操作和装配任务,我们使用 1,000 个单物体多阶段视频和 100 个多物体多阶段视频(分辨率 128×128×3)训练,在 50 个新初始化上测试。第三和第四个基准是布料折叠和展开任务,我们使用各 40 个不同视角的视频进行训练,在 10 个新视角上测试(分辨率 96×128×3)。评估方式为人工检查生成视频是否成功解决任务,我们与两个基准方法进行比较:1)UniPi,一种基于文本的视频生成方法;2)FLIP-NV,即移除价值模块的 FLIP 版本。
结果。实验结果如图 5 所示,显示 UniPi 的成功率较低,表明直接生成长视频有较大难度。FLIP-NV 表现优于 UniPi,说明图像流能有效指导视频生成。FLIP 的表现超过了所有基准,体现了价值模块对基于模型规划的重要性。
4.2 长时程视频生成评估
实验设置。本节我们定量评估 FLIP 生成长时程视频的质量,与其它视频生成模型进行对比。我们选择 LIBERO-LONG、FMB、布料折叠 / 展开,以及 Bridge-V2 基准进行评估,视频长度普遍超过 200 帧(Bridge-V2 除外)。我们选择的基准方法包括 LVDM(一种先进的文本到视频方法)和 IRASim(一种以机械臂末端轨迹为条件的视频生成方法)。评估指标包括潜在空间的 L2 距离、像素空间的 PSNR 和 FVD 视频质量评估指标。
图 5 定量实验结果
结果如图 5 所示。FLIP 在所有数据集上表现均优于基准方法。LVDM 在较短的 Bridge-V2 上表现尚可,但在长视频基准(如 LIBERO-LONG 和 FMB)表现不佳。IRASim 表现优于 LVDM,说明轨迹引导的重要性,但由于其自回归生成方式,仍不及 FLIP 通过模型规划和短视频片段拼接的方式生成高质量视频。FMB 的表现普遍较差,原因在于训练视频包含大量瞬时跳跃行为,而 FLIP 依靠历史观测的方式在一定程度上克服了这一问题。我们还定性展示了 FLIP 在 ALOHA 任务、转笔、机器人取药、系塑料袋、人类剥鸡蛋等复杂长视频任务上的应用,如图 6 所示。
图 6 基于世界模型的任务规划结果
4.3 上层规划引导的下层策略实验
实验设置。本节我们探讨生成的图像流和视频规划如何作为条件,用于训练操控策略完成任务。主要问题是确定图像流或视频(或二者结合)哪个更适合指导策略学习。我们使用 LIBERO-LONG 基准进行评估,每个任务使用 10 个带动作标注和 50 个无动作标注的视频示范进行训练。推理阶段,FLIP 作为闭环策略,每执行一段动作后重新规划。我们与 ATM 及其扩散策略版本,以及 OpenVLA(零样本和微调版)进行比较。
结果分析如图 7 所示。我们可以发现,相比扩散策略和 ATM-DP,我们提出的计划引导策略表现出更高的成功率,这表明密集的图像流信息和高质量的未来视频作为条件要优于稀疏的图像流信息。其中,图像流与视频共同引导的策略(Ours-FV)表现最佳,说明结合图像流和视频作为条件信息有助于提升策略成功率。此外,仅用视频引导的策略(Ours-V)虽然表现尚可,但在机器人偏离训练轨迹时生成的视频质量会降低,导致较大的表现波动;而加入图像流作为额外条件后,成功率的方差明显减小,体现了图像流预测的稳定性。
图 7 基于图像流的下层模型的成功率,和 FLIP 的价值函数模块效果
4.4 FLIP 基础特性的实验验证
为展示 FLIP 的几个关键特性,我们在 LIBERO-LONG 等基准数据集上进行了额外的实验验证。实验结果展示在图 8 中。
交互式世界模型能力。我们验证了训练好的动力学模块的交互性,即能够根据人为指定的图像流生成相应的视频。实验表明,该模块能够准确响应用户指定的图像流,生成对应的视频。
零样本迁移能力。我们展示了预训练的 FLIP 模型无需额外微调,即可有效处理未见过的任务数据,成功生成自然的机器人动作,表明 FLIP 具备一定的知识迁移能力。
可扩展性。通过在大规模视频数据集上训练,FLIP 显示出较好的扩展能力。即使面对大量复杂任务和视频数据,模型依然能稳定地实现有效的规划和视频生成。
图 8 FLIP 的三个特性
五、结语
在本研究中,我们提出了 FLIP,一种以图像流为核心的通用机器人操控任务生成规划方法。FLIP 通过图像流和视频生成实现对多种操控任务的通用规划。尽管 FLIP 表现出色,但仍存在一些局限性:首先是规划速度较慢,主要由于规划阶段需要进行大量的视频生成过程,限制了该方法在准静态操控任务中的应用。其次,FLIP 未使用场景的物理属性和三维信息。未来的研究可以考虑开发结合物理性质与三维场景信息的世界模型,以进一步扩展 FLIP 的适用范围。
#LightGen
无需百卡集群!港科等开源: 极低成本文生图方案媲美SOTA模型
LightGen 主要作者来自香港科技大学和 Everlyn AI, 第一作者为香港科技大学准博士生吴显峰,主要研究方向为生成式人工智能和 AI4Science。通讯作者为香港科技大学助理教授 Harry Yang 和中佛罗里达副教授 Sernam Lim。
共同一作有香港科技大学访问学生白亚靖,香港科技大学博士生郑皓泽,Everlyn AI 实习生陈浩东,香港科技大学博士生刘业鑫。还有来自香港科技大学博士生王子豪,马煦然,香港科技大学访问学生束文杰以及 Everlyn AI 实习生吴显祖。
文本到图像(Text-to-Image, T2I)生成任务近年来取得了飞速进展,其中以扩散模型(如 Stable Diffusion、DiT 等)和自回归(AR)模型为代表的方法取得了显著成果。然而,这些主流的生成模型通常依赖于超大规模的数据集和巨大的参数量,导致计算成本高昂、落地困难,难以高效地应用于实际生产环境。
为了解决这一难题,香港科技大学 Harry Yang 教授团队联合 Everlyn AI 和 UCF,提出了一种名为 LightGen 的新型高效图像生成模型,致力于在有限的数据和计算资源下,快速实现高质量图像的生成,推动自回归模型在视觉生成领域更高效、更务实地发展与应用。
论文标题:LightGen: Efficient Image Generation through Knowledge Distillation and Direct Preference Optimization
论文链接:https://arxiv.org/abs/2503.08619
模型链接:https://huggingface.co/Beckham808/LightGen
项目链接:https://github.com/XianfengWu01/LightGen
LightGen 借助知识蒸馏(KD)和直接偏好优化(DPO)策略,有效压缩了大规模图像生成模型的训练流程,不仅显著降低了数据规模与计算资源需求,而且在高质量图像生成任务上展现了与 SOTA 模型相媲美的卓越性能。
LightGen 相较于现有的生成模型,尽管参数量更小、预训练数据规模更精简,却在 geneval 图像生成任务的基准评测中达到甚至超出了部分最先进(SOTA)模型的性能。
此外,LightGen 在效率与性能之间实现了良好的平衡,成功地将传统上需要数千 GPU days 的预训练过程缩短至仅 88 个 GPU days,即可完成高质量图像生成模型的训练。
方法描述
LightGen 采用的训练流程主要包括以下关键步骤:
1. 数据 KD:利用当前 SOTA 的 T2I 模型,生成包含丰富语义的高质量合成图像数据集。这一数据集的图像具有较高的视觉多样性,同时包含由最先进的大型多模态语言模型(如 GPT-4o)生成的丰富多样的文本标注,从而确保训练数据在文本和图像两个维度上的多样性。
2.DPO 后处理:由于合成数据在高频细节和空间位置捕获上的不足,作者引入了直接偏好优化技术作为后处理手段,通过微调模型参数优化生成图像与参考图像之间的差异,有效提升图像细节和空间关系的准确性,增强了生成图像的质量与鲁棒性。
通过以上方法,LightGen 显著降低了图像生成模型的训练成本与计算需求,展现了在资源受限环境下获取高效、高质量图像生成模型的潜力。
实验分析
作者通过实验对比了 LightGen 与现有的多种 SOTA 的 T2I 生成模型,使用 GenEval 作为 benchmark 来验证我们的模型和其他开源模型的性能。
结果表明,我们的模型在模型参数和训练数量都小于其他模型的的前提下,在 256×256 和 512×512 分辨率下的图像生成任务中的表现均接近或超过现有的 SOTA 模型。
LightGen 在单物体、双物体以及颜色合成任务上明显优于扩散模型和自回归模型,在不使用 DPO 方法的情况下,分别达到 0.49(80k 步训练)和 0.53 的整体性能分数。在更高的 512×512 分辨率上,LightGen 达到了可比肩当前 SOTA 模型的成绩,整体性能分数达到 0.62,几乎超过所有现有方法。特别地,加入 DPO 方法后,模型在位置准确性和高频细节方面的表现始终稳定提升,这体现了 DPO 在解决合成数据缺陷上的有效性。
消融实验
消融实验结果显示,当数据规模达到约 100 万张图像时,性能提升会遇到瓶颈,进一步增加数据规模带来的收益很有限。因此,我们最终选择了 200 万张图像作为最优的预训练数据规模。
上图 (b) 探讨了不同训练迭代次数对 GenEval 在 256 与 512 分辨率下性能的影响。值得注意的是,在 256 像素阶段,仅经过 80k 训练步数便能达到相当不错的性能,这突显了数据蒸馏方法在训练效率上的优势。
总结与展望
LightGen 研究有效地降低了 T2I 模型训练的资源门槛,证明了通过关注数据多样性、小型化模型架构和优化训练策略,可以在极少量数据和计算资源的情况下达到最先进模型的性能表现。未来研究可进一步探索该方法在其他生成任务(如视频生成)上的应用,推动高效、低资源需求的生成模型进一步发展,以实现更加广泛的技术普及与落地应用。