This commit is contained in:
182
.gitea/checker/llm_reviewer.py
Normal file
182
.gitea/checker/llm_reviewer.py
Normal file
@@ -0,0 +1,182 @@
|
||||
"""
|
||||
豆包 LLM 接口参数变更审核模块。
|
||||
仅审核 Controller 层接口参数的增删改,不对 Java 源码做通用代码审查。
|
||||
"""
|
||||
|
||||
import json
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import requests
|
||||
|
||||
from comparator import EndpointChangeReport
|
||||
|
||||
|
||||
def is_llm_enabled(config: Dict[str, Any]) -> bool:
|
||||
"""
|
||||
判断大模型总开关是否开启。
|
||||
|
||||
:param config: 完整配置字典
|
||||
:return: True=启用 LLM 审核
|
||||
"""
|
||||
return config.get("llm", {}).get("enabled", True)
|
||||
|
||||
|
||||
def call_doubao_api(
|
||||
api_key: str,
|
||||
prompt: str,
|
||||
config: Dict[str, Any],
|
||||
) -> Optional[str]:
|
||||
"""
|
||||
调用火山引擎豆包 Chat Completions API。
|
||||
|
||||
:param api_key: API Key
|
||||
:param prompt: 用户提示词
|
||||
:param config: 完整配置
|
||||
:return: LLM 回复文本;失败返回 None
|
||||
"""
|
||||
if not api_key or api_key == "YOUR_DOUBAO_API_KEY":
|
||||
print("[警告] 未配置豆包 API Key,跳过 LLM 审核。")
|
||||
return None
|
||||
|
||||
llm_cfg = config.get("llm", {})
|
||||
model = llm_cfg.get("model") or llm_cfg.get("endpoint_id", "")
|
||||
if not model:
|
||||
print("[警告] 未配置 llm.model 或 llm.endpoint_id,跳过 LLM 审核。")
|
||||
return None
|
||||
|
||||
api_url = llm_cfg.get(
|
||||
"api_url", "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
|
||||
)
|
||||
timeout = llm_cfg.get("timeout")
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
}
|
||||
payload = {
|
||||
"model": model,
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": (
|
||||
"你是 Java Spring Boot Controller 接口参数变更分析专家。"
|
||||
"你的职责是识别并整理 Controller 层接口参数的增、删、改、重命名,"
|
||||
"确认 AST 解析结果是否准确,并指出对调用方的兼容性影响。"
|
||||
),
|
||||
},
|
||||
{"role": "user", "content": prompt},
|
||||
],
|
||||
"temperature": 0.1,
|
||||
}
|
||||
|
||||
try:
|
||||
kwargs = {"headers": headers, "json": payload}
|
||||
if timeout is not None:
|
||||
kwargs["timeout"] = timeout
|
||||
|
||||
resp = requests.post(api_url, **kwargs)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
if "choices" in data and data["choices"]:
|
||||
return data["choices"][0]["message"]["content"]
|
||||
print("[错误] AI 返回格式异常")
|
||||
return None
|
||||
except requests.RequestException as exc:
|
||||
print(f"[错误] 豆包 API 调用失败: {exc}")
|
||||
return None
|
||||
|
||||
|
||||
def build_parameter_change_prompt(
|
||||
reports: List[EndpointChangeReport],
|
||||
changed_files: List[str],
|
||||
git_diff: str = "",
|
||||
) -> str:
|
||||
"""
|
||||
构造接口参数变更审核提示词(对齐第一版需求:识别 Controller 参数增删改)。
|
||||
|
||||
:param reports: AST 解析对比结果
|
||||
:param changed_files: 本次变更的 Controller 文件列表
|
||||
:param git_diff: 相关文件的 Git diff 内容
|
||||
:return: 完整 prompt
|
||||
"""
|
||||
ast_report = []
|
||||
for r in reports:
|
||||
ast_report.append(
|
||||
{
|
||||
"uri": f"{r.http_method} {r.uri}",
|
||||
"controller": r.controller_class,
|
||||
"method": r.method_name,
|
||||
"is_new_endpoint": r.is_new_endpoint,
|
||||
"is_removed_endpoint": r.is_removed_endpoint,
|
||||
"parameter_changes": [
|
||||
{
|
||||
"type": c.change_type.value,
|
||||
"name": c.param_name,
|
||||
"java_type": c.param_type,
|
||||
"old_name": c.old_name,
|
||||
"old_type": c.old_type,
|
||||
"required": c.required,
|
||||
"detail": c.detail,
|
||||
}
|
||||
for c in r.parameter_changes
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
diff_block = git_diff.strip() if git_diff.strip() else "(无 diff 内容)"
|
||||
if len(diff_block) > 8000:
|
||||
diff_block = diff_block[:8000] + "\n... [diff 过长,已截断]"
|
||||
|
||||
return f"""请审核以下 Controller 层接口参数变更,整理并确认变更结果。
|
||||
|
||||
## 变更的 Controller 文件
|
||||
{json.dumps(changed_files, ensure_ascii=False)}
|
||||
|
||||
## AST 自动解析的参数变更报告
|
||||
{json.dumps(ast_report, ensure_ascii=False, indent=2)}
|
||||
|
||||
## Git Diff(Controller 相关)
|
||||
```diff
|
||||
{diff_block}
|
||||
```
|
||||
|
||||
## 审核要求
|
||||
1. 逐条确认 AST 报告的参数变更是否准确(增/删/改/重命名)
|
||||
2. 若 AST 有遗漏,补充遗漏的接口参数变更
|
||||
3. 若 AST 有误报,指出并修正
|
||||
4. 按以下格式整理每个接口的变更(与通知模板一致):
|
||||
URI: GET /api/xxx
|
||||
参数变更:
|
||||
- 删除: Boolean userType
|
||||
- 新增: Boolean includeDisabled (是否必填:false)
|
||||
- 重命名: String userName -> String accountName
|
||||
5. 简要说明是否存在破坏性变更(影响前端/调用方)
|
||||
6. 用中文回复,简洁清晰
|
||||
"""
|
||||
|
||||
|
||||
def review_parameter_changes(
|
||||
reports: List[EndpointChangeReport],
|
||||
config: Dict[str, Any],
|
||||
changed_files: List[str],
|
||||
git_diff: str = "",
|
||||
) -> Optional[str]:
|
||||
"""
|
||||
使用 LLM 审核 Controller 接口参数变更(AST 结果的二次确认与整理)。
|
||||
|
||||
:param reports: AST 对比报告
|
||||
:param config: 完整配置
|
||||
:param changed_files: 变更的 Controller 文件
|
||||
:param git_diff: Git diff 文本
|
||||
:return: LLM 整理后的审核结论;未启用或无报告时返回 None
|
||||
"""
|
||||
if not is_llm_enabled(config):
|
||||
print("[LLM] 大模型开关已关闭,跳过接口参数变更审核。")
|
||||
return None
|
||||
|
||||
if not reports:
|
||||
return None
|
||||
|
||||
llm_cfg = config.get("llm", {})
|
||||
prompt = build_parameter_change_prompt(reports, changed_files, git_diff)
|
||||
return call_doubao_api(llm_cfg.get("api_key", ""), prompt, config)
|
||||
Reference in New Issue
Block a user