天天看點

邏輯代碼自動生成相關技術概述

作者 | 妙淨
邏輯代碼自動生成相關技術概述
作者周婷婷(花名:妙淨,微信: weekendingting)是阿裡淘系技術部進階前端技術專家,視覺稿智能生成代碼 imgcook 平台負責人,阿裡經濟體前端智能化方向重要成員,來自業内首個 AI 前端團隊淘系前端之 F(x) Team 。去年我們聚焦在設計稿智能生成前端視圖代碼領域,但對于邏輯代碼的智能生成也一直在不斷嘗試,本文介紹邏輯代碼自動生成相關技術概述。

程式生成介紹

如何有效地提高軟體開發的效率和品質,一直是軟體工程領域關心的問題。其中, 程式自動生成技術被認為是提高軟體開發自動化程度和最終品質的重要方法,受到學術界和工業界的廣泛關注。程式自動生成技術指利用某些技術自動地為軟體生成源代碼,達到根據使用者的需求機器自動程式設計的目的。極大程度地減輕了程式員的開發負擔, 使得程式員可以更加關注于業務價值賦能。

學術界上,程式生成和代碼補全是程式綜合 (program synthesis) 的重要分支, 其目的在于輔助甚至代替程式員編寫程式。回到(前)端代碼的自動生成,分為視圖代碼和邏輯代碼,視圖代碼方面目前有類似基于設計稿自動生成 的方案(如 imgcook),本文重點講述邏輯代碼的生成技術方案,常見的生成邏輯代碼的方案包含基于可視化編排生成、基于輸入輸出樣例生成、基于代碼語料生成補全、基于功能描述生成等。

邏輯代碼自動生成技術方案對比

邏輯代碼自動生成相關技術概述

基于可視化編排生成代碼

可視化程式設計也發展了幾十年,其指的是借助于一些元件化的內建代碼可視化平台,一些不具備專業代碼技能和開發經驗的“小白”人群也能自主組織或參與應用開發,進而把代碼開發由一項程式員專屬職能擴充到更廣泛的人群。它主要是讓程式設計人員利用軟體本身所提供的各種控件,像搭積木式地構造應用程式的各種界面,可視化編排更适合界面視圖代碼的生成;目前國外主打可視化程式設計、低代碼程式設計的平台至少有十幾家,其中最具代表性的可以說是 OutSystems、Mendix、Salesforce 等幾家,而且對于邏輯代碼的可視化方案也有很多,如下:

邏輯代碼自動生成相關技術概述

以上類 blockly 等适合比較簡單的邏輯程式設計,目前在少兒程式設計領域的應用不錯;一但邏輯複雜,搭建出來的積木也無比龐大。這樣的系統在大公司,如果給業務方直接用,太複雜需要有業務方有程式設計思維,和 PRD 思維完全不一樣,門檻較高;如果給程式設計人員用,隻是用圖形來代替了程式設計語言,程式設計人員因熟悉程式設計語言和相關調試等配套環境,可視化搭建的方式生成代碼反而更低效。

其他主流的邏輯代碼的可視化的編排(如下圖),其優勢是突出“可視化流”和複用邏輯節點帶來的高效,主體是大的流程,輸入輸出、邏輯處理等細節包含在每個節點的具體表單規則中。此方案适合複用邏輯非常多的場景,複用的邏輯可抽象成流程圖中的“節點”。節點的複用顆粒度大小是比較關鍵的,顆粒度大到一個功能服務,就是業務流程編排了,業務流程複用度比較高的場景是比較适合讓業務方直接所見所得編排使用的;顆粒度小到表達式級别可以看做是業務邏輯編排,太小顆粒度是需要使用者有程式設計思維,顆粒度太小的可視化對于有程式設計思維的同學來說,可能直接寫代碼效率更高。

邏輯代碼自動生成相關技術概述

小結:可視化邏輯編排生成代碼,其本身編排的成本還是比較高的複雜情況下甚至比手寫代碼程式設計還要高,但在邏輯複用度非常高的場景是比較适合的,可抽象成可複用的邏輯節點去編排,節點的複用可以帶來部分提效。

基于輸入輸出樣例生成代碼

基于輸入輸出的樣例,自動推導出生成的邏輯程式,也叫 PBE(Programming by Examples),其是 2016 年微軟在論文中提到的一種程式綜合(program synthesis)的技術方案。現實中比較成功的應用案例是,Excel 中有個功能相信大家應該熟悉,那就是自動填表(FlashFill),其可以根據幾個樣例快速的生成表格項公式,比如下圖中,根據 第一列的 2 和 4,就可以填充偶數;第二列根據 50 和 40 自動推導出等差數列公式的結果。

邏輯代碼自動生成相關技術概述

以更複雜的情況為例:

邏輯代碼自動生成相關技術概述

上述的公式更複雜,現實情況,FlashFill 的正确率隻有不到 50%,後來又在 PBE 的基礎上提出了 NPBE(neural programming by example) 完成 Excel 中的 45 種字元串操作。NPBE 的意圖是讓模型從輸入輸出字元串中學習相關的特征, 并用學到的特征來歸納正确的程式。一般 PBE 的技術實作過程如下:

邏輯代碼自動生成相關技術概述

基于代碼語料生成補全代碼

随着 github 的開源代碼的積累和深度學習的興起,基于源代碼了解(程式了解)應用比較多,如代碼補全推薦、還有根據代碼猜測代碼片段的意思。

代碼補全

常用的內建開發環境中往往整合了代碼補全工具, 一般限于關鍵字或基于文法的提示,比如在 tsx 檔案中 this. 會提示出目前可用的類屬性、方法;現有的智能代碼補全工具通常基于模型性能考慮一般簡單基于靜态詞頻統計。

比如我們共建團隊同僚基于 javascript 代碼語料庫,對比 GPT2 之後,采用 n-gram 機率模型開發的代碼補全插件。詳見這裡,其主要流程圖如下:

邏輯代碼自動生成相關技術概述

代碼意圖生成

代碼意圖生成指根據代碼内容可以推測出代碼的功能作用,業界較知名的開源的模型和服務有 code2vec 和 code2seq,其中 code2vec 是做 code summarization(代碼功能概要);code2seq 做 code captioning (代碼功能說明)。

code2vec 示例說明如下:根據左側的代碼片段,分析代碼的功能是,90.93%的機率是 contains,右側是對代碼的分析可視化過程,重點關注節點間的連線粗細,粗細用來表示決策的資訊權重大小。

邏輯代碼自動生成相關技術概述

code2seq 示例說明如下:根據左側的代碼片段,分析此代碼的功能說明是,save bitmap to file,右側是對代碼的分析可視化過程,同樣重點關注節點間的連線粗細,粗細用來表示決策的資訊權重大小。

邏輯代碼自動生成相關技術概述

其内部模型詳見:其目前開源的模型資料集大小為 billon 級,也開源了基于 typeScript 的模型。

邏輯代碼自動生成相關技術概述

基于功能描述生成代碼

大家通常利用自然語言來描述程式功能, 從自然語言描述到程式的自動生成是極具挑戰性的問題。自然語言文本和程式的多樣性、文本的二義性以及代碼的複雜結構, 使得建立文本和代碼的聯系成為一個難題。目前業内有些探索,包括 NL2SQL、NL2TFTTT、基于功能描述生成代碼。

NL2SQL

Natural Language to SQL (NL2SQL) 是CUI(Conversation User Interface)的新興研究熱點,其研究目的是将使用者輸入的自然語言轉為可用的 SQL 語句,提高使用者查詢資料的效率,現在阻礙大資料價值變現的最大難題就是通路資料門檻太高,依賴資料庫管理者寫複雜的SQL,而且中文的表述更加多樣複雜。此領域的國内外的研究非常多,目前 NL2SQL 領域比較有名的資料集是英文版的資料集,包括 WikiSQL、Spider、CoSQL 等。

NL2SQL 典型的三層架構如下:

邏輯代碼自動生成相關技術概述

NL2SQL分為User query interface、Processing Unit、Database三部分,其中 Processing Unit 是整個架構的中心,也是語義解析的核心所在,打通了 User 與 Database 的互動通道,囊括智能分詞、實體識别、知識檢索等各個技術要點。在上述研究中,Processing Unit 的内部算法也在逐漸朝着深度學習的方向進展。下面是中文 NL2SQL 大賽中冠軍團隊提出的 M-SQL 模型,在中文資料集上達到了92%的準确率。

業内 Google的 Analyza 采用的是語義解析和規則的方式建構的,這種方式可控性較強,但是需要人工維護一些規則進去。端到端的方案則是通過深度學習方法,采用 encoder-decoder 的方式進行 NL2SQL 的實作,整個算法系統分成了對 SQL 幾個子句的識别,包括SELECT clause、WHERE clause,有時候還有 group by、limit 等操作符。每個部分還會涉及到很多細節,比如表識别、屬性識别等。不同算法都是在這樣的架構體系下,在細節的地方做一些改動和優化,以取得一個比較好的效果。雖然端到端的 NL2SQL 方案能夠減少人力維護的成本,但是隻有在 wikisql 這種簡單場景下有一定效果,針對相對複雜一點的 spider 或 cosql 場景來說,準确率非常低,達不到商業應用的要求。公司内部的數小蜜團隊實際業務落地的方案與Google的Analyza方案很相似,同時也已經對端到端 nl2sql 方案進行了研究和實作,下一步期望能夠将 NL2SQL 和語義規則解析的方式融合到一起,來解決複雜場景的需求。【此部分結論來源内部小蜜團隊】

NL2TFTTT

IFTTT 是什麼?意思是 if this then that;是一個新生的網絡服務平台,通過其他不同平台的條件來決定是否執行下一條指令。例如「如果明天下雨,請今天通知我」「當有人在 Facebook 标記有你在内的相片時,就自動将那張照片備份到iPhone 的照片相冊中」,這滿足了使用者把 A 服務内容串連到 B 服務的需求,并且使用者不用自己動手, IFTTT 可以自動幫忙完成上述動作。

功能示例

如下面的應用:

  • 如果明天下雨,請發通知給我
  • 請每天 7 點給我一份天氣預報

其設定如下:

邏輯代碼自動生成相關技術概述

NL2IFTTT 就是通過自然語言生成如上 If-This-Then-That(IFTTT) 代碼,IFTTT 程式相對于常用的程式設計語言來說, 其結構更加簡單, 也更容易學習其結構規則。IFTTT 基于任務的條件觸發,類似極簡版程式設計語言,即:“若 XXX 進行 YYY 行為,執行 ZZZ”。每一個可以觸發或者作為任務的網站叫做一個 Channel,觸發的條件叫做 Trigger,之後執行的任務叫做 Action,綜合上面的一套流程叫做 Recipe。

NL2IFTTT 方面的實踐,2016年, Liu等人提出了一種隐注意力機制, 該機制可以有效地學習自然語言中哪些詞對觸發器的預測更重要, 哪些詞對動作的預測更加重要。同年,Beltagy 等人将IFTTT 程式生成問題當做語義分析問題。

資料集示例

微軟有一份開源 IFTTT 樣本集,其樣本資料類似如下,可以友善大家更好地了解 NL2IFTTT 的問題定義:

邏輯代碼自動生成相關技術概述

NL2Code-TranX

相比于根據自然語言的功能描述生成 TFTTT 代碼 和 SQL,根據自然語言的需求描述直接生成 python、java、javascript 這類的程式設計語言邏輯代碼的難度要大的多。至今(2020.8)暫時沒有找到相關的線上可用服務,目前找到卡内基梅隆大學有相關研究産出 TranX,其可以做到單一功能描述 生成 表達式級的代碼,類似根據單行代碼注釋生成相應代碼,見其網站 demo 如下。

TranX 功能示例

邏輯代碼自動生成相關技術概述
邏輯代碼自動生成相關技術概述
邏輯代碼自動生成相關技術概述

TranX 資料集示例

{
    "intent": "Sending http headers with python",
    "rewritten_intent": "sending http headers to `client`",
    "snippet": "client.send('HTTP/1.0 200 OK\\r\\n')",
    "question_id": 8315209
  },
  {
    "intent": "Python -Remove Time from Datetime String",
    "rewritten_intent": "Format a datetime string `when` to extract date only",
    "snippet": "then = datetime.datetime.strptime(when, '%Y-%m-%d').date()",
    "question_id": 26153795
  },
  {
    "intent": "How do I split a multi-line string into multiple lines?",
    "rewritten_intent": "split a multi-line string `inputString` into separate strings",
    "snippet": "inputString.split('\\n')",
    "question_id": 172439
  },
  {
    "intent": "How do I split a multi-line string into multiple lines?",
    "rewritten_intent": "Split a multi-line string ` a \\n b \\r\\n c ` by new line character `\\n`",
    "snippet": "' a \\n b \\r\\n c '.split('\\n')",
    "question_id": 172439
  },           

TranX 模型示例

程式設計語言有嚴格的文法,它不能容忍拼寫錯誤和文法錯誤;此模型針對 AST 建構基于 Tree 的新型模型,能完整表達程式設計語言的所有文法;同時相應的語料标注是非常昂貴和耗時的,标記樣本的有限可用性是監督模型的瓶頸,此模型引入了 STRUCTVAE,一種用于半監督的自動編碼模型,它可以從有限的樣本中學習,又能從現成未标記的 NL 語言中學習。論文模型詳見:

邏輯代碼自動生成相關技術概述

NL2Code-debuild

功能描述生成代碼的應用,還有基于 GPT3.0 的 debuild 平台;目前示範網站關閉,從宣傳出來效果圖來看,可以看到從功能描述生成代碼新的可能性。其可以根據布局語言描述生成相應的布局代碼;也能根據簡單高階的功能描述生成相應的代碼。

debuild 功能示例

邏輯代碼自動生成相關技術概述

debuild 模型示例

此平台使用的模型基于 openAI 的 GPT3.0,作者表示自然語言生成代碼基于 GPT3.0 讓之前不敢想象的的 50 年之後能生成代碼 提前到 5 年内,目前的版本還是偏試驗,更多是偏簡單功能描述生成高階(封裝好的元件庫、子產品庫等)的功能代碼,感興趣的可以試試 GPT 3.0。

總結

總體來看,基于深度學習為自動生成程式代碼是趨勢,但目前利用深度學習技術的程式生成和代碼補全還處于起步階段。利用深度學習生成程式代碼和代碼補全與傳統方法相比有了較大的提升, 而程式生成技術還沒有用于工業化。其主要面臨着以下的挑戰:

1) 訓練語料的品質參差不齊。常見工作中, 用來訓練深度學習模型的語料大緻可以分為兩類:一類是基于 DSL 人為構造出的程式; 另一類是從開源社群, 如 GitHub 等網站上爬取的項目。基于 DSL 的程式往往文法較為簡單, 程式長度較短, 易于訓練和測試, 但同時, 針對 DSL 設計的模型也難以推廣到其他語言上使用; 而開源社群上爬取的項目雖然更接近于實際軟體開發, 但是也難以保證代碼的品質——低品質、不規範的代碼會給神經網絡帶來額外的噪聲, 而使用不同程式設計規範的代碼則會使神經網絡模型在訓練和預測時産生混淆。如何擷取統一規範的高品質程式語料庫也是一項挑戰。

2)使用者自定義邏輯生成後的泛化能力弱。程式代碼尤其是邏輯代碼,很多都是業務閉域的邏輯代碼,需要很多業務閉域的邏輯物料,需要對現有業務的所依賴的各種服務進行高階了解,新業務需要結合自己的物料庫訓練自己的模型;但往往全新的業務依賴的服務也需要從 0 開始開發,新物料的提供比較難,除非所有依賴的服務是不可拆分的原子服務。是以邏輯模型的普适性比較難,但方法論可以互相借鑒有普适性。

3)功能描述和程式代碼資訊不對稱。如果真的做到極緻,功能描述由 PRD 直接提供,可直接生成相應的程式代碼;需求描述比一般的功能描述還要高階和抽象化,需求描述->功能描述-代碼描述->程式代碼,這其中每一個環節都會有很多資訊損耗,這些損耗目前都是程式員通過業務經驗和程式設計經驗補上的。功能描述直接生成代碼解決辦法大緻有 3 種,一種是端到端的從需求描述并生成 AST,如果 PD 對軟體功能的描述足夠精确,相當于創造了一個更進階的描述語言; 第二種是後面的鍊路部分(功能描述-代碼描述->程式代碼)封裝抽象成顆粒度較大的功能塊描述,目前大部分是基于這種的可行性比較高(如 NL2TFTTT 等);第三種是真正深入到每一個業務域中,上述每一個環節都讓模型去一層層了解最後逐漸生成代碼,語料庫的品質和最後的模型準确度效果是比較大的挑戰。

為了減輕程式員的開發負擔, 提高軟體開發的自動化程度, 提高軟體開發的效率和品質, 學界和工業界都不斷嘗試研究程式自動生成技術。随着深度學習技術的快速發展, 相信在将來, 越來越多的重複性的程式開發将由機器代替, 程式員将更關注于底層架構和上層業務價值賦能。

對于邏輯代碼的智能生成,目前阿裡前端智能化團隊内部正在進行各次元的試驗,歡迎交流。

參考資料

邏輯代碼自動生成相關技術概述

關注「Alibaba F2E」

把握阿裡巴巴前端新動向