智能化 DSL 转换

avatar
阿里巴巴 前端委员会智能化小组 @阿里巴巴

文/ 阿里云流量产品团队 - 虚俞

智能化技术在不断的前进,随着训练算法的不断迭代,模型的识别准确率也在稳步提升,但是以当前智能化的进程来看,识别的准确率是无法到达100%的,而且部分场景的因为在表现形式上过于接近,导致在识别是差异不大。并且识别产生的数据是一个扁平化的数组,这样的数据在下游是无法直接使用的,无论是画布引擎的渲染,还是代码的生成,都是需要有一个立体的数据,即DSL。 本文会介绍Dumbo在这方面的设计思路及实现。

背景

Dumbo 是一个利用图像识别算法,一键生成前端代码的智能开发平台。目前已经落地于多个阿里云控制台及中后台项目。


首先,Dumbo 的基本链路为通过一张图片,利用智能化技术识别图片中各种信息数据,在通过DSL引擎转化为符合约定规范的 JSON 描述(即 Schema ),再通过可视化搭建平台进行人工微调修正,最后生成 React 模块代码。

无论在可视化搭建平台,还是直接利用Schema生成React模块代码,中间都需要先把利用图像识别算法得到的数据,转换为可被搭建平台/代码生成模块所认识的Schema,这部分就是本文所需要阐述内容。

解决方案

考虑到Dumbo有开放的模型训练能力,但是模型训练及识别之后的数据及DSL转化可能在不同团队之间是独立,基础组件库也不同,前期我们做了内部的Adapter转化引擎,主要是对Fusion/Antd的一些转换,但是有很多团队会有自己的一些组件库及业务组件,这部分可以在模型训练的时候添加标注,但是我们默认的DSL是不支持这类识别的,所以需要有一个特定的模块来处理这部分数据,并能够很好的支持后续的扩展。所以把DSL转化这层独立出来,作为一个单独的项目,目标成为一个能够通过简单配置就能够实现业务自定义DSL,快速的搭建一个完善的Adapter服务。

我们在实现DSL转化引擎之前,我们需要知道输入是什么?目标及输出是什么?这是转换的前提条件,我们弄清楚输入是怎么样的一个结构,然后才能根据相应的结构对输入进行处理。 首先,看下我们的输入结构:

[    {        "name": "Message",        "props": {        },        "probability": 1,        "position": {        },        "id": "534df201-bdcb-11eb-8e5e-8fd6c9c0318c"    }]

输入结构整体是一个扁平式的,所以我们Adapter的输入就是一组识别的大数组,那输出是什么,看如下数据:

{
    "version": "1.0.0",
    "componentsMap": [
        {
            "componentName": "Page",
            "exportName": "Page",
            "package": "@alifd/fusion",
            "version": "2.19.0",
            "destructuring": true
        }
    ],
    "componentsTree": [
        {
            "componentName": "Page",
            "children": [],
            "props": {}
        }
    ]
}

是一个立体化的结构,能够被搭建平台直接使用的Sechma及其相关的依赖关系。 所以基于以上的输入/输出特性,我们定义了Adapter引擎,整体的设计如下:


实现

下面我们分别对每个模块进行展开,简要阐述下具体的实现过程。

Node 节点的预处理工作 首先预处理部分,原始Node节点是一个扁平的数据数组,但是我们最终的目标是一个结构化、立体的数据,所以我们需要对数据进行一些前置处理,这样才能在后续的流程中更准确的来判断位置,识别特性等。我们此处以Table为例子,它所需要经历的预处理Plugins如下几种:


首先我们对文字进行了处理,包括但不仅限于文字的非正常拆分、特定无效文字的过滤等。机器识别的文字可能存在无效字符、断句拆分异常的问题,这可能会影响后续位置信息的判断,所以我们在文字预处理里面,会对整体文字进行合并,通过算法把一些合并度高的文字进行合并及过滤。 并会进行一些去重相关处理,这块去重则主要是部分特定的组件,在内部是不存在children,所以需要我们根据特定的场景,来去除该部分的一些无效文案,比如说一些Icon Button被文字识别成的特殊或者数字字符。这就需要有去重着一步来完成。 接下来是关系处理,我们会通过节点深度,来处理节点与节点间的关系,子节点是否包含子节点等,通过位置、重叠度、相似度算法,来初步处理子节点与父节点之间的关系,得到一个立体型的数据。

Adapter处理 Adapter处理就涉及到了每个组件的特性处理及细分内部具体属性信息,大致内部会做以下几种操作,功能因组件复杂程度来决定。 我们还是以Table为例子


首先我们会在子节点中找到Column Title相关的节点数据,并会对Column Title进行重组,变成Table.Column节点,作为Table的每一列,并会提取相关的子Text节点内部的英文文案作为Key值来进行后续的数据匹配。Table.Column查找会依据第一个行高度及整体识别的宽度信息,等综合进行判断,判断出Table.Column的存在,并封装为一个单独的节点数据。接下来表格存在多种属性,以我们集团的Fusion组件为例子,Table包含了一系列排序,筛选,选择字段。这部分需要通过对Icon的分析,来确定Table是否包含此类属性。我们也会处理表格内数据,生成一份识别类型的dataSource,供下游进行数据渲染,这里也会做一些我们项目中平时对于Table的基础属性的补全工作。

Node 节点的后处理 前面基本已经把一些节点的特殊属性,节点的缺失的一些属性做了补全,接下就是对组件库的适配,及最后依赖提取等,以Table为例,我们的流程节点包含如下:


在执行的时候我们会确定需要输出时依赖的底层组件库,会从相应库中找到对应字段,部分属性需要根据组件库进行转换,把内部的一些属性名称转为对应的组件库的属性。我们会维护一张大的组件Map表,会标注组件所支持的属性,及对应的标识符,以此来确定最终Sechma所需要的属性。最后是依赖的提取,也是根据用户所选择的基础组件库,获取到用户所用到的组件信息,自动生成符合集团规范的DSL依赖描述。 还有就是最终DSL的整体格式,也是通过这部分后处理来实现的,之后用户的自定义DSL也会在这里做实现,达到用户能够自定义输出DSL的能力。

细节

DSL转化我们做了很多次的优化,中间我们持续发现了一些bad case,内部会有很多处理这部分的逻辑,没办法以一种统一的方式来处理。

Button处理 我们在Button最开始的处理的时候,最开始的时候我们按照设计规范来定义Button内部的children,一般内部有Icon的则表示是一个Icon Button,有文字的则表示普通的Button,但是我们在具体实现的时候,发现Icon的是识别可能会把"刂"错识别成为排序的Icon,因为比较接近。这块导致Button从普通的变成了Icon Button,这种现象显然是我们没有预料到的。所以我们进行细化处理,区分children长度及特殊字符串、位置信息来进行预判Button是否是Icon Button,最终达到转换效果和设计稿一致的目标。

详情列表的label位置判断 详情列表在我们组件中存在垂直、水平2种label的呈现方式,因为该模型的特殊性相对于不是很明显,所以在模型识别之后整体呈现的效果并不佳,部分Item并没有准确的识别到, 这时我们就需要在已有识别的Item基础上,再根据位置信息来判断未被识别的Item是否存在,label的位置是如何的?我们这边进行了系列处理,来尽最大程度的实现label位置的查找。 1、这边会分2个分支处理,第一分支按行进行分组,判断行内是否有Item,如果有,则根据Item的label位置进行未识别位置判断,并且记录Item的个数。以位置基础为基准,根据左右/上下节点来判断出label。 2、继续处理其他行的数据,一般我们的交互规范不会出现垂直、水平2种都出现的情况。所以我们以多数Item的label位置作为所有的label位置,再2次进行查找未包含Item的行,最终达到优化识别的效果。

还有其他细节就不一一举例,当然这也是很小的点,后续有很多算法需要优化。

展望

以上我们介绍了现有我们DSL引擎支持的能力和解决方案的实现,后续我们会持续优化我们的DSL引擎,会根据我们的场景及组件特征,对一套组件的特性进行多算法的处理,结算处整体的有效性。在今年也会计划把整个DSL作为智能识别的一环服务,对我们集团内部做一些自定化的功能,接入方可以有效的复用我们的特性算法,也可以自定义组件特性算法,后续考虑把这个作为一个智能化DSL转化市场来做,甚至让用户在可视化的界面内就能够自由组合对应Plugin和Adapter,实现在线自定义DSL的场景。当然目前我们的项目还在高速迭代中,DSL引擎也有很多考虑不周的地方,有较多优化的空间,也有很多想法待实现,欢迎有想法的同学加入我们,可联系yaoli.pt@alibaba-inc.com,期待你与我们一路通行,一路探索。



淘系前端-F-x-Team 开通微博 啦!(微博登录后可见)
除文章外还有更多的团队内容等你解锁🔓