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

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

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

?
?
4. 實際應用效果驗證
案例1:成功預防空值處理事故
?

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

?
?
?
總結(jié)與展望
我們探索出的雙RAG架構,其價值核心并非追求極致的簡單或敏捷,而是它既能像資深的一線研發(fā)一樣,深度理解業(yè)務及代碼變更的具體語境與潛在影響,又能像嚴謹?shù)募軜嫀熞粯樱瑖栏褡裱晌牡囊?guī)范與最佳實踐。
通過結(jié)構化的協(xié)同機制,系統(tǒng)將兩種不同質(zhì)、不同源的知識(深度的代碼語義與精準的評審規(guī)則)進行融合,實現(xiàn)了 “1+1 > 2” 的智能涌現(xiàn),從而具備了識別并預防那些復雜、隱蔽代碼缺陷的深度推理能力。這正是我們在高并發(fā)、高可用要求極為嚴苛的大促等場景下,為夯實系統(tǒng)穩(wěn)定性基石所做出的關鍵性架構決策。
這一成功實踐,為我們奠定了代碼評審工作中堅實的技術基石,并清晰地指明了未來的演進路徑:
1.邁向多模態(tài)代碼理解:從純文本代碼評審,擴展至對架構圖、時序圖等非結(jié)構化設計產(chǎn)物的理解與合規(guī)性檢查。
2.構建全域業(yè)務知識庫:自動抓取并融合產(chǎn)品經(jīng)理的歷史PRD、設計文檔等非技術知識,將其轉(zhuǎn)化為知識工程中的關鍵上下文。這使得AI在評審時,不僅能理解“代碼怎么寫”,更能判斷“代碼為何而寫”,實現(xiàn)對業(yè)務意圖的精準校驗,從源頭規(guī)避偏離產(chǎn)品設計的實現(xiàn)。
3.實現(xiàn)需求上下文的自動關聯(lián):通過規(guī)范研發(fā)流程,約束在提交代碼時于commit信息中嵌入需求編號。系統(tǒng)在評審時自動提取該編號,并主動獲取對應的PRD詳情。這使得每一次代碼評審都能夠在完整的業(yè)務背景中進行,AI能夠直接對照需求文檔,判斷代碼實現(xiàn)是否完整、準確地滿足了所有功能點與業(yè)務規(guī)則,提供前更加精準的上下文。
雖然探索的道路并非坦途,我們曾在具體的技術細節(jié)中陷入困境,例如,為了在 CentOS 7.9 的環(huán)境中支持高版本 ONNX 運行時以啟用重排序功能,不得不手動編寫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.
-
代碼
+關注
關注
30文章
4956瀏覽量
73494 -
京東云
+關注
關注
0文章
205瀏覽量
243
發(fā)布評論請先 登錄
基于知識工程&JoyAgent雙RAG的智能代碼評審系統(tǒng)的探索與實踐
【社區(qū)之星】石建華:勤于探索,不斷實踐學習新知識
RAG實踐:一文掌握大模型RAG過程
電子發(fā)燒友工程師看!電子領域評職稱,技術之路更扎實
JoyAgent綜合測評報告
軟通動力發(fā)布智慧園區(qū)RAG解決方案
【「# ROS 2智能機器人開發(fā)實踐」閱讀體驗】+內(nèi)容初識
DevEco Studio AI輔助開發(fā)工具兩大升級功能 鴻蒙應用開發(fā)效率再提升
電機基本理論與工程實踐
設計評審利器——在線評審工具ReviewHub
《AI Agent 應用與項目實戰(zhàn)》閱讀心得3——RAG架構與部署本地知識庫
如何通過高效工程評審EQ流程,實現(xiàn)PCB零缺陷制造?
利用OpenVINO和LlamaIndex工具構建多模態(tài)RAG應用
基于知識工程JoyAgent雙RAG的智能代碼評審系統(tǒng)的探索與實踐
評論