淘寶天貓業務產品不少,每一年還會有不少大促活動,產品頁面心智不一樣致使 UI 視覺多樣、業務性質不一樣致使業務邏輯不一樣,大量的 UI 難以複用,須要投入大量的前端人力來開發,前端同窗的業務壓力很是大。爲了解決這種困境,咱們研發了自動生成代碼平臺 imgcook,幫助提高前端研發效率。 前端
在 imgcook 中咱們逐步引入了 CV、NLP 等 AI 技術來輔助識別設計稿信息智能生成可讀性和可維護性較高的代碼,並在雙 11 大促中自動生成了 79.34% 的前端代碼,助力前端研發效率提高 68%。智能生成代碼平臺 imgcook.com 在 2019 年已經正式對外開放,服務於 25000+ 用戶。 python
本次分享將爲你們介紹設計稿生成代碼平臺 imgcook 的核心思想以及AI技術在 imgcook 中的應用場景和落地實踐。 算法
分享的內容主要是咱們用機器學習技術能夠解決哪些設計稿生成代碼的問題,以及怎麼用機器學習技術來解決這些問題。指望能站在前端的視角下,講清楚用機器學習解決代碼生成問題的整個實踐過程。npm
imgcook 是一個設計稿智能生成代碼平臺,能夠將 Sketch、PSD、Figma、圖片等類型的設計稿一鍵生成可維護的前端代碼,例如 React、Vue、小程序等。 json
imgcook 到目前爲止已經經歷了3個階段,在 2019 年 1 月咱們正式對外開放了 imgcook 1.0 版本,後來通過 1 年多的發展,也就是 2.0 階段,逐步引入了計算機視覺、機器學習技術來幫助咱們解決設計稿生成代碼中遇到的一些的問題,產品鏈路也已經基本完善。到了 3.0 階段機器學習技術在 imgcook 中已經落地應用於多個場景了。小程序
在這些去年雙11活動頁面的模塊中,有 90.4% 的新增模塊使用了 imgcook 3.0 來生成代碼,生成代碼的可用率達 79%,幫助前端編碼效率提高了 68%。 瀏覽器
那 imgcook 是怎麼生成代碼的呢? markdown
咱們能夠從設計稿文件中提取到描述這個設計稿文件的 JSON Schema,若是你們手上有 Sketch 文件的話,能夠用 unzip 命令解壓這個 Sketch 文件,就能看到這個JSON Schema。 前端工程師
拿到這個 JSON Schema 以後呢,咱們可使用設計稿協議、程序算法和模型算法來計算、分析和識別,將這個JSON Schema 轉換成一個具備合理的嵌套佈局結構和代碼語義的 D2C JSON Schema。 框架
若是你們用過 imgcook 的話,能夠在 imgcook 編輯器中看到這個 D2C schema,而後咱們再經過各類不一樣的DSL 轉換函數將 D2C Schema 轉換成不一樣類型前端代碼,好比 React、Vue 等等
(imgcook 3.0 技術原理)
這是 imgcook 生成代碼的一個大體流程,其中程序算法是指經過有限的規則計算來自動的識別設計稿,例如咱們能夠根據每一個圖層的座標、寬高等信息來計算出它是否是一個循環結構,能夠根居字體的大小和字數來判斷這個文本是個標題仍是提示信息。
可是這種判斷的規則是有限的,沒辦法去解決千千萬萬的設計稿中的問題,而經過機器學習模型來智能識別可以解決一部分程序算法沒法覆蓋的問題,對於程序算法和模型算法目前都還不能解決的問題,咱們也提供了人工標記設計稿圖層的方式來解決。
那用機器學習模型來識別設計稿能解決哪些問題呢?在介紹機器學習能解決哪些代碼生成的問題以前,咱們先了解下機器學習能作什麼,它能解決哪些類型的問題。
咱們今天分享的主題是 AI 在 imgcook 中的應用實踐,AI 就是是人工智能的縮寫,人工智能能夠爲機器提供適應能力和推理能力,讓機器代替人來思考和工做,能夠幫助咱們下降人力成本。
而機器學習是實現人工智能的一種技術,能夠給機器學習的算法輸入大量的樣本,算法學習到這些樣本特徵以後,能夠去預測類似樣本有什麼特徵。
機器學習的過程與人類學習的過程是很類似的,通過學習總結獲得知識和經驗,當有相似的任務時能夠根據已有的經驗作出決定或行動。
有一點區別是人類的大腦只須要很是少的一些資料就能夠概括總結出適用性很是強的知識或者經驗,例如咱們只要見過幾只貓或幾隻狗就能正確的分辨出貓和狗,但對於機器來講它須要大量的學習資料。
深度學習是機器學習的分支,深度學習與傳統機器學習算法的主要不一樣在於對特徵處理的方式。這裏就不細講了。在 imgcook 中用到的多數是深度學習算法,也有傳統的機器學習算法,後面咱們在講的時候就統一叫機器學習算法了。
瞭解了這些概念以後,咱們再看下機器學習可以解決的什麼類型的問題。這裏列舉了在計算機視覺領域處理圖像的 4 大基本任務,和 NLP 領域處理文字的 4 大基本任務。
對於圖像的識別,給定一張圖像,若是隻是想識別這個物體是什麼,就是一個圖像分類任務,若是是要識別圖像中的目標物體,還要知道這個物體的位置,就是一個目標檢測的任務,對圖像更細粒度的識別還有語義分割、實體分割。
文本識別也是同樣的,好比這裏的知乎問題,若是想要之別這段文本是一個問題標題仍是問題描述,這是一個文本分類的問題,還有像從一段文本中識別出哪些是地名哪些是人名的序列標註任務、智能客服問答類的這種句子關係判斷的任務,還有像機器翻譯這種文本生成式任務。
那在 imgcook 中對頁面中 UI 信息的識別問題,通常都會定義成圖像分類、目標檢測和文本分類任務。
設計稿中是有不少不一樣維度的 UI 信息的,好比這份設計稿中有這些圖標,咱們能夠訓練一個圖標識別模型來識別頁面中有哪些圖標,好比這裏的頁面返回圖標、三個 … 表示更多的圖標
頁面中還有圖片,能夠經過圖片識別來獲取圖片的語義,還有文本識別、組件識別、模塊識別等等,這些均可以經過訓練一個機器學習模型來識別
那這些識別的結果能夠用來作什麼呢?你們能夠想一下,咱們手寫代碼時會寫什麼?
這些模型識別的結果能夠用於給類名一個易於理解的名稱、或者自動生成字段綁定代碼,若是識別到是一個按鈕組件,能夠生成無障礙屬性代碼,或者在生成代碼時自動引入外部組件,若是識別出是一個模塊,能夠生成模塊化代碼等等。
要用機器學習模型來識別這些UI信息並應用到代碼生成的鏈路,具體要怎麼作呢?
通常用機器學習解決問題的步驟都是這樣的。
先要肯定咱們要解決的業務問題是什麼,而後要肯定這個問題適不適合使用機器學習來解決,並非全部的問題都適合使用機器學習來解決的,好比若是用程序算法就能夠解決 90% 以上的問題,而且準確度很高,那就不必使用機器學習。
若是肯定了使用機器學習,咱們還要肯定這個問題是屬於什麼類型的機器學習任務,好比是一個圖像分類的任務仍是目標檢測的任務,肯定了任務類型以後,再開始準備樣本,由於不一樣的任務類型,模型訓練的數據集要求是不同的。
訓練數據準備好以後,還要再肯定用哪種機器學習算法,訓練數據有了、算法也肯定了,就能夠給算法輸入大量的訓練數據來學習樣本特徵,也就是訓練模型,獲得模型以後,再部署模型服務,最後在工程項目中調用模型服務來識別UI信息。
這就是我今天要重點要分享的,用機器學習來解決業務問題實踐過程。
這裏我不會去講怎麼去寫機器學習算法、也不會詳細的去講機器學習算法的原理,還有訓練模型時調參怎麼調這些。我是一個前端工程師哈,我比較關注的是怎麼用機器學習技術解決個人問題,我要給你們分享的也是這個用機器學習技術解決代碼生成問題的實踐過程,以及實踐過程當中的一些經驗。
這裏以代碼生成過程當中須要解決引入外部組件的問題爲例來詳細的介紹一下機器學習實踐落地的過程。
好比這樣一個頁面,裏面有 input 輸入框、button 按鈕,如今想要用 Ant Design 組件來實現,若是人工手寫,須要先引入 and design 組件庫,並使用 Antd 中的 Input 組件和 Button 組件。
那如今要自動生成的話,咱們從設計稿中提取到的都是矩形框、文本、圖片這些信息,並不知道哪些是組件,因此須要識別出頁面中的組件並替換成引入的 Antd 組件。
因此要作兩件事,組件識別和代碼表達。
咱們如今要識別出這個頁面中有哪些組件,若是機器學習模型的輸入是這一張頁面,模型須要識別出頁面中有哪些組件,組件位置的位置在哪裏,是什麼類別的組件,那這在機器學習中就是一個目標檢測的任務。
但咱們是能夠獲得這張頁面的 D2C JSON 描述信息的,每一個節點的位置信息都是知道的,好比這個按鈕的根節點,在D2C JSON描述中有這樣一個描述位置尺寸的 rect 屬性,那既然每一個節點的位置都是知道的,我只須要知道這個節點他是否是組件,是什麼類型的組件就能夠了。
那這個在機器學習中,就是一個圖像分類的任務,咱們給模型輸入這些節點的截圖,模型識別後告訴我這是什麼類型的組件就行了。
肯定了是一個圖像分類任務以後,就能夠準備模型訓練的樣本了。樣本數據的準備是整個階段最費時費力的事情,即須要收集大量的樣本,還須要給樣本標註類型。
由於咱們讓機器學習算法學習樣本特徵時,除了要給算法一張樣本的圖片,還須要告訴算法,這張圖片是什麼,這樣算法就能學習到,哦,這種類型的樣本都具備這些特徵,下次再有類似特徵的樣本,模型就能識別這個類似的樣本是什麼類型了。
在收集樣本以前,須要肯定模型須要識別哪些類別的組件,若是你給算法學習的樣本只有 button、searchbar、stepper、input、switch、tabbar 這幾個類別,那訓練出來的模型也只能識別這幾個類型的組件,若是你模型給一個進度條的組件截圖讓它識別,這個模型確定不能識別出來這是個進度條的,它只會告訴這個進度條屬於這幾個類別的機率是多少。
這裏咱們肯定了模型須要識別的 6 種類型,而後咱們就能夠開始收集樣本了,每個樣本包括一張組件的圖像以及這個組件圖像的類別。
收集頁面中的組件圖像
收集這些基礎組件的圖像,最直接的方式就是從線上頁面或者設計稿中提取組件的截圖。好比這裏先收集了這些頁面,而後經過一些工具或者腳本輔助把這些頁面中的組件截圖保存下來。
對這些組件的截圖,還須要作組件的類型標註,而後以這樣的文件格式存儲。同一種類型的組件圖像放在同一個文件夾下,文件夾的名稱就是組件的類型。而後壓縮成 zip 文件,這就是咱們須要的組件圖像分類的數據集了。
我是從咱們阿里內部 2 萬多份設計稿中提取的頁面,而後人工把這些組件從頁面中框選提取出來,當時記錄了一下,從 1 萬 4 千多張頁面中提取 2 個類別的組件截圖花了完整的 11 個小時,這只是 2 個類別組件的提取,前面還包括從 2 萬多份 Sketch 文件中提取頁面圖片、過濾、去重的時間,整個收集樣本的過程很艱辛。
並且,頁面中通常按鈕 button 比較多,但其餘類型的組件就不多,好比開關 switch、步進器 stepper , 這樣就會致使樣本不均衡。咱們輸入給算法學習的每一個分類的樣本是須要差很少的數量的。
樣本標註耗時:14000頁面 * 2個類別 == 11 個小時 樣本不均衡: 25647張頁面 == 7757個button + 1177個 switch + …
使用 puppeteer 自動生成組件樣本
對於這樣的問題,咱們能夠用咱們前端比較熟悉的技能來解決,就是使用無頭瀏覽器 puppeteer 來自動生成。
具體是這樣的,咱們能夠寫一個頁面,每刷新一次這個頁面就會渲染出不一樣類型不一樣樣式的組件。組件是隨機生成的,在實現組件樣式時作了 padding、margin、文字內容文字大小等的隨機生成,惟一肯定的是要給每一個組件加一個類型標記,好比若是是 stepper 組件,在這按鈕的節點上加一個 class 是 element-stepper 的類名。
這樣咱們再用無頭瀏覽器 puppeteer 自動訪問這個頁面,每訪問一次,從這個頁面中根據咱們設置好的類名獲取全部組件節點類型,並截圖保存。最後就獲得了咱們須要的數據集了。
有同窗可能會說,那我直接這樣自動生成不就行了,要多少就能夠生成多少。
也不是的,這種方式雖然能夠節省不少精力,可是畢竟仍是基於有限的規則生成的,樣本特徵不夠發散,與真實的樣本視覺特徵仍是有必定差別的。
若是輸入給算法學習的樣本多數是造出來的跟真實樣本有必定差別的圖像,那模型學習到的都是人造樣本的特徵,在用模型識別真實樣本時準確度也會比較差。
因此通常自動生成的樣本只是用做真實樣本比較少的一個補充。
如今數據集已經準備好了,下一步須要肯定選擇哪種機器學習算法來學習這些樣本的特徵。
由於這是一個圖像分類的任務,咱們能夠蒐集圖像分類算法的發展歷史,看下有哪些經典的算法。
(圖像分類經典算法)
而後從這些算法中選取業界使用比較多的幾個算法從模型精確度和預測耗時來那個方面作個比較。對於組件識別,組件圖像的複雜度相對較高,對識別的準確度要求也比較高,在組件識別中最後選擇 Resnet50。
像圖標識別模型,由於圖標相對比較簡單,識別的結果基本都是用於給 classname 命名,因此圖標分類算法選擇的是 MobileNetV2。
(幾種圖像分類算法的模型效果比較)
如今咱們已經肯定了使用的算法,下一步就是訓練模型了。
模型訓練的工做流通常是這樣的,咱們須要先下載數據集,而後可能須要作數據集格式轉換,而後作數據集處理,好比將準備好的數據集按必定比例拆分紅訓練集和測試集,而後下一步引入算法定義模型,而後開始用訓練集訓練模型,模型訓練完成後,用測試集作模型準確度評估。這樣模型訓練的流程就結束了,最後將訓練輸出的模型部署到遠程機器。
若是是機器學習工程師,對機器學習和 python 比較熟悉,會本身手寫這個模型訓練工做流的腳原本訓練模型。
對於前端同窗,咱們可使用前端算法工程框架 PipCook 來訓練模型,咱們能夠這樣來理解 PipCook,Nodejs 可讓前端工程師作服務端的事情,PipCook 也可讓前端工程師作機器學習任務。
PipCook 將這些過程作了封裝和集成,用一個 JSON 文件來表示,訓練工做流中的每一個階段都用一個插件來定義,支持配置每一個階段的參數。咱們只須要將數據收集這個插件的 url 參數的輸入值替換成本身的數據集連接便可。
而後執行 pipcook run pipline.json 就會開始訓練模型了。
訓練流程結束後會生成一個 model 文件,PipCook 將文件封裝成了一個 npm 包,咱們能夠直接在本地寫一個 js 腳本測試一下,預測的結果是這張測試樣本屬於每個分類的機率。咱們能夠設置一個閾值,當機率大於這個閾值時,則認爲識別的結果是可靠的。
若是要在工程項目中應用模型識別服務,還須要將模型部署到遠程機器上。
部署的方式有多種,例如咱們能夠將模型部署到阿里雲 EAS 上,阿里雲控制檯選擇模型在線服務,上傳模型文件部署,部署完成後,就能夠用虛擬機所在地區和填寫的模型名稱構造出訪問模型服務的 API。
也就是說模型部署以後,能夠獲得這樣一個可訪問的 RESTful API。如今咱們就能夠在 D2C 的工程鏈路中調用這個 API 來識別組件了,也就是最後的模型應用階段。
模型的應用鏈路在不一樣的應用場景都會不同,在 D2C 組件識別這個場景,咱們是在通過佈局算法生成了具備比較合理的嵌套佈局結構的 D2C Schema 以後,根據 div 容器節點的位置將這些頁面內部截圖裁剪出來,而後調用組件識別模型服務來識別,識別的結果再更新到 D2C Schema 中對應的節點的 smart 字段上。
那這樣模型應用是否是結束了?尚未啊,這裏只是完成了組件識別的過程,前面咱們講過,要作兩件事,一個是識別組件,一個是表達成代碼。咱們還要將識別的結果表達成代碼。
imgcook 支持用戶自定義 DSL 轉換函數,將 D2C Schema 轉換成不一樣類型的前端代碼。大體的邏輯是遞歸遍歷 D2C schema 中的節點,判斷節點類型,轉換成對應的標籤。
若是在轉換過程當中還須要將組件識別的結果轉換成引入外部組件的話,還須要給DSL函數輸入用戶錄入的組件,根據組件的類型和模型識別的結果,在生成代碼時引入用戶錄入的外部組件。
到這裏,用機器學習來解決引入外部組件的問題實踐過程就介紹完了。
咱們能夠回顧下,爲了解決在生成代碼時對於引入外部組件的場景也能自動生成的問題,咱們選擇訓練一個機器學習圖像分類模型來識別頁面中的組件。
首先須要準備樣本,咱們能夠收集真實的頁面或設計稿,從中提取組件並進行樣本標註,生成數據集,也能夠用pupeteer 自動生成,準備好數據集後,根據對模型識別準確率和識別速度的權衡,選擇了 Resnet 算法。
而後用前端機器學習算法框架 PipCook 來訓練模型,PipCook 爲咱們封裝好了載入數據集,數據處理、定義模型、訓練模型、模型評估一整條 pipline,咱們只要執行一條 pipcook run 就能夠開始訓練了。
訓練完成後會獲得一個模型文件,把這個模型文件部署到阿里雲 EAS,能夠獲得一個可訪問的模型識別服務 Restful API,而後在代碼生成鏈路中調用此 API 識別 UI 界面中的組件,組件識別結果最後用於生成代碼。
這裏提供了幾個 step by step 的實踐案例,第 1 個是用 pipcook 訓練,在 colab 中執行,不用考慮環境問題,直接點點點就行了。 第 2 個是用 pipcook 訓練在你的電腦上訓練,須要在你的電腦上安裝環境。第 3 個是一個用 python 實現的機器學習任務,你也能夠看下用 python 是怎麼實現數據集載入、模型定義和模型訓練這個流程的。
這幾個實踐任務,都提供了代碼和數據集。若是你們感興趣的話,能夠根據這個案例體驗一下今天介紹的這個機器學習實踐過程。
剛纔咱們以組件識別爲例,介紹了整個機器學習實踐和應用的過程。除了組件識別,還有文本識別、圖標識別、等,實踐方法基本都是這個步驟。
這些模型識別結果不只能夠應用於 UI 代碼的生成,還能夠應用於業務邏輯代碼的生成,在雙 11 頁面中有一些業務邏輯代碼不是很複雜的模塊,生成代碼可用率能夠達到 90% 以上,基本上能作到 0 研發投入。
好比這樣一個雙 11 活動頁面中的模塊,若是咱們人工手寫代碼的話,會涉及哪些業務邏輯。
好比這裏有個循環,咱們只須要實現一個商品的UI而後用 map 循環,好比這裏的商品標題、價格、商品圖等須要綁定動態數據,還有點擊商品要跳轉、在用戶點擊時還要發送埋點日誌。除了這些,好像也沒有其餘的業務邏輯了。
那這些業務邏輯咱們是能夠根據模型識別的結果來自動生成的,這裏是一個 1 排 2 的循環,能夠識別到這是一個商品標題,能夠識別出這是一個商品圖,這些識別的結果咱們能夠應用於字段綁定、頁面跳轉等業務邏輯代碼的生成。
前面也介紹過,識別的結果都是掛在在每一個節點的 smart 字段上,好比這裏識別到這個文本節點內容是一個商品標題 itemTitle,若是要將這個識別的結果用於字段綁定的話,咱們能夠把有這個識別結果的 text 節點的內容替換成字段綁定的表達式,
那這個替換的操做在哪作呢?imgcook 支持用戶錄入本身的業務邏輯,每一條業務邏輯都有一個識別器和一個表達器。
D2C Schema 中的每一個節點都會通過這些邏輯識別器看有沒有業務邏輯點,若是有的話,根據對應的表達器中的邏輯表達。
例如商品標題字段綁定這個業務邏輯,設置的識別器就是判斷文本節點的 smart 字段上 fieldbind 字段是否是itemTitle,若是是的話,就執行表達器中的邏輯,將此節點自動綁定上 itemTitle 字段。
這樣咱們就能根據用戶自定義的業務邏輯,更新 D2C Schema,最後再將這個帶有業務邏輯的 D2C Schema 用 DSL 轉換函數轉換成代碼。
這就是模型識別的結果是應用於業務邏輯代碼生成的過程,其餘業務邏輯生成也是用業務邏輯庫來承接模型識別結果真後應用於代碼生成。
將來咱們一方面會用智能化技術繼續提高生成代碼的數量和質量,另外一方面,在多狀態UI、微動效等複雜 UI 等代碼生成問題上會有一些新的探索,好比這裏的發佈試用報告按鈕,它有多種狀態,根據服務端返回的數據不一樣,展現不一樣的 UI,好比這個頁面中點擊進入按鈕,有這種微動效。
另外,設計稿生成代碼 D2C 的本質是對 「產品設計產物(高保真設計稿)」進行智能理解而高保真設計稿是通過產品設計週期,從產品經理基於一些方法和理論肯定業務目標和頁面結構,到視覺設計師結合產品特性、功能理解與視覺設計規範產出的。
咱們指望可以構建的一套這樣的 D2C 底層認知的理論體系,將產品設計和視覺設計方法融入 D2C 實踐中,基於產品設計方法和視覺設計原則智能理解設計產物,能夠幫助咱們對設計稿的理解更全面深刻,有助於生成數量更多質量更高的代碼。
(D2C 實踐理論體系)
imgcook 是一個對外開放的平臺,歡迎體驗設計稿生成代碼 imgcook,若是有使用問題,請加入 imgcook 社區用戶羣。
另外,若是你們對此次分享有所收穫,也能夠想一下,用機器學習能解決前端領域的哪些問題,好比智能設計、代碼推薦、智能 UI、UI 自動化測試等等,若是你們感興趣,也能夠用今天介紹的這個實踐流程,本身去寫一個 Demo 項目體驗一下。
將來,也但願有愈來愈多的同窗能參與到前端智能化的建設中,用智能化技術解決更多前端領域的問題。