首页 / 文章 / 利用大语言模型与持续集成棘轮机制评估 GraphQL 模式设计债务

利用大语言模型与持续集成棘轮机制评估 GraphQL 模式设计债务

如何使用大语言模型审查工具及1至5分的评分系统来发现新拉取请求中的主观性GraphQL设计问题,并梳理现有模式中的技术债务。

1929 词

无论风格指南有多完善,当数十甚至数百名工程师在多个产品领域不断修改同一个GraphQL架构时,该架构终究会出现偏差。代码检查工具能够发现一些机械性的问题,但更棘手的则是需要主观判断的情况:本应作为枚举类型的String,会无限增长的列表,以及实际上从未返回null值的可空字段。本文介绍了一种针对这类问题的两阶段解决方案:一种是在拉取请求阶段利用大语言模型辅助审查,从而防止新的设计缺陷产生;另一种则是对现有架构进行评分评估,将旧有的缺陷转化为有优先级且可追踪的任务清单,并通过持续集成机制加以管控。

为何API质量会成为一个系统问题

在仅有少数工程师的情况下,保持 API 的一致性主要依赖于大家的共同认知。大家坐在一起,互相审查架构变更,最终形成统一的规范。但随着组织规模的扩大,这种方式不再可行。新功能不断推出,旧有的惯例与新的规范共存,而最初制定规范的团队认为显而易见的决策,却会被那些从未参与过制定的团队以不同的方式应用。

此时就有三个问题需要得到答案,而且这些答案不应依赖于任何单个审查者的判断:

  • 当多个团队同时编辑架构时,如何保持 API 设计的一致性?
  • 如何确保新类型和字段遵循当前的最佳实践?
  • 如何找出那些在相关最佳实践出现之前就已设计的 API 部分?

前两项与预防措施相关。第三项涉及考古学,也是大多数治理工作会忽略的部分。

代码检查规则终止之处与人工判断开始之处

大部分API标准都是机械性的,静态分析能够很好地处理它们。命名规范、已废弃字段的使用、必填描述以及统一的错误格式,这些都是模式中的二元属性:某个字段要么符合规则,要么不符合,代码检查工具可以判断出结果。

其他标准则无法简化为明确的规则。典型例子包括:

  • 这个String类型应该设为枚举吗?
  • 这个列表需要分页处理吗?
  • 这个Int类型应该设为自定义标量吗?
  • 这个可为空的字段可以安全地改为不可空吗?
  • 这种结构是否与API中其他类似概念的建模方式一致?

这些问题都没有无需上下文的解决方案。返回 String 类型,甚至是未类型化的 JSON 数据,在某些情况下是正确的。但要判断这种做法是否正确,需要综合考虑三方面:模式声明、其背后的解析器实现,以及向客户端暴露这些数据的意图。只有综合这三方面,才能判断哪种数据格式最有利于客户端使用。

企业通常通过代码审查、与平台团队的交流时间以及书面指南来处理这一问题。这些方法虽然有效,但扩展性较差。交付压力会缩短审查时间,平台团队无法查看每个仓库中的所有模式变更,而且最佳实践的发展速度往往快于旧 API 的修订速度。这就导致了两个相关问题:防止新的设计债务产生,以及发现已存在的设计债务。

向左移动:用于模式变更的 LLM 审核工具

该系统的前半部分将 API 设计规范编码为自动代码审查工具。其目的并非取代人工审查员,而是为他们提供另一双眼睛,专门检查那些在常规拉取请求审查中容易被忽略的问题。让平台团队亲自审批所有仓库中的每一处 GraphQL 变更并不可行,而将标准规则嵌入到可遍及各处的 AI 审查工具中则可行。

由于该工具不仅能看到架构差异,还能理解上下文而不仅仅是语法结构。它会读取声明、对应字段的实现代码以及相关规则文本,然后提出具体问题。以下是两条具有代表性的评论:

  • 名为 updatedAt 的字段被定义为 String 类型。如果解析器返回的是 ISO 8601 格式的时间戳,那么应该使用专用的 ISO8601DateTime 类型。
  • Company.employees 返回的是普通列表。由于公司的员工数量没有上限,该字段应当返回分页的数据。

这些都不是代码检查工具能够可靠识别的问题。那种规定“以 At 结尾的字段必须是日期类型”的规则会引发误报,而且还会忽略 lastModified;而要求“所有列表都必须支持分页”的规则则不适用于返回三种支持货币类型的字段。大型语言模型可以查看解析器实际的处理方式。

关键在于时机。在 API 尚在设计阶段时就发现这些问题成本较低;而等到客户已经采用该架构后再发现问题,则需要经历废弃周期和迁移过程。

回顾过去:评估现有的架构

对于已存在的部分,预防措施毫无作用,而在成熟的 API 中,这类部分占比很大。其中一些甚至早于现行标准出现;有些则是为了解决当时存在的矛盾而做出的折中方案;还有些则因为不同团队以各自方式对同一概念进行建模而导致的不均衡。因此需要一种方法来回顾过去。

该系统的后半部分是一个批处理流程,用于补充正在解析架构的静态分析工具。其处理流程如下:

  1. 逐个领域遍历架构,筛选出那些需要依赖主观设计判断的字段或类型。
  • 将模式声明与相关的实现代码收集在一起。
  • 将该上下文以包含书面 API 设计规范的提示发送给大语言模型。
  • 询问模型该字段是否似乎违反了其中的某项主观规范。
  • 将结果以分数及书面解释的形式存储下来。
  • 按产品领域或负责团队汇总分析结果。
  • 第一步对于控制成本和减少冗余信息非常重要。没有必要对那些已经通过确定性检查分类的字段再询问模型;大语言模型只需处理确实需要判断的候选项。

    为何1到5分的评分优于通过/失败判定

    由于这些都属于主观判断,强行将每个分析结果归为二元结论会浪费信息。相反,每个字段都会获得1到5分的评估分数:

    • 1:该字段的表现符合设计预期。
    • 2:信号较弱,但应该没问题。
    • 3:需要人工检查。
    • 4:该字段很可能违反了相关规则。
    • 5:该字段是应当避免的典型案例。

    具体来说:用于存储用户输入任意文本的String字段应处于1附近。而名为errorCode、其解析器只能返回三个预定义值之一的String字段则应处于5附近,因为它实际上就是枚举的变体。

    分级评分比单纯的违规列表能提供更有用的信息。团队可以先关注置信度较高的4分和5分,同时也能看到那些需要进一步核查的低置信度区域。评分体系的中间区间还有另一用途:多个3分则表明平台的规则表述或提示存在模糊之处,这为优化判断提示提供了反馈,从而让结果更具确定性。

    如果构建类似系统,请要求模型输出结构化数据(将评分和解释作为独立字段),这样就可以在无需解析文字的情况下存储和汇总结果。同时要将规则文本及评分标准与提示一起版本化管理,以便追踪评分变化背后的规则变动。

    将发现转化为行动

    数据库中的分数本身并不会自动发生变化。通过按领域将它们汇总到仪表板中,可以让各负责团队清晰地了解其所在领域的 API 设计缺陷:不是零散的案例或偶尔的评审意见,而是一份需要迁移的字段和类型的优先级列表。

    同样的数据也有助于推动持续集成进程。重点不是一次性解决所有问题,因为对于拥有众多生产环境客户的大型 API 来说这并不现实。关键是在现有问题逐步得到改善的同时,确保情况不会进一步恶化:

    • 新的架构变更必须符合当前标准。
    • 现有的问题会被记录为已知的缺陷,而不会被悄悄忽视。
    • 随着团队逐步迁移或废弃旧有的模式,允许的缺陷阈值会逐渐收紧,从而防止已解决的缺陷再次出现。

    在代码清理过程中,一种常见的方法是记录每个区域的违规项数量:如果某次修改导致该数字上升,则构建失败;而当有人修复了某个违规项时,再降低记录的基准值。

    对于公开或被广泛使用的 API 来说,这种方法尤为重要,因为清理工作往往取决于客户端的迁移进度。其目的并非要求删除所有有问题的字段,而是生成一份按优先级排序的清单,标明 API 哪些部分已不符合当前标准,以便团队据此制定计划。

    为何大语言模型是处理此任务的理想工具

    大语言模型并非判断 API 设计的完美工具,系统也并不将其视为如此。它们的优势在于:能够同时读取代码和架构文档,将这些内容与用通俗语言写成的规范进行对比,并为那些静态规则无法处理的案例提供结构化的评估结果。

    静态规则可以告诉你某个字段会返回列表,但无法判断该列表是否会因用户输入而变长,从而需要分页处理。模型可以读取解析器内容,将其与策略中的示例进行对比,进而说明该字段为何符合或不符合特定模式。

    这样的解释比附在其中的数字更有价值。当某个字段被标记后,负责团队需要了解原因,以便快速判断该问题是否真实存在,若是的话,则需规划相应的迁移方案。仅有分数而没有原因只会增加另一个分类处理队列。

    你需要考虑的限制

    大语言模型审核并不能替代API的所有者责任或人工设计判断,明确剩余的工作内容很有帮助:

    • 误报仍然可能发生。
  • 有时仅凭实现细节无法看清全貌,比如当某些约束条件存在于其他服务中时。
  • 产品层面的约束往往会让原本不完美的方案成为可行的折中选择。
  • 该系统不会自动迁移客户端,也无法确保变更过程万无一失。它只能识别出现有问题;团队仍需谨慎规划并执行迁移操作。
  • 它所提供的,是一种可扩展的方法,用于揭示那些此前受限于人工审查能力的模式。这些指南只需编码一次,即可在所有代码库中统一应用,其结果能为团队在设计讨论时提供事实依据。

    总结

    该系统由两个相互关联的部分组成,遵循同一核心理念。在提交拉取请求时,LLM审核员会在客户端依赖新架构变更之前,先依据设计指南对其进行评估。在批量处理阶段,同样的评分系统会对现有架构打分,分数会被汇总到各团队的仪表板上,同时CI机制会防止总分持续上升,且随着时间推移评分阈值也会逐渐提高。这并非完全自动化的治理方式,也无意成为如此。它能让API质量变得足够透明,便于团队采取相应措施,同时为平台团队提供了反馈机制,以便在该方法应用于更多架构元素时不断优化规则。