docs: 注释规范要求精简可读,并清理生产代码中的历史叙事
AGENTS.md 的注释规范新增三节可执行约束:
- 只写代码真实逻辑:注释只回答"做什么"与"为什么必须这么做",禁止写决策/
修改时间、历史版本对比、实测数据与实验结论、事故与缺陷编号(run_xxxx /
batch_xxxx / R01 等)——这些属 docs/decisions.md 与审查跟踪文件;当前生效
的约束可以写,但不附带它何时因何变成这样。
- 精简可读:单段连续注释不超过 3 行;docstring 一句话概括职责,不重复函数名
已表达的信息;不写逐行翻译代码的废话注释,只在非显然处(业务规则、边界、
易错点、外部约束)加注。
- 覆盖范围:测试注释只说明验证什么行为,回归用例可保留一句溯源;并明确
参数说明应写在**参数读取处**附近,而不是把多个参数的解释堆在离使用位置
很远的注释块里。
按此清理生产代码(注释净减 70 行,18 个文件),典型处理:
- nodes/whisper.py:删掉堆在一起、含"用户 2026-08 决定 / 实测 savr-1054"
等叙事的参数块,把各参数说明移到各自的读取处与 model.transcribe 调用处;
- nodes/llm_filter.py、nodes/subtitle_cleanup.py:模块 docstring 去掉英文
背景叙事与条数统计,保留"默认只跑规则层""整条删除而非 '-' 占位"等当前
行为;
- src/wov_app/{batch,db,scheduler}.py 与 routers:去掉 batch_xxx/run_xxx 事故
编号与"修复前……"对比,改为一句"否则会出现什么问题";
- nodes/ass.py、frame_extract.py:去掉废弃值对比与日期,保留判据本身。
安全验证:用 AST 对比(剥离 docstring 后比较语法树)确认 18 个文件**零逻辑
变更**;`nodes/proper_nouns.py` 的规则表 reason 字段会注入 LLM 提示词,属于
数据而非注释,已恢复原值。全量测试 476 passed。
This commit is contained in:
+19
-39
@@ -1,28 +1,18 @@
|
||||
"""Subtitle cleanup: remove long-duration closing/greeting hallucinations.
|
||||
"""字幕清洗:删除寒暄幻觉与纯呻吟碎片。
|
||||
|
||||
Background (real run 20260905115050): after fixing the timing alignment,
|
||||
subtitles still contain "closing/greeting hallucination words" - fixed
|
||||
phrases like 'wan an / gan xie guan kan / gan xie nin de guan kan'
|
||||
(good night / thanks for watching) that the ASR/LLM repeatedly emits on
|
||||
empty segments, filling a full 30s block, unrelated to video content.
|
||||
Some 2s 'good night' might be real dialogue, so it must be kept.
|
||||
|
||||
处理策略(2026-09 用户确认改为"整条剔除"):
|
||||
幻觉识别出后(展示时长 ≥ 阈值 且 文本命中套话词表),应**连带时间戳把整条
|
||||
字幕 cue 删除**(剩余条目重新编号),而不是把文本替换成 '-' 占位留给下游——
|
||||
占位会一路流到 ASS 渲染成可见的"减号"、在翻译/过滤阶段都要额外特殊处理,
|
||||
处理位置绕且不彻底。因此清洗统一为:**在幻觉产生处(whisper 转录后 / LLM
|
||||
翻译后)整条删除**,时间轴随之消失,字幕序号重新连续编号。
|
||||
ASR(whisper 无 VAD 解码)与 LLM 翻译在无语音段会输出固定套话(如“晚安/
|
||||
感谢观看”/“おやすみなさい”),且在翻译产物里反复出现。处理方式为**连带
|
||||
时间戳整条删除** cue 并重新编号:不能改成 '-' 占位,否则会一路渲染成可见
|
||||
减号,并在翻译/过滤阶段需要额外特判。
|
||||
|
||||
两类词表:
|
||||
- HALLUCINATION_TOKENS:中文(LLM 翻译产物中的寒暄,如"晚安/感谢观看");
|
||||
- JAPANESE_HALLUCINATION_TOKENS:日文(whisper decode_full 无 VAD 解码在
|
||||
无语音段直接输出的套话,如"おやすみなさい/ご視聴ありがとうございました")。
|
||||
- HALLUCINATION_TOKENS:中文(LLM 翻译产物中的寒暄);
|
||||
- JAPANESE_HALLUCINATION_TOKENS:日文(whisper 无 VAD 解码直接输出的套话)。
|
||||
|
||||
阈值从真实运行实测数据判定:30s 幻觉占位 vs 2s 真实词,分界明显,
|
||||
默认 threshold=15s(≥15s 才删除;<15s 的相同词可能是剧情真实道晚安,保留)。
|
||||
删除只针对展示时长 ≥ 阈值的长条目:短时相同词可能是剧情真实台词(如真实
|
||||
互道晚安),必须保留。另外删除纯呻吟/喘息碎片(判据见 _is_pure_moan)。
|
||||
|
||||
Pure functions, unit-testable (tests/test_hallucination_mask.py).
|
||||
纯函数,不修改输入。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -39,11 +29,8 @@ HALLUCINATION_TOKENS = (
|
||||
# Display-duration threshold (seconds): only remove entries longer than this.
|
||||
DEFAULT_THRESHOLD_SECONDS = 15.0
|
||||
|
||||
# 日文 ASR 直出(whisper 节点 decode_full 无 VAD 整段解码)的收尾/寒暄幻觉词。
|
||||
# 无 VAD 解码会把无语音/音乐/呻吟段当语音,whisper 常在这些段重复输出套话
|
||||
# (实测 savr-1054 全片 119-149s/600-630s 等出现 30s 长"おやすみなさい"
|
||||
# "ご視聴ありがとうございました")。短时(≤阈值)的相同词可能是剧情里真实
|
||||
# 互道晚安,须保留;仅删除展示时长 ≥ 阈值的条目(与中文表同一机制)。
|
||||
# 日文套话词表:whisper 无 VAD 解码会把无语音/音乐段当语音,从而重复输出
|
||||
# 这些寒暄;短时相同词可能是剧情真实台词,靠时长阈值区分(同中文表机制)。
|
||||
JAPANESE_HALLUCINATION_TOKENS = (
|
||||
"おやすみなさい", # 晚安
|
||||
"ご視聴ありがとうございました", # 感谢观看
|
||||
@@ -58,14 +45,10 @@ JAPANESE_HALLUCINATION_TOKENS = (
|
||||
"Thank you for watching",
|
||||
)
|
||||
|
||||
# 纯呻吟/喘息字符集合(decode_full 救回弱语音后的去噪,2026-09 用户决策)。
|
||||
#
|
||||
# 背景(实测 savr-1054-2 前 600s):decode_full 无 VAD 解码会把呻吟/BGM 混叠
|
||||
# 的弱语音也整段救回,但其中混有大量**纯语气词碎片**(あ…/ん?/はぁ…/あ!あ!
|
||||
# /んふふ 等),这类内容放进字幕是噪声。判据:文本(去空白/标点)**全部由本
|
||||
# 集合字符组成**且有效假名数 ≤ 阈值才删除。集合**刻意排除** そ/こ/ね/や/ば/だ
|
||||
# /く/へ 等假名——真实短对话(そこ/やばい/ねえ/やだ/えへへ)都含这些字符,
|
||||
# 含任意非集合字符的条目天然不命中,从根上避免误删真实短句。
|
||||
# 纯呻吟/喘息字符集合:文本(去空白/标点)全部由本集合字符组成、且有效假名数
|
||||
# ≤ 阈值时才判为噪声删除。集合**刻意排除** そ/こ/ね/や/ば/だ/く/へ 等假名——
|
||||
# 真实短对话(そこ/やばい/ねえ/やだ/えへへ)都含这些字符,因此天然不命中,从
|
||||
# 判据根源上避免误删真实短句。
|
||||
MOAN_CHARS = frozenset(
|
||||
# 平假名元音与ん/ふ/は(呻吟与喘息气流音的主干)
|
||||
"あいうえおんふはっ"
|
||||
@@ -144,12 +127,9 @@ def remove_short_moan_entries(
|
||||
) -> str:
|
||||
"""删除 SRT 中'纯呻吟/喘息碎片'的**整条 cue**(whisper decode_full 去噪)。
|
||||
|
||||
decode_full 无 VAD 解码会把呻吟也整段救回,字幕混入大量纯语气词碎片
|
||||
(あ…/ん?/はぁ…)。判据:文本全部由 MOAN_CHARS 组成且有效假名数 ≤
|
||||
max_chars(默认 3)才删除(见 _is_pure_moan),真实短对话(そこ/やばい/
|
||||
ねえ/やだ/えへへ/行く行く行く)天然不命中。max_chars=0 时关闭过滤(原
|
||||
样返回)。仅在 whisper 节点 decode_full=true 时调用(用户 2026-09 决策,
|
||||
不作用于 learn-translate 等 VAD 链路)。纯函数,不修改输入。
|
||||
无 VAD 解码会把呻吟段也整段救回,字幕因此混入纯语气词碎片(あ…/ん?)。
|
||||
判据见 _is_pure_moan:文本全部由 MOAN_CHARS 组成且有效假名数 ≤ max_chars
|
||||
才删除;max_chars=0 时关闭过滤。纯函数,不修改输入。
|
||||
"""
|
||||
if max_chars <= 0:
|
||||
return srt_text
|
||||
|
||||
Reference in New Issue
Block a user