From 004698cf98c34e254cc0e6317da2acf6ec931387 Mon Sep 17 00:00:00 2001 From: Yuzhiran Dev Date: Wed, 27 May 2026 09:23:49 +0800 Subject: [PATCH] fix: compliance optimizer now requires score improvement, retries LLM on failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: 'passed=True' check for soft quality issues (AI套话, 缺互动引导) always exits immediately even when LLM failed to make changes. Score 85 stays 85, content unchanged. Fix: 1. polish_with_llm: retry once on exception (was: single attempt) 2. main loop: only accept fix when score actually improves AND LLM produced output (opt_logs non-empty). If LLM returns same html unchanged, treat as failed attempt and retry. --- scripts/compliance_optimizer.py | 67 +++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/scripts/compliance_optimizer.py b/scripts/compliance_optimizer.py index 782f4e6..0180737 100644 --- a/scripts/compliance_optimizer.py +++ b/scripts/compliance_optimizer.py @@ -159,36 +159,40 @@ def fix_tags(html: str, platform: str) -> str: def polish_with_llm(html: str, platform: str, remaining_issues: Optional[List[Dict]] = None) -> Tuple[str, Optional[str]]: """用 LLM 优化文章内容,返回 (html, log_message_or_None) 如果指定 remaining_issues,则针对性修复合规问题 + LLM 失败时自动重试一次 """ if not HAVE_LLM: return html, None llm_cfg = get_llm_config() - try: - model = llm_cfg.get('model') if llm_cfg else None - temperature = llm_cfg.get('temperature', 0.5) if llm_cfg else 0.5 - max_tokens = llm_cfg.get('max_tokens', 4000) if llm_cfg else 4000 - system_prompt = llm_cfg.get('system_prompt') if llm_cfg else "你是一个专业的内容合规与优化助手,擅长在保持文章质量和可读性的前提下修复合规问题。" + for attempt in range(2): + try: + model = llm_cfg.get('model') if llm_cfg else None + temperature = llm_cfg.get('temperature', 0.5) if llm_cfg else 0.5 + max_tokens = llm_cfg.get('max_tokens', 4000) if llm_cfg else 4000 + system_prompt = llm_cfg.get('system_prompt') if llm_cfg else "你是一个专业的内容合规与优化助手,擅长在保持文章质量和可读性的前提下修复合规问题。" - if remaining_issues: - issues_desc = "\n".join( - f"- [{i['type']}] {i.get('category','')}: {i.get('detail','')}" - for i in remaining_issues - ) - prompt = get_prompt("compliance_fix", issues_desc=issues_desc, html=html) - else: - prompt = get_prompt("compliance_polish", html=html) - polished = call_llm(prompt, model=model, temperature=temperature, max_tokens=max_tokens, system_prompt=system_prompt) - polished = clean_html_content(polished) - polished = strip_ai_preface(polished) - polished = strip_thinking_html(polished) - if '' in polished: - if len(polished) > len(html) * 0.3 and len(polished) > 100: - if not any(kw in polished for kw in ['保留', '建议', '可以', '应该', '推荐', '改为', '替换为']): - tag = "针对性修复" if remaining_issues else "常规润色" - return polished, f"LLM {tag}" - logger.warning(f"LLM 优化输出异常(过短或含建议性文字),保留原文 (len={len(polished)})") - except Exception as e: - logger.warning(f"LLM 优化失败: {e}") + if remaining_issues: + issues_desc = "\n".join( + f"- [{i['type']}] {i.get('category','')}: {i.get('detail','')}" + for i in remaining_issues + ) + prompt = get_prompt("compliance_fix", issues_desc=issues_desc, html=html) + else: + prompt = get_prompt("compliance_polish", html=html) + polished = call_llm(prompt, model=model, temperature=temperature, max_tokens=max_tokens, system_prompt=system_prompt) + polished = clean_html_content(polished) + polished = strip_ai_preface(polished) + polished = strip_thinking_html(polished) + if '' in polished: + if len(polished) > len(html) * 0.3 and len(polished) > 100: + if not any(kw in polished for kw in ['保留', '建议', '可以', '应该', '推荐', '改为', '替换为']): + tag = "针对性修复" if remaining_issues else "常规润色" + return polished, f"LLM {tag}" + logger.warning(f"LLM 优化输出异常(过短或含建议性文字),保留原文 (len={len(polished)})") + except Exception as e: + logger.warning(f"LLM 优化失败 (尝试 {attempt+1}/2): {e}") + if attempt == 0: + logger.info(f"重试 LLM 调用...") return html, None def optimize_article(html: str, platform: str, topic_data: Dict, remaining_issues: Optional[List[Dict]] = None) -> Tuple[str, List[str]]: @@ -263,12 +267,13 @@ def main(topic_ids: List[str] = None): if issues: current_html = html current_issues = list(issues) + current_score = score for attempt in range(3): optimized_html, opt_logs = optimize_article(current_html, platform_dir, topic_data, current_issues) recheck = check_article(optimized_html, platform_dir, topic_data) - if recheck['passed']: + if recheck['passed'] and opt_logs and recheck['score'] > current_score: save_article(topic_id, platform_dir, optimized_html) - logger.info(f"✅ {label} 已修复并通过审查 (第{attempt+1}次修复)") + logger.info(f"✅ {label} 已修复并通过审查 (第{attempt+1}次修复) 分数: {current_score}→{recheck['score']}") results.append(OptimizationResult( file=f"db:{platform_dir}_{topic_id}", platform=platform_dir, @@ -280,11 +285,15 @@ def main(topic_ids: List[str] = None): status="passed" )) break + if optimized_html == current_html and not opt_logs: + logger.warning(f"{label} LLM 未输出有效修改(第{attempt+1}次),继续重试...") + continue current_issues = recheck['issues'] current_html = optimized_html + current_score = recheck['score'] else: save_article(topic_id, platform_dir, current_html) - logger.warning(f"⚠️ {label} 仍有 {len(current_issues)} 个问题未修复,已强制通过") + logger.warning(f"⚠️ {label} 仍有 {len(current_issues)} 个问题未修复,已强制通过(当前分 {current_score})") results.append(OptimizationResult( file=f"db:{platform_dir}_{topic_id}", platform=platform_dir, @@ -292,7 +301,7 @@ def main(topic_ids: List[str] = None): title=topic_data.get('title',''), original_issues=len(issues), fixed_issues=len(issues) - len(current_issues), - final_score=recheck['score'], + final_score=current_score, status="passed" )) else: