news 2026/9/7 1:32:00

从零搭建Hermes:基于GitHub PR的AI自动化代码评审Agent实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零搭建Hermes:基于GitHub PR的AI自动化代码评审Agent实践

作为一个常年在一线写代码、也常年被 PR Review 卡住时间的人,我太清楚“自动化代码评审”这件事的诱惑和陷阱了。团队里每天二三十个 PR,每个人切换上下文的时间比写代码的时间还长,Lint 和静态扫描工具又永远只盯着格式和低级错误。所以当 Hermes 这个 GitHub PR 自动审查 Agent 的项目落到我手上时,我没有急着去调模型、写提示词,而是先花了一周时间想明白:到底什么样的自动化评审,才值得一个开发团队真的去用、愿意去回、不会被五分钟一次的通知气得关掉它。

这篇文章会把我从零搭建 Hermes 的完整过程讲清楚,包括事件接入、diff 处理、上下文构建、提示词设计、评论回写、部署形态,以及上线之后踩过的五个印象最深的坑。如果你想在自己的仓库里落地一套 AI 代码评审,这篇文章应该能帮你省掉大量试错成本。

1. 为什么写 Hermes:人工 Review 的三个真实痛点

1.1 团队 Review 的日常:不是在看代码,是在抢时间

我当时所在的业务小组,平均每天活跃 PR 大概接近 30 个。看起来不多,但如果每一个 PR 都要有两个人以上认真读一遍,根本不现实。我们当时用的是“谁提交谁指定 reviewer”的方式,结果就是技术骨干基本半天都在看 PR,剩下半天才能写需求;新来的同学则更愿意挑格式、命名、小毛病来提意见,反而把真正有风险的逻辑改动放过去了。

这个问题本质上不是态度问题,是成本问题。人从一段完整的开发状态切到另一段陌生的 diff,光是把那几处修改放到更大的背景下想明白,就至少需要十几分钟。你还要自己去点开文件、翻看调用链、回忆之前的约束。切回来以后,可能又要十几分钟才能回神。一天下来,大量时间都耗在这种切换上,代码质量和开发效率两头都受损。

1.2 现有自动化工具解决不了什么

用过的自动化工具其实不少。ESLint、SonarQube、CodeClimate 这些能帮你守住代码风格、控制圈复杂度、扫出明显的漏洞模式,但你让它回答“这次改动会不会影响另一个模块的线上行为”,它就无能为力了。它连这次改动在业务上想干什么都不知道。

后来又试过几种基于规则的审查机器人,它们把“数组越界、空指针、硬编码密码、忘记处理异常”这类模式总结成模板去匹配。好处是可解释、好部署,坏处是误报率奇高:模式匹配不看上下文,凡是出现JSON.parse就提示你处理 try/catch,不管你是不是已经包在 try 里。团队用了一个月,群里全是机器人的 @,真正的 review 体验反而更差。

1.3 Hermes 的定位:不让 AI 替代人,而是让人省出时间

所以做 Hermes 的时候,我给自己定的原则是:它不能停留在“规则匹配”和“lint 报告”这个层面,而应该像一个初级但勤奋的资深工程师,先把 PR 读一遍,把低级问题、明显风险、可疑逻辑找出来,给每个人留下有依据的评论;而人只需要在它筛选后的结果里做二次判断。这不是替代人的 code review,而是把所有重复劳动前置到机器人身上。

我把它命名为 Hermes,取希腊神话里信使神的意思——它不产出最终结论,它负责替人把信息跑起来。后面我会把它如何接收 GitHub 事件、如何处理 diff、如何组织评审结论、如何回写评论,以及我在生产环境中踩过的坑,全部展开。如果你也想在自己的项目里搭一套自动化代码评审,应该能得到一套可以直接上手的思路。

2. Hermes 的架构拆解:一次 PR 从事件到评论的完整旅程

2.1 触发与采集:GitHub App 还是 Webhook

第一件要做的事,是想清楚怎么让 Hermes 知道“有新 PR 或新 commit”。GitHub 官方推荐的方式是注册一个 GitHub App,订阅pull_requestissue_commentpull_request_review_comment这些事件。事件发生时,GitHub 会把包含完整信息的 payload 推送到你指定的回调地址。

我也见过用 GitHub Actions 做的轻量方案,但这里我选择 GitHub App 的原因有几个:App 事件比 Actions 丰富得多,拿到的 payload 里带了actionpull_requestrepository等字段,想触发的时候触发,不想触发的时候可以不触发;App 有独立身份,评论时不会占用某个同事的账号,权限控制也更干净。

回调地址收到事件以后,第一件事不是直接开始分析,而是做一个很不起眼但必须做的判断:事件是opened、是synchronize(新 commit 被推送)、还是review_requested。不同事件后续处理逻辑完全不同。比如synchronize事件如果每次都全量重跑整个 PR,一个开发到一半的分支会把你整个任务队列打满,所以 Hermes 只对最新一轮 diff 做增量评审,历史结论保留原样。

2.2 队列与任务编排:异步化是避免 Webhook 超时的底线

接着是最容易被新手忽略的一步——队列。GitHub Webhook 本质上是一次 HTTP POST,如果你在里面同步等待大模型分析完、再调用 GitHub API 写完评论,这个请求很可能 10 秒都回不去。GitHub 对 webhook 的响应有超时预期,超时后会判你投递失败并不断重试,最后就出现“同一份评论发好几次”的诡异现象。

Hermes 的处理方式是把任务分成两个阶段。接收端只做非常轻量的解析动作:验签、判断事件类型、把repo + pr_number + head_sha存进队列,然后立刻给 GitHub 返回 204。后端的 worker 从队列里取任务,再去拉取 diff、分析、评论。队列可以用 Redis,也可以用消息队列,甚至直接用数据库表当队列都行。关键是要保证两点:任务至少被消费一次;每条评论写入要做幂等控制。只要把握住这两个底线,后续怎么折腾都不会出大事故。

2.3 一次评审的完整流水:diff 拉取、上下文构建、模型推理、评论回写

一次完整的评审,我拆成下面几个阶段:

  1. 拉取元数据:从 GitHub API 拿 PR 的标题、描述、变更文件列表、提交记录。
  2. 拉取 diff:调用/repos/{owner}/{repo}/pulls/{pr}/files接口,拿到每个文件的 patch。
  3. 构建上下文:对 diff 做预处理,提取相关函数、被调用的符号、对应语言语法树,目标是让模型不用来回翻文件。
  4. 分批推理:把 diff 按文件或按函数切块,送到 LLM 推理,同时给模型的指令里带上项目自定义规则和全局约束。
  5. 整理结果:合并多批次的分析结果,去重、按严重程度排序。
  6. 回写评论:通过 GitHub API 以 App 身份创建 review,带上逐行评论或 suggestion。

听起来不复杂,但每个环节都有各种边界条件。比如第三步“构建上下文”,如果直接用原始 diff,很多语言模型会因为文件太长而截断,或者因为缺少函数定义而看不懂改动到底在做什么。这一层做得好不好,直接决定评审结果是不是真的能看,所以我单独用第三章来讲。

2.4 为什么坚持模型无关设计

推理环节我坚持做成模型无关的接口。内部定义了一个统一的分析调用格式:输入是评审任务(包含文件、diff、上下文、规则),输出是结构化的评审意见(JSON)。底层可以接任何大模型 API,也可以接本地部署的开源模型。

这么做的好处非常实际。第一,成本可控。平时用便宜的模型处理琐碎检查,遇到复杂核心逻辑再走贵一点的模型。第二,不会被某一家模型限制住。不同模型在代码理解上的强弱差异很大,你的真实需求也会变化。第三,方便做 A/B 对比。同一段 diff 丢给两个模型,看哪家给出的结论更有用,保留效果好的,这本身就是运维 Hermes 时经常要做的事。

3. Diff 预处理与上下文构建:评审质量的隐藏关卡

3.1 直接拿原始 diff 喂给模型的三宗罪

我最早的原型机就是直接把 GitHub 返回的 patch 文本拼进 prompt,跑出来的结果惨不忍睹。总结下来,原始 diff 有三个问题:

第一,大量噪音。依赖锁文件、自动生成文件、格式化工具改过的文件,会把 diff 撑得巨大,严重挤占上下文空间,模型可能看完了也没抓到真正重要的改动。第二,截断问题。GitHub API 对超大文件的 patch 返回有大小限制,直接拉出来本身就不完整。第三,缺少语义上下文。模型看到的只是 hunk,没有函数头、没有被调的接口、没有 import,它很难判断这次改动会不会破坏其它调用。

3.2 语义切片:按“变更单元”而不是按行分析

解决思路,是把一个巨大的 diff 切成若干语义独立的小单元。我建议不要按 hunk 去切,而要按“变更单元”去切。所谓变更单元,在函数式语言里可以是一个函数,在类里可以是一个方法,在配置文件里可以是一个完整的配置块。判断到底在哪一段,依靠的是语言解析器而不是字符串匹配。

以 JavaScript/TypeScript 为例,我先把文件用 Babel 解析成 AST,定位变更行,再找到变更行所在的函数或方法节点,把整个函数体、函数签名、注释都保留下来,形成一个最小分析单元。这样喂给模型的内容是一个“完整的函数改动”,而不是几根支离破碎的 diff 行。这个切片动作同时解决了上下文和 token 预算问题。这里贴一段核心逻辑,我用 Python 写处理脚本,解析 diff 并定位变更范围:

def extract_changed_functions(file_path, patch_text, parser): changed_lines = parse_patch_ranges(patch_text) tree = parser.parse_file(file_path) units = [] for node in find_all_function_nodes(tree): node_range = set(range(node.start_line, node.end_line + 1)) if node_range & changed_lines: units.append({ "function_name": node.name, "start": node.start_line, "end": node.end_line, "source": node.source, }) return units

这个函数本身不复杂,但实际项目中要处理的情况远比这多:一个函数有 500 行怎么办?公共函数同时被多个 PR 改动怎么办?我的建议是给分析单元设一个行数上限,超过上限的函数再按 hunk 或者按语法块切到更细粒度;同时保证每次分析时把“变更行所在的最小函数/方法”的完整签名给到模型,其他不相关的大段实现可以不进上下文。

3.3 上下文召回:把“它调用了谁、谁调用了它”补进来

切片之后,模型仍然只知道这个函数本身,还不知道它依赖的东西。真实 code review 里,你看到一行await sendEmail(user),你得知道sendEmail大概在干什么,才能评估这次改动是否合理。Hermes 的做法是定期扫描仓库,建立一份符号索引:每个函数名称、定义在哪个文件、接收什么参数、调用方大致有什么特征。评审时,如果 diff 里出现了调用某个符号,就把这个符号的简要定义或者调用处上下文一并塞给模型。

这块不用做到非常重,一条简单的文本索引就能解决大部分问题。重点是控制召回粒度:把符号定义控制在一二百字以内,调用点最多放两三个,否则上下文又要爆。上下文构建是成本和质量最尖锐的矛盾点,你必须不停调,直到找到一个平衡。

3.4 token 预算:每个 PR 到底该花多少

token 成本是你审时间长了以后一定会面对的。做一个大概估算:假设一个 PR 改 10 个文件,每个文件切片成 2 到 4 个分析单元,每个单元带上函数体、符号定义、提示词,一次推理大约消耗 2500 到 4000 个 token。如果每个 PR 再来一次全局总结分析,可能又要 8000 token。对于每天 30 个 PR 的团队,一天下来几十万 token,乘以模型单价,是不可忽略的开销。

我从一开始就把“评价单元的粒度”和“是否做全局总结”设置成可配置项。轻量模式只评审高影响区(业务源码、核心模块),重量模式才去分析测试文件、配置文件和文档。这里有一个很容易被忽略的妙招:如果模型对某种类型文件(比如测试代码)误报率特别高,你可以直接把这些文件排除在评审范围之外,省下的 token 远比你花在调试误报上的时间值钱——这个我后面还会再提。

4. 提示词设计:把“资深 Review 视角”教给模型

4.1 先定义问题等级:什么值得打断别人

提示词设计的前提,是先想清楚整套规则要识别什么、不识别什么。我把 Hermes 的评审结果分成四级:阻断级(Blocker)——会导致线上故障、安全漏洞、严重性能恶化的问题;应该改(Should)——明显逻辑缺陷但未必出大事;建议(Suggest)——可读性、边界情况、潜在优化点;风格(Nit)——命名不统一、格式问题等。

分级的意义是给模型一个清晰的注意力引导,让它不要把所有问题都按同一个强度提。如果一份评论满屏都是“Nit”,开发者的处理体验会非常差。Hermes 的默认设置是:Blocker 必须在 review 结论里置顶,Should 应当出现,Suggest 酌情,Nit 默认不输出。这直接决定了评论会不会被团队当成噪音。

4.2 提示词模板:角色、任务、规则、示例四段式

我最终的提示词基本固定为四段式结构,第一段定义角色,第二段写本次任务和输入格式,第三段写项目自定义规则,第四段是少样本示例。一个简化后的模板长这样:

你是资深 code reviewer,请基于以下 diff 做评审。 任务: 1. 只根据提供的 diff 和上下文作答,不要臆测未出现的内容; 2. 输出 JSON,格式为 {"comments": [{ "file": "...", "line": ..., "severity": "blocker|should|suggest", "message": "..." }]}; 3. 如果没有任何值得提的问题,输出空数组。 项目规则: - 不允许在日志中打印 token、密钥、密码; - 所有新增接口必须处理异常并记录错误; - 数据库查询不得在循环中执行。 变更文件: {file} 上下文: {context} Diff: {diff}

我实际用的模板比这个长得多,还会根据语言加入不同规则。关键点在于“如果没有任何值得提的问题,输出空数组”这句话,加上这句之后,空评论大幅减少,模型更倾向给出克制结果。同时,在任务里明确“不要臆测未出现的内容”,可以避免模型拿通用知识补齐接口定义时编出貌似合理但实际不存在的调用。

4.3 少样本示例:教模型做“减法”而不是“加法”

少样本里不要放“模型应该发现什么”的正向案例,反而要放“什么情况不要评论”的反向案例。比如加一段:diff 中一处方法改动了日志输出顺序,与逻辑无关,不应提为 should;再比如:一个临时调试代码片段出现在 dev 分支,规则里允许存在,则应标记为“建议删除”,而非“阻断”。

这些反向示例的作用,和训练新人的思路是一样的:人会被“最像问题的东西”吸引,模型也是。如果你只教它发现 bug,它会到处找 bug;如果你教它区分“问题”和“需求上下文”,它才会收敛。我给 Hermes 调提示词时,最高频的操作不是加规则,而是删规则加反例。很多团队在接入 AI 审查时体验不好,根源就在这里:他们疯狂往 prompt 里堆“应当”,却忘了告诉它“什么时候不应该”。

4.4 让模型“说人话”:一份评论只能有一个核心问题

生成的评论文本常常会有一种生硬的“AI 味”。我的办法是在提示词里加一条:“message 用一句话说明问题和理由,给出可操作建议,不要输出‘建议优化代码’这类空话”。并且要求它把建议具体到行和函数名,比如“这里user.id可能为空,调用getProfile前建议判空处理”,而不是“建议增强代码健壮性”。这样,即使模型偶尔误判,开发者也更容易判断这个评论是否值得处理。

这里必须给一个重要提示:模型会把行号搞错。它基于 diff 推断出的行号,经常因为 hunk 起始行偏移而错位。如果直接用line字段去创建 inline review comment,GitHub 会报“line must be part of the diff”之类的错误。我在第五章讲评论回写时,会给出一个实际用过的校正方法。

5. 评论回写与多轮交互:从“报告”到“对话”

5.1 三种回写方式的选择

GitHub 上回写评论有三种主要方式:PR 全局评论(review 正文)、逐行评论(pull request review comments)、以及代码建议(suggestion)。三者使用场景完全不同。

  • 全局评论:适合放评审总结和统计指标,比如“本 PR 共发现 2 个 blocker、5 个建议”。
  • 逐行评论:适合针对具体某一行指出问题,也是团队认为最不打扰人的方式。
  • 代码建议:可以给出修复后的代码块,开发者点一下就能应用,适合明确的修改场景,比如“变量名应改为 camelCase”。

Hermes 默认把 Blocker 和 Should 发成逐行评论,把 Suggest 合并进 review 总结;只有触发“严格模式”的时候,Suggest 级别的建议才变成可一键应用的 suggestion 评论。这样评论数量能压到 5 条以内,开发者不至于被刷屏。

5.2 行号校正:用 Git diff 的 hunk 信息对齐评论位置

模型输出里给的行号,写的是分析单元内部的相对位置。实际运行时我写过一段校正逻辑:拿到 diff 文件里的 hunk header,它的格式是@@ -start,count +start,count @@,其中+start表示新文件中该 hunk 的起始行号。按顺序累加 hunk 的偏移量,把模型给出的相对行号换算成 PR 中的绝对行号。

这里用一个简化例子:

def map_line(hunk_start_new, model_relative_line): return hunk_start_new + model_relative_line - 1

真正的实现要考虑多个 hunk、删除行引起的偏移、空行位置等因素。基本逻辑是:在做语义切片那一步,把每个切片对应的新文件起始行号记录下来,等推理完回写评论时直接查表映射。这是成本最低、最不容易错的方案,千万别等模型输出后再试图去猜行号。

5.3 去重与噪音控制:让每个人愿意继续看评论

评论风暴是最让团队反感的行为。Hermes 早期版本跑出来的 review,经常是同一个问题在不同的文件切片里出现好几遍。后来我在合并阶段做了一层语义去重:用规范化后的问题类型加文件名,再加关键函数名组合成去重键。比如,同一类空指针问题在不同位置出现,只保留最前置的一条。

另一个噪音来源,是“建议了太多无关紧要的小事”。我后来给评论系统加了一个简单的评分公式,每条评论的最终输出概率是:严重级权重加上可执行性评分(是否包含具体修改建议),低于某个阈值直接过滤掉。目标不是说每条都必须对,而是要保证即使错的那些评论,也不能让团队因为太吵而取关这个机器人。

5.4 从“单次报告”到“按需对话”:在评论里 @Hermes 追问

做到这一步,Hermes 已经能自动给出第一轮评审意见了。但 PR 是一个动态过程:开发者改了一版之后,机器人应该能跟进,而不是只对最初版本说话。我给它加了事件监听pull_request_review_comment,当有人创建新评论并 @Hermes 时,它会读取当前最新代码状态,结合之前的评审上下文,重新跑一轮分析并追加评论。

这样,整个流程从“一次性报告”变成了一个半交互式 Agent。它不是一个无人值守的裁判,而是可以被追问的助手。开发者在评论里可以写“这个建议在当前分支已经处理了,为什么还提”“你建议改成这样会不会影响某处的调用”,Hermes 就会把相关的上下文拉回来再回答。这部分功能上线后,团队对它的容忍度明显提高了,因为评论区终于像一个正常讨论,而不是机器人在单方面发号施令。

6. 部署形态与稳定性:GitHub Actions 和独立服务怎么选

6.1 两种部署方式的本质区别

Hermes 的部署方式,我建议根据团队规模来决定。如果你的仓库不多、PR 量不大,GitHub Actions 是更快的选择。在.github/workflows/hermes.yml里定义 workflow,监听pull_request事件,跑一个 Python 脚本完成拉取 diff、调用模型、回写评论,整个链路在一个工作流里就闭环了。优势是零服务器成本、配置简单、用 GitHub 托管的运行环境。

如果 PR 量上来了,或者需要复杂的队列、多模型、自定义事件逻辑,建议部署独立服务。独立服务可以用容器编排平台托管,配有持久化队列和任务重试机制。Webhook 接收端和 worker 分离,遇到模型 API 抖动时可自动重试;同时在评论前落库,避免因为中途失败而丢失评审任务。这两种形态甚至可以并存:团队内部跑独立服务给核心仓库用,边缘仓库只挂 Actions 轻量版本。我自己在落地时也是先用 Actions 验证效果,等跑通后再迁到独立服务。

6.2 用 GitHub Actions 快速起步的配置要点

如果你想先试效果,我建议保持入门配置尽量简单。Workflow 的核心就三件事:触发事件、安装依赖、运行评审脚本。有个容易忽视的点:在 Actions 里需要配一个 GitHub Token,权限要设置为能写 PR 评论。如果使用 GitHub App,则还需要额外引入获取临时 token 的动作;如果用 PAT(Personal Access Token),必须小心不要把它放到公开仓库里。

一个最小起步的 YAML 大致长这样:

name: hermes-review on: pull_request: types: [opened, synchronize] jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: '3.12' - run: pip install hermes-cli - run: hermes review env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MODEL_API_KEY: ${{ secrets.MODEL_API_KEY }}

这里fetch-depth: 0的作用是把完整 git 历史拉下来,不要只拉最新一次 commit,因为 diff 的比对需要在正确的 base commit 上进行。如果你用 event 里传的默认GITHUB_TOKEN,它默认权限极小,需要你在仓库设置里调高 job 的写权限,否则评论会写不进去。

6.3 独立服务的稳定性:持久化、重试、幂等

独立服务稳定性的核心,其实是前面 2.2 节提到的队列表和幂等。我在生产环境用了一个表来记录已处理评论的外键(repo + pr_number + head_sha + result_hash),写评论前先查这个外键,重复消费时不二次写入。这样即使某个 webhook 因网络问题被重复投递,也不会出现重复评论。

模型 API 偶尔会超时或者返回 5xx,所以 worker 里必须做退避重试。我的经验是:第一次重试等 5 秒,第二次 15 秒,第三次 60 秒,超过三次就把任务标记为失败并记录到日志里,同时发一个降级通知给管理员,而不是一直无限重试把队列堵塞。因为模型 API 的不稳定不只是网络,还可能是你上下文太大导致的响应超时,无限重试只会放大成本。

6.4 认证和权限管理的几个关键细节

如果你用 GitHub App,私钥文件绝对不能提交进仓库。App 安装后的私钥应该放到密钥管理系统里,运行时注入环境变量。另外,创建评论时要给 App 设置足够的权限:Pull requests 的读写权限、Contents 的只读权限等。权限给得越小,越能避免 App 被滥用。

还有一点很容易被忽略:不要把模型服务的 API Key 放进业务日志里。模型推理出现异常时,通常会把请求内容打出来方便排查,如果你不脱敏,key、token、甚至代码内容都可能流到日志聚合系统里。我在生产环境强制开启请求和响应的脱敏,凡是符合 key 特征的字段统一替换成***。这个习惯救过我一次,强烈建议一开始就加上。

7. 上线之后的踩坑复盘:5 个让我印象最深的问题

7.1 同一个 PR 被重复评论:根因是事件重放

上线第一周,团队成员反馈同一个 PR 总能收到两三条一模一样的评论。排查过程其实不复杂:先看 Hermes 的日志,发现同一个head_sha被消费了两次。再查队列,发现消息队列在消费后确认动作由于网络抖动没执行成功,导致消息重新进入队列。于是加了“按 head_sha + 结果哈希去重”的一层保障,重复消费不再产生新评论。这个问题最麻烦的点不在技术上,而在于它会迅速消耗团队对机器人的信任。所以哪怕牺牲一点实时性,也要把幂等做扎实。

7.2 模型输出非法 JSON,消费端直接崩掉

如果你让模型输出 JSON,它十次里总会有一次给你带个 Markdown 代码块包裹、或者多一个逗号、或者在 message 里出现换行符。直接在解析那一步抛异常,任务就会反复重试。我的做法是:解析之前先做一次轻量清洗,去掉首尾的 ``` 标记、去掉多余空白,再用json.loads解析;解析失败则进行一次模型自动修复尝试,即把原始输出和报错信息拼回给模型,要求它只返回合法 JSON。经过两轮修复后成功率能到 99% 以上。剩下的失败任务进入人工处理队列,不阻塞其它评审任务。

7.3 测试文件的“戏精”时刻:误把测试改动当成业务改动

有一次 Hermes 在一个纯测试文件 PR 里提了一堆“业务逻辑 bug”,比如“data可能为 undefined,访问data.length前建议判空”这样的评论。乍一看没错,但它没意识到那是it.each里的测试数据,根本不需要也不能判空。问题的根源是语义切片时我把所有文件都当成业务代码处理,没有给模型区分文件角色的信号。后来我加了一条规则:分析每个文件前先判断它的类型(源码、测试、配置、文档),在传给模型时明确标出“这是测试文件”,并且把测试专用规则和业务规则分开维护。那次之后类似误报基本消失。

7.4 评论风暴引发的“全员屏蔽”

我没有预料到的一点是,当 Hermes 把 50 多条 Suggest 评论一次性贴到 PR 上,开发者第一反应不是去改,而是直接在通知设置里把它屏蔽了。这也让我下定决心执行“默认严格过滤,只保留高置信度、高价值评论”的策略。我给每类问题定义了一个置信度阈值,与可行动性做加权。比如“空指针”这种明确问题置信度可以高,“代码风格”这种主观问题必须低;低置信度的问题只有出现在核心文件中才会输出。调整后,单条 PR 的平均评论量从 12 条降到了 4 条以内,开发者返回与机器人互动的意愿反而大幅提升。

7.5 差点把密钥直接打在公屏上:加一道最终拦截

最让我后怕的一次,是模型在一个 PR 的 diff 里发现某行测试配置包含一个很像密钥的字符串,于是它很认真地建议“这里可能有硬编码密钥”,并把这段字符串原样写进了评论。我是在发布前检查时发现的。如果评论被推送到 GitHub,敏感信息就会长期留在仓库的评论记录里。从那以后,我在评论回写之前加了一道脱敏过滤:凡是符合密钥格式、或者与仓库已配置的 secrets 相似的值,一律替换成[REDACTED]。这已经不只是功能问题,而是底线问题,强烈建议每个做 AI 评审的都把这一步当成强制要求。

8. 实际效果与我对自动化评审的边界判断

Hermes 上线两个月后,我拉过一次数据。每天 30 个 PR 的人工平均首次响应时间,从 3 小时以上降到了 40 分钟以内;PR 从提交到拿到至少一轮结构化意见的时间基本是 5 分钟。更重要的是,它的评论里可以确认的真实有效比例稳定在 60% 以上(剔除误报之后),这个比例在“辅助性评审”这个定位下已经非常够用。

但我必须说清楚我的边界判断:代码审查的核心结论,应该由人来下。Hermes 能让人省去通读 diff、找琐碎毛病的时间,但它不能理解这次上线背后的商业意图。它不知道你为了赶版本在某个边界场景故意牺牲了部分稳定性;它也不知道某个看似很丑的写法,是因为上下游接口尚未统一。所以我在团队里的定位是“第一轮 Reviewer”,而不是“最终审批人”。它还做不了大规模跨文件跨服务的影响面判断,那是架构师的工作,也是人独有的综合判断力所在。

如果你也想做类似的东西,我给三个建议:第一,开始就先分清主次,把 diff 处理、工具链跑通、能稳定输出“不讨厌”的评论,再考虑更复杂的功能;第二,模型能力提升很快,但提示词和切片才是真正的护城河——同样的模型,不同的切片和提示词,结果差别可能很大;第三,想清楚什么时候不接入也比较重要:如果你的仓库几乎没有人认真看 PR,机器人只会输出一堆没有人修的问题,并不会让团队工程文化自动变好。

最后说一个小实操技巧:在本地调试 Hermes 评论回写时,我通常直接构造一个假的pull_request事件 payload,发到一个测试仓库,而不是在线上仓库里一边开发一边被真实 PR 触发。你可以用一个本地脚本模拟 GitHub 的 API 调用,把评论写到测试仓库里,整个过程迭代速度会快很多。这个习惯帮我省下了大量调试时间,也希望能帮你少走一些弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 1:30:28

2027文献综述生成工具真实文献数量与写作质量测评

2027文献综述生成工具真实文献数量与写作质量测评 在新能源材料与钙钛矿太阳能电池(PSCs)界面钝化工程及稳定性机理方向的硕士开题与论文写作初期,文献综述的撰写常常耗费大量精力:2027文献综述生成工具真实文献数量与写作质量测…

作者头像 李华
网站建设 2026/9/7 1:28:00

提示词优化工具实操指南:从模糊想法到结构化提示词

一句“帮我写个文案”,放在任何大模型面前,大概率只会得到一段正确但普通的回答。真正想让模型输出稳定,问题往往不在模型,而在提示词没有把任务边界说清楚。GitHub 上这类拿下三万星标的 AI 提示词优化项目,解决的就是…

作者头像 李华
网站建设 2026/9/7 1:26:15

AI Agent 面试题 287:System Prompt中的工具使用指令如何优化?

🔥 AI Agent 面试题 287:System Prompt中的工具使用指令如何优化?摘要:本文深入解析了「System Prompt中的工具使用指令如何优化?」这一 AI Agent 领域的核心面试题。文章从 System Prompt 工程 的基本概念出发&#x…

作者头像 李华
网站建设 2026/9/7 1:26:08

基于物联网的光伏路灯设计|毕设答辩|单片机项目|毕设

一、項目介绍 摘 要 随着能源危机与环境问题日益严峻,高效节能的光伏路灯成为城市照明发展的重要方向。本文提出一种基于物联网技术的光伏路灯设计方案,通过集成传感器网络、通信模块与智能控制系统,实现路灯的远程监控、智能调光与故障诊断…

作者头像 李华