Commit 470113cc authored by 方海彤's avatar 方海彤 👶🏻

feat: display actual model names from API responses

Updates `call_llm` to return both the content and the actual model name returned by the API. This ensures that the review summary and notifications display the real model used (e.g., "codex" when using a local proxy) rather than static configuration values. Updated `main.py` to propagate and display these dynamic model names in the final report.
parent 25bd6025
...@@ -137,7 +137,8 @@ git diff → 文件过滤 → LLM 分流判定 → 审查 → 飞书通知 ...@@ -137,7 +137,8 @@ git diff → 文件过滤 → LLM 分流判定 → 审查 → 飞书通知
|------|------| |------|------|
| `AI_REVIEW_API_URL` | `http://<你Mac内网IP>:8088/v1` | | `AI_REVIEW_API_URL` | `http://<你Mac内网IP>:8088/v1` |
| `AI_REVIEW_API_KEY` | 上面的 `CODEX_PROXY_TOKEN` | | `AI_REVIEW_API_KEY` | 上面的 `CODEX_PROXY_TOKEN` |
| `AI_REVIEW_MODEL` | 任意值(代理忽略,例如 `codex`) |
仅此两项。飞书通知展示的模型名走 OpenAI 协议响应里的 `model` 字段——代理会回报 `codex`,代码自动如实展示,无需配 `AI_REVIEW_MODEL` / `AI_REVIEW_TRIAGE_MODEL`
> 已有项目检查项目级 Variables 里有没有 `AI_REVIEW_API_KEY` —— 项目级会覆盖 group 级,要么删掉让它继承,要么改成新 token。 > 已有项目检查项目级 Variables 里有没有 `AI_REVIEW_API_KEY` —— 项目级会覆盖 group 级,要么删掉让它继承,要么改成新 token。
......
...@@ -170,8 +170,11 @@ def build_deep_prompt(diff_text): ...@@ -170,8 +170,11 @@ def build_deep_prompt(diff_text):
def call_llm(system_msg, user_msg, max_tokens=4096, timeout=300, model=None, enable_thinking=False): def call_llm(system_msg, user_msg, max_tokens=4096, timeout=300, model=None, enable_thinking=False):
"""返回 (content, response_model)。response_model 来自服务端响应(OpenAI 协议字段),
本地代理会回报 "codex",真 LLM 会回报真实模型名;用于飞书通知里如实展示。"""
request_model = model or MODEL
payload = { payload = {
"model": model or MODEL, "model": request_model,
"messages": [ "messages": [
{"role": "system", "content": system_msg}, {"role": "system", "content": system_msg},
{"role": "user", "content": user_msg} {"role": "user", "content": user_msg}
...@@ -199,23 +202,24 @@ def call_llm(system_msg, user_msg, max_tokens=4096, timeout=300, model=None, ena ...@@ -199,23 +202,24 @@ def call_llm(system_msg, user_msg, max_tokens=4096, timeout=300, model=None, ena
try: try:
with urllib.request.urlopen(req, timeout=timeout) as resp: with urllib.request.urlopen(req, timeout=timeout) as resp:
result = json.loads(resp.read().decode("utf-8")) result = json.loads(resp.read().decode("utf-8"))
response_model = result.get("model") or request_model
choices = result.get("choices", []) choices = result.get("choices", [])
if not choices: if not choices:
return "⚠️ API 返回了空结果,可能触发了内容安全策略。" return "⚠️ API 返回了空结果,可能触发了内容安全策略。", response_model
msg = choices[0].get("message", {}) msg = choices[0].get("message", {})
content = msg.get("content", "⚠️ API 返回格式异常") content = msg.get("content", "⚠️ API 返回格式异常")
# 优先使用 reasoning_content(部分 OpenAI 兼容网关将 thinking 分离到此字段) # 优先使用 reasoning_content(部分 OpenAI 兼容网关将 thinking 分离到此字段)
# 如果存在 reasoning_content,说明 content 已经是干净的正文 # 如果存在 reasoning_content,说明 content 已经是干净的正文
if msg.get("reasoning_content"): if msg.get("reasoning_content"):
return content return content, response_model
# 过滤 thinking 内容,避免飞书通知等场景内容过长 # 过滤 thinking 内容,避免飞书通知等场景内容过长
if content: if content:
content = _strip_thinking(content) content = _strip_thinking(content)
return content return content, response_model
except urllib.error.HTTPError as e: except urllib.error.HTTPError as e:
body = e.read().decode("utf-8") if e.fp else "" body = e.read().decode("utf-8") if e.fp else ""
return f"❌ API 请求失败 (HTTP {e.code}): {body}" return f"❌ API 请求失败 (HTTP {e.code}): {body}", request_model
except urllib.error.URLError as e: except urllib.error.URLError as e:
return f"❌ 网络错误: {e.reason}" return f"❌ 网络错误: {e.reason}", request_model
except Exception as e: except Exception as e:
return f"❌ 调用失败: {e}" return f"❌ 调用失败: {e}", request_model
...@@ -45,7 +45,6 @@ def main(): ...@@ -45,7 +45,6 @@ def main():
[ [
f"提交者: {committer}", f"提交者: {committer}",
f"提交: {commit_sha_short} {commit_msg}", f"提交: {commit_sha_short} {commit_msg}",
f"分流模型: {TRIAGE_MODEL}",
"", "",
"✅ 没有需要审查的代码变更。", "✅ 没有需要审查的代码变更。",
] ]
...@@ -65,7 +64,7 @@ def main(): ...@@ -65,7 +64,7 @@ def main():
print(" ⏳ 正在调用大模型分流判定...") print(" ⏳ 正在调用大模型分流判定...")
t_triage = time.time() t_triage = time.time()
triage_system_msg, triage_user_msg = build_triage_prompt(triage_diff) triage_system_msg, triage_user_msg = build_triage_prompt(triage_diff)
triage_result = call_llm( triage_result, triage_model_used = call_llm(
triage_system_msg, triage_system_msg,
triage_user_msg, triage_user_msg,
max_tokens=256, max_tokens=256,
...@@ -89,6 +88,8 @@ def main(): ...@@ -89,6 +88,8 @@ def main():
review_level = triage_decision # skip / standard / deep review_level = triage_decision # skip / standard / deep
print(f" 📌 分流决策: {review_level} | 类型: {triage_category} | 原因: {triage_reason}") print(f" 📌 分流决策: {review_level} | 类型: {triage_category} | 原因: {triage_reason}")
review_model_used = triage_model_used # skip 路径下不会再发起调用,沿用分流模型名
if triage_decision == "skip": if triage_decision == "skip":
review_result = f"✅ 代码审查通过,LLM 判定可跳过完整审查:{triage_reason}" review_result = f"✅ 代码审查通过,LLM 判定可跳过完整审查:{triage_reason}"
print(f" ✅ 分流判定:跳过完整审查({triage_reason})") print(f" ✅ 分流判定:跳过完整审查({triage_reason})")
...@@ -100,7 +101,7 @@ def main(): ...@@ -100,7 +101,7 @@ def main():
print(f" ⏳ 正在调用标准审查 ({TRIAGE_MODEL})...") print(f" ⏳ 正在调用标准审查 ({TRIAGE_MODEL})...")
t_review = time.time() t_review = time.time()
system_msg, user_msg = build_standard_prompt(diff) system_msg, user_msg = build_standard_prompt(diff)
review_result = call_llm( review_result, review_model_used = call_llm(
system_msg, user_msg, system_msg, user_msg,
max_tokens=STANDARD_MAX_TOKENS, max_tokens=STANDARD_MAX_TOKENS,
timeout=STANDARD_TIMEOUT, timeout=STANDARD_TIMEOUT,
...@@ -116,7 +117,7 @@ def main(): ...@@ -116,7 +117,7 @@ def main():
print(f" ⏳ 正在调用深度审查 ({MODEL}, thinking mode)...") print(f" ⏳ 正在调用深度审查 ({MODEL}, thinking mode)...")
t_review = time.time() t_review = time.time()
system_msg, user_msg = build_deep_prompt(diff) system_msg, user_msg = build_deep_prompt(diff)
review_result = call_llm( review_result, review_model_used = call_llm(
system_msg, user_msg, system_msg, user_msg,
max_tokens=DEEP_MAX_TOKENS, max_tokens=DEEP_MAX_TOKENS,
timeout=DEEP_TIMEOUT, timeout=DEEP_TIMEOUT,
...@@ -147,8 +148,8 @@ def main(): ...@@ -147,8 +148,8 @@ def main():
_level_labels = { _level_labels = {
"skip": "跳过", "skip": "跳过",
"standard": f"标准审查 ({TRIAGE_MODEL})", "standard": f"标准审查 ({review_model_used})",
"deep": f"深度审查 ({MODEL}, thinking)", "deep": f"深度审查 ({review_model_used}, thinking)",
} }
review_level_label = _level_labels.get(review_level, review_level) review_level_label = _level_labels.get(review_level, review_level)
...@@ -158,7 +159,7 @@ def main(): ...@@ -158,7 +159,7 @@ def main():
f"分支: {branch}", f"分支: {branch}",
f"提交: {commit_sha_short} {commit_msg}", f"提交: {commit_sha_short} {commit_msg}",
f"变更: {files} 个文件, +{added} -{removed} 行", f"变更: {files} 个文件, +{added} -{removed} 行",
f"分流模型: {TRIAGE_MODEL}", f"分流模型: {triage_model_used}",
f"审查层级: {review_level_label}", f"审查层级: {review_level_label}",
f"变更类型: {triage_category}", f"变更类型: {triage_category}",
f"分析耗时: {elapsed_str}", f"分析耗时: {elapsed_str}",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment