AI編程輔助 | 基于代碼生成模型的實(shí)踐 精華
一、編程輔助例子
GitHub Copilot[1]基于OpenAI的Codex[2]模型(GPT-3[3]的后代)實(shí)現(xiàn),可以在代碼編寫的時(shí)候?qū)崟r(shí)地提供代碼補(bǔ)全建議和注釋,并且在多個(gè)編輯器的插件市場(chǎng)都可以下載使用。
不管是從Copilot官網(wǎng)上的例子,還是在互聯(lián)網(wǎng)上搜索關(guān)于Copilot的使用案例,你都可以發(fā)現(xiàn)它比一般的代碼補(bǔ)全工具更為先進(jìn)和靈活,它不僅能補(bǔ)全代碼,更能創(chuàng)造代碼,通過(guò)理解使用者簡(jiǎn)單的自然語(yǔ)言指令,它能夠按照這些指令直接構(gòu)建代碼片段,并且正確率超過(guò)4成。
圖1 Copilot示例-注釋生成代碼
另外在代碼補(bǔ)全功能上Copilot每次可以提供多個(gè)建議,你可以從多個(gè)候選項(xiàng)中選擇合適的代碼片段進(jìn)行補(bǔ)全。
圖2 Copilot示例-代碼補(bǔ)全
拋開上面這些較為“先進(jìn)”的功能,Copilot是否能在日常工作中真正地幫助程序員提升工作效率呢?從筆者使用的經(jīng)驗(yàn)上來(lái)說(shuō),Copilot最大的作用在于可以幫我們解決掉大量重復(fù)的、枯燥乏味的代碼編寫工作,而且越是這樣重復(fù)的代碼Copilot補(bǔ)全預(yù)測(cè)的越精確,這樣一來(lái)你大部分的精力和時(shí)間只需要花在最核心最富有創(chuàng)造力的部分上,而那些臟活累活就由“AI”幫你完成,程序員的工作效率和身心健康都能得到極大地提升。下面是一些Copilot在實(shí)際業(yè)務(wù)場(chǎng)景中使用時(shí)較為出彩的例子:
- 程序日志記錄:比如在Java或者Golang中使用日志組件打印一些調(diào)試信息或者記錄一些變量信息,每次使用時(shí)都需要寫一長(zhǎng)串代碼,而使用了Copilot后你剛打出logging,后面的代碼就自動(dòng)補(bǔ)全了,你需要的變量信息、日志的級(jí)別、格式化字符串都已經(jīng)生成完畢。
- 條件判斷&循環(huán)體:判斷某個(gè)數(shù)值變量是否在一個(gè)范圍中或者各種條件判斷,比如Python中寫了個(gè)for循環(huán)前面又有個(gè)數(shù)組沒(méi)用過(guò),就立馬幫你補(bǔ)全上for item in items。
- 模板代碼:例如 React 中,每次用 useState 都要寫一行模板性的初始化代碼。如果第一個(gè)變量名是 someVariable,第二個(gè)一定是 setSomeVariable。這種根本不需要過(guò)腦子的東西,最適合 Copilot 補(bǔ)全了。
二、背后的技術(shù)
1.Codex模型
Copilot工具背后真正的基石是Codex,是一個(gè)基于 GPT 的語(yǔ)言模型,在閱讀了Codex原始論文后,筆者發(fā)現(xiàn)它是GPT-3使用代碼文本數(shù)據(jù)進(jìn)行了Fine-Tuning之后的產(chǎn)物,在模型的結(jié)構(gòu)上Codex沒(méi)有做任何創(chuàng)新的地方。
這里是比較有意思的地方,因?yàn)镚PT系列模型的賣點(diǎn)就是從來(lái)不做微調(diào),而且GPT3跟 GPT本質(zhì)上差別也不大,所以Codex創(chuàng)新不在于模型的本身,而是在于實(shí)際的應(yīng)用上面,這時(shí)候去使用微調(diào)這樣的方法無(wú)疑性價(jià)比更高,也是合理的。
另外的創(chuàng)新點(diǎn)在于他提出了一個(gè)HumanEval的數(shù)據(jù)集來(lái)衡量模型的好壞,在這個(gè)數(shù)據(jù)集上Codex能夠解決28.8%的問(wèn)題,相比之下如果直接使用GPT-3則解決不了任何問(wèn)題。另外如果允許sampling的話(模型跑100遍,得到100個(gè)不一樣的結(jié)果,只要其中一個(gè)正確就算解決問(wèn)題)能提升到70.2%的成功率??偠灾瓹odex沒(méi)有做特別大的改動(dòng),它提出了一個(gè)問(wèn)題,然后把GPT-3在大量代碼組成的數(shù)據(jù)集上微調(diào)了一下并嘗試解決這個(gè)問(wèn)題,最后使用了一個(gè)全新的評(píng)測(cè)數(shù)據(jù)集來(lái)評(píng)判代碼生成質(zhì)量的好壞。
論文中的重點(diǎn)主要聚焦于他整體的評(píng)估框架,因?yàn)橥ㄟ^(guò)語(yǔ)言模型來(lái)生成復(fù)雜代碼這個(gè)問(wèn)題相對(duì)來(lái)說(shuō)還比較新穎,在GPT-3剛問(wèn)世的的時(shí)候OpenAI也給大家做過(guò)展示,GPT-3可以生成一些簡(jiǎn)單的代碼片段,但是如果用來(lái)生成較為復(fù)雜的代碼時(shí)效果很差,畢竟 GPT-3的訓(xùn)練數(shù)據(jù)中沒(méi)有包含特別多的代碼,因此一個(gè)Code Fine-Tuning數(shù)據(jù)集就呼之欲出了,根據(jù)論文介紹,Codex在2020年5月從Github 的 54,000,000 個(gè)公開代碼倉(cāng)上收集了數(shù)據(jù),在經(jīng)過(guò)過(guò)濾后,最終的數(shù)據(jù)集大小為159GB。
那么在評(píng)測(cè)數(shù)據(jù)集上采用哪種指標(biāo)來(lái)判斷模型的好壞呢?我們知道文本生成任務(wù)的輸出為一個(gè)文本序列,比如說(shuō)機(jī)器翻譯經(jīng)常用的一個(gè)評(píng)估方法叫做 BLEU score,BLUE這個(gè)分?jǐn)?shù)計(jì)算的是生成的序列和正確答案序列在一些子序列上的相似度,是一個(gè)模糊的匹配過(guò)程,因此在代碼生成上面BLUE分?jǐn)?shù)會(huì)存在一個(gè)大問(wèn)題——就算你在子片段上跟真實(shí)的代碼非常相近,但是很有可能你生成的代碼甚至連編譯都無(wú)法通過(guò)。最終Codex使用的是一個(gè)pass@k 的分?jǐn)?shù),其含義表示生成 k 個(gè)不同的結(jié)果,其中只要有一個(gè)結(jié)果能夠通過(guò)所有測(cè)試用例的話那么就認(rèn)為正確。
最后是HumanEval這個(gè)評(píng)測(cè)數(shù)據(jù)集,數(shù)據(jù)集中包含164個(gè)編程的問(wèn)題,主要涉及到語(yǔ)言的理解、算法能力、簡(jiǎn)單的數(shù)學(xué)推理以及一些簡(jiǎn)單的編程面試問(wèn)題,數(shù)據(jù)量不是那么大,其中每個(gè)編程問(wèn)題包括函數(shù)頭、docstrings、函數(shù)體和幾個(gè)單元測(cè)試用例,目前該數(shù)據(jù)集已經(jīng)開源→https://github.com/openai/human-eval。
2.模型推理優(yōu)化
基于預(yù)訓(xùn)練模型實(shí)現(xiàn)的工具應(yīng)用在實(shí)際業(yè)務(wù)場(chǎng)景中有一個(gè)不容忽視的問(wèn)題,那就是模型的推理性能是否能夠滿足需求,而Codex實(shí)際上就是GPT模型,在推理過(guò)程中需要逐字生成代碼,因此如果需要實(shí)時(shí)地提供補(bǔ)全建議則對(duì)模型的推理性能有很高的要求。
圖3 模型加速手段
上圖中包含了一些常用的模型加速手段,在論文中OpenAI并沒(méi)有披露針對(duì)模型部署方面的優(yōu)化,但是在后面我們實(shí)際嘗試去私有化部署代碼生成模型時(shí)還是應(yīng)用了多種模型加速方式,期望讓使用感受能夠接近Github Copilot。
3.組裝你自己的AI編程助手
在實(shí)際私有化部署我們的“AI輔助”前先看看我們手上有哪些資源:
?開源模型:雖然我們無(wú)法直接基于Codex部署私有化模型服務(wù),但是在Hugging Face的Model Hub社區(qū)上與代碼生成相關(guān)的開源模型仍然有許多可供我們選擇,更讓我們意外的是其中的開源模型CodeGen[4]甚至在HumanEval評(píng)測(cè)集上擊敗了Codex。
計(jì)算資源:只要不使用參數(shù)量最大的CodeGen-16B,服務(wù)器上的T4顯卡就有足夠的顯存來(lái)進(jìn)行推理,另外我們會(huì)測(cè)試INT-8量化下使用CPU部署服務(wù)的表現(xiàn)如何。
部署方式:在模型的推理服務(wù)器上我們使用了Triton Inference Server[5],因?yàn)榭梢院芎玫倪m配 FasterTransformer[6],另外也能搭配各種加速手段。
插件化方式:好消息是Github Copilot插件中的高級(jí)配置有調(diào)試選項(xiàng),可以直接配置模型服務(wù)的地址,因此當(dāng)啟用該選項(xiàng)時(shí)可以將其設(shè)置為我們自己的模型服務(wù)地址,另外在插件市場(chǎng)同樣有一些類似于Copilot的插件,并且可以配置本地的代碼生成服務(wù)地址。
接下來(lái)就是部署我們自己的代碼生成服務(wù)了,在使用GPU服務(wù)器進(jìn)行部署時(shí)我們選擇了CodeGen-2B模型支持多語(yǔ)言模式的版本:
圖4 CodeGen系列模型
然后使用Triton Inference Server以及 FasterTransformer backend來(lái)啟動(dòng)我們的模型服務(wù):
圖5 模型服務(wù)
修改Copilot的插件的配置選項(xiàng):
圖6 配置選項(xiàng)參考
最終讓我們看一下代碼生成的效果,就讓AI解一下斐波那契數(shù)列吧:
圖7 代碼生成效果
在使用GPU部署代碼生成模型服務(wù)的情況下,從代碼生成的速度上來(lái)說(shuō)并已經(jīng)完全不亞于于Github Copilot的速度了,通常來(lái)說(shuō)服務(wù)器上的GPU計(jì)算資源較為寶貴,但是卻有許多空閑的CPU資源,因此我們需要測(cè)試CPU部署時(shí)代碼的生成速度是否能夠滿足日常需求,首先是我們期望模型生成的代碼片段,這是Bert[7]模型定義中Embedding的一部分,實(shí)際測(cè)試時(shí)我們只鍵入Class名稱,藍(lán)色的注釋,然后讓模型來(lái)生成接下來(lái)的代碼片段:
圖8 Bert代碼片段
我們?cè)囉昧薈odeGen的多個(gè)模型,并且記錄在不同情況下他們返回結(jié)果的延時(shí):
模型 | 生成用時(shí)(ONNX+FP16) | 生成用時(shí)(TRT+INT8) |
codegen-6B-multi | 846s | 293s |
codegen-2B-multi | 79s | 18s |
codegen-350M-multi | 9s | 4s |
服務(wù)器CPU:Intel(R) Xeon(R) Gold 6240 CPU @ 2.60GHz |
從結(jié)果來(lái)看,使用CPU部署后在經(jīng)過(guò)INT8量化技術(shù)的加持下,當(dāng)我們使用參數(shù)量最小的代碼生成模型,至少在速度上可以獲得還不錯(cuò)的體驗(yàn)。
四、總結(jié)與思考
從本次探究Github Copilot背后的技術(shù)以及進(jìn)行簡(jiǎn)單的代碼生成實(shí)踐來(lái)看,基于GPT系列模型在文本生成這個(gè)領(lǐng)域上的確有著許多應(yīng)用落地的可能,然而代碼生成這一技術(shù)并不是“無(wú)害”的,首先是在模型訓(xùn)練過(guò)程中使用的“開源代碼數(shù)據(jù)集”中包含許多個(gè)人數(shù)據(jù),在筆者使用過(guò)程中發(fā)現(xiàn),如果涉及到文件路徑的鍵入,經(jīng)常會(huì)出現(xiàn)一些帶用戶名的路徑補(bǔ)全建議,其直接使用他人的開源代碼來(lái)作為訓(xùn)練數(shù)據(jù)也在社區(qū)上引起了廣泛的爭(zhēng)議,甚至有許多開源社區(qū)的作者期望制定一個(gè)新的開源協(xié)議,限制他們的開源庫(kù)不被用來(lái)作為深度學(xué)習(xí)的數(shù)據(jù)。另外經(jīng)過(guò)Copilot生成的代碼質(zhì)量難以把控,還是會(huì)存在“埋坑”的可能性,很有可能在某天當(dāng)你debug一個(gè)問(wèn)題時(shí)卻完全想不起來(lái)自己為什么會(huì)寫下這一段代碼,直到最后才意識(shí)到這是AI幫你生成的。
當(dāng)然我們并不會(huì)直接放棄這樣一個(gè)可以幫你干“臟活累活”的工具,畢竟如果只是作為一個(gè)“副駕駛”,時(shí)不時(shí)對(duì)你進(jìn)行提醒,而不是代替你開車,它還是可以做的非常好的。另外就像開頭所說(shuō)的,其實(shí)是隨著Github Copilot的收費(fèi)才促成了筆者的這一次實(shí)踐,許多社交媒體上的程序員都聲稱他們已經(jīng)離不開Copilot了。而目前來(lái)看我們已經(jīng)有了較為完善的私有化部署方式,還有開源模型CodeGen可供使用,作為一個(gè)在日常開發(fā)工作中的私有化工具已經(jīng)足夠好了。不過(guò)這還不夠,如果可以使用完全開源并且脫敏的代碼數(shù)據(jù),并按照合適的模型參數(shù)量來(lái)定制化的訓(xùn)練我們的模型??......總之,敬請(qǐng)期待吧??。
參考文獻(xiàn)
[1] 代碼生成工具GitHub Copilot:https://copilot.github.com/
[2] 代碼生成模型OpenAI-codex:https://openai.com/blog/openai-codex/
[3] https://gpt3demo.com
[4] 代碼生成模型CodeGen:https://github.com/salesforce/CodeGen.com/
[5] NVIDIA's Triton Inference Server:https://developer.nvidia.com/nvidia-triton-inference-server
[6] NVIDIA's Triton FasterTransformer:https://github.com/NVIDIA/FasterTransformer
[7] Devlin J, Chang M W, Lee K, et al. Bert: Pre-training of deep bidirectional transformers for language understanding[J]. arXiv preprint arXiv:1810.04805, 2018.
[8] FauxPilot - an open-source GitHub Copilot server:https://github.com/moyix/fauxpilot
[9] 盤點(diǎn)開源“Copilot”,do it yourself:https://lowin.li/2022/06/27/pan-dian-kai-yuan-copilot/
本文轉(zhuǎn)載自 ??AI遇見云??,作者: 張宇博
