From f51dc173f700b10f6fe40d7469fe253cda042ff5 Mon Sep 17 00:00:00 2001 From: OoO Date: Tue, 19 May 2026 00:04:27 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A3=9C=20PPT=20=E8=A6=96=E8=A6=BA=20QA=20?= =?UTF-8?q?=E8=A8=BA=E6=96=B7=E6=91=98=E8=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO_NEXT_STEPS.txt | 1 + config.py | 2 +- routes/admin_observability_routes.py | 34 +++++++++++++++++++++--- templates/admin/ppt_audit_history.html | 4 +-- tests/test_admin_observability_routes.py | 14 ++++++++-- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/TODO_NEXT_STEPS.txt b/TODO_NEXT_STEPS.txt index d543a5d..ffa026e 100644 --- a/TODO_NEXT_STEPS.txt +++ b/TODO_NEXT_STEPS.txt @@ -4,6 +4,7 @@ ================================================================================ 【已完成】 + - V10.213 補 `/observability/ppt_audit_history` 視覺 QA 診斷摘要:審核歷史與 Action Queue 直接顯示 `ppt_audit_results.issues_found` 的投影片問題,讓「有問題」可追查,不再只剩問題數或空白錯誤欄。 - V10.212 修正 PPT 視覺 QA 的 Ollama 三主機 fallback:當 Primary/Secondary request timeout 超過 unhealthy TTL 時,第三輪仍強制打 111 final fallback;PPT 截圖送模型前轉輕量 JPEG、縮小輸出 token,降低單檔審核耗時。 - V10.211 補 `/observability/ppt_audit_history` 全類型視覺 QA:審核歷史不再限 daily,頁面新增「立即視覺 QA」非阻塞補跑,結果寫入 `ppt_audit_results`;模型失敗時也保留 slide error,避免產線狀態只剩空白。 - V10.210 補 `/observability/ppt_audit_history` 審核歷史同頁回放:每筆 daily 視覺審核紀錄的動作欄新增「回放」按鈕,沿用 PDF 預覽抽屜並保留下載/開新頁,讓問題追查不必再回檔案表找簡報。 diff --git a/config.py b/config.py index 74592a2..a1a897b 100644 --- a/config.py +++ b/config.py @@ -320,7 +320,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.212" +SYSTEM_VERSION = "V10.213" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/routes/admin_observability_routes.py b/routes/admin_observability_routes.py index c00fbae..87b0193 100644 --- a/routes/admin_observability_routes.py +++ b/routes/admin_observability_routes.py @@ -2473,7 +2473,7 @@ def _build_ppt_pipeline_view(files, auto_generation, audit_stats, generation_run triage_entries.append({ 'title': item.get('pptx_filename') or '未命名檔案', 'meta': item.get('audited_at') or '時間未知', - 'detail': item.get('error_msg') or f"問題 {item.get('issues_count', 0)} 個", + 'detail': item.get('issue_summary') or item.get('error_msg') or f"問題 {item.get('issues_count', 0)} 個", 'status_label': '視覺 QA', 'filename': item.get('pptx_filename') or '', 'report_type': 'daily', @@ -2538,7 +2538,7 @@ def _build_ppt_pipeline_view(files, auto_generation, audit_stats, generation_run { 'title': item.get('pptx_filename') or '未命名檔案', 'meta': item.get('audited_at') or '時間未知', - 'detail': item.get('error_msg') or f"問題 {item.get('issues_count', 0)} 個,信心 {item.get('confidence', 0):.2f}", + 'detail': item.get('issue_summary') or item.get('error_msg') or f"問題 {item.get('issues_count', 0)} 個,信心 {item.get('confidence', 0):.2f}", 'status_label': '需修復' if item.get('audit_status') == 'failed' else '需排查', 'filename': item.get('pptx_filename'), } @@ -2792,6 +2792,32 @@ def ppt_audit_history(): audit_filter_sql = " AND pptx_filename LIKE :audit_prefix" audit_params['audit_prefix'] = f"{report_prefix}%" + def _summarize_ppt_issues(raw_issues) -> str: + """把 ppt_audit_results.issues_found 壓成表格可讀的診斷摘要。""" + if not raw_issues: + return '' + try: + import json as _json + issues_payload = _json.loads(raw_issues) if isinstance(raw_issues, str) else raw_issues + except Exception: + return '' + if not isinstance(issues_payload, list): + return '' + snippets = [] + for item in issues_payload: + if not isinstance(item, dict): + continue + slide = item.get('slide') + for issue in item.get('issues') or []: + text = str(issue).strip() + if not text: + continue + prefix = f"S{slide}: " if slide else "" + snippets.append(f"{prefix}{text}") + if len(snippets) >= 3: + return ';'.join(snippets) + return ';'.join(snippets) + # Phase 38+:讀指定月份 / 指定簡報類型 audit 歷史 try: session = get_session() @@ -2799,7 +2825,8 @@ def ppt_audit_history(): audit_rows = session.execute( sa_text(f""" SELECT audited_at, pptx_filename, audit_status, - issues_count, confidence, duration_ms, error_msg + issues_count, confidence, duration_ms, error_msg, + issues_found FROM ppt_audit_results WHERE audited_at >= :month_start AND audited_at < :month_end @@ -2818,6 +2845,7 @@ def ppt_audit_history(): 'confidence': float(r[4] or 0), 'duration_ms': int(r[5] or 0), 'error_msg': r[6], + 'issue_summary': _summarize_ppt_issues(r[7]), } for r in audit_rows ] diff --git a/templates/admin/ppt_audit_history.html b/templates/admin/ppt_audit_history.html index 66f72bb..9f45fb5 100644 --- a/templates/admin/ppt_audit_history.html +++ b/templates/admin/ppt_audit_history.html @@ -373,7 +373,7 @@
- + {% for r in audit_records %} @@ -390,7 +390,7 @@ - +
時間檔名結果問題信心耗時錯誤動作
時間檔名結果問題信心耗時診斷摘要動作
{{ r.issues_count }} {{ "%.2f"|format(r.confidence) }} {{ r.duration_ms }}{{ (r.error_msg or '')[:80] }}{{ (r.issue_summary or r.error_msg or '')[:180] }} {% if r.pptx_filename %}