#!/usr/bin/env python3 """ 合规审查:文章合规检查 → LLM迭代修复 从articles表读取待审文章,进行合规评分;不合格文章由LLM修复(最多3次),通过后更新选题状态为待发布 """ import json, os, datetime, logging, sys, re from pathlib import Path from typing import Dict, List, Optional, Tuple from dataclasses import dataclass, asdict PROJECT_ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(PROJECT_ROOT)) sys.path.insert(0, str(PROJECT_ROOT / "platform" / "backend")) from scripts.compliance_checker import check_article try: from app.core.nvidia_client import call_llm HAVE_LLM = True except ImportError: HAVE_LLM = False from db_helper import get_topic_by_id, update_topic_status, get_active_llm_config, get_articles_by_topic, save_article from content_cleaner import strip_thinking, strip_ai_preface, strip_thinking_html, clean_html_content from prompt_loader import get_prompt, get_prompt_params DATA_DIR = PROJECT_ROOT / "automation" / "data" DRAFTS_DIR = DATA_DIR / "drafts" LOGS_DIR = PROJECT_ROOT / "automation" / "logs" TODAY = datetime.datetime.now().strftime("%Y-%m-%d") logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[logging.FileHandler(LOGS_DIR / f"optimizer_{TODAY}.log"), logging.StreamHandler()]) logger = logging.getLogger(__name__) DEFAULT_PLATFORM_TAGS = { "zhihu": ["科技", "职场"], "xiaohongshu": ["AI", "可持续", "生活方式"] } _cached_platform_tags = None def _load_platform_tags(): global _cached_platform_tags if _cached_platform_tags is not None: return _cached_platform_tags try: from app.database import SessionLocal from app.models import PlatformConfig db = SessionLocal() try: configs = db.query(PlatformConfig).filter(PlatformConfig.is_active == True).all() if configs: _cached_platform_tags = {} for c in configs: tags = c.to_dict().get("allowed_tags", []) if tags: _cached_platform_tags[c.platform] = tags if _cached_platform_tags: logger.info(f"从DB加载 {len(_cached_platform_tags)} 个平台的标签") return _cached_platform_tags finally: db.close() except Exception as e: logger.warning(f"从DB加载 platform_tags 失败: {e}") _cached_platform_tags = DEFAULT_PLATFORM_TAGS return _cached_platform_tags def get_platform_tags(): return _load_platform_tags() _llm_config_cache = None def get_llm_config(): global _llm_config_cache if _llm_config_cache is None: _llm_config_cache = get_active_llm_config() return _llm_config_cache @dataclass class OptimizationResult: file: str platform: str topic_id: str title: str original_issues: int fixed_issues: int final_score: int status: str def load_topic_map(): from db_helper import export_topics_to_json topics = export_topics_to_json() return {t['id']: t for t in topics} def get_articles_from_db(topic_ids: Optional[List[str]] = None, today_only: bool = False) -> List[Tuple[str, str, str]]: """从 articles 表读取 HTML 内容 Returns: [(html_content, platform, topic_id), ...] """ from db_helper import get_articles_by_topic results = [] seen_topics = set() if topic_ids: for tid in topic_ids: articles = get_articles_by_topic(tid) for a in articles: if a.get("html_content"): results.append((a["html_content"], a["platform"], a["topic_id"])) seen_topics.add(a["topic_id"]) else: from app.database import SessionLocal from app.models import Article from sqlalchemy import func db = SessionLocal() try: query = db.query(Article).filter(Article.html_content.isnot(None)) if today_only: cutoff = datetime.datetime.now() - datetime.timedelta(hours=24) query = query.filter(Article.created_at >= cutoff) all_articles = query.all() for a in all_articles: results.append((a.html_content, a.platform, a.topic_id)) finally: db.close() return results def fix_wechat_title(html: str, title: str) -> str: suffix = f" - {TODAY} - 微信公众号" max_base_len = 32 - len(suffix) title_tag = re.search(r'