ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于LLM Agent与Git的CLI代码评审流水线实战

基于LLM Agent与Git的CLI代码评审流水线实战 1. 为什么我要自己搭一套 open-code-review团队里代码评审这件事说多了都是泪。项目一多人一忙PR 挂三天没人看是常态好不容易有人看了留一句“这里建议优化一下”就完事具体优化什么、为什么优化、怎么改全靠猜。更麻烦的是有些低级问题——比如空指针没判、日志里把用户手机号打出来了、循环里反复查数据库——每次都要靠人肉去盯评审者累提交者也烦。市面上现成的代码评审工具我基本都试过一圈。SaaS 类的要么按人头收费贵得离谱要么得把代码推到第三方平台安全合规过不了IDE 插件类的只能管自己本地那点改动跨仓库、跨团队根本使不上劲。于是我就琢磨着能不能用现在的大模型能力加上 Git 和 CLI 这套最朴素也最可靠的工具链自己攒一个open-code-review出来。所谓 open-code-review说白了就是一套开源的、跑在命令行里的、由 LLM Agent 驱动的代码评审流水线。它的核心工作流很直白从 Git 仓库拉取待评审的 diff把 diff 连同上下文喂给大模型让模型按预设的规则输出结构化的评审意见最后再把意见回写到 PR 评论、终端输出或者飞书群机器人里。整套东西不依赖任何特定平台你可以在本地跑也可以塞进 CI 里跑代码不出内网就能完成评审。这篇文章适合谁看如果你是团队里负责工程效能的那个人或者你是个喜欢折腾工具链的独立开发者再或者你只是单纯想搞清楚“LLM Agent 到底怎么跟 Git 结合干点实事”那这篇内容应该能给你省下不少踩坑的时间。我会把整套方案的设计思路、关键选型、实操步骤、参数计算和踩过的坑都摊开讲你照着抄作业基本就能跑起来。2. 整体架构与核心选型思路2.1 为什么是 CLI Git LLM Agent 这个组合先说说为什么我不选 Web 服务或者 IDE 插件那条路。CLI 最大的好处是可组合。Git 本身就是命令行工具CI 环境天然就是命令行环境我把评审逻辑做成一个 CLI 命令它就能像git diff一样被随意管道拼接、被脚本调用、被 CI 的 job 直接执行。你不需要为它单独开一个服务、维护一套前端、处理一堆鉴权运维成本几乎为零。Git 作为数据源也是顺理成章的选择。代码评审的本质输入就是“这次改了什么”而 Git 的 diff 恰好就是这个信息最精确、最结构化的表达。相比把整个文件丢给模型diff 的 token 消耗能降一个数量级而且模型注意力会集中在变更行上评审质量反而更高。这里有个细节值得展开Git diff 有几种格式--unified是默认的上下文格式--stat只给统计--name-only只给文件名。做评审我推荐用git diff --unified5把上下文行数从默认的 3 行提到 5 行模型能多看到一点周边逻辑判断“这个变量在上面是不是已经判空了”这类问题会准很多。至于 LLM Agent这里要澄清一个经常被混淆的概念。LLM 是模型本身Agent 是让模型能自主调用工具、分步完成任务的那层编排逻辑。打个比方LLM 是一个很聪明但只会动嘴的顾问Agent 是给这个顾问配了手和脚——能去读文件、能去跑命令、能根据中间结果决定下一步干什么。在 open-code-review 里Agent 的“手脚”就是 Git 命令、文件读取、规则检索这些工具。模型比如 DeepSeek、GPT 系列、Claude 系列负责理解和判断Agent 负责调度和落地。提示很多人问 DeepSeek 属于哪一类。DeepSeek 是 LLM也就是模型本身它不天然具备 Agent 能力。你要把它接进 Agent 框架里它才能参与“读 diff → 判断 → 输出意见”这个多步流程。2.2 评审规则怎么设计才不沦为摆设我见过太多团队的评审规则文档写得洋洋洒洒几十条最后没人看。原因很简单规则和评审动作是脱节的。open-code-review 的做法是把规则代码化、可执行化。每条规则就是一个检查项包含触发条件、检查逻辑、严重等级和修复建议。规则分两类。一类是确定性规则用正则或者 AST 就能判比如“禁止在日志里打印身份证号”“禁止提交 .env 文件”“函数圈复杂度超过 15 要告警”。这类规则不该浪费模型算力本地直接跑快且准。另一类是语义规则必须靠模型理解上下文比如“这个异常处理是不是吞掉了错误”“这个并发写法有没有竞态风险”“这个接口的幂等性有没有保证”。两类规则各司其职前者兜底后者提质。严重等级我建议分三档Blocker必须改否则不给合、Warning建议改评审者判断、Info提示性比如“这里可以抽个常量”。分档的意义在于CI 里可以配置“出现 Blocker 直接 fail”把人力从机械拦截里解放出来。2.3 模型选型与成本估算模型选型没有标准答案得看你的代码敏感度和预算。我实测下来对于常规的业务代码评审中等规模的模型已经够用关键是 prompt 要给足上下文和规则。如果代码涉及核心算法或者安全敏感逻辑那就得上更强的模型或者干脆本地部署。成本这块我算过一笔账。一个中等规模的 PRdiff 大概 300 到 800 行加上上下文和规则输入 token 大约 8000 到 15000输出评审意见 500 到 1500 token。按主流模型的定价单次评审成本在几分钱到几毛钱之间。一个团队一天 20 个 PR一个月也就几十块钱。相比一个高级工程师一小时的人力成本这个投入产出比相当划算。场景推荐模型档位单次评审成本估算说明常规业务代码中等规模模型0.05-0.2 元性价比最高核心算法/安全逻辑强模型0.3-1 元准确性优先敏感代码不出内网本地部署模型硬件摊销一次性投入3. 核心模块拆解与实操要点3.1 diff 提取模块别小看这一步diff 提取看着简单坑却不少。最典型的问题是大 PR 的 diff 太长直接超模型上下文。我的处理策略是分层先按文件切分每个文件单独评审单个文件如果还是太长就按 hunk变更块切分每个 hunk 带上足够的上下文独立送审。这样既控制了单次输入规模又能让评审意见精确定位到具体行。还有一个坑是二进制文件和生成文件。package-lock.json、图片、编译产物这些送进模型纯属浪费。我在提取阶段就加了一层过滤用git diff --numstat拿到每个文件的增删行数配合文件扩展名白名单把不该评审的直接跳过。# 拿到本次变更的文件列表和增删统计 git diff --numstat HEAD~1 HEAD # 只看指定类型的文件排除锁文件和产物 git diff --unified5 HEAD~1 HEAD -- *.py *.js *.ts *.go *.java \ :(exclude)*lock* :(exclude)*.min.js :(exclude)dist/*这里:(exclude)是 Git 的 pathspec 魔法比事后过滤优雅得多。实测下来加上这层过滤平均能砍掉 30% 到 50% 的无效 token。3.2 上下文增强让模型看到 diff 之外的东西只给 diff模型有时候会误判。比如 diff 里删了一行判空模型可能以为你引入了空指针风险但实际上这个变量在上面已经被断言过了。解决办法是上下文增强把变更行所在函数的完整定义、相关的类型声明、被调用的接口签名一并附上。我的做法是用一个轻量的代码解析器Python 用astJS/TS 用babel/parserGo 用go/parser定位变更行所属的函数把整个函数体抽出来作为补充上下文。这一步能让评审准确率明显提升尤其是涉及控制流和类型判断的场景。注意上下文不是越多越好。我试过把整个文件都塞进去结果模型注意力被稀释反而漏掉了关键问题。经验值是函数级上下文 变更行前后各 5 行这个组合最稳。3.3 Prompt 工程评审意见的质量命门Prompt 设计直接决定输出质量。我踩过的最大坑是让模型自由发挥结果它一会儿写一段散文一会儿又列个表格格式飘忽不定后面根本没法解析。后来我改成强制结构化输出要求模型返回 JSON字段固定为file、line、severity、rule、message、suggestion。系统提示词的核心逻辑是这样的先告诉模型它的角色是“严格的代码评审者”再给它评审规则清单然后明确输出格式最后强调“只报真实问题不要为了凑数而报”。我特别加了一条约束“如果某段代码没有问题不要强行找问题。”这条约束很关键否则模型会有“讨好型人格”硬凑意见。{ file: src/service/user.py, line: 42, severity: Blocker, rule: no-plaintext-password, message: 检测到密码以明文形式写入日志, suggestion: 改为记录用户 ID或对密码字段做脱敏处理 }3.4 结果回写让意见落到该落的地方评审意见生成后得送到人能看到的地方。我做了三个出口终端彩色输出本地开发用、PR 评论回写走 Git 平台的 API、飞书群机器人团队通知用。终端输出用rich库做高亮Blocker 标红Warning 标黄Info 标蓝一眼就能扫完。PR 评论回写要注意幂等性。同一个 PR 如果被触发多次评审不能重复刷评论。我的做法是给每条评论打一个隐藏标记比如 HTML 注释回写前先拉取已有评论比对标记已存在的就更新而不是新增。4. 完整实操流程与关键配置4.1 环境准备Git 和 CLI 基础先把地基打好。Git 的安装和配置是绕不开的第一步。Windows 上直接下 Git for Windows安装时注意勾选“Use Git from the command line”这样git命令才能在任何终端里用。装完验证一下git --version # 输出类似 git version 2.43.0 就对了配置用户信息是必须的否则 commit 会报错git config --global user.name 你的名字 git config --global user.email 你的邮箱如果你用 Gitee 或者自建 Git 服务还得配 SSH 密钥。生成密钥、把公钥贴到平台、测试连接这三步走完就行。这里有个小技巧ssh -T gitgitee.com可以测试连接是否通返回欢迎信息就说明配好了。提示git -c diff.mnemonicprefixfalse -c core.quotepathfalse这串参数是很多 IDE 调用 Git 时自动加的作用是让 diff 输出更规范、中文路径不乱码。你自己写脚本时也可以带上省得处理编码问题。4.2 安装与初始化 open-code-reviewopen-code-review 本身是个 CLI 工具我建议用包管理器装。Python 环境用pipNode 环境用npm。装完之后在项目根目录初始化ocr init这个命令会生成一个.ocr.yaml配置文件里面是模型接入信息、规则路径、输出方式这些。配置文件长这样model: provider: deepseek api_key: ${OCR_API_KEY} max_tokens: 4096 temperature: 0.2 rules: - ./rules/security.yaml - ./rules/performance.yaml output: - type: terminal - type: pr_comment - type: feishu webhook: ${FEISHU_WEBHOOK}temperature我设成 0.2评审这种任务要的是稳定和一致不需要创造力。api_key用环境变量注入别硬编码在文件里这是安全底线。4.3 跑一次完整的评审配置好之后评审一个分支的改动就这么一条命令ocr review --base main --head feature/login它内部干了这些事先git diff main...feature/login拿到三点 diff注意是三个点表示从共同祖先开始比避免把 main 上的新提交也算进来然后过滤文件、切分 hunk、增强上下文、调用模型、解析结果、输出报告。如果你想在 CI 里跑加个--fail-on blocker参数出现 Blocker 级别问题就返回非零退出码CI 直接 fail。这样机械性的问题根本进不了人工评审环节。4.4 接入 CI 的配置示例以常见的 CI 配置为例核心就是在流水线里加一个评审 jobcode_review: stage: review script: - pip install open-code-review - ocr review --base $CI_MERGE_REQUEST_TARGET_BRANCH --head $CI_COMMIT_SHA --fail-on blocker only: - merge_requests这里$CI_MERGE_REQUEST_TARGET_BRANCH和$CI_COMMIT_SHA是 CI 环境自带的变量指向目标分支和当前提交。评审结果会作为 job 日志输出同时通过配置的出口回写到 PR 和飞书。5. 常见问题与排查技巧实录5.1 模型输出格式错乱怎么办这是最高频的问题。模型有时候会在 JSON 外面包一层 markdown 代码块或者干脆返回一段自然语言。我的处理是双重保险prompt 里明确要求“只返回 JSON不要任何额外文字”同时在解析端做容错——先用正则把 JSON 部分抠出来再尝试解析解析失败就重试一次重试还失败就降级成纯文本输出并标记为“需人工确认”。5.2 diff 太大导致超上下文前面提过分层切分这里补充一个细节切分后每个 hunk 要独立编号评审结果里带上编号最后合并时按编号排序保证意见顺序和代码顺序一致。否则模型返回的意见顺序是乱的读起来很痛苦。5.3 误报太多怎么调误报是劝退团队使用这套工具的头号杀手。我的调优路径是先看误报集中在哪类规则如果是确定性规则误报说明正则写得太宽收紧如果是语义规则误报说明 prompt 里对该规则的描述不够精确补充反例。我还会维护一个忽略清单某些历史遗留代码或者特殊场景直接标记为“不评审”避免反复误报消耗信任。问题现象可能原因排查方向解决手段输出不是 JSONprompt 约束不够检查系统提示词强化格式约束 解析容错超上下文报错diff 过长看单文件行数按文件/hunk 切分误报频繁规则描述模糊统计误报规则分布收紧规则 忽略清单评审超时模型响应慢看单次耗时并发评审 超时重试评论重复刷幂等没做检查回写逻辑加隐藏标记去重5.4 几个我踩过的坑第一个坑是在 Windows 终端里跑中文输出乱码。原因是终端编码和脚本输出编码不一致解决办法是在脚本开头强制设置PYTHONIOENCODINGutf-8或者用chcp 65001切到 UTF-8 代码页。第二个坑是Git worktree 场景下的路径问题。如果你用git worktree开了多个工作区评审脚本里的相对路径会指向错误的位置。我的做法是统一用git rev-parse --show-toplevel拿到仓库根目录所有路径基于它拼接。第三个坑是模型对某些框架的惯用写法不理解比如把某个 ORM 的链式调用误判成 N1 查询。这种只能靠喂 few-shot 示例解决在 prompt 里放一两个正确写法的例子模型就懂了。6. 规则库的持续演进与团队落地工具搭起来只是开始真正决定它能不能活下去的是规则库的持续演进。我的做法是每周复盘一次评审记录把人工评审中发现但工具没报的问题转化成新规则加进去把工具报了但人工判断是误报的调整或删除对应规则。这样规则库是活的会随着团队代码风格和业务特点一起成长。团队落地的时候我建议先松后紧。一开始只开 Info 和 Warning 级别让大家先熟悉这个工具的存在别一上来就 Blocker 拦截容易激起抵触。等大家认可了评审质量再逐步把关键规则提到 Blocker。另外评审意见的措辞很重要同样的意思“这里有问题”和“这里建议改成 X因为 Y”给人的感受完全不同后者更容易被接受。我还做了个小功能评审意见的采纳率统计。每条意见被采纳代码按建议改了就记一笔定期看哪些规则的采纳率高、哪些低。采纳率低的规则要么是误报多要么是建议不实用都值得优化。这个数据反过来也能量化工具的价值跟团队汇报的时候有据可依。最后分享一个我在实际使用中的体会这套工具最大的价值不是替代人工评审而是把人工评审的起点抬高。机械性问题被工具拦掉之后人工评审可以聚焦在架构设计、业务逻辑、边界条件这些真正需要人脑的地方。评审者不累了评审质量反而上去了。至于后续扩展我打算把评审历史和代码库的知识图谱结合起来让模型能参考“这个模块以前的评审意见”给出更贴合项目语境的建议这个方向还在摸索中。
返回列表