配置全面迁移数据库:PromptConfig、TaskConfig动态调度、敏感词/清洗规则/趋势映射/平台标签/痛点模板全部可编辑
- 新增 PromptConfig 模型 + API,支持提示词在线编辑(16条默认) - 调度器动态读取 TaskConfig.schedule,admin 可调执行时间 - 新增 KeywordDomainMap、SensitiveWord、ContentCleanRule、TrendFieldMapping 表 - DOMAINS、TREND_DOMAIN_MAP、PLATFORM_TAGS、china_pains、RSS关键词、priority_weights 全部迁移到 DB - tasks.html 重构:卡片网格+配置/产出/历史/提示词四个Tab,折叠显示 - 清理冗余代码:DEFAULT_PROMPTS死代码、collector.py unreachable代码、compliance_checker bug - strip_thinking_html 改用 DB 规则优先
This commit is contained in:
@@ -20,6 +20,8 @@ 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"
|
||||
@@ -30,11 +32,42 @@ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(
|
||||
handlers=[logging.FileHandler(LOGS_DIR / f"optimizer_{TODAY}.log"), logging.StreamHandler()])
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
PLATFORM_TAGS = {
|
||||
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():
|
||||
@@ -110,13 +143,14 @@ def fix_wechat_title(html: str, title: str) -> str:
|
||||
return html
|
||||
|
||||
def fix_tags(html: str, platform: str) -> str:
|
||||
tags_map = get_platform_tags()
|
||||
if platform == "zhihu":
|
||||
tags_str = " ".join(f"#{t}" for t in PLATFORM_TAGS["zhihu"])
|
||||
tags_str = " ".join(f"#{t}" for t in tags_map.get("zhihu", []))
|
||||
if '<div class="tags">' in html:
|
||||
old = html.split('<div class="tags">')[1].split('</div>')[0]
|
||||
html = html.replace(f'<div class="tags">{old}</div>', f'<div class="tags">{tags_str}</div>')
|
||||
elif platform == "xiaohongshu":
|
||||
tags_str = " ".join(f"#{t}" for t in PLATFORM_TAGS["xiaohongshu"])
|
||||
tags_str = " ".join(f"#{t}" for t in tags_map.get("xiaohongshu", []))
|
||||
if '<div class="hashtags">' in html:
|
||||
old = html.split('<div class="hashtags">')[1].split('</div>')[0]
|
||||
html = html.replace(f'<div class="hashtags">{old}</div>', f'<div class="hashtags">{tags_str}</div>')
|
||||
@@ -140,32 +174,13 @@ def polish_with_llm(html: str, platform: str, remaining_issues: Optional[List[Di
|
||||
f"- [{i['type']}] {i.get('category','')}: {i.get('detail','')} (建议: {i.get('suggestion','')})"
|
||||
for i in remaining_issues
|
||||
)
|
||||
polish_prompt = f"""你是一个专业的内容合规优化助手。以下文章存在合规问题,请逐一修复并输出完整HTML。
|
||||
|
||||
需修复的问题:
|
||||
{issues_desc}
|
||||
|
||||
原文:
|
||||
{html}
|
||||
|
||||
要求:
|
||||
- 只修复上述问题,不改变文章结构和核心内容
|
||||
- 保持<h2>, <h3>, <p>等标签结构不变
|
||||
- 修复后内容依然保持可读性和自然语感(不要因为合规变成生硬的表达)
|
||||
- 替换敏感词时选择意思相近的替代词,不删节重要信息"""
|
||||
prompt = get_prompt("compliance_fix", issues_desc=issues_desc, html=html)
|
||||
else:
|
||||
polish_prompt = f"""你是一个专业的内容润色助手。请润色以下文章,提升表达的自然感和可读性。
|
||||
|
||||
原文:
|
||||
{html}
|
||||
|
||||
要求:
|
||||
- 保持原文事实、数据、章节结构不变
|
||||
- 输出相同的HTML格式(保留<h2>, <h3>, <p>标签)
|
||||
- 提升表达的自然感,让它更像是人写的
|
||||
- 避免AI常见表达模式(「首先其次最后」「总的来说」「值得注意的是」等)
|
||||
- 短句化,读起来更流畅"""
|
||||
polished = call_llm(polish_prompt, model=model, temperature=temperature, max_tokens=max_tokens, system_prompt=system_prompt)
|
||||
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[:100] for kw in ['保留', '建议', '可以', '应该', '推荐']):
|
||||
@@ -178,6 +193,7 @@ def polish_with_llm(html: str, platform: str, remaining_issues: Optional[List[Di
|
||||
|
||||
def optimize_article(html: str, platform: str, topic_data: Dict, remaining_issues: Optional[List[Dict]] = None) -> Tuple[str, List[str]]:
|
||||
logs = []
|
||||
html = strip_thinking_html(html)
|
||||
if platform == "wechat":
|
||||
html = fix_wechat_title(html, topic_data.get("title", ""))
|
||||
logs.append("标题截断(含后缀)")
|
||||
@@ -185,7 +201,8 @@ def optimize_article(html: str, platform: str, topic_data: Dict, remaining_issue
|
||||
before = html
|
||||
html = fix_tags(html, platform)
|
||||
if html != before:
|
||||
logs.append(f"标签标准化为{PLATFORM_TAGS[platform]}")
|
||||
tags_map = get_platform_tags()
|
||||
logs.append(f"标签标准化为{tags_map.get(platform, [])}")
|
||||
polished, pol_log = polish_with_llm(html, platform, remaining_issues)
|
||||
if pol_log:
|
||||
html = polished
|
||||
|
||||
Reference in New Issue
Block a user