如何实现代码自动生成?

简介: 每年大促前一个月都是奋战与忙碌的时节,不仅业务上在不断迭代创新,技术上也在推陈出新,需求推动技术变革是一个正向演进的过程,但革新是需要成本的,每一次技术与标准的革新都带来一场翻天覆地的大改造。如果我们能将需求与产物划上等号:需求即代码,那么我们只要找到两者之间的关联关系即可通过需求自动产出代码了,那岂不是乐哉美哉(diao zha tian le)。本文主要围绕自动化生成代码的目标,讲述我们在这一过程中的所思所想,以及我们在618期间的阶段成果实践。

滚动.gif

每年大促前一个月都是奋战与忙碌的时节,不仅业务上在不断迭代创新,技术上也在推陈出新,需求推动技术变革是一个正向演进的过程,但革新是需要成本的,每一次技术与标准的革新都带来一场翻天覆地的大改造。如果我们能将需求与产物划上等号:需求即代码,那么我们只要找到两者之间的关联关系即可通过需求自动产出代码了,那岂不是乐哉美哉(diao zha tian le)。

本文主要围绕自动化生成代码的目标,讲述我们在这一过程中的所思所想,以及我们在618期间的阶段成果实践。

前言

自然语言是及其抽象且强依赖上下文的,其整体表现为不精准,而代码是多维具象且有强相关性的,其整体要求为精准。这样两个不同概念的东西怎么找到他们之间的相关性呢?

需求和代码之间没有一个标准的转换模式,通过标准转换器来实现是不可能的,唯一可以采用的方案就是运用机器学习,并通过大量的样本来增强之间的关联性。但正如前面所提到的,代码和需求都不是对局部的简单理解就能完成的,而是对一个整体的理解,因此对每一句话的理解都不能是独立存在的,而是相互交织在一起的,这就增高了对整个需要理解的纬度,据鄙人所了解这个难度是非常大的。

但有时一个问题的难度大小也是由当下技术边界所决定的,比如3D打印的出现,就彻底将需求和产出物划上了等号,过去很多繁琐的工序都可以舍弃了,只需要一种实现方式就能让人们在家就可以下载设计稿并自己完成产品的实现。

当然3D打印的出现并不能解决代码自动生成的问题,3D打印只是在生产过程中运用了统一化的解决思路,而从需求到产出的过程依旧需要依靠设计图来对产出物的各项尺标数据做约束。所以设计稿的标准化一定是统一化的前提,3D打印更像是一个标准化出码的机器,而指挥这台机器如何生产的正式标准化下的设计稿,因此对我们来说需要思考两个问题:

1、自然表达的需求如何转变为标准化的“设计语言”

2、如何通过标准化的设计语言产出代码

我把第二个问题看作和3D打印一样,是一个标准化的问题,而有了标准化的设计语言再转到AST是很简单的事情,困难的是第一个问题,如何将需求转为标准化的设计语言。这是我们需要核心思考的问题,并且这个课题对于运用机器学习来解决也同样是非常困难的,那我们首先是否应该来了解一下目前机器学习的边界呢,并怎样拆分成具体目标去实现它。

聊聊AI

当我最早了解人工智能的时候是这部著名的《AI》。

image.png

电影中的小男孩大卫是个机器人,但是他被赋予了情感,他历经万险,为了一个注定幻灭的结局。"等我变成了真的小男孩,妈妈就会带我回家了"

“当人工智能开始寻求自我认同时,他就已经和人类没有区别了”。如果这个世界是虚拟的,造物主一定不会让我们发现丝毫,这也是当时这部电影令人感同身受最恸哭内心的部分。这也正验证了人与机器的本质区别,即是否能感受自我的存在。

回到当下,现实的AI 并不像电影里的那样,既没有情感也没有逻辑,更没有自我意识。比如知名的AI AlphaGo,从技术上讲,它之所以能够击败人类的围棋高手,是因为它具有由“小”变“大”的能力,人类将十几万的围棋博弈输入到它的“大脑”中,然后它就会进行自我“对战”,进而产生几百万甚至几千万的围棋博弈或者叫做棋谱,所以它在应付人类的围棋博弈时,就能够“从容不迫”。但他产生的模型的过程不能举一反三,当改变棋盘的尺度或改变规则时AI就再无法做出有效应对了,它必须得进行重新的学习,而人类只需要通过理解规则即可做出应对改变。

与AI 相比,人类似乎能够解释和理解其所生活的环境,而计算机只是一台从事匹配工作的机器。哲学家约翰·塞尔(John Searle)很久以前就通过他的“中文房间”思维实验(Chinese Room thought experiment)指出了这种差异。在本实验中,他将自己关在密闭的房间中。

这个实验是这样设计的:Searle 他既不会说也听不懂中文,但是在这个房间里有一本很大的手册,里面有一系列的假设陈述。通过门上的一个插槽,他可以接收汉字,查找手册中的字符串,并找到要通过插槽送出的字符串。显然,塞尔可能会让房间外的人相信他真的懂中文,但事实上他并不懂,他只是在匹配符号而已。

image.png

虽然从外部无法区分房内的人到底是否“懂得”中文,但是实质上房内的人是不懂中文的。因此以“是否无法区分‘懂得中文’和‘表现得完全像懂得中文’这两个现象”而将其两者认为是等同的,这个观点是不能够成立的。

AI 并不神奇,它预测的基础甚至和《易经》和 中医理论 都没有太大区别,如果要有,我觉得差在了灵魂和哲学的思考上。而对我们来说AI 是否真的能产生情感还是是否能真正能够理解处理信息,对我们来说都不是重要的,我们只需要他看起来可以做到准确预测即可,并不需要一个真正的人工智能。

用传统机器学习进行建模预测,其本质更接近于搜索,这是一个看起来会比较傻的弱人工智能,并且所有的预置算法都是由人类来写的,AI 只是一个按算法规则来进行分类/聚类的机器 ,比如对单个图形或句子进行预测,这些数据都是相对结构化的数据,而对于整篇文章或全幅大图做分析则需要强人工智能来完成,一般我们会用到深度学习,并需要使用多层处理单元的巨大神经网络利用强大计算能力和改进的训练技术来学习大量数据中的复杂模式。原理是计算机在学习特定问题时,需要大量输入这个问题相关的学习材料也就是数据,然后在计算机通过算法和模型来构建对这个具体问题的认知,也就是总结出一个规律,那么在以后遇到相似问题时,计算机会把收集的数据转成特征值,如果这个特征值符合这前面规律里面的特征值,那么这个事物、行为或者模式,就可以被识别出来。

背景

聊完AI,我们回归正题,说一下什么是P2C以及为什么要做P2C?

P2C即通过 prd 自动产出 code,即是我们开头所讲的需求即代码的终极目标。

image.png

讲完P2C是啥,我们再回过头来聊聊我们为什么要做P2C?

在开发链路中耗时较长的两个环节是「沟通成本」和「编码成本」,「沟通」一般是需求明确的过程,一般体现在各种需求评审上。而前端的「开发」成本则主要可看作两个部分:视图代码与逻辑代码两个部分的开发工作。目前我们团队的 D2C产品(imgcook 设计稿到代码) 已经能够帮我们准确的生成大部分的视觉代码了,甚至还可以分析出部分简单的的业务代码,因此对前端开发来说在开发中的成本主要花在非通用的逻辑表达部分,即粘合剂。

对于这些“粘合剂”逻辑,在产品的prd 中我们可以找到准确答案,但有时产品的prd 是不够结构化的,信息丢失也比较严重,这非常不利于机器学习进行学习和理解。因此我们需要一个平台来规范产品的需求,使产品能够按照要求进行结构化的录入。这就是我们做P2C 的初衷。、

挑战

前面我们对AI 的能力已经有所知之了,而现在我们要怎样一步步达成我们的终极目的 “Auto Code”呢?

我们知道AI 目前还不能够像人类一样来分析数据关系,而大部分prd 都是以文本为主的非结构化信息,这时候我们就需要利用 NLP技术对信息进行处理并根据意图翻译为可进行转化的逻辑描述DSL,因此我们通过相对具有结构化文档的方式来进行需求的收集,从而简化机器学习的难度。

虽然我们可以将原本海量信息的大文档进行结构化的信息表达,使局部信息清晰可解,但此降维操作也产生了新问题,就是关键点与关键点之间的联系变得更弱了。

我们的初衷是希望能降低需求沟通成本,并在此过程中积累智能化出码的能力,所以我们只是设计了简单的结构化收集方式,并不强制改变pd原有的需求录入方式,因此需求文档内容有着很高的不确定性,不仅存在上下文关系依赖,还有很多未描述的知识依赖,并且内容也都是允许其自由组合天马行空。

知乎有一篇买苹果的例子,很好的诠释了一个简单的需求背后所牵涉的复杂的关联关系。因此可见单纯的通过需求来推导出产出物是非常难的工作。既然如此为什么不直接走向另一个极端:严格的结构化需求录入呢?虽然严格的结构化信息录入可以帮助更清晰的将一个开域问题收拢回一个闭域问题,但是会让需求产生的过程变得更困难更具专业化,这和我们服务pd 更好的进行需求录入的初衷是相违背的,另外我们也不希望通过标准化的方式去限制业务的创新。

因此如何既能让 pd 录入需求的工作变得简单,又用能借此发展我们的“Auto Code”事业,是我们最大的一个难题。另外对于整个出码目标的技术链路我觉得目前也存在两个难点:

1、获取大量自然语言意图分析的训练样本:对于pd的同一个需求可以用一千个不同的句子来表达,同样一个需求表达也可以对应一千种实现方式。要想将自然语言的需求描述同实际产品表达进行准确关联需要对大量的样本数据进行学些

2、将所有自然语言逻辑使用统一的DSL描述:如开篇提到的3d打印,统一化的设计稿是实现转换的基石,因此一套描述需求的标准化DSL是必不可少的。

推导

既要让pd 录入需求时能录入的舒服,又得要求能按需出码,似乎两者是矛盾的,但是困难也都不可能是一朝就能解决掉的。

所以我们打算分步骤实现目标,首先我认为短时间对需求的结构化信息分析还很难达到从局部到整体的突破,文本的灵活性也会带来诸多问题,比如模块信息的增删改造成的信息错位,因此我们觉得第一步要从以P2C为核心出码的逻辑变为以D2C(即Design2Code - imgcook),因为视觉是产出是最终产出物比较接近终态的一个阶段,通过视觉我们将会更容易分析缺失部分的内容,然后结合P2C内容从中寻找补全的关键信息,比如一个视图是否是ScrollView 单从视觉上很难辨认,需要结合从prd 中获取的信息,甚至prd 中没有详细描述时还需要跟俊产品属性进行分析,例如这是一个音乐播放器的界面,那么其中应该包含什么功能组成,哪些功能组成一定会是ScrollView,这就需要一些知识依赖的输入,而这些宝贵数据资产都是需要脚踏实地不断积累的。

我觉的D2C和P2C的结合一定是1+1>2的,对于D2C视觉出码有了知识依赖做背景,对于视觉稿的整体判断及组成可以有了很好的依据,另外P2C也能够基于准确的视觉做精准的逻辑补充。因此以视觉稿为主导出码,以prd为辅助出码的思想浮出水面。

即我们第一阶段重修了目标:将原本的 AutoCode 目标先降低为 NoCode = 通用逻辑组件 + ProCode(AI)目标。

这个过程通俗来讲就是 通用组件 + 配置信息 的模式,配置信息即 ProCode 的部分,该部分即为需要 AI 自动产出的内容。因此想要完成自动出码,就需要对 ProCode 的部分进行样本制造和监督学习。

我们来总结一下我们的三步走计划:
1、需求的结构化收集 (为了降低NLP的分析难度)
2、创造结构化需求到标准逻辑表达的样本(为机器学习ProCode部分提供充足样本)
3、通过机器学习对样本进行学习,以达到AutoCode的目标(长期目标)

即我们需建立要两个平台,我们称之为P2C 的 2.0 代 和 1.0 代。P2C 1.0 负责打标需求数据,并为 2.0的智能出码提供庞大准确的数据。而 P2C 2.0则主要进行需求的结构化收集并与1.0 的样本进行关联学习,训练出码模型,最终达到创作和自动完成需求的目的。

两个平台所代表的关键词分别是:

  • P2C1.0:精确收集,精确产出
  • P2C2.0: 开放收集,创新产出

那么精确收集样本就成为我们 P2C 1.0 的主要工作方向。

打标样本一定要从实践出发,并能在该阶段帮助需求真实的进行产出,即我们提供的打标平台能真实的完成业务需求,因此我们决定开发一个可视化编排的平台,通过该平台来收集样本数据,并且可以顺手把需求也消化掉。

那么问题来了,这么多的样本打标的工作到底由谁来完成呢?

我们通过调研发现运营的角色在可视化编排方向上,是有着非常高契合度的。为什么呢?其一,运营都具备模块搭建的能力。其二,很多运营的需求都不一定有机会能够落地,主要原因是开发资源不足导致的,这也是多年来存在的业务与技术矛盾,前端这十年来一直朝着工程化、规范化、模块化的方向发展,本意是为了更有效的重用业务能力以达到解放生产力,而产品却一直在朝着丰富化、精细化的方式来运作,各个业务方不再是单单为了满足功能诉求而更讲求的是用户心智。最终致使现在对一个个性化需求的提出往往是用一个标准化方案来落地的。当业务方为资源不足妥协时,其业务整体感官也会越来越平庸化、趋同化,最终导致产品对用户的心智弱化。

image.png

因此对于运营的诉求是希望能将创新和业务思考带入到自己的产品中,而不是简单的拆解为一个个的标准实现。如何拉大与竞争对手的运营差异、交互差异、创新差异、视觉差异才是对于运营真正的核心价值。

在AI 的介绍篇中我们讲了对于复杂的逻辑关系我们依然可以采用抽象的组件化来实现,而这部分实现对比传统搭建体系的组件颗粒度更细,传统搭建一般是对模块的自定义配置,而在我们的编排体系里最小的组件应该是原子化的不可再被拆解的,比如一个Image 组件,而对组件的配置可以是一段编排好的逻辑实现,因此它能有着同代码一样的绝对灵活性。

拆解

在前面3D打印的内容中我们提到,自动化统一化生产的前提一定是要有一个标准化的表达做支撑的,这个中间 DSL该如何设计才能承载住全量的需求内容呢?另外通过什么样的方式可以让运营能接受和理解这部分的逻辑编排?

1、首先我们解决的问题一定是有边界的是处在一个业务领域的,并在这个业务域下进行分析。因此我们分析了一下我们最常见的业务形态-模块。而据统计“相同业务能力,不同技术实现”的模块在整个天马体系中的占比非常的高,单单拿通用商品坑来看就有上千个,而这些模块大部分都是相同的逻辑实现,也有很多是处于不同时期的技术产品。

2、一个模块在前端的开发设计里,大概可以分为4部分,通用组件,通用Action,视觉代码,驱动逻辑。

3、我们可以看到视觉和通用组件以及Action都是已经有了的,变动周期比较低。而驱动逻辑部分是是业务中的主要实现逻辑,如何让这部分逻辑能让运营进行产出呢?

4、首先我们将这部分能力进行一个拆解,我们得出一个初步的结构,就是由 运算符 + 表达式 + 基础action + pipeline 组成的表达结构,这个表达也可以组成一个新的action,再加上trigger,整体就完成一个workflow的能力了。

image.png

new Expression = Variable + Operator + Expression + Pipeline
new Action = Expression + Action
Workflow = Action + Expression + Trigger

业务模块的四个部分中,驱动逻辑就是我们主要核心产出的内容,根据我们的经验这部分ProCode 大部分都是表达式 Expression 内容。因此我们只要能让运营能够自主的完成 ProCode 部分的编排即可高级定制需求的产出物。

让运营完成所有的ProCode 也显然是不现实的,但是对于IFTTT 这种简单的逻辑表达,只要将这部分内容的表达可以使用更接近自然语言的表达方式,自然会降低整个的理解难度。

验证

为了验证我们的拆解过程,我们把pmod 分组下的9千多个仓库进行一个拆解分析,发现平均每个模块都有逻辑表达 52.6 个,函数表达 37.55 个, if 语句 35.5 个,这三大部分实现是符合我们的拆解预期的。这部分的逻辑大部分都是可以用IFTTT 的模型套用。

image.png

而一个复杂的模块,光有IFTTT 是不够的,逻辑的表达是具有很强的依赖上下文结构的,但是为了降低整体的复杂度,我们需要对逻辑进行拍平表述,对拍平后的逻辑我设计了一套 StateLink的工作流管理库,这里就不详细介绍了。

最后我们通过一个 When + Then + Trigger 三元素的DSL就能描述我们所有的业务逻辑部分了。这个DSL也为我们2.0 版的出码提前做好了准备,同时也能应对因技术升级而导致模块需要重新开发的尴尬。

image.png

为了让运营能够用得懂用的轻松,我们采取了中文编排的方式,即首先根据选取的视觉对象进行一些具象的操作表达。

为什么我们决定采用中文编排呢?中文编排是怎样一个编排方案呢?

image.png

我们将pd需求的一句可以拆分为上图这样的表达,对于使用者只需要顺着决策树表达自己的意图即可,类似于输入法,当我们输入一句话的时候,输入法通过预测词可以表达所有的表达意图,比如输入“我”,那么一定能够枚举“我们”、“我的”、“我..”等词并可以一直预测下去,而每个词的预测都是一个有限的枚举,同样pd在描述一个需求时我们也可以根据语法和目的预测出所有的可能项。

现状

我们将常用的逻辑表达拆解为中文关键词,通过关键词关系可以让运营通过编排一句话的形式来表达事物的逻辑关系。

我们目前已初步完成了第一个版本的运营逻辑编排平台,通过该平台可以先让运营能够进来满足一些简单的需求。

image.png

运营主要通过可视化的方式对元素上的逻辑进行中文关键词表达的编排

image.png

案例

“爆款来了”会场中的6个模块,由运营自行编排发布上线。

image.png

未来

虽然人工智能目前还有很多的不足和局限性,但随着深度学习的不断进化,我相信从需求理解到需求实现全过程的自动化会离我们越来越近。

image.png

我相信未来不仅可以实现从需求到代码的智能生产,也将会从智能生产覆盖到智能视觉、智能测试、智能运营的全链路智能场景。

就像我们的大厨,一开始是需要人工切菜人工炒菜,后来是人工按菜谱备料再由机器辅助炒菜,再然后是直接输入菜谱机器就能自动根据菜谱备料和炒菜,而未来只要描述想吃什么口味就能自动做出符合用户的菜。

P2C的未来就是将过程描述简化为目标描述,一个需求只需要表达诉求和目标而不再需要描述详细的生产过程及规则,只需简单的几句话我们就能够知道用户想要什么该产生什么样的交付物了,这就是我们未来的“智能大厨”。

频道与D2C智能 F(x) 团队


我们是阿里巴巴-淘系技术部-频道与D2C智能 F(x) 团队,致力于前端智能化领域的探索和实践,赋能淘宝、天猫、聚划算等日常与大促(如双 11 )业务,是淘系前端智能化实践的领路人,也是阿里经济体前端委员会智能化方向的核心团队。目前团队有较多高校和海外背景的技术小二,专业领域涉及前端、算法、全栈等。我们在 D2C(Design to Code) 领域开放了 Imgcook平台,在逐步释放阿里生态的前端生产力;我们也与 Google 的 tensorflow 团队保持长线合作,基于 tfjs-node 之上,开源了我们的前端算法工程框架 Pipcook,在引领前端行业向智能化时代迈进。

既然最后打算放个招聘贴,那么对于你一定想知道的是关于老板的故事,那么我就简单放上一些和老板相关的近期活动吧:

1、第十三届D2前端技术论坛

  • 时间:2019年1月
  • 事件:第十三届D2前端技术论坛举办

描述:正式开放 imgcook.com 向社区介绍阿里经济体前端委员会智能化方向。

2、QCon 10年前端技术分享

  • 时间:2019年5月
  • 事件:QCon 10年前端技术分享

描述:第一次公布 imgcook.com 背后的工程技术体系,通过实践过程详细揭示一路上的坎坷、挫折和我们的坚持与应对,并第一次公布 Pipcook 将开源的计划。

3、在美国硅谷山景城 Building 41 Tensorflow总部完成合作谈判

  • 时间:2019年8月
  • 事件:在美国硅谷山景城 Building 41 Tensorflow总部完成合作谈判

描述:向Google 的Tensorflow.js 团队介绍 D2C 的研究和实践成果,得到Tensorflow.js团队的一致好评,后Tensorflow.js团队亲赴西溪园区交流,双方在推动前端智能化方向上达成战略合作。
团队照片(第一张是我们帅气的老板)
image.png
image.png

最后,如果你对智能出码有兴趣并想成为我们的同路人请投递简历到
📮:nanji.ly@alibaba-inc.com

关注「淘系技术」微信公众号,一个有温度有内容的技术社区~

image.png

相关文章
|
6月前
|
前端开发 Java
前端基础 - 常用调试方式
前端基础 - 常用调试方式
36 0
|
1月前
|
C# Python
如何让 StyleCop 忽略 refit 自动生成的代码
创建自定义规则:我们需要创建一个自定义规则,该规则将用于排除特定类型的代码,我们可以创建一个自定义规则,用于检查类名是否以大写字母开头,然后忽略符合此规则的代码。
|
2月前
|
C++
win32编程 -- 通过空项目学习自动生成的代码框架
win32编程 -- 通过空项目学习自动生成的代码框架
12 0
|
7月前
|
小程序 API 开发者
【小程序全面解析】生命周期、常用组件,代码示例和使用场景
该文章全面介绍了小程序的生命周期、常用基础组件以及使用场景,并提供了相应的代码示例。读者可以了解小程序的生命周期函数及其执行时机,以及学习如何使用常用基础组件构建小程序页面。此外,文章还列举了各种使用场景,帮助读者更好地理解如何应用小程序开发。如果您是小程序开发的初学者或需要了解小程序的基础知识,该文章将为您提供全面的帮助和指导。
137 0
【小程序全面解析】生命周期、常用组件,代码示例和使用场景
|
3月前
关于调试的应用场景及如何编写优秀代码
关于调试的应用场景及如何编写优秀代码
24 0
|
架构师 开发者
项目开发助手|1分钟自动生成项目基础结构 + 重复代码
给大家推荐一个:一键生成表实体(包括controller,service,mapper等),以及一键生成项目基础架构的开源项目
281 0
项目开发助手|1分钟自动生成项目基础结构 + 重复代码
|
Java 开发工具 C#
如何以超快的方式调试?
如何以超快的方式调试?
|
SQL Java 数据库连接
AOSuite自动生成持久层代码
AOSuite自动生成持久层代码
77 0
|
iOS开发 Perl
SwiftGen 自动生成资源代码
SwiftGen 自动生成资源代码
572 0
SwiftGen 自动生成资源代码
|
JSON JavaScript 前端开发
接口测试平台代码实现46:接口调试用户异常操作处理
经过45节的学习,很多同学已经达到了一个不错的水准,可以自主找到一些问题并修复和提出改进方法,我很欣慰。 本节我们要处理的是用户异常操作引起的情况。 大部分处理我们最好都在前端上拦截,这样的好处是不通过请求 就可以瞬间提示错误,所以我们基本只打开P_apis.html就可以了。
接口测试平台代码实现46:接口调试用户异常操作处理