Skip to content

fix(polish): 上下文感知润色限最近 4 轮,消除历史堆积导致的首字延迟 (#678)#682

Open
appergb wants to merge 1 commit into
betafrom
fix/issue-678-polish-context-cap
Open

fix(polish): 上下文感知润色限最近 4 轮,消除历史堆积导致的首字延迟 (#678)#682
appergb wants to merge 1 commit into
betafrom
fix/issue-678-polish-context-cap

Conversation

@appergb

@appergb appergb commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

User description

关联 issue

Closes #678

问题

1.3.6 起非 Raw 润色默认把最近 5 分钟内的全部历史轮前置进 LLM 请求:

  • types.rs:828 默认窗口 5 分钟(开箱即开);
  • coordinator/dictation.rs::eligible_polish_context_turns 末尾直接 .collect()不限条数

历史越多 → 输入 token 越多 → 首 token 时间越长。在默认流式插入下,TTFT 就是「光标出现第一个字」的时刻 → 面向全体用户表现为转写变慢(约 +1s 量级,越重度越明显)。

改动(单一职责)

  • 新增常量 MAX_POLISH_CONTEXT_TURNS = 4
  • eligible_polish_context_turns.collect() 前加 .take(MAX_POLISH_CONTEXT_TURNS)sessions 为 newest-first(recent_within_minutes 保证),take 保留最近 4 轮build_polish_history_messages.rev() 成时序——顺序正确。
  • 把无界的上下文拼接收敛为常数量级,仍保留多轮连续性。

取值 4 偏向延迟优先、可调;未改时间窗口、未动其他逻辑。

测试

cargo test --lib coordinator::dictation
  polish_context_is_capped_to_most_recent_turns ... ok
  (其余 15 个 dictation 单测全绿,未受影响)

新测断言:堆积 7 条历史时只返回最近 4 轮(newest-first 的前 4 条)。

来源:2026-06-16 全仓多 Agent 审计(延迟专项)。注:另有一条仅影响 Windows 本地 sherpa 在线模型的冷加载延迟,单独跟进。


PR Type

Bug fix


Description

  • Limit polish context turns to 4 (MAX_POLISH_CONTEXT_TURNS).

  • Add unit test to verify capping behavior.


Diagram Walkthrough

flowchart LR
  HistoricalSessions["Historical Sessions (newest-first)"] -- ".take(4)" --> Capped["4 most recent turns"] --> BuildMessages["build_polish_history_messages .rev()"] --> LLMRequest["LLM request (capped tokens)"]
Loading

File Walkthrough

Relevant files
Bug fix
dictation.rs
Cap polish context turns to 4, add test                                   

openless-all/app/src-tauri/src/coordinator/dictation.rs

  • Added constant MAX_POLISH_CONTEXT_TURNS = 4.
  • Applied .take(MAX_POLISH_CONTEXT_TURNS) before collect() in
    eligible_polish_context_turns.
  • Added unit test polish_context_is_capped_to_most_recent_turns to
    verify capping.
+40/-1   

1.3.6 起非 Raw 润色默认把最近 5 分钟内「全部」历史轮前置进 LLM 请求
(types.rs 默认窗口 5 分钟,eligible_polish_context_turns 不限条数)。历史
越多、请求越长、首 token 越慢——流式插入下这正是「出第一个字」的时刻,
于是面向全体用户表现为转写变慢。

给 eligible_polish_context_turns 增加硬上限 MAX_POLISH_CONTEXT_TURNS=4:
sessions 为 newest-first,take 保留最近 4 轮,把无界的上下文拼接收敛为常数
量级,同时保留多轮连续性。附单测验证超量历史只回看最近 N 轮。
@appergb

appergb commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator Author

@claude 请审核:给上下文感知润色加最近 4 轮硬上限以消除历史堆积导致的首字延迟。重点看 (1) take(4) 作用在 newest-first 序列上是否确实保留「最近」N 轮、与 build_polish_history_messages 的 .rev() 配合后时序是否正确;(2) 取值 4 是否合理,是否该改成可配置(prefs)。另注:仅 Windows 本地 sherpa 在线模型的冷加载延迟是另一条路径,会单独提 PR。

@claude

claude Bot commented Jun 16, 2026

Copy link
Copy Markdown

Claude finished @appergb's task in 2m 37s —— View job


代码审核结论

  • 读取 PR 变更差异
  • 分析 eligible_polish_context_turnstake(4) 的顺序逻辑
  • 分析与 build_polish_history_messages.rev() 的配合
  • 评估常量值 4 及可配置性
  • 发布审核结论

问题一:take(4) 是否正确保留「最近」N 轮,时序是否正确?

结论:逻辑正确。

数据流如下:

阶段 代码位置 顺序
recent_within_minutes 返回结果 persistence.rs:1220-1227 newest-first(注释明确 + take_while 依赖此约定)
eligible_polish_context_turns 过滤 + take dictation.rs:2519-2544 维持 newest-first,.take(4)filter_map 之后,保留最近 4 条符合条件的
LLM 消息构建(OpenAI 路径) polish.rs:1227 .iter().rev() → oldest-first → 时序正确
LLM 消息构建(Gemini 路径) llm_gemini.rs:439 .iter().rev() → oldest-first → 时序正确

.take(MAX_POLISH_CONTEXT_TURNS) 作用在 filter_map 之后,语义是「最多保留 4 条通过所有过滤器的轮次」,而非「扫描最多 4 个原始 session 再过滤」——这更符合直觉,结果也正确。

一个隐性合约值得记录recent_within_minutes 内部用 take_while 而非 filter,依赖底层存储严格 newest-first。一旦该契约被打破(如并发写入或数据库修复后插入顺序乱掉),take_while 会静默截断,take(4) 随之保留到错误的轮次——但这是预存在风险,不是本 PR 引入的。


问题二:常量值 4 是否合理,是否应改为可配置?

值 4 本次可接受;可配置性建议作后续 PR。

合理性分析:

  • 4 轮 = 8 条 LLM message(user+assistant 各一条),转写场景每条通常一到两句,累计额外 token 约 100–300,但扩大到重度用户每天数百次触发时,削减效果显著。
  • 时间窗口(5 分钟)与轮数上限(4 轮)是两个正交旋钮:前者已作为 pref 暴露,后者此处硬编码——对延迟优先的场景是合理起点。

关于可配置性:

  • 项目里 prefs.polish_context_window_minutes 已经是用户 pref,风格一致的话 max_polish_context_turns 也可以加进去,让重度用户自行权衡延迟与连贯性。
  • 但作为修复 regression 的单一职责 PR,当前硬编码的选择是务实的——避免同时扩展 prefs schema。建议在后续 polish 体验迭代时一并加入。

测试覆盖的一个小盲区

现有新测用例 polish_context_is_capped_to_most_recent_turns 验证了「堆积 > 上限时截断为 4」的场景,是对的。但存在一个未覆盖的边界:

若部分 session 因 error_code 非空或 style_pack_id 不匹配被 filter/filter_map 淘汰,且淘汰后剩余数量 < 4,结果应该是 < 4(不是 4)。

这个行为实际上是正确的(.take() 在 filter 之后),但没有测试断言它。如果将来有人误将 .take() 移至 filter 之前,测试不会抓住这个 bug。可考虑补一个:

// 7 条中 3 条因 error_code 过滤,有效 4 条 —— 不应再被 take 截断
assert_eq!(turns.len(), 4);  // 恰好等于上限,确认 take 在 filter 之后生效

当然,这是锦上添花,不影响本 PR 正确性。


整体结论

可以合入。 修改逻辑正确、作用位置正确、时序正确、测试通过。唯一的后续行动项:

  1. (低优)补充「filter 减少 eligible 数量时 take 不会过度截断」的测试用例。
  2. (中优)后续版本将 max_polish_context_turns 作为用户 pref 暴露,与 polish_context_window_minutes 对齐。

@github-actions

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

678 - Partially compliant

Compliant requirements:

  • 条数上限已实现(取最近 4 轮)。
  • 新增单测验证条数上限。

Non-compliant requirements:

  • 可选的历史读取缓存未实现。

Requires further human verification:

  • 手测对比修复前后首字延迟(无法通过代码审查验证)。
⏱️ Estimated effort to review: 1 🔵⚪⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

@HKLHaoBin

Copy link
Copy Markdown
Contributor

PR 合并冲突提示(听写模块)

本 PR 与 #692#688#666 均修改了 openless-all/app/src-tauri/src/coordinator/dictation.rs。

实测结论:

建议: 合并前与 #666 作者确认顺序,避免一方已合入后另一方 rebase 成本突增。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[perf] 润色默认拼接 5 分钟内全部历史轮且不限条数,拖慢首字延迟(影响全体用户)

2 participants