編譯 | 蘇宓
出品 | CSDN(ID:CSDNnews)
“兩次 CPU 飆升的背后有個(gè)巧合,那就是——‘我們 CEO 登錄了賬號(hào)?!谑牵覀儼?CEO 的賬號(hào)給封了,繼續(xù)排查原因......”
聽起來像段子,但這真是 Sketch.dev 的工程師親口寫下的“事故總結(jié)”。而這一切的起因,只是因?yàn)橐欢斡?AI 生成的代碼。
Sketch.dev 是一家用 AI 輔助程序員寫代碼的開發(fā)平臺(tái),他們甚至用自己的工具開發(fā)自家產(chǎn)品。但在 7 月中旬,他們「栽」在了自己信任的 AI 手里。
系統(tǒng)突然卡頓、服務(wù)變慢、CPU 飆升,接連幾次“迷你宕機(jī)”之后,團(tuán)隊(duì)發(fā)現(xiàn):每次崩潰的起點(diǎn),都是 CEO 登錄系統(tǒng)。他們當(dāng)機(jī)立斷地封了 CEO 的賬號(hào),問題果然暫時(shí)消失了。
但后來經(jīng)過排查,問題不在 CEO,而在代碼。
對(duì)此,7 月 31 日,Sketch.dev工程師 Josh Bleecher Snyder 和 Sean McCullough 發(fā)布了一篇博客——《我們第一次因 LLM 生成代碼而宕機(jī)》,對(duì)整個(gè)事件進(jìn)行了回顧總結(jié)。這不是模型瞎寫代碼的問題,而是看起來沒問題的 AI 重構(gòu),把一個(gè)邏輯錯(cuò)誤埋進(jìn)了系統(tǒng)底層。
這次事故,成了團(tuán)隊(duì)第一次真正感受到:AI 編碼代理,也會(huì)帶來隱形的生產(chǎn)風(fēng)險(xiǎn)——不是“不會(huì)寫”,而是“寫得像對(duì)的”。
起因
時(shí)間回到 7 月 15 日,Sketch.dev 的工程團(tuán)隊(duì)發(fā)現(xiàn)自家網(wǎng)站開始出現(xiàn)一連串的小范圍宕機(jī)。
一開始的部署看起來很正常,但沒過多久,CPU 占用飆升,系統(tǒng)響應(yīng)開始嚴(yán)重卡頓。
后臺(tái)的性能分析工具顯示,是一些極其復(fù)雜的 SQL 查詢?cè)诏偪駡?zhí)行全表掃描,系統(tǒng)已經(jīng)被拖到快撐不住的臨界點(diǎn)。
為了解決這種情況,彼時(shí)Sketch.dev 的工程師覺得,無論如何,這些查詢都必須進(jìn)行優(yōu)化或徹底重寫。于是,團(tuán)隊(duì)修改了查詢邏輯并重新部署。沒想到同樣的情況再次發(fā)生:最初一切正常,之后又逐步滑向性能崩潰,陷入了惡性循環(huán)。
進(jìn)一步分析后,他們驚訝地發(fā)現(xiàn),兩次 CPU 飆升背后的“觸發(fā)器”竟然是:“我們 CEO 登錄了?!?/strong>
于是他們決定再次重啟部署清理狀態(tài),并順手永久封了 CEO 的賬號(hào),繼續(xù)追查問題。
雖然性能分析工具依然顯示是數(shù)據(jù)庫(kù)資源爭(zhēng)用的問題,但工程師們覺得,這個(gè)解釋已經(jīng)站不住腳了。
他們繼續(xù)往上追查調(diào)用棧,結(jié)果發(fā)現(xiàn)有一段平時(shí)幾乎不會(huì)執(zhí)行的代碼路徑,正是引發(fā)這些“數(shù)據(jù)庫(kù)過載查詢”的根源。而這段代碼——最近才剛被重構(gòu)過。
于是,他們果斷撤回了那次重構(gòu),重新部署了代碼,也把被封號(hào)的 CEO 解封,然后開始深入分析到底哪里出了問題。
直接原因初解析
根據(jù)Sketch.dev工程團(tuán)隊(duì)的介紹,其日常會(huì)使用自家 AI 平臺(tái)來開發(fā) Sketch 這款產(chǎn)品,而此次問題的根源在于一段由 LLM 生成、隨后經(jīng)人工審核的大規(guī)模代碼重構(gòu)。
這段代碼被從一個(gè)文件移動(dòng)到另一個(gè)文件中,而 Bug 就悄然藏在這個(gè)過程中。
詳細(xì)來看,重構(gòu)前的代碼如下:
for{
repos, repoResp, err := ghClient.Apps.ListUserRepos(ctx, *installation.ID, repoOpt)
iferr !=nil{
// Log error but continue with other installations
log.Printf("Error fetching repositories for installation %d: %v", *installation.ID, err)
break
}
// ...
}
重構(gòu)后的代碼:
for{
repos, repoResp, err := ghClient.ListUserRepos(ctx, *installation.ID, repoOpt)
iferr !=nil{
// Log error but continue with other installations
log.Printf("Error fetching repositories for installation %d: %v", *installation.ID, err)
continue
}
// ...
}
原本的break被改成了continue,錯(cuò)誤被“靜默”處理,直接導(dǎo)致死循環(huán)。
根本原因
說白了,這次宕機(jī)事故,其實(shí)源于一次代碼遷移時(shí)的一個(gè)細(xì)微變更。但因?yàn)檎未a整體都在遷移,這個(gè)小變動(dòng)就被“淹沒”在大量修改里,開發(fā)團(tuán)隊(duì)在代碼審核時(shí)沒能察覺。
該團(tuán)隊(duì)指出,這暴露出整個(gè)行業(yè)在“識(shí)別代碼小幅變更”這方面工具的不足。像 Git 這樣的主流工具,確實(shí)可以識(shí)別一個(gè)文件整體的“遷移+改動(dòng)”,但要是在同一個(gè)文件中某段代碼被改動(dòng)了位置又稍作修改,它就很難看出——技術(shù)上實(shí)現(xiàn)起來也確實(shí)不簡(jiǎn)單。
在實(shí)際開發(fā)中,這種情況并不少見:一大片紅綠 diff(即“新增/刪改”的代碼差異)中看起來大同小異,很容易漏掉真正重要的改動(dòng)。而這種錯(cuò)誤,并不是因?yàn)橛昧?AI 才出現(xiàn),哪怕是人類開發(fā)者也可能踩坑。
但問題在于:AI 更容易犯這種錯(cuò)。
人類開發(fā)者做重構(gòu)時(shí),往往是直接剪切原來的代碼,再粘貼到新位置,然后做有意識(shí)的修改。這個(gè)過程相對(duì)“閉環(huán)”,出錯(cuò)概率比較低。
然而,AI 編碼助手的邏輯則不同——它不會(huì)“剪切粘貼”,而是“先刪掉一段代碼,再重新寫一段”。本質(zhì)上,它是在嘗試“轉(zhuǎn)錄”舊的邏輯到新位置,稍有偏差就可能抄錯(cuò)。
而這次的 Bug,就屬于這種“轉(zhuǎn)錄錯(cuò)誤”的典型案例。
對(duì)此,Sketch.dev 團(tuán)隊(duì)也列舉了一個(gè)典型例子來說明這種轉(zhuǎn)錄錯(cuò)誤是如何發(fā)生的:
iferr != nil {
//Log error butcontinuewith other installations
log.Printf("Error fetching repositories for installation %d: %v", *installation.ID, err)
break
}
可以看到,上面代碼的注釋寫的是“but continue”,但實(shí)際的程序邏輯卻寫成了“中斷執(zhí)行”(break)。也就是說,注釋和代碼本身“打架”了。
這種錯(cuò)誤,是怎么發(fā)生的?該團(tuán)隊(duì)工程師分析后發(fā)現(xiàn),這是 AI 在生成代碼時(shí)兩種“判斷信號(hào)”發(fā)生了沖突:
一種是“轉(zhuǎn)錄信號(hào)”,也就是它試圖照搬舊代碼中的邏輯(這一層面它想用break);
另一種是“局部預(yù)測(cè)”,也就是它根據(jù)上下文猜測(cè)此時(shí)該寫什么(這一層面它認(rèn)為應(yīng)該用continue)。
很不幸,這次 AI 更相信自己的“直覺”——結(jié)果它選擇了continue,也就是錯(cuò)誤的那個(gè)選項(xiàng),從而引發(fā)了 Bug。
預(yù)防措施
為避免類似問題再次發(fā)生,Sketch.dev 研發(fā)團(tuán)隊(duì)對(duì)平臺(tái)的代理執(zhí)行環(huán)境進(jìn)行了改進(jìn),新增了剪貼板支持功能?,F(xiàn)在,AI 代理在修改文件時(shí)可以將代碼復(fù)制到剪貼板,并從中讀取內(nèi)容。
為了避免類似的錯(cuò)誤再次發(fā)生,Sketch.dev 研發(fā)團(tuán)隊(duì)給他們的 AI 編碼環(huán)境增加了“剪貼板”功能?,F(xiàn)在,AI 在修改代碼時(shí),可以像人一樣復(fù)制粘貼代碼,這樣可以盡量保持原樣不出錯(cuò)。
不過問題也來了——比如在像 Python 這樣非常依賴縮進(jìn)的語言里,粘貼過去的代碼縮進(jìn)可能不對(duì),所以他們還加了一個(gè)“自動(dòng)調(diào)整縮進(jìn)”的機(jī)制,確保粘貼后的代碼格式不會(huì)亂。未來他們還打算接入更智能的代碼格式工具(LSP),讓粘貼縮進(jìn)這件事更自動(dòng)化。
雖然這個(gè)新功能剛上線不久,但在一些更強(qiáng)大的 AI 模型上,初步效果還不錯(cuò)。
此外,該團(tuán)隊(duì)也呼吁:Git 能支持更智能的“跨區(qū)域改動(dòng)檢測(cè)”功能。這個(gè)技術(shù)本來就有用,但在現(xiàn)在這個(gè)“越來越多代碼由 AI 生成”的時(shí)代,如果 Git 能識(shí)別某段代碼從 A 文件移動(dòng)到 B 文件,還能看出其中有沒有被悄悄改動(dòng),將會(huì)極大提升發(fā)現(xiàn)錯(cuò)誤的能力。
AI 編程失誤引發(fā)問題不止一次兩次了
時(shí)下,Sketch.dev 的經(jīng)歷,也引發(fā)了廣泛關(guān)注。因?yàn)?AI 生成的代碼導(dǎo)致網(wǎng)站宕機(jī),工程師卻在第一時(shí)間將“矛頭”首先對(duì)準(zhǔn)自家 CEO,還直接封禁了他的賬戶。雖然事后澄清是誤會(huì),但仍引發(fā)大量網(wǎng)友吐槽:
“CEO 何其的冤枉,他就只是登錄時(shí)間碰巧和故障撞上了,然后你們居然把他封號(hào)了?”
但這場(chǎng)“烏龍”只是當(dāng)下 AI 編程困境的縮影,類似的情況早已不是孤例。
像不久前我們報(bào)道的——SaaStr 創(chuàng)始人 Jason Lemkin 就曾因使用:AI 不僅多次無視指令、篡改測(cè)試數(shù)據(jù),甚至在他反復(fù)強(qiáng)調(diào)“不要?jiǎng)泳€上數(shù)據(jù)庫(kù)”的情況下,仍然一鍵刪庫(kù)。氣得他發(fā)文吐槽:
“我提醒了它整整 11 次,但沒用……我現(xiàn)在真的開始擔(dān)心 AI 失控了?!?/p>
無獨(dú)有偶,Google 的 Gemini CLI 工具也出過同樣的事故。一位產(chǎn)品經(jīng)理嘗試用它整理文件夾,結(jié)果 AI 誤把文件移到了一個(gè)根本不存在的目錄,數(shù)據(jù)直接清空。出事之后,Gemini CLI 工具還自動(dòng)“認(rèn)錯(cuò)”道:
“我徹底而災(zāi)難性地失敗了。命令審查顯示我嚴(yán)重不稱職?!?/blockquote>同樣就在兩天前,更有開發(fā)者在 Reddit 論壇中發(fā)帖警告稱:“Gemini CLI 刪除了我的整個(gè) Windows 系統(tǒng)”,讓人覺得 AI 現(xiàn)在在幫助人類處理技術(shù)問題時(shí)逐漸離譜。
這名開發(fā)者寫道:
我分享這個(gè)經(jīng)歷,是想提醒所有使用 Gemini CLI 或類似工具、涉及文件系統(tǒng)操作的用戶:一定要小心。
當(dāng)時(shí)我在 Windows 上使用 Gemini CLI(從 Git Bash 啟動(dòng),在項(xiàng)目根目錄),我讓它把我的項(xiàng)目用另一種技術(shù)重寫,并新建一個(gè)分支。本來它應(yīng)該只刪除當(dāng)前分支下的文件,但結(jié)果卻執(zhí)行了一個(gè)破壞性的 rm -rf 命令。
盡管有些刪除操作因?yàn)闄?quán)限問題(比如C:\等系統(tǒng)文件夾)失敗了,但它仍然把我整個(gè) C 盤的大量?jī)?nèi)容都刪掉了。
任務(wù)結(jié)束后,我的系統(tǒng)幾乎徹底崩了:
程序無法啟動(dòng)
資源管理器打不開
很多關(guān)鍵文件和應(yīng)用全都不見了
幸運(yùn)的是,我通過系統(tǒng)還原(rstrui)挽回了大約 90% 的系統(tǒng)數(shù)據(jù),但依然有不少程序丟失或損壞。
補(bǔ)充說明:我還貼出了日志證據(jù),包括:
向 Gemini CLI 發(fā)出的提示內(nèi)容,其中有確認(rèn)是否可以刪除當(dāng)前分支文件(但我沒法找回 Gemini 返回的確認(rèn)消息,因?yàn)槲沂怯?Gmail 登錄的,不是 API key)
Git 日志:確認(rèn)我在新建分支上操作,隨后文件被刪除
renderer.log:記錄了刪除文件的操作
filewatcher.log:進(jìn)一步確認(rèn)文件被刪除
系統(tǒng)還原日志
使用 Wise Data Recovery 工具識(shí)別出的丟失文件
這些問題背后,其實(shí)都是同一種現(xiàn)象在作祟:AI 模型有時(shí)候并不真正“理解”代碼,這種方式往往會(huì)產(chǎn)生聽起來“像是真的”但實(shí)際上完全錯(cuò)誤的結(jié)果。
在中,66% 的開發(fā)者就表示,他們經(jīng)常遇到 AI 輸出“差一點(diǎn)就對(duì)”的答案,而調(diào)試這些“似是而非”的代碼反而更花時(shí)間,45% 的人對(duì)此深有同感。
相比之下,真正對(duì) AI 工具“完全放心”的人寥寥無幾——只有 3% 的受訪者表示“高度信任”,而明確“不信”的人更多,高達(dá) 46%。
經(jīng)驗(yàn)越豐富的程序員,態(tài)度往往也越謹(jǐn)慎:只有 2.5% 的資深開發(fā)者“高度信任”AI,反倒有 20.7% 明確表示“高度不信任”。
正如有網(wǎng)友所說:“寫代碼變成了喂提示詞 + 修爛攤子,AI 編程的未來也許值得期待,但現(xiàn)在還遠(yuǎn)沒到可以閉眼上產(chǎn)線的階段?!?/p>
對(duì)此,你怎么看?
參考:
https://sketch.dev/blog/our-first-outage-from-llm-written-code
https://www.reddit.com/r/GeminiAI/comments/1md2quz/warning_gemini_cli_deleted_my_entire_windows/
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.