|
""" |
|
ContentGuardian - AI-Powered Content Audit Agent |
|
China · Simplified Chinese · Hanyu Xinxie Style · AI-Driven Version |
|
Real AI content analysis with SVG visualization |
|
""" |
|
import gradio as gr |
|
import asyncio |
|
import aiohttp |
|
import json |
|
import os |
|
import datetime |
|
from typing import Dict, List |
|
|
|
|
|
class AIContentAnalyzer: |
|
def __init__(self): |
|
self.api_key = os.getenv("SILICONFLOW_API_KEY", "sk-your-api-key-here") |
|
self.base_url = "https://api.siliconflow.cn/v1/chat/completions" |
|
self.model = "Qwen/Qwen2.5-7B-Instruct" |
|
|
|
async def analyze_content(self, text: str, keywords: List[str] = None) -> Dict: |
|
"""AI-powered content analysis""" |
|
keywords_str = ", ".join(keywords) if keywords else "无" |
|
|
|
prompt = f""" |
|
你是专业的内容审核专家,请对以下文本进行全面审核分析: |
|
|
|
文本内容:{text} |
|
关键词:{keywords_str} |
|
|
|
请从以下维度进行分析: |
|
1. 错别字检测:识别文本中的拼写错误和用词不当 |
|
2. 违规内容:检测不当言论、违法违规表述 |
|
3. 虚假内容:识别可能的虚假信息和夸大宣传 |
|
4. 不当广告用语:检测违反广告法的用词 |
|
5. 关键词分析:分析指定关键词的使用情况 |
|
|
|
请以JSON格式返回分析结果: |
|
{{ |
|
"typos": [ |
|
{{"original": "错误词", "correct": "正确词", "reason": "错误原因"}} |
|
], |
|
"violations": [ |
|
{{"content": "违规内容", "type": "违规类型", "suggestion": "修改建议"}} |
|
], |
|
"fake_content": [ |
|
{{"content": "虚假内容", "type": "虚假类型", "suggestion": "修改建议"}} |
|
], |
|
"inappropriate_ads": [ |
|
{{"word": "不当用词", "reason": "违规原因", "suggestion": "替代建议"}} |
|
], |
|
"keywords_analysis": [ |
|
{{"keyword": "关键词", "frequency": 次数, "context": "使用语境", "assessment": "使用评价"}} |
|
], |
|
"overall_assessment": {{ |
|
"risk_level": "低/中/高", |
|
"total_issues": 问题总数, |
|
"main_concerns": ["主要问题1", "主要问题2"], |
|
"recommendations": ["建议1", "建议2"] |
|
}} |
|
}} |
|
""" |
|
|
|
try: |
|
headers = { |
|
"Authorization": f"Bearer {self.api_key}", |
|
"Content-Type": "application/json" |
|
} |
|
|
|
data = { |
|
"model": self.model, |
|
"messages": [ |
|
{"role": "system", "content": "你是专业的内容审核专家,擅长识别各类内容问题并提供专业建议。"}, |
|
{"role": "user", "content": prompt} |
|
], |
|
"temperature": 0.1, |
|
"max_tokens": 2000 |
|
} |
|
|
|
async with aiohttp.ClientSession() as session: |
|
async with session.post(self.base_url, headers=headers, json=data) as response: |
|
if response.status == 200: |
|
result = await response.json() |
|
ai_response = result["choices"][0]["message"]["content"] |
|
|
|
|
|
try: |
|
|
|
if "```json" in ai_response: |
|
ai_response = ai_response.split("```json")[1].split("```")[0] |
|
elif "```" in ai_response: |
|
ai_response = ai_response.split("```")[1].split("```")[0] |
|
|
|
analysis_result = json.loads(ai_response.strip()) |
|
return analysis_result |
|
except json.JSONDecodeError: |
|
|
|
return self._create_fallback_analysis(text, keywords) |
|
else: |
|
return self._create_fallback_analysis(text, keywords) |
|
|
|
except Exception as e: |
|
print(f"AI analysis error: {e}") |
|
return self._create_fallback_analysis(text, keywords) |
|
|
|
def _create_fallback_analysis(self, text: str, keywords: List[str] = None) -> Dict: |
|
"""备用分析方法""" |
|
|
|
inappropriate_words = ["绝对", "完全", "100%", "第一", "最好", "立即", "马上"] |
|
found_inappropriate = [word for word in inappropriate_words if word in text] |
|
|
|
return { |
|
"typos": [], |
|
"violations": [], |
|
"fake_content": [], |
|
"inappropriate_ads": [{"word": word, "reason": "可能违反广告法", "suggestion": "使用相对性表述"} for word in found_inappropriate], |
|
"keywords_analysis": [{"keyword": kw, "frequency": text.count(kw), "context": "文本中", "assessment": "正常使用"} for kw in (keywords or []) if kw in text], |
|
"overall_assessment": { |
|
"risk_level": "中" if found_inappropriate else "低", |
|
"total_issues": len(found_inappropriate), |
|
"main_concerns": ["广告用语不当"] if found_inappropriate else [], |
|
"recommendations": ["修改绝对化表述"] if found_inappropriate else ["内容表述规范"] |
|
} |
|
} |
|
|
|
|
|
ai_analyzer = AIContentAnalyzer() |
|
|
|
def generate_hanyu_xinxie_cards(analysis_result: Dict, original_text: str) -> str: |
|
"""生成汉语新解风格的SVG卡片""" |
|
overall = analysis_result.get("overall_assessment", {}) |
|
total_issues = overall.get("total_issues", 0) |
|
risk_level = overall.get("risk_level", "低") |
|
|
|
|
|
colors = { |
|
"primary": "#B6B5A7", |
|
"secondary": "#9A8F8F", |
|
"accent": "#C5B4A0", |
|
"background": "#F2EDE9", |
|
"text": "#5B5B5B", |
|
"light_text": "#8C8C8C", |
|
"divider": "#D1CBC3" |
|
} |
|
|
|
|
|
if risk_level == "高": |
|
colors["secondary"] = "#B85450" |
|
colors["accent"] = "#D4776B" |
|
elif risk_level == "中": |
|
colors["secondary"] = "#C4965A" |
|
colors["accent"] = "#D4A574" |
|
|
|
|
|
main_card = f""" |
|
<div style=" |
|
display: flex; |
|
justify-content: center; |
|
padding: 20px; |
|
background: linear-gradient(135deg, #E8E3DE 0%, #F2EDE9 100%); |
|
border-radius: 15px; |
|
font-family: 'Microsoft YaHei', 'Noto Sans SC', sans-serif; |
|
margin-bottom: 20px; |
|
"> |
|
<div style=" |
|
width: 350px; |
|
background-color: {colors['background']}; |
|
border-radius: 20px; |
|
box-shadow: 0 20px 40px rgba(0,0,0,0.1); |
|
overflow: hidden; |
|
position: relative; |
|
"> |
|
<!-- 标题区域 --> |
|
<div style=" |
|
background-color: {colors['secondary']}; |
|
color: {colors['background']}; |
|
padding: 20px; |
|
text-align: left; |
|
"> |
|
<h1 style="font-size: 20px; margin: 0; font-weight: 700;">🛡️ AI内容审核报告</h1> |
|
<p style="font-size: 12px; margin: 5px 0 0 0; opacity: 0.9;">中国·简体中文·汉语新解风格</p> |
|
</div> |
|
|
|
<!-- 内容区域 --> |
|
<div style="padding: 25px 20px;"> |
|
<!-- 主要统计 --> |
|
<div style="text-align: left; margin-bottom: 20px;"> |
|
<div style=" |
|
font-size: 36px; |
|
color: {colors['text']}; |
|
margin-bottom: 8px; |
|
font-weight: bold; |
|
position: relative; |
|
"> |
|
{total_issues} 处问题 |
|
<div style=" |
|
position: absolute; |
|
left: 0; |
|
bottom: -4px; |
|
width: 60px; |
|
height: 3px; |
|
background-color: {colors['accent']}; |
|
"></div> |
|
</div> |
|
<div style=" |
|
font-size: 16px; |
|
color: {colors['light_text']}; |
|
margin: 12px 0; |
|
">风险等级: {risk_level}</div> |
|
</div> |
|
|
|
<!-- 分隔线 --> |
|
<div style=" |
|
width: 100%; |
|
height: 1px; |
|
background-color: {colors['divider']}; |
|
margin: 20px 0; |
|
"></div> |
|
|
|
<!-- AI分析结果 --> |
|
<div style=" |
|
font-size: 14px; |
|
line-height: 1.6; |
|
text-align: left; |
|
"> |
|
<div style=" |
|
padding-left: 15px; |
|
border-left: 3px solid {colors['accent']}; |
|
">""" |
|
|
|
|
|
if analysis_result.get("typos"): |
|
main_card += f'<p style="margin: 8px 0; color: {colors["text"]};">• 错别字问题: {len(analysis_result["typos"])} 处</p>' |
|
|
|
if analysis_result.get("violations"): |
|
main_card += f'<p style="margin: 8px 0; color: {colors["text"]};">• 违规内容: {len(analysis_result["violations"])} 处</p>' |
|
|
|
if analysis_result.get("fake_content"): |
|
main_card += f'<p style="margin: 8px 0; color: {colors["text"]};">• 虚假内容: {len(analysis_result["fake_content"])} 处</p>' |
|
|
|
if analysis_result.get("inappropriate_ads"): |
|
main_card += f'<p style="margin: 8px 0; color: {colors["text"]};">• 不当广告用语: {len(analysis_result["inappropriate_ads"])} 处</p>' |
|
|
|
if analysis_result.get("keywords_analysis"): |
|
main_card += f'<p style="margin: 8px 0; color: {colors["text"]};">• 关键词分析: {len(analysis_result["keywords_analysis"])} 个</p>' |
|
|
|
if total_issues == 0: |
|
main_card += f'<p style="margin: 8px 0; color: {colors["light_text"]};">✅ 未发现明显问题</p>' |
|
|
|
main_card += f""" |
|
</div> |
|
</div> |
|
|
|
<!-- AI建议 --> |
|
<div style=" |
|
margin-top: 20px; |
|
padding: 15px; |
|
background-color: rgba(255,255,255,0.5); |
|
border-radius: 10px; |
|
border-left: 4px solid {colors['accent']}; |
|
"> |
|
<h4 style="margin: 0 0 10px 0; color: {colors['text']}; font-size: 14px;">🤖 AI建议</h4>""" |
|
|
|
recommendations = overall.get("recommendations", ["内容表述规范"]) |
|
for rec in recommendations[:2]: |
|
main_card += f'<p style="margin: 5px 0; color: {colors["light_text"]}; font-size: 13px;">• {rec}</p>' |
|
|
|
main_card += f""" |
|
</div> |
|
|
|
<!-- 中式印章风格装饰 --> |
|
<div style=" |
|
text-align: center; |
|
margin-top: 25px; |
|
padding: 10px; |
|
border: 2px solid {colors['accent']}; |
|
border-radius: 50%; |
|
width: 70px; |
|
height: 70px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
"> |
|
<span style=" |
|
font-size: 18px; |
|
color: {colors['secondary']}; |
|
font-weight: bold; |
|
">AI审核</span> |
|
</div> |
|
</div> |
|
|
|
<!-- 背景装饰文字 --> |
|
<div style=" |
|
position: absolute; |
|
font-size: 120px; |
|
color: rgba(182, 181, 167, 0.05); |
|
top: 50%; |
|
left: 50%; |
|
transform: translate(-50%, -50%); |
|
font-weight: bold; |
|
pointer-events: none; |
|
z-index: 0; |
|
">AI</div> |
|
</div> |
|
</div> |
|
""" |
|
|
|
return main_card |
|
|
|
def generate_error_card(error_msg: str) -> str: |
|
"""生成错误信息卡片""" |
|
return f""" |
|
<div style=" |
|
display: flex; |
|
justify-content: center; |
|
padding: 20px; |
|
background: linear-gradient(135deg, #E8E3DE 0%, #F2EDE9 100%); |
|
border-radius: 15px; |
|
font-family: 'Microsoft YaHei', sans-serif; |
|
"> |
|
<div style=" |
|
width: 350px; |
|
background-color: #F2EDE9; |
|
border-radius: 20px; |
|
box-shadow: 0 20px 40px rgba(0,0,0,0.1); |
|
padding: 30px; |
|
text-align: center; |
|
"> |
|
<h2 style="color: #B85450; margin-bottom: 15px;">⚠️ 分析出错</h2> |
|
<p style="color: #5B5B5B; margin-bottom: 20px;">AI分析过程中遇到问题:</p> |
|
<div style=" |
|
background-color: rgba(184, 84, 80, 0.1); |
|
padding: 15px; |
|
border-radius: 10px; |
|
border-left: 4px solid #B85450; |
|
text-align: left; |
|
"> |
|
<code style="color: #B85450; font-size: 12px;">{error_msg}</code> |
|
</div> |
|
<p style="color: #8C8C8C; margin-top: 15px; font-size: 14px;">请稍后重试或检查网络连接</p> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def comprehensive_text_audit(text, keywords=""): |
|
""" |
|
AI-powered comprehensive text audit with SVG visualization |
|
""" |
|
if not text.strip(): |
|
return "❌ Please enter text content" |
|
|
|
|
|
keyword_list = [k.strip() for k in keywords.split(",") if k.strip()] if keywords else [] |
|
|
|
try: |
|
|
|
loop = asyncio.new_event_loop() |
|
asyncio.set_event_loop(loop) |
|
|
|
try: |
|
|
|
analysis_result = loop.run_until_complete( |
|
ai_analyzer.analyze_content(text, keyword_list) |
|
) |
|
finally: |
|
loop.close() |
|
|
|
|
|
svg_cards = generate_hanyu_xinxie_cards(analysis_result, text) |
|
|
|
return svg_cards |
|
|
|
except Exception as e: |
|
print(f"Analysis error: {e}") |
|
|
|
return generate_error_card(str(e)) |
|
|
|
|
|
demo = gr.Interface( |
|
fn=comprehensive_text_audit, |
|
inputs=[ |
|
gr.Textbox( |
|
label="Text to Audit", |
|
placeholder="Please enter the text content to be audited...", |
|
lines=8 |
|
), |
|
gr.Textbox( |
|
label="Keywords (Optional)", |
|
placeholder="Please enter keywords to mark, separated by commas", |
|
lines=2 |
|
) |
|
], |
|
outputs=gr.HTML( |
|
label="AI Audit Report" |
|
), |
|
title="🛡️ ContentGuardian - AI Content Audit Agent", |
|
description=""" |
|
**China · Simplified Chinese · Hanyu Xinxie Style · AI-Driven Version** |
|
|
|
This system uses real AI analysis to detect content issues and generates beautiful Hanyu Xinxie style cards. |
|
Powered by advanced language models for intelligent content understanding. |
|
|
|
**Key Features:** |
|
- 🤖 AI-Powered Content Analysis |
|
- 🔍 Intelligent Error Detection |
|
- 📊 Beautiful SVG Card Visualization |
|
- 🎨 Hanyu Xinxie Aesthetic Style |
|
""", |
|
examples=[ |
|
["This product is absolutely effective, completely side-effect free, the first brand! Buy immediately, instant results!", "product,effect"], |
|
["Our product quality is very good, trustworthy, welcome to purchase.", "product,quality"], |
|
["这款产品效果绝对好,完全无副作用,第一品牌!立即购买,马上见效!", "产品,效果"], |
|
["Buy now, instant effect, 100% effective, absolutely satisfying!", "buy,effect"] |
|
], |
|
theme=gr.themes.Soft(), |
|
allow_flagging="never" |
|
) |
|
|
|
if __name__ == "__main__": |
|
demo.launch() |
|
|