AI 辅助架构评审——让 AI 做技术方案的质量把关
AI 辅助架构评审——让 AI 做技术方案的质量把关
上个季度我们团队做了一次新的尝试:在架构评审会之前,先让 AI 过一遍技术方案文档,把它发现的问题列出来,然后在评审会上重点讨论这些问题,而不是从头把方案念一遍。
效果出乎意料的好。AI 发现了 3 个人工忽略的问题,其中一个是单点故障,我们评审会上讨论了 40 分钟才想出解法。
这篇文章把整个实践过程讲清楚:AI 架构评审能发现什么、不能发现什么、怎么设计 Prompt、以及那个真实的单点故障案例。
一、AI 做架构评审的定位
先说清楚:AI 架构评审不是要替代人工评审,而是前置的自动化质量检查,帮助找出常见问题,让人工评审聚焦在更深层的设计决策上。
AI 架构评审能做什么:
- 检查文档是否覆盖了关键架构考量点(安全、可用性、扩展性等)
- 发现常见的架构反模式(单点故障、同步链太长、缺乏降级机制等)
- 识别文档描述不清晰的部分(需要补充的信息)
- 检查技术选型的合理性(技术是否匹配场景)
- 对比行业最佳实践,给出改进建议
AI 架构评审不能做什么:
- 理解深层的业务逻辑(它不了解你的具体业务场景)
- 判断方案是否符合公司的技术战略(它不了解公司全貌)
- 发现需要领域专家知识才能识别的问题(特定场景的性能问题、合规要求等)
- 替代深入的技术讨论(复杂权衡需要人来做)
二、Prompt 设计:检查单模式 vs 开放式评审
这是最关键的设计决策。我测试了两种 Prompt 模式:
2.1 检查单模式(Checklist)
把要检查的维度列出来,让 AI 逐项评估:
CHECKLIST_PROMPT = """
你是一个经验丰富的架构评审专家。请对下面的技术方案文档进行架构评审。
## 评审维度(逐项检查)
### 1. 可用性设计(0-10分)
- [ ] 是否有单点故障?
- [ ] 是否有降级方案?
- [ ] 是否定义了 SLA 目标?
- [ ] 是否有故障恢复流程?
### 2. 扩展性设计(0-10分)
- [ ] 水平扩展是否可行?
- [ ] 数据库是否有扩展瓶颈?
- [ ] 是否考虑了流量峰值?
### 3. 安全设计(0-10分)
- [ ] 认证和授权是否完整?
- [ ] 敏感数据是否加密?
- [ ] 是否有 SQL 注入等安全风险?
### 4. 数据一致性(0-10分)
- [ ] 分布式事务如何处理?
- [ ] 缓存一致性如何保证?
- [ ] 是否有幂等性设计?
### 5. 可观测性(0-10分)
- [ ] 是否有日志设计?
- [ ] 是否有监控和告警?
- [ ] 是否可以追踪请求链路?
## 输出格式
对每个维度:
1. 评分(0-10)
2. 发现的具体问题(如果有)
3. 改进建议
最后给出综合评分和 TOP3 优先改进项。
## 技术方案文档
{document_content}
"""检查单模式的优点: 覆盖全面,不容易漏掉维度,输出结构化,容易量化。
缺点: 容易「走过场」,AI 对每个维度只是表面评估,深度不够。
2.2 开放式评审模式
不给具体检查项,让 AI 自由发现问题:
OPEN_REVIEW_PROMPT = """
你是一个有15年经验的架构师,曾主导过多个大型分布式系统的设计和评审。
请对下面的技术方案进行批判性的架构评审。你的目标是:
1. 找到方案中最严重的潜在问题(不是挑毛病,而是帮助提前发现真正的风险)
2. 指出方案中描述不清晰、需要补充的部分
3. 对技术选型给出专业意见
请直接指出问题,不要只说「需要考虑XXX」,要说具体「在什么场景下会出什么问题」。
## 技术方案文档
{document_content}
## 评审重点(请特别关注)
- 这个方案在生产流量下会不会出问题?
- 如果某个组件挂了,会发生什么?
- 方案是否过度复杂,有没有更简单的实现?
"""开放式模式的优点: 发现的问题更有深度,更接近真实评审的质感。
缺点: 输出不结构化,覆盖面可能不均衡(AI 会重点评估它「擅长」的维度)。
2.3 我们最终使用的混合模式
@Service
public class ArchitectureReviewPromptBuilder {
public String buildPrompt(String documentContent, ReviewMode mode) {
return switch (mode) {
case COMPREHENSIVE -> buildComprehensivePrompt(documentContent);
case FOCUSED_AVAILABILITY -> buildAvailabilityFocusedPrompt(documentContent);
case QUICK_SCAN -> buildQuickScanPrompt(documentContent);
};
}
/**
* 综合评审:先开放式找主要问题,再用检查单补全
*/
private String buildComprehensivePrompt(String content) {
return String.format("""
你是一个有15年经验的分布式系统架构师,请对以下技术方案进行架构评审。
## 第一步:开放式评审
请先用架构师的视角,找出方案中最值得关注的3-5个问题。
不需要面面俱到,只找最重要的。
每个问题要说明:在什么场景下会出什么问题,后果是什么。
## 第二步:检查单扫描
然后按以下维度快速扫描,如果第一步已经覆盖就跳过:
- 单点故障:是否有不可替代的单点组件?
- 降级熔断:AI 或第三方服务不可用时的处理?
- 数据一致性:跨服务的数据一致性如何保证?
- 安全:认证、鉴权、数据加密是否完整?
- 监控:出问题时能否及时发现和定位?
## 第三步:综合评价
最终给出:
- 综合评分(1-10)
- 必须解决的问题(阻塞评审通过的)
- 建议优化的问题(不阻塞但建议处理)
- 认可的设计决策(方案中做得好的地方)
## 技术方案文档
%s
""",
content
);
}
}三、架构评审 Bot 的完整实现
@Service
@Slf4j
public class ArchitectureReviewBot {
private final ChatClient chatClient;
private final ReviewResultRepository reviewResultRepo;
/**
* 执行完整的架构评审
*/
public ArchitectureReviewResult review(ArchitectureReviewRequest request) {
log.info("开始架构评审,文档: {}, 模式: {}",
request.documentTitle(), request.mode());
long startTime = System.currentTimeMillis();
// 预处理文档(截断、提取关键章节)
String processedDocument = preprocessDocument(request.document());
// 构建 Prompt
String prompt = buildReviewPrompt(processedDocument, request);
// 调用 AI 进行评审
String rawReview = chatClient.prompt()
.system("""
你是一个严格但公正的架构评审专家。
你的评审目标是帮助团队提前发现问题,而不是挑剔或否定方案。
评审意见要具体、可操作,避免模糊的泛泛而谈。
""")
.user(prompt)
.options(OpenAiChatOptions.builder()
.temperature(0.1) // 低温度,保证评审结果的稳定性和客观性
.build())
.call()
.content();
// 解析评审结果
ArchitectureReviewResult result = parseReviewResult(
rawReview, request, System.currentTimeMillis() - startTime
);
// 保存评审记录
reviewResultRepo.save(result);
log.info("架构评审完成,文档: {}, 综合评分: {}, 发现问题: {}",
request.documentTitle(),
result.overallScore(),
result.issues().size()
);
return result;
}
/**
* 针对特定维度的深度评审(比如重点评审可用性)
*/
public String deepReviewDimension(
String document,
ReviewDimension dimension) {
String dimensionPrompt = switch (dimension) {
case AVAILABILITY -> buildAvailabilityDeepReview(document);
case SECURITY -> buildSecurityDeepReview(document);
case PERFORMANCE -> buildPerformanceDeepReview(document);
case DATA_CONSISTENCY -> buildDataConsistencyDeepReview(document);
};
return chatClient.prompt()
.user(dimensionPrompt)
.call()
.content();
}
private String buildAvailabilityDeepReview(String document) {
return String.format("""
请对以下技术方案的可用性设计进行深度评审。
重点检查:
1. **单点故障识别**
- 哪些组件是单点?(单个实例、没有备份的外部依赖)
- 单点组件故障后,整个系统会发生什么?
- 恢复时间(RTO)和数据丢失(RPO)是否可接受?
2. **级联故障风险**
- 如果下游服务(数据库、缓存、AI 服务)响应变慢,是否会拖垮整个系统?
- 是否有超时设置、熔断机制?
- 队列积压时如何处理?
3. **降级策略**
- AI 服务不可用时,系统是否有降级方案?
- 降级后用户体验如何?是否可接受?
- 降级切换是自动的还是手动的?
4. **容量规划**
- 当前设计支持的最大 QPS 是多少?
- 超过容量后会发生什么?(优雅降级还是系统崩溃)
请对每个问题给出具体的评估,而不是泛泛的建议。
## 技术方案
%s
""",
document
);
}
private String preprocessDocument(String rawDocument) {
// 如果文档超过 15,000 字符,需要截断
if (rawDocument.length() <= 15000) {
return rawDocument;
}
// 优先保留架构图描述、关键组件说明、问题与风险章节
// 简单处理:截取前 12,000 字符,并添加说明
String truncated = rawDocument.substring(0, 12000);
return truncated + "\n\n[文档已截断,以上为文档前12,000字符]";
}
}四、真实案例:AI 发现了人工忽略的单点故障
这是那个让我印象最深刻的案例,具体说一下。
背景: 团队在设计一个 AI 写作辅助平台。用户写作过程中,平台会调用 AI 实时给出修改建议。
原始方案(简化版):
用户浏览器 → Nginx → Spring Boot 应用集群 → Redis 会话存储
→ MySQL 数据库
→ OpenAI API人工评审的关注点: 团队在评审会上花了很多时间讨论「写作建议的延迟怎么优化」「Redis 集群如何配置」。
AI 发现的问题(原文):
【严重问题:Nginx 单点故障】
文档中描述使用单台 Nginx 作为负载均衡器,但没有提到 Nginx 的高可用方案。
在当前设计中,如果这台 Nginx 宕机:
- 所有用户的写作请求将无法到达后端
- 即使后端 Spring Boot 集群正常运行,用户也无法访问
- 这是一个典型的单点故障
建议:
1. 使用 Nginx + Keepalived 实现主备切换(VIP 漂移)
2. 或者改用云厂商的托管负载均衡服务(AWS ALB、阿里云 SLB)
3. 如果使用 k8s,Ingress Controller 本身已经是多副本的
当前文档没有提到 Nginx 的部署细节(单机还是集群),如果是单机部署,这是必须解决的问题。人工评审团队里有 4 个人,但没有人提出这个问题。不是因为没能力,而是大家的注意力被「AI 延迟优化」这个复杂问题吸走了,忽略了这个看似基础却很重要的问题。
后续处理: 评审会上看到 AI 的这个反馈,团队立刻确认:Nginx 确实是单机部署的。讨论了 40 分钟,最终决定用阿里云 SLB 替换自建 Nginx,彻底解决这个单点问题。
五、批量评审和结果管理
当积累了多份评审结果后,可以做一些有价值的分析:
@Service
public class ArchitectureReviewAnalytics {
private final ReviewResultRepository reviewResultRepo;
/**
* 分析近期架构方案的共性问题
*/
public CommonIssuesReport analyzeCommonIssues(int recentDays) {
List<ArchitectureReviewResult> recentReviews =
reviewResultRepo.findByDateRange(
LocalDate.now().minusDays(recentDays),
LocalDate.now()
);
// 统计问题类型分布
Map<String, Long> issueTypeCount = recentReviews.stream()
.flatMap(r -> r.issues().stream())
.collect(Collectors.groupingBy(
Issue::type,
Collectors.counting()
));
// 找出最常见的 TOP5 问题
List<Map.Entry<String, Long>> top5 = issueTypeCount.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(5)
.toList();
// 平均评分趋势
double avgScore = recentReviews.stream()
.mapToDouble(ArchitectureReviewResult::overallScore)
.average()
.orElse(0.0);
return new CommonIssuesReport(top5, avgScore, recentReviews.size());
}
}六、接入 GitHub PR 流程
架构文档评审可以集成到 GitHub PR 流程中,让 PR 提交时自动触发:
@RestController
@RequestMapping("/webhooks")
public class GitHubWebhookController {
private final ArchitectureReviewBot reviewBot;
private final GitHubService githubService;
/**
* 接收 GitHub PR 事件
* 当 PR 包含架构文档(*.md 文件在 docs/architecture/ 目录)时触发评审
*/
@PostMapping("/github/pr")
public ResponseEntity<Void> handlePullRequest(
@RequestBody GitHubPullRequestEvent event,
@RequestHeader("X-GitHub-Event") String eventType) {
if (!"pull_request".equals(eventType)) {
return ResponseEntity.ok().build();
}
// 检查 PR 是否包含架构文档
List<String> changedFiles = githubService.getChangedFiles(
event.repository().fullName(),
event.pullRequest().number()
);
List<String> archDocs = changedFiles.stream()
.filter(f -> f.startsWith("docs/architecture/") && f.endsWith(".md"))
.toList();
if (archDocs.isEmpty()) {
return ResponseEntity.ok().build();
}
// 异步触发评审(不阻塞 webhook 响应)
CompletableFuture.runAsync(() -> {
for (String docPath : archDocs) {
String content = githubService.getFileContent(
event.repository().fullName(),
docPath,
event.pullRequest().head().sha()
);
ArchitectureReviewResult result = reviewBot.review(
ArchitectureReviewRequest.builder()
.documentTitle(docPath)
.document(content)
.mode(ReviewMode.COMPREHENSIVE)
.build()
);
// 把评审结果发布为 PR Comment
githubService.createPrComment(
event.repository().fullName(),
event.pullRequest().number(),
formatReviewComment(result)
);
}
});
return ResponseEntity.ok().build();
}
private String formatReviewComment(ArchitectureReviewResult result) {
StringBuilder sb = new StringBuilder();
sb.append("## AI 架构评审报告\n\n");
sb.append(String.format("**综合评分:%d/10**\n\n", result.overallScore()));
if (!result.blockers().isEmpty()) {
sb.append("### 必须解决的问题(阻塞合并)\n");
result.blockers().forEach(issue ->
sb.append(String.format("- **[%s]** %s\n - 影响:%s\n - 建议:%s\n\n",
issue.severity(), issue.title(), issue.impact(), issue.suggestion()))
);
}
if (!result.suggestions().isEmpty()) {
sb.append("### 建议优化(不阻塞合并)\n");
result.suggestions().forEach(issue ->
sb.append(String.format("- %s:%s\n", issue.title(), issue.suggestion()))
);
}
sb.append("\n> 此评审由 AI 自动生成,仅供参考,最终评审决策由人工进行。");
return sb.toString();
}
}七、AI 评审的局限性和规避
使用了一段时间后,我总结了几个 AI 评审的局限性以及规避方法:
局限 1:没有业务上下文
AI 不了解你的业务规则,可能会建议「加缓存」但不知道这个数据不能缓存(因为实时性要求)。
规避: 在方案文档里显式说明业务约束,比如「此接口需要实时查询,不能使用缓存」。
局限 2:评审结果有时过于严格
AI 会对每个「可能的问题」都发出警告,导致「警报疲劳」——开发者看到太多问题就不认真看了。
规避: 在 Prompt 里明确要求只报告「高优先级」问题,设置一个阈值,低于这个优先级的建议放到独立的章节,不突出显示。
局限 3:无法评估方案的真实复杂度
AI 可能建议把一个「实际上够用的简单方案」改造成「看起来更健壮的复杂方案」,但没有考虑实现成本。
规避: 在文档里说明「这是 MVP 阶段,优先简单可用」,让 AI 评审时考虑这个约束。
// 在 Prompt 里注入项目阶段信息
private String buildContextAwarePrompt(String content, ProjectPhase phase) {
String phaseContext = switch (phase) {
case MVP -> "这是 MVP 阶段,优先实现核心功能,可以接受一定的技术债务";
case GROWTH -> "系统处于快速增长期,需要平衡功能迭代速度和系统稳定性";
case MATURE -> "系统已经稳定,对可用性和性能有较高要求,可以接受较高的实现复杂度";
};
return String.format("""
%s
项目阶段:%s
## 技术方案
%s
""",
BASE_REVIEW_PROMPT, phaseContext, content
);
}八、与 Jira/Confluence 集成
@Service
public class ConfluenceIntegration {
private final ConfluenceClient confluenceClient;
private final ArchitectureReviewBot reviewBot;
/**
* 监听 Confluence 页面更新,自动触发架构评审
*/
@Scheduled(fixedDelay = 300000) // 每5分钟检查一次
public void checkAndReviewUpdatedDocs() {
// 查找最近5分钟更新的架构设计文档
List<ConfluencePage> updatedPages = confluenceClient.findRecentlyUpdated(
"architecture", // 空间
5, // 5分钟内
"design" // 包含"design"标签
);
for (ConfluencePage page : updatedPages) {
// 避免重复评审
if (hasBeenReviewed(page.id(), page.lastModified())) {
continue;
}
String content = confluenceClient.getPageContent(page.id());
ArchitectureReviewResult result = reviewBot.review(
ArchitectureReviewRequest.builder()
.documentTitle(page.title())
.document(content)
.mode(ReviewMode.COMPREHENSIVE)
.build()
);
// 在 Confluence 页面末尾添加评审意见
confluenceClient.appendComment(
page.id(),
formatConfluenceComment(result)
);
}
}
}九、小结
AI 辅助架构评审,我用下来最大的感受是:它是一个很好的「守门员」,但不是「裁判」。
它的价值在于:
- 在人工评审之前,先做一轮全面但快速的扫描
- 找出容易被忽视的「基础问题」(就像那个 Nginx 单点的例子)
- 提醒评审团队关注某些容易遗漏的维度(安全、可观测性)
它的边界在于:
- 不能替代领域专家对业务逻辑的判断
- 不能评估方案的「实现成本 vs 收益」
- 不了解团队的技术能力边界和实际约束
把这两点都想清楚,AI 架构评审就是一个有价值、有边界的好工具。
