Update spam autolearn behaviour

This commit is contained in:
mdecimus
2025-12-18 09:24:22 +01:00
parent 8c016b4907
commit 43efa37c6a
2 changed files with 25 additions and 23 deletions

View File

@@ -87,8 +87,8 @@ pub struct ClassifierConfig {
pub min_spam_samples: u64, pub min_spam_samples: u64,
pub auto_learn_reply_ham: bool, pub auto_learn_reply_ham: bool,
pub auto_learn_card_is_ham: bool, pub auto_learn_card_is_ham: bool,
pub auto_learn_spam_score: f32, pub auto_learn_spam_trap: bool,
pub auto_learn_ham_score: f32, pub auto_learn_spam_rbl_count: u32,
pub hold_samples_for: u64, pub hold_samples_for: u64,
pub train_frequency: Option<u64>, pub train_frequency: Option<u64>,
pub log_scale: bool, pub log_scale: bool,
@@ -489,12 +489,12 @@ impl ClassifierConfig {
auto_learn_reply_ham: config auto_learn_reply_ham: config
.property_or_default("spam-filter.trusted-reply.learn", "true") .property_or_default("spam-filter.trusted-reply.learn", "true")
.unwrap_or(true), .unwrap_or(true),
auto_learn_spam_score: config auto_learn_spam_trap: config
.property_or_default("spam-filter.classifier.auto-learn.spam-score", "8.0") .property_or_default("spam-filter.classifier.auto-learn.spam-trap", "true")
.unwrap_or(8.0), .unwrap_or(true),
auto_learn_ham_score: config auto_learn_spam_rbl_count: config
.property_or_default("spam-filter.classifier.auto-learn.ham-score", "-8.0") .property_or_default("spam-filter.classifier.auto-learn.spam-rbl-count", "2")
.unwrap_or(-8.0), .unwrap_or(2),
hold_samples_for: config hold_samples_for: config
.property_or_default::<Duration>("spam-filter.classifier.samples.hold-for", "180d") .property_or_default::<Duration>("spam-filter.classifier.samples.hold-for", "180d")
.unwrap_or(Duration::from_secs(180 * 24 * 60 * 60)) .unwrap_or(Duration::from_secs(180 * 24 * 60 * 60))

View File

@@ -56,6 +56,8 @@ impl SpamFilterAnalyzeScore for Server {
// Calculate final score // Calculate final score
let mut results = vec![]; let mut results = vec![];
let mut header_len = 60; let mut header_len = 60;
let mut is_spam_trap = false;
let mut rbl_count = 0;
for tag in &ctx.result.tags { for tag in &ctx.result.tags {
let score = match self.core.spam.lists.scores.get(tag) { let score = match self.core.spam.lists.scores.get(tag) {
@@ -68,6 +70,11 @@ impl SpamFilterAnalyzeScore for Server {
} }
None | Some(SpamFilterAction::Disabled) => 0.0, None | Some(SpamFilterAction::Disabled) => 0.0,
}; };
if tag == "SPAM_TRAP" {
is_spam_trap = true;
} else if score > 1.0 && tag.starts_with("RBL_") {
rbl_count += 1;
}
ctx.result.score += score; ctx.result.score += score;
header_len += tag.len() + 10; header_len += tag.len() + 10;
if score != 0.0 || !tag.starts_with("X_") { if score != 0.0 || !tag.starts_with("X_") {
@@ -145,11 +152,8 @@ impl SpamFilterAnalyzeScore for Server {
let _ = write!(&mut headers, "X-Spam-LLM: {category} ({explanation})\r\n",); let _ = write!(&mut headers, "X-Spam-LLM: {category} ({explanation})\r\n",);
} }
let class = if final_score >= self.core.spam.scores.spam_threshold { let is_spam = final_score >= self.core.spam.scores.spam_threshold;
"spam" let class = if is_spam { "spam" } else { "ham" };
} else {
"ham"
};
if avg_confidence != 0.0 { if avg_confidence != 0.0 {
let _ = write!( let _ = write!(
@@ -163,18 +167,16 @@ impl SpamFilterAnalyzeScore for Server {
); );
} }
// Autolearn // Autolearn SPAM
let mut train_spam = None; let mut train_spam = None;
let config = self.core.spam.classifier.as_ref().unwrap(); if is_spam
if config.auto_learn_spam_score > 0.0 && final_score >= config.auto_learn_spam_score { && self.core.spam.classifier.as_ref().is_some_and(|c| {
if !ctx.result.has_tag("PROB_SPAM_HIGH") { (c.auto_learn_spam_trap && is_spam_trap)
train_spam = Some(true); || (c.auto_learn_spam_rbl_count > 0
} && rbl_count >= c.auto_learn_spam_rbl_count)
} else if config.auto_learn_ham_score < 0.0 })
&& final_score <= config.auto_learn_ham_score
&& !ctx.result.has_tag("PROB_HAM_HIGH")
{ {
train_spam = Some(false); train_spam = Some(true);
} }
SpamFilterAction::Allow(SpamFilterScore { SpamFilterAction::Allow(SpamFilterScore {