feat: 实现基于 AI 反馈的智能关键字优化系统

- 黑名单拦截时向评论者发送通知邮件(带 AI 复审按钮)
- 用户可申请 AI 复审,AI 重新评估评论内容
- AI 判定无误时自动恢复评论并优化关键字规则
- 自动移除不合理的黑名单关键字
- 记录所有优化操作,可在设置页查看日志
- 新增黑名单拦截通知邮件模板
- 新增反馈处理页面,显示 AI 评估结果
- 设置页新增黑名单拦截通知开关
- 设置页新增关键字优化日志查看和清除功能
- 充分利用 AI 智能,实现自我学习和优化
This commit is contained in:
2026-01-27 11:21:44 +08:00
parent 17c5f8365d
commit e990cb81de
3 changed files with 624 additions and 0 deletions

View File

@@ -284,6 +284,7 @@ require_once(get_template_directory() . '/email-templates/comment-notify.php');
require_once(get_template_directory() . '/email-templates/reply-notify.php');
require_once(get_template_directory() . '/email-templates/feedback-notify.php');
require_once(get_template_directory() . '/email-templates/spam-notify.php');
require_once(get_template_directory() . '/email-templates/blacklist-spam-notify.php');
require_once(get_template_directory() . '/email-templates/username-change-notify.php');
//检测更新
@@ -2868,6 +2869,7 @@ function post_comment_preprocessing($comment){
if (isset($keyword_check['is_blacklist']) && $keyword_check['is_blacklist']) {
$comment['comment_approved'] = 'spam';
$_POST['_argon_spam_blacklist_keywords'] = json_encode($keyword_check['keywords']);
$_POST['_argon_spam_by_blacklist'] = 'true';
} else {
// 触发关键字,需要 AI 检测
$should_check = true;
@@ -2986,6 +2988,29 @@ add_action('argon_async_comment_mail_notify', 'argon_async_comment_mail_notify_h
function post_comment_updatemetas($id){
$parentID = $_POST['comment_parent'];
$comment = get_comment($id);
// 保存黑名单关键字标记
if (isset($_POST['_argon_spam_blacklist_keywords'])) {
update_comment_meta($id, '_argon_spam_blacklist_keywords', $_POST['_argon_spam_blacklist_keywords']);
}
if (isset($_POST['_argon_spam_by_blacklist'])) {
update_comment_meta($id, '_argon_spam_by_blacklist', 'true');
// 发送黑名单拦截通知邮件(带反馈按钮)
if (get_option('argon_comment_spam_blacklist_notify', 'true') === 'true') {
argon_send_blacklist_spam_notify_email($comment);
}
}
// 保存触发的关键字
if (isset($_POST['_argon_spam_triggered_keywords'])) {
update_comment_meta($id, '_argon_spam_triggered_keywords', $_POST['_argon_spam_triggered_keywords']);
}
// 保存需要 AI 检测的标记
if (isset($_POST['_argon_needs_spam_check'])) {
update_comment_meta($id, '_argon_needs_spam_check', 'true');
}
$commentPostID = $comment -> comment_post_ID;
$commentAuthor = $comment -> comment_author;
$mailnoticeUnsubscribeKey = get_random_token();
@@ -12680,3 +12705,399 @@ function argon_clear_spam_error_log() {
}
}
add_action('wp_ajax_argon_clear_spam_error_log', 'argon_clear_spam_error_log');
// ==========================================================================
// 黑名单关键字智能优化系统
// ==========================================================================
/**
* 处理黑名单拦截反馈请求
*/
function argon_handle_spam_feedback() {
// 验证参数
if (!isset($_GET['action']) || $_GET['action'] !== 'argon_spam_feedback') {
return;
}
if (!isset($_GET['comment_id']) || !isset($_GET['token'])) {
wp_die('无效的反馈链接');
}
$comment_id = intval($_GET['comment_id']);
$token = sanitize_text_field($_GET['token']);
// 获取评论
$comment = get_comment($comment_id);
if (!$comment) {
wp_die('评论不存在');
}
// 验证 token
$saved_token = get_comment_meta($comment_id, '_argon_spam_feedback_token', true);
if ($token !== $saved_token) {
wp_die('无效的反馈链接');
}
// 检查是否已经处理过
$feedback_processed = get_comment_meta($comment_id, '_argon_spam_feedback_processed', true);
if ($feedback_processed === 'true') {
wp_die('此反馈已经处理过了');
}
// 标记为正在处理
update_comment_meta($comment_id, '_argon_spam_feedback_processing', 'true');
// 使用 AI 重新评估
$result = argon_ai_review_blacklist_spam($comment);
if ($result['success']) {
// 标记为已处理
update_comment_meta($comment_id, '_argon_spam_feedback_processed', 'true');
update_comment_meta($comment_id, '_argon_spam_feedback_result', json_encode($result));
if ($result['action'] === 'restore') {
// 显示成功页面
argon_show_feedback_result_page($comment, $result, 'success');
} else {
// 显示维持拦截页面
argon_show_feedback_result_page($comment, $result, 'rejected');
}
} else {
// 显示错误页面
argon_show_feedback_result_page($comment, $result, 'error');
}
exit;
}
add_action('template_redirect', 'argon_handle_spam_feedback');
/**
* 使用 AI 重新评估被黑名单拦截的评论
*
* @param WP_Comment $comment 评论对象
* @return array 评估结果
*/
function argon_ai_review_blacklist_spam($comment) {
// 获取触发的黑名单关键字
$blacklist_keywords = get_comment_meta($comment->comment_ID, '_argon_spam_blacklist_keywords', true);
$keywords_array = json_decode($blacklist_keywords, true);
if (empty($keywords_array)) {
return [
'success' => false,
'error' => '无法获取触发的关键字'
];
}
// 构建 AI 评估提示词
$prompt = '你是专业的内容审核专家。一条评论因触发黑名单关键字而被拦截,现在需要你重新评估。
评估要求:
1. 判断这条评论是否真的是垃圾评论(广告、违法、色情、暴力、恶意攻击等)
2. 分析触发的关键字是否合理
3. 如果评论正常,建议如何优化关键字规则
请返回 JSON 格式:
{
"is_spam": true/false,
"confidence": 0-100,
"reason": "判断理由50字以内",
"keyword_analysis": {
"keyword": "关键字",
"is_reasonable": true/false,
"suggestion": "优化建议(如果不合理)"
}[],
"action_suggestion": "restore恢复评论或 maintain维持拦截"
}';
$content = sprintf(
"触发的关键字:%s\n\n用户名%s\n评论内容%s",
implode('、', $keywords_array),
$comment->comment_author,
$comment->comment_content
);
// 调用 AI
$ai_result = argon_ai_query('blacklist_review', $prompt, $content, [
'comment_id' => $comment->comment_ID,
'keywords' => $keywords_array
]);
if ($ai_result === false) {
return [
'success' => false,
'error' => 'AI 评估失败'
];
}
// 解析 AI 结果
$review = json_decode($ai_result, true);
if (!$review || !isset($review['is_spam'])) {
return [
'success' => false,
'error' => 'AI 返回格式错误'
];
}
// 保存 AI 评估结果
update_comment_meta($comment->comment_ID, '_argon_spam_ai_review', json_encode($review));
// 根据 AI 判断执行操作
if (!$review['is_spam'] && $review['confidence'] >= 70) {
// AI 认为这不是垃圾评论,恢复评论
wp_set_comment_status($comment->comment_ID, 'approve');
// 优化关键字
argon_optimize_blacklist_keywords($keywords_array, $review['keyword_analysis'], $comment);
// 记录日志
error_log(sprintf(
'Argon: 黑名单拦截误判,已恢复评论 #%d优化关键字%s',
$comment->comment_ID,
implode('、', $keywords_array)
));
return [
'success' => true,
'action' => 'restore',
'reason' => $review['reason'],
'confidence' => $review['confidence'],
'optimizations' => $review['keyword_analysis']
];
} else {
// AI 认为确实是垃圾评论,维持拦截
return [
'success' => true,
'action' => 'maintain',
'reason' => $review['reason'],
'confidence' => $review['confidence']
];
}
}
/**
* 优化黑名单关键字
*
* @param array $triggered_keywords 触发的关键字
* @param array $keyword_analysis AI 分析结果
* @param WP_Comment $comment 评论对象
*/
function argon_optimize_blacklist_keywords($triggered_keywords, $keyword_analysis, $comment) {
// 获取当前黑名单关键字
$blacklist_text = get_option('argon_comment_spam_detection_keywords', '');
$blacklist_array = array_filter(array_map('trim', explode("\n", $blacklist_text)));
$removed_keywords = [];
$modified_keywords = [];
// 根据 AI 分析优化关键字
foreach ($keyword_analysis as $analysis) {
$keyword = $analysis['keyword'];
if (!$analysis['is_reasonable']) {
// 关键字不合理,移除
$key = array_search($keyword, $blacklist_array);
if ($key !== false) {
unset($blacklist_array[$key]);
$removed_keywords[] = $keyword;
}
} elseif (!empty($analysis['suggestion'])) {
// 有优化建议,记录但不自动修改
$modified_keywords[] = [
'original' => $keyword,
'suggestion' => $analysis['suggestion']
];
}
}
// 更新黑名单
if (!empty($removed_keywords)) {
$new_blacklist = implode("\n", array_values($blacklist_array));
update_option('argon_comment_spam_detection_keywords', $new_blacklist);
// 记录优化历史
$optimization_log = get_option('argon_spam_keyword_optimization_log', []);
$optimization_log[] = [
'time' => time(),
'comment_id' => $comment->comment_ID,
'removed_keywords' => $removed_keywords,
'modified_suggestions' => $modified_keywords,
'comment_author' => $comment->comment_author,
'comment_content' => mb_substr($comment->comment_content, 0, 100)
];
// 只保留最近 50 条记录
if (count($optimization_log) > 50) {
$optimization_log = array_slice($optimization_log, -50);
}
update_option('argon_spam_keyword_optimization_log', $optimization_log);
}
}
/**
* 显示反馈结果页面
*
* @param WP_Comment $comment 评论对象
* @param array $result 处理结果
* @param string $type 结果类型success, rejected, error
*/
function argon_show_feedback_result_page($comment, $result, $type) {
$site_name = get_bloginfo('name');
$post = get_post($comment->comment_post_ID);
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>反馈处理结果 - <?php echo esc_html($site_name); ?></title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
background: white;
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
max-width: 600px;
width: 100%;
padding: 40px;
}
.icon {
width: 80px;
height: 80px;
margin: 0 auto 20px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
}
.icon.success { background: #d4edda; color: #28a745; }
.icon.rejected { background: #fff3cd; color: #ffc107; }
.icon.error { background: #f8d7da; color: #dc3545; }
h1 {
text-align: center;
color: #333;
margin-bottom: 20px;
font-size: 24px;
}
.message {
color: #666;
line-height: 1.8;
margin-bottom: 20px;
text-align: center;
}
.detail-box {
background: #f8f9fa;
border-left: 4px solid #5e72e4;
padding: 15px;
margin: 20px 0;
border-radius: 4px;
}
.detail-box p {
color: #666;
margin: 8px 0;
line-height: 1.6;
}
.detail-box strong {
color: #333;
}
.btn {
display: inline-block;
padding: 12px 30px;
background: #5e72e4;
color: white;
text-decoration: none;
border-radius: 6px;
margin-top: 20px;
transition: background 0.3s;
}
.btn:hover {
background: #4c63d2;
}
.btn-container {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<?php if ($type === 'success'): ?>
<div class="icon success">✓</div>
<h1>评论已恢复</h1>
<p class="message">
经过 AI 重新评估,您的评论没有违规内容,已经成功恢复并发布。
</p>
<div class="detail-box">
<p><strong>AI 评估结果:</strong><?php echo esc_html($result['reason']); ?></p>
<p><strong>置信度:</strong><?php echo esc_html($result['confidence']); ?>%</p>
<?php if (!empty($result['optimizations'])): ?>
<p><strong>关键字优化:</strong>系统已自动优化相关关键字规则,避免类似误判。</p>
<?php endif; ?>
</div>
<p class="message">
感谢您的反馈,这有助于我们改进系统!
</p>
<?php elseif ($type === 'rejected'): ?>
<div class="icon rejected">!</div>
<h1>维持拦截决定</h1>
<p class="message">
经过 AI 重新评估,您的评论仍然被判定为不符合社区规范。
</p>
<div class="detail-box">
<p><strong>AI 评估结果:</strong><?php echo esc_html($result['reason']); ?></p>
<p><strong>置信度:</strong><?php echo esc_html($result['confidence']); ?>%</p>
</div>
<p class="message">
如有疑问,请联系网站管理员。
</p>
<?php else: ?>
<div class="icon error">×</div>
<h1>处理失败</h1>
<p class="message">
抱歉,处理您的反馈时出现了错误。
</p>
<div class="detail-box">
<p><strong>错误信息:</strong><?php echo esc_html($result['error']); ?></p>
</div>
<p class="message">
请稍后重试或联系网站管理员。
</p>
<?php endif; ?>
<div class="btn-container">
<a href="<?php echo esc_url(get_permalink($post->ID)); ?>" class="btn">返回文章</a>
</div>
</div>
</body>
</html>
<?php
}
/**
* AJAX: 清除关键字优化日志
*/
function argon_ajax_clear_keyword_optimization_log() {
check_ajax_referer('argon_clear_keyword_optimization_log', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => '权限不足']);
}
delete_option('argon_spam_keyword_optimization_log');
wp_send_json_success(['message' => '关键字优化日志已清除']);
}
add_action('wp_ajax_argon_clear_keyword_optimization_log', 'argon_ajax_clear_keyword_optimization_log');