feat: 重构项目结构并添加平台同步基础架构
- 重构项目目录结构,将功能模块移至 modules/ 目录 - 创建平台同步基础架构,包括发布器基类和 GitHub 发布器 - 新增 UI 状态管理模块 (modules/ui/state.py) 统一管理会话状态 - 更新依赖配置,添加平台同步所需依赖 (httpx, pyperclip) - 整理文档结构,将所有文档分类移至 docs/ 目录 - 添加 .cursorrules 文件定义项目开发规范 - 清理根目录重复文件,保持项目结构整洁
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
"""
|
||||
负面防护监控模块
|
||||
自动生成负面查询,验证负面提及情况,生成澄清模板,提供预警机制
|
||||
"""
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user