Files
AI-Check-Test/.gitea/checker/llm_reviewer.py
dongzi 556f5b8ab6
Some checks failed
API Parameter Change Check / api-param-check (push) Failing after 3s
test
2026-06-03 15:02:21 +08:00

183 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
豆包 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 DiffController 相关)
```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)