- 待办:会话式长上下文方案标记为已技术评审且不实施;补记问题 A 的阶段性结论(暂缓) - 新增 docs/实验数据-字幕审校定位与修复实验.md:LLM 定位触发率/召回、合成正样本、逐条修复前后对照、成本与复现方式 - 新增 docs/实验数据-字幕重生成成本与耗时.md:单价口径、功率画像、全量推算 - decisions:补充两条决策(会话式长上下文否决、审校定位+定向修复暂缓) - scripts:归档一次性探测脚本 probe_subtitle_review_stage0.py(含 rebuild 子步骤) - AGENTS/README:补充实验与改动许可规则、文档索引
10 KiB
10 KiB
实验数据:字幕审校(问题定位 + 定向修复)
本文件记录"用 LLM 定位有问题的字幕 cue,再定向修复该 cue"这一方案的实测数据与结论。 方案背景与需求见 待办-翻译上下文复用与语义纠错.md, 结论的取舍理由见 decisions.md。
一句话结论:这套结构对"术语/忠实性"类问题有效且便宜,但对"字面通顺但语义错" (问题 A:ASR 听岔成正常句子)无效——把中文、日文原文、邻句、系列词表全给 LLM,它既定位不出、也改不动,甚至会把本来正常的句子改坏。判定为当前模型能力不足, 暂缓实施。
一、口径与素材
| 项 | 值 |
|---|---|
| 素材 | /mnt/fnOS/123/kiwvr-886/masex.tv@kiwvr00886_{1,2}_8k.{JA,CN}.srt(生产产物) |
| 规模 | part1 337 条 cue/part2 504 条 cue;JA 与 CN 条数与时间轴逐条一致 |
| 已知问题样本(正样本) | part2 的 183 / 184 / 185(见待办文档问题 A:ママの声をおなか、あくまで×2) |
| 模型 | SiliconFlow Qwen/Qwen3.5-35B-A3B(enable_thinking=false,与生产翻译节点一致) |
| 批大小 | 定位 30 条/请求;修复窗口 = 目标 ±2 条;合成正样本窗口 30 条 |
| 词表 | 由该文件夹自己的产物挖掘(不调 LLM,见下),严格映射阈值 50% |
词表为什么不用 LLM 生成:直接问"这些成人用语的中文译名"会被模型拒答 (实测返回"我无法提供涉及色情内容的信息")。改为从库内已有
.JA.srt/.CN.srt反推:候选日文词来自静态表 + 通用领域词表,中文译名取"含该词的 cue 里过半数 出现"的中文候选词,否则留空。
二、方法(4 步)
- 规则层(对照用):
① 词表违背(日文用了词表词但译文没体现该译名)、② 近音可疑(日文里出现与词表词同长度、编辑距离 ≤1 的片段,且译文没体现该译名)。 - 定位层 V1:只给中文(
id|时间|译文)+ 系列词表,让 LLM 找出"与上下文不符、 逻辑不通、或与词表不一致"的条目。这就是"纯 LLM 智力定位"的原设计。 - 定位层 V2:给 中文 + 日文原文 + 系列词表,让 LLM 找"译文与日文原意不符 (含近音听错)、上下文矛盾、与词表不一致"的条目。
- 修复层:只对目标 cue,给
日文原文 + 现有译文 + ±2 邻句(日文+中文)+ 系列词表, 要求返回窗口内全部 id 的译文(允许顺带改邻句,禁止增删条目)。 - 合成正样本:把正常译文里的域词替换成中性词(小穴→肚子/声音/苹果…), 制造"字面通顺但语义错"的样本,测定位召回。
三、实测结果
3.1 定位层(全片 part2,504 条)
| 变体 | 输入 | 命中(触发率) | 三条目标召回 | 判为"误听/近音"的原因数 |
|---|---|---|---|---|
| V1 | 中文 + 词表 | 37/504 = 7.3% | 0/3 | 0 |
| V2 | 中文 + 日文 + 词表 | 38/504 = 7.5% | 1/3(命中 184) | 15 |
- V1 在 165–195 区间标的是 165/175/176/177/192,恰好漏掉 183("那我让妈妈的声音 进入你肚子里了哦")——中文通顺时,纯中文审校不会怀疑它。
- V2 加上日文后模型明显更会往"听错"方向想:把 187
口紋、192生鼻、32/46 的生おなか(判为生おなほ的误听)都标了出来,但 183 仍漏。 - 差异原因:32/46 的中文不通("因为是新鲜的肚子")才触发怀疑;183 的中文是正常人话。
3.2 规则层(对照,证明硬规则泛化不了)
| 口径 | 命中率 | 目标召回 |
|---|---|---|
| 等长窗口 + 编辑距离 ≤1 + 映射阈值 50% | 33/841 = 3.9%(part2 3.2%) | 0/3 |
| 放宽到 ±1 长度 + 距离 ≤2 | 409/841 = 48.6% | 3/3(但全是噪声:まま→マット/マンゴー) |
即:严格则漏,宽松则全是假阳性;近音匹配只能当候选生成器,不能当判定依据。
3.3 合成正样本(V2 定位,14 条)
| 项 | 值 |
|---|---|
| 召回 | 11/14 = 78.6% |
| 漏掉的 3 条 | 看看肚子、时候插在里面、就是这里,这个时候——全是"读起来通顺"的 |
3.4 修复层(输入:日文 + 译文 + ±2 邻句 + 词表)
| id | 日文 | 改前 | 改后 | 判定 |
|---|---|---|---|---|
| 183 | じゃあ、ママの声をおなかに入れますね | 那我让妈妈的声音进入你肚子里了哦 | 那我把妈妈的声音传送到你身体里了哦 | ✗ 仍是"声音" |
| 184 | あくまで、あくまでください | 再吃一个,再吃一个吧 | 继续,继续吃 | ✗ 仍是"吃" |
| 185 | あくまで入ってしまいました | 它已经全都进来了 | 它已经完全进去了 | ✗ 未到"最里面" |
| 51 | 今のマンコの締め付け… | 刚才阴道的紧致感不错吗? | 刚才小穴的紧致感不错吗? | ✓ 术语统一 |
| 55 | 生の方に生チュートが入っていた | 生来的里面插着生来的玩具 | 小鸡鸡插进了小穴里 | ✓ 大幅改善 |
| 48 | あ、お腹鳴っちゃう | 啊,肚子饿了 | 啊,小穴要湿了 | ✗ 改坏了(脑补,日文无依据) |
四、成本与耗时
| 项 | 值 |
|---|---|
| 本次实测 | 71 次调用,输入 67,213 / 输出 12,630 tokens → 约 ¥0.067(¥0.4/M 入、¥3.2/M 出) |
| 挂钟 | 全流程约 4 分钟(含 17+17 批定位、8 次修复、14 次合成样本) |
| 外推(每素材小时) | 定位约 15 批 + 修复约 25 个窗口 → 约 +¥0.04/素材小时 |
| 全量外推(187 小时待重生成) | 约 +¥7(相对现状 ¥0.03–0.05/素材小时,约 2 倍) |
成本不是瓶颈;触发率(7.5%)决定成本,也决定"改坏正常句"的风险面。
五、结论与原因分析
- 有效面:术语/忠实性类(
词表违背、译文与日文不一致、上下文称呼跳变)—— 修复正确率高(51/55 明显变好),合成正样本召回 79%。这部分即使单独做也有价值。 - 无效面(问题 A):
字面通顺但语义错。原因不是"上下文给得不够":- 定位阶段:中文通顺 ⇒ 模型不怀疑日文中的错词(183 在 V1/V2 都没被标出);
- 修复阶段:唯一可依据的日文原文本身是错的 ⇒ 模型沿错译走,只能换词(肚子→身体), 不能凭空生成正确含义。这与待办文档里记录的两次失败实验(纠错节点、 提示词 A/B)结论一致。
- 副作用:允许改邻句会脑补出新意思(48 从"肚子饿了"改成"小穴要湿了"), 需要"必须给出日文依据/候选词才允许改动"的硬约束。
- 判定:当前 LLM 能力不足以完成"从错误的日文原文反推真实含义"这一步, 方案暂缓;不再在翻译侧继续做语义纠错。
六、未验证的下一步(若将来重开)
按"换提问对象、换判据"而非"加规则"的思路,三条可测方向:
- 不审译文,审日文:只给日文 + 系列词表,逐条问"这句像不像把某个词听成了另一个
常见词?给出候选词"。这样中文的通顺度再也掩盖不了问题(183 的
おなか在 "本系列おなほ出现 29 次"的语境下有机会被标出并给出候选おなほ)。 - 先建场景再对照:让 LLM 通读一个场景的日文,总结"在做什么、用了哪些道具/称呼", 再用这份场景模型审中文(针对"进入肚子里"这类与动作链矛盾的句子)。
- 召回优先的提问:把"找出有问题的条目"改为"逐条给可疑度 0–3 打分 + 理由", 避免"只有读不通才报"的偏置,用阈值调触发率。
- 配套约束:修复必须能指出日文依据或候选词才允许改动正文,否则拒绝改写。
第 1、2 条本质上是把纠错从翻译侧挪回ASR 侧(那里才有声学证据)。
七、复现方式
# 全流程(规则层 + 定位 V1/V2 + 修复 + 合成正样本;约 71 次调用、¥0.07)
uv run python scripts/probe_subtitle_review_stage0.py --steps rules,locate,repair,synthetic
# 只跑规则层(不调 LLM,验证脚本行为)
uv run python scripts/probe_subtitle_review_stage0.py --steps rules --out /tmp/stage0
# 从原始调用日志重算统计(不重跑、不烧 token)
uv run python scripts/probe_subtitle_review_stage0.py --steps rebuild
| 产物 | 路径(data/ 已 gitignore,仅本机存档) |
|---|---|
| 每次请求与响应原文(唯一证据源) | data/experiments/review_stage0/out/calls.jsonl |
| 本次运行统计 | data/experiments/review_stage0/out/summary.json |
| 从日志重建的统计(定位/修复) | data/experiments/review_stage0/out/rebuilt_summary.json |
| 挖掘出的词表 / 规则层明细 | .../out/glossary.json、.../out/rules.json |
| 运行日志 | data/experiments/review_stage0/run_all.log |
素材依赖:媒体库挂载 /mnt/fnOS/123;模型与端点来自 .env(LLM_API_BASE/LLM_API_KEY/
LLM_MODEL)。素材缺失时脚本会直接报错退出(一次性实验,不做跳过)。
八、实验过程中发现的坑(供后续复用)
- 两个 SRT 的 id 都从 1 开始:跨文件统计必须按
(part, id)组键,否则 part1 的 同号条目会冒充 part2 的条目,直接把召回率算错。 - 词表映射不能靠共现:低词频词的共现映射全是噪声(
ビクビク被映射成"小穴"); 必须要求"含该词的 cue 里过半数出现"才采纳,否则词表不可信。 - 系列自身译法就不一致:同一个
おなほ(本系列出现 29 次)在已有译文里被译成 "自慰套/手办/小鼻鼻/嘴"等多种说法——这既是文件夹级上下文的价值,也说明 "惯用译名"本身需要人工或强约束来固定,挖不出来。 - 统计产物会被后续步骤覆盖:区分统计(
summary.json)与原始证据(calls.jsonl), 改口径时用--steps rebuild从日志重算。