diff --git a/services/code_review_pipeline_service.py b/services/code_review_pipeline_service.py index adc0ebd..4fb37bb 100644 --- a/services/code_review_pipeline_service.py +++ b/services/code_review_pipeline_service.py @@ -189,10 +189,10 @@ class CodeReviewPipeline: # ── Step 2:Hermes 掃描 ─────────────────────────────────────────────────── def _hermes_scan(self, files: Dict[str, str]) -> List[Dict]: + """直呼內網 Ollama(http://192.168.0.111:11434),免認證""" try: - from services.ai_provider import ai_provider_service + import requests as _req - # 最多送 4 個檔案給 Hermes,避免 context overflow files_text = "\n\n".join( f"### {name}\n```python\n{content}\n```" for name, content in list(files.items())[:4] @@ -212,23 +212,21 @@ class CodeReviewPipeline: 只輸出 JSON 陣列,不含其他文字。無問題時輸出 []""" - resp = ai_provider_service.generate( - prompt=prompt, - provider="ollama", - model="hermes3:latest", - temperature=0.1, + resp = _req.post( + "http://192.168.0.111:11434/api/generate", + json={"model": "hermes3:latest", "prompt": prompt, + "stream": False, "options": {"temperature": 0.1}}, timeout=120, ) - if not (resp and resp.success): - logger.warning("[CodeReview] Hermes 未回應: %s", getattr(resp, "error", "")) - return [] + resp.raise_for_status() + raw = resp.json().get("response", "").strip() - match = re.search(r"\[.*\]", resp.content, re.DOTALL) + match = re.search(r"\[.*\]", raw, re.DOTALL) if not match: + logger.warning("[CodeReview] Hermes 回應無 JSON: %s", raw[:200]) return [] findings = json.loads(match.group()) - # 更新 severity 計數 for f in findings: sev = f.get("severity", "LOW").lower() if sev in self.state["severity_summary"]: @@ -244,46 +242,64 @@ class CodeReviewPipeline: # ── Step 3:OpenClaw 評估 ────────────────────────────────────────────────── def _openclaw_assess(self, files: Dict[str, str], findings: List[Dict]) -> str: - if not GEMINI_API_KEY: - logger.warning("[CodeReview] GEMINI_API_KEY 未設定,跳過 OpenClaw") - return "" - try: - import google.generativeai as genai - genai.configure(api_key=GEMINI_API_KEY) - model = genai.GenerativeModel( - model_name=REVIEW_MODEL, - generation_config=genai.types.GenerationConfig( - temperature=0.3, max_output_tokens=1500, - ), - system_instruction=( - "你是 OpenClaw 程式碼品質戰略分析師,以技術主管視角評估部署後程式碼。" - "語言:繁體中文。風格:精準、數據導向、可執行建議。" - ), - ) - sev = self.state["severity_summary"] - findings_json = json.dumps(findings[:8], ensure_ascii=False, indent=2) - files_list = "\n".join(f"- {k} ({len(v)} 字元)" for k, v in list(files.items())[:5]) + """ + 優先用 Gemini(GEMINI_API_KEY),降級用 ElephantAlpha via OpenRouter + (容器內 OPENROUTER_API_KEY 一定存在) + """ + sev = self.state["severity_summary"] + findings_json = json.dumps(findings[:8], ensure_ascii=False, indent=2) + files_list = "\n".join(f"- {k} ({len(v)} 字元)" for k, v in list(files.items())[:5]) - prompt = f"""【部署資訊】Commit {self.commit_sha[:8]} @ {self.branch} + system = ( + "你是 OpenClaw 程式碼品質戰略分析師,以技術主管視角評估部署後程式碼。" + "語言:繁體中文。風格:精準、數據導向、可執行建議。" + ) + user_prompt = f"""【部署】Commit {self.commit_sha[:8]} @ {self.branch} 【變更檔案】 {files_list} 【Hermes 掃描摘要】CRITICAL={sev['critical']} HIGH={sev['high']} MEDIUM={sev['medium']} LOW={sev['low']} -【Hermes 詳細問題】 +【問題明細】 {findings_json} 請產出程式碼品質評估(使用 HTML 標題,150字以內): +🔍 整體風險等級(一句理由) +⚠️ 最需關注問題(TOP 2) +💡 架構優化方向(1條長期建議) +✅ 本次部署亮點""" -🔍 整體風險等級(CRITICAL / HIGH / MEDIUM / LOW,一句理由) -⚠️ 最需關注問題(TOP 2,具體說明) -💡 架構優化方向(1 條長期建議) -✅ 本次部署亮點(值得肯定的地方)""" + # 優先 Gemini + if GEMINI_API_KEY: + try: + import google.generativeai as genai + genai.configure(api_key=GEMINI_API_KEY) + model = genai.GenerativeModel( + model_name=REVIEW_MODEL, + generation_config=genai.types.GenerationConfig( + temperature=0.3, max_output_tokens=1500, + ), + system_instruction=system, + ) + resp = model.generate_content(user_prompt, request_options={"timeout": 90}) + return resp.text or "" + except Exception as e: + logger.warning("[CodeReview] OpenClaw Gemini 失敗,降級 ElephantAlpha: %s", e) - resp = model.generate_content(prompt, request_options={"timeout": 90}) - return resp.text or "" + # 降級:ElephantAlpha via OpenRouter(OPENROUTER_API_KEY 容器內一定有) + try: + from services.elephant_service import elephant_service + resp = elephant_service.generate( + prompt=user_prompt, + system_prompt=system, + temperature=0.3, + timeout=90, + ) + if resp.success: + return resp.content or "" except Exception as e: - logger.warning("[CodeReview] OpenClaw 評估失敗: %s", e) - return "" + logger.warning("[CodeReview] OpenClaw ElephantAlpha 降級也失敗: %s", e) + + return "" # ── Step 4:ElephantAlpha 決策 ─────────────────────────────────────────────