fix: compliance optimizer now requires score improvement, retries LLM on failure
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.
This commit is contained in:
@@ -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 '<h2' in polished or '<p>' 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 '<h2' in polished or '<p>' 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:
|
||||
|
||||
Reference in New Issue
Block a user