317 lines
11 KiB
Python
317 lines
11 KiB
Python
|
|
"""
|
|||
|
|
负面防护监控模块
|
|||
|
|
自动生成负面查询,验证负面提及情况,生成澄清模板,提供预警机制
|
|||
|
|
"""
|
|||
|
|
from typing import List, Dict, Optional, Tuple
|
|||
|
|
from datetime import datetime
|
|||
|
|
import re
|
|||
|
|
|
|||
|
|
|
|||
|
|
class NegativeMonitor:
|
|||
|
|
"""负面防护监控器"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
# 负面查询模板
|
|||
|
|
self.negative_query_templates = [
|
|||
|
|
"{brand} 缺点",
|
|||
|
|
"{brand} 问题",
|
|||
|
|
"{brand} 不足",
|
|||
|
|
"{brand} 缺陷",
|
|||
|
|
"{brand} 不好",
|
|||
|
|
"{brand} 差评",
|
|||
|
|
"{brand} 投诉",
|
|||
|
|
"{brand} 负面",
|
|||
|
|
"{brand} 不推荐",
|
|||
|
|
"{brand} 避坑",
|
|||
|
|
"{brand} 坑",
|
|||
|
|
"{brand} 不值得",
|
|||
|
|
"{brand} 失败",
|
|||
|
|
"{brand} 错误",
|
|||
|
|
"{brand} 风险",
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 负面关键词模式
|
|||
|
|
self.negative_keywords = [
|
|||
|
|
"缺点", "问题", "不足", "缺陷", "不好", "差评", "投诉", "负面",
|
|||
|
|
"不推荐", "避坑", "坑", "不值得", "失败", "错误", "风险",
|
|||
|
|
"bug", "issue", "problem", "flaw", "weakness", "disadvantage"
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
def generate_negative_queries(self, brand: str, count: int = 5) -> List[str]:
|
|||
|
|
"""
|
|||
|
|
生成负面查询列表
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
brand: 品牌名称
|
|||
|
|
count: 生成数量(默认5个)
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
负面查询列表
|
|||
|
|
"""
|
|||
|
|
queries = []
|
|||
|
|
templates = self.negative_query_templates[:count] if count <= len(self.negative_query_templates) else self.negative_query_templates
|
|||
|
|
|
|||
|
|
for template in templates:
|
|||
|
|
query = template.format(brand=brand)
|
|||
|
|
queries.append(query)
|
|||
|
|
|
|||
|
|
return queries
|
|||
|
|
|
|||
|
|
def detect_negative_sentiment(self, text: str) -> Tuple[bool, float, List[str]]:
|
|||
|
|
"""
|
|||
|
|
检测文本中的负面情感
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
text: 待检测文本
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
(是否包含负面情感, 负面程度得分, 负面关键词列表)
|
|||
|
|
"""
|
|||
|
|
text_lower = text.lower()
|
|||
|
|
found_keywords = []
|
|||
|
|
negative_score = 0.0
|
|||
|
|
|
|||
|
|
# 检测负面关键词
|
|||
|
|
for keyword in self.negative_keywords:
|
|||
|
|
if keyword.lower() in text_lower:
|
|||
|
|
found_keywords.append(keyword)
|
|||
|
|
negative_score += 1.0
|
|||
|
|
|
|||
|
|
# 检测负面短语模式
|
|||
|
|
negative_phrases = [
|
|||
|
|
r'不(?:好|行|适合|推荐|值得)',
|
|||
|
|
r'有(?:问题|缺陷|不足)',
|
|||
|
|
r'存在(?:问题|缺陷|不足)',
|
|||
|
|
r'缺乏',
|
|||
|
|
r'缺少',
|
|||
|
|
r'无法',
|
|||
|
|
r'不能',
|
|||
|
|
r'失败',
|
|||
|
|
r'错误',
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
for phrase in negative_phrases:
|
|||
|
|
matches = re.findall(phrase, text_lower)
|
|||
|
|
if matches:
|
|||
|
|
negative_score += 0.5 * len(matches)
|
|||
|
|
|
|||
|
|
# 计算负面程度(0-1,1为最负面)
|
|||
|
|
# 基于负面关键词数量和文本长度
|
|||
|
|
text_length = len(text)
|
|||
|
|
if text_length > 0:
|
|||
|
|
normalized_score = min(negative_score / max(text_length / 100, 1), 1.0)
|
|||
|
|
else:
|
|||
|
|
normalized_score = 0.0
|
|||
|
|
|
|||
|
|
is_negative = negative_score > 0
|
|||
|
|
|
|||
|
|
return is_negative, normalized_score, found_keywords
|
|||
|
|
|
|||
|
|
def analyze_negative_mentions(
|
|||
|
|
self,
|
|||
|
|
brand: str,
|
|||
|
|
query: str,
|
|||
|
|
response: str,
|
|||
|
|
mention_count: int
|
|||
|
|
) -> Dict[str, any]:
|
|||
|
|
"""
|
|||
|
|
分析负面查询的提及情况
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
brand: 品牌名称
|
|||
|
|
query: 查询问题
|
|||
|
|
response: AI 响应内容
|
|||
|
|
mention_count: 品牌提及次数
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
分析结果字典
|
|||
|
|
"""
|
|||
|
|
# 检测负面情感
|
|||
|
|
is_negative, negative_score, negative_keywords = self.detect_negative_sentiment(response)
|
|||
|
|
|
|||
|
|
# 计算风险等级
|
|||
|
|
risk_level = "低"
|
|||
|
|
if mention_count == 0 and is_negative:
|
|||
|
|
risk_level = "高" # 负面查询但未提及品牌,可能是负面信息
|
|||
|
|
elif mention_count > 0 and is_negative:
|
|||
|
|
risk_level = "中" # 负面查询且提及品牌,需要关注
|
|||
|
|
elif mention_count == 0:
|
|||
|
|
risk_level = "中" # 未提及品牌,可能被忽略
|
|||
|
|
|
|||
|
|
# 生成风险说明
|
|||
|
|
risk_description = ""
|
|||
|
|
if risk_level == "高":
|
|||
|
|
risk_description = "⚠️ 高风险:负面查询中未提及品牌,可能存在负面信息或品牌被忽略"
|
|||
|
|
elif risk_level == "中":
|
|||
|
|
if is_negative:
|
|||
|
|
risk_description = "⚠️ 中风险:负面查询中提及品牌,需要关注并准备澄清内容"
|
|||
|
|
else:
|
|||
|
|
risk_description = "⚠️ 中风险:未提及品牌,可能影响品牌可见性"
|
|||
|
|
else:
|
|||
|
|
risk_description = "✅ 低风险:品牌正常提及,无负面信息"
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"query": query,
|
|||
|
|
"brand": brand,
|
|||
|
|
"mention_count": mention_count,
|
|||
|
|
"is_negative": is_negative,
|
|||
|
|
"negative_score": round(negative_score, 2),
|
|||
|
|
"negative_keywords": negative_keywords,
|
|||
|
|
"risk_level": risk_level,
|
|||
|
|
"risk_description": risk_description,
|
|||
|
|
"response_preview": response[:200] + "..." if len(response) > 200 else response
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def generate_clarification_template(
|
|||
|
|
self,
|
|||
|
|
brand: str,
|
|||
|
|
negative_query: str,
|
|||
|
|
negative_points: List[str] = None,
|
|||
|
|
advantages: str = ""
|
|||
|
|
) -> str:
|
|||
|
|
"""
|
|||
|
|
生成澄清模板(回应负面信息)
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
brand: 品牌名称
|
|||
|
|
negative_query: 负面查询
|
|||
|
|
negative_points: 负面要点列表(可选)
|
|||
|
|
advantages: 品牌优势(用于澄清)
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
澄清模板内容
|
|||
|
|
"""
|
|||
|
|
template = f"""# {brand} 关于"{negative_query}"的澄清说明
|
|||
|
|
|
|||
|
|
## 📋 问题概述
|
|||
|
|
|
|||
|
|
针对"{negative_query}"这一查询,我们提供以下澄清说明:
|
|||
|
|
|
|||
|
|
## ✅ 实际情况
|
|||
|
|
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
if negative_points:
|
|||
|
|
template += "### 关于常见误解\n\n"
|
|||
|
|
for i, point in enumerate(negative_points, 1):
|
|||
|
|
template += f"{i}. **{point}**\n"
|
|||
|
|
template += f" - 实际情况:[在此说明实际情况]\n"
|
|||
|
|
template += f" - {brand} 的解决方案:[在此说明解决方案]\n\n"
|
|||
|
|
|
|||
|
|
if advantages:
|
|||
|
|
template += f"## 🌟 {brand} 的优势\n\n"
|
|||
|
|
template += f"{advantages}\n\n"
|
|||
|
|
|
|||
|
|
template += """## 💡 建议
|
|||
|
|
|
|||
|
|
如果您对 {brand} 有任何疑问或需要帮助,我们建议:
|
|||
|
|
|
|||
|
|
1. **查看官方文档**:访问 [官方文档链接] 了解详细信息
|
|||
|
|
2. **联系客服**:通过 [联系方式] 获取专业支持
|
|||
|
|
3. **参考案例**:查看 [案例链接] 了解实际应用效果
|
|||
|
|
4. **试用体验**:通过 [试用链接] 亲自体验产品
|
|||
|
|
|
|||
|
|
## 📞 联系方式
|
|||
|
|
|
|||
|
|
如有任何问题,欢迎通过以下方式联系我们:
|
|||
|
|
- 官网:[官网链接]
|
|||
|
|
- 客服:[客服联系方式]
|
|||
|
|
- 社区:[社区链接]
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*本澄清说明基于当前信息,如有更新请以官方最新信息为准。*
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
return template.format(brand=brand)
|
|||
|
|
|
|||
|
|
def generate_negative_report(
|
|||
|
|
self,
|
|||
|
|
brand: str,
|
|||
|
|
analysis_results: List[Dict[str, any]],
|
|||
|
|
threshold: float = 0.3
|
|||
|
|
) -> Dict[str, any]:
|
|||
|
|
"""
|
|||
|
|
生成负面监控报告
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
brand: 品牌名称
|
|||
|
|
analysis_results: 分析结果列表
|
|||
|
|
threshold: 预警阈值(提及率低于此值时预警)
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
报告字典
|
|||
|
|
"""
|
|||
|
|
if not analysis_results:
|
|||
|
|
return {
|
|||
|
|
"brand": brand,
|
|||
|
|
"total_queries": 0,
|
|||
|
|
"high_risk_count": 0,
|
|||
|
|
"medium_risk_count": 0,
|
|||
|
|
"low_risk_count": 0,
|
|||
|
|
"average_mention_count": 0.0,
|
|||
|
|
"average_negative_score": 0.0,
|
|||
|
|
"alerts": [],
|
|||
|
|
"recommendations": []
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 统计风险等级
|
|||
|
|
high_risk = [r for r in analysis_results if r.get("risk_level") == "高"]
|
|||
|
|
medium_risk = [r for r in analysis_results if r.get("risk_level") == "中"]
|
|||
|
|
low_risk = [r for r in analysis_results if r.get("risk_level") == "低"]
|
|||
|
|
|
|||
|
|
# 计算平均提及次数
|
|||
|
|
avg_mention = sum(r.get("mention_count", 0) for r in analysis_results) / len(analysis_results)
|
|||
|
|
|
|||
|
|
# 计算平均负面得分
|
|||
|
|
avg_negative_score = sum(r.get("negative_score", 0) for r in analysis_results) / len(analysis_results)
|
|||
|
|
|
|||
|
|
# 生成预警
|
|||
|
|
alerts = []
|
|||
|
|
if avg_mention < threshold:
|
|||
|
|
alerts.append({
|
|||
|
|
"level": "高",
|
|||
|
|
"message": f"⚠️ 平均提及次数 ({avg_mention:.2f}) 低于预警阈值 ({threshold}),品牌可见性可能受到影响"
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
if len(high_risk) > 0:
|
|||
|
|
alerts.append({
|
|||
|
|
"level": "高",
|
|||
|
|
"message": f"⚠️ 发现 {len(high_risk)} 个高风险负面查询,建议立即处理"
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
if len(medium_risk) > 0:
|
|||
|
|
alerts.append({
|
|||
|
|
"level": "中",
|
|||
|
|
"message": f"⚠️ 发现 {len(medium_risk)} 个中风险负面查询,建议关注"
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
# 生成建议
|
|||
|
|
recommendations = []
|
|||
|
|
if len(high_risk) > 0:
|
|||
|
|
recommendations.append("立即生成澄清内容,回应高风险负面查询")
|
|||
|
|
|
|||
|
|
if avg_mention < threshold:
|
|||
|
|
recommendations.append("优化内容策略,提升品牌在负面查询中的提及率")
|
|||
|
|
|
|||
|
|
if avg_negative_score > 0.3:
|
|||
|
|
recommendations.append("加强正面内容建设,降低负面信息影响")
|
|||
|
|
|
|||
|
|
if len(high_risk) == 0 and len(medium_risk) == 0:
|
|||
|
|
recommendations.append("当前负面监控状态良好,继续保持")
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"brand": brand,
|
|||
|
|
"total_queries": len(analysis_results),
|
|||
|
|
"high_risk_count": len(high_risk),
|
|||
|
|
"medium_risk_count": len(medium_risk),
|
|||
|
|
"low_risk_count": len(low_risk),
|
|||
|
|
"average_mention_count": round(avg_mention, 2),
|
|||
|
|
"average_negative_score": round(avg_negative_score, 2),
|
|||
|
|
"high_risk_queries": [r.get("query") for r in high_risk],
|
|||
|
|
"medium_risk_queries": [r.get("query") for r in medium_risk],
|
|||
|
|
"alerts": alerts,
|
|||
|
|
"recommendations": recommendations,
|
|||
|
|
"generated_at": datetime.now().isoformat()
|
|||
|
|
}
|