人們在日常生活和工作中越來越多地接觸到 AI。JetBrains 是一家為程序員開發工具的公司,我們認為軟件開發行業也處在這樣的趨勢中。
AI 的兩種用途:
取代人類,完全自動化他們的一些工作。
增強人類,幫助他們保持關鍵地位。
算法已經能夠自己編寫代碼了,但人類開發者不需要擔心會立即被取代。
之所以這麼說,並不是因為人類不可能教會計算機取代程序員所需的技能,而是因為這是不切實際的。
限制 AI 發展的三大因素:
有限的訓練數據可用性。
有限的計算資源。
算法和人類之間接口的複雜性。
為了增強人類程序員的工作,許多普通的任務,如代碼補全、代碼搜索和錯誤檢測,現在都通過機器學習來提供幫助。
圖 1. AI 應用方法和每一種方法的困境
當人們聽到「AI」這個詞時,他們通常會想到計算機將取代人類,與人類執行同樣的任務,並比人類做得更好:更快、更便宜、質量更高,或者所有這些結合在一起。這類任務包括下象棋或圍棋、寫詩和開車。
有些人希望計算機能夠將他們從日常繁重的工作中解放出來,而另一些人則持懷疑態度。後者可能會聲稱:機器遠不能與人類匹敵。
比如,類似「你如何教會計算機做這些事情?」這樣的話往往暗示着「你做不到」。以下是過去人們提出的一些類似的疑問:
圍棋的合理步數超過了可用的計算資源。你如何取代人類的直覺?在這篇 1997 年發表的 文章 中,專家估計這需要一百年時間。
你如何讓一輛自動駕駛汽車看到潮濕的路面並減速?
計算機已經會玩圍棋和開車了,所以這些問題現在已經過時了。這讓我們有理由相信,這類仍然懸而未決的問題最終也會得到解答。無論是哪個專業領域,計算機比我們大多數人認為的更接近人類的技能。
然而,取代人類並不是權宜之計。AI 開發者不會與人類展開競爭,他們會選擇不同的產品策略,嘗試使用算法來增加程序員的工作,提高他們的生產力。
在軟件開發領域,我們已經清楚地看到 AI 可以執行人工任務,也可以增加程序員的工作。
GitHub Copilot(由 OpenAI 提供支持)的發布再次激起有關計算機何時或是否將取代人類程序員的討論。那些認為計算機不可能取代人類的懷疑論者總是會問:
你如何向機器解釋你的程序應該做什麼?
答案很簡單。你可以使用自然語言定義你想要的內容,為函數提供一個名字,並(可選地)編寫幾行代碼來啟動函數。Copilot 會填補餘下的內容,就像一個真正的程序員一樣。
有些人對智能的 Copilot 感到很滿意,有些人則會抓住它的小問題,並認為這些問題足以表明在可預見的未來仍然需要人類程序員。還有一群人也注意到了同樣的問題,但得出的結論是:Copilot 是一個可怕而危險的工具,所以不應該去碰它。
Copilot 生成的代碼通常很冗長,難以閱讀。
代碼清晰度很重要,因為對於開發人員來說,讀代碼比寫代碼更重要。在大多數情況下,程序員需要在已有代碼 (通常是其他人編寫的) 的基礎上添加新功能。對於這種情況,寫代碼就像是給老房子增加一個新房間。你必須確定增加新房間是否會破壞平衡並導致整座房屋倒塌。如果它是安全的,你仍然需要了解現有的房屋結構,並加以修改,以便在其上增加新房間。程序員的大部分時間就是在「現有房屋」上增加「新房間」。
R. Minelli、A. Mochi 和 M. Lanza發現,程序員花在理解代碼上的時間大約占 70%,而寫代碼只占大約 5%。基於此類研究,我們可以看到開發人員工作時間的分布,如圖 2 所示。
圖 2. 程序員在工作中花費的時間,按活動分類
冗長和含糊不清的機器生成代碼可能會讓本已難以理解的部分更加晦澀難懂。
人類的認知負載仍然存在:程序員仍然需要理解算法。計算機設定的節奏人類能保持多久?讓 AI 來編寫代碼可能會加快處理小任務的速度,但不一定會加快大型項目的速度。
我們將其與上世紀 70 年代出現的版本控制系統做一下對比。追蹤和回退變更的能力極大地擴大了人們理解代碼的範圍,使大型團隊合作成為可能,也因此可以開發出更複雜的系統。這是整個行業的變革。
Copilot 是展示 AI 潛力的一項優勢的研究成果。它做到了許多人認為不可能的事情。然而,我們並不指望這些工具能夠在短期內重新定義程序員的職業。
雖然 Copilot 是 AI 領域的一項與編程相關的突破,但它既不是行業革命,也不能取代人類工作。請記住,這樣的變革可能會在某一時刻發生,但我們仍然需要繼續改進現有的軟件開發過程。幫助程序員更有效地執行小任務是 AI 的一個廣闊的應用領域。
軟件開發人員使用的工具通常有嚴格的規則 (「啟發式」),但沒有 AI 的成分。隨着每個工具提供越來越多的功能,規則變得越來越複雜。最終,人類不可能理解所有東西,也不知道如何改變工具,而這恰恰是 AI 可以提供幫助的地方。
當你在谷歌搜索輸入框輸入搜索關鍵字時,它會向你建議完整的搜索選項。源代碼編輯器為程序員提供了類似的功能。
代碼補全的第一個版本出現在很久以前,可能是在某某世紀,主要是通過計算項目中出現的單詞的頻率來實現的。它們根據用戶輸入的開頭字符顯示出現頻率最高的單詞。這種基於頻率的方法還不錯,可以提高工作效率。多年來,人們在頻率的基礎上使用了一些啟發式算法來改進補全建議,但為了精確地提供用戶想要的單詞,我們使用機器學習對補全建議進行排序。
因為用來確定最佳補全建議的信息太過豐富,所以我們不可能創建出一個將所有這些都考慮在內的確定性算法。我們不得不處理很多特殊情況。
例如,根據一般性規則,標記的定義與程序員當前編輯的位置越接近,就越有可能是這個標記。而且,標準語言庫可以按流行程度排序,流行程度最低的庫的標記將被剝奪優先級。綜上所述,假設你用 Java 開發了一個源代碼編輯器 (我們在 JetBrains 就是做這個的),並輸入「Co」。以下兩個建議你會選擇哪一個?
一方面,我們確實在編輯器中使用了紅黑樹。另一方面,java.awt 包在行業中很少被使用。但是,在我們的項目中,「Color」很可能是指 java.awt.Color。
影響補全建議排序的因素有成百上千個。補全建議是用戶項目中定義的符號、標準語言庫還或導入的第三方庫?補全建議插入的地方是在一行的開頭還是中間?在這個位置前面有沒有點號?用戶平均每天工作多長時間?他們現在是否在另一個編輯器標籤中打開了補全建議的定義?
藉助機器學習,我們可以用半自動化的方式提取模式,在不可能明確列出所有依賴關係的情況下將所有這些因素都考慮在內。
更進一步,我們還可以使用 AI 生成較小的代碼片段。如果編輯器可以補全一整行,而不是一個單詞,那麼在開發速度和認知負載之間就有了一個很好的權衡:
圖 3. 一個代碼補全的例子。不只是建議一個單詞
一些公司將這一功能作為其業務的核心。例如,TabNine 和 Kite 將他們開發的軟件作為編輯器插件發行,幫助程序員「以 AI 的方式」補全代碼行。
源代碼編輯器是一種複雜的軟件,程序員可以執行數以百計的操作來提高生產力。可惜的是,程序員不可能了解所有這些操作。
我們可以在編輯器啟動時顯示提示,但要在使用編輯器時回想這些提示可能很困難。程序員通常有 50 多個最喜歡使用的命令。有了智能提示,我們可以根據用戶的工作模式和習慣為他們提供兩到三個特別有用的操作。
AI 可以用來創建這些個性化的建議。例如,當且僅當程序員經常在同一個屏幕中執行剪切和粘貼操作時,我們就可以告訴他們如何更好地進行代碼移動操作:
圖 4. 「代碼移動」操作提示
實現這個特性最直接的方法是使用「協同過濾」。音樂、視頻、書籍和商品等現代推薦系統都在使用它。它有兩個基本的步驟:
找到與指定用戶「相似」的用戶。
找出這些用戶做了哪些指定用戶還沒有做的事情,並根據這些差異給出建議。
對於內容推薦,找到相似的用戶是相當簡單的:如果我們的目標用戶與其他一組人喜歡相同的 10 部電影,但沒看過這個組中所有人都喜歡的電影,那麼推薦這部電影就一個相當安全的押注。唯一需要注意的是要避免那些幾乎每個人都給予正面評價的超級受歡迎的電影。喜歡《教父》或《阿甘正傳》並不代表用戶的喜好。
對於源代碼編輯器,就有點困難了。因為沒有相同類型或相同演員的特徵,我們必須分析較小的行為模式。用戶花了多少時間調試?他們多久編輯一次已有的代碼?他們打字有多快?他們是在編寫代碼之前還是之後編寫測試用例?將這些因素都考慮在內,就可以確定用戶之間的相似性,並根據已知的行為模式推薦有用的工具。
搜索是許多軟件產品(從 Web 搜索引擎到在線商店)都存在的一個功能。源代碼編輯器也有這個功能:開發人員經常需要在他們的代碼、文檔和工具配置選項中搜索一些東西。這些信息屬於不同的類型,用戶需要在開發工具的不同位置來搜索它們。
我們希望在源代碼編輯器中提供一個統一的搜索功能,用於查找上述的任意一種信息,並把同義詞和拼寫錯誤考慮在內。因為有很多人致力於研究搜索算法,人們希望存在一個標準的可重用解決方案,但是,每個領域都有自己的特點,所以需要單獨開發搜索功能。
當項目中不同類型的信息具有相似的名字時,複雜性就出現了。當用戶在搜索框中輸入「format」,並他們的項目中有一個名為 Formatter.java 的文件,那麼他們是在查找這個文件還是在查找標準格式庫函數,抑或是查找可以格式化代碼的 IDE 功能?
機器學習將不同來源的搜索結果混合在一起並進行權衡。影響決策的因素包括文本匹配、用戶的搜索歷史和他們以前的偏好 (例如,他們曾經點擊過文件搜索結果嗎?)、用戶項目的內容,以及用戶在進行搜索之前所編輯的內容。開發一個可以考慮所有這些因素的確定性算法看起來是不可行的,而機器學習可以自動提取其中的模式。
將所有 AI 為用戶生產力帶來的微小改進加在一起,可以帶來令人印象深刻的整體提升。然而,這是有代價的。
基於 AI 的系統在大多數情況下運行良好,但在某些情況下也會提供奇怪的結果。向用戶提供這樣的結果會失去一些用戶的信任。每次用 AI 驅動的決策系統取代嚴格的規則時,我們都必須決定是否要做出權衡。我們可以提高平均決策質量,但也可能會失去一些用戶的信任。
如果能建立一個完美無瑕的系統,不會因為糟糕的建議而失去用戶的信任,那當然很好,但要做到這一點,還存在一些障礙。
許多機器學習算法在訓練階段需要樣本數據,而且數據集的質量至關重要。通常,我們知道需要獲取哪些數據,但獲取這些數據要麼代價高昂,要麼是非法的。
代碼生成任務(無論是 IDE 的自動補全還是用 Copilot 生成整個功能)需要有用於訓練的源代碼,那麼使用 GitHub 上的開源代碼庫似乎是很自然的事。然而,這些代碼庫有許可方面的限制,這些許可可能對衍生品有額外的要求。
這給我們留下了兩大問題:我們的 AI 算法是從我們用來訓練它的代碼衍生出來的嗎?這個算法生成的代碼是衍生品嗎?
一方面,AI 算法作者並沒有將任何內容複製到算法中。另一方面,神經網絡不能獨立思考。它生成的所有代碼都是它在學習階段看到的片段的組合。它甚至可以生成看起來與訓練數據集完全相同的代碼片段。關鍵是,即使看起來獨立的代碼片段也並不比複製品更獨立。
這是個新問題,我們還沒有看到任何法律方面的裁決。這種不確定性讓產品開發人員小心翼翼:他們不希望在未來可能成為非法的東西上大舉投入。
我們在開發代碼補全系統時也遇到了同樣的問題。除了潛在的法律限制之外,還有技術上的困難。我們在開源代碼庫中找到的代碼在某種意義上是「完整的」。它們通常都可以通過編譯,可以通過簡單的測試,格式清晰,不包含重複塊或臨時調試內容。然而,我們在編輯器中處理的代碼大多數時候是不「完整」的。因此,我們從開源代碼庫中獲得的訓練數據與開發條件不匹配。
我們通過使用來自我們產品的使用統計數據來解決這些問題。為了讓這些數據完全匿名,我們做了很多努力,但最終一切都很順利。你可以在 JetBrains 的這篇 博文 中了解更多的技術細節。
這些只是人們在為 AI 算法收集訓練數據時面臨的幾種示例情況。
AI 算法非常渴求資源。這種渴求在學習和探索階段有着不同的含義。資源限制在學習階段給算法開發人員帶來了額外的成本,他們需要決定是否在硬件方面投入。但在探索階段,限制因素不是算法開發人員的資源,而是用戶的資源。
探索階段的資源需求標準解決方案是將資源密集型計算轉移到遠程集群上。我們的客戶通常希望將源代碼保存在受保護的網絡中,因此使用遠程服務器通常是不可能的。這意味着我們的算法必須運行在用戶電腦上的源代碼編輯器中。編輯器提供了很多特性,並且已經消耗了相當多的資源,所以每個新分配的字節都不能隨意浪費掉。
普通軟件開發人員和機器學習開發人員對資源的看法非常不同。下面的故事可以說明這種差異有多大。
當我們第一次用機器學習取代基於規則的代碼補全功能時,負責這項任務的團隊將額外的內存需求減少到了 1.5MB。團隊認為他們將內存需求降到了極致,並為此感到自豪。當其他人得知這件事時,他們的反應很有趣:
與我們一起合作的 AI 研究人員說:「1.5MB?你一定是在開玩笑!至少 1GB 起步才行!」
傳統的工具開發人員在評審了這個變化後說:「1.5MB?為什麼需要這麼多?」
研究人員通常假設資源是無限的,而產品必須運行在可用的硬件上。這就是為什麼 AI 領域的突破性研究成果難以產品化的原因之一。
即使可以在遠程執行,在遠程服務器而不是客戶的機器上運行 AI 也可能存在重大的可用性問題。
任何延遲對用戶來說都是無法忍受的,特別是對於非常小的事情。因此,在使用代碼補全、功能推薦和其他 AI 驅動的特性時,絕對要杜絕到服務器的往返。
即使速度足夠快,AI 驅動的功能也必須無縫地融入到用戶的工作流中,而不是分散用戶的注意力。
例如,我們可以給用戶的代碼找 Bug。乍一看,這似乎是用戶可能會接受的功能,但要在正確的時間向用戶報告 Bug 是一個巨大的挑戰。當用戶正在埋頭寫代碼時提醒他們,只會分散他們的注意力,並可能導致他們禁用這個特性。我們必須抓住程序員已經完成了一大塊工作那一刻,在他們處於想要檢查代碼是否有問題的精神狀態下向他們報告 Bug。
或許,我們可以用一個 AI 算法來決定何時展示另一個 AI 算法的結果?
AI 正在進入軟件開發領域,就像它進入其他領域一樣,試圖模仿人類並增強人類的工作能力。
計算機現在可以寫代碼,但我們不認為這是一場行業變革。計算機寫代碼的能力不足以取代人類程序員。人類能夠思考複雜的軟件組件交互,這種思考能力是至關重要的,而 AI 還無法做到。
不過,有很多東西可以使用機器學習來實現小的改進,把這些小改進累積起來,可以大大提高軟件開發人員的工作效率。軟件開發工具公司正在迅速發展將 AI 解決方案產品化的能力,因此,我們預計在不久的將來會出現更多這樣的解決方案。
作者簡介:
Nikita Povarov 是 JetBrains 的數據分析和機器學習團隊負責人。他主要參與 ML 項目,在沒有 A/B 測試的情況下為公司決策開發分析流程。自 2012 年以來,他一直是 JetBrains 計算機科學中心的講師。2011 年至 2015 年,Nikita 在 Yandex 擔任數據分析師,專注於 A/B 測試系統。
原文鏈接:
https://www.infoq.com/articles/ai-for-software-developers/
點擊底部閱讀原文訪問 InfoQ 官網,獲取更多精彩內容!
從維護性工作到軟件開發革命,運維 15 年間的大逆轉
IE 瀏覽器已「死」,一個時代的終結
被捧上天的 Scrum 敏捷管理為何不受大廠歡迎了?
2022,我們該如何理解可觀測技術
點個在看少個 bug👇