fix: 三平台内容差异化 + admin敏感词管理表格化
- writer.py: _expand_section() 去除 <100字阈值,始终调用 LLM 平台专属扩写
- prompt_loader.py: 新增 section_expansion_zhihu/wechat/xiaohongshu 三个独立 prompt
- admin.html: 配置管理标签页 + 敏感词/清理规则子标签 + 敏感词表格化管理(编辑/删除)
- config_items.py: PUT /sensitive-words/{id} 支持更新 word/category
- compliance_checker.py: AI 套话从 DB 加载 + 人称规则修正
- initial_data.py: PlatformConfig 字数迁移 + 新种子
- 各前端页面: LLM 配置 rate_limit 字段 + 供应商列表排序
This commit is contained in:
@@ -100,6 +100,32 @@ DEFAULT_CONTENT_CLEAN_RULES = [
|
||||
{"rule_type": "verbosity", "pattern": r"^综上所述$", "description": "AI废话-综上所述", "sort_order": 14},
|
||||
{"rule_type": "verbosity", "pattern": r"^通过以上", "description": "AI废话-通过以上", "sort_order": 15},
|
||||
{"rule_type": "html_thinking", "pattern": r"<p[^>]*>(好的|好的,|好[的,]|我来|让我|我将|我这就)", "description": "AI思考-HTML模式", "sort_order": 16},
|
||||
{"rule_type": "ai_telltale", "pattern": r"值得注意的是", "description": "AI套话—值得注意的是", "sort_order": 20},
|
||||
{"rule_type": "ai_telltale", "pattern": r"首先.*其次.*最后", "description": "AI套话—首先其次最后", "sort_order": 21},
|
||||
{"rule_type": "ai_telltale", "pattern": r"综上所述", "description": "AI套话—综上所述", "sort_order": 22},
|
||||
{"rule_type": "ai_telltale", "pattern": r"总的来说", "description": "AI套话—总的来说", "sort_order": 23},
|
||||
{"rule_type": "ai_telltale", "pattern": r"总而言之", "description": "AI套话—总而言之", "sort_order": 24},
|
||||
{"rule_type": "ai_telltale", "pattern": r"无可否认", "description": "AI套话—无可否认", "sort_order": 25},
|
||||
{"rule_type": "ai_telltale", "pattern": r"毋庸置疑", "description": "AI套话—毋庸置疑", "sort_order": 26},
|
||||
{"rule_type": "ai_telltale", "pattern": r"众所周知", "description": "AI套话—众所周知", "sort_order": 27},
|
||||
{"rule_type": "ai_telltale", "pattern": r"不可否认", "description": "AI套话—不可否认", "sort_order": 28},
|
||||
{"rule_type": "ai_telltale", "pattern": r"从某种意义上", "description": "AI套话—从某种意义上", "sort_order": 29},
|
||||
{"rule_type": "ai_telltale", "pattern": r"从某种程度上", "description": "AI套话—从某种程度上", "sort_order": 30},
|
||||
{"rule_type": "ai_telltale", "pattern": r"在一定程度上", "description": "AI套话—在一定程度上", "sort_order": 31},
|
||||
{"rule_type": "ai_telltale", "pattern": r"换而言之", "description": "AI套话—换而言之", "sort_order": 32},
|
||||
{"rule_type": "ai_telltale", "pattern": r"换言之", "description": "AI套话—换言之", "sort_order": 33},
|
||||
{"rule_type": "ai_telltale", "pattern": r"归根结底", "description": "AI套话—归根结底", "sort_order": 34},
|
||||
{"rule_type": "ai_telltale", "pattern": r"说到底", "description": "AI套话—说到底", "sort_order": 35},
|
||||
{"rule_type": "ai_telltale", "pattern": r"这为我们提供了", "description": "AI套话—这为我们提供了", "sort_order": 36},
|
||||
{"rule_type": "ai_telltale", "pattern": r"引人深思", "description": "AI套话—引人深思", "sort_order": 37},
|
||||
{"rule_type": "ai_telltale", "pattern": r"毫无悬念", "description": "AI套话—毫无悬念", "sort_order": 38},
|
||||
{"rule_type": "ai_telltale", "pattern": r"不知大家", "description": "AI套话—不知大家", "sort_order": 39},
|
||||
{"rule_type": "ai_telltale", "pattern": r"说回到", "description": "AI套话—说回到", "sort_order": 40},
|
||||
{"rule_type": "ai_telltale", "pattern": r"如果你也", "description": "AI套话—如果你也", "sort_order": 41},
|
||||
{"rule_type": "ai_telltale", "pattern": r"我们不难发现", "description": "AI套话—我们不难发现", "sort_order": 42},
|
||||
{"rule_type": "ai_telltale", "pattern": r"我们可以看出", "description": "AI套话—我们可以看出", "sort_order": 43},
|
||||
{"rule_type": "ai_telltale", "pattern": r"从以上分析可以看出", "description": "AI套话—从以上分析可以看出", "sort_order": 44},
|
||||
{"rule_type": "ai_telltale", "pattern": r"来说说到底", "description": "AI套话—来说说到底", "sort_order": 45},
|
||||
]
|
||||
|
||||
class KeywordDomainMapResponse(BaseModel):
|
||||
@@ -193,6 +219,14 @@ def _ensure_defaults(db: Session):
|
||||
if db.query(ContentCleanRule).count() == 0:
|
||||
for item in DEFAULT_CONTENT_CLEAN_RULES:
|
||||
db.add(ContentCleanRule(**item))
|
||||
else:
|
||||
# 补入缺失的 ai_telltale 规则(不覆盖已存在的内容)
|
||||
existing_patterns = {r.pattern for r in db.query(ContentCleanRule).filter(ContentCleanRule.rule_type == 'ai_telltale').all()}
|
||||
for item in DEFAULT_CONTENT_CLEAN_RULES:
|
||||
if item['rule_type'] == 'ai_telltale' and item['pattern'] not in existing_patterns:
|
||||
db.add(ContentCleanRule(**item))
|
||||
if any(item['rule_type'] == 'ai_telltale' and item['pattern'] not in existing_patterns for item in DEFAULT_CONTENT_CLEAN_RULES):
|
||||
db.flush()
|
||||
if db.query(TrendFieldMapping).count() == 0:
|
||||
for item in DEFAULT_TREND_FIELD_MAP:
|
||||
db.add(TrendFieldMapping(**item))
|
||||
@@ -253,12 +287,12 @@ def create_sensitive_word(data: SensitiveWordCreate, db: Session = Depends(get_d
|
||||
return item
|
||||
|
||||
@router.put("/sensitive-words/{item_id}", response_model=SensitiveWordResponse)
|
||||
def update_sensitive_word(item_id: int, enabled: bool = None, db: Session = Depends(get_db), admin_user=Depends(get_current_admin)):
|
||||
def update_sensitive_word(item_id: int, body: SensitiveWordCreate, db: Session = Depends(get_db), admin_user=Depends(get_current_admin)):
|
||||
item = db.query(SensitiveWord).filter(SensitiveWord.id == item_id).first()
|
||||
if not item:
|
||||
raise HTTPException(status_code=404, detail="未找到")
|
||||
if enabled is not None:
|
||||
item.is_active = enabled
|
||||
item.word = body.word
|
||||
item.category = body.category
|
||||
db.commit()
|
||||
db.refresh(item)
|
||||
return item
|
||||
|
||||
Reference in New Issue
Block a user