如何使用 Novita AI API 构建长上下文代码审查工作流

如何使用 Novita AI API 构建长上下文代码审查工作流

当代码审查需要的不仅仅是一个 diff 时,请通过 Novita AI API 使用 MiniMax M3。本教程将展示如何打包功能简介、选定的源文件、测试输出以及仓库说明,将它们发送给 minimax/minimax-m3,并将响应转化为维护人员在合并前可以实际检查的审查发现。

关键要点

  • 当审查需要广泛的代码上下文、测试输出、图像输入(例如截图)或结构化输出时,MiniMax M3 是一个不错的选择。
  • Novita AI API 使用与 OpenAI 兼容的基础 URL,因此现有的聊天补全客户端代码很容易适配。
  • 确保 AI 审查评论有据可依。如果一个发现无法追溯到代码、测试、日志或需求,就不要将其作为事实发布。

什么是长上下文代码审查 API 工作流?

长上下文代码审查 API 会将拉取请求中审查人员通常需要在不同标签页中打开的内容发送给模型:变更摘要、相关文件、diff、失败的测试、日志、架构说明和审查规则。然后模型会返回可能的风险、建议的修复以及供维护人员考虑的问题。

这不会取代测试或人工审查。它有助于解决令人烦恼的部分:在脑海中保持足够的上下文。Linter 和静态分析器在行级检查方面表现出色。但在发现依赖于远端模块、旧的迁移、特性标志或部署设置的行为方面,它们要差得多。

MiniMax M3 适合这项工作,因为 Novita AI 将其列为具有 1,000,000 token 上下文窗口、131,072 token 最大输出、无服务器访问和编程导向能力的模型。这对于实际的拉取请求很重要,其中有用的上下文可能包括源代码、测试输出、截图和简短的产品简介。

何时使用 Novita AI API 进行代码审查

当代码审查需要成为可重复流程的一部分时,请使用 Novita AI API:持续集成(CI)、拉取请求机器人、发布清单或内部开发者工具。一次性的聊天提示适用于临时帮助。而当需要保持输入格式、输出模式、日志、成本追踪和回退行为一致时,API 调用则是更好的选择。

此模式适用于:

  • 涉及多个服务或包的大型拉取请求。
  • 需要同时考虑 schema、API、配置和测试的迁移审查。
  • 需要对不安全的输入处理、授权漏洞或密钥泄露进行二次检查的安全敏感变更。
  • 源文件和截图都很重要,但最终答案应为文本的 UI 变更。
  • 在实现代理提出补丁后需要验证步骤的智能编程系统。

不要将 AI 审查用于静态分析已经处理得很好的工作。格式化、未使用的导入、依赖项许可证扫描和已知漏洞检查应保持确定性。将模型放在这些工具的上层,问题更接近“当我阅读周围系统时,这个变更是否仍然合理?”

选择合适的 Novita AI 模型或 API 路径

当审查需要广泛了解变更时,请从 MiniMax M3 开始。对于短的单文件检查,使用较小的模型或完全跳过 AI 步骤。

选项 最适合 为何选择 注意
minimax/minimax-m3 大型代码库审查、迁移风险分析、代理验证器检查 长上下文、大输出、多模态输入、函数调用、结构化输出、无服务器访问 对于短的单文件检查来说模型太大
Novita OpenAI 兼容的聊天补全 已使用 OpenAI SDK 请求模式的应用 通常只需更改基础 URL 和模型 ID 即可适配现有客户端代码 在部署前检查模型限制、定价和受支持的功能
静态分析器和测试套件 代码风格、类型、安全和回归检查 快速、可重复、易于在 CI 中设置门禁 它们无法很好地解释跨文件的产品风险或模糊意图

对于本教程,最有用的版本是迁移风险审查:一个请求中包含功能简介、变更的文件、相关未变更的文件、相关测试输出和审查规则。MiniMax M3 的长上下文允许您保留更多这些材料,而不是将其压缩成模糊的摘要。

第 1 步:定义代码审查输入和输出格式

在调用 API 之前,确定模型被允许审查什么以及您想要什么样的答案。一个有用的请求通常包含五个部分。

首先,包含一个简短的变更说明。解释目标、受影响的特性、预期行为以及任何不允许更改的内容。模型应该知道它正在审查的是重构、新的 API 端点、数据库迁移、依赖项升级还是 UI 行为变更。

其次,包含 diff 和选定的完整文件。Diffs 显示更改了什么。完整文件显示约定、辅助函数、验证模式和现有边缘情况。对于大型仓库,应包括变更的文件、被变更文件导入的文件以及测试或日志中提到的文件。

第三,添加机器输出:失败的测试、相关通过的测试名称、linter 输出、API 契约片段、数据库 schema 变更或部署配置。大力修剪终端日志。模型不需要 600 行的安装噪音。

第四,包含审查规则。告诉模型什么重要:正确性、安全性、数据丢失、兼容性、性能、可观测性、部署安全性或文档偏离。还要说明忽略什么,例如由其他工具处理的格式化。

第五,要求结构化输出。Novita 的聊天补全 API 支持带有 JSON schema 的 response_format,并且 MiniMax M3 被列为支持结构化输出。这使得结果更易于解析、去重并转化为拉取请求评论。

这是一个合理的初始 schema:

{
  "summary": "一段审查摘要。",
  "risk_level": "low | medium | high",
  "findings": [
    {
      "severity": "blocker | high | medium | low",
      "title": "简短发现标题",
      "evidence": "文件、函数、测试或日志证据",
      "impact": "可能出什么问题",
      "recommendation": "具体的修复或验证步骤",
      "confidence": "high | medium | low"
    }
  ],
  "needs_human_review": [
    "需要维护人员处理的具体问题或假设"
  ]
}

第 2 步:配置 Novita AI API 请求

Novita AI 暴露了一个与 OpenAI 兼容的聊天补全端点。将客户端基础 URL 设置为 https://api.novita.ai/openai,使用 /v1/chat/completions,并将您的 API 密钥作为 Bearer token 发送。

将 API 密钥设置在环境变量中:

export NOVITA_API_KEY="your_api_key_here"

如果您的项目中尚未包含 OpenAI Python SDK,请安装它:

pip install openai

然后使用 Novita 的基础 URL 配置客户端:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["NOVITA_API_KEY"],
    base_url="https://api.novita.ai/openai",
)

使用 minimax/minimax-m3 作为模型 ID。在日志中记录模型 ID、提示版本、源提交、包含的文件、token 使用情况和验证状态。这些细节在审查评论出错之前可能显得无聊,但那时它们正是您需要的。

第 3 步:适配代码审查 API 请求

以下示例是一个起始模式,而非可直接运行的 CI 机器人。替换示例的 review_packet,使用您自己的 Novita API 密钥进行测试,并在将任何内容发布到拉取请求之前确认响应形状。

import json
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["NOVITA_API_KEY"],
    base_url="https://api.novita.ai/openai",
)

review_packet = {
    "change_brief": "用流式 CSV 解析器替换旧版用户导入作业。",
    "review_goals": [
        "发现正确性风险",
        "发现数据丢失风险",
        "检查迁移和回滚安全性",
        "忽略仅格式化的评论"
    ],
    "diff": """
diff --git a/jobs/import_users.py b/jobs/import_users.py
...
""",
    "related_files": {
        "jobs/import_users.py": "def import_users(...): ...",
        "models/user.py": "class User(...): ...",
        "tests/test_import_users.py": "def test_duplicate_email_rows(...): ..."
    },
    "test_output": "2 失败,41 通过。失败原因:重复的电子邮件行覆盖了现有活跃用户。",
}

schema = {
    "type": "object",
    "additionalProperties": False,
    "properties": {
        "summary": {"type": "string"},
        "risk_level": {"type": "string", "enum": ["low", "medium", "high"]},
        "findings": {
            "type": "array",
            "items": {
                "type": "object",
                "additionalProperties": False,
                "properties": {
                    "severity": {
                        "type": "string",
                        "enum": ["blocker", "high", "medium", "low"]
                    },
                    "title": {"type": "string"},
                    "evidence": {"type": "string"},
                    "impact": {"type": "string"},
                    "recommendation": {"type": "string"},
                    "confidence": {
                        "type": "string",
                        "enum": ["high", "medium", "low"]
                    }
                },
                "required": [
                    "severity",
                    "title",
                    "evidence",
                    "impact",
                    "recommendation",
                    "confidence"
                ]
            }
        },
        "needs_human_review": {
            "type": "array",
            "items": {"type": "string"}
        }
    },
    "required": ["summary", "risk_level", "findings", "needs_human_review"]
}

response = client.chat.completions.create(
    model="minimax/minimax-m3",
    messages=[
        {
            "role": "system",
            "content": (
                "你是高级代码审查员。仅返回有提供证据支持的发现。"
                "不要虚构文件、测试、日志、需求或行号。"
            ),
        },
        {
            "role": "user",
            "content": json.dumps(review_packet),
        },
    ],
    max_tokens=4096,
    temperature=0.1,
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "code_review_result",
            "schema": schema,
            "strict": True,
        },
    },
)

result = json.loads(response.choices[0].message.content)
print(json.dumps(result, indent=2))
print(response.usage)

保持 max_tokens 足够大以包含有用的发现,但又足够小以避免输出过多页面。Novita 的聊天补全参考要求 max_tokens,并且提示加上输出必须适合模型上下文。如果请求太大,Novita 可能会降低 max_tokens 以适应。这可以防止一些硬性失败,但您的应用仍应跟踪提示大小,以便在重要审查上下文被压缩时发出警告。

第 4 步:验证并改进代码审查结果

不要因为 AI 审查说它看起来安全就合并代码。要将响应视为有时会过度推断的尖锐审查者。

从 schema 开始。如果响应不匹配,使用相同的输入和更严格的系统指令重试一次。如果仍然失败,将 AI 审查标记为不确定,而不是发布格式错误的评论。

然后检查证据。每个发现应指向请求中的文件、函数、测试、日志行或需求。删除任何无法追溯到所提供上下文的内容。按受影响的组件和用户影响对重复项进行分组。先显示严重项。

这是一个简单的后处理模式:

def filter_supported_findings(result):
    supported = []
    for finding in result["findings"]:
        evidence = finding["evidence"].lower()
        has_file_or_test = any(
            marker in evidence
            for marker in [".py", ".ts", ".go", ".java", "test", "log", "migration"]
        )
        if has_file_or_test and finding["confidence"] != "low":
            supported.append(finding)
    return supported

supported_findings = filter_supported_findings(result)

对于真实系统,将那个简单的过滤器替换为仓库感知的验证。检查引用的路径是否存在于拉取请求中,测试名称是否出现在测试输出中,以及发现是否指向更改的行或相关依赖项。

第 5 步:为生产环境准备代码审查工作流

生产环境的审查机器人需要在成本、隐私、可靠性和信任方面设置防护措施。

关于成本,从实时的 Novita 模型列表和您的账户仪表板开始。不要在机器人中对 token 价格进行硬编码。记录每个响应的 token 使用情况,在部署前检查当前的 MiniMax M3 定价,并针对实际的拉取请求量设置警报。

关于隐私,严格限制进入请求的内容。不要发送密钥、私钥、客户数据或生产凭据。在 API 调用之前运行密钥扫描并清理日志。如果审查需要机密文件,请先检查您的内部数据策略。

关于可靠性,决定 API 调用失败时的处理方式。一个合理的默认值是:“AI 审查不可用;确定性检查仍在运行。”除非团队明确选择了该权衡,否则不要让每次瞬态 AI 中断都阻塞所有拉取请求。

关于审查者信任,少发表评论。带有 30 条推测性评论的拉取请求评论将被忽略。发布高置信度的发现,将其与相关文件或测试关联,并包含模型 ID 和提示版本以便审计。

首先以观察模式推出。运行 AI 审查但不发布评论,将其发现与人工审查结果进行比较,并跟踪真阳性和假阳性。只有在此之后,才应启用拉取请求评论。阻止行为应罕见且严格,例如确认的密钥泄露或迁移回滚缺口。

AI 代码审查清单

  • 请求包含变更说明、diff、选定的完整文件、相关测试和审查规则。
  • 响应与您的 JSON schema 匹配。
  • 发现引用提供的上下文,而不是虚构的文件、测试或行号。
  • 每个发现都有严重性、证据、影响、建议和置信度。
  • 日志记录模型 ID、提示版本、源提交、包含的文件、token 使用情况和验证状态。
  • 拉取请求机器人隐藏低置信度或重复的评论。
  • 在部署前检查当前定价、模型限制和可用性。

解决 Novita AI API 工作流问题

问题 可能原因 修复方法
API 返回身份验证错误 Bearer token 缺失或格式错误 确认设置了 NOVITA_API_KEY 并以 Authorization: Bearer ... 形式发送
响应是有效文本但非有效 JSON schema 未强制执行或模型未获得清晰的输出合同 使用带有 json_schemaresponse_format,保持 schema 较小,并重试一次
审查遗漏了明显的问题 请求未包含证明该问题的文件、测试或需求 包含变更的文件、直接导入、失败的测试和迁移文件
审查引用了不存在的证据 提示允许猜测,或后处理器未检查引用 仅要求提供提供的上下文,并删除未映射到请求文件或日志的发现
拉取请求评论太长 schema 允许太多发现 在发布前按严重性和置信度限制发现数量
成本快速攀升 diff 非常大、重复重试或 max_tokens 值过高 测量 token 使用情况,限制重试次数,并总结低价值文件
延迟过高 请求包含的内容超出了审查所需 按组件拆分检查,或仅对大型或风险变更保留长上下文审查

常见问题

应该使用哪个 Novita AI 模型进行长上下文代码审查?

当审查需要广泛的代码上下文、测试输出、图像输入(如截图)或结构化输出时,使用 minimax/minimax-m3。Novita 将 MiniMax M3 列为无服务器聊天模型,具有 1,000,000 token 上下文窗口和 131,072 最大输出 token。对于较短的检查,考虑测试较小的模型,并在您自己的工作负载上比较成本、延迟和质量。

我可以在 Novita AI API 工作流中稍后切换模型吗?

可以,只要替换模型支持您依赖的端点模式和功能。在切换之前,检查模型 ID、上下文长度、最大输出、模态支持、结构化输出支持、工具支持、定价以及在您自己的审查集上的输出质量。

如何估算使用 Novita AI API 进行代码审查的成本?

使用实时的 Novita 定价和您自己的 token 测量。对于每次运行,记录提示 token、生成 token、重试次数以及是否使用了缓存上下文。将使用情况与当前的 MiniMax M3 定价进行比较,然后再设置预算或将机器人设为阻塞性的 CI 步骤。

哪些输入最适合 AI 代码审查?

最好的输入是具体的:变更说明、diff、选定的完整文件、测试输出、相关日志、schema 或 API 契约以及审查规则。默认情况下避免转储整个仓库。长上下文有帮助,但不相关的上下文会使审查更慢且更嘈杂。

生产中 AI 代码审查的主要风险是什么?

主要风险是虚假信心、无依据的发现、遗漏的问题、敏感数据暴露、成本漂移和审查疲劳。通过 schema 验证、证据检查、密钥扫描、token 监控、人工审查和保守的拉取请求评论规则来降低这些风险。