| 391 | |
| 392 | |
| 393 | class AILogAnalyzeThread(QThread): |
| 394 | resultSignal = pyqtSignal(bool, str) |
| 395 | |
| 396 | def __init__(self, base_url: str, api_key: str, model: str, raw_log: str, parent=None): |
| 397 | super().__init__(parent) |
| 398 | self.base_url = _normalize_base_url(base_url) |
| 399 | self.api_key = api_key.strip() |
| 400 | self.model = model.strip() |
| 401 | self.raw_log = raw_log |
| 402 | |
| 403 | def _load_prompt(self) -> str: |
| 404 | return get_ai_analyze_prompt() |
| 405 | |
| 406 | def _upload_to_mclogs(self) -> dict: |
| 407 | s = MCSLNetworkSession() |
| 408 | headers = dict(s.MCSLNetworkHeaders) |
| 409 | r = s.post("https://api.mclo.gs/1/log", data={"content": self.raw_log}, headers=headers) |
| 410 | data = r.json() |
| 411 | if not data.get("success"): |
| 412 | raise RuntimeError(data.get("error") or "mclo.gs 请求失败") |
| 413 | return data |
| 414 | |
| 415 | def _fetch_mclogs_insights(self, log_id: str) -> dict: |
| 416 | s = MCSLNetworkSession() |
| 417 | headers = dict(s.MCSLNetworkHeaders) |
| 418 | r = s.get(f"https://api.mclo.gs/1/insights/{log_id}", headers=headers) |
| 419 | if getattr(r, "status_code", 0) != 200: |
| 420 | raise RuntimeError(f"mclo.gs insights 请求失败:HTTP {getattr(r, 'status_code', 0)}") |
| 421 | data = r.json() |
| 422 | if not isinstance(data, dict): |
| 423 | raise RuntimeError("mclo.gs insights 返回格式异常") |
| 424 | if data.get("success") is False: |
| 425 | raise RuntimeError(data.get("error") or "mclo.gs insights 请求失败") |
| 426 | return data |
| 427 | |
| 428 | def _format_mclogs_summary(self, mclogs_data: dict) -> str: |
| 429 | analysis = mclogs_data.get("analysis") or {} |
| 430 | problems = analysis.get("problems") or [] |
| 431 | if not problems: |
| 432 | return "(无)" |
| 433 | lines = [] |
| 434 | for p in problems[:15]: |
| 435 | msg = _as_text(p.get("message")) |
| 436 | counter = p.get("counter") |
| 437 | if not msg: |
| 438 | continue |
| 439 | if isinstance(counter, int) and counter > 1: |
| 440 | lines.append(f"- {msg} (x{counter})") |
| 441 | else: |
| 442 | lines.append(f"- {msg}") |
| 443 | solutions = p.get("solutions") or [] |
| 444 | for s in solutions[:3]: |
| 445 | sm = _as_text(s.get("message")) |
| 446 | if sm: |
| 447 | lines.append(f" • {sm}") |
| 448 | return "\n".join(lines) if lines else "(无)" |
| 449 | |
| 450 | def _call_ai(self, prompt: str, user_content: str) -> str: |