[BUG] AI 分句复用字幕翻译的 provider 配置,temperature 无法为分句独立设置
Before you report
- I have searched existing issues to avoid duplicates
- I have tried with the latest available version (or can reproduce on latest)
Current vs. Expected behavior
本 issue 已在复测后修正。 原始版本把截图现象归因为「两条 cue 同时在屏」,该归因经实测证伪并已移除,修正说明见文末。本 issue 现聚焦 temperature 无法为分句独立设置这一设计问题。
runAiSegmentSubtitles 与字幕翻译共用同一份 provider 配置,因此 provider 上的 temperature
会被原样应用到分句调用,无法为分句单独设置。
但分句不是翻译任务。按 DEFAULT_SUBTITLES_SEGMENTATION_SYSTEM_PROMPT 的 rule 3,模型要做的
是确定性查表:找句子第一个词的 s、最后一个词的 e,输出 s --> e。这是 argmax 该做的事,
不是 sampling 该做的事。为翻译自然度调高的 temperature(DeepSeek 官方对翻译的推荐值是 1.3)
会直接降低这个结构化抽取任务的稳定性。
调用链已逐行核实:
aiSegmentBlock(utils/subtitles/processor/ai-segmentation.ts)复用 session 的videoSubtitlesproviderRef —— 函数上方的注释说明这个复用是有意为之(为省一次hostedAi.status往返)。generateTextForProviderRef(entrypoints/background/background-stream.ts:725)的 destructure 不包含temperature。- 同文件
:773,...buildLocalGenerateTextParams(providerRef.config)在generateText()的参数对象里最后展开,会覆盖前面设置的任何同名字段。 buildLocalGenerateTextParams(utils/providers/generate-params.ts)返回temperature: config.temperature。
因此在 payload 里传 temperature 是无效的,必须在调用点替换 ref 携带的 config。
影响范围: 只影响 local / 自定义 provider。hosted 路径(providerRef.kind === "system")
走 createHostedTextPartStream,根本不传 temperature,用内置 provider 复现不出来。
预期行为: 分句应跑在适合结构化抽取的 temperature 上,与用户为翻译选择的值解耦。
补充观测:temperature 不是唯一因素。
在同一视频、同一时间点分别用 temperature 1.3 与 0.3 复测,分句边界每次都不同(说明
aiSegmentationCache 正常 miss、确实重新采样),但两个 temperature 下都稳定产出畸形结果。
所以降低 temperature 能提升稳定性,但不足以单独解决问题 —— 分句 prompt 本身在词级输入上对
轻量模型要求过高(实测单次请求 187 个词级碎片 / 8110 字符 JSON / 覆盖 60 秒,要求逐词对齐
毫秒时间戳)。
相关的健壮性缺口
分句结果在进入缓存和渲染前没有任何一层校验,采样噪声造成的畸形输出会被完整放行:
parseSimplifiedVttToFragments(utils/subtitles/processor/ai-segmentation.ts)零校验 —— 不检查时间戳单调性、不检查区间重叠、不检查 rule 8 要求的 "No omission" 覆盖度。而且 prompt 里没有任何一条禁止重复,所以同一源片段进多条 cue 是完全放行的。runAiSegmentSubtitles(entrypoints/background/ai-segmentation.ts)写 cache 的唯一闸门是parseSimplifiedVttToFragments(result).length === 0—— 只要有一条 cue 就算通过。replaceProcessedChunk(entrypoints/subtitles.content/segmentation-pipeline.ts)删除旧 cue 用的是原始 chunk 的[chunkStart, chunkEnd),但 push 进去的是模型生成的 fragments, 没有 clamp 回这个窗口。
这三点独立于 temperature 成立。
To Reproduce
- 配置一个自定义 OpenAI-compatible provider(如 DeepSeek),在 provider 设置里把 temperature 调到 1.0 或更高。
- 把它分配给视频字幕,开启 AI 分句。
- 播放一个带 word-level 自动字幕(
scrolling-asr格式)的 YouTube 视频。 - 观察分句结果的时间戳与边界质量。
Which area(s) are affected? (Select all that apply)
Other
Extension version (if applicable)
1.46.0
Provide environment information
- Extension channel/version: Chrome Web Store 1.46.0
其余无关Additional context
最小修复 —— 在分句调用点 clone 一份 ref:
const segmentationRef = providerRef.kind === "local"
? { ...providerRef, config: { ...providerRef.config, temperature: 0 } }
: providerRef(config 必须单独展开一层,浅拷贝会让副本与原对象共享同一个 config 引用。)
或者给 generateTextForProviderRef 增加一个显式的 temperature override 参数,在 spread 之后
生效。
建议同时加一个校验层,在写 cache 之前拒绝 start 非单调、区间重叠、或同一源片段出现在多条
cue 里的结果。目前坏结果会被写进 db.aiSegmentationCache,同一 config 下重放同一视频会一直
命中它。
更彻底的做法是不让模型产出时间戳:让它只返回句子边界在输入数组里的索引,时间戳由代码
回查。这样 end < start、区间重叠、片段重复在结构上都不可能发生,与 temperature 无关,顺带
可以删掉 prompt 里那段很长的 WRONG/CORRECT 示例。这与 #2100 提到的「词级时间戳不该在管线中途
被丢弃」是同一个方向。
修订说明(复测后)
原始版本把截图里「上下两段内容相同、措辞不同」归因为两条 cue 同时在屏,并推论「同一批源 片段被分配进了两条 cue、各翻译了一次」。该归因经实测证伪:
displaySubtitleAtom(entrypoints/subtitles.content/atoms.ts)用.find()返回单个 fragment;MainSubtitle与TranslationSubtitle读取的是同一个 fragment 的.text与.translation。渲染层在架构上不可能同时显示两条 cue。- 在页面上直接读取 shadow DOM 实测:
.subtitles-main与.subtitles-translation在 DOM 中 各只有一个元素。
该现象的真实成因是 AI 分句阶段模型翻译了原文,使 fragment.text 本身变成目标语言;双语
模式下原文行因此显示译文,译文行则是对已译文本的二次翻译。已另开 issue 单独跟踪:#2101。
相关:#2100(超长 cue,根因不同)
需要可以提 PR
Source: mengxi-ream/read-frog