发布时间:2026-01-31
浏览次数:0
大促备战中的代码评审困境与破局
双十一搞大促,这可是系统稳定性方面的终极“大考”呀。为了躲开上线时可能出现的风险,技术那边会开启系统封板管控,还会主动把发布窗口提前,针对那些不是特别紧急的需求。这样的行动,在保证系统稳定性之时,肯定会让研发需求提前并且集中起来,进而致使封板之前的代码评审任务量明显增多。我们正面临着一个特别严酷的“量与质”的挑战,那就是:
怎样于时间紧迫、任务繁重的双重压力状况下,去保障可以代码评审的效率以及质量,进而在前面就发现潜在风险,有效地拦截线上所出现的 BUG 呢?
传统的代码评审模式,在这个场景里面,效率很低、质量不怎么样(风险遗漏的可能性非常高),然而现有的AI辅助工具。又因为误报率高所以陷入尴尬境地:所产生的大多数评审意见,并没有实际上的帮助,工程师仍然需要耗费大量时间去进行判断以及筛选。
正是处于这样的背景状况之下,【供应链技术部 - 商家导入研发组】针对 AI 代码评审展开了某些方面的探索行动,(尝试着把知识工程代码进行知识检索的能力与(已经更改名称为:)知识库检索能力相互结合起来)构建起了一套代码评审系统。这一套双 RAG 架构为我们所进行的代码评审工作予以了一些全新的思路想法,在这个地方分享呈现出来,期望能够与各位同行一起来交流探讨,从而共同实现进步发展。
现有技术方案的局限性技术1:基于流水线的AI代码评审方案
核心技术路径:在借助公共流程,也就是触发、解析MR并获取Diff之后,得到了代码变更内容,此方案的核心处理流程是这样的:
文件类型实施过滤,只留下.java文件,以及.yaml文件,还有.md文件,用以开展后续的分析工作,并且要清晰明确优先级的处理顺序。
为了防止触碰到大模型上下文窗口的上限,采用了一种依据固定行数来执行的上下文截断策略。这种策略仅仅截取在代码变更附近放置的预先设定好的行数之内的这两行文本内容,就像10行那样标点符号。
首先,进行驱动评审,接着,把经过过滤后的代码片段拿出来,之后,再拿经过截断后的代码片段,然后,将它们与预设的评审规则组合在一起,最后,发送给通用大语言模型。
4. 输出评审意见,对大模型的返回结果予以解析,借助平台API把评审结果增添至MR中。
核心问题识别:
造成问题的根本原因之一,是其所选用的那种“固定行数截断”策略,这个策略致使评审完全失去了对于项目架构、模块依赖还有完整业务逻辑的全面视野,就好像“管中窥豹”一般,进而使得评审深度,以及评审准确性都受到了非常严重的制约。
2.提示词的极致上限:全部专家评议的准则以及知识都采取硬编码的方式融汇其中,当规则出现扩充后,极其容易遭遇到模型上下文长度界限的制约,便于维护的特性以及能够拓展的性能极其堪忧。
3. 知识没办法沉淀下来:成效的提升完全依靠于“去更换更为强大的基础模型”以及“进行调整”,其自身欠缺能够持续积累、沉淀以及复用领域知识的机制。
技术2:基于知识库的RAG代码评审
首先,核心技术路径为,其次,是在借助公共流程来取得代码差异之后,再者,此方案具有的核心流程是这样的。
将格式化后的Diff内容发送给,由LLM智能体针对其开展初步的“知识归纳”一事,是要以此来理解此次变更的核心意图,这属于知识归纳内容项下的操作步骤之环节。
以下是改写后的内容:第一,规则检索,是依据归纳出来的知识,借助RAG机制从自定义知识库当中召回相关的代码评审规则,这个知识库支持在线文档、离线文档等多种格式,像PDF、Word等。第二,该方案的核心灵活性在于其”自定义知识库绑定“机制,接入者能够在平台上自定义智能体,通过工作流绑定自定义知识库,这就使得在召回评审规则之际,系统能够动态地查找并且应用接入者自定义的评审规则,进而达成了无需修改就可定制评审规则的能力。
3.行级评审:把代码Diff跟召回的特定且具体的规则相互结合起来,再次进而去调用LLM开展精确评审。借助Git Diff信息里所包含的代码行信息,能够把评审意见精准无误地关联到确切的具体代码行标点符号。
直接使用的输出结果,先输出它,再凭借平台API,把评审结果增添至MR里面 ,这是输出结果。
核心问题识别:
核心问题出自其“知识归纳”步骤,这就是知识归纳失真的根源所在。此步骤依靠底层大模型去总结Code Diff,那个过程不稳定,总要遗漏或者曲解原始代码变更的关键上下文,结果是把后续流程置于一个不完整或者失真的基于信息之上了。
2. 检索跟生成联动出现失效情况,进行RAG检索是基于失真的知识归纳结果,这致使召回的规则和真实代码场景匹配程度低,另外,检索结果没有经过有效的重排序,就直接跟不完整的代码上下文一同被送入大模型,这让模型缺失进行准确判断的可靠依据,最终肯定会生成大量不可靠乃至错误的评审意见。
从线上问题到技术突破问题1:三方系统空值处理异常
示例:
// 问题代码:三方系统地址编码字段处理
request.setAddressCode(String.valueOf(address.getCode()));
// 当address.getCode()为null时,String.valueOf(null)返回"null"字符串
// 导致三方系统Integer.parseInt("null")抛出NumberFormatException
技术1的问题:
在理论层面上,借着于其中硬编码“三方接口地址编码必须是数字类型字符串”这样的规则得以识别该问题,不过,伴随业务场景数量的增多,全部规则都在限定颇有限的上下文窗口之内形成竞争态势。当代码出现变更进而触发自动压缩情况(像被截断至仅限10行这般)的时候,留存下来的上下文有着不小的随机性,和当下评审关联度很强的评审规则极有可能被其他并无关联的规则挤压出去,或是因为自动压缩而被截除掉,致使其没办法被稳定地触发,最终造成漏报。
技术2的问题:
该方案在理论层面是能够借助知识库检索获取相关规则的,然而,其知识归纳过程存在不稳定的状况,这致使代码上下文的理解出现时而良好时而欠佳的情形,进而造成规则检索的准确性呈现出较大幅度的波动。与此同时,该方案并未针对检索结果实施重排序操作,这进一步加剧了这种不确定性。最终的结果是,鉴于缺乏稳定且可靠的上下文予以支撑,系统没有办法持续且准确地识别此类问题,其评审结果展现出显著的随机性。
问题2:EDI项目中的语法错误
示例:
EDI平台介绍:
京东物流与多样化商家系统间对接难题的解决技术是EDI(电子数据交换),其关键功能有协议转换,还有,数据格式转换,也有,数据校验,并且有流程编排。这就表明,EDI配置文件得严格依照预定义的语法以及标准,只要有任何偏差,便极有可能致使平台的核心转换与校验功能无法正常发挥作用。
技术1的问题:
因为它欠缺对于EDI配置语法以及规范相关的领域知识,要是去自定义规则的话,就会碰见如同问题1那般的提示词天花板的情况,还会有上下文截断的问题。
技术2的问题:
除了上面所讲的知识归纳进程的不稳定状况,技术2还面临一个更靠前的挑战,它欠缺对项目身份的感知本事,系统在处理一个XML配置文件之际,没办法自动辨认它归属于“EDI项目”并不是普通Java应用,所以,在后续的RAG检索进程中,它很有可能运用通用的Java代码评审规则,而不能够精确命中“EDI专用配置规范”这个关键上下文,致使检索方向有误,最终无法识别出必须使用字面常量这个特定于EDI领域的合规性要求。
解决方案:双RAG架构
1. 识别项目类型
特征识别,是依靠文件扩展名(.flow、.dt)来展开精准判断的。
EDI项目识别,比普通JAVA程序优先,以使特殊程度优先被区分,从而进行优先处理,这便是优先级设定。
项目类型对后续评审规则的选择有着直接的决定作用,项目类型还直接决定RAG知识库的检索策略,从源头层面保障了评审的针对性。
2. 代码分块处理
2.1 Token估算算法
鉴于我们所运用的底层大模型为JoyAI,不存在公开的细节情况,依据官网文档所给出的token计算API:
链接为,http://api..jd.com/api/v1// 且针对 -token-count ,是这样的一个链接。
测试了几组数据:
推导过程
通过分析测试数据,我们发现了以下关键规律:
1.基础系统开销:所有请求都有63 的固定开销
2.英文单词分级:
把1到5个字符的单词,视作1个token,比如"a"这种 ,还有"hello"这般呈现给你看 ,以及"code"这样的情况在其中。
6-10字符单词 ≈ 2 (推测值)
11+字符单词 = 3 ("")
3.中文分词规则:每2个中文字符 = 1 token
4.空格处理:空格作为分隔符,不增加额外token
5.混合内容:按字符类型分段计算后求和
基于上述规律,我们构建了以下估算公式:
总Tokens = 63 + ∑(单词token)
单词token计算:
- 单字符单词: 1 token
- 英文单词(≤5字符): 1 token
- 英文单词(6-10字符): 2 tokens
- 英文单词(≥11字符): 3 tokens
- 中文文本: (字符数 + 1) / 2 tokens
- 混合内容: 分段计算后求和
2.2 分块阈值与安全设计
触发阈值是,当预估Token数大于100,000的时候,就会自动触发分块处理流程。
JoyAI的上下文窗口为128K,鉴于JoyAI未对1K究竟是1024还是1000作出说明,故而进行保守估计采用1000。
128K 的数值等于,由于要防止超出上下文窗口情况的发生,所以预留出一定的富余量可供使用,采用 80%的比例进行计算,也就是 12800 乘以 0.8 的值等于,其结果约等于。
对于单块容量,进行设定,设定的值为60000,要为模型输出以及上下文预留40%的安全余量。
采取严格的容量控制方式,以保障单次处理负载都处于模型窗口的安全范围之中,这便是设计理念。
2.3 智能分块策略
系统采用两级分块策略,确保代码语义的完整性:
2.3.1 文件级分割
利用git diff指令去辨认文件边界,以此保证单个文件的代码完整性,防止发生跨文件分割。
Pattern.compile("diff --git a/(.+?) b/(.+?)\n")
2.3.2 代码结构感知分割
利用方法签名模式识别代码结构边界:
Pattern methodPattern = Pattern.compile(
"([+-]\\s*((public|private|protected)\\s+)?(\\w+\\s+)?\\w+\\s*\\([^)]*\\)\\s*\\{)",Pattern.MULTILINE);
于方法或者类那自然的边界之处展开分割,将代码块语义的完整性保持到最大限度。
3. RAG增强与重排序机制
3.1 基于知识工程的代码片段、业务上下文的检索
在 RAG增加服务中实现多维度检索增强:
•业务领域识别:凭借代码内容来进行识别,所识别的是仓业务也就是WMS、还有仓配接入业务即ECLP、以及转运中心业务那便是TC等。
•关键词提取与过滤:从变更文件中提取并净化关键术语。
•通过执行语义搜索。
将检索结果,运用BGE模型codejock v171,重新加以排序并进行优化之举,来达到提升相关性之目的。
3.2 重排序
于RAG系统里头,检索也就是召回这一环节一般运用向量相似度搜索,此方法所谋求的乃高召回率,亦即在最大程度上刻意不去略过那般任何有可能存在关联的文档。然而这就促使冒出来了一个并不容易解决的事情:
数量太多:有可能会返回数目庞大的候选文档,要是全部都送进大模型,就会使得超出上下文窗口的限制,这样成本很高,而且速度还慢。
质量存在不均衡情况,向量搜索是依据语义相似度来开展的,然而“相似”并不必然就等同于“有用”,它有可能会召回某些。
主题相关但内容泛泛的文档。
包含关键词但逻辑不匹配的文档。
相关性排名不高但实际至关重要的“珍宝”文档。
例如检索“如何做番茄炒蛋”,向量相似度查询结果可能会找到:
《番茄炒蛋的最正宗做法》 (极度相关,排名第一)
《100道家常菜谱》 (相关,但范围太广)
《鸡蛋的营养价值》 (部分相关)
《番茄种植指南》 (仅关键词相关,实际无用)
要是不经过处理,就把这四篇文档交给大模型,那么模型就得费劲地从海量文本里分辨出哪些是真正有用的信息,这样不但增加了Token消耗,更为严重的是,无关信息会变成“噪声”,进而干扰模型的判断,致使生成质量降低 —— 出现模型幻觉。
为了节省成本,我们使用了本地重排序方案:
用于模型的文件是,bge--base.onnx ,此为 BGE 重排序模型。
分词器:
运行时: ONNX Java API
// 核心流程
public List> rerankBatch(String query, List documents) {
// 1. 文本预处理和分词
// 2. 构建查询-文档对
// 3. ONNX模型推理
// 4. 相关性评分计算
// 5. 按分数降序排序
// 6. 返回排序结果
}
示例:
4. 实际应用效果验证
案例1:成功预防空值处理事故
案例2:EDI配置规范检查
总结与展望
我们所探索出来的双RAG架构,它的价值核心并非是去追求那种极致的简单或者敏捷,而是它能够比如说像那些资深的一线研发人员那样,深入地去理解业务以及代码变更的具体语境,还有潜在影响,还能这般像严谨的架构师一样,严格地去遵循成文的规范以及最佳实践。
经由结构化的协同机制,系统把两种不一样质、不一样源的知识,也就是深度的代码语义与精准的评审规则予以融合,达成了 “1+1>2” 的智能涌现,进而拥有了识别以及预防那些复杂、隐蔽代码缺陷的深度推理能力。这恰恰是我们于高并发、高可用要求极其严苛的大促等场景下,为夯实系统稳定性基石而做出的关键性架构决策。
这一回的成功实践,给我们奠定了在代码评审工作里坚实的技术基石,还清楚地指明了未来的演进道路:
1.朝着多模态代码理解迈进,从单纯的文本代码评审开始,延伸到对架构图这类事物的理解,再延伸到对时序图这类事物的理解codejock v171,还要进行关于架构图的合规性检查,以及关于时序图的合规性检查。
构建全域业务知识库,自动抓取产品经理的历史PRD、设计文档等非技术知识,并且将其融合,把这些知识转化为知识工程里关键上下文,这让AI在评审的时候,不但能够理解“代码怎么写”,还能够判断“代码缘何而写”,成就对业务意图的精准校验,从源头避免偏离产品设计的实现。
借助规范研发流程,在提交代码时,于信息里嵌入需求编号并受到约束。之后系统评审时,会自动提取该编号,并主动去获取对应的PRD详情。如此一来,每一回代码评审都能在完整业务背景下开展,然后AI能直接对照需求文档,判定代码实现是否完整且准确地满足了全部功能点跟业务规则等,进而提供更精准的上下文。
纵然探索之路并非一帆风顺,我们曾于具体的技术细节里遭遇困境,比如说,为了在7.9的情形下支持较高版本ONNX运行时从而启用重排序功能,不得不亲自编写脚本自源码编译较高版本的cglib依赖。这段过往,恰好证实了弗雷德里克·布鲁克斯在《人月神话》中所披露的那句格言:
如有侵权请联系删除!
Copyright © 2023 江苏优软数字科技有限公司 All Rights Reserved.正版sublime text、Codejock、IntelliJ IDEA、sketch、Mestrenova、DNAstar服务提供商
13262879759
微信二维码