这一页回答什么
abuse-enforcement-service/(下称处置服务)读取什么输入,按什么规则决定打标签、发挑战还是封禁。abuse-ledger-service/的“申诉保护期”是什么,怎样阻止重复处置。safety-label-source/怎样把帖子标签提供给可见性过滤。safety-label-user-agg/怎样根据一个账号最近帖子的标签,给该账号打标签。takedowns/怎样合并帖子级和账号级的下架原因。
打标签规则 由事件驱动;本页的系统则基于模型分数或帖子标签的累计。
核心结论
- 处置服务按规则表从上到下匹配,取第一条为真的规则(
abuse-enforcement-service/service-lib/src/rules.rs:311-332)。用户与帖子各有一张规则表,规则写在 YAML 中。文件注释写明“从 GrowthBook 动态配置镜像,最后同步 2026-10-20”(abuse-enforcement-service/service-lib/rules/enforcement_user.yaml:1)。 - 动作只有六种: 封禁账号(临时或永久)、加账号标签、加帖子标签、Arkose 挑战、验证码、活体检测(
abuse-enforcement-service/service-lib/src/decision.rs:1-24)。 - 最常见的处置是加
SpamHighRecall账号标签,有效 7 天或 30 天。 带这个标签的账号,其帖子在站外推荐中被丢弃(见 可见性过滤)。 - 用户表的最后一条是兜底封禁:
act_suspend,条件为true,动作是临时封禁,策略为PlatformManipulation(enforcement_user.yaml:184-189)。测试代码强制它必须在最后(rules.rs:1227-1228)。 - 处置服务先跳过粉丝数高和可信度分高的账号。 开源 YAML 中的阈值是占位值 12.34(
enforcement_user.yaml:19-33)。代码中另有一道写死的粉丝上限检查(abuse-enforcement-service/service-lib/src/safety_checks.rs:158-175)。 - 申诉推翻过的处置不会被自动重做。 处置服务在封禁或加特定标签前,向 abuse-ledger-service 查询有效保护期;开源默认关闭这道检查(
abuse-enforcement-service/service-lib/src/overturn_hold.rs:150-162)。 - 帖子标签累计到一定数量,账号也会被打标签。 默认规则:最近 5 条帖子中至少 3 条带
NSFW_HIGH_PRECISION(60 天内)时,账号获得NSFW_HIGH_PRECISION标签,有效 7 天(safety-label-user-agg/postToUserLabelRules.strato:395-426)。
abuse-enforcement-service:读取分数,执行处置
输入
- 来自 Kafka 的评分事件
ScoreResult(xai_abuse_proto::enforcement,abuse-enforcement-service/service-lib/src/facts.rs:5、:145-170)。规则读取其中的score.labels。BDSM 也定义了同名消息(bdsm/proto/abuse_inference.proto:80),二者是否为同一定义,源码未说明。BDSM 结果汇写出的enforcement_cusp_*、enforcement_threshold_reached与处置规则引用的标签名一致。 - 账号与帖子事实:是否存在、是否已封禁/停用、现有标签、粉丝数、可信度分(
cred.score、cred.is_high)、是否在允许名单中(facts.rs:215、abuse-enforcement-service/service-lib/src/allowlist.rs:10)。 topic_labels配置决定哪些 Kafka 主题、带哪些标签的事件进入处置(abuse-enforcement-service/service-lib/src/config.rs:50-55)。该配置文件不在仓库中。
用户规则表(开源默认值)
| 顺序 | 规则 id | 条件 | 结果 |
|---|---|---|---|
| 1 | user_in_allowlist |
在允许名单 | 跳过 |
| 2 | user_not_found |
账号不存在 | 跳过 |
| 3 | high_follower_count |
粉丝数 ≥ 12.34(占位值) | 跳过 |
| 4 | pagerank_skipped |
cred.is_high 或可信度分 ≥ 12.34(占位值) |
跳过 |
| 5 | anchor_campaign_suspend / _cse |
评分标签含对应值 | 临时封禁(平台操纵)/ 永久封禁(CSE) |
| 6 | anchor_campaign_user |
anchor_campaign_user |
加 SpamHighRecall(无 TTL) |
| 7 | panda_reports_embedding_v10_rough_spam、act_bb1_*_suspend |
对应标签 | 临时封禁 |
| 8 | act_bb1_*_bounce |
对应标签 | SpamHighRecall 30 天 + 活体检测 |
| 9 | act_liveness_check_and_spam_high_recall_7d / act_spam_high_recall_7d |
对应标签 | SpamHighRecall 7 天(前者加活体检测) |
| 10 | act_add_llm_slop_label |
llm_slop_user,且账号尚无 SpamHighRecall |
SpamHighRecall 7 天 |
| 11 | act_add_majority_poster_label |
SpamEmbeddingMajorityPoster,且尚无该标签 |
SpamHighRecall 30 天 |
| 12 | act_spam_liveness_check |
spam_liveness_check_required |
活体检测 |
| 13 | already_suspended / already_deactivated |
已封禁 / 已停用 | 跳过 |
| 14 | act_cusp_arkose / _captcha / _liveness |
BDSM 临界挑战标签,且没有 enforcement_threshold_reached |
对应挑战 |
| 15 | act_impersonation_scam_suspend |
impersonation_scam_classifier_v1_suspend |
临时封禁 |
| 16 | act_suspend |
true |
临时封禁 |
依据:abuse-enforcement-service/service-lib/rules/enforcement_user.yaml:5-189。TTL 换算:604800000 ms = 7 天,2592000000 ms = 30 天。
BDSM 的 enforcement_threshold_reached 没有专门规则。带这个标签的事件跳过第 14 行,落到第 16 行,即临时封禁(依规则表推断)。
帖子规则表(开源默认值)
| 规则 id | 条件 | 结果 |
|---|---|---|
post_in_allowlist / user_in_allowlist / user_not_found |
名单或不存在 | 跳过 |
high_follower_count / pagerank_skipped |
作者粉丝或可信度高(占位值),且事件未要求跳过此检查 | 跳过 |
act_add_llm_slop_post_label |
llm_slop_post |
帖子标签 RiskyHighVizReply,30 天 |
act_add_gibberish_post_label |
gibberish_post |
帖子标签 SpamHighRecall,30 天 |
act_add_fast_reply_spam_post_label |
fast_reply_spam_post |
帖子标签 SpamHighRecall,30 天 |
anchor_campaign_post / act_add_spam_embedding_ptos_distilled_label |
对应标签 | 帖子标签 SpamHighRecall(无 TTL) |
act_suspend_ncmec_reported_content_author |
cse_reports_embedding_v2 |
作者永久封禁(CSE) |
post_no_actionable_label |
true |
跳过 |
依据:abuse-enforcement-service/service-lib/rules/enforcement_post.yaml:3-82。帖子表的兜底动作是跳过,不是封禁。
带 SpamHighRecall 标签的帖子在站外推荐中被丢弃(visibility-filtering/rules/tweet_rules.rs:944-949)。RiskyHighVizReply 只在通知级别中使用(visibility-filtering/rules/levels.rs:217)。
处置前的检查
flowchart TD
E["评分事件 ScoreResult"] --> R["规则表: 第一条为真"]
R -- "skip" --> X["不处置"]
R -- "act" --> C["粉丝上限检查"]
C -- "超上限" --> X
C -- "未超" --> H{"需要查申诉保护期?"}
H -- "否" --> A["执行动作"]
H -- "是" --> L["abuse-ledger-service 查询"]
L -- "有有效保护期" --> X
L -- "无" --> A
- 粉丝上限:规则
very_high_follower_count,条件为cred.follower_count >= 12345.67。超过上限时,处置服务把所有决定改成跳过,允许名单和账号不存在两种决定除外(safety_checks.rs:158-175、rules.rs:291-309)。该数值形似占位值,生产值未公开(推测)。 - 申诉保护期见下一节。
abuse-ledger-service:申诉保护期
- 该服务只读一张表
ledger.enforcement_holds。查询条件:用户 id 匹配、未清除、未过期,且动作是封禁,或动作是加标签且标签在请求列表中(abuse-ledger-service/src/sql.rs:3-7)。 - 返回的保护记录包含
action_kind、label、head(模型头)、expires_at、case_group_id、reason(abuse-ledger-service/src/repo.rs:15-25)。 - 处置服务按以下方式调用它(
abuse-enforcement-service/service-lib/src/overturn_hold.rs):- 接口为
/v1/holds/lookup,默认超时 200 ms,正结果缓存 60 秒(:24-33)。 - 模式有
off/shadow/enforce三种,开源默认为off。默认只检查封禁,不检查标签(:150-162、:396-406)。 enforce模式下命中保护期时,处置服务跳过动作,并把状态记为hold_overturned(:1709-1710)。- 永久封禁只受指定案件组的保护期或人工(
manual)保护期约束(:408-415)。
- 接口为
- 保护期时长:上游 README 写明“按申诉队列设定的固定时长”(上游 README 组件表
abuse-ledger-service/一行)。写入保护期的代码不在仓库中。
safety-label-source:标签读取层
VF 通过 safety-label-source 读取帖子的 SafetyLabelMap(visibility-filtering/server_deps.rs:39-40、:148)。
| 层 | 参数(开源默认值) | 锚点 |
|---|---|---|
| 进程内缓存 | 每条 TTL 10 秒 | safety-label-source/source.rs:13 |
| Dragonfly 缓存 | 键前缀 sls:;写入 TTL 24 小时;30 秒、90 秒两档刷新 |
safety-label-source/dragonfly.rs:25-38 |
| Manhattan 存储 | 超时 200 ms,重试 1 次,扫描上限 512 | safety-label-source/mh_client.rs:11-13 |
- 标签可以带过期时间
expires_at_msec。读取时,safety-label-source 剔除过期标签(safety-label-source/source.rs:35-54、:138-140)。打标签规则中的 7 天、14 天 TTL 靠这一步生效。 - 远端不可用时,safety-label-source 走降级路径(
source.rs:130-134)。
safety-label-user-agg:按帖子给账号打标签
flowchart LR
K["Kafka: vf_tweet_safety_labels_event_prod"] -- "延迟 10 分钟转发" --> P["Processor"]
P --> T{"新加的标签是否触发规则?"}
T -- "是" --> U["取作者状态: nsfw 标记 / 高 PageRank / 灰标 / 现有标签"]
U --> S["扫描作者最近 N 条帖子的标签"]
S --> M{"满足计数条件?"}
M -- "是" --> W["写 Gizmoduck 账号标签, 带 TTL"]
- 输入:帖子标签事件流。Processor 只处理“新加”(Applied)事件;转发延迟 10 分钟,SLO 最大延迟 20 分钟(
safety-label-user-agg/safetyLabelToUserLevelAggregationV2Forwarder.strato:3-21、safetyLabelToUserLevelAggregationV2Processor.strato:14-19)。 - 规则来自功能开关
safety_understanding_post_to_user_label_rules。开关缺省时,Processor 使用代码中的默认 JSON(postToUserLabelRules.strato:360-432)。 - 规则结构:触发标签 → 排除条件 → 若干条件,每个条件含 (窗口条数, 最少命中条数, 最大帖龄, 是否只看带媒体帖, 标签选择器) → 账号标签与 TTL(
postToUserLabelRules.strato:6-47)。 - 可写的账号标签只有
POSSIBLY_NSFW_ACCOUNT与NSFW_HIGH_PRECISION(postToUserLabelRules.strato:96-99)。 - 配置上限:最多 10 条规则;窗口 ≤ 10;最少命中 ≤ 11;帖龄 ≤ 60 天;TTL ≤ 7 天(
postToUserLabelRules.strato:100-107)。 - 帖子扫描:Processor 从作者主页时间线倒序取帖;遇到转发时,取原帖的标签(
safetyLabelToUserLevelAggregationV2Processor.strato:59-87)。 - 写入时,
byUser与source都记为"Grox"(safetyLabelToUserLevelAggregationV2Processor.strato:91-106)。
默认有两条规则:
| 规则 id | 触发标签 | 条件 | 账号标签 | 排除 | 锚点 |
|---|---|---|---|---|---|
possibly_nsfw_account |
NSFW_HIGH_PRECISION、SOFT_NSFW | 最近 10 条中至少 11 条带其一 | POSSIBLY_NSFW_ACCOUNT,7 天 |
nsfw 用户、nsfw 管理员标记、高 PageRank 或灰标、已有同类标签 | postToUserLabelRules.strato:363-394 |
nsfw_high_precision |
NSFW_HIGH_PRECISION | 最近 5 条中至少 3 条带该标签,帖龄 ≤ 60 天 | NSFW_HIGH_PRECISION,7 天 |
nsfw 管理员标记、已有该标签 | postToUserLabelRules.strato:395-426 |
possibly_nsfw_account 的默认条件“10 条中至少 11 条”永远无法满足,因此这条规则默认等于关闭(依代码推断)。VF 的账号标签枚举中也没有 POSSIBLY_NSFW_ACCOUNT(visibility-filtering/models/author.rs:20-37)。
NSFW_HIGH_PRECISION 账号标签会触发站外推荐丢弃(visibility-filtering/rules/author_rules.rs:176-181)。结果是:一个账号最近 5 条帖子中有 3 条被判为高精度成人内容时,接下来 7 天它的所有帖子都不会出现在非关注者的推荐中。
takedowns:下架原因合并
- 帖子的
takedownReasons= 帖子自身原因 + 作者账号的原因。系统只在帖子的hasTakedown为真时查询(takedowns/tweet-entity-service/TakedownReasonsTransform.scala:19-72)。 - Gizmoduck 读取账号级原因时,先去掉“不执行”的部分:全部 DMCA,国家码为
xy的法律请求和未注明原因,国家码为xx/xy的第三方举报(takedowns/gizmoduck/RedactUnenforcedTakedownsFilter.scala:64-81)。因此,账号级的版权下架不会波及该账号的所有帖子。 - VF 怎样按国家使用这些原因,见 可见性过滤 的“国家下架与法律下架(takedown)”一节。
设计决策
| 决策 | 理由 |
|---|---|
| 规则放在 YAML 中,由动态配置下发 | 处置策略可以快速调整,不必发版 |
| 用户表以封禁兜底,帖子表以跳过兜底 | 推测:进入用户处置流的事件已经过上游模型和主题筛选;帖子事件只在标签明确时才处置 |
| 先检查名单、粉丝数、可信度分 | 减少对高影响力账号的自动误判 |
| 申诉保护期独立成服务,且只读 | 处置服务只需要“能不能做”的答案;写入走人工申诉流程 |
| 标签带 TTL,读取时过滤过期标签 | 自动化标签到期自然失效,不依赖清理任务 |
| 账号聚合规则有硬上限 | 防止配置错误导致大面积给账号打标签 |
源码锚点
abuse-enforcement-service/service-lib/src/rules.rs:287-332—— 第一条为真的规则abuse-enforcement-service/service-lib/src/decision.rs:1-24—— 动作种类abuse-enforcement-service/service-lib/rules/enforcement_user.yaml:5-189—— 用户规则abuse-enforcement-service/service-lib/rules/enforcement_post.yaml:3-82—— 帖子规则abuse-enforcement-service/service-lib/src/safety_checks.rs:158-175—— 粉丝上限abuse-enforcement-service/service-lib/src/overturn_hold.rs:150-162、:396-415—— 申诉保护期门abuse-ledger-service/src/sql.rs:3-7—— 保护期查询safety-label-source/source.rs:13-54—— 本地缓存与过期过滤safety-label-user-agg/postToUserLabelRules.strato:96-107、:360-428—— 聚合规则上限与默认规则takedowns/gizmoduck/RedactUnenforcedTakedownsFilter.scala:64-81—— 不执行的账号级下架
相关页面
- 账号级信号 —— BDSM 评分与可信度分
- 打标签规则 —— 事件驱动的打标签
- 可见性过滤 —— 标签的效果
- Under the Hood 透明度报告 —— 用户能看到哪些标签和下架