ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Hermes实战:结合规则引擎与LLM的GitHub PR自动化代码评审

2026/9/5 22:38:05 拓冰建站 浏览量
Hermes实战:结合规则引擎与LLM的GitHub PR自动化代码评审 先从一个我自己的真实场景说起。周一上午打开 GitHubPR 列表里躺着十几条待审请求而这一天的计划本来是开发新功能。逐条点开、扫几眼、回一句“LGTM”很多人都做过这种事。这么操作下来代码评审基本形同虚设。后来我开始研究能不能让工具替我先做一轮自动评审把精力聚焦在真正需要人判断的地方最终把方案收敛到一个叫 Hermes 的自动化代码评审智能体上。它跑在 GitHub Actions 或独立 Docker 服务里收到 PR 事件后自动拉取代码变更用规则引擎加大模型语义理解做双路审查再把带文件路径、行号和严重级别的评论直接回写到 PR 上。对于每天有大量 PR 的中小研发团队或者一个人维护多个开源仓库的独立开发者这套东西都能明显提升 review 的覆盖率和一致性。这篇内容把整体思路、部署步骤和实际运营中踩过的坑都整理成文可以直接照着试。1. 为什么我把 GitHub PR 自动评审交给 Hermes1.1 人工评审的两个死穴没时间和“抹不开面子”先复盘人工评审最容易翻车的地方。最典型的场景就是 PR 挂了两三天没人理作者催一下评审人点开发现改动太多根本不想从零开始看于是留下一句“整体思路没问题细节我们再对齐”然后 Approve。这种评审对代码质量没有任何帮助只是给合并流程补了个章。另一个问题是社交压力。同一个团队里你很难对一个很熟的同事说“你这段逻辑写得不行”。很多评审人会把阻塞性问题降级成建议把建议藏在评论末尾最后作者也没有认真处理。时间一长评审变成了一种“确认过眼神”的仪式感。我当时的判断是评审必须能被机器稳定触发、按统一标准输出、不带情绪同时又能理解业务逻辑层面的模糊问题。前者靠固定规则就能解决后者必须依赖具备代码理解能力的大语言模型。Hermes 把这两者结合在同一个工作流里这才是我决定试它的主要原因。1.2 Hermes 的核心价值不是替代人而是让评审形成闭环Hermes 做的事情本质上是把“评审”从一个依赖人的环节变成一条自动触发的流水线。每次开发者提交 PR它会根据事件类型决定是重新审查还是增量审查先跑规则扫描再用 LLM 对代码变更做语义分析最终生成结构化评论。这套机制最有价值的地方在于闭环。人工评审经常出现“评论完没人改”的情况而 Hermes 接入后评论会在 PR 里持续可见作者修改后再 push它会基于新 commit 重新分析如果旧问题已经修复就不会再提。整个从“提交→发现→修复→确认”的过程被固化到流程里而不是靠一个人记住上次说了什么。Hermes 不是去替代人的最终判断而是把那些“一眼能看出来的问题”和“需要翻上下文才能发现的隐患”提前捞出来人只需要处理它提出的一小部分关键项。这个定位很重要如果一开始就指望它完全替代资深评审结果通常会很失望。1.3 什么仓库最适合引入 Hermes如果你们团队符合下面任一特征Hermes 的投入产出比就会很高仓库活跃每天 PR 数量在 5 到 20 条之间人工无法逐条仔细看。团队只有两三个核心开发者但承担了大量维护任务没有专职 QA。开源项目外部贡献者水平参差不齐需要一套统一的入门门槛检查。代码涉及安全敏感信息、支付逻辑或数据隐私对遗漏的容忍度低。反过来如果项目还在原型阶段代码风格和架构每天都在变这时候跑自动评审会产生大量无效评论既浪费 token也容易让人产生“机器人总在瞎说”的抵触情绪。建议先把项目结构和团队规范稳定下来再引入这类工具。成本方面不用担心太多。单次 PR 评审的 token 消耗取决于 diff 大小和上下文窗口日常小 PR 也就几千到几万 token相比花一个人一小时去 review经济性高得多。2. Hermes 如何自动审查一次代码变更2.1 从 PR 事件到评审任务整条链路是怎么串起来的Hermes 的工作触发点来自 GitHub 的 PR 事件。最常见的是pull_request的这三种 typeopened、synchronize、reopened。opened代表新 PR 创建synchronize代表作者又 push 了新 commitreopened则是重新打开已关闭的 PR。Hermes 拿到这些事件后会先判断当前任务是该走全量评审还是增量评审。大多数实现是创建 PR 时做完整审查后续 commit 到达时只检查变更的部分避免每次都重复处理整个 PR。增量评审的策略很关键否则一个大 PR 改十次模型就要重复处理十轮成本和延迟都不可控。如果走独立服务模式Hermes 会以一个后台 Agent 的形式长期监听 Webhook类似一个常驻的“评审班长”把收到的任务放到队列里逐个处理。如果走 GitHub Actions 模式就是由 GitHub 的 Runner 临时拉起一个容器执行一次跑完就销毁。两种模式的任务生命周期不同但核心审查逻辑一致。2.2 diff 提取、噪声过滤和上下文增强自动评审的第一步永远是拿代码变更。Hermes 会调用 GitHub API 获取这个 PR 的 diff把每个文件的增删行整理出来。这里有三个必须处理的细节。第一diff 里的变更行参数是 GitHub 用来定位评论位置的核心信息Hermes 需要精确区分新增行和删除行才能把评论锚定到正确的位置。第二有些文件根本不应该被 LLM 阅读比如package-lock.json、go.sum、生成后的代码、二进制文件等。这些文件噪声大对模型理解没有帮助通常只保留一个更新记录或直接跳过。第三很多问题是只看 diff 看不出来的模型如果不知道函数原本的职责、调用方的预期很容易把正确代码误判为问题或者反过来漏掉真正的隐患。所以 Hermes 在审查单个文件时会额外读取这个文件在 base 分支中的完整上下文必要时把相关的函数定义和调用点一并提供给模型。这一步对误报率的影响非常大。很多团队一开始自己写提示词调模型做评审效果不好很大程度上就是因为只把 diff 丢给了模型没给上下文。2.3 规则扫描和 LLM 语义分析怎么分工我接触过不少“AI 自动评审”方案要么纯靠正则规则要么纯靠 ChatGPT 总结。纯正则的局限是只能查固定模式换个写法就失灵纯靠 LLM 的问题是输出不稳定同一个问题两次审查可能得出不同结论而且模型容易一本正经地胡说八道。Hermes 的做法是把两者叠加。规则引擎负责确定性问题比如硬编码密钥、日志里打隐私数据、禁用 API 调用、遗留的 TODO 等这类检查有明确的判定标准不需要模型“思考”。LLM 语义分析负责另一类问题例如某段并发逻辑可能导致竞态条件某个函数在异常路径中吞掉了异常或者某个边界条件没处理。两类问题在输出形式上也不一样。规则引擎查出的结果通常直接给出固定文案LLM 分析的结果则会附上理由、严重级别和修改建议。整体效果是硬性错误一个不漏软性设计问题也能被覆盖到。检查维度规则引擎LLM 语义分析判定方式确定、可重复概率性、依赖模型典型问题密钥泄露、禁用方法、TODO 遗留并发隐患、逻辑边界、异常吞噬误报控制低需要提示词与阈值控制输出形式固定规则文案自然语言加行号建议2.4 评论是怎么写回 PR 的分析完成后Hermes 会通过 GitHub API 在 PR 上创建 review。这里有两个关键细节。针对具体代码行Hermes 会使用pull request review comments接口把评论放到对应文件行的位置。这种内联评论对开发者最友好因为修改代码的时候能直接看到上下文。对于无法定位到具体行的问题或者全 PR 层面的整体评价它会在 PR 的 review body 里做总结。在评论内容上建议明确要求输出格式包含文件路径、行号、严重级别、问题描述、修复建议。有了严重级别开发者才能快速判断哪条需要立刻处理哪条可以延迟到后续优化哪条只是风格建议。如果所有评论都像一个模子里刻出来的“建议考虑 xxx”没人愿意点开看。示例输出 - 文件src/services/payment.ts第 142 行 - 严重级别blocker - 问题将原始 access token 写入了日志 - 建议使用脱敏后的摘要信息替换完整 token避免泄漏3. 5分钟部署 HermesGitHub Actions Docker 快速接入3.1 三种接入方式到底怎么选Hermes 的部署方式大体分三类。很多人第一次搜到 Hermes 时经常会看到 Docker 镜像、桌面端 Studio、Agent 常驻服务等不同形态有点凌乱。我帮你理一下。第一种是 GitHub Actions 方式把审查作为一个 Job 写进仓库的 workflow 文件里。适合单个仓库快速验证零服务器成本GitHub 托管 Runner 直接跑配好 Action 后一提交就生效。第二种是独立 Docker 服务适合需要同时监听多个仓库、想统一保存审查历史、还要接自己团队内部门禁的场景。第三种是桌面端或 Studio 形态通常在本地运行有一个可视化面板可以查看当前审查队列、历史记录和参数配置适合个人项目或前期试验。不要一上来就搭独立服务。先用 Actions 跑通感受一下评论质量和误报率确认它真的对团队有帮助再考虑是否升级。接入方式适合场景基础设施备注GitHub Actions单仓库快速试用无每个仓库都要配一次独立 Docker 服务多仓库、统一管理审查历史一台服务器或容器平台需要配置 WebhookStudio / 桌面端本地开发、个人测试本地 Docker 环境适合观察具体审查过程3.2 最快路径在 GitHub Actions 里跑起 Hermes下面我给一个最小可用的 workflow 示例。不同版本的具体命令名可能有差异整体结构是一致的。name: Hermes PR Review on: pull_request: types: [opened, synchronize, reopened] jobs: hermes-review: runs-on: ubuntu-latest permissions: contents: read pull-requests: write issues: write steps: - uses: actions/checkoutv4 with: fetch-depth: 2 - name: Run Hermes review env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} HERMES_LLM_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} HERMES_LLM_MODEL: deepseek-chat run: | docker run --rm \ -v $PWD:/repo \ -e GITHUB_TOKEN$GITHUB_TOKEN \ -e HERMES_LLM_API_KEY$HERMES_LLM_API_KEY \ -e HERMES_LLM_MODEL$HERMES_LLM_MODEL \ your-registry/hermes:latest \ review --repo-path /repo --pr-number ${{ github.event.pull_request.number }}这里解释几个关键点。permissions非常重要。pull-requests: write是 Hermes 在 PR 上创建评论的权限少了它程序跑完但评论发不出去日志里又没有明显报错排查起来很麻烦。contents: read用来读取仓库代码。不要把默认的GITHUB_TOKEN直接写进代码或日志它在 Secret 里自动注入就行。fetch-depth: 2用于获取最近两个 commit这样 Hermes 能判断当前 PR 相对于 base 分支多出了哪些变更如果只需要当前 commit 和上一个 commit 的 diff这个深度就够了太大反而拖慢检出速度。模型 API Key 放在仓库的 Secrets 里。以 DeepSeek 这类兼容 OpenAI 接口的模型为例在 Git仓库 page 的 Settings → Secrets and variables → Actions 里新增DEEPSEEK_API_KEY然后把 workflow 里的变量名对应改好。Hermes 的模型层是插件式的不绑定特定厂商所以你想换其他模型只需要调整模型名、API Key 和 Base URL。3.3 更完整的独立 Docker 部署姿势如果你的团队有多个仓库每个仓库都复制一份 Action 会很难维护规则更新一遍要操作十几次。这时候独立部署更合适。假设你已经准备了 Dockerfile 或官方镜像可以参考下面这个docker-compose.yml的结构。services: hermes: image: your-registry/hermes:latest container_name: hermes-reviewer restart: unless-stopped ports: - 8080:8080 environment: GITHUB_TOKEN: ${GITHUB_TOKEN} HERMES_LLM_API_KEY: ${DEEPSEEK_API_KEY} HERMES_LLM_MODEL: deepseek-chat HERMES_WEBHOOK_SECRET: ${HERMES_WEBHOOK_SECRET} volumes: - ./config:/etc/hermes环境变量的作用很清楚环境变量作用注意事项GITHUB_TOKEN读取 PR、创建评论、拉取代码需要具备 repo 和 pull_request 的写入权限HERMES_LLM_API_KEY调用大模型接口不要把真实 Key 直接写进 compose 文件HERMES_LLM_MODEL指定模型名以模型服务商实际支持为准HERMES_WEBHOOK_SECRET校验 GitHub Webhook 请求来源防止恶意构造请求触发垃圾审查容器起来以后去 GitHub 仓库的 Settings → Webhooks 里新建一个 WebhookPayload URL 填http://你的服务地址/hermes/webhookContent type 选择application/jsonSecret 填你刚才设置的HERMES_WEBHOOK_SECRETEvents 勾选 Pull requests。独立服务的好处是可以把审查规则配置放到一个共享目录里所有仓库共用。想加新规则时只改一份配置文件再重启容器即可不用一处处去改 Actions。3.4 接入后怎么验证真的生效了部署完先别急着把大量 PR 交给它用一个小 PR 做冒烟测试。建议故意提交一段有明显问题的代码例如在代码里硬编码一个 API Key或者在日志里打印用户邮箱然后观察 Hermes 是否会分别从规则和语义层面识别出来。如果发现评论没有出现按这个顺序排查先去 Actions 日志或容器日志里确认任务有没有被触发再看调用模型 API 时是否返回了鉴权错误最后确认 GitHub Token 的权限范围。大部分首次接入失败都是这三个原因和代码审查逻辑本身没多大关系。4. 把 Hermes 调教成团队评审员规则、模型与提示词的组合技巧4.1 为什么不能直接拿通用提示词跑评审很多 AI 评审工具给人“鸡肋”的感觉不是模型不行而是没有给它约束。你直接对模型说“请 review 这段代码”它大概率会生成一段万能回复“整体结构清晰部分边界条件需要处理建议增加单元测试并优化性能。”这种废话放到任何 PR 上都成立没有可执行价值。要让评审真正落地必须定义三层内容哪些文件要审、哪些文件不审、问题分几级、每一级怎么处理。Hermes 的可配置项越多越需要一开始就把这层梳理清楚否则自动化的规模越大产生的无效噪音也越多。一个典型的配置文件可能长这样review: ignore_paths: - src/generated/** - vendor/** - *.lock rules: - name: no-hardcoded-secret severity: blocker scan: content - name: no-log-credentials severity: major scan: content - name: no-todo-in-merge severity: minor scan: code output: format: markdown include_suggestion: trueignore_paths用来排除自动生成的代码、依赖目录和锁文件。生成代码如果也被送进模型审查结果基本没有意义还会白白消耗 token。rules里面定义的几类检查每个团队都可以按自己的红线来配置。注意规则不是越多越好每条规则后续都会带来维护成本。一开始只保留会真正造成事故的检查项例如密钥泄露、日志打印敏感数据、禁用历史上出过事的 API其他都先放一放。4.2 模型选择DeepSeek 和 Ollama 私有化部署怎么取舍Hermes 的模型能力直接决定语义审查的质量选型时主要看三点代码理解能力、输出稳定性、单位成本。我自己的项目中大量使用 DeepSeek 的 chat 模型核心原因是它对代码上下文的理解能力比较强在中文技术场景下的表达也准确不会频繁给出含糊其辞的结论。对大多数中小团队的 PR 评审场景每千 token 的成本比做一次完整代码 review 的人力成本低了几个量级这种性价比非常明显。如果团队代码有严格的保密要求不希望发送到外部 API那就选 Hermes 的本地模型部署方式比如通过 Ollama 加载开源模型。本地模型的优势是数据不出内网劣势是对服务器显存有要求同时模型判断能力通常比商业化 API 版本弱一截。要在“隐私边界”和“评审质量”之间做权衡。无论选哪家模型都建议把模型的temperature参数调低控制在 0 到 0.2 之间。代码评审需要的是确定性不是创意写作温度过高会让模型偶尔发挥出“奇思妙想”把不存在的 bug 说得头头是道。4.3 提示词层面的几个关键约束优秀提示词的核心不是让模型多聪明而是约束它不要在哪些方面胡说。我常用的做法是给模型三条明确的指令。第一所有判断都必须引用 diff 中的具体行号和原代码片段如果找不到出处就不要断言。第二如果对问题不确定降级为建议或疑问不要用斩钉截铁的语气描述不确定的问题。第三输出结构必须固定每条评论要有“文件路径、行号、严重级别、问题描述、修复建议”五个字段禁止输出空泛的总结。这套约束能极大减少模型“抠字眼式误报”的情况。模型很容易看到代码里有个TODO就提醒你应该补功能但实际可能这个 TODO 是后续迭代计划。加上“必须基于证据”的约束后它会更倾向于只报自己确认真实存在的问题。4.4 评审级别怎么映射到门禁策略Hermes 输出的问题级别大约可以划分为 blocker、major、minor、nit 四档。不同级别在实际工程中要有完全不同的处理方式。级别含义建议动作blocker阻断合并可能引发安全事故或严重逻辑错误必须修复后才能合并major明显质量缺陷可能导致线上问题合入前应修复或讨论minor代码风格或局部优化空间不强制建议后续处理nit措辞、命名、格式等小问题可不处理接入 CI 门禁时我建议只把 blocker 级别的结果映射为失败的 status checkmajor 及以下级别先作为参考。如果一上来就把所有 minor 问题都设为合并条件开发者会被大量小问题淹没对整条流水线的信任度会快速降低。等运行一段时间确认质量稳定后再逐步收紧门禁。还可以在规则里预设例外机制。比如代码中明确写了// hermes: skip注释Hermes 就会跳过对应位置的检查。这给开发者留了一个有意识的例外通道而不是只能跟机器人对抗。5. 运行中踩过的典型问题误报、刷屏、超时怎么排查5.1 评论没有出现或只出现在日志里遇到过太多次了workflow 显示跑成功但 PR 上没有评论最后查出来是 Token 权限不够。GitHub 的GITHUB_TOKEN默认权限在新老仓库设置中可能不一样如果只给了contents: readHermes 能读代码但没有pull-requests: write权限就无法创建 review。排查时先看 Actions 日志或者独立服务的日志看它对 GitHub API 的响应是什么。如果返回403十有八九是权限问题。还有一个隐蔽点如果是 Code Owner 设置的仓库需要额外确认 bot 账号或 Token 对应的身份是否能通过 CODEOWNERS 约束。反正先在最小仓库里跑通再铺到更大范围最稳妥。5.2 一个 PR 刷出二十条评论怎么处理一个大型 PR 经过 LLM 审查后很容易生成大量评论开发体验会非常差。许多人因此直接关掉自动评审宁可回到人工 review。解决思路有三个。第一按严重级别做截断只输出 major 及以上级别的问题minor 和 nit 统一在 summary 里聚合。第二对超大 diff 做切片不要一次读完整的大 PR按文件或按逻辑块分批处理。第三在 Git 层面对重复评论做状态管理。作者 push 新 commit 后Hermes 应只针对新的 diff 产生增量评论不要重复宣读旧问题已经修复的问题还要能自动标记为“已解决”。如果 Hermes 本身没有对 PR 级别的状态进行缓存可以考虑在项目里约定一个规则把上一次所有评论的 ID 或标题 hash 保存下来在新结果里去重。这样每次 push 之后PR 上只会看到新增或未解决的问题。5.3 模型幻觉式误报怎么压下去模型幻觉是这个领域最难根治的问题。有一个印象很深的案例代码中某个函数接收了一个时间戳参数模型在上下文里看到另一个地方有人把这个字段当成日期处理于是断言类型不匹配实际上两处根本不是同一个变量。这种误报会让开发者觉得“机器人根本不懂项目”。减少幻觉的核心方法是限制模型的信息来源。Hermes 必须明确区分“我从 diff 里看到的事实”和“我推测的结论”。我建议在配置里开启“证据牵引”模式强制模型输出前引用具体文件和行号。如果找不到证据那一条结论应该被标记为“疑问”并降低严重级别而不是高置信度地指摘代码。另外要建立反馈闭环。如果团队发现某类幻觉频繁出现比如模型对多态调用理解不够、对宏展开判断错误就把这类问题加入“不检查清单”把规则引擎里更确定性的检查作为兜底。AI 评审本质上是个持续调优的过程不是在第一天就完美的。5.4 审查超时和并发打满大 PR 一次要读很多文件模型接口并发可能被限流或直接超时。遇到这种情况我的经验是不要试图让一次请求处理整个 PR而是让 Hermes 按文件或目录拆分任务再控制并发数。并发太大上游 API 会拒绝服务并发太小一个 PR 要等很久。另一个建议是设置合理的超时时间并为模型响应做断线重试。LLM 输出有时候会因为网络原因中断完整 JSON 没拿到Hermes 应该能重试而不是直接把半截结果当评审意见。配置层面可以增加retry参数并在日志中保留请求耗时方便观察瓶颈到底在 GitHub API 拉代码还是模型生成结论。5.5 常见问题速查表现象可能原因排查方向任务没触发Webhook 没配置或事件类型不对看 GitHub 的 Webhook 最近投递记录评论没发出来Token 权限不足或 PULL_REQUEST 事件未写入检查 workflow 权限和 Secret评论质量忽好忽坏模型温度过高或提示词没有约束证据来源调低 temperature加强输出格式指令大 PR 总是超时单次请求包含内容太多按文件拆分任务调整并发度反复评论同一个问题缺少去重状态启用状态缓存按 commit 做增量审查审查了不该看的文件缺少 ignore 路径在配置里排除生成目录和锁文件5.6 公共仓库和私有仓库的安全边界最后单独提醒一下安全。自动评审工具本身需要高权限 Token这会对仓库形成一定风险。在私有仓库中Token 或 API Key 不要直接硬编码进 workflow 文件也不要写进 compose 文件后推到任何共享仓库。对于公共开源项目要格外注意规则文件里是否包含内部路径、内部服务名或其他本不该公开的信息。如果 Hermes 会把评审日志传送到第三方模型 API需要提前确认这些数据是不是可以被外部服务处理。保密要求高的团队建议选择本地模型路线甚至可以在内网单独拉一个 Hermes 实例不让请求离开自己的网络环境。这个问题很多人接入前不会想到等出了事才处理就晚了。我在实际使用中最大的体会是Hermes 这类自动化代码评审工具不是用来让人不看 PR 的它的作用是确保“没人看的 PR 至少被认真读过一遍”。它不睡觉、不客气、不会因为和谁关系好就放水。但反过来它也会一根筋地重复提醒偶尔还会判断过头。所以在接入初期一定要控制范围先让它只输出参考意见等团队对评论质量建立起信任之后再逐步把门禁权限交给它。最后再分享一个很实用的小技巧。我维护的一个开源项目里会把需求描述中的验收点解析成 checklist 放在 Hermes 的总评开头。作者每完成一项就在回复里勾选并说明下一轮推送时 Hermes 会结合新的代码状态更新 checklist。这种做法让 PR 的评论历史意外地变成了一份自动同步的“验收记录”后续回溯问题时非常有帮助。现在这个方案还在继续演进我计划再扩展机器人命令例如在评论里回复特定指令就能触发重新审查让 Hermes 真正变成一个团队每天都在用的工程设施。