feat(meituan): 政治类文章拦截 + 写'无可奉告' + Angel 并发 3→1
- llm_settings 加 meituan_blocked_topics / blocked_keywords / no_comment_text - alembic 0006 迁移,默认 topics=[时政/国际/军事/政治/战争/冲突/制裁/选举], 默认文案='无可奉告' - enrichment._is_meituan_blocked 预检:category 命中 topic 或 关键词 → 直接写'无可奉告',不调美团 API - 命中后 commentary_meituan_model='policy-block' 标识非真实生成 - enrichment_loop Semaphore(3)→(1),Agnes 免费 plan 不再 429 - 前端 AdminLlmSettings 美团卡片加 3 字段 UI(主题/关键词/固定文案)
This commit is contained in:
@@ -320,10 +320,55 @@ async def _enrich_commentary_angel(
|
||||
article.commentary_engine = ",".join(sorted(engines))
|
||||
|
||||
|
||||
# === 美团"无可奉告"预检 ===
|
||||
# 美团(LongCat)对战争/政治/敏感新闻会触发 security_audit_fail 400,
|
||||
# 死循环重试不解决问题。命中"政治类"文章直接写固定文案,不调美团 API。
|
||||
# 命中规则:
|
||||
# 1) article.category(LLM 已分类,逗号分隔)中含 meituan_blocked_topics 任一项
|
||||
# 2) 标题/正文命中 meituan_blocked_keywords 任一关键词(宽松包含)
|
||||
def _is_meituan_blocked(article: Article, setting: LlmSetting) -> bool:
|
||||
"""返回 True 表示这篇应该被"无可奉告"处理(不调美团 API)。"""
|
||||
topics = set(setting.meituan_blocked_topics or [])
|
||||
keywords = [k for k in (setting.meituan_blocked_keywords or []) if k]
|
||||
if topics:
|
||||
cats = {c.strip() for c in (article.category or "").split(",") if c.strip()}
|
||||
if cats & topics:
|
||||
return True
|
||||
if keywords:
|
||||
text = " ".join(
|
||||
(article.title_zh or ""), (article.title or ""),
|
||||
(article.body_zh_text or "")[:1500],
|
||||
)
|
||||
for kw in keywords:
|
||||
if kw and kw in text:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
async def _enrich_commentary_meituan(
|
||||
article: Article, setting: LlmSetting, client: LlmClient
|
||||
) -> None:
|
||||
"""美团评论 — 写入 commentary_meituan 等新字段。"""
|
||||
"""美团评论 — 写入 commentary_meituan 等新字段。
|
||||
|
||||
预检:命中"政治类"主题的文章直接写"无可奉告"固定文案,
|
||||
不调美团 API(避免 LongCat security_audit_fail 400 循环)。
|
||||
"""
|
||||
# === 预检:政治类文章写"无可奉告" ===
|
||||
if _is_meituan_blocked(article, setting):
|
||||
no_text = setting.meituan_no_comment_text or "无可奉告"
|
||||
article.commentary_meituan = no_text
|
||||
article.commentary_meituan_status = "ok"
|
||||
article.commentary_meituan_error = None
|
||||
article.commentary_meituan_model = "policy-block" # 标识非真实生成
|
||||
engines = set(filter(None, (article.commentary_engine or "").split(",")))
|
||||
engines.add(PROVIDER_MEITUAN)
|
||||
article.commentary_engine = ",".join(sorted(engines))
|
||||
logger.info(
|
||||
"commentary_meituan policy-block for article %s (category=%s)",
|
||||
article.id, article.category,
|
||||
)
|
||||
return
|
||||
|
||||
# 优先用 setting.meituan_commentary_prompt,留空用默认
|
||||
template = setting.meituan_commentary_prompt or _default_commentary_prompt()
|
||||
prompt = _safe_format(
|
||||
@@ -548,7 +593,10 @@ async def enrichment_loop() -> None:
|
||||
|
||||
# 并发 enrich 多篇(LlmClient 内部 interval_sec 已经做了限速,这里只并发不限并发上限)
|
||||
# 但为了不让 LLM API 同时打太多,加一层并发上限
|
||||
sem = asyncio.Semaphore(3)
|
||||
# 2026-06-12 调:3→1。Agnes 免费 plan 在并发 3 时会偶发 429
|
||||
# (每篇 enrich 内部 Angel 跑 4 chat + 1 image,3 路并发 = 12+3 短时突发),
|
||||
# 降到 1 路串行,稳定不超限,且不浪费 429 重试窗口。
|
||||
sem = asyncio.Semaphore(1)
|
||||
async def _run_one(aid: int) -> None:
|
||||
async with sem:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user