大多数“AI代码审查”演示,本质就是一个大语言模型调用,配上一段精心设计的提示词。效果看起来不错,但这压根不是真实团队协作的审查方式。真实场景里,有人死磕边界条件,有人专挑命名规范,有人只关心上线后会不会拖慢性能。最后还得有个人拍板:这PR到底合并不合并。
一位开发者最近提交给SigNoz黑客松的项目,把这个认知差距直接做成了系统。他搭建了一个由三个专业AI代理和一个仲裁代理组成的审查团队,然后给整个系统接上了可观测性工具。结果发现,很多事情和他预想的完全不一样。
这三个专业代理分工明确。逻辑审查代理只关注边界条件和逻辑漏洞,风格审查代理只看命名规范和PEP 8违规,性能审查代理则专门评估时间复杂度和生产环境隐患。每个代理的系统提示词都被严格限定在自己的职责范围内,不允许越界。仲裁代理负责读取三份独立审查意见,整合成一份最终裁决,当不同代理之间存在分歧时,它要明确指出冲突点。
整个流程涉及四次连续的API调用,每次调用都有自己的延迟和token消耗。项目开发的早期阶段,作者手里唯一的调试工具是print()语句。如果仲裁代理给出了一个奇怪的判决,他无从快速判断到底是逻辑审查代理产生了幻觉,还是仲裁代理在整合时出了问题。如果某次运行感觉变慢了,他也看不出四个代理中哪一个成了瓶颈。
这正是SigNoz这类可观测性平台要解决的核心问题。作者用OpenTelemetry对每一个代理调用进行了埋点。三个专业代理和仲裁代理各自运行在独立的span中,分别标记为agent.logic_reviewer、agent.style_reviewer、agent.performance_reviewer和agent.moderator。这四个span全部嵌套在一个名为code_review_session的父span下,所以一次完整的审查运行会以一条trace的形式呈现,包含四个子span。每个span都携带了对调试AI代理真正有价值的属性:模型名称、输入和输出的token数量、延迟时间,以及代理输出内容的预览。
当这套系统接入SigNoz并运行起来后,几个之前完全不可见的事实立刻浮现了出来。测试用例是一个故意写得有问题的代码文件,包含一个在空输入时除零的函数、一个O(n²)复杂度的重复检查逻辑,以及几处PEP 8违规。性能审查代理始终是最慢的那个环节。表面上看,它不需要处理更多的token,但它的系统提示词要求它逐行推理代码的时间复杂度。这一特征直接反映在它span上的延迟属性中,数值明显高于另外两个专业代理。
token成本的分布也出乎意料。作者原本以为仲裁代理会是最昂贵的步骤,因为它需要读取三份审查意见和原始代码。但在实际运行中,风格审查代理的输出往往最长,因为它会逐条列出每一个命名违规的细节。这个发现是在对比了各个span中的llm.output_tokens属性之后才浮现的。如果没有这些可观测性数据,开发者可能还会长期误判成本结构的分布。
从工程角度看,这个项目的价值不在于提示词设计本身。四个串联的API调用背后,真正有趣的问题是:当一个系统变得足够复杂,涉及多个环节的连续推理时,你如何知道系统内部到底在发生什么?可观测性带来的不是理论上的改进,而是让隐形的瓶颈和资源消耗变得直接可见,让调试从猜测变成了定位。
热门跟贴