
Figure 1: 本文叙述的终点。/studio 的 LoRA 下拉菜单中加入了新训练的 nipple_v2,此处与既有的 kotonia03 (anime + 美感) 叠加。右下角的星级评分 UI 是 dataset labeling 工具,与生成同时运行。
"LoRA 在 @1.5 强度下的输出质量比 @1.0 还要高"
这听起来只是"开大一点就强一点"的随手观察,其实这是 under-fit 在暗中报警的不祥信号。
我经营的 kotonia.ai 把开放权重的图像生成模型 HiDream-O1-Image 以 fp8 常驻显存,在其上叠加多个自训练 LoRA 来表达专门差分。其中一个叫 nipple_v1,用于提升人体细节的渲染质量。当用户反馈"用 1.5 看起来比 1.0 好"的那一刻,我立刻判断:这是 under-fit 在说话。
之后用一个晚上,把"爬数据→重新设计 caption pipeline→规模扩大 17 倍→训练→A/B→部署"一口气跑完。途中我发现了一个事实:整个 NSFW 数据集世界从结构上被 CSAM 污染和 DRM 双重锁死。所以本文从那里开始讲,最后落到方法论:3-stage Caption。
1. "@1.5 > @1.0" 实际在传递的信号
LoRA 的工作方式是在 base model 的权重上叠加一个低秩差分 ΔW,推理时再乘以一个标量 α:W' = W + α · ΔW。训练时以 α=1.0 为"标定刻度"对齐,推理时用户可以调节 0.5 或 1.5。
通常 @1.0 是 natural sweet spot,@1.5 要么过度,要么破坏解剖结构,要么显得不自然。而 kotonia.ai 的 nipple_v1 出现了反向:@1.5 的解剖质感优于 @1.0。
含义:训练过程中,LoRA 的 magnitude 没有伸展到位就早期收敛了。具体可能是:
- rank 太小,表达空间装不下数据的 variability
- LR 太保守,每一步移动距离太短
- 数据量太少,根本没有产生 variability
v1 的训练参数:525 张图像,rank 32,1500 步。这是 smoke test 级别的迷你配置,从来没有扩展到生产规模。用户层面的症状"请用 1.5",就是这笔账到期了。
修复路径需要提高 rank,扩大数据,多跑步数,并从根本上提升 caption 质量。故事从数据采集开始。
2. 公开 NSFW 数据集世界被 CSAM 关上的门
"我想做一个专用人体细节 LoRA,需要写实数据集"——在 ML 圈这是再普通不过的需求,过去你会去找 NudeNet、LAION-NSFW subset,或是 Figshare 14495367(Image and video dataset for adult content detection)这类学术发布。
2025 年风向变了。
加拿大儿童保护中心(C3P)对 NudeNet 分类器数据集(约 70 万张)进行了审计,发现了 680 张 CSAM 图像,其中 120 张是 identified victim(与执法部门数据库匹配过的真实受害者)。Academic Torrents 收到通知后下架数据集。archive.org 的原始 URL 现在是 404。引用过 NudeNet 的 250 多篇学术论文一夜之间立场尴尬。
这不是孤立事故,是结构性的。Stanford Internet Observatory 早在 2023 年就已在 LAION-5B 中发现 3,200 多张 CSAM。共同的根源:从色情网站抓取。所有按这个方法构建的公开 NSFW 数据集都继承了同一个结构性污染风险。
Figshare 14495367 在其描述中写明"通过浏览色情网站"采集,目前没有公开审计记录,但只要采集方法相同,统计上可期待相同的污染率(约 0.1%)。在 30,800 张图像中,统计上预期约 30 张 CSAM 混入。
法律账面也很严:
- 持有 CSAM 本身即犯罪,含日本在内的多数司法辖区。以 AI 训练为目的下载,构成 possession
- "我下载后再过滤" 不能脱罪——下载的瞬间已经构成违法,且没有能让普通用户安全识别 CSAM 的手段
- 可追溯性也真实存在——对 LoRA 权重做 membership inference attack,可以事后查证训练数据是否包含某个 dataset
到这一步,公开 NSFW 数据集路线在结构上已经走死。换下一个候选。
3. "我在 FANZA 买的,所以合法" 只对了一半
第二个假设:合法购买商业日本成人作品并从中抽帧。按日本著作权法第 30 条(私的使用),个人用途的复制应在许可范围,自己下载的视频抽取个别帧应当落在这个范围内。是吧?
我在 FANZA 买了一部 S1 厂牌的作品,下载下来是一个 .dcv 文件。file 命令显示:ISO Media MP4 v1。看起来就是普通 MP4。
但是 ffprobe -read_intervals "%+#1" -show_packets 暴露了真相:
[PACKET]
codec_type=video
flags=K__
[SIDE_DATA]
side_data_type=Encryption info ← 这里
[/SIDE_DATA]
CENC(Common Encryption,MPEG-DASH 系 DRM)正在对视频样本加密。容器(MP4 ftyp/moov)可读,但所有 H.264 NAL 单元都是加密字节。播放时 DMM Player 从 DRM 服务器取得密钥,在内存中解密(Widevine/PlayReady 等同)。
这直接撞上日本著作权法第 30 条第 1 项第 2 号及第 2 项(2012 年修订,2018 年加强)。通过回避技术性保护手段进行的复制,即使是私人使用也违法——刑事处罚(2 年以下徒刑或 200 万日元以下罚金)。"我自己买的"和"我只在自己设备上做 AI 训练"都无法救济。回避 DRM 这个行为本身就是违法。
实体媒介(Blu-ray、DVD)采用 AACS/CSS,同一种 DRM 结构,同一个问题。
也就是说主要的商业 AV 下载渠道作为 AI 训练数据源在结构上是封闭的。我那 9.6 GB 的购买只能用于个人观看,抽帧路径走不通。
4. 走到 CivitAI RED——剩下的只有 AI 生成路径
公开 NSFW 数据集被 CSAM 关死。商业 AV 被 DRM 关死。自掏腰包拍摄在 indie 预算尺度上不现实。剩下的就是 CivitAI 的 AI 生成图像库。
CivitAI 通过 API 提供社区生成的图像,按 browsingLevel(1=PG ... 16=XXX)分类。让这条路安全的结构性属性:
- 不存在 CSAM 风险——AI 生成内容没有 identified victim,概念上根本不适用
- 明确的年龄政策——CivitAI 将描绘未成年人视为 TOS 违规并删除
- 认证的批量 API 访问——基于 token,分页可控
- provenance 干净——每张图像都附带原始 prompt、模型名、creator
一个常见担忧:"训练 AI 生成图像会导致 mode collapse"。这个担忧针对的是 self-distillation——同一模型的输出又被喂回同一模型。CivitAI 是 PonyDiffusion / Flux / SDXL / 各种 community LoRA 的异构混合,与 HiDream 全部不同源(跨架构),不构成 self-distillation。
我写了 civitai_collect.py,用 --target 20000 --weights "8:0.25,16:0.75" --min_hearts 30 跑了一遍。CivitAI API 在分页过程中多次返回 500/503,我多次从 cursor 续传。最终产量:level 8 5,000 张 + level 16 4,707 张 = 9,707 张。未达 20k 目标,但比 v1 的 525 张多 18.5 倍,已经进入实用规模。
数据搞定。接下来是 caption 设计。
5. 17 倍数据本身不够——caption mode collapse 的发现
"加数据就能解决 under-fit"这个直觉只对了一半。
v1 的 525 张 caption 是用 Grok 2-stage pipeline 生成的:Stage 1 用 JSON 抽取 attribute,Stage 2 强制将所有 attribute 逐字使用合成 caption。把同一 pipeline 放大到 9,707 张时——
所有 caption 在结构上几乎一样。原因:
- Stage 1 抽取的 attribute 字段固定(7 个)
- Stage 2 用的是单一模板 prompt
- temperature 0.25 接近确定性
每张图像在 attribute 层面有 uniqueness,但句法结构、词汇选择、连接词、段落布局几乎全图相同。caption 之间存在 structural identity——这种重复 TF-IDF 检测不出来,因为词汇重叠看起来不高,但结构重叠是 100%。
这就是 caption mode collapse。一旦识别出,诊断就清晰了:用这种语料训练的 LoRA 会过拟合到特定的句法模式,推理时面对 prompt 变体就脆弱。
修复方向必须是在生成时就引入多样性。Post-hoc dedup(TF-IDF / cosine 聚类)只能捕捉词汇重叠,看不见结构重复。必须改变生成时的概率分布。
3-stage Captioning 在这里诞生。
6. 设计 3-stage Captioning——informational value frame
设计目标:
- 每张图像抽取更多结构性 uniqueness fodder
- 在生成时降低结构相同输出的概率
- 提高 nipple 区域词汇密度(色 + 形 + 状态 + areola 自然织入)
- 用本地 LLM(vLLM 上的 Gemma 4 26B A4B Uncensored,端口 8899)并行处理全部 9,707 张
三段:
Stage 1:Factual inventory(T=0.1)
12 个字段的结构化 JSON 抽取。在原 7 个之上增加 nipple_detail(color/shape/state/areola)、breast_detail(size/shape/skin_finish)、pose_framing、expression_mood、color_palette。
Stage 2:Analytical reasoning(T=0.4) ← 新增
以 Stage 1 的 JSON 为输入,让模型回答:"这张图像作为训练数据为什么 informative,用 2-3 句分析。" 显式约束:
Do NOT make subjective quality judgments — no "beautiful", "attractive", "well-composed", "high quality", "stunning". Describe informational value only.
这就是 informational value frame。它从结构上阻止主观质量词汇渗入推理。原因要点:如果"beautiful"被 caption 学到,模型会把"beautiful 是出现可见解剖的前提"也学进去——这是你不想要的脆弱性。
每张图像的 reasoning trace 不同(每张图像的 distinctive feature 不同),这种不对称性成为最终 caption 多样性的驱动器。
Stage 3:Caption synthesis with skeleton rotation(T=0.7)
输入 Stage 1 的 attribute + Stage 2 的 reasoning,生成最终 caption。八种句子骨架按图像 round-robin 分配,强制使用不同句法结构:
S0: "Close-up of [subject + pose]. [nipple/breast detail]. [lighting], [style]."
S1: "[Style] image: [pose_framing], [breast detail]. [nipple detail]. [mood], [lighting]."
S2: "[Mood] [subject] in [pose]; visible anatomy [list]. [props]. [lighting], [style]."
... (S3-S7)
并显式指导提高 nipple 区域词汇密度:
For the nipple region, weave 2-4 complementary terms naturally into the caption. Use complementary attributes (color + shape + state + areola) rather than synonym-stuffing. Vary which subset appears across captions in this batch.
产出例如 "pink, pointed nipples with prominent areolae"——四个属性自然织入,而不是 booru-tag 式罗列。HiDream 的 Qwen3VL 文本编码器是为自然语言 caption 而设计的,所以这种形式确实能落地。

Figure 2: V2 LoRA 与 kotonia03 (anime aesthetic) 叠加的单张生成。前文描述的自然语言多词汇 caption 模式("pink, pointed nipples with prominent areolae")在推理时翻译为解剖一致性:areola 纹理与 nipple 形状协调落地。
525 张 smoke test 结果:
- areola 出现率:v1 是 0/15,V2 是 4/15(新解锁词汇)
- erect 出现率:2 → 7(3.5x)
- pointed 出现率:0 → 3(新)
- unique trigram ratio:0.873 → 0.919(+5.3pp)
- self-BLEU proxy:0.018 → 0.008(−55%,自相似度降低)
在完整 9,707 张规模下,caption 在 concurrency 16 下 51 分钟完成(Gemma 26B uncensored 的 vLLM continuous batching 起作用)。
7. 训练与 A/B——under-fit 真的解了
训练配置:
- 9,138 张(9,707 减去 age safety filter 拦截 515 张和 discriminator 低于 3.0 分的 54 张)
- rank 64 / alpha 64(v1 的 2 倍)
- LR 1e-4(v1 的 2 倍)
- 30,000 步 / batch 1(v1 的 20 倍)
- fresh from base(不从 v1 续训,不继承 anime bias)
- patch_align 保持原始 aspect ratio(batch>1 化方案因 aspect 失真问题放弃)
在 GPU 0(Blackwell 6000,96GB)上停掉 image_server / LTX-2 / Gemma 26B 进行独占,约 3 小时完成训练。loss 稳定在 0.03-0.06 区间,无 divergence。

Figure 3: A/B 评估网格(40 张样本)。列:base / [email protected] / [email protected] / [email protected] / [email protected]。行:8 条 eval prompt。v1 列可见:多条 prompt 明确写 "topless",但 v1 输出穿衣版本(prompt adherence 失败)。v2 列:8/8 正确解读 topless。这是 3-stage caption pipeline 对 prompt adherence 改善的直接视觉证据。
A/B 评估覆盖 8 个 prompt × 5 个 config:
| config | 观察 |
|---|---|
| base(无 LoRA) | 解剖描绘在 base model 水平,保守 |
| [email protected] | 8 个 prompt 里有 4-5 次忽略 "topless",输出穿着衣服的版本 |
| [email protected] | overshoot 恢复了品质,是 v1 实用最优 |
| [email protected] | 8/8 正确解读 topless,nipple 细节(areola/shape)干净,aesthetic 持平或更优 |
| [email protected] | 与 [email protected] 几乎无差(overshoot 余地小 = under-fit 解决的证据) |
[email protected] ≈ [email protected] 是 under-fit 解决的信号。对比 [email protected] ≪ [email protected]。
接着是 8 个 prompt × 6 个 strength 的 sweep:
- Nipple-focused prompt 4 条:0.5 弱,0.75 sweet,1.0 强,1.25-1.5 出现 body inflation 迹象
- 泛化探针 4 条(着装女性、山脉风景、动漫制服、拉面碗):风景和食物在所有 strength 下完全不受影响。着装意图在所有 strength 下保持(不脱衣)。高 strength 下有轻微 breast emphasis 上升,但没有打破着装的 framing
这说明 LoRA 的 specialization 局限于 nipple/breast 域——无关域(风景、食物)完全没被 corrupt。
8. 这暴露了 indie 的 compounding loop
部署:在 /studio 的 LoRA 下拉菜单加入 nipple_v2(人体细节品质 + 泛化保持),default weight 0.75,在 image_server 的 HIDREAM_LORAS 环境变量中注册,rebuild 前端。~10 分钟。
这一个晚上产出的可复用资产:
- 3-stage caption 在方法论上可迁移。下一个专用 LoRA(手部品质 / 服装细节 / 特定风格)可以复用同一 pipeline
- age safety filter + discriminator + caption 存在的三重过滤是通用的。会成为 CivitAI 抓取的标准后处理
- A/B + strength sweep + 泛化探针 是任意 LoRA 都能复用的评估框架
除了这些 artifact,还有一件关于 indie 工具栈值得说出来。
公开数据集被 CSAM 关死。商业 AV 被 DRM 关死。在这种风景里剩下的路径是自己打 API,自己设计 caption pipeline,自己烧 GPU,自己部署。这是 VC 撑腰的 dumping 创业公司模仿不来的动法,而且因为对外依赖归零,每次尝试的输出会成为下次尝试精度的输入。compounding loop 闭合。
"导入数据"变成"自己蒸馏数据","购买 caption"变成"自己设计 caption","外包训练"变成"自己跑训练"。每个 delta 都很小,但对一个握住整套 stack 的 indie 来说,零外部依赖的 compounding 是真实的。
V3 的遗留任务也明确了:
- vulva bias 根治:在 Stage 1 prompt 中把 vulva 从
anatomy_visible排除,或在上游用 detector 过滤掉显示 vulva 的训练图像 - lying pose 拉长:CivitAI 的躺姿图像倾向于纵向 aspect ratio,怀疑在训练时产生了偏差。aspect-ratio-weighted sampling 应能 normalize
- stack rank 不匹配(v2 rank 64 与 k03 rank 32):
add_weighted_adapter linear要求同 rank,绕过路径是peft_model.base_model.set_adapter([list])+ per-adapter scaling
这些是用"caption 与采样设计"而非"加数据"解决的问题——V3 将更多是方法论上的精修。
我在夜里开始这个 session,到早上已经把 v2 部署上线。要允许一句自吹的话,那就是indie 的 compounding loop 在一个晚上闭合了一整个周期。