大促備戰(zhàn)中的代碼評(píng)審困境與破局
雙十一大促是系統(tǒng)穩(wěn)定性的終極“大考”。為規(guī)避上線風(fēng)險(xiǎn),技術(shù)側(cè)會(huì)啟動(dòng)系統(tǒng)封板管控,主動(dòng)將非緊急需求的發(fā)布窗口前置。這一舉措在保障系統(tǒng)穩(wěn)定性的同時(shí),也必然導(dǎo)致研發(fā)需求的前置與集中,使得封板前的代碼評(píng)審任務(wù)量顯著增加。我們面臨著一個(gè)嚴(yán)峻的“量與質(zhì)”的挑戰(zhàn):
如何在時(shí)間緊、任務(wù)重的雙重壓力下,確保代碼評(píng)審的效率與質(zhì)量,從而前置發(fā)現(xiàn)潛在風(fēng)險(xiǎn),有效攔截線上BUG?
傳統(tǒng)的代碼評(píng)審模式在此場(chǎng)景下效率低、質(zhì)量差(風(fēng)險(xiǎn)遺漏的可能性高),而現(xiàn)有的AI輔助工具又因誤報(bào)率高而陷入尷尬:產(chǎn)生的多數(shù)評(píng)審意見(jiàn)并無(wú)實(shí)質(zhì)幫助,工程師仍需花費(fèi)大量時(shí)間進(jìn)行判斷與篩選。
正是在此背景下,【供應(yīng)鏈技術(shù)部-商家導(dǎo)入研發(fā)組】在AI代碼評(píng)審方面進(jìn)行了一些探索,嘗試將知識(shí)工程代碼知識(shí)檢索能力與AutoBots(已更名為:JoyAgent)知識(shí)庫(kù)檢索能力相結(jié)合,構(gòu)建了一套代碼評(píng)審系統(tǒng)。這套雙RAG架構(gòu)為我們的代碼評(píng)審工作提供了一些新思路,在此分享出來(lái),希望與各位同行交流探討,共同進(jìn)步。
現(xiàn)有技術(shù)方案的局限性
技術(shù)1:基于流水線的AI代碼評(píng)審方案
核心技術(shù)路徑: 在通過(guò)公共流程(Webhook觸發(fā)、解析MR、獲取Diff)得到代碼變更內(nèi)容后,該方案的核心處理流程如下:
1.文件類型過(guò)濾:僅保留.java、.yaml和.md文件進(jìn)行后續(xù)分析,并明確優(yōu)先級(jí)的處理順序。
2.上下文截?cái)?/strong>:為避免觸及大模型上下文窗口上限,采用了一種基于固定行數(shù)的上下文截?cái)嗖呗?。該策略僅截取代碼變更處附近預(yù)設(shè)行數(shù)(如10行)的文本內(nèi)容。
3.Prompt驅(qū)動(dòng)評(píng)審:將經(jīng)過(guò)過(guò)濾和截?cái)嗪蟮拇a片段,與預(yù)設(shè)的評(píng)審規(guī)則Prompt組合,發(fā)送給通用大語(yǔ)言模型。
4.輸出評(píng)審意見(jiàn):解析大模型的返回結(jié)果,通過(guò)coding平臺(tái)API將評(píng)審結(jié)果添加到MR中。
核心問(wèn)題識(shí)別:
1.全局上下文缺失:其采用的“固定行數(shù)截?cái)唷辈呗允菍?dǎo)致問(wèn)題的根本原因之一。這使得評(píng)審?fù)耆珕适Я隧?xiàng)目架構(gòu)、模塊依賴和完整業(yè)務(wù)邏輯的視野,如同“管中窺豹”,評(píng)審深度和準(zhǔn)確性受到嚴(yán)重制約。
2.提示詞天花板:所有評(píng)審規(guī)則與知識(shí)硬編碼于Prompt中,規(guī)則膨脹后極易觸及模型上下文長(zhǎng)度上限,可維護(hù)性與擴(kuò)展性差。
3.知識(shí)無(wú)法沉淀:效果提升完全依賴于“更換更強(qiáng)的基礎(chǔ)模型”與“調(diào)整Prompt”,自身缺乏可持續(xù)積累、沉淀和復(fù)用領(lǐng)域知識(shí)的機(jī)制。
技術(shù)2:基于JoyAgent知識(shí)庫(kù)的RAG代碼評(píng)審
核心技術(shù)路徑: 在通過(guò)公共流程獲取代碼差異后,該方案的核心流程如下:
1.知識(shí)歸納:將格式化后的Diff內(nèi)容發(fā)送給JoyAgent,由LLM智能體對(duì)其進(jìn)行初步的“知識(shí)歸納”,以理解此次變更的核心意圖。
2.規(guī)則檢索:基于歸納出的知識(shí),通過(guò)RAG機(jī)制從自定義知識(shí)庫(kù)中召回相關(guān)的代碼評(píng)審規(guī)則。此知識(shí)庫(kù)支持在線文檔(Joyspace)、離線文檔(PDF/Word)等多種格式。該方案的核心靈活性在于其“自定義知識(shí)庫(kù)綁定”機(jī)制。接入者可以在JoyAgent平臺(tái)上自定義智能體,通過(guò)工作流綁定自定義知識(shí)庫(kù)。這使得在召回評(píng)審規(guī)則時(shí),系統(tǒng)能動(dòng)態(tài)地查找并應(yīng)用接入者自定義的評(píng)審規(guī)則,從而實(shí)現(xiàn)了無(wú)需修改Prompt即可定制評(píng)審規(guī)則的能力。
3.行級(jí)評(píng)審:JoyAgent將代碼Diff與召回的具體規(guī)則相結(jié)合,再次調(diào)用LLM進(jìn)行精確評(píng)審。利用Git Diff信息中包含的代碼行信息,能夠?qū)⒃u(píng)審意見(jiàn)精準(zhǔn)關(guān)聯(lián)到具體的代碼行。
4.輸出結(jié)果:直接使用JoyAgent的輸出結(jié)果,通過(guò)coding平臺(tái)API將評(píng)審結(jié)果添加到MR中。
核心問(wèn)題識(shí)別:
1.知識(shí)歸納失真:核心問(wèn)題源于其“知識(shí)歸納”步驟。該步驟依賴底層大模型對(duì)Code Diff進(jìn)行總結(jié),此過(guò)程不穩(wěn)定,經(jīng)常遺漏或曲解原始代碼變更的關(guān)鍵上下文,導(dǎo)致后續(xù)流程建立在一個(gè)不完整或失真的信息基礎(chǔ)之上。
2.檢索與生成聯(lián)動(dòng)失效:基于失真的知識(shí)歸納結(jié)果進(jìn)行RAG檢索,導(dǎo)致召回的規(guī)則與真實(shí)代碼場(chǎng)景匹配度低。此外,檢索結(jié)果未經(jīng)有效的重排序,直接與不完整的代碼上下文一并送入大模型,這使得模型缺乏進(jìn)行準(zhǔn)確判斷的可靠依據(jù),最終必然生成大量不可靠甚至錯(cuò)誤的評(píng)審意見(jiàn)。
從線上問(wèn)題到技術(shù)突破
問(wèn)題1:三方系統(tǒng)空值處理異常
示例:
// 問(wèn)題代碼:三方系統(tǒng)地址編碼字段處理
request.setAddressCode(String.valueOf(address.getCode()));
// 當(dāng)address.getCode()為null時(shí),String.valueOf(null)返回"null"字符串
// 導(dǎo)致三方系統(tǒng)Integer.parseInt("null")拋出NumberFormatException
技術(shù)1的問(wèn)題:
理論上,可以通過(guò)在Prompt中硬編碼“三方接口地址編碼須為數(shù)字類型字符串” 的規(guī)則來(lái)識(shí)別此問(wèn)題。然而,隨著業(yè)務(wù)場(chǎng)景增多,所有規(guī)則都被擠壓在有限的上下文窗口內(nèi)競(jìng)爭(zhēng)。當(dāng)代碼變更觸發(fā)自動(dòng)壓縮(如截?cái)嘀?0行)時(shí),被保留的上下文具有極大的隨機(jī)性,與當(dāng)前評(píng)審強(qiáng)相關(guān)的評(píng)審規(guī)則很可能被其他無(wú)關(guān)規(guī)則擠掉或因自動(dòng)壓縮而被截掉,導(dǎo)致其無(wú)法被穩(wěn)定觸發(fā),從而漏報(bào)。
技術(shù)2的問(wèn)題:
該方案雖然理論上能夠通過(guò)知識(shí)庫(kù)檢索到相關(guān)規(guī)則,但其不穩(wěn)定的知識(shí)歸納過(guò)程導(dǎo)致代碼上下文的理解時(shí)好時(shí)壞,使得規(guī)則檢索的準(zhǔn)確性波動(dòng)較大。同時(shí),未對(duì)檢索結(jié)果進(jìn)行重排序,進(jìn)一步放大了這種不確定性。最終,由于缺乏穩(wěn)定、可靠的上下文支撐,系統(tǒng)無(wú)法持續(xù)、準(zhǔn)確地識(shí)別此類問(wèn)題,其評(píng)審結(jié)果表現(xiàn)出顯著的隨機(jī)性。
問(wèn)題2:EDI項(xiàng)目中的語(yǔ)法錯(cuò)誤
示例:
!-- 錯(cuò)誤:使用變量而非字面常量 --?>
!-- 正確應(yīng)使用字面值: -->
EDI平臺(tái)介紹:
EDI(電子數(shù)據(jù)交換)是用來(lái)解決京東物流與多樣化商家系統(tǒng)間的對(duì)接難題的技術(shù),其關(guān)鍵功能包括協(xié)議轉(zhuǎn)換、數(shù)據(jù)格式轉(zhuǎn)換、數(shù)據(jù)校驗(yàn)和流程編排。這意味著EDI配置文件必須嚴(yán)格遵守預(yù)定義的語(yǔ)法和標(biāo)準(zhǔn),任何偏差都可能導(dǎo)致平臺(tái)的核心轉(zhuǎn)換與校驗(yàn)功能失效。
技術(shù)1的問(wèn)題:
由于其缺乏對(duì)EDI配置語(yǔ)法與規(guī)范的領(lǐng)域知識(shí),如果自定義規(guī)則,會(huì)遇到問(wèn)題1一樣的提示詞天花板和上下文截?cái)嗟膯?wèn)題。
技術(shù)2的問(wèn)題:
除了上面提到的知識(shí)歸納過(guò)程的不穩(wěn)定問(wèn)題,技術(shù)2也面臨一個(gè)更前置的的挑戰(zhàn):它缺乏對(duì)項(xiàng)目身份的感知能力。系統(tǒng)在處理一個(gè)XML配置文件時(shí),無(wú)法自動(dòng)識(shí)別它隸屬于“EDI項(xiàng)目”而非普通Java應(yīng)用。因此,在后續(xù)的RAG檢索過(guò)程中,它極有可能使用通用的Java代碼評(píng)審規(guī)則,而無(wú)法精準(zhǔn)命中“EDI專用配置規(guī)范”這一關(guān)鍵上下文,導(dǎo)致檢索方向錯(cuò)誤,最終無(wú)法識(shí)別出必須使用字面常量這一特定于EDI領(lǐng)域的合規(guī)性要求。
解決方案:雙RAG架構(gòu)
?

?
?
1. 識(shí)別項(xiàng)目類型
?特征識(shí)別:基于文件擴(kuò)展名(.flow, .dt)進(jìn)行精準(zhǔn)判斷。
?優(yōu)先級(jí)設(shè)定:EDI項(xiàng)目識(shí)別優(yōu)先于普通JAVA項(xiàng)目,確保領(lǐng)域特殊性得到優(yōu)先處理。
?策略影響:項(xiàng)目類型直接決定后續(xù)評(píng)審規(guī)則的選擇與RAG知識(shí)庫(kù)的檢索策略,從源頭保障了評(píng)審的針對(duì)性。
2. 代碼分塊處理
2.1 Token估算算法
由于我們使用的底層大模型是JoyAI,并沒(méi)有公開tokenizer的細(xì)節(jié),根據(jù)官網(wǎng)文檔提供的token計(jì)算API: http://api.chatrhino.jd.com/api/v1/tokenizer/estimate-token-count
測(cè)試了幾組數(shù)據(jù):
| 測(cè)試文本 | 字符長(zhǎng)度 | 實(shí)際Token數(shù) | 內(nèi)容Token增量 |
|---|---|---|---|
| 空字符串 | 0 | 63 | 0 |
| "a" | 1 | 64 | +1 |
| "hello" | 5 | 64 | +1 |
| "code" | 4 | 64 | +1 |
| "hello world" | 11 | 65 | +2 |
| "測(cè)試" | 2 | 64 | +1 |
| "編程編程" | 4 | 65 | +2 |
| "測(cè)試測(cè)試測(cè)試測(cè)試測(cè)試" | 10 | 68 | +5 |
| "hello世界" | 7 | 65 | +2 |
| "programming代碼" | 13 | 66 | +3 |
| 重復(fù)"programming代碼"3次 | 39 | 72 | +9 |
推導(dǎo)過(guò)程
通過(guò)分析測(cè)試數(shù)據(jù),我們發(fā)現(xiàn)了以下關(guān)鍵規(guī)律:
1.基礎(chǔ)系統(tǒng)開銷:所有請(qǐng)求都有63 tokens的固定開銷
2.英文單詞分級(jí):
?1-5字符單詞 = 1 token("a"、"hello"、"code")
?6-10字符單詞 ≈ 2 tokens(推測(cè)值)
?11+字符單詞 = 3 tokens("programming")
3.中文分詞規(guī)則:每2個(gè)中文字符 = 1 token
4.空格處理:空格作為分隔符,不增加額外token
5.混合內(nèi)容:按字符類型分段計(jì)算后求和
基于上述規(guī)律,我們構(gòu)建了以下估算公式:
總Tokens = 63 + ∑(單詞token)
單詞token計(jì)算:
- 單字符單詞: 1 token
- 英文單詞(≤5字符): 1 token
- 英文單詞(6-10字符): 2 tokens
- 英文單詞(≥11字符): 3 tokens
- 中文文本: (字符數(shù) + 1) / 2 tokens
- 混合內(nèi)容: 分段計(jì)算后求和
2.2 分塊閾值與安全設(shè)計(jì)
?觸發(fā)閾值:當(dāng)預(yù)估Token數(shù) > 100,000時(shí),自動(dòng)觸發(fā)分塊處理流程。
?JoyAI的上下文窗口是128K,由于JoyAI沒(méi)說(shuō)明1K是1024還是1000,保守估計(jì)使用1000
?128K = 128000,為了避免超過(guò)上下文窗口,留個(gè)富余量,使用80%,12800*0.8=102400 ≈100000
?

?
?
?單塊容量:設(shè)定 MAX_TOKENS_PER_CHUNK = 60000,為模型輸出及上下文預(yù)留40%的安全余量。
?設(shè)計(jì)理念:通過(guò)嚴(yán)格的容量控制,確保單次處理負(fù)載均在模型窗口的安全范圍內(nèi)。
2.3 智能分塊策略
系統(tǒng)采用兩級(jí)分塊策略,確保代碼語(yǔ)義的完整性:
2.3.1 文件級(jí)分割
通過(guò)git diff指令識(shí)別文件邊界,確保單個(gè)文件的代碼完整性,避免跨文件分割。
Pattern.compile("diff --git a/(.+?) b/(.+?)n")
2.3.2 代碼結(jié)構(gòu)感知分割
利用方法簽名模式識(shí)別代碼結(jié)構(gòu)邊界:
Pattern methodPattern = Pattern.compile(
"([+-]\s*((public|private|protected)\s+)?(\w+\s+)?\w+\s*\([^)]*\)\s*\{)",Pattern.MULTILINE);
在方法或類的自然邊界處進(jìn)行分割,最大限度保持代碼塊的語(yǔ)義完整性。
3. RAG增強(qiáng)與重排序機(jī)制
3.1 基于知識(shí)工程的代碼片段、業(yè)務(wù)上下文的檢索
在 RAG增加服務(wù)中實(shí)現(xiàn)多維度檢索增強(qiáng):
?業(yè)務(wù)領(lǐng)域識(shí)別:基于代碼內(nèi)容識(shí)別是倉(cāng)業(yè)務(wù)(WMS)、倉(cāng)配接入業(yè)務(wù)(ECLP)、轉(zhuǎn)運(yùn)中心業(yè)務(wù)(TC)等。
?關(guān)鍵詞提取與過(guò)濾:從變更文件中提取并凈化關(guān)鍵術(shù)語(yǔ)。
?通過(guò)執(zhí)行語(yǔ)義搜索。
重排序優(yōu)化:對(duì)檢索結(jié)果使用BGE模型進(jìn)行重排序,提升相關(guān)性。
3.2 重排序
在RAG系統(tǒng)中,檢索(召回)這一步通常使用向量相似度搜索。這種方法追求的是高召回率——即盡可能不遺漏任何可能相關(guān)的文檔。但這就帶來(lái)了一個(gè)問(wèn)題:
?數(shù)量過(guò)多:可能會(huì)返回大量候選文檔,全部送入大模型會(huì)導(dǎo)致超過(guò)上下文窗口限制,成本高昂且速度慢。
?質(zhì)量不均:向量搜索是基于語(yǔ)義相似度,但“相似”不一定等于“有用”。它可能會(huì)召回一些:
?主題相關(guān)但內(nèi)容泛泛的文檔。
?包含關(guān)鍵詞但邏輯不匹配的文檔。
?相關(guān)性排名不高但實(shí)際至關(guān)重要的“珍寶”文檔。
例如檢索“如何做番茄炒蛋”,向量相似度查詢結(jié)果可能會(huì)找到:
?《番茄炒蛋的最正宗做法》 (極度相關(guān),排名第一)
?《100道家常菜譜》 (相關(guān),但范圍太廣)
?《雞蛋的營(yíng)養(yǎng)價(jià)值》 (部分相關(guān))
?《番茄種植指南》 (僅關(guān)鍵詞相關(guān),實(shí)際無(wú)用)
如果不經(jīng)處理,把這四篇文檔塞給大模型,模型需要費(fèi)力地從大量文本中辨別哪些是真正有用的信息,不僅增加了Token消耗,更嚴(yán)重的是,無(wú)關(guān)信息會(huì)形成“噪聲”,干擾模型的判斷,導(dǎo)致生成質(zhì)量下降——模型幻覺(jué)。
為了節(jié)省成本,我們使用了本地重排序方案:
?模型文件: bge-reranker-base.onnx (BGE重排序模型)
?分詞器: HuggingFaceTokenizer
?運(yùn)行時(shí): ONNX Runtime Java API
// 核心流程
public List> rerankBatch(String query, List documents) {
// 1. 文本預(yù)處理和分詞
// 2. 構(gòu)建查詢-文檔對(duì)
// 3. ONNX模型推理
// 4. 相關(guān)性評(píng)分計(jì)算
// 5. 按分?jǐn)?shù)降序排序
// 6. 返回排序結(jié)果
}
示例:
?

?
?
4. 實(shí)際應(yīng)用效果驗(yàn)證
案例1:成功預(yù)防空值處理事故
?

?
?
案例2:EDI配置規(guī)范檢查
?

?
?
?
總結(jié)與展望
我們探索出的雙RAG架構(gòu),其價(jià)值核心并非追求極致的簡(jiǎn)單或敏捷,而是它既能像資深的一線研發(fā)一樣,深度理解業(yè)務(wù)及代碼變更的具體語(yǔ)境與潛在影響,又能像嚴(yán)謹(jǐn)?shù)募軜?gòu)師一樣,嚴(yán)格遵循成文的規(guī)范與最佳實(shí)踐。
通過(guò)結(jié)構(gòu)化的協(xié)同機(jī)制,系統(tǒng)將兩種不同質(zhì)、不同源的知識(shí)(深度的代碼語(yǔ)義與精準(zhǔn)的評(píng)審規(guī)則)進(jìn)行融合,實(shí)現(xiàn)了 “1+1 > 2” 的智能涌現(xiàn),從而具備了識(shí)別并預(yù)防那些復(fù)雜、隱蔽代碼缺陷的深度推理能力。這正是我們?cè)诟卟l(fā)、高可用要求極為嚴(yán)苛的大促等場(chǎng)景下,為夯實(shí)系統(tǒng)穩(wěn)定性基石所做出的關(guān)鍵性架構(gòu)決策。
這一成功實(shí)踐,為我們奠定了代碼評(píng)審工作中堅(jiān)實(shí)的技術(shù)基石,并清晰地指明了未來(lái)的演進(jìn)路徑:
1.邁向多模態(tài)代碼理解:從純文本代碼評(píng)審,擴(kuò)展至對(duì)架構(gòu)圖、時(shí)序圖等非結(jié)構(gòu)化設(shè)計(jì)產(chǎn)物的理解與合規(guī)性檢查。
2.構(gòu)建全域業(yè)務(wù)知識(shí)庫(kù):自動(dòng)抓取并融合產(chǎn)品經(jīng)理的歷史PRD、設(shè)計(jì)文檔等非技術(shù)知識(shí),將其轉(zhuǎn)化為知識(shí)工程中的關(guān)鍵上下文。這使得AI在評(píng)審時(shí),不僅能理解“代碼怎么寫”,更能判斷“代碼為何而寫”,實(shí)現(xiàn)對(duì)業(yè)務(wù)意圖的精準(zhǔn)校驗(yàn),從源頭規(guī)避偏離產(chǎn)品設(shè)計(jì)的實(shí)現(xiàn)。
3.實(shí)現(xiàn)需求上下文的自動(dòng)關(guān)聯(lián):通過(guò)規(guī)范研發(fā)流程,約束在提交代碼時(shí)于commit信息中嵌入需求編號(hào)。系統(tǒng)在評(píng)審時(shí)自動(dòng)提取該編號(hào),并主動(dòng)獲取對(duì)應(yīng)的PRD詳情。這使得每一次代碼評(píng)審都能夠在完整的業(yè)務(wù)背景中進(jìn)行,AI能夠直接對(duì)照需求文檔,判斷代碼實(shí)現(xiàn)是否完整、準(zhǔn)確地滿足了所有功能點(diǎn)與業(yè)務(wù)規(guī)則,提供前更加精準(zhǔn)的上下文。
雖然探索的道路并非坦途,我們?cè)诰唧w的技術(shù)細(xì)節(jié)中陷入困境,例如,為了在 CentOS 7.9 的環(huán)境中支持高版本 ONNX 運(yùn)行時(shí)以啟用重排序功能,不得不手動(dòng)編寫docker腳本從源碼編譯高版本的cglib依賴。這段經(jīng)歷,恰恰印證了弗雷德里克·布魯克斯在《人月神話》中所揭示的那句箴言:
The only way to accelerate software work is to simplify the product and the process, and to face the essential complexity of the software task itself with courage and skill.
-
代碼
+關(guān)注
關(guān)注
30文章
4967瀏覽量
73954 -
京東云
+關(guān)注
關(guān)注
0文章
205瀏覽量
254
發(fā)布評(píng)論請(qǐng)先 登錄
RAG(檢索增強(qiáng)生成)原理與實(shí)踐
夢(mèng)之墨藍(lán)牙音響工程實(shí)踐課程開啟電子專業(yè)實(shí)訓(xùn)新體驗(yàn)
基于知識(shí)工程&JoyAgent雙RAG的智能代碼評(píng)審系統(tǒng)的探索與實(shí)踐
【社區(qū)之星】石建華:勤于探索,不斷實(shí)踐學(xué)習(xí)新知識(shí)
RAG實(shí)踐:一文掌握大模型RAG過(guò)程
電子發(fā)燒友工程師看!電子領(lǐng)域評(píng)職稱,技術(shù)之路更扎實(shí)
JoyAgent綜合測(cè)評(píng)報(bào)告
軟通動(dòng)力發(fā)布智慧園區(qū)RAG解決方案
【「# ROS 2智能機(jī)器人開發(fā)實(shí)踐」閱讀體驗(yàn)】+內(nèi)容初識(shí)
如何成為一名合格的KaihongOS北向應(yīng)用開發(fā)工程師
DevEco Studio AI輔助開發(fā)工具兩大升級(jí)功能 鴻蒙應(yīng)用開發(fā)效率再提升
電機(jī)基本理論與工程實(shí)踐
設(shè)計(jì)評(píng)審利器——在線評(píng)審工具ReviewHub
基于知識(shí)工程JoyAgent雙RAG的智能代碼評(píng)審系統(tǒng)的探索與實(shí)踐
評(píng)論