ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Civitai 未成年人模型哈希检测系统(Minor Model Hash Detection)设计与实现

Civitai 未成年人模型哈希检测系统(Minor Model Hash Detection)设计与实现 Civitai 未成年人模型哈希检测系统Minor Model Hash Detection设计与实现【免费下载链接】civitaiA repository of models, textual inversions, and more项目地址: https://gitcode.com/GitHub_Trending/ci/civitai导读本文基于 docs/features/minor-model-hash-detection.md 展开系统讲解 Civitai 如何通过SHA256 文件哈希识别被审核员标记为未成年minor的模型文件被再次上传这一行为。文章完整覆盖该特性的架构设计、种子集定义、两条无人值守检测路径扫描时钩子与夜间扫描任务、快照回滚机制、审核工作台、通知链路、Flipt 功能开关与部分索引优化并结合 minor-hash.service.ts、model.service.ts、model-file-scan.service.ts 等源码给出实现级证据。读完本文你将掌握这套以哈希为内容身份、只以人工决策为种子、默认关闭的重复上传拦截方案的核心设计原则与全部落地细节。1. 系统概述用 SHA256 识别重复上传当审核员将一个模型标记为 minor 时该决定只作用于一行Model记录——没有任何机制阻止同一文件被包装成新模型再次上传。Minor Model Hash Detection 系统将模型文件的SHA256 哈希视为内容的身份一旦与人工 minor 决策绑定的哈希再次出现系统按上传者身份分两条路径处理同一上传者自动标记 minor无人介入之后进入审核队列供复核不同上传者绝不自动标记仅进入审核队列。因为哈希只能证明文件相同不能证明是同一个人上传的。两条无人值守路径共用一个 Flipt 功能开关minor-hash-auto-flag且默认关闭。该系统与 model-file-scanning.md扫描钩子的触发位置和 nsfw-filtering.mdgallerySettings.level语义紧密相关。关键文件一览文件职责minor-hash.service.ts全部匹配、扫描、审核队列与回滚逻辑model-file-scan.service.tsapplyScanOutcome—— 扫描完成时的钩子model.service.tssetModelMinor、captureMinorFlagSnapshot、applyModelFlagSideEffects、withoutMinorHashMetaminor-flag-meta.tsisMinorAutoFlagged、stripMinorHashMeta、filterModelMetaForClientminor-flag.notifications.tsmodel-flagged-minor所有者通知minor-hash-sweep.ts夜间扫描任务45 3 * * *minor-hash-sweep.ts回填 回滚端点WEBHOOK_TOKEN保护minor-hash-matches.tsx审核员工作台两个页签moderator/index.tsmoderator.models.*过程minor-hash.schema.tsZod 输入校验flipt/client.tsFLIPT_FEATURE_FLAGS.MINOR_HASH_AUTO_FLAG2. 标记为 minor到底做了什么setModelMinor({ minor: true })model.service.ts按如下顺序执行捕获前置快照到Model.meta.minorFlagSnapshot在任何变更发生之前。写入minor true、nsfw false、sfwOnly true、gallerySettings.level sfwBrowsingLevelsFlag。将[minor,nsfw,sfwOnly]即MINOR_LOCKED_PROPERTIES定义于 model.service.ts追加到lockedProperties使创作者无法自行改回。写入一条ModActivity记录人工标记为setMinor自动化标记为setMinorAutoHash。调用applyModelFlagSideEffectsmodel.service.ts刷新模型标签缓存、排队模型搜索索引更新、删除 gallery-settings 的 Redis key、重新摄取模型并将该模型所有版本的所有帖子中的所有图片一次性置位minor基于集合的 UPDATE并将这些图片 ID 排入搜索索引队列。需要特别强调的是minor存在于Model而非ModelVersion——一个匹配的文件会限制该模型的所有版本。每次标记的影响范围都远大于触发它的那个哈希。取消标记minor: false时刻意不动nsfw/sfwOnly/gallerySettings——该模型在被标记之前可能本来就是合法的 SFW-only。恢复这些字段是回滚路径的职责且必须依据快照而非猜测。3. 种子集什么算已知 minormoderatorMinorSeedPredicateminor-hash.service.ts是唯一定义同时被扫描时查询和扫描任务的 CTE 复用m.minor AND minor ANY(m.lockedProperties) AND m.meta-minorFlagSnapshot-source IS DISTINCT FROM auto每个子句都有其存在的理由仅有minor不够——创作者可以把自己的模型自我声明为 minor。lockedProperties中包含minor才能证明是审核员施加的从而防止创作者靠自我声明把别人的上传也卷进种子集。排除sourceauto——阻止自动化自我播种。若不加这一条每个被自动标记的模型都会成为种子贡献其上的每一个哈希包括从未被审核员与 minor 内容绑定的哈希种子集会从机器决策中不断膨胀dry run 也就无法预测后续轮次会匹配什么。在生产规模克隆库上的实测dry run 说 300实际回填写了 302。审核员自己点 Set as Minor 会写入sourcemanual仍然会播种。旧版标记完全没有快照同样会播种NULL IS DISTINCT FROM auto为真。而一个被审核员确认的自动标记会被晋升为sourcemanual见下文Keep flagged从而开始播种——排除的是未经复核的机器输出而不是主题本身。实际后果种子集只会因人工决策而增长。这正是 dry run 的预测能够成立的原因——一次运行写入的任何东西都不会改变后续运行匹配的内容。只有ModelFile.type Model的文件参与MINOR_HASH_FILE_TYPE定义见 minor-hash.service.ts种子侧和候选侧都是如此。ModelFileHash.hash是citext类型所有存储的 SHA256 均为大写十六进制。4. 候选模型minorHashCandidatesCteminor-hash.service.ts定义其typeModel的 SHA256 哈希出现在种子集中、且NOT m.minor、status Deleted、文件未被回滚盖章覆盖notMinorHashClearedPredicate见下文的模型。对每个模型sameUploader是bool_or——它的匹配哈希中是否存在携带该哈希的种子属于同一userId。标记一个模型会把它从候选集中移除它变成了minor这正是扫描任务可恢复且幂等的原因。5. 路径一扫描时钩子applyScanOutcomemodel-file-scan.service.ts在模型文件扫描完成后调用checkMinorHashOnScan其门槛依次为文件有 SHA256、file.type Model、以及 Flipt 开关开启——开关放在最后检查只为真正可能匹配的文件付出一次开关求值。applyMinorHashMatchminor-hash.service.ts的决策矩阵情况结果匹配中包含被扫描的模型自身skipped它已经是种子没有其他模型匹配skipped某些其他匹配与扫描模型同userIdflagged—— 以系统用户-1调用setModelMinor活动记录setMinorAutoHash只有不同上传者的匹配queued—— 出现在审核页面checkMinorHashOnScanminor-hash.service.ts吞掉所有错误记录到 Axiom返回skipped——minor 哈希的失败绝不能导致扫描回调失败。这是唯一在实时上传时触发的路径。值得注意的实现细节清除盖章clear stamp的查询isMinorHashClearedForFile只在flagged写入路径上执行——因为匹配查询中的m是种子侧而非被扫描的模型扫描路径无法携带该谓词把这次额外的往返放在每次写入一次而不是每次扫描一次的位置上。6. 路径二夜间扫描任务minorHashSweepminor-hash-sweep.ts在45 3 * * *运行用于捕捉钩子无法覆盖的情况在原文件被标记之前就已上传、且扫描早已完成的副本。它与扫描钩子受同一 Flipt 开关控制因此两条无人值守路径无需部署即可同时停用。export const minorHashSweep createJob(minor-hash-sweep, 45 3 * * *, async () { if (!(await isFlipt(FLIPT_FEATURE_FLAGS.MINOR_HASH_AUTO_FLAG))) return; const swept await sweepMinorHashMatches({ dryRun: false, limit: 500 }); const accepted await acceptExpiredMinorAutoFlags({ dryRun: false, limit: 500 }); return { ...swept, ...accepted }; });sweepMinorHashMatches({ dryRun, limit, concurrency })minor-hash.service.ts的行为要点候选拆分统计来自不受 limit 限制的总数查询——这样 dry run 描述的是真实总体而不是自己的窗口写入阶段最多并行处理limit个同上传者标记concurrency控制并发只标记同上传者匹配不同上传者只作为计数上报由人工复核单模型失败被计数并记录日志绝不抛出完成报告在 HTTP 响应之前写入 Axiom——即使网关超时已提交的写入仍留有记录。DEFAULT_SWEEP_CONCURRENCY 5每个任务约 68 次顺序数据库往返吞吐量受 DB 延迟限制因此限制并行模型数即可。此外任务还调用acceptExpiredMinorAutoFlags未被复核的自动标记在30 天复核窗口AUTO_FLAG_REVIEW_WINDOW_DAYS 30见 minor-hash.service.ts之后被持久化为已接受写入minorHashAccepted键保持sourceauto——这样从无人复核过的标记永远不会成为后续自动化标记的种子。7. 快照与回滚Model.meta.minorFlagSnapshot由captureMinorFlagSnapshotmodel.service.ts幂等写入WHERE NOT (meta ? key)因此重复标记永远不会覆盖原始的标记前状态字段含义at标记施加的时间sourceauto活动setMinorAutoHash或manualprevNsfw、prevSfwOnly、prevGalleryLevel标记前的值prevLockedProperties完整的标记前数组prevMinorImageIds标记前已经是 minor 的图片快照捕获是尽力而为的丢失它最多阻碍后续回滚不能阻碍标记本身失败只记日志不抛出。rollbackMinorHashAutoFlagsminor-hash.service.ts有两种模式Blanket全量——source IS DISTINCT FROM manual且未被人工确认。审核员自己的决定绝不会作为撤销回填的附带损伤被回滚。Targeted定向modelIds——精确到这些模型任何 source不做确认跳过。指名模型本身就是审慎的决定这是误点后的逃生通道。人工确认 一条ModActivity记录entityTypemodel、activitysetMinor且createdAt snapshot.at。该排除在SQL 层完成而非事后过滤被确认的行永远保留 meta 键若留在ORDER BY id LIMIT n窗口内会永久占据槽位、拖垮排水进度。它们的数量作为skipped单独上报来自不受限的查询操作员因此能区分没有可撤销的了与剩下的全是人工决定。每次回滚调用setModelMinor({ minor: false })复用其搜索索引/缓存/图片机制然后从快照恢复nsfw/sfwOnly/gallery level/lockedProperties将快照键替换为清除盖章并把prevMinorImageIds重新标记为 minor取消标记清掉了所有图片的 minor包括那些本来就合法 minor 的。清除盖章clear stamp——为什么回滚要被记住删除快照正是让回滚被遗忘的原因模型重新变成普通候选下一次无人值守运行会把人工刚刚撤销的标记再加回去。因此与删除快照的同一写入会在Model.meta.minorHashCleared { at }上盖章notMinorHashClearedPredicateminor-hash.service.ts将其排除NOT (m.meta ? minorHashCleared) OR mf.createdAt (m.meta-minorHashCleared-at)::timestamptz它以文件时间为作用域而非整体排除模型回滚发生时已存在的文件被该决定覆盖之后上传的文件是上传者的新行为仍可被捕捉。全量排除会让一次回滚永久屏蔽自动化对该模型的识别。两个候选 CTE扫描任务与审核队列都携带该谓词。扫描路径无法携带匹配查询的m是种子侧因此applyMinorHashMatch只在标记路径上对照盖章检查被扫描文件isMinorHashClearedForFile——该额外往返每次写入只付一次。清除盖章只约束自动化。审核员随时可以手动标记该模型。8. 审核员工作台/moderator/minor-hash-matches审核员导航菜单中。两个页签Pending review待复核——不同上传者匹配queryMinorHashMatches。操作Set as Minormodel.setMinor人工标记——同样会快照因此可撤销但只能定向回滚DismissdismissMinorHashMatch写入Model.meta.minorHashDismissed被驳回的模型从队列中排除。Auto-flagged自动标记——扫描钩子标记、但尚无审核员签字的模型queryAutoFlaggedMinorModelssourceauto且未人工确认最新的在前。操作Keep flaggedconfirmMinorHashAutoFlagminor-hash.service.ts——将快照晋升为sourcemanual保留confirmedFrom/confirmedAt/confirmedBy并记录审核员自己的setMinorModActivity。confirmedFrom写入为COALESCE(已有 confirmedFrom, 当前 source)所以第二次确认读到的是已晋升的manual不会抹去标记始于auto这一事实——所有者告警与通知都依赖该来源。这一次晋升承载了整个决定该行离开队列、全量回滚不再能撤销它、模型的哈希开始为未来匹配播种。快照的标记前状态被保留定向撤销仍可行。若快照捕获失败晋升 no-op仅靠ModActivity行保护该标记。RevertrevertMinorHashAutoFlag——对这一个模型做定向回滚并写入一条rollbackMinorAutoHashModActivity。两个队列都不分页limit默认 1000、最大 2000外加truncated标志。这是刻意为之行在处理后离开队列任何服务端窗口OFFSET 或 keyset要么跳过未复核模型要么把客户端排序限制在已加载子集上。成本由候选 CTE 主导而非行数。注意FlaggedModelsList存在 OFFSET 版本的同类缺陷不要照抄它的分页。行详情封面图、上传者模型数/注册日期、匹配的模型、完整哈希由单独的逐行查询queryMinorHashMatchDetail在展开时获取列表查询保持轻量。自动标记页签的详情面板复用完全相同的getMinorHashMatchDetail——两个面板按构造保持一致而非靠人工同步。历史标记来源记录很少——生产约 13.5K 个 minor 锁定模型中只有 2 个有setMinorModActivity行。Set minor by/at 几乎总是空白渲染时必须做条件显示。9. 告知所有者自动标记在无人介入的情况下限制了别人的模型因此所有者会收到两次告知发生时一条通知以及每次打开模型页时一条告警。两者使用同一句话且刻意模糊Your model{name}has been marked as depicting a minor. If you believe this is a mistake, contact support.你的模型{name}已被标记为描绘未成年人。若你认为这是误判请联系支持。它不点名哈希、不点名匹配的模型、不点名来源也不列举被施加的限制。这些细节每一个都会告诉重复上传者要改哪些字节。应用内没有申诉通道Auto-flagged 页签本身就是对每条自动标记的审核申诉队列会与之重复——所有者被引导到支持审核员从该页签处理。通知——model-flagged-minorminor-flag.notifications.tsNotificationCategory.Systemtoggleable: false。它轮询at晚于任务游标的快照门槛为COALESCE(meta-minorFlagSnapshot-confirmedFrom, meta-minorFlagSnapshot-source) auto用COALESCE而非source——确认自动标记会把source改写为manual只轮询source会静默跳过审核员在下一轮运行前确认过的每条标记而那恰恰是标记永久生效的情形。查询还要求m.minor快照写在标记落地之前且在普通取消标记后仍存活仅凭其存在不能证明模型当前是 minor并排除userId -1deleteUser会重新指派模型。它还携带m.meta ? minorFlagSnapshot看似冗余实则不然——见下文部分索引一节。告警——当isCreator model.minorAutoFlagged时渲染在/models/[id]。服务端在getModelHandler中以isOwner model.minor isMinorAutoFlagged(meta)计算minorAutoFlagged使用脱敏之前的原始 meta。它在服务端做所有者门控因为model.getById是publicProcedure且页面是服务端渲染的——标记来自自动化还是人工不是访客该关心的事。告警在Keep flagged后持续存在模型仍为 minor在Revert后消失快照被删除。isMinorAutoFlagged与resolveMinorFlagged、resolveMinorAppeal都定义在 minor-flag-meta.ts其中申诉边界非所有者一律返回 null被独立封装以保证可测试性。10. 什么永远不会到达客户端该系统写入的三个Model.meta键仅限审核使用。minorFlagSnapshot携带prevMinorImageIds——模型上所有已经是 minor 的图片——以及source和时间戳minorHashDismissed携带审核员的userId。stripMinorHashMetaminor-flag-meta.ts是哪些键是机密的唯一定义。filterModelMetaForClient将其与既有的敏感词过滤组合注意其不对称性——敏感词数据保留给审核员而 minor-hash 键对所有人剥离因为审核员 UI 通过自己的过程queryAutoFlaggedMinorModels、queryMinorHashMatchDetail读取它们从不经过model.getById。脱敏在控制器层与服务层都执行因为updateModelById调用dbWrite.model.update时不带select会返回所有列——任何返回其结果的处理函数都会把快照直接交给客户端站点经由getModelHandlermodel.getByIdgetModelsPagedSimpleHandlermodel.getAllPagedSimple公开60s 缓存updateModelByIdrequestReview、changeMode、reorderVersions、updateGallerySettings、setCollectionShowcaseupsertModel两个分支model.upsertprivateModelFromTrainingprivate-model-from-training 流程getTrainingModelsForModeratorsmod.models.queryTraining一个grant标志而非isModerator缺少服务层那一半的话所有者可以在自己自动标记的模型上点击Request review从响应里读出source: auto、时间戳和prevMinorImageIds——这会让那套模糊文案失去意义。任何把Model行返回给客户端的新功能都应加入此列表。与剥离方向对称的还有stripModerationOwnedMetaminor-flag-meta.tsmodelUpsertSchema.meta是looseObject未知键会存活并随客户端副本合并进Model.meta——若不加这层防护创作者可以自行铸造minorFlagSnapshot让申诉流程把一条伪造的键当作自动标记的证据。MODERATION_OWNED_META_KEYS与剥离列表刻意保持一致加上敏感词键对从不安全下发与从不安全接收共用一张清单两个方向不会漂移。11. 功能开关minor-hash-auto-flagFLIPT_FEATURE_FLAGS.MINOR_HASH_AUTO_FLAGflipt/client.ts控制两条无人值守路径。默认关闭是构造出来的isFlipt对未知标志或不可达的 Flipt 返回false——没有定义标志时什么都不自动标记Flipt 宕机时也保持关闭。对于会自动限制他人模型的路径不标记是安全的失败模式——漏报只是让扫描任务之后还能捕捉的重新上传多活一阵误报却会错误地把他人的模型标记为 minor。它位于FLIPT_EVAL_CACHE_BYPASSflipt/client.ts中kill 开关在 60s 配置轮询后即可生效无需再等求值 TTL。求值是进程内的wasm 引擎单次扫描的求值开销可忽略。Flipt 仅走 GitOps——创建或启用该标志需要配置推送而非 API 写入。管理端点是刻意不设开关门控的回滚必须在开关被拉下之后仍可用——而那正是最需要它的时候。通知同样不受开关控制且没有关闭开关。开关只是停止模型被标记通知轮询每 60s 照常运行一旦出现新的sourceauto快照就会触发。开关关闭时这等于无事发生因为没有写入方——安全性是二阶的不是一道闸门。两点后果需要明说运行回填 通知它所标记的每一位所有者。不存在先安静回填、再打开通知的做法。若要分阶段可在排水前把KeyValue行last-sent-notification-model-flagged-minor前移之后再恢复。管理端点不加门控的actionsweep可以在开关读作 off 时写入自动快照所有者在一分钟内就会收到通知。部署本身是安全的全新通知类型没有游标行getJobDate会回退到全局last-sent-notifications值约 1 分钟前而不是纪元send-notifications.ts。已存在的快照at更旧永远不会触发。12. 部分索引Model_minorFlagSnapshot_source_idxCREATE INDEX CONCURRENTLY Model_minorFlagSnapshot_source_idx ON Model (((meta-minorFlagSnapshot-source))) WHERE meta ? minorFlagSnapshot;迁移20260730120000_model_minor_flag_snapshot_index与此仓库的所有迁移一样手工执行。它是部署前置条件不是后续优化——无论 Flipt 开关是否开启通知每 60s 轮询一次。通知查询重复书写m.meta ? minorFlagSnapshot尽管COALESCE(...) auto已隐含它。这个子句是承重的。要使用部分索引Postgres 必须证明查询的WHERE蕴含索引谓词而predicate_implied_by只能推理equal()子句和 btree 操作符族。?是jsonb_exists属于 GINjsonb_ops没有 btree 操作符族所以查询中的其他任何东西都无法推导出它——缺少这个字面子句时predOK为 false索引会被直接排除出规划。在生产规模克隆库上的实测带该子句不带计划Index ScanParallel Seq Scan3 workersBuffers1112,491执行耗时0.047 ms237 ms索引键并不服务通知查询CoalesceExpr永远无法匹配索引表达式因此COALESCE(...)、at、minor、userId都作为索引后的 Filter 应用。全部收益来自部分谓词把Model裁剪到快照子集。审核员的 Auto-flagged 队列则直接匹配键它直接过滤source获得真正的 Index Cond。13. 管理端点GET /api/admin/temp/minor-hash-sweep?token$WEBHOOK_TOKENdryRuntruelimit1000 GET /api/admin/temp/minor-hash-sweep?token$WEBHOOK_TOKENactionrollbackdryRuntrue GET /api/admin/temp/minor-hash-sweep?token$WEBHOOK_TOKENactionrollbackdryRunfalsemodelIds123,456参数语义minor-hash-sweep.ts 中的 Zod schemaaction默认sweep。sweep标记同上传者哈希匹配rollback用快照撤销先前的标记恢复nsfw/sfwOnly/gallery level/lockedProperties与先前 minor 的图片。不带modelIds时只覆盖自动化标记并跳过审核员已人工确认的。modelIds仅 rollback 可用其他 action 传它会返回 400。逗号分隔的模型 ID定向撤销——无论标记来源如何包括审核员的手动 Set as Minor都精确回滚这模型且不做人工确认跳过。这是误点后的逃生通道全量回滚永远不会触碰手动标记。dryRun两个 action 默认均为 true。为 true 时什么都不写报告展示候选拆分与至多 20 行的样本。limit默认 100、最大 1000。限制每次调用写入的模型数sweep 为标记数rollback 为处理数——sweep 上报的候选拆分始终覆盖全量总体与 limit 无关因此任意 limit 下的 dry run 都显示真实总数。concurrency默认 5、最大 10。并行写入的模型数。两个 action 都可恢复且幂等被标记的模型离开 sweep 的候选集被回滚的模型失去其 meta 键。因此以重复的小调用如limit50排水比一次性大跑更可取——后者有中途网关超时的风险。补充安全约束modelIds与action ! rollback组合时返回 400。整个端点由WebhookEndpoint与?token$WEBHOOK_TOKEN保护。14. 写入的数据位置值Model.meta.minorFlagSnapshot标记前状态 source确认后追加confirmedFrom/confirmedAt/confirmedByModel.meta.minorHashCleared{ at }—— 发生过回滚自动化对早于此的文件不再动作Model.meta.minorHashDismissed{ at, by }—— 将该模型从待复核队列移除Model.meta.minorHashAccepted{ at }—— 30 天窗口过期的未复核自动标记持久化为已接受ModActivitysetMinor、unsetMinor、setMinorAutoHash、rollbackMinorAutoHash、dismissMinorHashMatchModActivity以(activity, entityType, entityId)为唯一键用DO UPDATE SET createdAt NOW()做 upsert——每个 (模型, 活动) 组合只有一行确认操作是更新时间戳而非报错。所有三个加上minorHashAccepted共四个Model.meta键都会从所有面向客户端的响应中剥离——见什么永远不会到达客户端。无 schema 变更一切依托现有的Model.meta与ModActivity列。唯一一次迁移是一个索引20260730120000_model_minor_flag_snapshot_index它不新增任何状态。15. 删除与重新上传已覆盖。所有面向用户的删除都是软删除——deleteModelById设置statusDeleteddeleteUser设置{deletedAt, status:Deleted}或重新指派给userId -1。哈希存活所以被删除的 minor 模型仍然播种。只有permaDeleteModelById会销毁种子CASCADE 到ModelFileHash且它受审核员门控。来自新账号的重新上传会落入不同上传者审核队列而非自动标记——这是正确的因为哈希证明的是文件身份而非背后的人是谁。16. 设计不变量以下是该设计所持守的性质以及各自的强制位置。破坏其中任何一条该特性会从仅仅是错误变成不安全不变量强制位置只有人工决策播种moderatorMinorSeedPredicatelockedPropertiessource auto自动化绝不标记不同上传者applyMinorHashMatchqueued、扫描任务WHERE c.sameUploaderdry run 预测 live run 的写入种子集不能因自动化输出而增长回滚会被记住minorHashClearednotMinorHashClearedPredicate回滚不会永久屏蔽自动化清除盖章按ModelFile.createdAt作用域化审核员的标记绝不被机器回滚autoFlaggedPredicatehumanConfirmedPredicate每条标记都可逆任何变更前先captureMinorFlagSnapshot手动标记亦然minor 哈希失败绝不导致扫描失败checkMinorHashOnScan吞掉并记录两条无人值守路径一起停无需部署一个 Flipt 开关两处都检查快照永不触达客户端控制器与服务层返回处都做stripMinorHashMeta机器标记模型时所有者被告知model-flagged-minor 模型页告警确认不会抹去标记始于自动化晋升时COALESCE(confirmedFrom, source)所有者文案不能让重新上传者知道该改什么两个界面共用一句通用文案17. 注意事项Caveatsminor是模型级的。一个匹配文件限制该模型的所有版本。按被标记模型数衡量影响会低估它。同上传者是唯一的自动标记信号。用新账号的执着重新上传者会落入审核队列——这是设计使然哈希证明文件身份而非背后的人。管理端点的actionsweep不加门控不只是actionrollback。即使拉下 kill 开关任何持有WEBHOOK_TOKEN的人仍可运行 live sweep。历史标记来源数据很薄——见审核页备注不要构建假设setMinorModActivity行存在的 UI。清除盖章从不清理。模型可能无限期携带minorHashCleared它只会收窄自动化的动作范围因此是惰性而非过期的。通知没有关闭开关——见功能开关一节。回填即通知。驳回是永久且模型级的。minorHashDismissed只在待复核查询中检查所以被驳回的模型即使后续出现无关哈希匹配也不会回到该队列——而扫描钩子在同上传者匹配时仍会自动标记它。按匹配作用域化是一个已知的后续改进。prevMinorImageIds无上界。它只保存标记之前就已是 minor 的图片实测中位数 3、p99 64、最大 1,174但平台上最大的画廊约 226K 张图片病态模型会把数 MB 的数组放进每次页面加载都会读取的Model.meta行。applyModelFlagSideEffects交叉写入poi和minor。一条 UPDATE 在任一变化时同时写两者所以标记 minor 会覆盖每张图片独立扫描出的poi反之亦然且两者都不在对方的快照中——回滚无法恢复。这是与 poi 路径共享的既有问题。结语Minor Model Hash Detection 是一个高度克制的自动化系统以 SHA256 为内容身份、以仅人工决策为种子集的唯一来源、以同上传者才自动标记为安全边界、以幂等快照保证每条自动化决策可逆、以清除盖章防止回滚被遗忘、以默认关闭的 Flipt 开关让两条无人值守路径可零部署同时停用。其核心经验——把不可逆操作的失败模式设计为漏报而非误报、让 dry run 与 live run 描述同一总体、在 SQL 层而非应用层维护不变量——对任何做内容治理与重复上传检测的系统都极具参考价值。相关实现可从 minor-hash.service.ts 与 minor-hash-sweep.ts 入手继续深入。【免费下载链接】civitaiA repository of models, textual inversions, and more项目地址: https://gitcode.com/GitHub_Trending/ci/civitai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进