Files
openless/docs/qa-reasoning-roadmap.md
T
baiqing 6e49281519 feat(qa): v2 多轮对话 + 流式输出 + macOS 浮窗修复
issue #118 v2 完整闭环。

## 多轮对话
- QaSessionState 加 messages: Vec<QaChatMessage> + panel_visible flag。
- Cmd+Shift+/ 现在 toggle 浮窗可见性(不再启动录音);浮窗可见时 rightOption
  路由到 QA recording,不可见时仍是主听写。open_qa_panel / close_qa_panel 分离。
- 第一轮 user message 嵌选区原文(# 选区原文 / # 我的问题),之后只送提问。
- 前端 QaPanel 渲染气泡列表(user 蓝色靠右 / assistant 灰色 markdown 靠左)。

## 流式输出
- chat_completion_history → chat_completion_history_streaming:开 stream:true
  + SSE chunk 解析,on_delta 回调把每 chunk emit 成 qa:state{kind:"answer_delta"}。
- 前端 streamingAnswer state + StreamingAssistantBubble(带蓝色闪烁 caret)。
- answer 事件落定后清空 buffer,最终 messages 接管。

## macOS 浮窗修复(v1 一直存在的雷)
- capabilities/default.json 加 "qa" 到 windows 数组。否则前端 listen("qa:state")
  被 Tauri 权限拦截,浮窗永远收不到事件。
- show_qa_window 用 NSWindow.orderFrontRegardless 替代 window.show()
  (后者在 macOS 走 makeKeyAndOrderFront 抢 frontmost)。这样 capture_selection
  的 AX read / Cmd+C fallback 能稳定从原 app 读到选区。
- 所有 ObjC msg_send 必须 wrap 进 app.run_on_main_thread —— macOS 26 对
  NSWindow 主线程要求是硬断言(违反直接 SIGTRAP)。
- NSWindow.movableByWindowBackground=YES:浮窗任意空白处可拖。
- QA hotkey 注册在主线程:global-hotkey crate 在 macOS 用 Carbon
  RegisterEventHotKey,事件回调要靠主 run loop dispatch。

## 胶囊状态同步
- QA 录音 / 转写 / 思考 同步推 capsule:state,让用户在底部胶囊也看到状态。
- schedule_capsule_idle 同时检查 dictation 和 QA 都 Idle 才隐藏,避免旧
  dictation Done timer 把 QA 的胶囊误关。
- open_qa_panel 进入时先 emit Idle 清掉 dictation 残留 message + insertedChars。

## 设置页
- SelectionAsk 独立成一级 tab;预设减到 4 个 cmd+shift+ 系列(Option 跟主听写
  共用,不放进 QA hotkey)。
- howto / hotkey / privacy 文案重写,反映 v2 的「先开浮窗、再 Option 录音」流程。
- prefs 默认 qaHotkey = cmd+shift+;。

## 后续路线图
- docs/qa-reasoning-roadmap.md:思考能力 v2.2 设计稿(C 路线 reasoner model
  切换 + reasoning_content delta + 折叠思考块)。
2026-05-01 17:40:22 +08:00

3.7 KiB
Raw Blame History

划词追问:思考能力(Reasoning)路线图

创建于 2026-05-01。流式输出(v2.1)已完成,思考能力(v2.2)暂未实施——这份文档是后续迭代的设计稿。

关联:issue #118 v2、PR #119、openless-all/app/src-tauri/src/polish.rs、openless-all/app/src/pages/SelectionAsk.tsx。

背景与决策

用户提出:"QA 应该让 LLM 进行思考后再回复,并且可以设置思考强度"。

讨论了 3 条路径:

方案 实现 优 劣
A prompt-engineered(system prompt 加 <thinking> 块要求) 0 配置改动;现 model 即可 思考质量受小模型限制;不可控
B OpenAI 标准 reasoning_effort: low/medium/high 字段 标准化 DeepSeek-v4-flash 不识别该字段
C 切换 reasoner 模型(deepseek-r1 / o1 / claude extended thinking) 真思考;可视化推理过程 用户得多配一个 model;UI 复杂度高

结论:选 C。A/B 在当前 provider 下等于无效。

实施分解

后端

  1. 凭据存储:CredentialAccount 加两条

    • ArkReasonerModelId(如 deepseek-r1、doubao-seed-1.6-thinking)
    • 复用现有 ArkApiKey / ArkEndpoint(同一 provider 不同 model)
  2. prefs:Preferences 加字段

    • qa_reasoning_effort: ReasoningEffort 枚举 Off | Low | Medium | High
    • 默认 Off(与现行为一致)
  3. answer_chat_streaming 重载:根据 effort 决定走 chat 还是 reasoner endpoint

    • Off:走 v2.1 现路径(chat 模型 + stream)
    • Low/Medium/High:走 reasoner 模型;强度通过 system prompt hint 调("简短思考即可" / "详细思考" / "深度推理多角度")
    • SSE 解析时同时收 delta.content + delta.reasoning_content,两者通过不同事件 emit:
      • qa:state {kind:"reasoning_delta", chunk}
      • qa:state {kind:"answer_delta", chunk} (已存在)
  4. answer_chat 拼装最终 message 时,reasoning_content 不写入 messages 数组(只显示用,不进上下文)。多轮提问只把最终答案带回上下文。

前端

  1. SelectionAsk.tsx 新增配置块:

    • 「思考强度」下拉:关闭 / 浅 / 中 / 深
    • 「思考模型」输入框(model id;默认 deepseek-r1)
    • i18n:zh-CN / en
  2. QaPanel.tsx 新增「思考过程」可折叠区块:

    • 在 user 气泡下方、最终 assistant 气泡上方
    • 默认折叠,标题 思考中… / 思考过程(X 字),点击展开
    • 流式期间:实时拼接 reasoning_delta,气泡有打字 caret
    • 答案完成:折叠收起;用户随时可点开看推理
  3. types.ts:QaStateKind 加 'reasoning_delta';payload 加 reasoning_chunk?: string

边界与风险

  • Provider 兼容性:火山 Ark 的 deepseek-r1 / doubao-thinking 都返回 reasoning_content;OpenAI o1 通过 thinking blocks(不是 reasoning_content),需要单独 adapter
  • Token 成本:reasoner 模型 token 价格高 5-10x;用户开「深度」就是真烧钱,UI 应该有提示
  • 延迟:reasoner 首 token 可能 > 5s(思考阶段无 content 输出)。要在 UI 上区分「思考中」(reasoning streaming)vs「答题中」(content streaming),避免用户以为卡了

工作量估算

  • 后端 reasoner 通路 + SSE 双流解析:~2h
  • 前端折叠思考区块 + 打字 caret + 状态切换:~1.5h
  • prefs / SelectionAsk 配置 UI + i18n:~0.5h
  • 端到端测试(三档强度 × 单/多轮 × 错误回退):~1h
  • 总计:~5h

实施先决条件

  1. 用户配置好一个 reasoner model(deepseek-r1 / doubao-thinking-pro 等)
  2. 后端凭据 vault 写入对应 model id
  3. v2.1 流式输出已稳定(已完成 ✅)