# 实验数据:字幕审校(问题定位 + 定向修复) 本文件记录"用 LLM 定位有问题的字幕 cue,再定向修复该 cue"这一方案的**实测数据与结论**。 方案背景与需求见 [待办-翻译上下文复用与语义纠错.md](./待办-翻译上下文复用与语义纠错.md), 结论的取舍理由见 [decisions.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. **规则层**(对照用):`① 词表违背`(日文用了词表词但译文没体现该译名)、 `② 近音可疑`(日文里出现与词表词同长度、编辑距离 ≤1 的片段,且译文没体现该译名)。 2. **定位层 V1**:只给**中文**(`id|时间|译文`)+ 系列词表,让 LLM 找出"与上下文不符、 逻辑不通、或与词表不一致"的条目。**这就是"纯 LLM 智力定位"的原设计**。 3. **定位层 V2**:给 **中文 + 日文原文** + 系列词表,让 LLM 找"译文与日文原意不符 (含近音听错)、上下文矛盾、与词表不一致"的条目。 4. **修复层**:只对目标 cue,给 `日文原文 + 现有译文 + ±2 邻句(日文+中文)+ 系列词表`, 要求返回窗口内**全部 id** 的译文(允许顺带改邻句,禁止增删条目)。 5. **合成正样本**:把正常译文里的域词替换成中性词(小穴→肚子/声音/苹果…), 制造"字面通顺但语义错"的样本,测定位召回。 --- ## 三、实测结果 ### 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%)决定成本,也决定"改坏正常句"的风险面。 --- ## 五、结论与原因分析 1. **有效面**:术语/忠实性类(`词表违背`、译文与日文不一致、上下文称呼跳变)—— 修复正确率高(51/55 明显变好),合成正样本召回 79%。这部分即使单独做也有价值。 2. **无效面(问题 A)**:`字面通顺但语义错`。原因不是"上下文给得不够": - 定位阶段:中文通顺 ⇒ 模型不怀疑日文中的错词(183 在 V1/V2 都没被标出); - 修复阶段:唯一可依据的日文原文本身是错的 ⇒ 模型沿错译走,只能换词(肚子→身体), 不能凭空生成正确含义。这与待办文档里记录的两次失败实验(纠错节点、 提示词 A/B)结论一致。 3. **副作用**:允许改邻句会脑补出新意思(48 从"肚子饿了"改成"小穴要湿了"), 需要"必须给出日文依据/候选词才允许改动"的硬约束。 4. **判定**:**当前 LLM 能力不足以完成"从错误的日文原文反推真实含义"这一步**, 方案暂缓;不再在翻译侧继续做语义纠错。 --- ## 六、未验证的下一步(若将来重开) 按"换提问对象、换判据"而非"加规则"的思路,三条可测方向: 1. **不审译文,审日文**:只给日文 + 系列词表,逐条问"这句像不像把某个词听成了另一个 常见词?给出候选词"。这样中文的通顺度再也掩盖不了问题(183 的 `おなか` 在 "本系列 `おなほ` 出现 29 次"的语境下有机会被标出并给出候选 `おなほ`)。 2. **先建场景再对照**:让 LLM 通读一个场景的日文,总结"在做什么、用了哪些道具/称呼", 再用这份场景模型审中文(针对"进入肚子里"这类与动作链矛盾的句子)。 3. **召回优先的提问**:把"找出有问题的条目"改为"逐条给可疑度 0–3 打分 + 理由", 避免"只有读不通才报"的偏置,用阈值调触发率。 4. 配套约束:修复必须能指出**日文依据或候选词**才允许改动正文,否则拒绝改写。 第 1、2 条本质上是把纠错从**翻译侧**挪回**ASR 侧**(那里才有声学证据)。 --- ## 七、复现方式 ```bash # 全流程(规则层 + 定位 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` 从日志重算。