在产品能力不增加的情况下,D2C的自来水用户目前依旧保持活跃。核心策略是:
- 业务赋能:提供设计稿生成代码各种原子能力,无缝融入阿里研发流程形成各个业务自己的研发解决方案,帮助提高业务交付效率。
- 提升生成代码质量:聚焦视图代码生成可用性,对标内部专业前端对代码的可维护性要求,生成高可用代码。阿里内部用户使用原子化开放能力,还原服务API 调用 227w 次左右。核心只基于问题驱动减少设计稿干预提升代码生成质量,其中问题大部分出现在布局算法层,同时由于D2C体系的复杂度,D2C本身的工程质量提升也是保持持续迭代的根基。接下来重点介绍下 D2C 布局算法和 D2C工程质量的核心进展:
▐ 布局算法背景
对于 D2C 系统整体, 数据的来源是 Sketch 等原型图设计工具的设计稿, 根据设计稿上每一个元素在空间上的分布, 例如x坐标, y坐标, 图层(z坐标), 宽度与高度, 可以精确描述整张设计稿的内容, 例如图2.1的二维设计稿, 实际上能够转化为图1.2的三维分布描述:
对于三维分布的结果, 向z的负方向进行投影, 则可以得到一颗初步成型的DOM树:
这样的操作生成的DOM节点和设计稿中元素一一对应, 但是设计稿中主要进行的是视觉描述, 存在大量被省略的中间节点, 以及少量视觉表达正常而元素使用不合理的节点, 需要经过布局算法的预处理与成组划分, 转换或生成这些新的节点。
除此以外, 布局算法需要对各元素进行识别与定位, 尤其是绝对定位元素的识别, 在判断本应在文档流内的元素的分布时混入本应在文档流外的元素, 会产生严重的错误。
▐ 布局算法优化进展
- 预处理
文本合并策略
背景
设计稿中, 存在部分“通过多个单行文本节点表达多行文本”的操作(如图2.1), 同时存在“通过间断的单行文本片段表达连续的文本”的操作(如图2.2):
基于以上问题, 需要一种文本合并的解决方案
问题定义
给定在三维空间下的单行文本元素集合, 通过一定的“搜索规则”, 找到需要合并的“单行文本节点簇”, 通过 “合并操作” 生成新的文本元素集合。
同时, “合并操作” 需要保证结果与原先的“单行文本节点簇”在二维空间投影下的显示尽可能相似。
解决方案
- 首先可以排除在二维投影中互相覆盖的元素, 因为除开“生成图片”这样的“合并操作”, 通过简单的“合并操作”不可能得到一个相似的结果, 重叠的文本无法在一个“DOM节点”中表达。
- 其二, 排除 font-size , color , font-weight 等文本样式属性不相同的合并目标, 因为生成的结果只能有同一的文本样式属性。
- 其三, “合并操作” 考虑通过 text-indent, line-height 及 "添加空格与空行" 对合并后的文本进行调整。
- 其四, 文本合并后, 如果有明显的对齐特征, 则考虑使用 text-align 进行对齐而非上述方案, 以增强文本的扩展性。
- 最后, “搜索规则” 根据经验, 定义为 “小于或等于 2 的曼哈顿距离”。
详细讨论 “合并操作”,显然,对于混合的 text-align , 处理会比较复杂, 基于此, “合并操作” 每次只处理 “两个来自设计稿的文本节点” 排除 “已处理的结果” , 这样的处理也可以避免 “无法表达的单行文本节点簇”。
定义另一个短节点为 “节点B”,基于上文中提到的 font-size 相同的前提, 不妨假设 "节点A" 有 2 个字符长, “节点B” 有 1 个字符长,滑动 “节点B” 并记录左上角顶点和右下角顶点的边界情况。
那么, 通过 “空格” 与 text-indent 可以调整x轴的起点与终点, 通过 “空行” 与 line-height 可以调整y轴的起点与终点, 两个维度的结合, 可以表达全部的52种可能,对于 text-align , 可以取52种可能中明显的对齐分布, 覆写上述策略。
角标的识别
背景
绝对定位的元素有两个来源, “几何” 与 “语义” , 其中 “几何” 的绝对定位 (或称被动的绝对定位) 在本层元素无法通过算法的布局策略定位(如元素相交) 时触发, 而 “语义” 的绝对定位 (或称主动的绝对定位) 来源于开发惯例(如 Tooltip )对于角标 (徽标 Badge) , 显然遵循 “语义的绝对定位”, 尤其是下图(图2.7)中的场景, 角标并没有和任何元素相交, “几何的绝对定位” 失效, 须提前识别到本角标元素。
解决方案
显然, 如果需要解决此类问题, 最好应当采用目标检测方法, 但是基于时间与计算资源有限, 只能人工抽样并提取特征,那么, 需要多份不同来源的含角标实体图例。
总结后, 不难发现, 子元素的 border-radius 与对齐能够作为关键特征,那么, 便可以有如下定义:
定义: 对于两节点, 通过成树后为父子关系, 且子元素非文本节点并含有 border-radius, 子元素与父元素顶部对齐, 则称子元素为角标,后续将 角标 绝对定位即可。
第一步:用行投影预处理
首先我们通过 模糊投影操作(在行投影的基础上模糊边界) 找到符合以下特征的 连续行
- 每行元素通过 列投影 能相似等分
- 每行元素通过 列间隙投影 能相似等分
- 第二行开始每行与上一行 居中对齐 或者 左对齐
- 每行每区域可能不止一个节点
找到满足以上条件的连续行,为接下来的「行合并」作准备
第二步 行合并
预处理完成之后,我们可以标记每个网格的元素类型。并且通过类型来判断每列节点的循环关系。
在此,我们综合了两种方案
方式一:直接统计每行元素类型,是否能满足固定重复的结构
例:[图文图文图文] => [[图文],[图文],[图文]]
例:[图文文图文文] => [[图文文],[图文文]]
方式二: 当上述无法判断时,通过在循环成组中使用过的 HAC聚类的方式,同样也可以找出满足循环条件的结构。
第三步 样式生成
至此,整体成组结构已经完成。将循环的部分标记为 GridItem,整体标记Grid。在样式生成时可以针对此结构,计算出网格宽高间隙,用 display: grid 来实现。
骨架成组
背景
在布局算法中,「循环成组」中主要通过对「节点类型聚类」和「节点位置向量的聚类来识别循环」
「骨架结构相似判断」将更直接的通过重合相似度来判断成组,核心是找到更多相似的行结构成组。相比较于兜底行成组,骨架可以找到更多的行间关系。
解决方案
将区域划分成 N 多个 网格状区域,N 越大,精度越高,计算越准确。分别比较每个相同位置的内容,根据不同权重来计算是否相似。注意以下几个关键特征:
- 相交区域 重合面积(内容一致的格子数)
- 相交区域 空心面积(没有节点的格子数)
- 相交区域 实心面积(有节点格子数)
- 相交区域 实心比
- 相似区域 占 相交区域 比例
- 相似区域 占 整体有变化区域 比例
- 形状结构复杂度
当然也需要运用一些 人视觉判断时的心理活动 作为判断依据:
- 结构越复杂,越奇形怪状,相似度的阈值可以更低。
- 复杂度太低的节点,严格增加限制控制相似。比如节点数量等。
- 重合面积占据空间越满,则越不可信。
当然,布局算法在原有的基础上,也引入了一些别的成组方式来解决有明显业务含义的问题,比如直接为 图标按钮这类结构成组,顶部导航栏成组,有明显视觉分割特征的分割线成组,具有严格对齐特征的行列成组。
- 样式
定宽高问题的优化
背景
大促产品化项目中,希望生成的代码后只要绑定数据源能达到直接可用的目的。其中就要求针对动态内容是否定宽要符合预期。如图,利益点“满200减30” 希望是动态宽度,而“定金100”希望是固定宽度。
解决方案
经过总结,我们认为这类卡片中,也存在一些明显可总结的规则
- 多行文本定宽(如标题)
- 单行文本,价格默认不定宽
- 图片定宽
- 标签类文本不定宽(如上图满减)
- 按钮胶囊类按钮根据文本与容器的间隙来判断容器是否定宽。(如上图定金100)
- 循环容器定宽,防止被内部元素撑开
- 通过是否充实,防止塌陷
- 特征工程
背景
当前布局算法为预测分布状况, 采用人工构造的特征, 然而这些特征并未进行过优化, 部分特征可以合并降维, 而部分也可以拆解升维, 同时了解特征对分类的贡献, 也有利于后续新的特征的构造,基于以上等原因, 可以采用决策树对样本进行解释与分析。
解决方案
对此, 将数据通过决策树进行训练, 并绘制决策树模型
基于本决策树使用“信息增益”生成, 可以合理推断出 feat_2 , feat_5 , feat_9 与 feat_10 有较高的贡献, 后续会对这四个特征进行进一步分析。
▐ 工程质量进展
- 单元测试
背景
布局算法的执行流程, 抽象来看属于Pipeline的执行流程, 下图中为布局算法的执行流程:
对于每一个最小的执行单元, 布局算法中称其为 Transformation (转换) , 其输入一个节点 node ,处理后生成一个新的节点 transformedNode将树上的每一个节点进行转化, 即一轮 “转换” , 称为 Epoch (周期) , 其输入一颗由节点构成的树, 生成一个处理后的树,上图中的每一个功能, 都可以抽象的看作一个 Epoch , 在每个 Epoch 之间, 能够获得中间结果并进行可视化。
解决方案
基于部分 Transformation 并不是标准的纯函数, 其不止作用于输入的 node 节点, 还有可能作用其子节点, 故将 Epoch 作为一个单元, 并且 Epoch 本身只依赖初始的参数设置与输入的树对象,那么, 可以简单的在各 Epoch 之间截取每一个结果, 并将其作为输入的树与输出的结果快照。
聚划算欢聚日模块使用直接生成的方式完成了整个模块的开发。其中原本需要“人工干预”才能完成的部分,通过逻辑库来实现;部分样式通过大促产品化中元件的 UI可变性来实现。
- 核心思路
- 规范视觉稿,将需求中需要作为背景图合并的内容,在图层上打#merge#标记
- 准备大促产品化中相关元件(1x3 布局,左下角的静态按钮元件,价格元件)
- 实现元件的识别逻辑,用于分析设计稿中的元件组成和关键样式
- 使用 imgcook 解析设计稿并还原之后得到 schema
- 使用逻辑库识别的方式分析结构,识别出 1x3 的一个布局
- 提取关键样式,比如左下角按钮槽位里左边的边距。
- 智能UI一直致力于做UI的有效性表达,之前的技术重点主要投入在供给和投放两个方向上:在供给侧如何提升物料的生产效率,在投放侧如何改进UI样式的推荐算法。随着智能UI和业务的深入结合,我们发现原先基于“物料&分区”的智能UI协议无法支持更细粒度的UI调控诉求,同时,在UI展现上也没有针对不同类目的商品进行差异化的信息表达,一个页面几百种商品全部采用了统一的样式进行渲染。基于这些问题我们对鲸幂平台的产品能力进行了改造升级,以更好的支撑不同的业务需求。
▐ 能力完善
- 更细粒度的UI调控能力
智能UI将一个商品模块的设计数据进行了结构化的拆解,如下:
所以原先智能 UI 的调控粒度是“物料&分区”,UI 的样式实际上耦合到了物料(字段)中,假设我们只想调控字体的颜色或者大小,每种样式的物料都需要单独开发。
为了满足运营同学对模块样式可配置的诉求(比如修改文字大小、颜色、背景等等),我们对智能 UI 的数据结构进行了升级,基于 DesignToken 的能力,将「样式」剥离开单独控制。整体链路如下,模块内在设置元件的可变性值时使用了一个由页面统一调控的新DesignToken 值,而该值将在页面级别下发生效。另外,当页面不需要进行 UI 统一调控时,该模块的展示仍不受影响。
- 更高效的模块研发能力
当一个智能UI模块进行前台渲染时,在工程链路上会分别请求ald数据接口,以及素材个性化tpp服务,假如我们要对主图的素材(场景图、白底图、长图)进行个性化展示,按原先的逻辑前端一方面要开发场景图、白底图、长图三种不同的组件,另一方面需要将从素材个性化服务中获取到的字段决策值,与阿拉丁的数据做校验,因为可能会存在推荐值不存在的情况,而行为埋点则直接取了素材个性化服务的埋点信息。
现在我们直接在阿拉丁侧实现了素材个性化的补全服务,在服务内部调用素材个性化tpp决策要使用的素材图片,前端直接请求阿拉丁的数据接口,不需要做额外的改造,在行为埋点时也直接取用阿拉丁返回值,使埋点信息更准确了。这样通过阿拉丁这样一个中心化的内容分发节点,智能素材可以以较低的研发成本接入多个业务场景。
- 可观测的 UI 定投实验能力
基于人群差异、品类差异对 UI 进行精细化的调控,是提升消费者体验以及对产品“独有价值”感知度的一个技术手段。我们将人群定投,品类定投的技术能力产品化到鲸幂平台,形成一个可观测的实验系统,作为鲸幂产品能力的升级。
支持以下四种投放类型:
- 变量A/B(general):单一变量的随机实验,用于不同UI策略的AB测试
- 人群定投(crowd):为指定的用户展示指定的UI策略
- 行业定投(cate):为指定的一级类目匹配指定的UI策略
- 个性化投放(algo):接入智能UI推荐算法模型,对于不同的用户,通过算法决策要展示的UI策略
产品化页面如下:
- 人群定投 - 基于人群的 UI 差异化表达
通过智能UI推荐算法可以实现对不同用户的UI个性化展现,但在新业务的探索阶段,往往需要更具解释性的技术工具,能够直接结合业务目标对用户进行分层。基于以往的实验和经验总结,UI要素在如下人群中的浏览和点击差异较为显著,是可运营的分类方法:
- 日常/大促:大促期间用户更注重浏览的效率,且会忽视掉其他内容字段的变化;日常期间用户开始关注商品内容,且对利益点、角标、牛皮癣等内容字段也比较敏感
- 女性/男性:女性的点击率显著高于男性
- 年龄:在一定程度上随着年龄增加,浏览深度降低,但点击行为也更聚集
- 用户活跃度:高、中、低活,新人
- 用户点击行为特征
智能UI通过接入奥格人群SDK实现人群投放服务,先在奥格平台进行人群圈选和投放服务化,然后在DSM平台进行UI方案的人群打标过程,在DSM进行实验创建时会自动同步一个鲸幂项目,便于后续在鲸幂平台进行方案的投放,在DSM上的基础操作流程如下,
人群和UI的绑定规则:
- 人群tag(crowd_id)和 UI方案 之间没有严格的映射要求, 可以是一对一、 一对多、或者多对一的关系,如果是一对多的关系,在投放时会给该人群随机分配一个方案;
- 由于人群是和UI方案绑定的,在同一个方案包集合中,人群tags要互斥,比如同一个user_id,不能既属于人群 1,又属于人群 2,否则在该方案包中,对于同一人群无法归类;
- 支持六种打标方案。
- 类目定投 - 基于品类的 UI 差异化表达
由于商品卡片的空间固定,所承载信息量极其有限。除去图片所占空间与必要的留白面积,卡片内留给商品描述性文本的空间很少,因此针对用户偏好呈现商品重点信息十分重要。不同行业商品的信息表达示例如下:
要实现基于类目进行UI投放,是将原先以单页面返回UI的方式改为以单商品坑返回UI。tpp服务的入参需传递多个商品 id,服务端通过数组的顺序匹配对应scene,
[{"scene":"122_4411","items":"618764511532,641571898810"}]
返回的数据示例:
{ "result": [ //场景一的数据 { "scene": "122_4411", "algoName": "RANDOM", "abType": "random", //每个 item 的数据 "items":[ { "id":"1", "key":"A^331|B^997|C^5124|D^5110|E^5125|F^988|G^980|H^2518", "trackInfo": "/jingmi.module.exp-----lyg=122_4411.lyg_jmui_183458|random|RANDOM_null.A^331|B^997|C^5124|D^5110|E^5125|F^988|G^980|H^2518.null&item_id=1&scene=122_4411&pageId=null&bucket=183458&ui=A^331|B^997|C^5124|D^5110|E^5125|F^988|G^980|H^2518&score=1.0E-6-----GET", "content": {}, }, { "id":"2", "key":"A^331|B^997|C^5124|D^5110|E^5125|F^988|G^980|H^2518", "trackInfo": "/jingmi.module.exp-----lyg=122_4411.lyg_jmui_183458|random|RANDOM_null.A^331|B^997|C^5124|D^5110|E^5125|F^988|G^980|H^2518.null&item_id=2&scene=122_4411&pageId=null&bucket=183458&ui=A^331|B^997|C^5124|D^5110|E^5125|F^988|G^980|H^2518&score=1.0E-6-----GET", "content": {} } ] } ]}
同时,在算法侧也需要将欲打分的UI方案和商品做笛卡尔积处理,由多商品请求服务带来的性能开销通过算法和工程上的优化可以控制在50ms以内,在前台渲染侧是可接受的范围。
类目和UI方案的绑定同样有一个打标的操作过程,方法跟上面的人群定投类似,不同的是不需要去奥格平台圈人。
▐ 落地使用
- 运营减负 - 页面级 UI 样式调控在小二工作台的应用
在每次大促活动中,同一个会场页面经常会遇到样式风格不统一的问题,比如不同模块之间的上下边距、左右边距不统一,不同模块的标题字号、字重不统一,价格字号、主题色不统一等等。为了帮助运营减负,以一种低成本的方式既快又好地统一调控页面的 UI 风格,我们为方舟模块工坊的生产链路提供了对UI样式可变性进行调控的能力。
上图是模块工坊的生产链路。可以看到,模块的生产角色转变成了运营,运营可以在模块编辑器中根据元件搭建出满足需求的模块,而前端开发只需按照设计师给的规范开发出相应的元件即可。
以点赞数的样式定义举例,首先,设计师会针对不同的业务场景抽象设计出对应的元件,并指定了这些元件的样式可变性范围。开发阶段我们定义了两个 Token: --dt-font-size 和 --dt-color。
.like-count-text { font-size: var(--dt-font-size, 20rpx); color: var(--dt-color, #333);}
在元件发布时,我们会对代码进行扫描,从中提取出元件中定义的所有 DesignToken,并注册到元件中心,当运营同学在模块编辑器上使用该元件时,就能对其样式可变性进行修改。
在完成模块的搭建之后,通过发布运营同学就能在方舟搭建页面上使用该模块了,而到了页面运行时,模块将根据 CSS 变量的方式使得可变样式生效。因此,对于页面级 UI 样式调控的诉求,运营只需统一配置页面级的 DesignToken 值即可,从而大大减轻了配置的工作量。
- 研发提效 - 智能补全字段在聚划算频道场的应用
在聚划算大牌折扣页面,我们应用智能UI进行商品短标题和IC商品标题的个性化投放,只需要在阿拉丁侧和鲸幂侧分别进行配置,通过字段名进行关联。阿拉丁的字段补全服务会自动调用智能素材的tpp服务,前端只需要增加模块的曝光和点击埋点,不需要研发智能模块了,应用一次减少2人日的开发工作量,由3人日下降到1人日,研发效率提升约60%。
- 人群的精细化运营 - 人群的UI差异化投放在天天特卖中的探索
天天特卖频道通过挖掘不同人群的行为特征数据,应用智能 UI 的人群定投功能,结合不同的交互和 UI 策略,在最佳前台表达方案的探索上进行了多角度尝试。可以看到通过对不同用户做精细化策略投放,提升目标初见成效,实验目前最高相对提升35.7%的目标用户转化。
▐ 智能 UI 总结
鲸幂智能UI项目通过升级智能UI协议规范,支持物料(M)、布局(L),以及更细粒度的字段(F)、风格(S) 的调控,也为基于人群和品类的UI差异化运营提供了一个可干预的技术手段,将来会在探索UI有效性表达的方向上继续深耕,同时会更多的围绕业务需求组织技术迭代和升级鲸幂产品。
展望
前端智能化各子领域百花齐放,通过最近这 2 年的阿里业务应用发现,其中前端端智能、智能UI、D2C的使用较为高频,其中前端端智能是近期业务面对流量红利消失用增乏力背景下精细化用户运营的策略,是实现感知用户实时意图的重要能力;在精细化用户运营的背景下终端的交付物(UI交互)怎么进行千人千面的有效表达进而促进转化,未来甚至是短视频、AR/VR的有效表达。D2C还是问题驱动,坚定不移提升设计稿生成视图代码的还原度和可维护性的下限,并基于之上结合C端营销导购场景,探索无代码面向非编程人员的应用,这几乎对设计稿生成代码的还原能力需要接近 100%,继续加油,当 D2C 体验鸿沟真正跨越的时候,才能带来基于此的应用方式的大革新。