diff --git a/.env.example b/.env.example index 989eb7b7c..f7a190317 100644 --- a/.env.example +++ b/.env.example @@ -105,6 +105,7 @@ MATTERS_PASSPHRASES_SECRET= MATTERS_SPAM_DETECTION_API_URL= MATTERS_SHORT_CONTENT_SPAM_DETECTION_API_URL= MATTERS_COMMENT_SPAM_DETECTION_API_URL= +MATTERS_MOMENT_SPAM_DETECTION_API_URL= MATTERS_COMMENT_SPAM_AUTO_COLLAPSE=false MATTERS_AWS_SPAM_SAMPLE_QUEUE_URL= MATTERS_SPAM_SAMPLE_HASH_SALT= diff --git a/src/common/environment.ts b/src/common/environment.ts index 9eeea3b3f..59af45655 100644 --- a/src/common/environment.ts +++ b/src/common/environment.ts @@ -197,6 +197,11 @@ export const environment = { process.env.MATTERS_SHORT_CONTENT_SPAM_DETECTION_API_URL || '', commentSpamDetectionApiUrl: process.env.MATTERS_COMMENT_SPAM_DETECTION_API_URL || '', + // Dedicated moment spam model (label-fix retrain; fixes the shared short-content + // model's ~90% false-kill on Chinese moments). Falls back to the short-content + // model when unset, so this is a zero-downtime opt-in via env. + momentSpamDetectionApiUrl: + process.env.MATTERS_MOMENT_SPAM_DETECTION_API_URL || '', // When true, a comment whose spam score reaches the system spam threshold is // auto-collapsed (folded but still expandable in-thread — "不刪除,只是不再被 // 看見"). Default off so scoring stays observe-only until ops opts in. diff --git a/src/connectors/momentService.ts b/src/connectors/momentService.ts index 7ef20aa4d..2186e7e54 100644 --- a/src/connectors/momentService.ts +++ b/src/connectors/momentService.ts @@ -461,8 +461,11 @@ export class MomentService { id: string content: string }) => { + // Prefer the dedicated moment model; fall back to the shared short-content + // model when MATTERS_MOMENT_SPAM_DETECTION_API_URL is unset (zero-downtime). const detector = new SpamDetector( - environment.shortContentSpamDetectionApiUrl + environment.momentSpamDetectionApiUrl || + environment.shortContentSpamDetectionApiUrl ) const score = await detector.detect(content)