feat: 翻译任务支持按任务选词库并通读摘要 - #436
Conversation
任务可显式选用参与匹配的词库,不再只能跟随全局 enabled 开关。
- core: 新增 resolveTaskGlossaryEntries(glossaries, ids)。筛选发生在
normalizeGlossaries 之后、enabled 过滤之前:给了 ids 就按 ids 取(忽略
enabled,关掉的库仍可被显式勾上),没给就按 enabled。两条路径都保持全局
order 排序与「同原文首个胜出」语义,冲突判定不随勾选顺序变化。
- core: 新增纯函数 describeGlossarySource() 生成来源标注,
logGlossaryConflicts / logGlossaryMatches 的 context 追加「任务词库 N 个」
或「全局已启用」,便于排查未命中原因。
- glossaryManager: 新增 getTaskGlossaryResolution(ids);
resolveEnabledGlossaryEntries / getActiveGlossaryResolution 保留为等价包装,
校对链路调用点不受影响。
- translateWithProvider: 已有 10 个位置参数,扩参走尾部 options 对象
({ glossaryIds }),避免错位;未传 options 的调用点日志字节级不变。
- types: IFormData.glossaryIds?: string[]。undefined = 回落全部已启用(旧配方
与历史快照的语义),[] = 明确不用词库,两者全链路不得互相塌缩;非数组的畸形
输入按 undefined 走旧行为。
- renderer: 新增 GlossarySelectControl 配置条多选,未建库时显示「去词库」链接
且不挡开始;停用库标注「已停用」仍可勾选;提供「恢复默认」写回 undefined。
- test: scripts/test-glossary.ts 扩 testTaskGlossarySelection,覆盖 undefined /
[] / 指定 id / 勾中 disabled 库 / order 不随勾选顺序变 / 未知与重复 id /
畸形输入 / 入参不被改写。63 → 87 passed。
任务选用的词库随 sidecar 落盘,校对台的单条优化 / 批量优化 / 重翻失败 三条链路都按任务词库工作,而不再固定读全局已启用。 - types/proofreadData: ProofreadDataMeta 增加 glossaryIds?: string[];meta 归一化 抽出 normalizeProofreadMeta + 纯函数 normalizeMetaGlossaryIds 做边界校验。 非数组 → undefined(旧 sidecar 回落全局已启用),数组只保留字符串成员, [] 保持 [](明确不用词库)。旧 sidecar 归一化后不写出显式 undefined 键。 PROOFREAD_DATA_VERSION 保持 2:meta 是展开合并、未知字段原样保留,无需 bump。 - proofreadData: writeProofreadDataFromFiles 增加 glossaryIds 参数,条件展开写入 meta;fileProcessor 调用点传 formData?.glossaryIds。 - subtitleCorrectionService: CorrectionParams 增加 glossaryIds?, getActiveGlossaryResolution() 改为 getTaskGlossaryResolution(params.glossaryIds); 不传时语义与此前完全一致。correctionRunner 从 formData 透传。 - ipcProofreadHandlers: 三个 handler 的 payload 增加 proofreadDataFile?, 经 readSidecarGlossaryIds 读取 meta.glossaryIds。无路径或读取失败 → 记 warning 并回落 undefined,独立校对模式(直接拖字幕进校对台)行为不变。 - renderer: ProofreadEditor 把 file.proofreadDataFile 透传给 SubtitleEditToolbar、 BatchAiOptimizeDialog 与 useRetranslateFailed,三处 invoke 带上该路径。 - test: 新增 scripts/test-proofread-data.ts 与 yarn test:proofread-data,覆盖 保留显式 id / 保留 [] / 旧 v1 与 v2 sidecar 无该键 / 五种畸形输入 / 非字符串 成员剔除 / 未知 meta 字段前后兼容。32 passed。
Product-level defaultSummaryPrompt plus settings.summaryPrompt with a restore-to-factory control. Translation page is now providers + summary panel. Empty stored drafts fall back to the factory template.
…nslation Add the test:summary seam and the runtime stage: optional per-file read-through before translate, independent AI provider, trivial-file skip, degrade-without-fail, and one-pass system prompt injection. Task UI can toggle the stage; non-AI translation keeps the summary for reference only.
Document task-level glossary selection, the translation-page summary
prompt, ${summary} as an optional placeholder, and the generate-summary
flow on the subtitle translation guide.
… size Plain-text summary calls now set structuredOutput=disabled so json_schema providers do not force the src/tr protocol. Trivial-skip and cost logs use the translation provider's capped batch size, not the summary provider's.
Add summaryFollowLabel, document ${summary} in systemPromptTips, and show
task glossary state plus follow-hint on the snapshot bar. zh/en keys stay
paired; check:i18n passes.
The factory draft no longer asks the summary model to rewrite names into glossary Chinese. Recap stays in the target language; names stay as in the source so later translation batches can align. Glossary appendix is for not inventing extra names. Tests and the enhancement plan follow.
The S01E06 hand-test facts stay. Retract the claim that source names in the summary prove the glossary table was sent. Record whole-episode matching versus per-batch injection, and that keeping source names is now the factory spec (b533bef).
Keep the archived task log with the plan and evidence chain. Drop the step-2 implement handoff; it is process-only and not needed upstream.
buxuku
left a comment
There was a problem hiding this comment.
主要 Findings
-
[P1] 关闭摘要后重跑,旧摘要仍会注入 AI 翻译。
main/helpers/fileProcessor.ts:280-310 清理阶段状态时没有清理 episodeSummary;main/translate/index.ts:197-200 又无条件传入它,最终由 main/translate/services/ai.ts:171-
177 注入 system prompt。用户第一次开启摘要、之后关闭并重跑时,旧摘要仍会影响译文并产生额外 token 成本。应在关闭摘要时清空,或仅在 generateSummary === true 时传递。 -
[P1] resume 快路径会把“未生成摘要”直接标成 done。
main/helpers/fileProcessor.ts:402-440 在已有翻译产物的 pipeline 任务中跳过字幕段,428-432 只要开关开启就发送 summarizeEpisode: 'done',不会调用 runEpisodeSummaryStage。
因此摘要首次失败、或翻译完成后才开启摘要时,重试会显示完成但永远没有摘要。 -
[P1] “不超过 400 字”没有运行时约束。
types/summaryPrompt.ts:15 明确要求 400 字;但 main/helpers/episodeSummaryCore.ts:83-90 接受任意非空响应,main/helpers/episodeSummary.ts:291-315 直接持久化并重复注入。PR
自带日志 summary_glossary_test.log:34 已记录 676 字摘要。应在剥离思考内容后限制、截断或降级,并校验 resume 时复用的旧摘要。 -
[P1] 摘要调用没有使用任务实际的扩展服务商配置。
main/helpers/taskProcessor.ts:191-203,557-579 为正式翻译加载 customParameters;但摘要阶段在 main/helpers/episodeSummary.ts:79-102,270-277 重新从 store 取原始 provider。
自定义 headers/body 参数因此不会传入摘要请求,某些已配置服务商会只在摘要阶段失败并被静默降级。应传入 extendedProvider,或对摘要 provider 也加载 configurationManager 配
置。 -
[P2] 主进程只检查 isAi,没有检查服务商是否已配置。
main/helpers/episodeSummary.ts:79-102 不检查 API key、URL、model 等必填字段。UI 的 TaskControls/TaskWizard 有校验,但 resume 或其他非 UI 路径仍可能发起一个必然失败的摘
要调用。应复用主进程侧的配置校验。 -
[P2] 摘要用量统计丢失 input tokens。
main/helpers/episodeSummary.ts:269-286 明确写入 input_tokens: undefined,只保存 completion tokens。规格要求把 usage 记录到 file.summaryUsage,目前无法排查摘要输入成本。 -
[P1] PR 提交了完整真实字幕、译文和运行环境信息。
docs/docs/summary_glossary_enhancement/summary_glossary_test.log:1-3512 包含整集源字幕/译文、用户本机路径、API endpoint、模型配置以及首批完整 system prompt。即使 API
key 部分遮罩,这仍是版权内容与环境信息泄露风险,不应作为仓库测试证据提交。应改成合成样本或脱敏摘要,并清理历史。
Standards
-
renderer/components/tasks/GlossarySelectControl.tsx:20-23、SummaryGenerateControl.tsx:18-28,44,50、renderer/components/TaskControls.tsx:160-168 新增大量 any/as any,违
反 docs/docs/development.md:87-88 的“TypeScript 类型完整”要求。 -
摘要服务商校验在 TaskControls.tsx、TaskWizard.tsx、SummaryGenerateControl.tsx 重复,属于可能的 duplicated code / shotgun surgery。
-
scripts/test-summary.ts:25 直接导入 renderer helper,跨越 scripts 与 renderer 边界,后续构建环境变化时容易失效。
Spec
- 规格要求摘要 provider 必须是“已配置的 AI 服务商”,实现只保证 isAi。
- 规格要求 resume 时已有摘要才跳过;当前实现会在无摘要时直接标记完成。
- 规格要求保存摘要 usage;实现丢弃 input token。
摘要
启动台「翻译已有字幕」(及共用配置条的其它翻译路径)增加:
glossaryIds三态:未选 = 全部已启用,[]= 不用,显式 id = 含已停用库)不含
dist/、.next/、app/等编译产物。行为要点
summaryProvider缺省跟随翻译服务(须为已配置 AI)meta写入glossaryIds+episodeSummary,不 bump 版本;独立校对回落全局已启用yarn check:i18n通过内部文档(本 PR 一并带上)
docs/docs/summary_glossary_enhancement/summary_glossary_enhance_plan.mddocs/docs/summary_glossary_enhancement/evidence.mddocs/docs/summary_glossary_enhancement/summary_glossary_test.log(S01E06 手测归档,API Key 已脱敏)用户文档:
docs/docs/advanced/glossary.md、custom-prompts.md、features/subtitle-translation.md测试
yarn test:glossaryyarn test:summary(35)yarn test:proofread-datayarn check:i18nA.French.Village.S01E06.eng.srt(647 条 / 13 批),摘要注入首批 system,sidecar 落盘 676 字手测建议