代码审查多智能体系统实战
·
1. 引言
代码审查是软件开发过程中的关键环节,它不仅能提高代码质量,还能促进团队知识共享。随着人工智能技术的发展,利用多智能体系统进行自动化代码审查已成为一种趋势。本文将详细介绍如何构建一个智能代码审查多智能体系统,包括系统架构设计、核心功能实现、系统集成与测试等方面。
2. 代码审查多智能体系统架构
2.1 系统架构设计
代码审查多智能体系统采用分层架构,由以下几个核心智能体组成:
- 接入智能体:负责接收代码提交和审查请求
- 代码分析智能体:负责静态代码分析和质量评估
- 安全审查智能体:负责代码安全漏洞检测
- 性能评估智能体:负责代码性能分析和优化建议
- 最佳实践智能体:负责检查代码是否符合最佳实践
- 评审协调智能体:负责协调各个智能体的工作流程
- 人类协作智能体:负责与人类开发者进行交互
2.2 智能体之间的协作流程
- 接入智能体接收代码提交
- 评审协调智能体分配任务给各个专业智能体
- 各专业智能体并行分析代码
- 评审协调智能体汇总分析结果
- 人类协作智能体呈现审查结果并收集反馈
- 系统根据反馈持续优化
3. 核心功能实现
3.1 多渠道接入
# 多渠道接入实现
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import uvicorn
import asyncio
import redis
app = FastAPI()
redis_client = redis.Redis(host='localhost', port=6379, db=0)
class CodeReviewRequest(BaseModel):
repository: str
branch: str
commit_hash: str
reviewer: str
review_type: str
class WebhookPayload(BaseModel):
action: str
repository: dict
pull_request: dict
@app.post("/api/review")
async def create_review(request: CodeReviewRequest):
"""创建代码审查请求"""
review_id = f"review_{int(asyncio.get_event_loop().time())}"
# 存储审查请求
redis_client.hset(review_id, mapping={
"repository": request.repository,
"branch": request.branch,
"commit_hash": request.commit_hash,
"reviewer": request.reviewer,
"review_type": request.review_type,
"status": "pending",
"created_at": str(asyncio.get_event_loop().time())
})
# 触发审查流程
await trigger_review_process(review_id)
return {"review_id": review_id, "status": "created"}
@app.post("/webhook/github")
async def github_webhook(payload: WebhookPayload):
"""GitHub Webhook 处理"""
if payload.action == "opened" or payload.action == "synchronize":
pr = payload.pull_request
review_request = CodeReviewRequest(
repository=payload.repository.get("full_name"),
branch=pr.get("head", {}).get("ref"),
commit_hash=pr.get("head", {}).get("sha"),
reviewer="system",
review_type="full"
)
return await create_review(review_request)
return {"status": "ignored"}
async def trigger_review_process(review_id: str):
"""触发审查流程"""
# 这里将审查请求发送给评审协调智能体
print(f"Triggering review process for {review_id}")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
3.2 代码分析智能体
# 代码分析智能体实现
import ast
import re
import os
import subprocess
from typing import List, Dict, Any
class CodeAnalysisAgent:
def __init__(self):
self.quality_metrics = {
"cyclomatic_complexity": 0,
"code_coverage": 0,
"duplication_rate": 0,
"maintainability_index": 0
}
def analyze_code(self, code_path: str) -> Dict[str, Any]:
"""分析代码质量"""
results = {
"syntax_errors": [],
"code_smells": [],
"complexity_issues": [],
"style_violations": [],
"metrics": self.quality_metrics
}
# 静态代码分析
results["syntax_errors"] = self._check_syntax(code_path)
results["code_smells"] = self._detect_code_smells(code_path)
results["complexity_issues"] = self._analyze_complexity(code_path)
results["style_violations"] = self._check_style(code_path)
# 计算质量指标
results["metrics"] = self._calculate_metrics(code_path)
return results
def _check_syntax(self, code_path: str) -> List[str]:
"""检查语法错误"""
errors = []
for root, _, files in os.walk(code_path):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
code = f.read()
ast.parse(code)
except SyntaxError as e:
errors.append(f"{file_path}: {e.msg} at line {e.lineno}")
except Exception as e:
errors.append(f"{file_path}: {str(e)}")
return errors
def _detect_code_smells(self, code_path: str) -> List[str]:
"""检测代码异味"""
smells = []
# 简单的代码异味检测
for root, _, files in os.walk(code_path):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
code = f.read()
# 检测过长函数
if len(code.split('\n')) > 50:
smells.append(f"{file_path}: 函数过长")
# 检测重复代码
if self._detect_duplication(code):
smells.append(f"{file_path}: 存在重复代码")
except Exception as e:
pass
return smells
def _analyze_complexity(self, code_path: str) -> List[str]:
"""分析代码复杂度"""
issues = []
# 使用 radon 工具分析复杂度
try:
result = subprocess.run(
["radon", "cc", code_path, "-a"],
capture_output=True,
text=True
)
if result.stdout:
for line in result.stdout.split('\n'):
if "F" in line or "E" in line:
issues.append(f"复杂度问题: {line}")
except Exception as e:
pass
return issues
def _check_style(self, code_path: str) -> List[str]:
"""检查代码风格"""
violations = []
# 使用 flake8 检查代码风格
try:
result = subprocess.run(
["flake8", code_path],
capture_output=True,
text=True
)
if result.stdout:
for line in result.stdout.split('\n'):
if line:
violations.append(line)
except Exception as e:
pass
return violations
def _calculate_metrics(self, code_path: str) -> Dict[str, float]:
"""计算质量指标"""
metrics = self.quality_metrics.copy()
# 计算圈复杂度
try:
result = subprocess.run(
["radon", "cc", code_path, "-a"],
capture_output=True,
text=True
)
if result.stdout:
# 简单计算平均复杂度
lines = result.stdout.split('\n')
complexity_sum = 0
count = 0
for line in lines:
if "Average complexity" in line:
match = re.search(r'([0-9.]+)', line)
if match:
metrics["cyclomatic_complexity"] = float(match.group(1))
except Exception as e:
pass
return metrics
def _detect_duplication(self, code: str) -> bool:
"""检测代码重复"""
# 简单的重复代码检测
lines = code.split('\n')
line_count = len(lines)
if line_count < 10:
return False
# 检查是否有重复的代码块
for i in range(line_count - 5):
block1 = '\n'.join(lines[i:i+5])
for j in range(i + 5, line_count - 5):
block2 = '\n'.join(lines[j:j+5])
if block1 == block2:
return True
return False
3.3 安全审查智能体
# 安全审查智能体实现
import os
import subprocess
from typing import List, Dict, Any
class SecurityReviewAgent:
def __init__(self):
self.vulnerability_types = [
"injection",
"broken_authentication",
"sensitive_data_exposure",
"xml_external_entities",
"broken_access_control",
"security_misconfiguration",
"cross_site_scripting",
"insecure_deserialization",
"using_components_with_known_vulnerabilities",
"insufficient_logging_and_monitoring"
]
def review_security(self, code_path: str) -> Dict[str, Any]:
"""审查代码安全性"""
results = {
"vulnerabilities": [],
"security_score": 100.0,
"recommendations": []
}
# 执行安全扫描
results["vulnerabilities"] = self._scan_vulnerabilities(code_path)
# 计算安全评分
results["security_score"] = self._calculate_security_score(results["vulnerabilities"])
# 生成安全建议
results["recommendations"] = self._generate_recommendations(results["vulnerabilities"])
return results
def _scan_vulnerabilities(self, code_path: str) -> List[Dict[str, Any]]:
"""扫描代码漏洞"""
vulnerabilities = []
# 使用 bandit 工具扫描 Python 代码漏洞
try:
result = subprocess.run(
["bandit", "-r", code_path],
capture_output=True,
text=True
)
if result.stdout:
# 解析 bandit 输出
lines = result.stdout.split('\n')
for line in lines:
if "[B" in line:
parts = line.split()
if len(parts) > 5:
vuln = {
"type": parts[0],
"severity": parts[2],
"confidence": parts[4],
"description": ' '.join(parts[5:])
}
vulnerabilities.append(vuln)
except Exception as e:
pass
# 手动检测常见漏洞
vulnerabilities.extend(self._detect_common_vulnerabilities(code_path))
return vulnerabilities
def _detect_common_vulnerabilities(self, code_path: str) -> List[Dict[str, Any]]:
"""检测常见漏洞"""
vulnerabilities = []
for root, _, files in os.walk(code_path):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
code = f.read()
# 检测 SQL 注入
if re.search(r'cursor\.execute\([^,]+\s*\+\s*[^,]+\)', code):
vulnerabilities.append({
"type": "SQL_INJECTION",
"severity": "HIGH",
"confidence": "MEDIUM",
"description": f"{file_path}: 可能存在 SQL 注入漏洞"
})
# 检测硬编码密码
if re.search(r'password\s*=\s*["\'].*["\']', code):
vulnerabilities.append({
"type": "HARDCODED_PASSWORD",
"severity": "MEDIUM",
"confidence": "HIGH",
"description": f"{file_path}: 存在硬编码密码"
})
# 检测命令注入
if re.search(r'os\.system\([^,]+\s*\+\s*[^,]+\)', code):
vulnerabilities.append({
"type": "COMMAND_INJECTION",
"severity": "HIGH",
"confidence": "MEDIUM",
"description": f"{file_path}: 可能存在命令注入漏洞"
})
except Exception as e:
pass
return vulnerabilities
def _calculate_security_score(self, vulnerabilities: List[Dict[str, Any]]) -> float:
"""计算安全评分"""
score = 100.0
# 根据漏洞严重程度扣分
for vuln in vulnerabilities:
severity = vuln.get("severity", "LOW")
if severity == "HIGH":
score -= 10.0
elif severity == "MEDIUM":
score -= 5.0
elif severity == "LOW":
score -= 2.0
return max(0.0, score)
def _generate_recommendations(self, vulnerabilities: List[Dict[str, Any]]) -> List[str]:
"""生成安全建议"""
recommendations = []
# 根据漏洞类型生成建议
vuln_types = set([v.get("type", "") for v in vulnerabilities])
if "SQL_INJECTION" in vuln_types:
recommendations.append("使用参数化查询防止 SQL 注入攻击")
if "HARDCODED_PASSWORD" in vuln_types:
recommendations.append("使用环境变量或配置文件存储敏感信息")
if "COMMAND_INJECTION" in vuln_types:
recommendations.append("使用 subprocess 的安全参数形式,避免直接拼接命令")
if "XSS" in vuln_types:
recommendations.append("对用户输入进行适当的转义和验证")
# 通用安全建议
recommendations.extend([
"定期更新依赖库,避免使用有已知漏洞的版本",
"实施最小权限原则",
"使用 HTTPS 保护网络通信",
"实施适当的日志记录和监控"
])
return recommendations
# 导入必要的模块
import re
3.4 性能评估智能体
# 性能评估智能体实现
import os
import subprocess
import re
from typing import List, Dict, Any
class PerformanceEvaluationAgent:
def __init__(self):
self.performance_metrics = [
"execution_time",
"memory_usage",
"cpu_usage",
"io_operations",
"network_traffic"
]
def evaluate_performance(self, code_path: str) -> Dict[str, Any]:
"""评估代码性能"""
results = {
"performance_issues": [],
"performance_score": 100.0,
"optimization_suggestions": [],
"metrics": {}
}
# 分析性能问题
results["performance_issues"] = self._analyze_performance_issues(code_path)
# 计算性能评分
results["performance_score"] = self._calculate_performance_score(results["performance_issues"])
# 生成优化建议
results["optimization_suggestions"] = self._generate_optimization_suggestions(results["performance_issues"])
# 收集性能指标
results["metrics"] = self._collect_performance_metrics(code_path)
return results
def _analyze_performance_issues(self, code_path: str) -> List[Dict[str, Any]]:
"""分析性能问题"""
issues = []
# 检测常见性能问题
for root, _, files in os.walk(code_path):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
code = f.read()
# 检测低效的循环
if re.search(r'for\s+.*in\s+range\(.*\):', code):
# 检查是否有嵌套循环
if code.count('for ') > 1:
issues.append({
"type": "INEFFICIENT_LOOP",
"severity": "MEDIUM",
"description": f"{file_path}: 存在嵌套循环,可能影响性能"
})
# 检测重复计算
if self._detect_redundant_calculations(code):
issues.append({
"type": "REDUNDANT_CALCULATION",
"severity": "LOW",
"description": f"{file_path}: 存在重复计算,建议缓存结果"
})
# 检测大文件读取
if re.search(r'open\(.*\).*read\(\)', code):
issues.append({
"type": "INEFFICIENT_IO",
"severity": "MEDIUM",
"description": f"{file_path}: 可能存在低效的文件读取方式"
})
# 检测过多的函数调用
if code.count('(') > 100:
issues.append({
"type": "EXCESSIVE_FUNCTION_CALLS",
"severity": "LOW",
"description": f"{file_path}: 函数调用次数较多,可能影响性能"
})
except Exception as e:
pass
return issues
def _detect_redundant_calculations(self, code: str) -> bool:
"""检测重复计算"""
# 简单的重复计算检测
lines = code.split('\n')
expressions = []
for line in lines:
# 提取可能的计算表达式
if '=' in line and any(op in line for op in ['+', '-', '*', '/', '**']):
parts = line.split('=')
if len(parts) > 1:
expr = parts[1].strip()
if expr and expr not in expressions:
expressions.append(expr)
elif expr and expr in expressions:
return True
return False
def _calculate_performance_score(self, issues: List[Dict[str, Any]]) -> float:
"""计算性能评分"""
score = 100.0
# 根据问题严重程度扣分
for issue in issues:
severity = issue.get("severity", "LOW")
if severity == "HIGH":
score -= 10.0
elif severity == "MEDIUM":
score -= 5.0
elif severity == "LOW":
score -= 2.0
return max(0.0, score)
def _generate_optimization_suggestions(self, issues: List[Dict[str, Any]]) -> List[str]:
"""生成优化建议"""
suggestions = []
# 根据问题类型生成建议
issue_types = set([issue.get("type", "") for issue in issues])
if "INEFFICIENT_LOOP" in issue_types:
suggestions.append("优化循环结构,减少嵌套循环,考虑使用列表推导式或生成器表达式")
if "REDUNDANT_CALCULATION" in issue_types:
suggestions.append("缓存重复计算的结果,避免不必要的计算")
if "INEFFICIENT_IO" in issue_types:
suggestions.append("使用上下文管理器和适当的缓冲区大小进行文件操作")
if "EXCESSIVE_FUNCTION_CALLS" in issue_types:
suggestions.append("减少不必要的函数调用,考虑内联关键代码")
# 通用性能优化建议
suggestions.extend([
"使用适当的数据结构,如字典代替列表进行频繁查找",
"考虑使用并行处理优化计算密集型任务",
"避免在循环中进行字符串拼接,使用 join() 方法",
"使用生成器代替列表处理大量数据"
])
return suggestions
def _collect_performance_metrics(self, code_path: str) -> Dict[str, Any]:
"""收集性能指标"""
metrics = {}
# 这里可以集成性能分析工具,如 cProfile
# 为了简单起见,我们只返回空字典
return metrics
3.5 最佳实践智能体
# 最佳实践智能体实现
import os
import re
from typing import List, Dict, Any
class BestPracticesAgent:
def __init__(self):
self.best_practices = {
"naming_conventions": {
"variables": r'^[a-z_][a-z0-9_]*$',
"functions": r'^[a-z_][a-z0-9_]*$',
"classes": r'^[A-Z][a-zA-Z0-9]*$',
"constants": r'^[A-Z_][A-Z0-9_]*$'
},
"code_organization": {
"max_line_length": 79,
"indentation": 4,
"blank_lines": {
"between_functions": 2,
"between_class_methods": 1
}
},
"documentation": {
"require_docstrings": True,
"docstring_format": "google"
}
}
def review_best_practices(self, code_path: str) -> Dict[str, Any]:
"""审查代码最佳实践"""
results = {
"violations": [],
"compliance_score": 100.0,
"suggestions": []
}
# 检查命名规范
results["violations"].extend(self._check_naming_conventions(code_path))
# 检查代码组织
results["violations"].extend(self._check_code_organization(code_path))
# 检查文档
results["violations"].extend(self._check_documentation(code_path))
# 计算合规性评分
results["compliance_score"] = self._calculate_compliance_score(results["violations"])
# 生成改进建议
results["suggestions"] = self._generate_suggestions(results["violations"])
return results
def _check_naming_conventions(self, code_path: str) -> List[Dict[str, Any]]:
"""检查命名规范"""
violations = []
for root, _, files in os.walk(code_path):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
code = f.read()
# 检查变量命名
variable_pattern = re.compile(r'\b([a-z_][a-z0-9_]*)\s*=')
matches = variable_pattern.findall(code)
for var_name in matches:
if not re.match(self.best_practices["naming_conventions"]["variables"], var_name):
violations.append({
"type": "NAMING_VIOLATION",
"severity": "LOW",
"description": f"{file_path}: 变量 {var_name} 不符合命名规范"
})
# 检查函数命名
function_pattern = re.compile(r'def\s+([a-z_][a-z0-9_]*)\s*\(')
matches = function_pattern.findall(code)
for func_name in matches:
if not re.match(self.best_practices["naming_conventions"]["functions"], func_name):
violations.append({
"type": "NAMING_VIOLATION",
"severity": "LOW",
"description": f"{file_path}: 函数 {func_name} 不符合命名规范"
})
# 检查类命名
class_pattern = re.compile(r'class\s+([A-Z][a-zA-Z0-9]*)\s*')
matches = class_pattern.findall(code)
for class_name in matches:
if not re.match(self.best_practices["naming_conventions"]["classes"], class_name):
violations.append({
"type": "NAMING_VIOLATION",
"severity": "LOW",
"description": f"{file_path}: 类 {class_name} 不符合命名规范"
})
except Exception as e:
pass
return violations
def _check_code_organization(self, code_path: str) -> List[Dict[str, Any]]:
"""检查代码组织"""
violations = []
for root, _, files in os.walk(code_path):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
# 检查行长度
for i, line in enumerate(lines):
if len(line) > self.best_practices["code_organization"]["max_line_length"]:
violations.append({
"type": "LINE_LENGTH_VIOLATION",
"severity": "LOW",
"description": f"{file_path}: 第 {i+1} 行长度超过 {self.best_practices['code_organization']['max_line_length']} 字符"
})
# 检查缩进
for i, line in enumerate(lines):
if line.strip() and not line.startswith(' ' * self.best_practices["code_organization"]["indentation"] * (line.count('\t') if '\t' in line else 0)):
violations.append({
"type": "INDENTATION_VIOLATION",
"severity": "LOW",
"description": f"{file_path}: 第 {i+1} 行缩进不符合规范"
})
except Exception as e:
pass
return violations
def _check_documentation(self, code_path: str) -> List[Dict[str, Any]]:
"""检查文档"""
violations = []
for root, _, files in os.walk(code_path):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
code = f.read()
# 检查函数文档字符串
function_pattern = re.compile(r'def\s+([a-z_][a-z0-9_]*)\s*\([^)]*\):\s*([^\n]*)')
matches = function_pattern.findall(code)
for func_name, docstring in matches:
if not docstring.strip().startswith('"""') and not docstring.strip().startswith("'''"):
violations.append({
"type": "DOCUMENTATION_VIOLATION",
"severity": "LOW",
"description": f"{file_path}: 函数 {func_name} 缺少文档字符串"
})
# 检查类文档字符串
class_pattern = re.compile(r'class\s+([A-Z][a-zA-Z0-9]*)\s*:\s*([^\n]*)')
matches = class_pattern.findall(code)
for class_name, docstring in matches:
if not docstring.strip().startswith('"""') and not docstring.strip().startswith("'''"):
violations.append({
"type": "DOCUMENTATION_VIOLATION",
"severity": "LOW",
"description": f"{file_path}: 类 {class_name} 缺少文档字符串"
})
except Exception as e:
pass
return violations
def _calculate_compliance_score(self, violations: List[Dict[str, Any]]) -> float:
"""计算合规性评分"""
score = 100.0
# 根据违规严重程度扣分
for violation in violations:
severity = violation.get("severity", "LOW")
if severity == "HIGH":
score -= 5.0
elif severity == "MEDIUM":
score -= 3.0
elif severity == "LOW":
score -= 1.0
return max(0.0, score)
def _generate_suggestions(self, violations: List[Dict[str, Any]]) -> List[str]:
"""生成改进建议"""
suggestions = []
# 根据违规类型生成建议
violation_types = set([violation.get("type", "") for violation in violations])
if "NAMING_VIOLATION" in violation_types:
suggestions.append("遵循 PEP 8 命名规范:变量和函数使用小写字母加下划线,类使用驼峰命名法,常量使用全大写字母加下划线")
if "LINE_LENGTH_VIOLATION" in violation_types:
suggestions.append("每行代码长度不超过 79 字符,长行可以使用括号进行换行")
if "INDENTATION_VIOLATION" in violation_types:
suggestions.append("使用 4 个空格进行缩进,避免混合使用空格和制表符")
if "DOCUMENTATION_VIOLATION" in violation_types:
suggestions.append("为所有公共函数和类添加文档字符串,遵循 Google 文档字符串格式")
# 通用最佳实践建议
suggestions.extend([
"遵循 PEP 8 代码风格指南",
"使用类型提示提高代码可读性和可维护性",
"编写单元测试确保代码质量",
"使用版本控制系统管理代码变更"
])
return suggestions
3.6 评审协调智能体
# 评审协调智能体实现
from typing import Dict, Any, List
import asyncio
import redis
import json
class ReviewCoordinatorAgent:
def __init__(self):
self.redis_client = redis.Redis(host='localhost', port=6379, db=0)
self.agents = {
"code_analysis": "CodeAnalysisAgent",
"security_review": "SecurityReviewAgent",
"performance_evaluation": "PerformanceEvaluationAgent",
"best_practices": "BestPracticesAgent"
}
async def coordinate_review(self, review_id: str) -> Dict[str, Any]:
"""协调代码审查流程"""
# 获取审查请求信息
review_info = self._get_review_info(review_id)
if not review_info:
return {"error": "Review not found"}
# 更新审查状态
self._update_review_status(review_id, "in_progress")
try:
# 并行执行各个智能体的审查
results = await self._execute_reviews(review_info)
# 汇总审查结果
summary = self._summarize_results(results)
# 生成审查报告
report = self._generate_report(review_id, review_info, summary)
# 更新审查状态
self._update_review_status(review_id, "completed")
# 存储审查结果
self._store_review_results(review_id, report)
return report
except Exception as e:
# 更新审查状态为失败
self._update_review_status(review_id, "failed")
return {"error": str(e)}
def _get_review_info(self, review_id: str) -> Dict[str, Any]:
"""获取审查请求信息"""
info = self.redis_client.hgetall(review_id)
if not info:
return {}
# 转换字节为字符串
review_info = {}
for key, value in info.items():
review_info[key.decode('utf-8')] = value.decode('utf-8')
return review_info
def _update_review_status(self, review_id: str, status: str):
"""更新审查状态"""
self.redis_client.hset(review_id, "status", status)
async def _execute_reviews(self, review_info: Dict[str, Any]) -> Dict[str, Any]:
"""并行执行各个智能体的审查"""
results = {}
# 模拟代码分析智能体
from code_analysis_agent import CodeAnalysisAgent
code_analyzer = CodeAnalysisAgent()
# 模拟安全审查智能体
from security_review_agent import SecurityReviewAgent
security_reviewer = SecurityReviewAgent()
# 模拟性能评估智能体
from performance_evaluation_agent import PerformanceEvaluationAgent
performance_evaluator = PerformanceEvaluationAgent()
# 模拟最佳实践智能体
from best_practices_agent import BestPracticesAgent
best_practices_reviewer = BestPracticesAgent()
# 并行执行审查
tasks = [
asyncio.to_thread(code_analyzer.analyze_code, review_info.get("repository", ".")),
asyncio.to_thread(security_reviewer.review_security, review_info.get("repository", ".")),
asyncio.to_thread(performance_evaluator.evaluate_performance, review_info.get("repository", ".")),
asyncio.to_thread(best_practices_reviewer.review_best_practices, review_info.get("repository", "."))
]
# 等待所有审查完成
code_analysis_result, security_result, performance_result, best_practices_result = await asyncio.gather(*tasks)
# 收集结果
results["code_analysis"] = code_analysis_result
results["security"] = security_result
results["performance"] = performance_result
results["best_practices"] = best_practices_result
return results
def _summarize_results(self, results: Dict[str, Any]) -> Dict[str, Any]:
"""汇总审查结果"""
summary = {
"total_issues": 0,
"issue_severity_distribution": {
"high": 0,
"medium": 0,
"low": 0
},
"overall_score": 0.0,
"key_issues": [],
"recommendations": []
}
# 计算总问题数和严重程度分布
for agent, agent_results in results.items():
if "vulnerabilities" in agent_results:
for vuln in agent_results["vulnerabilities"]:
summary["total_issues"] += 1
severity = vuln.get("severity", "low").lower()
if severity in summary["issue_severity_distribution"]:
summary["issue_severity_distribution"][severity] += 1
if "violations" in agent_results:
for violation in agent_results["violations"]:
summary["total_issues"] += 1
severity = violation.get("severity", "low").lower()
if severity in summary["issue_severity_distribution"]:
summary["issue_severity_distribution"][severity] += 1
if "issues" in agent_results:
for issue in agent_results["issues"]:
summary["total_issues"] += 1
severity = issue.get("severity", "low").lower()
if severity in summary["issue_severity_distribution"]:
summary["issue_severity_distribution"][severity] += 1
# 收集关键问题
if "vulnerabilities" in agent_results:
for vuln in agent_results["vulnerabilities"]:
if vuln.get("severity", "low").lower() == "high":
summary["key_issues"].append(vuln.get("description", ""))
# 收集建议
if "recommendations" in agent_results:
summary["recommendations"].extend(agent_results["recommendations"])
if "optimization_suggestions" in agent_results:
summary["recommendations"].extend(agent_results["optimization_suggestions"])
if "suggestions" in agent_results:
summary["recommendations"].extend(agent_results["suggestions"])
# 计算总体评分
scores = []
if "security" in results and "security_score" in results["security"]:
scores.append(results["security"]["security_score"])
if "performance" in results and "performance_score" in results["performance"]:
scores.append(results["performance"]["performance_score"])
if "best_practices" in results and "compliance_score" in results["best_practices"]:
scores.append(results["best_practices"]["compliance_score"])
if scores:
summary["overall_score"] = sum(scores) / len(scores)
return summary
def _generate_report(self, review_id: str, review_info: Dict[str, Any], summary: Dict[str, Any]) -> Dict[str, Any]:
"""生成审查报告"""
report = {
"review_id": review_id,
"review_info": review_info,
"summary": summary,
"timestamp": asyncio.get_event_loop().time(),
"status": "completed"
}
return report
def _store_review_results(self, review_id: str, report: Dict[str, Any]):
"""存储审查结果"""
# 存储审查报告
report_key = f"{review_id}:report"
self.redis_client.set(report_key, json.dumps(report))
# 设置过期时间(7天)
self.redis_client.expire(review_id, 7 * 24 * 60 * 60)
self.redis_client.expire(report_key, 7 * 24 * 60 * 60)
# 注意:实际使用时需要确保导入的模块存在
# 这里为了演示,我们假设这些模块已经实现
3.7 人类协作智能体
# 人类协作智能体实现
from typing import Dict, Any, List
import redis
import json
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
class HumanCollaborationAgent:
def __init__(self):
self.redis_client = redis.Redis(host='localhost', port=6379, db=0)
self.email_config = {
"smtp_server": "smtp.example.com",
"smtp_port": 587,
"username": "code-review@example.com",
"password": "your-password",
"from_email": "code-review@example.com"
}
def notify_reviewers(self, review_id: str, report: Dict[str, Any]):
"""通知人类审查者"""
# 获取审查请求信息
review_info = report.get("review_info", {})
reviewer = review_info.get("reviewer", "")
# 生成审查报告摘要
summary = report.get("summary", {})
report_summary = self._generate_report_summary(summary)
# 发送通知
if reviewer:
# 发送邮件通知
self._send_email_notification(reviewer, review_id, report_summary)
# 存储审查报告供人类审查者查看
self._store_report_for_human_review(review_id, report)
return {"status": "notification_sent"}
def collect_human_feedback(self, review_id: str, feedback: Dict[str, Any]):
"""收集人类反馈"""
# 存储人类反馈
feedback_key = f"{review_id}:feedback"
self.redis_client.set(feedback_key, json.dumps(feedback))
# 更新审查状态
self.redis_client.hset(review_id, "human_feedback_received", "true")
# 分析反馈并改进系统
self._analyze_feedback(feedback)
return {"status": "feedback_received"}
def _generate_report_summary(self, summary: Dict[str, Any]) -> str:
"""生成审查报告摘要"""
report_lines = []
report_lines.append("=== 代码审查报告摘要 ===")
report_lines.append(f"总体评分: {summary.get('overall_score', 0.0):.2f}/100")
report_lines.append(f"总问题数: {summary.get('total_issues', 0)}")
report_lines.append("问题严重程度分布:")
report_lines.append(f" - 高: {summary.get('issue_severity_distribution', {}).get('high', 0)}")
report_lines.append(f" - 中: {summary.get('issue_severity_distribution', {}).get('medium', 0)}")
report_lines.append(f" - 低: {summary.get('issue_severity_distribution', {}).get('low', 0)}")
if summary.get('key_issues', []):
report_lines.append("\n关键问题:")
for issue in summary.get('key_issues', [])[:5]: # 只显示前5个关键问题
report_lines.append(f" - {issue}")
if summary.get('recommendations', []):
report_lines.append("\n改进建议:")
for recommendation in summary.get('recommendations', [])[:5]: # 只显示前5个建议
report_lines.append(f" - {recommendation}")
report_lines.append("\n请登录代码审查系统查看完整报告。")
return '\n'.join(report_lines)
def _send_email_notification(self, reviewer: str, review_id: str, report_summary: str):
"""发送邮件通知"""
try:
# 创建邮件
msg = MIMEMultipart()
msg['From'] = self.email_config["from_email"]
msg['To'] = reviewer
msg['Subject'] = f"代码审查报告 - 审查ID: {review_id}"
# 添加邮件正文
msg.attach(MIMEText(report_summary, 'plain'))
# 发送邮件
with smtplib.SMTP(self.email_config["smtp_server"], self.email_config["smtp_port"]) as server:
server.starttls()
server.login(self.email_config["username"], self.email_config["password"])
server.send_message(msg)
print(f"Email notification sent to {reviewer}")
except Exception as e:
print(f"Failed to send email: {str(e)}")
def _store_report_for_human_review(self, review_id: str, report: Dict[str, Any]):
"""存储审查报告供人类审查者查看"""
# 这里可以将报告存储到数据库或文件系统中
# 为了简单起见,我们只在Redis中存储
report_key = f"{review_id}:full_report"
self.redis_client.set(report_key, json.dumps(report))
# 设置过期时间(30天)
self.redis_client.expire(report_key, 30 * 24 * 60 * 60)
def _analyze_feedback(self, feedback: Dict[str, Any]):
"""分析反馈并改进系统"""
# 这里可以实现反馈分析逻辑
# 例如,识别系统漏检的问题,调整评分算法等
# 为了简单起见,我们只打印反馈
print(f"Analyzing human feedback: {feedback}")
# 这里可以添加机器学习逻辑,根据人类反馈改进系统
# 例如,使用反馈训练模型,提高问题检测准确率
4. 系统集成与测试
4.1 系统集成
代码审查多智能体系统的集成主要包括以下几个方面:
- 版本控制系统集成:与 GitHub、GitLab 等版本控制系统集成,通过 Webhook 接收代码提交事件
- CI/CD 系统集成:与 Jenkins、GitHub Actions 等 CI/CD 系统集成,在构建过程中执行代码审查
- 代码托管平台集成:与代码托管平台集成,在 Pull Request 中显示审查结果
- 通知系统集成:与邮件、Slack 等通知系统集成,及时通知审查结果
4.2 系统测试
系统测试包括以下几个方面:
- 单元测试:测试各个智能体的核心功能
- 集成测试:测试智能体之间的协作
- 系统测试:测试整个代码审查流程
- 性能测试:测试系统在处理大型代码库时的性能
# 系统测试代码
import unittest
import asyncio
from review_coordinator_agent import ReviewCoordinatorAgent
from human_collaboration_agent import HumanCollaborationAgent
class TestCodeReviewSystem(unittest.TestCase):
def setUp(self):
self.coordinator = ReviewCoordinatorAgent()
self.human_agent = HumanCollaborationAgent()
def test_review_coordination(self):
"""测试审查协调流程"""
# 创建测试审查请求
test_review_id = "test_review_123"
# 模拟审查请求信息
import redis
redis_client = redis.Redis(host='localhost', port=6379, db=0)
redis_client.hset(test_review_id, mapping={
"repository": "./test_code",
"branch": "main",
"commit_hash": "test_hash",
"reviewer": "test@example.com",
"review_type": "full",
"status": "pending"
})
# 执行审查
loop = asyncio.get_event_loop()
result = loop.run_until_complete(self.coordinator.coordinate_review(test_review_id))
# 验证审查结果
self.assertEqual(result.get("status"), "completed")
self.assertIn("summary", result)
# 清理测试数据
redis_client.delete(test_review_id)
def test_human_feedback(self):
"""测试人类反馈收集"""
test_review_id = "test_review_456"
# 创建测试反馈
feedback = {
"reviewer": "test@example.com",
"rating": 4,
"comments": "审查结果准确,建议有用",
"issues_found": [],
"issues_missed": []
}
# 收集反馈
result = self.human_agent.collect_human_feedback(test_review_id, feedback)
# 验证反馈收集结果
self.assertEqual(result.get("status"), "feedback_received")
if __name__ == "__main__":
unittest.main()
5. 部署与运维
5.1 部署架构
代码审查多智能体系统的部署架构包括以下几个组件:
- 前端应用:Web 界面,用于查看审查报告和管理审查流程
- 后端服务:API 服务,处理审查请求和返回结果
- 智能体服务:各个智能体的运行环境
- 数据存储:Redis 用于缓存,数据库用于持久化存储
- 消息队列:用于智能体之间的通信
5.2 容器化部署
使用 Docker 容器化部署代码审查多智能体系统:
# docker-compose.yml
version: '3.8'
services:
redis:
image: redis:6.2-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
web:
build: ./web
ports:
- "8000:8000"
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
code_analysis_agent:
build: ./agents/code_analysis
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
security_review_agent:
build: ./agents/security_review
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
performance_evaluation_agent:
build: ./agents/performance_evaluation
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
best_practices_agent:
build: ./agents/best_practices
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
review_coordinator:
build: ./agents/review_coordinator
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
human_collaboration_agent:
build: ./agents/human_collaboration
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
volumes:
redis_data:
5.3 运维监控
系统运维监控包括以下几个方面:
- 系统监控:监控各个智能体的运行状态和资源使用情况
- 审查队列监控:监控审查请求的处理状态
- 性能监控:监控系统处理审查请求的性能
- 错误监控:监控系统运行中的错误和异常
更多推荐
所有评论(0)