很早的时候就想着用AI来做Code Review,最近也看到了一些不错的实现,但是没有一个使用Java来构建的,看的比较费劲,虽然说语言只是一种工具,但是还是想用Java重新写一遍,正好最近Spring AI Alibaba出了正式版,就拿来用了。
简单的效果图
1. 架构概览
本应用采用事件驱动架构,其核心工作流程如下:
- GitHub Webhook 触发:开发者在 GitHub 仓库中创建或更新一个 Pull Request (PR) 时,会触发一个预先配置好的 Webhook。
- 事件接收与处理:后端的 Spring Boot 应用通过
GitHubWebhookController
接收该事件。 - 任务分发:
GithubWebhookServiceImpl
解析 Webhook 负载,提取 PR 相关信息,并异步触发CodeReviewServiceImpl
执行代码评审任务。 - 获取代码变更:
CodeReviewServiceImpl
调用GitHubAdapter
,通过 GitHub API 获取该 PR 的代码变更详情(diff)。 - 调用大模型分析:
LlmAdapter
负责构建发送给大模型的 Prompt。该 Prompt 包含代码变更、预设的评审规则以及可选的 RAG(检索增强生成)知识。随后,它通过 Spring AI 的ChatClient
将请求发送给阿里巴巴通义千问模型。 - 处理与发布结果:应用接收 LLM 返回的评审建议,将其格式化后,通过
GitHubAdapter
调用 GitHub API,将评审评论发布到对应的 PR 下。
2. 依赖配置 (pom.xml
)
<!-- Spring AI 核心与阿里巴巴通义千问集成 --><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId></dependency><!-- GitHub API Java 客户端 -->
<dependency><groupId>org.kohsuke</groupId><artifactId>github-api</artifactId><version>1.321</version>
</dependency>
spring-ai-alibaba-tongyi-spring-boot-starter
:这是 Spring AI 对接阿里巴巴通义千问模型的关键,它提供了自动配置和ChatClient
实现。github-api
:一个便捷的 Java 库,用于与 GitHub REST API 进行交互。
3. 应用配置 (application.yml
)
所有外部服务的凭证和行为都在 application.yml
中定义。
server:port: 8080spring:# Spring AI 配置ai:dashscope:api-key: ${DASHSCOPE_API_KEY}# GitHub App 相关配置
github:# App IDapp-id: ${GITHUB_APP_ID}# App 安装后的 Installation IDinstallation-id: ${GITHUB_INSTALLATION_ID}# App 生成的私钥(Base64 编码)private-key: ${GITHUB_PRIVATE_KEY}# Webhook 使用的密钥webhook-secret: ${GITHUB_WEBHOOK_SECRET}
spring.ai.alibaba.tongyi.*
:此路径下的所有配置都用于设置通义千问模型。你需要提供一个有效的 API Key,并可以选择合适的模型。github.*
:此处配置了 GitHub App 的认证信息。使用 GitHub App 而非个人访问令牌(PAT)是最佳实践,因为它提供了更细粒度的权限控制。
4. 核心代码实现
4.1. GitHub Webhook 接入
GitHubWebhookController
是应用的入口点。它负责验证和接收来自 GitHub 的 HTTP POST 请求。
// GitHubWebhookController.java
@RestController
@RequestMapping("/api/github")
public class GitHubWebhookController {// ...@PostMapping("/webhook")public ResponseEntity<String> handleWebhook(@RequestHeader("X-Hub-Signature-256") String signature,@RequestBody String payload) {// 1. 验证签名// 2. 调用 IGithubWebhookService 处理业务逻辑githubWebhookService.processPullRequestEvent(payload);return ResponseEntity.ok("Event received");}
}
4.2. Code Review 核心服务
CodeReviewServiceImpl
是业务逻辑的核心。它编排了整个代码评审的流程。
// CodeReviewServiceImpl.java
@Service
public class CodeReviewServiceImpl implements ICodeReviewService {// ...@Overridepublic ReviewResultDTO reviewCode(ReviewTaskDTO reviewTask) {// 1. 获取代码 diffString diff = githubAdapter.getPullRequestDiff(reviewTask.getOwner(), reviewTask.getRepo(), reviewTask.getPullRequestNumber());// 2. 准备 PromptString userMessage = "请评审以下代码变更:\n" + diff;// 3. 调用 LLMString reviewContent = llmAdapter.generateReview(userMessage);// 4. 解析 LLM 响应并构建 ReviewResultDTO// ...return reviewResult;}
}
4.3. 与大模型交互
LlmAdapter
封装了与 Spring AI 和通义千问模型的所有交互细节。
// LlmAdapter.java
@Component
public class LlmAdapter {private final ChatClient chatClient;@Autowiredpublic LlmAdapter(ChatClient chatClient) {this.chatClient = chatClient;}public String generateReview(String codeDiff) {// 系统消息,用于设定 AI 的角色和任务String systemMessage = "你是一个资深软件工程师,擅长代码评审..."// 用户消息,包含具体的代码变更String userMessage = "请评审以下代码变更,并以JSON格式返回你的发现...\n\n" + codeDiff;Prompt prompt = new Prompt(List.of(new SystemMessage(systemMessage),new UserMessage(userMessage)));ChatResponse response = chatClient.call(prompt);return response.getResult().getOutput().getContent();}
}
这里使用了 SystemMessage
来为 AI 设定角色和输出要求,这有助于获得更稳定和结构化的输出。
4.4. 发布评审结果
当 CodeReviewServiceImpl
获得格式化的评审结果后,会调用 ResultPublishServiceImpl
,后者再通过 GitHubAdapter
将评论发布回 GitHub。
// GitHubAdapter.java
public void postReviewComment(String owner, String repo, int prNumber, String commentBody, String commitId, String path, int lineNumber) {try {GHRepository repository = getGithubClient().getRepository(owner + "/" + repo);GHPullRequest pullRequest = repository.getPullRequest(prNumber);pullRequest.createReviewComment(commentBody, commitId, path, lineNumber);} catch (IOException e) {throw new RuntimeException("Failed to post review comment to GitHub", e);}
}
5. (暂时简单实现) 结合 RAG 提升评审质量
RAGService
为项目引入了检索增强生成(RAG)的能力。通过将内部的编码规范、最佳实践或常见错误模式文档化并存储在向量数据库(如 Elasticsearch)中,我们可以在生成 Prompt 前,先检索与代码变更最相关的信息。
将这些检索到的信息一并提供给 LLM,可以显著提升评审的准确性和深度,使其更贴合团队的特定规范。