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:
+18
-26
@@ -225,28 +225,22 @@ def invoke(request: InvokeRequest) -> InvokeResponse:
|
||||
device=device,
|
||||
compute_type=compute_type,
|
||||
)
|
||||
# language 默认日语;vad_filter 默认开启(用户 2026-08 决定):过滤静音
|
||||
# 段以提速并减少无语音处幻觉;长静音时 VAD 压缩时间轴可能轻微错位,
|
||||
# 如需极致对齐可在工作流参数中显式关闭。
|
||||
# decode_full=true(默认 false):VAD 对呻吟/轻语/BGM 混叠声学切段会
|
||||
# 把真话当非语音剔除(实测 savr-1054 全片仅召回 115 条),开启后强制
|
||||
# 无 VAD 整段解码(vad_filter=False 且跳过自动 VAD 分析)以召回弱语音,
|
||||
# 代价是无语音段会产生长时套话幻觉,由下方日语幻觉清洗兜底移除。
|
||||
# 另:decode_full 救回的弱语音中混有纯语气词碎片(あ/ん?等),由
|
||||
# short_moan_max_chars(默认 3,0=关闭)参数控制短呻吟整条删除。
|
||||
# task 默认 transcribe,中文直出模型可传 translate 直接翻译为目标语言。
|
||||
# condition_on_previous_text 默认 False:长音频下开启会导致重复/漂移,
|
||||
# 关闭后每个 30s 窗口独立解码,是 faster-whisper 官方建议的长音频方案。
|
||||
# 常用参数默认值见各参数的读取处;完整参数手册见
|
||||
# workflows/learn-translate.json 的 params._node_help。
|
||||
output_dir = Path(request.output_dir)
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
# 分块转写:默认每 1 分钟一块(chunk_seconds=60),切块失败自动回退整段。
|
||||
chunk_seconds = int(request.params.get("chunk_seconds", 60))
|
||||
chunks = _split_audio(audio_path, output_dir, chunk_seconds, _ffmpeg_bin())
|
||||
# decode_full 时强制无 VAD:不传 vad_filter/vad_parameters,也不跑自动 VAD
|
||||
# 分析(分析结果对呻吟/轻语类音频无效,只会把整块切碎/剔除真话)。
|
||||
# decode_full:忽略 vad_filter 与 vad_parameters,整段无 VAD 解码以召回
|
||||
# 被 VAD 当非语音剔除的弱语音(代价是无语音段产生长时幻觉,由末尾清洗
|
||||
# 处理)。为 False 时是否启用 VAD 由下方 vad_filter / 自动分析决定。
|
||||
decode_full = bool(request.params.get("decode_full", False))
|
||||
vad_parameters = request.params.get("vad_parameters")
|
||||
# 默认开 VAD:滤掉静音段提速并减少无语音处幻觉;代价是长静音下时间轴
|
||||
# 会被压缩回映射,需极致对齐的素材可显式关掉。
|
||||
vad_filter = bool(request.params.get("vad_filter", True))
|
||||
# 未显式给参且开启 VAD 时,按音频信号分析自动推荐参数(可 WOV_AUTO_VAD=0 关)。
|
||||
if not decode_full and vad_filter and not vad_parameters and os.getenv("WOV_AUTO_VAD", "1") == "1":
|
||||
try:
|
||||
from nodes.vad_profiler import vad_parameters_for_audio
|
||||
@@ -278,14 +272,18 @@ def invoke(request: InvokeRequest) -> InvokeResponse:
|
||||
if (Path(request.output_dir).parent.parent / PAUSE_FLAG).exists():
|
||||
raise RuntimeError(f"whisper 被暂停(run {request.run_id})")
|
||||
chunk_started = time.monotonic()
|
||||
# decode_full=true 时 vad_filter 传 False:跳过 VAD 剔除弱语音段。
|
||||
segments, _info = model.transcribe(
|
||||
str(chunk),
|
||||
# 源语言默认日语;中文直出模型配合 task=translate 可直接出中文。
|
||||
language=str(request.params.get("language", "ja")),
|
||||
task=str(request.params.get("task", "transcribe")),
|
||||
# beam_size=1(贪心)足够且最快,提高只对难句有微弱收益。
|
||||
beam_size=int(request.params.get("beam_size", 1)),
|
||||
# decode_full 时关闭 VAD,跳过对弱语音段的剔除。
|
||||
vad_filter=False if decode_full else vad_filter,
|
||||
vad_parameters=None if decode_full else vad_parameters,
|
||||
# 默认 False:长音频下开启会累积上下文导致重复/漂移,
|
||||
# 关闭后每个 30s 窗口独立解码。
|
||||
condition_on_previous_text=bool(
|
||||
request.params.get("condition_on_previous_text", False)
|
||||
),
|
||||
@@ -302,17 +300,9 @@ def invoke(request: InvokeRequest) -> InvokeResponse:
|
||||
chunk_seconds / chunk_elapsed if chunk_elapsed > 0 else 0.0,
|
||||
time.monotonic() - transcribe_started,
|
||||
)
|
||||
# decode_full(无 VAD)副作用:无语音/音乐/呻吟段会产生长时寒暄套话幻觉
|
||||
# (おやすみなさい/ご視聴ありがとうございました 等),在此**连带时间戳整条
|
||||
# 剔除**(序号/时间轴/文本全删、剩余重编号),不留下 '-' 占位污染下游
|
||||
# (占位会渲染进 ASS 成减号、翻译/过滤都要额外处理);短时(≤15s)相同词
|
||||
# 可能是剧情真实道晚安,保留。见 nodes/subtitle_cleanup.py。
|
||||
# 其次(2026-09 用户决策):decode_full 也会把呻吟/BGM 混叠的弱语音整段
|
||||
# 救回,其中混有大量**纯语气词碎片**(あ…/ん?/はぁ…/あ!あ!/んふふ 等),
|
||||
# 这类噪声影响字幕观感;在此按'全部字符∈纯呻吟集合 且 有效假名≤max_chars'
|
||||
# 判据**整条删除**(remove_short_moan_entries),真实短对话(そこ/やばい/
|
||||
# ねえ/やだ)天然不命中。仅 decode_full 生效,learn-translate 等 VAD 链路不受影响;
|
||||
# 参数 short_moan_max_chars 可调(默认 3,设 0 关闭)。
|
||||
# decode_full(无 VAD)的副作用清理:无语音段的长时寒暄幻觉与纯语气词
|
||||
# 碎片都是噪声,整条删除(序列号重排,不留 '-' 占位污染下游);判据与
|
||||
# 细节见 nodes/subtitle_cleanup.py。仅 decode_full 时启用。
|
||||
if decode_full:
|
||||
from nodes.subtitle_cleanup import (
|
||||
clean_japanese_hallucinations,
|
||||
@@ -320,6 +310,8 @@ def invoke(request: InvokeRequest) -> InvokeResponse:
|
||||
)
|
||||
|
||||
body = clean_japanese_hallucinations("\n".join(lines))
|
||||
# short_moan_max_chars:有效假名 ≤ 该值的纯呻吟碎片整条删除,
|
||||
# 设 0 关闭(真实短对话不会命中,判据见 subtitle_cleanup)。
|
||||
body = remove_short_moan_entries(
|
||||
body,
|
||||
max_chars=int(request.params.get("short_moan_max_chars", 3)),
|
||||
|
||||
Reference in New Issue
Block a user