基于LLM Agent与CLI的open-code-review自动化代码审查流程实战
2026/9/20 23:02:23 网站建设 项目流程

1. 为什么我要自己搭一套 open-code-review 流程

代码审查这件事,做过团队协作的人都有体会。理想状态下,每次提交都有人认真看、认真提意见、认真改;现实状态往往是,提交堆成山,审查靠自觉,最后变成“看一眼没问题就合并”。尤其是个人项目或者小团队,根本没有专职的审查者,自己审自己更是形同虚设。

open-code-review这个方向,说白了就是把代码审查这件事从“靠人”变成“靠流程 + 工具”。核心思路是:用 CLI 把 Git 的变更抓出来,交给 LLM Agent 做第一轮分析,再由人做最终判断。它不是要替代人,而是把人的精力从“找明显问题”转移到“判断复杂逻辑”上。

我搭这套东西的起因很简单:手上同时维护几个仓库,每次提交前自己过一遍 diff,时间长了眼睛会疲劳,漏掉的问题越来越多。后来试过纯手工检查清单,也试过让 AI 直接读整个文件,效果都不理想——前者太依赖状态,后者上下文太散。最后落到“只审 diff + 结构化提示词 + CLI 自动化”这个组合上,才算跑通。

这套流程适合谁?适合有一定 Git 基础、想给自己或小团队加一道质量防线的开发者。不需要你懂模型训练,也不需要你搭服务,会装 Git、会跑命令行、能配一个 API Key 就能上手。下面我按实际搭建顺序,把每个环节拆开讲。

2. 整体设计思路与方案选型

2.1 为什么是 CLI 而不是 IDE 插件

一开始我也想过用 IDE 插件,点一下就能审。但实际用下来有几个问题:插件绑定编辑器,换环境就得重装;插件对 diff 的获取方式不透明,有时候把未暂存的改动也带进去;最关键的是,插件很难和 CI 或者 Git Hook 串起来。

CLI 的好处是“可组合”。git diff输出什么,我就审什么;审完的结果可以写文件、可以贴到终端、可以塞进提交信息。它不依赖你用什么编辑器,VS Code 也好,IDEA 也好,甚至纯终端也好,流程是一样的。而且 CLI 天然适合做自动化——后面接 pre-commit 或者 CI 都是顺手的事。

提示:如果你平时用 GUI 工具比较多,比如 Git 小乌龟这类,也不用担心。CLI 流程和 GUI 不冲突,你照样可以用 GUI 提交,只是在提交前多跑一条命令而已。

2.2 为什么用 LLM Agent 而不是传统静态检查

传统静态检查工具,比如各种 linter,擅长的是语法层面、风格层面、已知模式的问题。它们快、稳定、不花钱,但有个硬伤:不理解意图。一个变量命名不规范它能报,但“这段逻辑在并发下会不会出问题”它报不出来。

LLM Agent 的价值在于它能读上下文、能推理。你把 diff 给它,它能结合周边代码判断“这个改动是不是漏了边界条件”“这个异常处理是不是吞掉了错误”。当然它也会胡说,所以定位必须是“第一轮筛查”,不是“最终裁决”。

这里要区分几个容易混的概念。Agent、LLM、AI 模型不是一回事:LLM 是底层的大语言模型,比如 DeepSeek 这类属于模型层;Agent 是在模型外面套了一层“能调工具、能多步执行”的逻辑;AI 模型是个更大的筐,机器学习模型、深度学习模型都算。我们这套流程里,LLM 负责“读和判断”,Agent 负责“按步骤调 Git、调模型、整理输出”。Embedding 则是另一条线,主要用在检索和相似度上,代码审查里暂时用不到,不用被这些名词绕晕。

2.3 审查范围怎么定:只审 diff 的取舍

这是整个设计里最关键的一个决定。我试过三种范围:

审查范围优点缺点适用场景
整个仓库上下文全太贵、太慢、噪音大几乎不用
单个文件全文上下文较全无关代码干扰判断小文件重构
仅 diff聚焦、便宜、快缺全局上下文日常提交

最后我固定用“仅 diff”,但做了两个补偿:一是把 diff 涉及的文件的周边函数签名一起带上,二是让 Agent 在不确定时主动说“需要更多上下文”。这样既控制了成本,又不会因为上下文太窄而误判。

2.4 工具链的整体串联方式

整条链路是这样的:Git 负责产出 diff,一个脚本负责把 diff 和提示词拼起来,CLI 负责调用模型,输出结果再回到终端或者文件。中间不引入数据库、不引入服务,全部是本地文件和标准输入输出。

这样做的好处是排查问题特别简单。哪一步不对,就看哪一步的中间产物。diff 不对就看 Git 命令,提示词不对就看拼接脚本,模型输出不对就调提示词。没有黑盒。

3. 核心细节解析与实操要点

3.1 Git 侧的准备:安装、配置与 diff 的正确取法

先把 Git 本身弄利索。Windows 上装 Git,直接下安装包一路下一步就行,装完在终端里跑git --version能出版本号就算成。装完建议做两件配置:一是git config --global user.nameuser.email,二是如果连的是 Gitee 这类平台,配好 SSH 密钥,省得每次输密码。

取 diff 有几个容易踩的坑。第一个是暂存区和工作区的区别:

# 只看已暂存的改动(推荐,因为提交前你会先 add) git diff --cached # 看工作区所有未提交改动(包含未暂存) git diff HEAD # 看某次提交的改动 git diff HEAD~1 HEAD

我推荐用git diff --cached,因为你的提交流程通常是“改代码 → add → 审查 → commit”。审查已暂存的内容,正好对应你即将提交的东西。如果你习惯不 add 直接 commit,那就用git diff HEAD

第二个坑是路径和引号。Windows 下如果文件名带中文或者空格,diff 输出可能带转义。可以在命令前加参数:

git -c core.quotepath=false diff --cached

这个core.quotepath=false能让中文路径正常显示,不然你会看到一堆八进制转义,模型读起来也费劲。

第三个坑是 diff 太大。一次提交改了三千行,直接丢给模型既贵又容易丢重点。我的做法是设一个阈值,比如超过 800 行就分段审,或者先让模型只看文件列表和改动统计:

git diff --cached --stat

先看统计,判断这次改动是不是该拆成多个提交。很多时候 diff 太大本身就是个信号——这次提交做的事太多了。

3.2 提示词的设计:让模型说人话、说重点

提示词决定了输出质量。我踩过的最大坑是提示词太笼统,比如“帮我审查这段代码”,模型就会给你一堆“建议增加注释”“建议统一命名风格”这种正确的废话。

后来我把提示词改成结构化输出,要求模型按固定格式回答:

你是一名资深代码审查者。请审查以下 git diff。 要求: 1. 只报告真实存在的问题,不要提风格偏好。 2. 每个问题标注严重程度:blocker / major / minor。 3. 每个问题必须给出:文件、行号范围、问题描述、修改建议。 4. 如果 diff 信息不足以判断,明确说“需要更多上下文”,不要猜。 5. 最后给一个总体结论:可以提交 / 修改后提交 / 需要讨论。 diff 如下: <diff>

这个提示词的关键在于“只报告真实存在的问题”和“不要猜”。前者压掉了大量噪音,后者减少了幻觉。严重程度分级则让你能快速判断这次提交能不能过。

还有一个细节:把 diff 放在提示词最后。有些模型对末尾内容更敏感,放最后能提高它认真读的概率。这不是玄学,是实测下来输出质量确实更稳。

3.3 模型调用的封装:一个脚本搞定

不需要复杂的框架,一个 shell 脚本或者 Python 脚本就够了。核心逻辑是:读 diff、拼提示词、调接口、输出结果。

import subprocess import sys def get_diff(): result = subprocess.run( ["git", "-c", "core.quotepath=false", "diff", "--cached"], capture_output=True, text=True ) return result.stdout def build_prompt(diff): return f"""你是一名资深代码审查者。请审查以下 git diff。 要求: 1. 只报告真实存在的问题,不要提风格偏好。 2. 每个问题标注严重程度:blocker / major / minor。 3. 每个问题必须给出:文件、行号范围、问题描述、修改建议。 4. 如果 diff 信息不足以判断,明确说"需要更多上下文",不要猜。 5. 最后给一个总体结论:可以提交 / 修改后提交 / 需要讨论。 diff 如下: {diff} """ if __name__ == "__main__": diff = get_diff() if not diff.strip(): print("没有已暂存的改动,跳过审查。") sys.exit(0) prompt = build_prompt(diff) # 这里接你的模型调用,可以是本地模型也可以是 API print(prompt)

这个脚本先跑通“拿到 diff 并拼出提示词”,模型调用部分单独接。这样做的好处是调试方便——你可以先把 prompt 打出来看看对不对,再决定怎么调模型。

注意:不要把 API Key 硬编码在脚本里。用环境变量,或者放在一个不进版本库的配置文件里。这是基本的安全习惯,别嫌麻烦。

3.4 输出结果的落地:终端、文件还是提交信息

审查结果有几种用法,我一般分场景:

  • 日常提交前:直接打终端,看一眼没问题就 commit。
  • 重要改动:输出到文件,比如review-$(date +%s).md,留档方便回看。
  • 团队协作:把结论精简成一行,塞进 commit message 的末尾,比如[review: pass]

不建议把完整审查结果塞进 commit message,太长了。commit message 是给人快速扫的,不是给机器读的。

4. 实操过程与核心环节实现

4.1 从零搭起:环境准备清单

先把要装的东西列清楚,避免中途卡壳:

  1. Git:装好并配置 user.name、user.email。
  2. Python 3.8+:用来跑封装脚本。
  3. 一个模型调用方式:可以是本地跑的模型,也可以是 API。本地模型对机器有要求,API 则要管好 Key。
  4. 一个终端:Windows Terminal、iTerm、普通终端都行。

装完先验证:

git --version python --version

两个都能出版本号,基础环境就 OK 了。

4.2 第一次跑通:用一个小改动验证全链路

别一上来就拿大改动试。先改一个文件,加一行注释,然后:

git add . python review.py

看输出的 prompt 里 diff 对不对、格式对不对。确认没问题后,再接模型调用。第一次跑通的目标不是“审出问题”,而是“链路通”。

我当时的做法是先用一个故意写错的改动试,比如把if x > 0改成if x >= 0,看模型能不能指出边界变化。能指出来,说明提示词和调用都到位了。

4.3 参数与成本控制:怎么让审查不烧钱

如果用 API,成本主要看输入输出 token 数。控制成本有几个实招:

  • 只审 diff,不审全文,这是最大的节省。
  • 设 diff 行数上限,超过就分段或者先拆提交。
  • 提示词尽量精简,别写一堆没用的背景。
  • 输出要求结构化,避免模型长篇大论。

我实测下来,一个中等规模的提交(200 行 diff 以内),审查成本是很低的。真正贵的是那种一次改几千行的大提交,所以“拆小提交”本身就是省钱手段。

4.4 和 Git Hook 结合:提交前自动跑

想省事的话,可以挂到 pre-commit 钩子上。在.git/hooks/pre-commit里写:

#!/bin/sh python review.py

记得给执行权限。这样每次 commit 前会自动跑审查。但有个问题:如果审查结果只是打印,它不会阻止提交。要阻止的话,得让脚本在发现 blocker 时返回非零退出码。

我的建议是前期不要自动阻止,先让它跑着,你人工看结果。跑一段时间,确认误报率可接受了,再考虑加阻止逻辑。一上来就卡提交,很容易因为误报把自己搞烦,最后把钩子删了。

5. 常见问题与排查技巧实录

5.1 diff 为空或者内容不对

最常见的原因是改动没 add。git diff --cached只看暂存区,你没 add 它当然是空的。先git status看一眼,确认改动状态。

另一个原因是路径问题。如果你在子目录里跑脚本,Git 可能只取当前目录的 diff。要么在仓库根目录跑,要么加--指定路径。

5.2 模型输出全是废话

大概率是提示词太松。检查两点:一是有没有明确“只报告真实问题”,二是有没有要求结构化输出。如果还不行,就在提示词里加一两个反例,比如“不要输出‘建议增加注释’这类内容”。

5.3 模型说“需要更多上下文”

这是好事,说明它没瞎猜。这时候你有两个选择:一是手动把相关文件的关键部分贴进去,二是调整审查范围,把整个文件带上。我一般先看它要什么上下文,如果只是某个函数,就单独贴那个函数。

5.4 中文路径乱码

前面提过,加-c core.quotepath=false。如果还乱,检查终端编码是不是 UTF-8。Windows 老终端默认编码可能不是,换成 Windows Terminal 一般就好了。

5.5 常见问题速查表

现象可能原因处理方式
diff 为空没 add / 路径不对git status 确认,仓库根目录跑
中文乱码quotepath 未关加 -c core.quotepath=false
输出全是套话提示词太松加“只报真实问题”和结构化要求
模型瞎猜没要求“不确定就说”提示词加“需要更多上下文”条款
成本偏高diff 太大拆提交,设行数上限
钩子不阻止提交脚本没返回非零发现 blocker 时 sys.exit(1)

5.6 几个我踩过的坑

第一个坑是拿未暂存的 diff 去审,结果审的是半成品,改到一半的代码被报了一堆问题。后来固定用--cached,世界清净了。

第二个坑是提示词里没限定语言,模型有时候中英混杂。后来明确要求“用中文输出”,统一了。

第三个坑是忘了处理空 diff。第一次跑钩子的时候,空 diff 也去调模型,白花钱。加了个判断,空 diff 直接退出。

6. 后续可以怎么扩展

这套流程跑顺之后,能扩展的方向不少。比如把审查结果按严重程度分类存档,积累一段时间后看哪类问题最常出现,反过来指导自己的编码习惯。再比如把 blocker 级别的问题自动生成待办,接到任务管理工具里。

还可以做多轮审查:第一轮让模型找问题,第二轮让另一个模型或者同一模型换个角度复核,减少漏报。这个成本会上去,适合重要分支合并前用。

如果团队里有人用不同的编辑器,这套 CLI 流程照样通用,因为它不绑定任何编辑器。谁都能在自己环境里跑,输出格式统一,讨论起来也有共同语言。

我个人在实际操作中的体会是,这套东西最大的价值不是“审出多少问题”,而是“让提交前多一道固定动作”。习惯一旦养成,代码质量的下限就被抬高了。至于模型选哪个、提示词怎么调,都是在这个习惯之上慢慢磨的事,不用一开始就追求完美。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询