序言
前端和设计师一直以来都在致力于为用户提供出色的人机交互体验。在这个过程中,如何为双方提供高效的协同产品,降低设计师与前端的沟通成本,以及提升双方的工作效率,都是非常有价值的探索点。
笔者来自网易云音乐-公共技术部,目前是云音乐设计中台的技术负责人。从 2021 年 7 月入职网易到现在,一直在「前端与设计协同」领域里探索和实践,期间沉淀了若干经验和方法论,希望能和大家一起分享,于是就有了这篇文章。
本文将从问题出发,详细介绍云音乐设计协同的演进之路。按照时间的维度,云音乐设计协同的演进之路为:
PS:本文很长,万字有余,赶时间的同学可在 ChatGPT 的陪同下阅读。
提起「前端与设计协同」(后面简称「设计协同」),相信大家都不陌生。它伴随着互联网精细化的分工而出现,在 PC 互联网时代发展壮大,在移动互联网时代趋于成熟。
而所谓「设计协同」,其主要功能就是在设计师和前端的协同工作下,将产品需求转化成代码的过程。
所以,我们研究「设计协同」的目的,就是设法使协同流程变高效,缩短产品的交付时间。
为此,我们需要解决以下三个问题:
然而,同时解决这三件事并不容易。
因为,这三件事彼此互为关联,并不独立,在协同上下游上相互影响。如果单纯 Case By Case 地解决,很容易出现【解决了问题 A,但引发了问题 B】的尴尬情况。
所以「设计协同」需要的不是单点方案,而是系统化的解决方案。
时间回到 2021 年,彼时云音乐的设计协同还较为初级,我称之为 「原始阶段」。
「原始阶段」存在的问题比较多,可以用下面这张图来说明:
此外,开发作为设计的下游,设计侧存在的问题,也会同步影响到开发侧,具体体现在:
分析之后不难得出,以上问题存在的根本原因在于:
而业界解决此问题的传统思路,一般是采取以 设计系统 为中心的「有损」设计协同。
作为背景知识,在这里容我先简单介绍一下设计系统。
设计系统(Design System)不是系统设计(System Design),前者是关于设计的系统,后者是关于系统的设计 🤣。
具体而言,所谓设计系统,就是一系列遵循严格设计规范的可复用的组件集合,由风格指南、模式库和组件库三部分组成。 而关于它的定义,最早可追溯到 Design Better - Introducing design systems 这篇文章对其的介绍。
而以 设计系统 为中心的「有损」设计协同,具体而言,就是为设计系统提供两套组件实现:
基于此的工作流程一般为:
为什么这么说呢?
这是因为,在以设计系统为中心的解决方案之中,设计规范存在两套相互独立的实现:
这就导致二者并不同源。
因此,设计意图从设计师传递到前端的过程中,不可避免引入「信息损耗」,而这种「损耗」则必须通过人的沟通才能解决,从而导致了不确定性和时间成本的产生。
所以,解决问题的关键在于,能否设法消除这种「信息损耗」?
于是,我们提出了基于 C2D2C 的无损设计协同。其核心思路是:通过工程化的手段,打通设计和前端,统一协作语言。
具体做法为:
整体如下图所示:
此方案的好处主要有:
为此,为了实现基于 C2D2C 的无损设计协同,我们构建了三个子产品:
这个三个子产品共同实现了 C2D2C 的闭环流程:
这里有一个完整的演示,用来说明三者是如何相互联动, C2D2C 闭环的:
海豚设计系统是 C2D2C 的基石,但是构建起来并不容易。
首先,由于云音乐 App 使用的跨端技术栈有两套:
所以,海豚组件库需要同时支持 React Native 和 H5。在技术选型上,有两种方案可供选择。
方案一:分别为 React Native 和 H5 独立实现两套组件库
方案二:只实现一套 React Native 组件库,利用 react-native-web 实现 H5 的兼容
鉴于需要开发的组件数量较多(50 +),且开发资源有限(2 人),综合考虑投入产出比后,最终选用了方案二。
好的技术架构决定产品的生命力,特别是像组件库这种生命周期长的产品。在选用了方案二后,摆在我们面前的问题有:
为了解决以上问题,我们设计了海豚组件库的三层架构:
它主要特点有:
换肤是云音乐 App 的重要功能;此外,云音乐还存在着像直播、音街这类不同子品牌的 App。
所以,为了支持以上这些场景,海豚组件库需要:
那具体要如何实现呢?
我们的核心思路是:抽象变与不变,描述组件的组成关系。
以海豚 Button 为例,决定 Button 样式变化的 4 个属性分别为:
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
type | 类型 | 'surface', 'outline', 'text' | 'surface' |
level | 层级 | 'primary', 'secondary', 'normal' | 'primary' |
ghost | 是否是幽灵按钮 | boolean | false |
size | 大小 | 'xs', 's', 'm', 'l', 'xl', 'xxl' | 'l' |
所以,可以按照这四个维度,将 Button 拆解成 变化的视觉 + 不变的骨架。
变化的视觉为:
不变的骨架,是由这四个属性排列组合成的正交变体:
通过将变化的视觉解构成两类 token:
colorPrimary1
colorNeutral4
spaceModule1
spaceComponent1
fontSizeMedium1
buttonPaddingXS
: theme.spaceComponent5
buttonHeightXS
: 18
最后,只要配置不同的全局 token 和组件 token,就能实现全局换肤和组件粒度的品牌定制。
Fin 1.0 设计插件的定位是提供给设计师的设计资产管理工具,让设计师可以利用 C2D 技术搭建出设计稿。
鉴于当时(2021 年)Sketch 还是主流设计软件,Figma 在设计团队中的使用也比较多,这就要求我们要同时支持 Sketch 和 Figma。
为了降低研发成本,我们设计了跨平台的插件架构,其核心思路就是用 Web 来承载 UI 和业务逻辑。
我们可以把插件分成 端容器 Client 和 Webview:
这样拆分后,Sketch 和 Figma 便能完全复用 UI,仅需要针对「端容器」和「Webview」通信方式、设计稿渲染逻辑上的不同,在 Client 上做差异化处理即可。
C2D 的本质是代码转设计稿。
在业界,目前做 C2D 一般有两种思路:
思路一:将 Sketch 或 Figma 作为 React 的一个端,利用类 RN 的语法,渲染出设计稿,比如 airbnb 的 react-sketchapp;
思路二:直接将组件的 html 转设计稿,比如 ant-design 的 html2sketch。
对 Sketch 而言,由于其发布的时间较早,C2D 的生态相对成熟,基于 html 的开源方案有 html-sketchapp、 html2sketch,但是 html2sketch 作为后来者在还原度上更佳,所以最终选用了 html2sketch 作为 Sketch 的 C2D 方案。
而 Figma 是 2016 年发布的,相对年轻,其 C2D 的生态还不够成熟,基于 html 的开源方案有 figma-html,但是其还原度还不够好,所以我们参考了 figma-html 的思路,选择了自研 html2figma。
html2figma 的本质,其实就是 DSL 的转换:将描述网页的 html, 转换成描述 Figma 设计稿的 Schema。
具体而言,就是将 html 的元素,比如 div 标签
、p 标签
、svg 标签
,映射成 figma 的 frame 节点、文字节点和矢量节点。
举个 🌰:我们有一个 div
元素,长和宽为 80px
,圆角为 40px
,背景色为红色。
我们可以将其转换成 Figma Frame Schema:长和宽分别为 80px
,填充色为红色,圆角为 40px
。
转换之后,通过 Figma 的 Plugin API, 就可以将其渲染到画布上,可以看到,二者在视觉上完全一样。
更多转换细节就不再展开了,感兴趣的同学可参考 figma-html 关于此转换的实现。
海豹 D2C 是 C2D2C 的最后一步:将设计稿转换成代码。
说到 D2C,想必大家也并不陌生,比如阿里巴巴的 imgcook,或者是京东的 Deco 。特别是 imgcook,由于其率先将基于 AI 的 D2C 用在生产环境,而且取得了不错的效果,这可能就会给大家造成一种误解:认为 D2C 就一定要用到 AI。
其实,不一定。
因为 D2C 的本质是将设计意图还原成代码,所以 D2C 的关键就在于如何让机器理解设计意图。
对于一张图片而言,由于其是非结构化的,它的所有信息完全包含在其二维像素平面内。对于这种场景,用基于 CV 技术的 AI 模型做组件识别,然后基于识别结果做 D2C 是非常合适的,但实现成本会比较高,因为会涉及到大量的数据标记和模型训练工作,整体 ROI 会较低。
但是,对于 Sketch 或 Figma 设计稿而言,因为其本身是结构化的,所以将其转换成代码是完全可行的,社区也有很多插件能做到这点,但真正的难点在于组件识别,也就是如何识别图层,将其与已有的组件库进行关联。
而海豹 D2C 的优势就在于,以较低的成本,实现了基于元数据的组件识别方案。
在「Fin 1.0 设计插件」的介绍中,我们知道,通过 Fin 1.0 C2D 产出的设计稿,会默认注入组件元数据,所以在 D2C 的过程中,只需要检测当前图层是否包含元数据,便能实现组件识别功能。
具体的处理流程为:
由于设计稿是设计师在画布上通过拖拉拽搭建出来的,受设计师作图习惯的影响,设计稿中的元素一般都是平铺的。
如果不进行布局优化,那么整个页面将是一个扁平的结构,生成的将是绝对定位的代码,虽然还原度能够保证,但是可读性会比较差,比如:
而布局优化的过程,则是对 ABCD 进行分组,首先将页面分为 ABC 和 D 两行,然后将 ABC 分为 A 和 BC 两列,最后将 BC 分为 B 和 C 两行。
分好组后,通过新增三个布局容器,形成行列嵌套结构,这样最终生成的代码将符合开发者的直觉,具备较好的可读性:
从上面优化的过程可知,布局优化,其实就是在做行列分割,完整的流程如下图所示:
第一步,获取待处理的所有节点坐标。
第二步,对所有节点做节点关系处理,判断它们是处于包含、还是相交还是相离关系。处理逻辑为:
第三步,对处理完成的节点做二维空间投影,找到行列分割的依据,例如:
第四步,依据二维投影得到的信息,对节点做行列分割,然后添加布局节点,进行行列分组。
最后一步,就是计算样式,生成包括 Flex 布局、绝对定位以及 Margin 偏移量等。
由于篇幅有限,关于设计工程化阶段 1.0 更为详细的介绍,可参阅笔者在 GMTC 上的分享:《网易云音乐基于 C2D2C 的无损设计协同》[]
工程化阶段 2.0 是对工程化阶段 1.0 的补充和完善。
为什么要做设计工程化阶段 2.0 呢?那肯定是 1.0 存在某些问题。(笑
随着 Fin 1.0(C2D) 和 D2C 落地的深入,一些问题也慢慢暴露出来。
在 2022 年中的时候,在线协同类设计软件慢慢崛起,Sketch 已是明日黄花,云音乐的设计团队已基本全面拥抱 Figma / MasterGo 这类在线协同类设计软件。
随着设计师对此类工具了解的加深,他们发现使用 Fin 1.0 C2D 来做设计稿存在以下问题:
在 D2C 最初的产品设计中,我们将云音乐的页面类型分为两种:
我们的判断是:
所以,我们认为 C2D2C 非常优雅地解决了组件识别的问题。
但随着业务落地的深入,我们发现,对于营销活动页面而言,虽然没有既定的设计规范,但也会用到一些通用的 UI Pattern,比如弹窗:
对于此类场景,由于弹窗的样式并不稳定,无法沉淀成规范,这就导致:
最后造成前端需要基于已有组件库(比如 antd)进行大量的样式复写,工作量大且低效。
另外,虽然 D2C 在出码阶段进行了布局优化,但是用户反馈生成的代码可读性还是存在一些问题,特别是生成的 className:
总结一下,工程化 2.0 面临的问题主要有 3 个:
在回答这个问题前,我们需要做一些拆解。
对设计师友好的 C2D = 对设计师友好的工作方式 + C2D
那什么是对设计师友好的工作方式呢?通过用户调研后发现,对设计师友好的工作方式,有以下几个特点:
具体到设计稿生产,就是能利用 Library 来做设计。
那 Library 要如何与 C2D 进行结合呢?通过对 Library 调研后发现,Figma / MasterGo 原生提供的 Library 能力很强大,支持 Component 和 Variant ,能实现设计稿与代码的一一对应:
且通过原生提供的属性配置面板,能非常高效便捷地完成组件的配置!
因此,对设计师友好的 C2D,就是为设计师提供一套海豚组件的 Library,但是这套 Library 是通过 C2D 生成的!
相应地,我们做 C2D 的思路,就从「运行时动态生成并注入元数据」变成了 「预构建 Library 并注入元数据」,由于设计稿元数据的格式没变,所以后续的 D2C 流程完全不受影响,完美!
对于这个问题,现有 D2C 难以解决的原因是:
那有没有既能解决 UI 定制化的问题,又能保留组件的交互逻辑的方案呢?
于是,我们提出了基于 Headless UI 的 D2C 方案。
作为背景知识,首先简单介绍下 Headless UI。
Headless UI,顾名思义就是没有样式的 UI,只保留了骨架和交互逻辑,样式完全依靠用户自定义。它可以看成「样式与逻辑分离」在组件库上的一种实践。
所以,利用 Headless UI,将「样式与逻辑分离」的思想,应用在 D2C 上,不就可以实现了吗?!
对于这个问题,若在前 LLM 时代,是非常难解的。
但随着 LLM 时代的到来,GPT 3.5、GPT 4 等大模型的成熟,这个问题变得非常简单了:直接丢给大模型做语义优化即可。
当然,由于大模型的黑盒性质 + 结果不稳定,需要通过一些工程实践来规避由此带来的不确定性。
以海豚的 Button 为例,和样式相关的 API 有:
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
type | 按钮类型 | "outline" | "text" | "surface" | surface |
level | 按钮层级 | "primary" | "secondary" | "normal" | primary |
ghost | 是否为幽灵按钮 | boolean | false |
size | 按钮大小 | "m" | "xs" | "s" | "l" | "xl" | "xxl" | l |
disabled | 是否禁用 | boolean | false |
leftIcon | 左侧图标 | ReactNode | - |
rightIcon | 右侧图标 | ReactNode | - |
loading | 设置按钮载入状态 | boolean | - |
如果要构建 Button 的 Library,则需要为 Button 的每一种不同的样式组合,在 Library 中提供一个对应的变体(Variant)。
我们可以简单估算一下,下面是 8 个与样式相关的参数的枚举值统计:
参数 | 枚举数量 |
---|---|
type | 3 |
level | 3 |
ghost | 2 |
size | 6 |
disabled | 2 |
leftIcon | 7(默认提供 7 种) |
rightIcon | 7(默认提供 7 种) |
loading | 2 |
组合而成的变体数量为:3 *3*2*6*2*7* 7* 2 = 21168 个。
是不是很震惊?
一个 Button 就有上万个变体,50 多个组件全加在一起,数量将是巨大的。
人工来做完全不现实。
所以,肯定要借助工程化的手段,通过脚本来批量生产。
得益于我们在 Fin 1.0 中 C2D 技术上的积累,我们通过 html2figma 实现了 Library 的自动化生产。
以 Button 为例:
视频演示为:
这是我们采用此方案构建的海豚组件库 Library :
由于营销活动的组件非常业务化,所以最好是可以将此能力开放出来,让用户自行定义、自行处理。
为此,我们设计了 D2C 的微插件方案,通过为用户暴露 D2C 生命周期各阶段的 Hook,让用户可以实现:
然后,基于微插件,业务开发利用我们提供的 Headless UI 微插件脚手架,适配到自己的业务场景即可,具体的使用流程为:
视频演示:
如果直接将 D2C 生成的 JSX 和 CSS 输入给 LLM,让其对 className 进行语义化,并输出 JSX 和 CSS,在大部分情况下能正常 work,但是存在两个潜在的问题:
为此,我们对此过程进行了改造:
具体的 Prompt 为:
You are a front-end technologist.
Help me process the incoming JSX code so that the className is well semanticised and overall readable.
Then output the mapping relationship before and after the className to me in JSON (direct JSON output). For example:
Input:
```jsx
import React from 'react';
import '. /index.css';
const App = () => {
return (
<div className="music_1_1">
<div className="music_1_2"> 上一步 </div>
<div className="music_1_3"> 下一步 </div>
</div>
);
};
export default App;
```
Output:
```json
{
"music_1_1": "main",
"music_1_2": "prev",
"music_1_3": "next"
}
```
Understood, please reply 1
这样做的好处是:
Prompt 演示:
在 D2C 上的最终效果为:
时间来到 2023 年。
回顾过往,设计工程化所解决的问题,主要集中在 「降低设计与前端的沟通成本」 和 「提高前端工作效率」 上,然而,在「提高设计工作效率」方面,设计工程化的贡献相对有限。
随着 AIGC 的火爆出圈,在了解到 AIGC 在「提高设计工作效率」上的潜力后,我们决定要利用 AIGC 搞一些事情 👻。
为此,我们对云音乐的设计师进行了多次田野调查,梳理出了当前的设计流程,并按照需求来源的不同,将其分为两种:
1、需求源自策划的设计流程:
2、需求源自运营的设计流程:
通过分析后发现,现有的设计流程存在以下痛点:
具体情况如下图所示:
我们都知道,问题能被解决的关键,在于是否能清晰地定义问题。
因此,为了从根本上解决上述问题,我们必须回答:UI 设计的本质是什么?
为此,我们可以对设计流程进行抽象和简化,如下图所示:
可以看到,UI 设计可以抽象成一个输入输出模型:输入是自然语言描述的需求,输出是设计稿。
因此,UI 设计的本质,就是一个「将自然语言描述的需求翻译成设计稿」的过程。
具体而言,就是将「自然语言描述的需求」翻译成由若干由「组件」、「图标」或「图片」组合而成的设计稿,这个过程可以用下面的公式来表达:
那么,造成的「UI 设计低效」的原因,就在于这个「翻译的过程」大部分是由人参与并执行的,这是因为:
所以,如果想从根本上解决 UI 设计的效率问题,就应该利用 AIGC 重构这个「翻译过程」:
而为了实现以上目标,我们需要解决以下三个「翻译问题」:
为此,我们推出了全新的产品——Fin 2.0,提供三大 AIGC 能力矩阵(文生稿、文生图、文生 ICON)+ AIGC 资产共享中心,赋能策划、运营、设计,降低沟通成本,提高设计效率,让业务创新变得简单。
文生稿:
文生图:
文生 ICON:赋能设计师,降低 ICON 生产的时间成本。
AIGC 资产共享中心:对用户 AIGC 过程中产出的设计组件、提示词、图片和 ICON 进行回流沉淀,共享复用。
1、需求源自策划的设计流程
新流程特点:
2、需求源自运营的设计流程
新流程特点: 赋能运营,基于「文生稿」功能,搭配「文生图」和「文生 ICON」直接出稿,免去了和设计之间沟通协作,提高了设计效率。
对于 AI 驱动的应用而言,单纯的 AI 能力(GPT 3.5/4、Stable Diffusion)并不能构成产品的核心竞争力,因为大家都是调包工程师。(笑
所以,核心竞争力在于是否具备产品力,用大白话讲,就是是否能真正解决实际问题。关于这这一点,不管是内部产品还是外部产品,同样适用。
所以,一个好的产品方案至关重要。
为了实现这一目标,Fin 2.0 的产品设计遵循以下原则:
在 LLM 时代,AI 的内涵和外延都应该被重新定义:AI 既是一种技术,也是 UI 本身,是人与机器交互的终极方案。
不管是 ChatUI、 Conversational UI 还是 Dialog UI, 都是 AI 这种全新 UI 的实现。
某大佬曾言:在 LLM 时代,所有应用都值得被 AI 重做一遍。
我的理解是:这句话的本质,讲的其实就是将现有的 GUI 重构成 AI 这种 UI。正如在图形界面时代,所有的 CLI 应用被 GUI 重做一样。
所以,我们基于 AI 这种全新的 UI 来设计产品交互,通过自然语言对话的方式提供一个「超级入口」,轻松触达所有功能,比如:
「小而美」也是我们产品设计的一个重要理念。但是,我们需要明确一个事实:小而美是实现路径,而非目标,产品的目标永远是创造价值。
在产品从 0 到 1 的阶段里,小而美是为了控制成本,聚焦产品,是非常必要的:永远是做简单且完整的产品,不是复杂事物的 0.1 版,而是简单事物的 1.0 版。
1、信息架构简单且清晰
充分利用对话式 AI 的优势,保证整体的信息架构简单且清晰,层级结构尽可能简单,2 层是极限。
2、功能简单但完整
简单且完整的功能,除了能解决问题外,还能带给人秩序感和愉悦感:
3、聚焦
通过聚焦,砍掉不必要的功能,降低研发投入:
1、精美的图标
2、合理的排版
3、流畅的动效
4、合理的引导和提示
Fin 2.0 Chat UI 的技术架构为:
其基本流程是:
以上流程中,最核心的部分是意图识别。
在前 LLM 时代,意图识别一般采用 NLP 来实现,其成本高,准确率低。LLM 时代到来后,意图识别变得非常简单和直接。
比如,我希望用户在输入「文生图」后,可以识别此意图,并自动路由到「文生图」页面上。现在只需利用 GPT 的 Few-shot learning 能力, 给出类似下面的 Prompt 即可:
System:
You need to analyze the content of Inputs based on the information of Resources, follow the constraints of Constraints, and return data that conforms to the Response Format format
Input:
打开文生图
Constraints:
1.According to Inputs, match a most relevant command KEY
2.If there is no suitable match in the preset instructions, "NOOP" is used by default
Resources:
"TEXT_TO_IMG":[STRING]当用户想要打开「文生图」功能时命中,例如输入 「打开文生图」「文生图」「AI 生图」
"TEXT_TO_DESIGN":[STRING]当用户想要打开「文生稿」功能时命中,例如输入 「打开文生稿」「文生稿」「AI 生稿」
"TEXT_TO_ICON":[STRING]当用户想要打开「文生 ICON」功能时命中,例如输入 「打开文生 ICON」「文生 ICON」「文生 icon」「AI 生 ICON」
You should only respond in JSON format as described below
Response Format:
{
"payload": “the matched instruction key",
"type": "route",
}
Ensure the response can be parsed by Javascript JSON.parse();
For example:
Input:
文生图
output:
{
"payload": "TEXT_TO_IMG"
"type":"route"
}
Understood, please reply 1
GPT 经过学习之后,就能充当一个非常好的意图识别器:
对于「文生图」而言,图片的 AIGC 已比较成熟,不管是闭源的 Midjourney,还是开源的 Stable Diffusion,都能生成效果非常棒的作品。
但正如在上面的「痛点」中所提到的:
所以,综合考虑收益和成本后,最终的方案是:基于内网部署的 Stable Diffusion(DreamMaker)进行二次封装,提供简单易用的「文生图」方案。
更为详细的介绍,可以参考:《如何使用 Fin2.0 文生图登上云音乐首页》
对于「文生 ICON」 而言,SVG 矢量图标的 AIGC ,业界暂无成熟方案。
但是,学术界已有了相关尝试:借助 Stable Diffusion 和 VectorFusion 技术,可以实现「文生 ICON」。然而,此方案仍处于实验阶段,暂无法用于生产。
所以,考虑到实际情况后,最终的解法是分阶段来实现:
语义化检索最大的优势,就是根据语义进行检索,不是传统的「关键字匹配」,更好用,更符合人类直觉。
因为图标的数量很大,有接近 2 万个,要怎么用 ChatGPT 实现 语义化搜索呢?如果直接将其作为 ChatGPT 的上下文输入,必然会超限,而且也会存在较大的 IO 性能问题。
为此,我们采用 embedding API 来实现,其基本原理是:
首先,将所有的 ICON 数据标准化成下面的格式:
{
"id": 17246,
"name": "zoom",
"library": "icon-park",
"label": "滑动,侧滑,放大,zoom,Hands,手势动作",
"style": "outlined"
}
然后, 通过 OpenAI 的 embedding API 进行向量化,并存储到向量数据库中,比如 pinecone,或者 chroma。
这里需要注意的是,由于 API 字符数的限制,需要使用文本分词器进行分批向量化。
最后,用户通过关键字进行语义搜索时,首先会对关键字进行向量匹配,向量数据库会按照相似度返回近似结果,然后将此结果连同用户的原始输入,一并提供给 ChatGPT,ChatGPT 就会返回在语义上最匹配的 ICON 了。
对于「文生稿」 而言,问题就稍为复杂一点。
大语言模型 LLM 能很好地理解自然语言,但由于其输入输出是基于文本的,所以并不能直接生成设计稿。因此,这中间必然有一个 Text2Design 的过程。
于是,就有了下面两种方案:
方案一:LLM 返回 HTML,通过 C2D 技术转成设计稿。
优势:
缺点:
方案二:LLM 返回自定义 DSL,解析 DSL 转成设计稿。
优势:
缺点:自行设计和实现 DSL 协议和渲染,有一定的开发成本,但是并不复杂。
考虑到「文生稿」需要与设计系统结合,最终选用了方案二。
我们设计的 DSL 结构非常简单,每个节点只有两个属性,componentName 和 props:
interface NodeDSL {
componentName: string;
props?: Record<string, any>;
}
type DSL = NodeDSL[];
但是利用 Figma / MasterGo 的 Component 和 Variant 能力,就能释放强大的表达能力(有点类似前端的可视化搭建):
const page: Page = [
{
componentName: 'StatusBar',
props: {
title: '歌单列表 & 专辑卡片',
},
},
{
componentName: 'List',
props: {
title: '歌单列表',
content: [
{
title: '张杰新歌',
subTitle: '曲风:流行',
icon: '🎵',
},
{
title: '周杰伦经典',
subTitle: '曲风:流行',
icon: '🎧',
},
{
title: 'KTV 最爱',
subTitle: '曲风:流行',
icon: '🎤',
},
{
title: '说唱力 MAX',
subTitle: '曲风:说唱',
icon: '🔥',
},
{
title: '粤语老歌',
subTitle: '曲风:粤语',
icon: '🎵',
},
],
},
},
{
componentName: 'Card',
props: {
title: '推荐专辑',
content: [
{
title: '跨时代',
tag: '周杰伦',
icon: '🎧',
},
{
title: '周杰伦的床边故事',
tag: '周杰伦',
icon: '🎤',
},
{
title: 'Universe',
tag: '杨峰',
icon: '🎵',
},
{
title: 'F.A.M.E.',
tag: '马尔代夫',
icon: '🔥',
},
{
title: '语重心长',
tag: '林宥嘉',
icon: '🎵',
},
{
title: '灿烂人生',
tag: '林忆莲',
icon: '🎧',
},
],
},
},
];
为了能让用户用自然语言准确地描述设计需求,我们对 Prompt 进行了规范:
Prompt = 动作 + 主体 + 主题色 + 设计风格 + 布局
比如下面的 Prompt:
设计一个音乐 App 首页,主题色为蓝色,扁平化风格,采用瀑布流
我们利用 ChatGPT 实现了一个简单的意图处理器(和 Chat UI 部分意图识别类似,不再展开),可以将用户的输入转换成下面的结构化数据:
{
"actionType": "add",
"style": "flat",
"main": "一个音乐 App 首页",
"theme": "#0000ff",
"layouts": "flow"
}
有了这样的结构化数据后,用户的意图就变得清晰了,方便后续利用不同风格的组件库、布局模版模仿人类来搭建设计稿。
通过上面所说的「意图识别」后,我们已经能够明确用户的设计需求了。那怎么让 ChatGPT 利用已有的物料模仿人类完成搭建呢?
问题的关键在于让 ChatGPT 学会使用我们提供的组件库。
因为 ChatGPT 拥有非常强大的文本理解能力,所以我们的做法其实非常简单:直接将组件的 API 文档作为上下文提供给 ChatGPT。
这种做法看似粗暴,但是效果出乎意料的好。下面是一个简化了的小 Demo:
具体的 Prompt 对话可见:https://chat.openai.com/share/69aee90a-101f-4356-87fe-e59729ec2f06
当然,实际在项目中的使用并没有这么简单,需要考虑很多工程上的问题,比如:
这些问题解决起来都不难,鉴于本文已经很长了 😅,就不再展开了。
截止到今天(2023-12-26),Fin 2.0 已累计生图 11360+,产出设计稿 921+,覆盖云音乐 10+ 业务场景,综合提效 33% ~ 200%。
网易云音乐的设计协同经历了原始阶段、工程化阶段 1.0 和 2.0,目前已进入智能化阶段。
尽管智能化刚刚起步,但充满了潜力和想象空间,尤其是近期 AI Agent 技术的蓬勃发展,将彻底重构现有的协同流程。
因此,在未来,我们将持续探索基于 AI Native 的智能化设计协同,打造云音乐设计生产一体化方案——AI2D2C 👏。
筚路蓝缕,以启山林,最后感谢为云音乐设计协同添砖加瓦的每一个人 ❤️,他们是:
感谢你们!
更多岗位,可进入网易招聘官网查看 https://hr.163.com/